View | Details | Raw Unified | Return to bug 15838
Collapse All | Expand All

(-)linux-2.6.25.4-unionfs.orig/fs/aufs/aufs.h (+53 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * main header files
21
 *
22
 * $Id: aufs.h,v 1.2 2008/04/21 01:31:49 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_H__
26
#define __AUFS_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/version.h>
31
32
#include "debug.h"
33
34
#include "branch.h"
35
#include "cpup.h"
36
#include "dcsub.h"
37
#include "dentry.h"
38
#include "dir.h"
39
#include "file.h"
40
#include "hinode.h"
41
#include "inode.h"
42
#include "misc.h"
43
#include "module.h"
44
#include "opts.h"
45
#include "super.h"
46
#include "sysaufs.h"
47
#include "vfsub.h"
48
#include "whout.h"
49
#include "wkq.h"
50
//#include "xattr.h"
51
52
#endif /* __KERNEL__ */
53
#endif /* __AUFS_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/branch.c (+916 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * branch management
21
 *
22
 * $Id: branch.c,v 1.5 2008/05/19 01:52:18 sfjro Exp $
23
 */
24
25
#include <linux/iso_fs.h>
26
#include <linux/loop.h>
27
#include <linux/romfs_fs.h>
28
#include <linux/smp_lock.h>
29
#include "aufs.h"
30
31
static void free_branch(struct au_branch *br)
32
{
33
	AuTraceEnter();
34
35
	if (br->br_xino)
36
		fput(br->br_xino);
37
	dput(br->br_wh);
38
	dput(br->br_plink);
39
	if (!au_test_nfs(br->br_mnt->mnt_sb))
40
		mntput(br->br_mnt);
41
	else {
42
		lockdep_off();
43
		mntput(br->br_mnt);
44
		lockdep_on();
45
	}
46
	AuDebugOn(au_br_count(br) || atomic_read(&br->br_wh_running));
47
	//AuDbg("free\n");
48
	kfree(br);
49
}
50
51
/*
52
 * frees all branches
53
 */
54
void au_br_free(struct au_sbinfo *sbinfo)
55
{
56
	aufs_bindex_t bmax;
57
	struct au_branch **br;
58
59
	AuTraceEnter();
60
	bmax = sbinfo->si_bend + 1;
61
	br = sbinfo->si_branch;
62
	while (bmax--)
63
		free_branch(*br++);
64
}
65
66
/*
67
 * find the index of a branch which is specified by @br_id.
68
 */
69
int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
70
{
71
	aufs_bindex_t bindex, bend;
72
73
	AuTraceEnter();
74
75
	bend = au_sbend(sb);
76
	for (bindex = 0; bindex <= bend; bindex++)
77
		if (au_sbr_id(sb, bindex) == br_id)
78
			return bindex;
79
	return -1;
80
}
81
82
/*
83
 * test if the @h_sb is real-readonly.
84
 */
85
int au_test_def_rr(struct super_block *h_sb)
86
{
87
	switch (h_sb->s_magic) {
88
#ifdef CONFIG_AUFS_RR_SQUASHFS
89
	case SQUASHFS_MAGIC_LZMA:
90
	case SQUASHFS_MAGIC:
91
	case SQUASHFS_MAGIC_LZMA_SWAP:
92
	case SQUASHFS_MAGIC_SWAP:
93
		return 1; /* real readonly */
94
#endif
95
96
#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
97
	case ISOFS_SUPER_MAGIC:
98
		return 1;
99
#endif
100
101
#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
102
	case CRAMFS_MAGIC:
103
		return 1;
104
#endif
105
106
#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
107
	case ROMFS_MAGIC:
108
		return 1;
109
#endif
110
111
	default:
112
		return 0;
113
	}
114
}
115
116
/* ---------------------------------------------------------------------- */
117
118
/*
119
 * test if two hidden_dentries have overlapping branches.
120
 */
121
static int do_test_overlap(struct super_block *sb, struct dentry *h_d1,
122
			   struct dentry *h_d2)
123
{
124
	int err;
125
126
	LKTRTrace("%.*s, %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2));
127
128
	err = au_test_subdir(h_d1, h_d2);
129
	AuTraceErr(err);
130
	return err;
131
}
132
133
static int test_overlap_loopback(struct super_block *sb, struct dentry *h_d1,
134
				 struct dentry *h_d2)
135
{
136
#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
137
	struct inode *h_inode;
138
	struct loop_device *l;
139
140
	h_inode = h_d1->d_inode;
141
	if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
142
		return 0;
143
144
	l = h_inode->i_sb->s_bdev->bd_disk->private_data;
145
	h_d1 = l->lo_backing_file->f_dentry;
146
	if (unlikely(h_d1->d_sb == sb))
147
		return 1;
148
	return do_test_overlap(sb, h_d1, h_d2);
149
#else
150
	return 0;
151
#endif
152
}
153
154
static int test_overlap(struct super_block *sb, struct dentry *h_d1,
155
			struct dentry *h_d2)
156
{
157
	LKTRTrace("d1 %.*s, d2 %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2));
158
159
	if (unlikely(h_d1 == h_d2))
160
		return 1;
161
	return do_test_overlap(sb, h_d1, h_d2)
162
		|| do_test_overlap(sb, h_d2, h_d1)
163
		|| test_overlap_loopback(sb, h_d1, h_d2)
164
		|| test_overlap_loopback(sb, h_d2, h_d1);
165
}
166
167
/* ---------------------------------------------------------------------- */
168
169
static int init_br_wh(struct super_block *sb, aufs_bindex_t bindex,
170
		      struct au_branch *br, int new_perm,
171
		      struct dentry *h_root, struct vfsmount *h_mnt)
172
{
173
	int err, old_perm;
174
	struct inode *dir, *h_dir;
175
	const int new = (bindex < 0);
176
177
	LKTRTrace("b%d, new_perm %d\n", bindex, new_perm);
178
179
	dir = sb->s_root->d_inode;
180
	h_dir = h_root->d_inode;
181
	if (new)
182
		mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
183
	else
184
		au_hdir_lock(h_dir, dir, bindex);
185
186
	br_wh_write_lock(br);
187
	old_perm = br->br_perm;
188
	br->br_perm = new_perm;
189
	err = au_wh_init(h_root, br, au_do_nfsmnt(h_mnt), sb);
190
	br->br_perm = old_perm;
191
	br_wh_write_unlock(br);
192
193
	if (new)
194
		mutex_unlock(&h_dir->i_mutex);
195
	else
196
		au_hdir_unlock(h_dir, dir, bindex);
197
198
	AuTraceErr(err);
199
	return err;
200
}
201
202
/* ---------------------------------------------------------------------- */
203
204
/*
205
 * returns a newly allocated branch. @new_nbranch is a number of branches
206
 * after adding a branch.
207
 */
208
static struct au_branch *alloc_addbr(struct super_block *sb, int new_nbranch)
209
{
210
	struct au_branch **branchp, *add_branch;
211
	int sz;
212
	void *p;
213
	struct dentry *root;
214
	struct inode *inode;
215
	struct au_hinode *hinodep;
216
	struct au_hdentry *hdentryp;
217
218
	LKTRTrace("new_nbranch %d\n", new_nbranch);
219
	SiMustWriteLock(sb);
220
	root = sb->s_root;
221
	DiMustWriteLock(root);
222
	inode = root->d_inode;
223
	IiMustWriteLock(inode);
224
225
	add_branch = kmalloc(sizeof(*add_branch), GFP_KERNEL);
226
	//if (LktrCond) {kfree(add_branch); add_branch = NULL;}
227
	if (unlikely(!add_branch))
228
		goto out;
229
230
	sz = sizeof(*branchp) * (new_nbranch - 1);
231
	if (unlikely(!sz))
232
		sz = sizeof(*branchp);
233
	p = au_sbi(sb)->si_branch;
234
	branchp = au_kzrealloc(p, sz, sizeof(*branchp) * new_nbranch,
235
			       GFP_KERNEL);
236
	//if (LktrCond) branchp = NULL;
237
	if (unlikely(!branchp))
238
		goto out_br;
239
	au_sbi(sb)->si_branch = branchp;
240
241
	sz = sizeof(*hdentryp) * (new_nbranch - 1);
242
	if (unlikely(!sz))
243
		sz = sizeof(*hdentryp);
244
	p = au_di(root)->di_hdentry;
245
	hdentryp = au_kzrealloc(p, sz, sizeof(*hdentryp) * new_nbranch,
246
				GFP_KERNEL);
247
	//if (LktrCond) hdentryp = NULL;
248
	if (unlikely(!hdentryp))
249
		goto out_br;
250
	au_di(root)->di_hdentry = hdentryp;
251
252
	sz = sizeof(*hinodep) * (new_nbranch - 1);
253
	if (unlikely(!sz))
254
		sz = sizeof(*hinodep);
255
	p = au_ii(inode)->ii_hinode;
256
	hinodep = au_kzrealloc(p, sz, sizeof(*hinodep) * new_nbranch,
257
			       GFP_KERNEL);
258
	//if (LktrCond) hinodep = NULL; // unavailable test
259
	if (unlikely(!hinodep))
260
		goto out_br;
261
	au_ii(inode)->ii_hinode = hinodep;
262
	return add_branch; /* success */
263
264
 out_br:
265
	kfree(add_branch);
266
 out:
267
	AuTraceErr(-ENOMEM);
268
	return ERR_PTR(-ENOMEM);
269
}
270
271
/*
272
 * test if the branch permission is legal or not.
273
 */
274
static int test_br(struct super_block *sb, struct inode *inode, int brperm,
275
		   char *path)
276
{
277
	int err;
278
279
	err = 0;
280
	if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
281
		AuErr("write permission for readonly fs or inode, %s\n", path);
282
		err = -EINVAL;
283
	}
284
285
	AuTraceErr(err);
286
	return err;
287
}
288
289
/*
290
 * returns:
291
 * 0: success, the caller will add it
292
 * plus: success, it is already unified, the caller should ignore it
293
 * minus: error
294
 */
295
static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
296
{
297
	int err;
298
	struct dentry *root;
299
	struct inode *inode, *h_inode;
300
	aufs_bindex_t bend, bindex;
301
302
	LKTRTrace("%s, remo%d\n", add->path, remount);
303
304
	root = sb->s_root;
305
	bend = au_sbend(sb);
306
	if (unlikely(bend >= 0
307
		     && au_find_dbindex(root, add->nd.path.dentry) >= 0)) {
308
		err = 1;
309
		if (!remount) {
310
			err = -EINVAL;
311
			AuErr("%s duplicated\n", add->path);
312
		}
313
		goto out;
314
	}
315
316
	err = -ENOSPC; //-E2BIG;
317
	//if (LktrCond) bend = AUFS_BRANCH_MAX;
318
	if (unlikely(AUFS_BRANCH_MAX <= add->bindex
319
		     || AUFS_BRANCH_MAX - 1 <= bend)) {
320
		AuErr("number of branches exceeded %s\n", add->path);
321
		goto out;
322
	}
323
324
	err = -EDOM;
325
	if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
326
		AuErr("bad index %d\n", add->bindex);
327
		goto out;
328
	}
329
330
	inode = add->nd.path.dentry->d_inode;
331
	AuDebugOn(!inode || !S_ISDIR(inode->i_mode));
332
	err = -ENOENT;
333
	if (unlikely(!inode->i_nlink)) {
334
		AuErr("no existence %s\n", add->path);
335
		goto out;
336
	}
337
338
	err = -EINVAL;
339
	if (unlikely(inode->i_sb == sb)) {
340
		AuErr("%s must be outside\n", add->path);
341
		goto out;
342
	}
343
344
	if (unlikely(au_test_nested(inode->i_sb))) {
345
		AuErr("nested " AUFS_NAME " %s\n", add->path);
346
		goto out;
347
	}
348
349
	if (unlikely(!strcmp(au_sbtype(inode->i_sb), "unionfs"))) {
350
		AuErr("unsupported filesystem, %s\n", add->path);
351
		goto out;
352
	}
353
354
	if (unlikely(au_test_unsupported_nfs(inode->i_sb))) {
355
		AuErr(AuNoNfsBranchMsg " %s\n", add->path);
356
		goto out;
357
	}
358
359
	err = test_br(sb, add->nd.path.dentry->d_inode, add->perm, add->path);
360
	if (unlikely(err))
361
		goto out;
362
363
	if (bend < 0)
364
		return 0; /* success */
365
366
	h_inode = au_h_dptr(root, 0)->d_inode;
367
	if (unlikely(au_opt_test(au_mntflags(sb), WARN_PERM)
368
		     && ((h_inode->i_mode & S_IALLUGO)
369
			 != (inode->i_mode & S_IALLUGO)
370
			 || h_inode->i_uid != inode->i_uid
371
			 || h_inode->i_gid != inode->i_gid)))
372
		AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
373
		       add->path,
374
		       inode->i_uid, inode->i_gid, (inode->i_mode & S_IALLUGO),
375
		       h_inode->i_uid, h_inode->i_gid,
376
		       (h_inode->i_mode & S_IALLUGO));
377
378
	err = -EINVAL;
379
	for (bindex = 0; bindex <= bend; bindex++)
380
		if (unlikely(test_overlap(sb, add->nd.path.dentry,
381
					  au_h_dptr(root, bindex)))) {
382
			AuErr("%s is overlapped\n", add->path);
383
			goto out;
384
		}
385
	err = 0;
386
387
 out:
388
	AuTraceErr(err);
389
	return err;
390
}
391
392
static int au_br_init(struct au_branch *br, struct super_block *sb,
393
		      struct au_opt_add *add)
394
{
395
	int err;
396
397
	AuTraceEnter();
398
399
	err = 0;
400
	au_rw_init_nolock(&br->br_wh_rwsem);
401
	br->br_plink = NULL;
402
	br->br_wh = NULL;
403
	if (unlikely(au_br_writable(add->perm))) {
404
		err = init_br_wh(sb, /*bindex*/-1, br, add->perm,
405
				 add->nd.path.dentry, add->nd.path.mnt);
406
		if (unlikely(err))
407
			goto out;
408
	}
409
410
	br->br_xino = NULL;
411
	br->br_mnt = mntget(add->nd.path.mnt);
412
	if (au_opt_test(au_mntflags(sb), XINO)) {
413
		err = au_xino_br(sb, br, add->nd.path.dentry->d_inode->i_ino,
414
				 au_sbr(sb, 0)->br_xino, /*do_test*/1);
415
		if (unlikely(err)) {
416
			AuDebugOn(br->br_xino);
417
			goto out;
418
		}
419
	}
420
421
	atomic_set(&br->br_wh_running, 0);
422
	br->br_id = au_new_br_id(sb);
423
	br->br_perm = add->perm;
424
	atomic_set(&br->br_count, 0);
425
	br->br_bytes = 0;
426
	br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
427
	atomic_set(&br->br_xino_running, 0);
428
	sysaufs_br_init(br);
429
	br->br_generation = au_sigen(sb);
430
	//smp_mb(); /* atomic_set */
431
432
 out:
433
	AuTraceErr(err);
434
	return err;
435
}
436
437
int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
438
{
439
	int err, amount;
440
	aufs_bindex_t bend, add_bindex;
441
	struct dentry *root, *dentry;
442
	struct au_iinfo *iinfo;
443
	struct au_sbinfo *sbinfo;
444
	struct au_dinfo *dinfo;
445
	struct inode *root_inode, *inode;
446
	unsigned long long maxb;
447
	struct au_branch **branchp, *add_branch;
448
	struct au_hdentry *hdentryp;
449
	struct au_hinode *hinodep;
450
451
	dentry = add->nd.path.dentry;
452
	LKTRTrace("b%d, %s, 0x%x, %.*s\n",
453
		  add->bindex, add->path, add->perm, AuDLNPair(dentry));
454
	SiMustWriteLock(sb);
455
	root = sb->s_root;
456
	DiMustWriteLock(root);
457
	root_inode = root->d_inode;
458
	IMustLock(root_inode);
459
	IiMustWriteLock(root_inode);
460
461
	err = test_add(sb, add, remount);
462
	if (unlikely(err < 0))
463
		goto out;
464
	if (err)
465
		return 0; /* success */
466
467
	bend = au_sbend(sb);
468
	add_branch = alloc_addbr(sb, bend + 2);
469
	err = PTR_ERR(add_branch);
470
	if (IS_ERR(add_branch))
471
		goto out;
472
	err = au_br_init(add_branch, sb, add);
473
	if (unlikely(err)) {
474
		kfree(add_branch);
475
		goto out;
476
	}
477
478
	add_bindex = add->bindex;
479
	if (remount)
480
		sysaufs_brs_del(sb, add_bindex);
481
482
	sbinfo = au_sbi(sb);
483
	dinfo = au_di(root);
484
	iinfo = au_ii(root_inode);
485
486
	amount = bend + 1 - add_bindex;
487
	branchp = sbinfo->si_branch + add_bindex;
488
	memmove(branchp + 1, branchp, sizeof(*branchp) * amount);
489
	*branchp = add_branch;
490
	hdentryp = dinfo->di_hdentry + add_bindex;
491
	memmove(hdentryp + 1, hdentryp, sizeof(*hdentryp) * amount);
492
	au_h_dentry_init(hdentryp);
493
	hinodep = iinfo->ii_hinode + add_bindex;
494
	memmove(hinodep + 1, hinodep, sizeof(*hinodep) * amount);
495
	hinodep->hi_inode = NULL;
496
	au_hin_init(hinodep, NULL);
497
498
	sbinfo->si_bend++;
499
	dinfo->di_bend++;
500
	iinfo->ii_bend++;
501
	if (unlikely(bend < 0)) {
502
		sbinfo->si_bend = 0;
503
		dinfo->di_bstart = 0;
504
		iinfo->ii_bstart = 0;
505
	}
506
	inode = dentry->d_inode;
507
	au_set_h_dptr(root, add_bindex, dget(dentry));
508
	au_set_h_iptr(root_inode, add_bindex, igrab(inode), 0);
509
	if (remount)
510
		sysaufs_brs_add(sb, add_bindex);
511
512
	if (!add_bindex)
513
		au_cpup_attr_all(root_inode);
514
	else
515
		au_add_nlink(root_inode, inode);
516
	maxb = dentry->d_sb->s_maxbytes;
517
	if (sb->s_maxbytes < maxb)
518
		sb->s_maxbytes = maxb;
519
520
 out:
521
	AuTraceErr(err);
522
	return err;
523
}
524
525
/* ---------------------------------------------------------------------- */
526
527
#define AuVerbose(do_info, fmt, args...) do { \
528
	if (!do_info) \
529
		LKTRTrace(fmt, ##args); \
530
	else \
531
		AuInfo(fmt, ##args); \
532
} while (0)
533
534
/*
535
 * test if the branch is deletable or not.
536
 */
537
static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
538
			    au_gen_t sigen)
539
{
540
	int err, i, j, ndentry, verbose;
541
	struct au_dcsub_pages dpages;
542
	struct au_dpage *dpage;
543
	struct dentry *d;
544
	aufs_bindex_t bstart, bend;
545
	struct inode *inode;
546
547
	LKTRTrace("b%d, gen%d\n", bindex, sigen);
548
	SiMustWriteLock(root->d_sb);
549
550
	err = au_dpages_init(&dpages, GFP_TEMPORARY);
551
	if (unlikely(err))
552
		goto out;
553
	err = au_dcsub_pages(&dpages, root, NULL, NULL);
554
	if (unlikely(err))
555
		goto out_dpages;
556
557
	verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
558
	for (i = 0; !err && i < dpages.ndpage; i++) {
559
		dpage = dpages.dpages + i;
560
		ndentry = dpage->ndentry;
561
		for (j = 0; !err && j < ndentry; j++) {
562
			d = dpage->dentries[j];
563
			AuDebugOn(!atomic_read(&d->d_count));
564
			inode = d->d_inode;
565
			AuDebugOn(!inode);
566
			if (au_digen(d) == sigen
567
			    && au_iigen(inode) == sigen)
568
				di_read_lock_child(d, AuLock_IR);
569
			else {
570
				di_write_lock_child(d);
571
				err = au_reval_dpath(d, sigen);
572
				if (!err)
573
					di_downgrade_lock(d, AuLock_IR);
574
				else {
575
					di_write_unlock(d);
576
					break;
577
				}
578
			}
579
580
			bstart = au_dbstart(d);
581
			bend = au_dbend(d);
582
			if (bstart <= bindex
583
			    && bindex <= bend
584
			    && au_h_dptr(d, bindex)
585
			    && (!S_ISDIR(d->d_inode->i_mode)
586
				|| bstart == bend)) {
587
				err = -EBUSY;
588
				AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
589
			}
590
			di_read_unlock(d, AuLock_IR);
591
		}
592
	}
593
594
 out_dpages:
595
	au_dpages_free(&dpages);
596
 out:
597
	AuTraceErr(err);
598
	return err;
599
}
600
601
static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
602
			   au_gen_t sigen)
603
{
604
	int err, verbose;
605
	struct inode *i;
606
	aufs_bindex_t bstart, bend;
607
608
	LKTRTrace("b%d, gen%d\n", bindex, sigen);
609
	SiMustWriteLock(sb);
610
611
	err = 0;
612
	verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
613
	list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
614
		AuDebugOn(!atomic_read(&i->i_count));
615
		if (!list_empty(&i->i_dentry))
616
			continue;
617
618
		if (au_iigen(i) == sigen)
619
			ii_read_lock_child(i);
620
		else {
621
			ii_write_lock_child(i);
622
			err = au_refresh_hinode_self(i);
623
			if (!err)
624
				ii_downgrade_lock(i);
625
			else {
626
				ii_write_unlock(i);
627
				break;
628
			}
629
		}
630
631
		bstart = au_ibstart(i);
632
		bend = au_ibend(i);
633
		if (bstart <= bindex
634
		    && bindex <= bend
635
		    && au_h_iptr(i, bindex)
636
		    && (!S_ISDIR(i->i_mode) || bstart == bend)) {
637
			err = -EBUSY;
638
			AuVerbose(verbose, "busy i%lu\n", i->i_ino);
639
			//au_debug_on();
640
			//DbgInode(i);
641
			//au_debug_off();
642
			ii_read_unlock(i);
643
			break;
644
		}
645
		ii_read_unlock(i);
646
	}
647
648
	AuTraceErr(err);
649
	return err;
650
}
651
652
static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
653
{
654
	int err;
655
	au_gen_t sigen;
656
657
	LKTRTrace("b%d\n", bindex);
658
	SiMustWriteLock(root->d_sb);
659
	DiMustWriteLock(root);
660
	//todo: dont trust BKL.
661
	AuDebugOn(!kernel_locked());
662
663
	sigen = au_sigen(root->d_sb);
664
	DiMustNoWaiters(root);
665
	IiMustNoWaiters(root->d_inode);
666
	di_write_unlock(root);
667
	err = test_dentry_busy(root, bindex, sigen);
668
	if (!err)
669
		err = test_inode_busy(root->d_sb, bindex, sigen);
670
	di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
671
672
	AuTraceErr(err);
673
	return err;
674
}
675
676
int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
677
{
678
	int err, do_wh, rerr, verbose;
679
	struct dentry *root;
680
	struct inode *inode, *hidden_dir;
681
	aufs_bindex_t bindex, bend, br_id;
682
	struct au_sbinfo *sbinfo;
683
	struct au_dinfo *dinfo;
684
	struct au_iinfo *iinfo;
685
	struct au_branch *br;
686
	unsigned int mnt_flags;
687
688
	//au_debug_on();
689
	LKTRTrace("%s, %.*s\n", del->path, AuDLNPair(del->h_root));
690
	SiMustWriteLock(sb);
691
	root = sb->s_root;
692
	DiMustWriteLock(root);
693
	inode = root->d_inode;
694
	IiMustWriteLock(inode);
695
696
	err = 0;
697
	bindex = au_find_dbindex(root, del->h_root);
698
	if (bindex < 0) {
699
		if (remount)
700
			goto out; /* success */
701
		err = -ENOENT;
702
		AuErr("%s no such branch\n", del->path);
703
		goto out;
704
	}
705
	LKTRTrace("bindex b%d\n", bindex);
706
707
	err = -EBUSY;
708
	mnt_flags = au_mntflags(sb);
709
	verbose = au_opt_test(mnt_flags, VERBOSE);
710
	bend = au_sbend(sb);
711
	if (unlikely(!bend)) {
712
		AuVerbose(verbose, "no more branches left\n");
713
		goto out;
714
	}
715
	br = au_sbr(sb, bindex);
716
	if (unlikely(au_br_count(br))) {
717
		AuVerbose(verbose, "%d file(s) opened\n", au_br_count(br));
718
		goto out;
719
	}
720
721
	do_wh = 0;
722
	hidden_dir = del->h_root->d_inode;
723
	if (br->br_wh || br->br_plink) {
724
		dput(br->br_wh);
725
		dput(br->br_plink);
726
		br->br_plink = NULL;
727
		br->br_wh = NULL;
728
		do_wh = 1;
729
	}
730
731
	err = test_children_busy(root, bindex);
732
	if (unlikely(err)) {
733
		if (unlikely(do_wh))
734
			goto out_wh;
735
		goto out;
736
	}
737
738
	err = 0;
739
	if (remount)
740
		sysaufs_brs_del(sb, bindex);
741
	sbinfo = au_sbi(sb);
742
	dinfo = au_di(root);
743
	iinfo = au_ii(inode);
744
745
	dput(au_h_dptr(root, bindex));
746
	au_hiput(iinfo->ii_hinode + bindex);
747
	br_id = br->br_id;
748
	free_branch(br);
749
750
	//todo: realloc and shrink memory
751
	if (bindex < bend) {
752
		const aufs_bindex_t n = bend - bindex;
753
		struct au_branch **brp;
754
		struct au_hdentry *hdp;
755
		struct au_hinode *hip;
756
757
		brp = sbinfo->si_branch + bindex;
758
		memmove(brp, brp + 1, sizeof(*brp) * n);
759
		hdp = dinfo->di_hdentry + bindex;
760
		memmove(hdp, hdp + 1, sizeof(*hdp) * n);
761
		hip = iinfo->ii_hinode + bindex;
762
		memmove(hip, hip + 1, sizeof(*hip) * n);
763
	}
764
	sbinfo->si_branch[0 + bend] = NULL;
765
	dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
766
	iinfo->ii_hinode[0 + bend].hi_inode = NULL;
767
	au_hin_init(iinfo->ii_hinode + bend, NULL);
768
769
	sbinfo->si_bend--;
770
	dinfo->di_bend--;
771
	iinfo->ii_bend--;
772
	if (remount)
773
		sysaufs_brs_add(sb, bindex);
774
775
	if (!bindex)
776
		au_cpup_attr_all(inode);
777
	else
778
		au_sub_nlink(inode, del->h_root->d_inode);
779
	if (au_opt_test(mnt_flags, PLINK))
780
		au_plink_half_refresh(sb, br_id);
781
782
	if (sb->s_maxbytes == del->h_root->d_sb->s_maxbytes) {
783
		bend--;
784
		sb->s_maxbytes = 0;
785
		for (bindex = 0; bindex <= bend; bindex++) {
786
			unsigned long long maxb;
787
			maxb = au_sbr_sb(sb, bindex)->s_maxbytes;
788
			if (sb->s_maxbytes < maxb)
789
				sb->s_maxbytes = maxb;
790
		}
791
	}
792
	goto out; /* success */
793
794
 out_wh:
795
	/* revert */
796
	rerr = init_br_wh(sb, bindex, br, br->br_perm, del->h_root, br->br_mnt);
797
	if (rerr)
798
		AuWarn("failed re-creating base whiteout, %s. (%d)\n",
799
		       del->path, rerr);
800
 out:
801
	AuTraceErr(err);
802
	//au_debug_off();
803
	return err;
804
}
805
806
static int do_need_sigen_inc(int a, int b)
807
{
808
	return (au_br_whable(a) && !au_br_whable(b));
809
}
810
811
static int need_sigen_inc(int old, int new)
812
{
813
	return (do_need_sigen_inc(old, new)
814
		|| do_need_sigen_inc(new, old));
815
}
816
817
int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
818
	      int *do_update)
819
{
820
	int err;
821
	struct dentry *root;
822
	aufs_bindex_t bindex;
823
	struct au_branch *br;
824
	struct inode *hidden_dir;
825
826
	LKTRTrace("%s, %.*s, 0x%x\n",
827
		  mod->path, AuDLNPair(mod->h_root), mod->perm);
828
	SiMustWriteLock(sb);
829
	root = sb->s_root;
830
	DiMustWriteLock(root);
831
	IiMustWriteLock(root->d_inode);
832
833
	bindex = au_find_dbindex(root, mod->h_root);
834
	if (bindex < 0) {
835
		if (remount)
836
			return 0; /* success */
837
		err = -ENOENT;
838
		AuErr("%s no such branch\n", mod->path);
839
		goto out;
840
	}
841
	LKTRTrace("bindex b%d\n", bindex);
842
843
	hidden_dir = mod->h_root->d_inode;
844
	err = test_br(sb, hidden_dir, mod->perm, mod->path);
845
	if (unlikely(err))
846
		goto out;
847
848
	br = au_sbr(sb, bindex);
849
	if (br->br_perm == mod->perm)
850
		return 0; /* success */
851
852
	if (au_br_writable(br->br_perm)) {
853
		/* remove whiteout base */
854
		//todo: mod->perm?
855
		err = init_br_wh(sb, bindex, br, AuBr_RO, mod->h_root,
856
				 br->br_mnt);
857
		if (unlikely(err))
858
			goto out;
859
860
		if (!au_br_writable(mod->perm)) {
861
			/* rw --> ro, file might be mmapped */
862
			struct file *file, *hf;
863
864
			DiMustNoWaiters(root);
865
			IiMustNoWaiters(root->d_inode);
866
			di_write_unlock(root);
867
868
			/*
869
			 * no need file_list_lock()
870
			 * since BKL (and sbinfo) is locked
871
			 */
872
			AuDebugOn(!kernel_locked());
873
			list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
874
				LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
875
				if (!au_test_aufs_file(file))
876
					continue;
877
878
				fi_read_lock(file);
879
				if (!S_ISREG(file->f_dentry->d_inode->i_mode)
880
				    || !(file->f_mode & FMODE_WRITE)
881
				    || au_fbstart(file) != bindex) {
882
					FiMustNoWaiters(file);
883
					fi_read_unlock(file);
884
					continue;
885
				}
886
887
				if (unlikely(au_test_mmapped(file))) {
888
					err = -EBUSY;
889
					FiMustNoWaiters(file);
890
					fi_read_unlock(file);
891
					break;
892
				}
893
894
				// todo: already flushed?
895
				hf = au_h_fptr(file, au_fbstart(file));
896
				hf->f_flags = au_file_roflags(hf->f_flags);
897
				hf->f_mode &= ~FMODE_WRITE;
898
				put_write_access(hf->f_dentry->d_inode);
899
				FiMustNoWaiters(file);
900
				fi_read_unlock(file);
901
			}
902
903
			/* aufs_write_lock() calls ..._child() */
904
			di_write_lock_child(root);
905
		}
906
	}
907
908
	if (!err) {
909
		*do_update |= need_sigen_inc(br->br_perm, mod->perm);
910
		br->br_perm = mod->perm;
911
	}
912
913
 out:
914
	AuTraceErr(err);
915
	return err;
916
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/branch.h (+324 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * branch filesystems and xino for them
21
 *
22
 * $Id: branch.h,v 1.3 2008/04/28 03:03:32 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_BRANCH_H__
26
#define __AUFS_BRANCH_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/mount.h>
32
#include <linux/sysfs.h>
33
#include <linux/aufs_type.h>
34
#include "misc.h"
35
#include "super.h"
36
37
/* ---------------------------------------------------------------------- */
38
39
/* an entry in a xino file */
40
struct au_xino_entry {
41
	ino_t ino;
42
	//__u32 h_gen;
43
} __packed;
44
45
//#define AuXino_INVALID_HGEN	(-1)
46
47
/* a xino file */
48
struct au_xino_file {
49
	//struct file		**xi_file;
50
	struct file		*xi_file;
51
52
	/* array management */
53
	//unsigned long long	xi_limit;	/* Max xino file size */
54
	//unsigned long long	xi_size; /* s_maxbytes */
55
56
	/* truncation */
57
	blkcnt_t		xi_upper;	/* watermark in blocks */
58
	//u64			xi_upper;	/* watermark in bytes */
59
	//u64			xi_step;	/* to next watermark in bytes */
60
	atomic_t 		xi_running;
61
};
62
63
/* protected by superblock rwsem */
64
struct au_branch {
65
	struct file		*br_xino;
66
	//struct au_xino_file		*br_xino;
67
68
	aufs_bindex_t		br_id;
69
70
	int			br_perm;
71
	struct vfsmount		*br_mnt;
72
	atomic_t		br_count;
73
74
	/* whiteout base */
75
	struct au_rwsem		br_wh_rwsem;
76
	struct dentry		*br_wh;
77
	atomic_t 		br_wh_running;
78
79
	/* pseudo-link dir */
80
	struct dentry		*br_plink;
81
82
	/* xino truncation */
83
	blkcnt_t		br_xino_upper;	/* watermark in blocks */
84
	atomic_t		br_xino_running;
85
86
	/* mfs mode */
87
	u64			br_bytes;
88
89
#ifdef CONFIG_SYSFS
90
	/* an entry under sysfs per mount-point */
91
	char			br_name[8];
92
	struct attribute	br_attr;
93
#endif
94
95
	au_gen_t		br_generation;
96
};
97
98
/* ---------------------------------------------------------------------- */
99
100
/* branch permission and attribute */
101
enum {
102
	AuBr_RW,		/* writable, linkable wh */
103
	AuBr_RO,		/* readonly, no wh */
104
	AuBr_RR,		/* natively readonly, no wh */
105
106
	AuBr_RWNoLinkWH,	/* un-linkable whiteouts */
107
108
	AuBr_ROWH,
109
	AuBr_RRWH,		/* whiteout-able */
110
111
	AuBr_Last
112
};
113
114
static inline int au_br_writable(int brperm)
115
{
116
	return (brperm == AuBr_RW || brperm == AuBr_RWNoLinkWH);
117
}
118
119
static inline int au_br_whable(int brperm)
120
{
121
	return (brperm == AuBr_RW
122
		|| brperm == AuBr_ROWH
123
		|| brperm == AuBr_RRWH);
124
}
125
126
static inline int au_br_hinotifyable(int brperm)
127
{
128
#ifdef CONFIG_AUFS_HINOTIFY
129
	return (brperm != AuBr_RR && brperm != AuBr_RRWH);
130
#else
131
	return 0;
132
#endif
133
}
134
135
/* ---------------------------------------------------------------------- */
136
137
/* branch.c */
138
struct au_sbinfo;
139
void au_br_free(struct au_sbinfo *sinfo);
140
int au_test_def_rr(struct super_block *h_sb);
141
int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
142
struct au_opt_add;
143
int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
144
struct au_opt_del;
145
int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
146
struct au_opt_mod;
147
int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
148
	      int *do_update);
149
150
/* xino.c */
151
int au_xib_trunc(struct super_block *sb);
152
153
struct file *au_xino_create(struct super_block *sb, char *fname, int silent,
154
			    struct dentry *parent);
155
ino_t au_xino_new_ino(struct super_block *sb);
156
int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
157
		   ino_t ino);
158
int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
159
		  struct au_xino_entry *xinoe);
160
int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
161
		 struct au_xino_entry *xinoe);
162
int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
163
	       struct file *base_file, int do_test);
164
int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
165
166
struct au_opt_xino;
167
int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
168
void au_xino_clr(struct super_block *sb);
169
struct file *au_xino_def(struct super_block *sb);
170
171
/* ---------------------------------------------------------------------- */
172
173
//todo: memory barrier?
174
static inline int au_br_count(struct au_branch *br)
175
{
176
	return atomic_read(&br->br_count);
177
}
178
179
static inline int au_br_get(struct au_branch *br)
180
{
181
	return atomic_inc_return(&br->br_count);
182
}
183
184
static inline int au_br_put(struct au_branch *br)
185
{
186
	return atomic_dec_return(&br->br_count);
187
}
188
189
static inline au_gen_t au_br_gen(struct au_branch *br)
190
{
191
	return br->br_generation;
192
}
193
194
/*
195
 * test if the @br is readonly or not.
196
 */
197
static inline int au_br_rdonly(struct au_branch *br)
198
{
199
	return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
200
		|| !au_br_writable(br->br_perm))
201
		? -EROFS : 0;
202
}
203
204
/* ---------------------------------------------------------------------- */
205
206
/* Superblock to branch */
207
static inline
208
aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
209
{
210
	return au_sbr(sb, bindex)->br_id;
211
}
212
213
static inline
214
struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
215
{
216
	return au_sbr(sb, bindex)->br_mnt;
217
}
218
219
static inline
220
struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
221
{
222
	return au_sbr_mnt(sb, bindex)->mnt_sb;
223
}
224
225
static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
226
{
227
	au_br_put(au_sbr(sb, bindex));
228
}
229
230
static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
231
{
232
	return au_sbr(sb, bindex)->br_perm;
233
}
234
235
static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
236
{
237
	return au_br_whable(au_sbr_perm(sb, bindex));
238
}
239
240
static inline int au_test_trunc_xino(struct super_block *sb)
241
{
242
	return au_test_tmpfs(sb);
243
}
244
245
/* temporary support for i#1 in cramfs */
246
static inline int au_test_unique_ino(struct dentry *h_dentry, ino_t h_ino)
247
{
248
#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
249
	if (unlikely(h_dentry->d_sb->s_magic == CRAMFS_MAGIC))
250
		return (h_ino != 1);
251
#endif
252
	return 1;
253
}
254
255
#ifdef CONFIG_AUFS_BR_NFS
256
static inline int au_test_unsupported_nfs(struct super_block *h_sb)
257
{
258
	return 0;
259
}
260
261
static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
262
{
263
	if (!au_test_nfs(h_mnt->mnt_sb))
264
		return NULL;
265
	return h_mnt;
266
}
267
268
/* it doesn't mntget() */
269
static inline
270
struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
271
{
272
	return au_do_nfsmnt(au_sbr_mnt(sb, bindex));
273
}
274
275
#define AuNoNfsBranchMsg "dummy"
276
277
#else
278
static inline int au_test_unsupported_nfs(struct super_block *h_sb)
279
{
280
	return au_test_nfs(h_sb);
281
}
282
283
static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
284
{
285
	return NULL;
286
}
287
288
static inline
289
struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
290
{
291
	return NULL;
292
}
293
294
#define AuNoNfsBranchMsg "NFS branch is not supported" \
295
	", try some configurations and patches included in aufs source CVS."
296
297
#endif /* CONFIG_AUFS_BR_NFS */
298
299
/* ---------------------------------------------------------------------- */
300
301
/*
302
 * br_wh_read_lock, br_wh_write_lock
303
 * br_wh_read_unlock, br_wh_write_unlock, br_wh_downgrade_lock
304
 */
305
AuSimpleRwsemFuncs(br_wh, struct au_branch *br, br->br_wh_rwsem);
306
307
/* to debug easier, do not make them inlined functions */
308
#define BrWhMustReadLock(br) do { \
309
	/* SiMustAnyLock(sb); */ \
310
	AuRwMustReadLock(&(br)->br_wh_rwsem); \
311
} while (0)
312
313
#define BrWhMustWriteLock(br) do { \
314
	/* SiMustAnyLock(sb); */ \
315
	AuRwMustWriteLock(&(br)->br_wh_rwsem); \
316
} while (0)
317
318
#define BrWhMustAnyLock(br) do { \
319
	/* SiMustAnyLock(sb); */ \
320
	AuRwMustAnyLock(&(br)->br_wh_rwsem); \
321
} while (0)
322
323
#endif /* __KERNEL__ */
324
#endif /* __AUFS_BRANCH_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/br_fuse.c (+78 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 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
 * special handling for inode attributes on FUSE branch
21
 *
22
 * $Id: br_fuse.c,v 1.2 2008/04/21 01:32:05 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
/* h_mnt can be NULL, is it safe? */
28
int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry)
29
{
30
	int err;
31
	struct kstat st;
32
33
	LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
34
35
	err = 0;
36
	if (unlikely(h_dentry->d_inode
37
		     //&& atomic_read(&h_dentry->d_inode->i_count)
38
		     && au_test_fuse(h_dentry->d_sb))) {
39
		err = vfsub_getattr(h_mnt, h_dentry, &st, /*dlgt*/0);
40
		if (unlikely(err)) {
41
			AuDbg("err %d\n", err);
42
			au_debug_on();
43
			AuDbgDentry(h_dentry);
44
			au_debug_off();
45
			WARN_ON(err);
46
		}
47
	}
48
	return err;
49
}
50
51
/* currently, for fuse only */
52
int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st)
53
{
54
	int err;
55
	struct inode *inode, *h_inode;
56
	struct dentry *h_dentry;
57
58
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
59
60
	err = 0;
61
	aufs_read_lock(dentry, AuLock_IR);
62
	inode = dentry->d_inode;
63
	h_inode = au_h_iptr(inode, au_ibstart(inode));
64
	if (unlikely(au_test_fuse(h_inode->i_sb))) {
65
		h_dentry = d_find_alias(h_inode);
66
		/* simply gave up updating fuse inode */
67
		if (h_dentry) {
68
			/*ignore*/
69
			if (!au_update_fuse_h_inode(NULL, h_dentry))
70
				au_cpup_attr_all(inode);
71
			dput(h_dentry);
72
		}
73
	}
74
	generic_fillattr(inode, st);
75
76
	aufs_read_unlock(dentry, AuLock_IR);
77
	return err;
78
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/br_nfs.c (+358 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 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
 * lookup functions for NFS branch in linux-2.6.19 and later
21
 *
22
 * $Id: br_nfs.c,v 1.3 2008/05/04 23:51:14 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
static struct file *au_find_h_intent(struct au_hdentry *hd, struct file *file)
28
{
29
	struct file *h_file, *hf;
30
	struct au_hdintent *hdi, *tmp, *do_free;
31
32
	LKTRTrace("%.*s\n", AuDLNPair(hd->hd_dentry));
33
34
	h_file = NULL;
35
	do_free = NULL;
36
	spin_lock(&hd->hd_lock);
37
	list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list, hdi_list) {
38
		hf = hdi->hdi_file[AuIntent_BRANCH];
39
		if (hdi->hdi_file[AuIntent_AUFS] == file
40
		    && hf->f_dentry == hd->hd_dentry) {
41
			h_file = hf;
42
			do_free = hdi;
43
			list_del(&hdi->hdi_list);
44
			break;
45
		}
46
	}
47
	spin_unlock(&hd->hd_lock);
48
	kfree(do_free);
49
50
	return h_file;
51
}
52
53
struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
54
			 struct file *file)
55
{
56
	struct file *h_file;
57
	struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
58
59
	LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
60
	DiMustAnyLock(dentry);
61
	AuDebugOn(bindex < au_di(dentry)->di_bstart
62
		  || bindex > au_di(dentry)->di_bend);
63
64
	h_file = NULL;
65
	if (!hd->hd_intent_list || !file)
66
		return h_file; /* success */
67
68
	//AuDebugOn(au_test_wkq(current));
69
	h_file = au_find_h_intent(hd, file);
70
	//AuDbgFile(h_file);
71
	return h_file;
72
}
73
74
static int au_set_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
75
			   struct file *file, struct file *h_file)
76
{
77
	int err;
78
	struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
79
	struct au_hdintent *hdi;
80
	struct file *hf;
81
82
	LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
83
	/* d_revalidate() holds read_lock */
84
	//DiMustWriteLock(dentry);
85
	AuDebugOn(bindex < au_di(dentry)->di_bstart
86
		  || bindex > au_di(dentry)->di_bend
87
		  || !file
88
		  || !h_file
89
		  /* || au_test_wkq(current) */);
90
91
	err = -ENOMEM;
92
	if (hd->hd_intent_list) {
93
		while (1) {
94
			hf = au_find_h_intent(hd, file);
95
			if (!hf)
96
				break;
97
			fput(hf);
98
			AuWarn("freed hfile %.*s b%d left\n",
99
			       AuDLNPair(dentry), bindex);
100
		}
101
	} else {
102
		spin_lock(&hd->hd_lock);
103
		if (!hd->hd_intent_list) {
104
			hd->hd_intent_list
105
				= kmalloc(sizeof(*hd->hd_intent_list),
106
					  GFP_ATOMIC);
107
			if (unlikely(!hd->hd_intent_list)) {
108
				spin_unlock(&hd->hd_lock);
109
				goto out;
110
			}
111
			INIT_LIST_HEAD(hd->hd_intent_list);
112
		}
113
		spin_unlock(&hd->hd_lock);
114
	}
115
116
	hdi = kmalloc(sizeof(*hdi), GFP_TEMPORARY);
117
	if (unlikely(!hdi))
118
		goto out;
119
120
	err = 0;
121
	//hdi->hdi_pid = current->pid;
122
	hdi->hdi_file[AuIntent_AUFS] = file;
123
	hdi->hdi_file[AuIntent_BRANCH] = h_file;
124
	spin_lock(&hd->hd_lock);
125
	list_add(&hdi->hdi_list, hd->hd_intent_list);
126
	spin_unlock(&hd->hd_lock);
127
	//AuDbgDentry(dentry);
128
	//AuDbgFile(h_file);
129
130
 out:
131
	AuTraceErr(err);
132
	return err;
133
}
134
135
int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
136
		       aufs_bindex_t bindex, struct nameidata *nd)
137
{
138
	int err;
139
140
	AuTraceEnter();
141
142
	err = 0;
143
	if (!nd_file)
144
		goto out;
145
146
	AuDebugOn(!nd);
147
	err = au_set_h_intent(dentry, bindex, nd->intent.open.file, nd_file);
148
	//err = -1;
149
	if (unlikely(err)) {
150
		fput(nd_file);
151
		au_set_h_dptr(dentry, bindex, NULL);
152
		//todo: update bstart and bend?
153
	}
154
155
 out:
156
	AuTraceErr(err);
157
	return err;
158
}
159
160
/* ---------------------------------------------------------------------- */
161
162
void au_hintent_put(struct au_hdentry *hd, int do_free)
163
{
164
	struct au_hdintent *hdi, *tmp;
165
	struct file *hf;
166
167
	if (unlikely(hd->hd_intent_list)) {
168
		// no spin lock
169
		list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list,
170
					 hdi_list) {
171
			LKTRTrace("hdi %p\n", hdi);
172
			hf = hdi->hdi_file[AuIntent_BRANCH];
173
			if (unlikely(hf))
174
				fput(hf);
175
			//list_del(&hdi->hdi_list);
176
			kfree(hdi);
177
		}
178
		if (do_free)
179
			kfree(hd->hd_intent_list);
180
	}
181
}
182
183
/* ---------------------------------------------------------------------- */
184
185
int au_fake_intent(/* struct au_ndsub *save,  */struct nameidata *nd,
186
		   int perm)
187
{
188
	int err;
189
190
	LKTRTrace("perm %d\n", perm);
191
192
	err = 0;
193
194
	nd->intent.open.file = NULL;
195
	if (nd->flags & LOOKUP_OPEN) {
196
		err = -ENFILE;
197
		nd->intent.open.file = get_empty_filp();
198
		if (unlikely(!nd->intent.open.file)) {
199
			//nd->intent.open.file = save->intent.open.file;
200
			goto out;
201
		}
202
203
		err = 0;
204
		if (!au_br_writable(perm)) {
205
			nd->intent.open.flags = FMODE_READ
206
				| au_file_roflags(nd->intent.open.flags);
207
			nd->flags &= ~LOOKUP_CREATE;
208
		}
209
	}
210
211
 out:
212
	AuTraceErr(err);
213
	return err;
214
}
215
216
int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
217
		       aufs_bindex_t bindex, struct file *file)
218
{
219
	int err;
220
221
	LKTRTrace("nd %p, %.*s, b%d, f %d\n",
222
		  nd, AuDLNPair(dentry), bindex, !!file);
223
224
	err = 0;
225
	if ((nd->flags & LOOKUP_OPEN)
226
	    && nd->intent.open.file
227
	    && !IS_ERR(nd->intent.open.file)) {
228
		if (nd->intent.open.file->f_dentry) {
229
			//AuDbgFile(nd->intent.open.file);
230
			err = au_set_h_intent(dentry, bindex, file,
231
					      nd->intent.open.file);
232
			if (!err)
233
				nd->intent.open.file = NULL;
234
		}
235
		if (unlikely(nd->intent.open.file))
236
			put_filp(nd->intent.open.file);
237
	}
238
239
	return err;
240
}
241
242
#ifdef CONFIG_AUFS_DLGT
243
struct au_lookup_hash_args {
244
	struct dentry **errp;
245
	struct qstr *name;
246
	struct dentry *base;
247
	struct nameidata *nd;
248
};
249
250
static void au_call_lookup_hash(void *args)
251
{
252
	struct au_lookup_hash_args *a = args;
253
	*a->errp = vfsub__lookup_hash(a->name, a->base, a->nd);
254
}
255
256
static struct dentry *
257
au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent,
258
		  struct nameidata *nd, unsigned int flags)
259
{
260
	struct dentry *dentry;
261
	int dirperm1;
262
263
	dirperm1 = au_ftest_ndx(flags, DIRPERM1);
264
	if (!dirperm1 && !au_ftest_ndx(flags, DLGT))
265
		dentry = vfsub__lookup_hash(this, parent, nd);
266
	else {
267
		int wkq_err;
268
		struct au_lookup_hash_args args = {
269
			.errp	= &dentry,
270
			.name	= this,
271
			.base	= parent,
272
			.nd	= nd
273
		};
274
		wkq_err = au_wkq_wait(au_call_lookup_hash, &args,
275
				      /*dlgt*/!dirperm1);
276
		if (unlikely(wkq_err))
277
			dentry = ERR_PTR(wkq_err);
278
	}
279
280
	AuTraceErrPtr(dentry);
281
	return dentry;
282
}
283
#else
284
static struct dentry *
285
au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent,
286
		  struct nameidata *nd, unsigned int flags)
287
{
288
	return vfsub__lookup_hash(this, parent, nd);
289
}
290
#endif /* CONFIG_AUFS_DLGT */
291
292
struct dentry *au_lkup_hash(const char *name, struct dentry *parent,
293
			    int len, struct au_ndx *ndx)
294
{
295
	struct dentry *dentry;
296
	char *p;
297
	unsigned long hash;
298
	struct qstr this;
299
	unsigned int c;
300
	struct nameidata tmp_nd, *ndo;
301
	int err;
302
303
	LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
304
305
	//todo: export and call __lookup_one_len() in fs/namei.c
306
	dentry = ERR_PTR(-EACCES);
307
	this.name = name;
308
	this.len = len;
309
	if (unlikely(!len))
310
		goto out;
311
312
	p = (void *)name;
313
	hash = init_name_hash();
314
	while (len--) {
315
		c = *p++;
316
		if (unlikely(c == '/' || c == '\0'))
317
			goto out;
318
		hash = partial_name_hash(c, hash);
319
	}
320
	this.hash = end_name_hash(hash);
321
322
	ndo = ndx->nd;
323
	if (ndo) {
324
		tmp_nd = *ndo;
325
		err = au_fake_intent(&tmp_nd, ndx->br->br_perm);
326
		dentry = ERR_PTR(err);
327
		if (unlikely(err))
328
			goto out_intent;
329
	} else
330
		memset(&tmp_nd, 0, sizeof(tmp_nd));
331
332
	tmp_nd.path.dentry = parent;
333
	tmp_nd.path.mnt = ndx->nfsmnt;
334
	path_get(&tmp_nd.path);
335
	dentry = au_lkup_hash_dlgt(&this, parent, &tmp_nd, ndx->flags);
336
	if (0 && !IS_ERR(dentry))
337
		AuDbgDentry(dentry);
338
	if (!IS_ERR(dentry)) {
339
		/* why negative dentry for a new dir was unhashed? */
340
		if (unlikely(d_unhashed(dentry)))
341
			d_rehash(dentry);
342
		if (tmp_nd.intent.open.file
343
		    && tmp_nd.intent.open.file->f_dentry) {
344
			//AuDbgFile(tmp_nd.intent.open.file);
345
			ndx->nd_file = tmp_nd.intent.open.file;
346
			tmp_nd.intent.open.file = NULL;
347
			//au_br_get(ndx->br);
348
		}
349
	}
350
	path_put(&tmp_nd.path);
351
352
 out_intent:
353
	if (tmp_nd.intent.open.file)
354
		put_filp(tmp_nd.intent.open.file);
355
 out:
356
	AuTraceErrPtr(dentry);
357
	return dentry;
358
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/br_xfs.c (+69 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 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
 * special handling inode attributes on XFS branch in linux-2.6.24 and later
21
 *
22
 * $Id: br_xfs.c,v 1.2 2008/04/21 01:33:00 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
/* h_mnt can be NULL, is it safe? */
28
dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
29
		struct dentry *h_dentry)
30
{
31
	dev_t rdev;
32
	int err;
33
	struct kstat st;
34
35
	LKTRTrace("hi%lu\n", h_inode->i_ino);
36
	if (h_dentry)
37
		LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
38
39
	rdev = h_inode->i_rdev;
40
	if (!rdev || !au_test_xfs(h_inode->i_sb))
41
		goto out;
42
43
	rdev = 0;
44
	if (!h_dentry) {
45
		err = 0;
46
		h_dentry = d_find_alias(h_inode);
47
		if (unlikely(!h_dentry))
48
			goto failure;
49
		err = PTR_ERR(h_dentry);
50
		if (IS_ERR(h_dentry)) {
51
			h_dentry = NULL;
52
			goto failure;
53
		}
54
		LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
55
	} else
56
		dget(h_dentry);
57
58
	err = vfsub_getattr(h_mnt, h_dentry, &st, /*dlgt*/0);
59
	dput(h_dentry);
60
	if (!err) {
61
		rdev = st.rdev;
62
		goto out; /* success */
63
	}
64
65
 failure:
66
	AuIOErr("failed rdev for XFS inode, hi%lu, %d\n", h_inode->i_ino, err);
67
 out:
68
	return rdev;
69
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/cpup.c (+1039 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * copy-up functions, see wbr_policy.c for copy-down
21
 *
22
 * $Id: cpup.c,v 1.5 2008/05/12 00:29:11 sfjro Exp $
23
 */
24
25
#include <linux/fs_stack.h>
26
#include <linux/uaccess.h>
27
#include "aufs.h"
28
29
/* violent cpup_attr_*() functions don't care inode lock */
30
void au_cpup_attr_timesizes(struct inode *inode)
31
{
32
	struct inode *h_inode;
33
34
	LKTRTrace("i%lu\n", inode->i_ino);
35
	//IMustLock(inode);
36
	h_inode = au_h_iptr(inode, au_ibstart(inode));
37
	AuDebugOn(!h_inode);
38
	//IMustLock(!h_inode);
39
40
	fsstack_copy_attr_times(inode, h_inode);
41
	//todo: this spin_lock conflicts the new unionfs patch in -mm tree
42
	spin_lock(&inode->i_lock);
43
	fsstack_copy_inode_size(inode, h_inode);
44
	spin_unlock(&inode->i_lock);
45
}
46
47
void au_cpup_attr_nlink(struct inode *inode)
48
{
49
	struct inode *h_inode;
50
51
	LKTRTrace("i%lu\n", inode->i_ino);
52
	//IMustLock(inode);
53
	AuDebugOn(!inode->i_mode);
54
55
	h_inode = au_h_iptr(inode, au_ibstart(inode));
56
	inode->i_nlink = h_inode->i_nlink;
57
58
	/*
59
	 * fewer nlink makes find(1) noisy, but larger nlink doesn't.
60
	 * it may includes whplink directory.
61
	 */
62
	if (unlikely(S_ISDIR(h_inode->i_mode))) {
63
		aufs_bindex_t bindex, bend;
64
		bend = au_ibend(inode);
65
		for (bindex = au_ibstart(inode) + 1; bindex <= bend; bindex++) {
66
			h_inode = au_h_iptr(inode, bindex);
67
			if (h_inode)
68
				au_add_nlink(inode, h_inode);
69
		}
70
	}
71
}
72
73
void au_cpup_attr_changeable(struct inode *inode)
74
{
75
	struct inode *h_inode;
76
77
	LKTRTrace("i%lu\n", inode->i_ino);
78
	//IMustLock(inode);
79
	h_inode = au_h_iptr(inode, au_ibstart(inode));
80
	AuDebugOn(!h_inode);
81
82
	inode->i_mode = h_inode->i_mode;
83
	inode->i_uid = h_inode->i_uid;
84
	inode->i_gid = h_inode->i_gid;
85
	au_cpup_attr_timesizes(inode);
86
87
	//??
88
	inode->i_flags = h_inode->i_flags;
89
}
90
91
void au_cpup_igen(struct inode *inode, struct inode *h_inode)
92
{
93
	inode->i_generation = h_inode->i_generation;
94
	au_ii(inode)->ii_hsb1 = h_inode->i_sb;
95
}
96
97
void au_cpup_attr_all(struct inode *inode)
98
{
99
	struct inode *h_inode;
100
101
	LKTRTrace("i%lu\n", inode->i_ino);
102
	//IMustLock(inode);
103
	h_inode = au_h_iptr(inode, au_ibstart(inode));
104
	AuDebugOn(!h_inode);
105
106
	au_cpup_attr_changeable(inode);
107
	if (inode->i_nlink > 0)
108
		au_cpup_attr_nlink(inode);
109
110
	switch (inode->i_mode & S_IFMT) {
111
	case S_IFBLK:
112
	case S_IFCHR:
113
		inode->i_rdev = au_h_rdev(h_inode, /*h_mnt*/NULL,
114
					  /*h_dentry*/NULL);
115
	}
116
	inode->i_blkbits = h_inode->i_blkbits;
117
	au_cpup_igen(inode, h_inode);
118
}
119
120
/* ---------------------------------------------------------------------- */
121
122
/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
123
124
/* keep the timestamps of the parent dir when cpup */
125
void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
126
		    struct dentry *h_dentry, struct au_hinode *hdir)
127
{
128
	struct inode *inode;
129
130
	LKTRTrace("%.*s, hdir %d\n", AuDLNPair(dentry), !!hdir);
131
	AuDebugOn(!dentry || !h_dentry || !h_dentry->d_inode);
132
133
	dt->dt_dentry = dentry;
134
	dt->dt_h_dentry = h_dentry;
135
	dt->dt_hdir = hdir;
136
	inode = h_dentry->d_inode;
137
	dt->dt_atime = inode->i_atime;
138
	dt->dt_mtime = inode->i_mtime;
139
	//smp_mb();
140
}
141
142
void au_dtime_revert(struct au_dtime *dt)
143
{
144
	struct iattr attr;
145
	int err;
146
	struct au_hin_ignore ign;
147
	struct vfsub_args vargs;
148
149
	LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry));
150
151
	attr.ia_atime = dt->dt_atime;
152
	attr.ia_mtime = dt->dt_mtime;
153
	attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
154
		| ATTR_ATIME | ATTR_ATIME_SET;
155
156
	vfsub_args_init(&vargs, &ign,
157
			au_opt_test_dlgt(au_mntflags(dt->dt_dentry->d_sb)), 0);
158
	if (unlikely(dt->dt_hdir))
159
		vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hdir);
160
	err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs);
161
	if (unlikely(err))
162
		AuWarn("restoring timestamps failed(%d). ignored\n", err);
163
}
164
165
/* ---------------------------------------------------------------------- */
166
167
static noinline_for_stack int
168
cpup_iattr(struct dentry *h_dst, struct dentry *h_src, int dlgt)
169
{
170
	int err, sbits;
171
	struct iattr ia;
172
	struct inode *h_isrc, *h_idst;
173
	struct vfsub_args vargs;
174
175
	LKTRTrace("%.*s\n", AuDLNPair(h_dst));
176
	h_idst = h_dst->d_inode;
177
	//IMustLock(h_idst);
178
	h_isrc = h_src->d_inode;
179
	//IMustLock(h_isrc);
180
181
	ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
182
		| ATTR_ATIME | ATTR_MTIME
183
		| ATTR_ATIME_SET | ATTR_MTIME_SET;
184
	ia.ia_mode = h_isrc->i_mode;
185
	ia.ia_uid = h_isrc->i_uid;
186
	ia.ia_gid = h_isrc->i_gid;
187
	ia.ia_atime = h_isrc->i_atime;
188
	ia.ia_mtime = h_isrc->i_mtime;
189
	sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
190
191
	vfsub_args_init(&vargs, NULL, dlgt, /*force_unlink*/0);
192
	err = vfsub_notify_change(h_dst, &ia, &vargs);
193
	//if (LktrCond) err = -1;
194
195
	/* is this nfs only? */
196
	if (!err && sbits && au_test_nfs(h_dst->d_sb)) {
197
		ia.ia_valid = ATTR_FORCE | ATTR_MODE;
198
		ia.ia_mode = h_isrc->i_mode;
199
		err = vfsub_notify_change(h_dst, &ia, &vargs);
200
	}
201
202
	if (!err)
203
		h_idst->i_flags = h_isrc->i_flags; //??
204
205
	AuTraceErr(err);
206
	return err;
207
}
208
209
/*
210
 * to support a sparse file which is opened with O_APPEND,
211
 * we need to close the file.
212
 */
213
static noinline_for_stack int
214
cpup_regular(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
215
	     loff_t len)
216
{
217
	int err, i;
218
	struct super_block *sb;
219
	struct inode *h_inode;
220
	enum { SRC, DST };
221
	struct {
222
		aufs_bindex_t bindex;
223
		unsigned int flags;
224
		struct dentry *dentry;
225
		struct file *file;
226
		void *label, *label_file;
227
	} *h, hidden[] = {
228
		{
229
			.bindex = bsrc,
230
			.flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
231
			.file = NULL,
232
			.label = &&out,
233
			.label_file = &&out_src_file
234
		},
235
		{
236
			.bindex = bdst,
237
			.flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
238
			.file = NULL,
239
			.label = &&out_src_file,
240
			.label_file = &&out_dst_file
241
		}
242
	};
243
244
	LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
245
		  AuDLNPair(dentry), bdst, bsrc, len);
246
	AuDebugOn(bsrc <= bdst);
247
	AuDebugOn(!len);
248
	sb = dentry->d_sb;
249
	AuDebugOn(au_test_ro(sb, bdst, dentry->d_inode));
250
	/* bsrc branch can be ro/rw. */
251
252
	h = hidden;
253
	for (i = 0; i < 2; i++, h++) {
254
		h->dentry = au_h_dptr(dentry, h->bindex);
255
		AuDebugOn(!h->dentry);
256
		h_inode = h->dentry->d_inode;
257
		AuDebugOn(!h_inode || !S_ISREG(h_inode->i_mode));
258
		h->file = au_h_open(dentry, h->bindex, h->flags, /*file*/NULL);
259
		//if (LktrCond)
260
		//{fput(h->file);au_sbr_put(sb, h->bindex);h->file=ERR_PTR(-1);}
261
		err = PTR_ERR(h->file);
262
		if (IS_ERR(h->file))
263
			goto *h->label;
264
		err = -EINVAL;
265
		if (unlikely(!h->file->f_op))
266
			goto *h->label_file;
267
	}
268
269
	/* stop updating while we copyup */
270
	IMustLock(hidden[SRC].dentry->d_inode);
271
	err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb);
272
273
 out_dst_file:
274
	fput(hidden[DST].file);
275
	au_sbr_put(sb, hidden[DST].bindex);
276
 out_src_file:
277
	fput(hidden[SRC].file);
278
	au_sbr_put(sb, hidden[SRC].bindex);
279
 out:
280
	AuTraceErr(err);
281
	return err;
282
}
283
284
static noinline_for_stack int
285
au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
286
		   aufs_bindex_t bsrc, loff_t len, struct inode *h_inode,
287
		   struct inode *h_dir, struct dentry *h_dst, int dlgt)
288
{
289
	int err, rerr;
290
	loff_t l;
291
	struct vfsub_args vargs;
292
293
	AuTraceEnter();
294
295
	err = 0;
296
	l = i_size_read(h_inode);
297
	if (len == -1 || l < len)
298
		len = l;
299
	if (len)
300
		err = cpup_regular(dentry, bdst, bsrc, len);
301
		//if (LktrCond) err = -1;
302
	if (!err)
303
		goto out; /* success */
304
305
	vfsub_args_init(&vargs, NULL, dlgt, 0);
306
	rerr = vfsub_unlink(h_dir, h_dst, &vargs);
307
	if (rerr) {
308
		AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
309
			AuDLNPair(h_dst), err, rerr);
310
		err = -EIO;
311
	}
312
313
 out:
314
	AuTraceErr(err);
315
	return err;
316
}
317
318
static noinline_for_stack int
319
au_do_cpup_symlink(struct dentry *h_dst, struct dentry *h_src,
320
		   struct inode *h_dir, umode_t mode, int dlgt)
321
{
322
	int err, symlen;
323
	char *sym;
324
	mm_segment_t old_fs;
325
326
	AuTraceEnter();
327
328
	err = -ENOMEM;
329
	sym = __getname();
330
	//if (LktrCond) {__putname(sym); sym = NULL;}
331
	if (unlikely(!sym))
332
		goto out;
333
334
	old_fs = get_fs();
335
	set_fs(KERNEL_DS);
336
	symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
337
						PATH_MAX);
338
	err = symlen;
339
	//if (LktrCond) err = symlen = -1;
340
	set_fs(old_fs);
341
342
	if (symlen > 0) {
343
		sym[symlen] = 0;
344
		err = vfsub_symlink(h_dir, h_dst, sym, mode, dlgt);
345
		//if (LktrCond)
346
		//{vfs_unlink(h_dir, h_dst); err = -1;}
347
	}
348
	__putname(sym);
349
350
 out:
351
	AuTraceErr(err);
352
	return err;
353
}
354
355
/* return with hidden dst inode is locked */
356
static noinline_for_stack int
357
cpup_entry(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
358
	   loff_t len, unsigned int flags, int dlgt)
359
{
360
	int err, isdir, hinotify;
361
	struct dentry *h_src, *h_dst, *h_parent, *parent;
362
	struct inode *h_inode, *h_dir;
363
	struct au_dtime dt;
364
	umode_t mode;
365
	struct super_block *sb;
366
	struct au_hinode *hgdir;
367
	const int do_dt = au_ftest_cpup(flags, DTIME);
368
	unsigned int mnt_flags;
369
370
	LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, dtime %u\n",
371
		  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
372
		  do_dt);
373
	sb = dentry->d_sb;
374
	AuDebugOn(bdst >= bsrc || au_test_ro(sb, bdst, NULL));
375
	/* bsrc branch can be ro/rw. */
376
377
	h_src = au_h_dptr(dentry, bsrc);
378
	AuDebugOn(!h_src);
379
	h_inode = h_src->d_inode;
380
	AuDebugOn(!h_inode);
381
382
	/* stop referencing while we are creating */
383
	parent = dget_parent(dentry);
384
	h_dst = au_h_dptr(dentry, bdst);
385
	AuDebugOn(h_dst && h_dst->d_inode);
386
	h_parent = h_dst->d_parent; /* dir inode is locked */
387
	h_dir = h_parent->d_inode;
388
	IMustLock(h_dir);
389
390
	mnt_flags = au_mntflags(sb);
391
	hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY);
392
	if (do_dt) {
393
		hgdir = NULL;
394
		if (unlikely(hinotify && !IS_ROOT(parent))) {
395
			struct dentry *gparent;
396
			gparent = dget_parent(parent);
397
			hgdir = au_hi(gparent->d_inode, bdst);
398
			dput(gparent);
399
		}
400
		au_dtime_store(&dt, parent, h_parent, hgdir);
401
	}
402
403
	isdir = 0;
404
	mode = h_inode->i_mode;
405
	switch (mode & S_IFMT) {
406
	case S_IFREG:
407
		/* stop updating while we are referencing */
408
		IMustLock(h_inode);
409
		err = au_h_create(h_dir, h_dst, mode | S_IWUSR, dlgt, NULL,
410
				  au_nfsmnt(sb, bdst));
411
		//if (LktrCond) {vfs_unlink(h_dir, h_dst); err = -1;}
412
		if (!err)
413
			err = au_do_cpup_regular(dentry, bdst, bsrc, len,
414
						 h_inode, h_dir, h_dst, dlgt);
415
		break;
416
	case S_IFDIR:
417
		isdir = 1;
418
		err = vfsub_mkdir(h_dir, h_dst, mode, dlgt);
419
		//if (LktrCond) {vfs_rmdir(h_dir, h_dst); err = -1;}
420
		if (!err) {
421
			/* setattr case: dir is not locked */
422
			if (0 && au_ibstart(parent->d_inode) == bdst)
423
				au_cpup_attr_nlink(parent->d_inode);
424
			au_cpup_attr_nlink(dentry->d_inode);
425
		}
426
		break;
427
	case S_IFLNK:
428
		err = au_do_cpup_symlink(h_dst, h_src, h_dir, mode, dlgt);
429
		break;
430
	case S_IFCHR:
431
	case S_IFBLK:
432
		AuDebugOn(!capable(CAP_MKNOD));
433
		/*FALLTHROUGH*/
434
	case S_IFIFO:
435
	case S_IFSOCK:
436
		err = vfsub_mknod(h_dir, h_dst, mode,
437
				  au_h_rdev(h_inode, /*h_mnt*/NULL, h_src),
438
				  dlgt);
439
		//if (LktrCond) {vfs_unlink(h_dir, h_dst); err = -1;}
440
		break;
441
	default:
442
		AuIOErr("Unknown inode type 0%o\n", mode);
443
		err = -EIO;
444
	}
445
446
	//todo: should it be always?
447
	if (unlikely(hinotify
448
		     && !isdir
449
		     && au_opt_test(mnt_flags, XINO)
450
		     && h_inode->i_nlink == 1
451
		     && bdst < bsrc))
452
		au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0);
453
		/* ignore this error */
454
455
	if (do_dt)
456
		au_dtime_revert(&dt);
457
	dput(parent);
458
	AuTraceErr(err);
459
	return err;
460
}
461
462
/*
463
 * copyup the @dentry from @bsrc to @bdst.
464
 * the caller must set the both of hidden dentries.
465
 * @len is for truncating when it is -1 copyup the entire file.
466
 */
467
int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
468
		   aufs_bindex_t bsrc, loff_t len, unsigned int flags)
469
{
470
	int err, rerr, isdir, dlgt, plink;
471
	struct dentry *h_src, *h_dst, *parent, *h_parent;
472
	struct inode *dst_inode, *h_dir, *inode;
473
	struct super_block *sb;
474
	aufs_bindex_t old_ibstart;
475
	struct au_dtime dt;
476
	struct vfsub_args vargs;
477
	struct au_hinode *hgdir;
478
	unsigned int mnt_flags;
479
480
	LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
481
		  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
482
		  flags);
483
	sb = dentry->d_sb;
484
	AuDebugOn(bsrc <= bdst);
485
	h_dst = au_h_dptr(dentry, bdst);
486
	AuDebugOn(!h_dst || h_dst->d_inode);
487
	h_parent = h_dst->d_parent; /* dir inode is locked */
488
	h_dir = h_parent->d_inode;
489
	IMustLock(h_dir);
490
	h_src = au_h_dptr(dentry, bsrc);
491
	AuDebugOn(!h_src || !h_src->d_inode);
492
	inode = dentry->d_inode;
493
	IiMustWriteLock(inode);
494
	parent = dget_parent(dentry);
495
496
	mnt_flags = au_mntflags(sb);
497
	dlgt = !!au_opt_test_dlgt(mnt_flags);
498
	plink = !!au_opt_test(mnt_flags, PLINK);
499
	dst_inode = au_h_iptr(inode, bdst);
500
	if (unlikely(dst_inode)) {
501
		if (unlikely(!plink)) {
502
			err = -EIO;
503
			AuIOErr("i%lu exists on a upper branch "
504
				"but plink is disabled\n", inode->i_ino);
505
			goto out;
506
		}
507
508
		if (dst_inode->i_nlink) {
509
			h_src = au_plink_lkup(sb, bdst, inode);
510
			err = PTR_ERR(h_src);
511
			if (IS_ERR(h_src))
512
				goto out;
513
			AuDebugOn(!h_src->d_inode);
514
			err = vfsub_link(h_src, h_dir, h_dst, dlgt);
515
			dput(h_src);
516
			goto out;
517
		} else
518
			//todo: cpup_wh_file
519
			/* udba work */
520
			au_update_brange(inode, 1);
521
	}
522
523
	old_ibstart = au_ibstart(inode);
524
	err = cpup_entry(dentry, bdst, bsrc, len, flags, dlgt);
525
	if (unlikely(err))
526
		goto out;
527
	dst_inode = h_dst->d_inode;
528
	mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
529
530
	//todo: test dlgt
531
	err = cpup_iattr(h_dst, h_src, dlgt);
532
	//if (LktrCond) err = -1;
533
	isdir = S_ISDIR(dst_inode->i_mode);
534
	if (!err) {
535
		if (bdst < old_ibstart)
536
			au_set_ibstart(inode, bdst);
537
		au_set_h_iptr(inode, bdst, igrab(dst_inode),
538
			      au_hi_flags(inode, isdir));
539
		mutex_unlock(&dst_inode->i_mutex);
540
		if (!isdir
541
		    && h_src->d_inode->i_nlink > 1
542
		    && plink)
543
			au_plink_append(sb, inode, h_dst, bdst);
544
		goto out; /* success */
545
	}
546
547
	/* revert */
548
	mutex_unlock(&dst_inode->i_mutex);
549
	hgdir = NULL;
550
	if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
551
		     && !IS_ROOT(parent))) {
552
		struct dentry *gparent;
553
		gparent = dget_parent(parent);
554
		hgdir = au_hi(gparent->d_inode, bdst);
555
		dput(gparent);
556
	}
557
	au_dtime_store(&dt, parent, h_parent, hgdir);
558
	vfsub_args_init(&vargs, NULL, dlgt, 0);
559
	if (!isdir)
560
		rerr = vfsub_unlink(h_dir, h_dst, &vargs);
561
	else
562
		rerr = vfsub_rmdir(h_dir, h_dst, &vargs);
563
	//rerr = -1;
564
	au_dtime_revert(&dt);
565
	if (rerr) {
566
		AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
567
		err = -EIO;
568
	}
569
570
 out:
571
	dput(parent);
572
	AuTraceErr(err);
573
	return err;
574
}
575
576
struct au_cpup_single_args {
577
	int *errp;
578
	struct dentry *dentry;
579
	aufs_bindex_t bdst, bsrc;
580
	loff_t len;
581
	unsigned int flags;
582
};
583
584
static void au_call_cpup_single(void *args)
585
{
586
	struct au_cpup_single_args *a = args;
587
	*a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
588
				  a->flags);
589
}
590
591
int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
592
		       aufs_bindex_t bsrc, loff_t len, unsigned int flags)
593
{
594
	int err, wkq_err;
595
	struct dentry *h_dentry;
596
	umode_t mode;
597
598
	LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
599
		  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
600
		  flags);
601
602
	h_dentry = au_h_dptr(dentry, bsrc);
603
	mode = h_dentry->d_inode->i_mode & S_IFMT;
604
	if ((mode != S_IFCHR && mode != S_IFBLK)
605
	    || capable(CAP_MKNOD))
606
		err = au_cpup_single(dentry, bdst, bsrc, len, flags);
607
	else {
608
		struct au_cpup_single_args args = {
609
			.errp		= &err,
610
			.dentry		= dentry,
611
			.bdst		= bdst,
612
			.bsrc		= bsrc,
613
			.len		= len,
614
			.flags		= flags
615
		};
616
		wkq_err = au_wkq_wait(au_call_cpup_single, &args, /*dlgt*/0);
617
		if (unlikely(wkq_err))
618
			err = wkq_err;
619
	}
620
621
	AuTraceErr(err);
622
	return err;
623
}
624
625
/*
626
 * copyup the @dentry from the first active hidden branch to @bdst,
627
 * using au_cpup_single().
628
 */
629
int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
630
		   unsigned int flags)
631
{
632
	int err;
633
	struct inode *inode;
634
	aufs_bindex_t bsrc, bend;
635
636
	LKTRTrace("%.*s, bdst %d, len %Ld, flags 0x%x\n",
637
		  AuDLNPair(dentry), bdst, len, flags);
638
	inode = dentry->d_inode;
639
	AuDebugOn(!S_ISDIR(inode->i_mode) && au_dbstart(dentry) < bdst);
640
641
	bend = au_dbend(dentry);
642
	for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
643
		if (au_h_dptr(dentry, bsrc))
644
			break;
645
	AuDebugOn(!au_h_dptr(dentry, bsrc));
646
647
	err = au_lkup_neg(dentry, bdst);
648
	//err = -1;
649
	if (!err) {
650
		err = au_cpup_single(dentry, bdst, bsrc, len, flags);
651
		if (!err)
652
			return 0; /* success */
653
654
		/* revert */
655
		au_set_h_dptr(dentry, bdst, NULL);
656
		au_set_dbstart(dentry, bsrc);
657
	}
658
659
	AuTraceErr(err);
660
	return err;
661
}
662
663
struct au_cpup_simple_args {
664
	int *errp;
665
	struct dentry *dentry;
666
	aufs_bindex_t bdst;
667
	loff_t len;
668
	unsigned int flags;
669
};
670
671
static void au_call_cpup_simple(void *args)
672
{
673
	struct au_cpup_simple_args *a = args;
674
	*a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
675
}
676
677
int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
678
		       unsigned int flags)
679
{
680
	int err, do_sio, dlgt, wkq_err;
681
	struct dentry *parent;
682
	struct inode *h_dir, *dir;
683
684
	LKTRTrace("%.*s, b%d, len %Ld, flags 0x%x\n",
685
		  AuDLNPair(dentry), bdst, len, flags);
686
687
	parent = dget_parent(dentry);
688
	dir = parent->d_inode;
689
	h_dir = au_h_iptr(dir, bdst);
690
	dlgt = !!au_opt_test_dlgt(au_mntflags(dir->i_sb));
691
	do_sio = au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE, dlgt);
692
	if (!do_sio) {
693
		/*
694
		 * testing CAP_MKNOD is for generic fs,
695
		 * but CAP_FSETID is for xfs only, currently.
696
		 */
697
		umode_t mode = dentry->d_inode->i_mode;
698
		do_sio = (((mode & (S_IFCHR | S_IFBLK))
699
			   && !capable(CAP_MKNOD))
700
			  || ((mode & (S_ISUID | S_ISGID))
701
			      && !capable(CAP_FSETID)));
702
	}
703
	if (!do_sio)
704
		err = au_cpup_simple(dentry, bdst, len, flags);
705
	else {
706
		struct au_cpup_simple_args args = {
707
			.errp		= &err,
708
			.dentry		= dentry,
709
			.bdst		= bdst,
710
			.len		= len,
711
			.flags		= flags
712
		};
713
		wkq_err = au_wkq_wait(au_call_cpup_simple, &args, /*dlgt*/0);
714
		if (unlikely(wkq_err))
715
			err = wkq_err;
716
	}
717
718
	dput(parent);
719
	AuTraceErr(err);
720
	return err;
721
}
722
723
/* ---------------------------------------------------------------------- */
724
725
static noinline_for_stack int
726
au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
727
	      struct dentry *wh_dentry, struct file *file, loff_t len)
728
{
729
	int err;
730
	struct au_dinfo *dinfo;
731
	aufs_bindex_t bstart;
732
	struct dentry *h_d_bdst, *h_d_bstart;
733
734
	AuTraceEnter();
735
736
	dinfo = au_di(dentry);
737
	bstart = dinfo->di_bstart;
738
	h_d_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
739
	dinfo->di_bstart = bdst;
740
	dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
741
	h_d_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
742
	if (file)
743
		dinfo->di_hdentry[0 + bstart].hd_dentry
744
			= au_h_fptr(file, au_fbstart(file))->f_dentry;
745
	err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME);
746
	//if (LktrCond) err = -1;
747
	if (!err && file) {
748
		err = au_reopen_nondir(file);
749
		//err = -1;
750
		dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_bstart;
751
	}
752
	dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_bdst;
753
	dinfo->di_bstart = bstart;
754
755
	AuTraceErr(err);
756
	return err;
757
}
758
759
/*
760
 * copyup the deleted file for writing.
761
 */
762
int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
763
	       struct file *file)
764
{
765
	int err, dlgt;
766
	struct dentry *parent, *h_parent, *wh_dentry;
767
	struct super_block *sb;
768
	unsigned int mnt_flags;
769
	struct au_dtime dt;
770
	struct vfsub_args vargs;
771
	struct au_hinode *hgdir;
772
	struct au_ndx ndx = {
773
		.nd	= NULL,
774
		.flags	= 0,
775
		//.br	= NULL
776
	};
777
778
	LKTRTrace("%.*s, bdst %d, len %Lu\n", AuDLNPair(dentry), bdst, len);
779
	AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
780
		  || (file && !(file->f_mode & FMODE_WRITE)));
781
	DiMustWriteLock(dentry);
782
783
	parent = dget_parent(dentry);
784
	IiMustAnyLock(parent->d_inode);
785
	h_parent = au_h_dptr(parent, bdst);
786
	AuDebugOn(!h_parent);
787
788
	sb = parent->d_sb;
789
	mnt_flags = au_mntflags(sb);
790
	dlgt = 0;
791
	ndx.nfsmnt = au_nfsmnt(sb, bdst);
792
	if (unlikely(au_opt_test_dlgt(mnt_flags))) {
793
		dlgt = 1;
794
		au_fset_ndx(ndx.flags, DLGT);
795
	}
796
	wh_dentry = au_whtmp_lkup(h_parent, &dentry->d_name, &ndx);
797
	//if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
798
	err = PTR_ERR(wh_dentry);
799
	if (IS_ERR(wh_dentry))
800
		goto out;
801
802
	hgdir = NULL;
803
	if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
804
		     && !IS_ROOT(parent))) {
805
		struct dentry *gparent;
806
		gparent = dget_parent(parent);
807
		hgdir = au_hi(gparent->d_inode, bdst);
808
		dput(gparent);
809
	}
810
	au_dtime_store(&dt, parent, h_parent, hgdir);
811
	err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
812
	if (unlikely(err))
813
		goto out_wh;
814
815
	AuDebugOn(!d_unhashed(dentry));
816
	/* dget first to force sillyrename on nfs */
817
	dget(wh_dentry);
818
	vfsub_args_init(&vargs, NULL, dlgt, 0);
819
	err = vfsub_unlink(h_parent->d_inode, wh_dentry, &vargs);
820
	//if (LktrCond) err = -1;
821
	if (unlikely(err)) {
822
		AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
823
			AuDLNPair(wh_dentry), err);
824
		err = -EIO;
825
	}
826
	au_dtime_revert(&dt);
827
	au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
828
829
 out_wh:
830
	dput(wh_dentry);
831
 out:
832
	dput(parent);
833
	AuTraceErr(err);
834
	//au_debug_off();
835
	return err;
836
}
837
838
struct au_cpup_wh_args {
839
	int *errp;
840
	struct dentry *dentry;
841
	aufs_bindex_t bdst;
842
	loff_t len;
843
	struct file *file;
844
};
845
846
static void au_call_cpup_wh(void *args)
847
{
848
	struct au_cpup_wh_args *a = args;
849
	*a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
850
}
851
852
int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
853
		   struct file *file)
854
{
855
	int err, wkq_err;
856
	struct dentry *parent;
857
	struct inode *dir, *h_dir;
858
859
	AuTraceEnter();
860
	parent = dget_parent(dentry);
861
	dir = parent->d_inode;
862
	IiMustAnyLock(dir);
863
	h_dir = au_h_iptr(dir, bdst);
864
865
	if (!au_test_h_perm_sio
866
	    (h_dir, MAY_EXEC | MAY_WRITE,
867
	     au_opt_test_dlgt(au_mntflags(dentry->d_sb))))
868
		err = au_cpup_wh(dentry, bdst, len, file);
869
	else {
870
		struct au_cpup_wh_args args = {
871
			.errp	= &err,
872
			.dentry	= dentry,
873
			.bdst	= bdst,
874
			.len	= len,
875
			.file	= file
876
		};
877
		wkq_err = au_wkq_wait(au_call_cpup_wh, &args, /*dlgt*/0);
878
		if (unlikely(wkq_err))
879
			err = wkq_err;
880
	}
881
	dput(parent);
882
883
	AuTraceErr(err);
884
	return err;
885
}
886
887
/* ---------------------------------------------------------------------- */
888
889
/*
890
 * generic routine for both of copy-up and copy-down.
891
 * Although I've tried building a path by dcsub, I gave up this approach.
892
 * Since the ancestor directory may be moved/renamed during copy.
893
 */
894
/* cf. revalidate function in file.c */
895
int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked,
896
	       int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
897
			 struct dentry *h_parent, void *arg),
898
	       void *arg)
899
{
900
	int err, hinotify;
901
	struct super_block *sb;
902
	struct dentry *d, *parent, *h_parent, *gparent, *real_parent;
903
904
	LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
905
		  AuDLNPair(dentry), bdst, parent_ino(dentry), locked);
906
	sb = dentry->d_sb;
907
	AuDebugOn(au_test_ro(sb, bdst, NULL));
908
	err = 0;
909
	parent = dget_parent(dentry);
910
	IiMustWriteLock(parent->d_inode);
911
	if (unlikely(IS_ROOT(parent)))
912
		goto out;
913
	if (locked) {
914
		DiMustAnyLock(locked);
915
		IiMustAnyLock(locked->d_inode);
916
	}
917
918
	/* slow loop, keep it simple and stupid */
919
	real_parent = parent;
920
	hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY);
921
	while (1) {
922
		dput(parent);
923
		parent = dget_parent(dentry);
924
		h_parent = au_h_dptr(parent, bdst);
925
		if (h_parent)
926
			goto out; /* success */
927
928
		/* find top dir which is needed to cpup */
929
		do {
930
			d = parent;
931
			dput(parent);
932
			parent = dget_parent(d);
933
			if (parent != locked) {
934
				di_read_lock_parent3(parent, !AuLock_IR);
935
				h_parent = au_h_dptr(parent, bdst);
936
				di_read_unlock(parent, !AuLock_IR);
937
			} else
938
				h_parent = au_h_dptr(parent, bdst);
939
		} while (!h_parent);
940
941
		if (d != real_parent)
942
			di_write_lock_child3(d);
943
944
		/* somebody else might create while we were sleeping */
945
		if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
946
			struct inode *h_dir = h_parent->d_inode,
947
				*dir = parent->d_inode;
948
949
			if (au_h_dptr(d, bdst))
950
				au_update_dbstart(d);
951
			//AuDebugOn(au_dbstart(d) <= bdst);
952
			if (parent != locked)
953
				di_read_lock_parent3(parent, AuLock_IR);
954
			gparent = NULL;
955
			if (unlikely(hinotify && !IS_ROOT(parent))) {
956
				gparent = dget_parent(parent);
957
				if (gparent != locked)
958
					ii_read_lock_parent4(gparent->d_inode);
959
				else {
960
					dput(gparent);
961
					gparent = NULL;
962
				}
963
			}
964
			au_hdir_lock(h_dir, dir, bdst);
965
			err = cp(d, bdst, h_parent, arg);
966
			//if (LktrCond) err = -1;
967
			au_hdir_unlock(h_dir, dir, bdst);
968
			if (unlikely(gparent)) {
969
				ii_read_unlock(gparent->d_inode);
970
				dput(gparent);
971
			}
972
			if (parent != locked)
973
				di_read_unlock(parent, AuLock_IR);
974
		}
975
976
		if (d != real_parent)
977
			di_write_unlock(d);
978
		if (unlikely(err))
979
			break;
980
	}
981
982
 out:
983
	dput(parent);
984
	AuTraceErr(err);
985
	return err;
986
}
987
988
static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
989
		       struct dentry *h_parent, void *arg)
990
{
991
	int err;
992
993
	err = au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
994
995
	AuTraceErr(err);
996
	return err;
997
}
998
999
int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
1000
		 struct dentry *locked)
1001
{
1002
	int err;
1003
1004
	err = au_cp_dirs(dentry, bdst, locked, au_cpup_dir, NULL);
1005
1006
	AuTraceErr(err);
1007
	return err;
1008
}
1009
1010
int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
1011
			  struct dentry *locked)
1012
{
1013
	int err;
1014
	struct dentry *parent;
1015
	struct inode *dir;
1016
1017
	parent = dget_parent(dentry);
1018
	dir = parent->d_inode;
1019
	LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
1020
		  AuDLNPair(dentry), bdst, dir->i_ino, locked);
1021
	DiMustReadLock(parent);
1022
	IiMustReadLock(dir);
1023
1024
	err = 0;
1025
	if (au_h_iptr(dir, bdst))
1026
		goto out;
1027
1028
	di_read_unlock(parent, AuLock_IR);
1029
	di_write_lock_parent2(parent);
1030
	/* someone else might change our inode while we were sleeping */
1031
	if (unlikely(!au_h_iptr(dir, bdst)))
1032
		err = au_cpup_dirs(dentry, bdst, locked);
1033
	di_downgrade_lock(parent, AuLock_IR);
1034
1035
 out:
1036
	dput(parent);
1037
	AuTraceErr(err);
1038
	return err;
1039
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/cpup.h (+82 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * copy-up/down functions
21
 *
22
 * $Id: cpup.h,v 1.2 2008/04/21 01:33:43 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_CPUP_H__
26
#define __AUFS_CPUP_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/aufs_type.h>
32
33
void au_cpup_attr_timesizes(struct inode *inode);
34
void au_cpup_attr_nlink(struct inode *inode);
35
void au_cpup_attr_changeable(struct inode *inode);
36
void au_cpup_igen(struct inode *inode, struct inode *h_inode);
37
void au_cpup_attr_all(struct inode *inode);
38
39
/* ---------------------------------------------------------------------- */
40
41
/* cpup flags */
42
#define AuCpup_DTIME	1	/* do dtime_store/revert */
43
#define au_ftest_cpup(flags, name)	((flags) & AuCpup_##name)
44
#define au_fset_cpup(flags, name)	{ (flags) |= AuCpup_##name; }
45
#define au_fclr_cpup(flags, name)	{ (flags) &= ~AuCpup_##name; }
46
47
int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
48
		   aufs_bindex_t bsrc, loff_t len, unsigned int flags);
49
int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
50
		       aufs_bindex_t bsrc, loff_t len, unsigned int flags);
51
int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
52
		   unsigned int flags);
53
int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
54
		       unsigned int flags);
55
int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
56
	       struct file *file);
57
int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
58
		   struct file *file);
59
60
int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked,
61
	       int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
62
			 struct dentry *h_parent, void *arg),
63
	       void *arg);
64
int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
65
		 struct dentry *locked);
66
int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
67
			  struct dentry *locked);
68
69
/* ---------------------------------------------------------------------- */
70
71
/* keep timestamps when copyup */
72
struct au_dtime {
73
	struct dentry *dt_dentry, *dt_h_dentry;
74
	struct au_hinode *dt_hdir;
75
	struct timespec dt_atime, dt_mtime;
76
};
77
void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
78
		    struct dentry *h_dentry, struct au_hinode *hdir);
79
void au_dtime_revert(struct au_dtime *dt);
80
81
#endif /* __KERNEL__ */
82
#endif /* __AUFS_CPUP_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dcsub.c (+233 lines)
Line 0 Link Here
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
 * sub-routines for dentry cache
21
 *
22
 * $Id: dcsub.c,v 1.3 2008/05/19 01:47:37 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
static void au_dpage_free(struct au_dpage *dpage)
28
{
29
	int i;
30
31
	AuTraceEnter();
32
	AuDebugOn(!dpage);
33
34
	for (i = 0; i < dpage->ndentry; i++)
35
		dput(dpage->dentries[i]);
36
	free_page((unsigned long)dpage->dentries);
37
}
38
39
int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
40
{
41
	int err;
42
	void *p;
43
44
	AuTraceEnter();
45
46
	err = -ENOMEM;
47
	dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
48
	if (unlikely(!dpages->dpages))
49
		goto out;
50
	p = (void *)__get_free_page(gfp);
51
	if (unlikely(!p))
52
		goto out_dpages;
53
	dpages->dpages[0].ndentry = 0;
54
	dpages->dpages[0].dentries = p;
55
	dpages->ndpage = 1;
56
	return 0; /* success */
57
58
 out_dpages:
59
	kfree(dpages->dpages);
60
 out:
61
	AuTraceErr(err);
62
	return err;
63
}
64
65
void au_dpages_free(struct au_dcsub_pages *dpages)
66
{
67
	int i;
68
69
	AuTraceEnter();
70
71
	for (i = 0; i < dpages->ndpage; i++)
72
		au_dpage_free(dpages->dpages + i);
73
	kfree(dpages->dpages);
74
}
75
76
static int au_dpages_append(struct au_dcsub_pages *dpages,
77
			    struct dentry *dentry, gfp_t gfp)
78
{
79
	int err, sz;
80
	struct au_dpage *dpage;
81
	void *p;
82
83
	//AuTraceEnter();
84
85
	dpage = dpages->dpages + dpages->ndpage - 1;
86
	AuDebugOn(!dpage);
87
	sz = PAGE_SIZE / sizeof(dentry);
88
	if (unlikely(dpage->ndentry >= sz)) {
89
		LKTRLabel(new dpage);
90
		err = -ENOMEM;
91
		sz = dpages->ndpage * sizeof(*dpages->dpages);
92
		p = au_kzrealloc(dpages->dpages, sz,
93
				 sz + sizeof(*dpages->dpages), gfp);
94
		if (unlikely(!p))
95
			goto out;
96
		dpages->dpages = p;
97
		dpage = dpages->dpages + dpages->ndpage;
98
		p = (void *)__get_free_page(gfp);
99
		if (unlikely(!p))
100
			goto out;
101
		dpage->ndentry = 0;
102
		dpage->dentries = p;
103
		dpages->ndpage++;
104
	}
105
106
	dpage->dentries[dpage->ndentry++] = dget(dentry);
107
	return 0; /* success */
108
109
 out:
110
	//AuTraceErr(err);
111
	return err;
112
}
113
114
int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
115
		   au_dpages_test test, void *arg)
116
{
117
	int err;
118
	struct dentry *this_parent = root;
119
	struct list_head *next;
120
	struct super_block *sb = root->d_sb;
121
122
	AuTraceEnter();
123
124
	err = 0;
125
	spin_lock(&dcache_lock);
126
 repeat:
127
	next = this_parent->d_subdirs.next;
128
 resume:
129
	if (this_parent->d_sb == sb
130
	    && !IS_ROOT(this_parent)
131
	    && atomic_read(&this_parent->d_count)
132
	    && this_parent->d_inode
133
	    && (!test || test(this_parent, arg))) {
134
		err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
135
		if (unlikely(err))
136
			goto out;
137
	}
138
139
	while (next != &this_parent->d_subdirs) {
140
		struct list_head *tmp = next;
141
		struct dentry *dentry = list_entry(tmp, struct dentry,
142
						   d_u.d_child);
143
		next = tmp->next;
144
		if (unlikely(/*d_unhashed(dentry) || */!dentry->d_inode))
145
			continue;
146
		if (!list_empty(&dentry->d_subdirs)) {
147
			this_parent = dentry;
148
			goto repeat;
149
		}
150
		if (dentry->d_sb == sb
151
		    && atomic_read(&dentry->d_count)
152
		    && (!test || test(dentry, arg))) {
153
			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
154
			if (unlikely(err))
155
				goto out;
156
		}
157
	}
158
159
	if (this_parent != root) {
160
		next = this_parent->d_u.d_child.next;
161
		this_parent = this_parent->d_parent; /* dcache_lock is locked */
162
		goto resume;
163
	}
164
 out:
165
	spin_unlock(&dcache_lock);
166
	AuTraceErr(err);
167
	return err;
168
}
169
170
int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
171
		       int do_include, au_dpages_test test, void *arg)
172
{
173
	int err;
174
175
	AuTraceEnter();
176
177
	err = 0;
178
	spin_lock(&dcache_lock);
179
	if (do_include && (!test || test(dentry, arg))) {
180
		err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
181
		if (unlikely(err))
182
			goto out;
183
	}
184
	while (!IS_ROOT(dentry)) {
185
		dentry = dentry->d_parent; /* dcache_lock is locked */
186
		if (!test || test(dentry, arg)) {
187
			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
188
			if (unlikely(err))
189
				break;
190
		}
191
	}
192
193
 out:
194
	spin_unlock(&dcache_lock);
195
196
	AuTraceErr(err);
197
	return err;
198
}
199
200
int au_test_subdir(struct dentry *d1, struct dentry *d2)
201
{
202
	int err;
203
	int i, j;
204
	struct au_dcsub_pages dpages;
205
	struct au_dpage *dpage;
206
	struct dentry **dentries;
207
208
	LKTRTrace("%.*s, %.*s\n", AuDLNPair(d1), AuDLNPair(d2));
209
210
	err = au_dpages_init(&dpages, GFP_TEMPORARY);
211
	if (unlikely(err))
212
		goto out;
213
	err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
214
	if (unlikely(err))
215
		goto out_dpages;
216
217
	for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
218
		dpage = dpages.dpages + i;
219
		dentries = dpage->dentries;
220
		for (j = dpage->ndentry - 1; !err && j >= 0; j--) {
221
			struct dentry *d;
222
			d = dentries[j];
223
			//AuDbg("d %.*s\n", AuDLNPair(d));
224
			err = (d == d2);
225
		}
226
	}
227
228
 out_dpages:
229
	au_dpages_free(&dpages);
230
 out:
231
	AuTraceErr(err);
232
	return err;
233
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dcsub.h (+54 lines)
Line 0 Link Here
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
 * sub-routines for dentry cache
21
 *
22
 * $Id: dcsub.h,v 1.1 2008/04/18 12:18:29 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_DCSUB_H__
26
#define __AUFS_DCSUB_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/dcache.h>
31
32
struct au_dpage {
33
	int ndentry;
34
	struct dentry **dentries;
35
};
36
37
struct au_dcsub_pages {
38
	int ndpage;
39
	struct au_dpage *dpages;
40
};
41
42
/* ---------------------------------------------------------------------- */
43
44
int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
45
void au_dpages_free(struct au_dcsub_pages *dpages);
46
typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
47
int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
48
		   au_dpages_test test, void *arg);
49
int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
50
		       int do_include, au_dpages_test test, void *arg);
51
int au_test_subdir(struct dentry *d1, struct dentry *d2);
52
53
#endif /* __KERNEL__ */
54
#endif /* __AUFS_DCSUB_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/debug.c (+328 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * debug print functions
21
 *
22
 * $Id: debug.c,v 1.2 2008/04/21 01:33:00 sfjro Exp $
23
 */
24
25
//#include <linux/errno.h>
26
#include "aufs.h"
27
28
atomic_t au_cond = ATOMIC_INIT(0);
29
30
char *au_plevel = KERN_DEBUG;
31
#define dpri(fmt, arg...) do { \
32
	if (LktrCond) \
33
		printk("%s" fmt, au_plevel, ##arg); \
34
} while (0)
35
36
/* ---------------------------------------------------------------------- */
37
38
void au_dpri_whlist(struct au_nhash *whlist)
39
{
40
	int i;
41
	struct hlist_head *head;
42
	struct au_vdir_wh *tpos;
43
	struct hlist_node *pos;
44
45
	for (i = 0; i < AuSize_NHASH; i++) {
46
		head = whlist->heads + i;
47
		hlist_for_each_entry(tpos, pos, head, wh_hash)
48
			dpri("b%d, %.*s, %d\n",
49
			     tpos->wh_bindex,
50
			     tpos->wh_str.len, tpos->wh_str.name,
51
			     tpos->wh_str.len);
52
	}
53
}
54
55
void au_dpri_vdir(struct au_vdir *vdir)
56
{
57
	int i;
58
	union au_vdir_deblk_p p;
59
	unsigned char *o;
60
61
	if (!vdir || IS_ERR(vdir)) {
62
		dpri("err %ld\n", PTR_ERR(vdir));
63
		return;
64
	}
65
66
	dpri("nblk %d, deblk %p, last{%d, %p}, ver %lu\n",
67
	     vdir->vd_nblk, vdir->vd_deblk,
68
	     vdir->vd_last.i, vdir->vd_last.p.p, vdir->vd_version);
69
	for (i = 0; i < vdir->vd_nblk; i++) {
70
		p.deblk = vdir->vd_deblk[i];
71
		o = p.p;
72
		dpri("[%d]: %p\n", i, o);
73
	}
74
}
75
76
static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
77
			struct dentry *wh)
78
{
79
	char *n = NULL;
80
	int l = 0, ntfy = 0;
81
82
	if (!inode || IS_ERR(inode)) {
83
		dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
84
		return -1;
85
	}
86
87
	/* the type of i_blocks depends upon CONFIG_LSF */
88
	BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
89
		     && sizeof(inode->i_blocks) != sizeof(u64));
90
	if (wh) {
91
		n = (void *)wh->d_name.name;
92
		l = wh->d_name.len;
93
	}
94
95
	ntfy = au_test_inotify(inode);
96
	dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, ntfy %d, sz %Lu, blk %Lu,"
97
	     " ct %Ld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
98
	     bindex,
99
	     inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
100
	     atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
101
	     ntfy,
102
	     i_size_read(inode), (u64)inode->i_blocks,
103
	     timespec_to_ns(&inode->i_ctime) & 0x0ffff,
104
	     inode->i_mapping ? inode->i_mapping->nrpages : 0,
105
	     inode->i_state, inode->i_flags, inode->i_generation,
106
	     l ? ", wh " : "", l, n);
107
	return 0;
108
}
109
110
void au_dpri_inode(struct inode *inode)
111
{
112
	struct au_iinfo *iinfo;
113
	aufs_bindex_t bindex;
114
	int err;
115
116
	err = do_pri_inode(-1, inode, NULL);
117
	if (err || !au_test_aufs(inode->i_sb))
118
		return;
119
120
	iinfo = au_ii(inode);
121
	if (!iinfo)
122
		return;
123
	dpri("i-1: bstart %d, bend %d, gen %d\n",
124
	     iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
125
	if (iinfo->ii_bstart < 0)
126
		return;
127
	for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
128
		do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
129
			     iinfo->ii_hinode[0 + bindex].hi_whdentry);
130
}
131
132
static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry,
133
			 struct list_head *intent)
134
{
135
	struct dentry *wh = NULL;
136
137
	if (!dentry || IS_ERR(dentry)) {
138
		dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
139
		return -1;
140
	}
141
	/* do not call dget_parent() here */
142
	dpri("d%d: %.*s/%.*s, %s, cnt %d, flags 0x%x, intent %d\n",
143
	     bindex,
144
	     AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
145
	     dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
146
	     atomic_read(&dentry->d_count), dentry->d_flags, !!intent);
147
	if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
148
		struct au_iinfo *iinfo = au_ii(dentry->d_inode);
149
		if (iinfo)
150
			wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
151
	}
152
	do_pri_inode(bindex, dentry->d_inode, wh);
153
	return 0;
154
}
155
156
static struct list_head *au_dbg_h_intent(struct au_dinfo *dinfo,
157
					 aufs_bindex_t bindex)
158
{
159
#ifdef CONFIG_AUFS_BR_NFS
160
	return dinfo->di_hdentry[0 + bindex].hd_intent_list;
161
#else
162
	return NULL;
163
#endif
164
}
165
166
void au_dpri_dentry(struct dentry *dentry)
167
{
168
	struct au_dinfo *dinfo;
169
	aufs_bindex_t bindex;
170
	int err;
171
172
	err = do_pri_dentry(-1, dentry, NULL);
173
	if (err || !au_test_aufs(dentry->d_sb))
174
		return;
175
176
	dinfo = au_di(dentry);
177
	if (!dinfo)
178
		return;
179
	dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
180
	     dinfo->di_bstart, dinfo->di_bend,
181
	     dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
182
	if (dinfo->di_bstart < 0)
183
		return;
184
	for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
185
		do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry,
186
			      au_dbg_h_intent(dinfo, bindex));
187
}
188
189
static int do_pri_file(aufs_bindex_t bindex, struct file *file)
190
{
191
	char a[32];
192
193
	if (!file || IS_ERR(file)) {
194
		dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
195
		return -1;
196
	}
197
	a[0] = 0;
198
	if (bindex < 0
199
	    && file->f_dentry
200
	    && au_test_aufs(file->f_dentry->d_sb)
201
	    && au_fi(file))
202
		snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file));
203
	dpri("f%d: mode 0x%x, flags 0%o, cnt %d, pos %Lu%s\n",
204
	     bindex, file->f_mode, file->f_flags, file_count(file),
205
	     file->f_pos, a);
206
	if (file->f_dentry)
207
		do_pri_dentry(bindex, file->f_dentry, NULL);
208
	return 0;
209
}
210
211
void au_dpri_file(struct file *file)
212
{
213
	struct au_finfo *finfo;
214
	aufs_bindex_t bindex;
215
	int err;
216
217
	err = do_pri_file(-1, file);
218
	if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
219
		return;
220
221
	finfo = au_fi(file);
222
	if (!finfo)
223
		return;
224
	if (finfo->fi_bstart < 0)
225
		return;
226
	for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
227
		struct au_hfile *hf;
228
		//dpri("bindex %d\n", bindex);
229
		hf = finfo->fi_hfile + bindex;
230
		do_pri_file(bindex, hf ? hf->hf_file : NULL);
231
	}
232
}
233
234
static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
235
{
236
	struct vfsmount *mnt;
237
	struct super_block *sb;
238
239
	if (!br || IS_ERR(br)
240
	    || !(mnt = br->br_mnt) || IS_ERR(mnt)
241
	    || !(sb = mnt->mnt_sb) || IS_ERR(sb)) {
242
		dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
243
		return -1;
244
	}
245
246
	dpri("s%d: {perm 0x%x, cnt %d}, "
247
	     "%s, flags 0x%lx, cnt(BIAS) %d, active %d, xino %d\n",
248
	     bindex, br->br_perm, au_br_count(br),
249
	     au_sbtype(sb), sb->s_flags, sb->s_count - S_BIAS,
250
	     atomic_read(&sb->s_active), !!br->br_xino);
251
	return 0;
252
}
253
254
void au_dpri_sb(struct super_block *sb)
255
{
256
	struct au_sbinfo *sbinfo;
257
	aufs_bindex_t bindex;
258
	int err;
259
	struct vfsmount mnt = { .mnt_sb = sb };
260
	struct au_branch fake = {
261
		.br_perm = 0,
262
		.br_mnt = &mnt,
263
		.br_count = ATOMIC_INIT(0),
264
		.br_xino = NULL
265
	};
266
267
	atomic_set(&fake.br_count, 0);
268
	smp_mb(); /* atomic_set */
269
	err = do_pri_br(-1, &fake);
270
	dpri("dev 0x%x\n", sb->s_dev);
271
	if (err || !au_test_aufs(sb))
272
		return;
273
274
	sbinfo = au_sbi(sb);
275
	if (!sbinfo)
276
		return;
277
	for (bindex = 0; bindex <= sbinfo->si_bend; bindex++) {
278
		//dpri("bindex %d\n", bindex);
279
		do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
280
	}
281
}
282
283
/* ---------------------------------------------------------------------- */
284
285
void au_dbg_sleep(int sec)
286
{
287
	static DECLARE_WAIT_QUEUE_HEAD(wq);
288
	wait_event_timeout(wq, 0, sec * HZ);
289
}
290
291
/* ---------------------------------------------------------------------- */
292
293
void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
294
{
295
#ifdef ForceInotify
296
	au_opt_set_udba(sbinfo->si_mntflags, UDBA_INOTIFY);
297
#endif
298
#ifdef ForceDlgt
299
	au_opt_set(sbinfo->si_mntflags, DLGT);
300
#endif
301
#ifdef ForceNoPlink
302
	au_opt_clr(sbinfo->si_mntflags, PLINK);
303
#endif
304
#ifdef ForceNoXino
305
	au_opt_clr(sbinfo->si_mntflags, XINO);
306
#endif
307
#ifdef ForceNoRefrof
308
	au_opt_clr(sbinfo->si_mntflags, REFROF);
309
#endif
310
}
311
312
int __init au_debug_init(void)
313
{
314
	aufs_bindex_t bindex;
315
	struct au_vdir_destr destr;
316
317
	bindex = -1;
318
	AuDebugOn(bindex >= 0);
319
320
	destr.len = -1;
321
	AuDebugOn(destr.len < NAME_MAX);
322
323
#ifdef CONFIG_4KSTACKS
324
	AuWarn("CONFIG_4KSTACKS is defined.\n");
325
#endif
326
327
	return 0;
328
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/debug.h (+210 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * debug print functions
21
 *
22
 * $Id: debug.h,v 1.2 2008/04/21 02:00:37 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_DEBUG_H__
26
#define __AUFS_DEBUG_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
32
/* to debug easier, do not make it an inlined function */
33
#define MtxMustLock(mtx)	AuDebugOn(!mutex_is_locked(mtx))
34
35
#ifdef CONFIG_AUFS_DEBUG
36
/* sparse warns about pointer */
37
#define AuDebugOn(a)		BUG_ON(!!(a))
38
extern atomic_t au_cond;
39
#define au_debug_on()		atomic_inc_return(&au_cond)
40
#define au_debug_off()		atomic_dec_return(&au_cond)
41
static inline int au_debug_test(void)
42
{
43
	return atomic_read(&au_cond);
44
}
45
#else
46
#define AuDebugOn(a)		do {} while (0)
47
#define au_debug_on()		do {} while (0)
48
#define au_debug_off()		do {} while (0)
49
static inline int au_debug_test(void)
50
{
51
	return 0;
52
}
53
#endif /* CONFIG_AUFS_DEBUG */
54
55
/* ---------------------------------------------------------------------- */
56
57
/* debug print */
58
#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
59
#include <linux/lktr.h>
60
#ifdef CONFIG_AUFS_DEBUG
61
#undef LktrCond
62
#define LktrCond	unlikely(au_debug_test() || (lktr_cond && lktr_cond()))
63
#endif
64
#else
65
#define LktrCond			au_debug_test()
66
#define LKTRDumpVma(pre, vma, suf)	do {} while (0)
67
#define LKTRDumpStack()			do {} while (0)
68
#define LKTRTrace(fmt, args...) do { \
69
	if (LktrCond) \
70
		AuDbg(fmt, ##args); \
71
} while (0)
72
#define LKTRLabel(label)		LKTRTrace("%s\n", #label)
73
#endif /* CONFIG_LKTR */
74
75
#define AuTraceErr(e) do { \
76
	if (unlikely((e) < 0)) \
77
		LKTRTrace("err %d\n", (int)(e)); \
78
} while (0)
79
80
#define AuTraceErrPtr(p) do { \
81
	if (IS_ERR(p)) \
82
		LKTRTrace("err %ld\n", PTR_ERR(p)); \
83
} while (0)
84
85
#define AuTraceEnter()	LKTRLabel(enter)
86
87
/* dirty macros for debug print, use with "%.*s" and caution */
88
#define AuLNPair(qstr)		(qstr)->len, (qstr)->name
89
#define AuDLNPair(d)		AuLNPair(&(d)->d_name)
90
91
/* ---------------------------------------------------------------------- */
92
93
#define AuDpri(lvl, fmt, arg...) \
94
	printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
95
	       __func__, __LINE__, current->comm, current->pid, ##arg)
96
#define AuDbg(fmt, arg...)	AuDpri(KERN_DEBUG, fmt, ##arg)
97
#define AuInfo(fmt, arg...)	AuDpri(KERN_INFO, fmt, ##arg)
98
#define AuWarn(fmt, arg...)	AuDpri(KERN_WARNING, fmt, ##arg)
99
#define AuErr(fmt, arg...)	AuDpri(KERN_ERR, fmt, ##arg)
100
#define AuIOErr(fmt, arg...)	AuErr("I/O Error, " fmt, ##arg)
101
#define AuIOErrWhck(fmt, arg...) AuErr("I/O Error, try whck. " fmt, ##arg)
102
#define AuWarn1(fmt, arg...) do { \
103
	static unsigned char _c; \
104
	if (!_c++) AuWarn(fmt, ##arg); \
105
} while (0)
106
107
#define AuErr1(fmt, arg...) do { \
108
	static unsigned char _c; \
109
	if (!_c++) AuErr(fmt, ##arg); \
110
} while (0)
111
112
#define AuIOErr1(fmt, arg...) do { \
113
	static unsigned char _c; \
114
	if (!_c++) AuIOErr(fmt, ##arg); \
115
} while (0)
116
117
#define AuUnsupportMsg	"This operation is not supported." \
118
			" Please report this application to aufs-users ML."
119
#define AuUnsupport(fmt, args...) do { \
120
	AuErr(AuUnsupportMsg "\n" fmt, ##args); \
121
	dump_stack(); \
122
} while (0)
123
124
/* ---------------------------------------------------------------------- */
125
126
struct au_sbinfo;
127
#ifdef CONFIG_AUFS_DEBUG
128
extern char *au_plevel;
129
struct au_nhash;
130
void au_dpri_whlist(struct au_nhash *whlist);
131
struct au_vdir;
132
void au_dpri_vdir(struct au_vdir *vdir);
133
void au_dpri_inode(struct inode *inode);
134
void au_dpri_dentry(struct dentry *dentry);
135
void au_dpri_file(struct file *filp);
136
void au_dpri_sb(struct super_block *sb);
137
void au_dbg_sleep(int sec);
138
int __init au_debug_init(void);
139
void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
140
#define AuDbgWhlist(w) do { \
141
	LKTRTrace(#w "\n"); \
142
	au_dpri_whlist(w); \
143
} while (0)
144
145
#define AuDbgVdir(v) do { \
146
	LKTRTrace(#v "\n"); \
147
	au_dpri_vdir(v); \
148
} while (0)
149
150
#define AuDbgInode(i) do { \
151
	LKTRTrace(#i "\n"); \
152
	au_dpri_inode(i); \
153
} while (0)
154
155
#define AuDbgDentry(d) do { \
156
	LKTRTrace(#d "\n"); \
157
	au_dpri_dentry(d); \
158
} while (0)
159
160
#define AuDbgFile(f) do { \
161
	LKTRTrace(#f "\n"); \
162
	au_dpri_file(f); \
163
} while (0)
164
165
#define AuDbgSb(sb) do { \
166
	LKTRTrace(#sb "\n"); \
167
	au_dpri_sb(sb); \
168
} while (0)
169
170
#define AuDbgSleep(sec) do { \
171
	AuDbg("sleep %d sec\n", sec); \
172
	au_dbg_sleep(sec); \
173
} while (0)
174
#else
175
static inline int au_debug_init(void)
176
{
177
	return 0;
178
}
179
static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
180
{
181
	/* empty */
182
}
183
#define AuDbgWhlist(w)		do {} while (0)
184
#define AuDbgVdir(v)		do {} while (0)
185
#define AuDbgInode(i)		do {} while (0)
186
#define AuDbgDentry(d)		do {} while (0)
187
#define AuDbgFile(f)		do {} while (0)
188
#define AuDbgSb(sb)		do {} while (0)
189
#define AuDbgSleep(sec)		do {} while (0)
190
#endif /* CONFIG_AUFS_DEBUG */
191
192
#ifdef DbgUdbaRace
193
#define AuDbgSleep_UdbaRace()	AuDbgSleep(DbgUdbaRace)
194
#else
195
#define AuDbgSleep_UdbaRace()	do {} while (0)
196
#endif
197
198
#ifdef CONFIG_AUFS_MAGIC_SYSRQ
199
int __init au_sysrq_init(void);
200
void au_sysrq_fin(void);
201
#else
202
static inline int au_sysrq_init(void)
203
{
204
	return 0;
205
}
206
#define au_sysrq_fin()		do {} while (0)
207
#endif
208
209
#endif /* __KERNEL__ */
210
#endif /* __AUFS_DEBUG_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dentry.c (+976 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * lookup and dentry operations
21
 *
22
 * $Id: dentry.c,v 1.6 2008/05/19 01:46:53 sfjro Exp $
23
 */
24
25
//#include <linux/fs.h>
26
//#include <linux/namei.h>
27
#include "aufs.h"
28
29
/* ---------------------------------------------------------------------- */
30
31
/*
32
 * au_lkup_one() is a generic abstract entry function which calls
33
 * lookup_one_len() or __lookup_hash() finally. it is some condisions that makes
34
 * lookup complicated, which are nfs branch, open-intent and dlgt mode.
35
 */
36
37
#if defined(CONFIG_AUFS_BR_NFS) || defined(CONFIG_AUFS_DLGT)
38
/* cf. lookup_one_len() in linux/fs/namei.c */
39
struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
40
			   struct au_ndx *ndx)
41
{
42
	struct dentry *dentry;
43
44
	LKTRTrace("%.*s/%.*s, ndx{%d, 0x%x}\n",
45
		  AuDLNPair(parent), len, name, !!ndx->nfsmnt, ndx->flags);
46
47
	ndx->nd_file = NULL;
48
	if (!ndx->nfsmnt)
49
		dentry = au_lkup_one_dlgt(name, parent, len, ndx->flags);
50
	else
51
		dentry = au_lkup_hash(name, parent, len, ndx);
52
53
	AuTraceErrPtr(dentry);
54
	return dentry;
55
}
56
#endif /* CONFIG_AUFS_BR_NFS || CONFIG_AUFS_DLGT */
57
58
struct au_lkup_one_args {
59
	struct dentry **errp;
60
	const char *name;
61
	struct dentry *parent;
62
	int len;
63
	struct au_ndx *ndx;
64
};
65
66
static void au_call_lkup_one(void *args)
67
{
68
	struct au_lkup_one_args *a = args;
69
	*a->errp = au_lkup_one(a->name, a->parent, a->len, a->ndx);
70
}
71
72
#define AuLkup_ALLOW_NEG	1
73
#define AuLkup_DLGT		(1 << 1)
74
#define AuLkup_DIRPERM1		(1 << 2)
75
#define au_ftest_lkup(flags, name)	((flags) & AuLkup_##name)
76
#define au_fset_lkup(flags, name)	{ (flags) |= AuLkup_##name; }
77
#define au_fclr_lkup(flags, name)	{ (flags) &= ~AuLkup_##name; }
78
#ifndef CONFIG_AUFS_DLGT
79
#undef AuLkup_DLGT
80
#define AuLkup_DLGT	0
81
#undef AuLkup_DIRPERM1
82
#define AuLkup_DIRPERM1	0
83
#endif
84
85
struct au_do_lookup_args {
86
	unsigned int		flags;
87
	mode_t			type;
88
	struct nameidata	*nd;
89
};
90
91
/*
92
 * returns positive/negative dentry, NULL or an error.
93
 * NULL means whiteout-ed or not-found.
94
 */
95
static noinline_for_stack
96
struct dentry *au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
97
			    aufs_bindex_t bindex, struct qstr *wh_name,
98
			    struct au_do_lookup_args *args)
99
{
100
	struct dentry *h_dentry;
101
	int wh_found, wh_able, opq, err;
102
	struct inode *h_dir, *h_inode, *inode;
103
	struct qstr *name;
104
	struct super_block *sb;
105
	unsigned int nd_flags;
106
	struct au_ndx ndx = {
107
		.flags	= 0,
108
		.nd	= args->nd
109
	};
110
	const int allow_neg = au_ftest_lkup(args->flags, ALLOW_NEG);
111
112
	LKTRTrace("%.*s/%.*s, b%d, {flags 0x%x, type 0%o, nd %d}\n",
113
		  AuDLNPair(h_parent), AuDLNPair(dentry), bindex,
114
		  args->flags, args->type, !!args->nd);
115
	if (args->nd)
116
		LKTRTrace("nd{0x%x}\n", args->nd->flags);
117
	AuDebugOn(IS_ROOT(dentry));
118
	h_dir = h_parent->d_inode;
119
120
	nd_flags = 0;
121
	wh_found = 0;
122
	sb = dentry->d_sb;
123
	ndx.nfsmnt = au_nfsmnt(sb, bindex);
124
	if (unlikely(au_ftest_lkup(args->flags, DLGT)))
125
		au_fset_ndx(ndx.flags, DLGT);
126
	if (unlikely(au_ftest_lkup(args->flags, DIRPERM1)))
127
		au_fset_ndx(ndx.flags, DIRPERM1);
128
	LKTRTrace("nfsmnt %p\n", ndx.nfsmnt);
129
	ndx.br = au_sbr(sb, bindex);
130
	wh_able = au_br_whable(ndx.br->br_perm);
131
	name = &dentry->d_name;
132
	if (unlikely(wh_able))
133
		wh_found = au_test_robr_wh(name, h_parent, wh_name,
134
					   /*try_sio*/0, &ndx);
135
	//if (LktrCond) wh_found = -1;
136
	h_dentry = ERR_PTR(wh_found);
137
	if (!wh_found)
138
		goto real_lookup;
139
	if (unlikely(wh_found < 0))
140
		goto out;
141
142
	/* We found a whiteout */
143
	//au_set_dbend(dentry, bindex);
144
	au_set_dbwh(dentry, bindex);
145
	if (!allow_neg)
146
		return NULL; /* success */
147
	if (unlikely(ndx.nd
148
		     && au_test_nfs(h_parent->d_sb)
149
		     && (ndx.nd->flags & LOOKUP_CREATE))) {
150
		nd_flags = ndx.nd->flags;
151
		ndx.nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE);
152
	}
153
154
 real_lookup:
155
	/* do not superio. */
156
	h_dentry = au_lkup_one(name->name, h_parent, name->len, &ndx);
157
	//if (LktrCond) {dput(h_dentry); h_dentry = ERR_PTR(-1);}
158
	if (IS_ERR(h_dentry))
159
		goto out;
160
	AuDebugOn(d_unhashed(h_dentry));
161
	h_inode = h_dentry->d_inode;
162
	if (!h_inode) {
163
		if (!allow_neg)
164
			goto out_neg;
165
	} else if (wh_found
166
		   || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
167
		goto out_neg;
168
169
	if (au_dbend(dentry) <= bindex)
170
		au_set_dbend(dentry, bindex);
171
	if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
172
		au_set_dbstart(dentry, bindex);
173
	au_set_h_dptr(dentry, bindex, h_dentry);
174
175
	err = au_br_nfs_h_intent(ndx.nd_file, dentry, bindex, args->nd);
176
	if (unlikely(err)) {
177
		h_dentry = ERR_PTR(err);
178
		goto out;
179
	}
180
181
	inode = dentry->d_inode;
182
	if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
183
	    || (inode && !S_ISDIR(inode->i_mode)))
184
		goto out; /* success */
185
186
	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
187
	opq = au_diropq_test(h_dentry, &ndx);
188
	//if (LktrCond) opq = -1;
189
	mutex_unlock(&h_inode->i_mutex);
190
	if (opq > 0)
191
		au_set_dbdiropq(dentry, bindex);
192
	else if (unlikely(opq < 0)) {
193
		au_set_h_dptr(dentry, bindex, NULL);
194
		h_dentry = ERR_PTR(opq);
195
	}
196
	goto out;
197
198
 out_neg:
199
	dput(h_dentry);
200
	h_dentry = NULL;
201
 out:
202
	if (unlikely(nd_flags))
203
		ndx.nd->flags |= (nd_flags & (LOOKUP_OPEN | LOOKUP_CREATE));
204
	AuTraceErrPtr(h_dentry);
205
	return h_dentry;
206
}
207
208
/*
209
 * returns the number of hidden positive dentries,
210
 * otherwise an error.
211
 * can be called at unlinking with @type is zero.
212
 */
213
int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
214
		   struct nameidata *nd)
215
{
216
	int npositive, err, isdir;
217
	struct dentry *parent;
218
	aufs_bindex_t bindex, btail, bdiropq;
219
	const struct qstr *name = &dentry->d_name;
220
	struct qstr whname;
221
	struct super_block *sb;
222
	unsigned int mnt_flags;
223
	struct inode *inode;
224
	struct au_do_lookup_args args = {
225
		.type	= type,
226
		.nd	= nd
227
	};
228
229
	LKTRTrace("%.*s, b%d, type 0%o\n", AuLNPair(name), bstart, type);
230
	AuDebugOn(bstart < 0 || IS_ROOT(dentry));
231
232
	/* dir may not be locked */
233
	parent = dget_parent(dentry);
234
235
	err = au_test_robr_shwh(dentry->d_sb, name);
236
	if (unlikely(err))
237
		goto out;
238
239
	err = au_wh_name_alloc(name->name, name->len, &whname);
240
	//if (LktrCond) {au_wh_name_free(&whname); err = -1;}
241
	if (unlikely(err))
242
		goto out;
243
244
	sb = dentry->d_sb;
245
	mnt_flags = au_mntflags(sb);
246
	inode = dentry->d_inode;
247
	isdir = (inode && S_ISDIR(inode->i_mode));
248
	args.flags = 0;
249
	if (unlikely(au_opt_test_dlgt(mnt_flags)))
250
		au_fset_lkup(args.flags, DLGT);
251
	if (unlikely(au_opt_test_dirperm1(mnt_flags)))
252
		au_fset_lkup(args.flags, DIRPERM1);
253
	if (!type)
254
		au_fset_lkup(args.flags, ALLOW_NEG);
255
	npositive = 0;
256
	btail = au_dbtaildir(parent);
257
	for (bindex = bstart; bindex <= btail; bindex++) {
258
		struct dentry *h_parent, *h_dentry;
259
		struct inode *h_inode, *h_dir;
260
261
		h_dentry = au_h_dptr(dentry, bindex);
262
		if (h_dentry) {
263
			if (h_dentry->d_inode)
264
				npositive++;
265
			if (type != S_IFDIR)
266
				break;
267
			continue;
268
		}
269
		h_parent = au_h_dptr(parent, bindex);
270
		if (!h_parent)
271
			continue;
272
		h_dir = h_parent->d_inode;
273
		if (!h_dir || !S_ISDIR(h_dir->i_mode))
274
			continue;
275
276
		mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
277
		h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
278
					&args);
279
		// do not dput for testing
280
		//if (LktrCond) {h_dentry = ERR_PTR(-1);}
281
		mutex_unlock(&h_dir->i_mutex);
282
		err = PTR_ERR(h_dentry);
283
		if (IS_ERR(h_dentry))
284
			goto out_wh;
285
		au_fclr_lkup(args.flags, ALLOW_NEG);
286
287
		if (au_dbwh(dentry) >= 0)
288
			break;
289
		if (!h_dentry)
290
			continue;
291
		h_inode = h_dentry->d_inode;
292
		if (!h_inode)
293
			continue;
294
		npositive++;
295
		if (!args.type)
296
			args.type = h_inode->i_mode & S_IFMT;
297
		if (args.type != S_IFDIR)
298
			break;
299
		else if (isdir) {
300
			/* the type of lowers may be different */
301
			bdiropq = au_dbdiropq(dentry);
302
			if (bdiropq >= 0 && bdiropq <= bindex)
303
				break;
304
		}
305
	}
306
307
	if (npositive) {
308
		LKTRLabel(positive);
309
		au_update_dbstart(dentry);
310
	}
311
	err = npositive;
312
313
 out_wh:
314
	au_wh_name_free(&whname);
315
 out:
316
	dput(parent);
317
	AuTraceErr(err);
318
	return err;
319
}
320
321
struct dentry *au_sio_lkup_one(const char *name, struct dentry *parent, int len,
322
			       struct au_ndx *ndx)
323
{
324
	struct dentry *dentry;
325
	int wkq_err;
326
327
	LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
328
329
	if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC,
330
				au_ftest_ndx(ndx->flags, DLGT)))
331
		dentry = au_lkup_one(name, parent, len, ndx);
332
	else {
333
		// ugly
334
		unsigned int flags = ndx->flags;
335
		struct au_lkup_one_args args = {
336
			.errp	= &dentry,
337
			.name	= name,
338
			.parent	= parent,
339
			.len	= len,
340
			.ndx	= ndx
341
		};
342
343
		au_fclr_ndx(ndx->flags, DLGT);
344
		au_fclr_ndx(ndx->flags, DIRPERM1);
345
		wkq_err = au_wkq_wait(au_call_lkup_one, &args, /*dlgt*/0);
346
		if (unlikely(wkq_err))
347
			dentry = ERR_PTR(wkq_err);
348
		ndx->flags = flags;
349
	}
350
351
	AuTraceErrPtr(dentry);
352
	return dentry;
353
}
354
355
/*
356
 * lookup @dentry on @bindex which should be negative.
357
 */
358
int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
359
{
360
	int err;
361
	struct dentry *parent, *h_parent, *h_dentry;
362
	struct inode *h_dir;
363
	struct au_ndx ndx = {
364
		.flags	= 0,
365
		.nd	= NULL,
366
		//.br	= NULL
367
	};
368
	struct super_block *sb;
369
	unsigned int mnt_flags;
370
371
	LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
372
	/* dir may not be locked */
373
	parent = dget_parent(dentry);
374
	AuDebugOn(!parent || !parent->d_inode
375
		  || !S_ISDIR(parent->d_inode->i_mode));
376
	h_parent = au_h_dptr(parent, bindex);
377
	AuDebugOn(!h_parent);
378
	h_dir = h_parent->d_inode;
379
	AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode));
380
381
	sb = dentry->d_sb;
382
	mnt_flags = au_mntflags(sb);
383
	ndx.nfsmnt = au_nfsmnt(sb, bindex);
384
	if (unlikely(au_opt_test_dlgt(mnt_flags)))
385
		au_fset_ndx(ndx.flags, DLGT);
386
	if (unlikely(au_opt_test_dirperm1(mnt_flags)))
387
		au_fset_ndx(ndx.flags, DIRPERM1);
388
	h_dentry = au_sio_lkup_one(dentry->d_name.name, h_parent,
389
				   dentry->d_name.len, &ndx);
390
	//if (LktrCond) {dput(h_dentry); h_dentry = ERR_PTR(-1);}
391
	err = PTR_ERR(h_dentry);
392
	if (IS_ERR(h_dentry))
393
		goto out;
394
	if (unlikely(h_dentry->d_inode)) {
395
		err = -EIO;
396
		AuIOErr("b%d %.*s should be negative.\n",
397
			bindex, AuDLNPair(h_dentry));
398
		dput(h_dentry);
399
		goto out;
400
	}
401
402
	if (bindex < au_dbstart(dentry))
403
		au_set_dbstart(dentry, bindex);
404
	if (au_dbend(dentry) < bindex)
405
		au_set_dbend(dentry, bindex);
406
	au_set_h_dptr(dentry, bindex, h_dentry);
407
	err = 0;
408
409
 out:
410
	dput(parent);
411
	AuTraceErr(err);
412
	return err;
413
}
414
415
/*
416
 * returns the number of found hidden positive dentries,
417
 * otherwise an error.
418
 */
419
int au_refresh_hdentry(struct dentry *dentry, mode_t type)
420
{
421
	int npositive, new_sz;
422
	struct au_dinfo *dinfo;
423
	struct super_block *sb;
424
	struct dentry *parent;
425
	aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend;
426
	struct au_hdentry *p;
427
	au_gen_t sgen;
428
429
	LKTRTrace("%.*s, type 0%o\n", AuDLNPair(dentry), type);
430
	DiMustWriteLock(dentry);
431
	sb = dentry->d_sb;
432
	AuDebugOn(IS_ROOT(dentry));
433
	sgen = au_sigen(sb);
434
	parent = dget_parent(dentry);
435
	AuDebugOn(au_digen(parent) != sgen
436
		  || au_iigen(parent->d_inode) != sgen);
437
438
	npositive = -ENOMEM;
439
	new_sz = sizeof(*dinfo->di_hdentry) * (au_sbend(sb) + 1);
440
	dinfo = au_di(dentry);
441
	p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1),
442
			 new_sz, GFP_KERNEL);
443
	//p = NULL;
444
	if (unlikely(!p))
445
		goto out;
446
	dinfo->di_hdentry = p;
447
448
	bend = dinfo->di_bend;
449
	bwh = dinfo->di_bwh;
450
	bdiropq = dinfo->di_bdiropq;
451
	p += dinfo->di_bstart;
452
	for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
453
		struct dentry *hd, *hdp;
454
		struct au_hdentry tmp, *q;
455
		aufs_bindex_t new_bindex;
456
457
		hd = p->hd_dentry;
458
		if (!hd)
459
			continue;
460
		hdp = dget_parent(hd);
461
		if (hdp == au_h_dptr(parent, bindex)) {
462
			dput(hdp);
463
			continue;
464
		}
465
466
		new_bindex = au_find_dbindex(parent, hdp);
467
		dput(hdp);
468
		AuDebugOn(new_bindex == bindex);
469
		if (dinfo->di_bwh == bindex)
470
			bwh = new_bindex;
471
		if (dinfo->di_bdiropq == bindex)
472
			bdiropq = new_bindex;
473
		if (new_bindex < 0) { // test here
474
			au_hdput(p, /*do_free*/0);
475
			p->hd_dentry = NULL;
476
			continue;
477
		}
478
		/* swap two hidden dentries, and loop again */
479
		q = dinfo->di_hdentry + new_bindex;
480
		tmp = *q;
481
		*q = *p;
482
		*p = tmp;
483
		if (tmp.hd_dentry) {
484
			bindex--;
485
			p--;
486
		}
487
	}
488
489
	// test here
490
	dinfo->di_bwh = -1;
491
	if (unlikely(bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh)))
492
		dinfo->di_bwh = bwh;
493
	dinfo->di_bdiropq = -1;
494
	if (unlikely(bdiropq >= 0 && bdiropq <= au_sbend(sb)
495
		     && au_sbr_whable(sb, bdiropq)))
496
		dinfo->di_bdiropq = bdiropq;
497
	parent_bend = au_dbend(parent);
498
	p = dinfo->di_hdentry;
499
	for (bindex = 0; bindex <= parent_bend; bindex++, p++)
500
		if (p->hd_dentry) {
501
			dinfo->di_bstart = bindex;
502
			break;
503
		}
504
	p = dinfo->di_hdentry + parent_bend;
505
	//for (bindex = parent_bend; bindex > dinfo->di_bstart; bindex--, p--)
506
	for (bindex = parent_bend; bindex >= 0; bindex--, p--)
507
		if (p->hd_dentry) {
508
			dinfo->di_bend = bindex;
509
			break;
510
		}
511
512
	npositive = 0;
513
	parent_bstart = au_dbstart(parent);
514
	if (type != S_IFDIR && dinfo->di_bstart == parent_bstart)
515
		goto out_dgen; /* success */
516
517
	npositive = au_lkup_dentry(dentry, parent_bstart, type, /*nd*/NULL);
518
	//if (LktrCond) npositive = -1;
519
	if (npositive < 0)
520
		goto out;
521
	if (unlikely(dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart))
522
		d_drop(dentry);
523
524
 out_dgen:
525
	au_update_digen(dentry);
526
 out:
527
	dput(parent);
528
	AuTraceErr(npositive);
529
	return npositive;
530
}
531
532
static int au_lock_nd(struct dentry *dentry, struct nameidata *nd)
533
{
534
	int locked = 0;
535
	if (nd && dentry != nd->path.dentry) {
536
		di_read_lock_parent(nd->path.dentry, 0);
537
		locked = 1;
538
	}
539
	return locked;
540
}
541
542
static void au_unlock_nd(int locked, struct nameidata *nd)
543
{
544
	if (locked)
545
		di_read_unlock(nd->path.dentry, 0);
546
}
547
548
//#define TestingFuse
549
static noinline_for_stack int
550
au_do_h_d_reval(struct dentry *dentry, aufs_bindex_t bindex,
551
		struct nameidata *nd, struct dentry *h_dentry)
552
{
553
	int err, valid, e;
554
	int (*reval)(struct dentry *, struct nameidata *);
555
	struct super_block *sb;
556
	struct nameidata fake_nd, *p;
557
558
	LKTRTrace("%.*s, b%d, nd %d\n", AuDLNPair(dentry), bindex, !!nd);
559
560
	err = 0;
561
	reval = NULL;
562
	if (h_dentry->d_op)
563
		reval = h_dentry->d_op->d_revalidate;
564
	if (!reval)
565
		goto out;
566
567
	sb = dentry->d_sb;
568
	if (nd) {
569
		memcpy(&fake_nd, nd, sizeof(*nd));
570
		err = au_fake_intent(&fake_nd, au_sbr_perm(sb, bindex));
571
		if (unlikely(err)) {
572
			err = -EINVAL;
573
			goto out;
574
		}
575
	}
576
	p = au_fake_dm(&fake_nd, nd, sb, bindex);
577
	AuDebugOn(IS_ERR(p));
578
	AuDebugOn(nd && p != &fake_nd);
579
	LKTRTrace("b%d\n", bindex);
580
581
	/* it may return tri-state */
582
	valid = reval(h_dentry, p);
583
	if (unlikely(valid < 0))
584
		err = valid;
585
	else if (!valid)
586
		err = -EINVAL;
587
	else
588
		AuDebugOn(err);
589
590
	if (p) {
591
		AuDebugOn(!nd);
592
		e = au_hin_after_reval(p, dentry, bindex, nd->intent.open.file);
593
#ifndef TestingFuse
594
		au_update_fuse_h_inode(p->path.mnt, h_dentry); /*ignore*/
595
#endif
596
		if (unlikely(e && !err))
597
			err = e;
598
	}
599
#ifndef TestingFuse
600
	else
601
		au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
602
#endif
603
	au_fake_dm_release(p);
604
605
 out:
606
	AuTraceErr(err);
607
	return err;
608
}
609
610
static noinline_for_stack int
611
h_d_revalidate(struct dentry *dentry, struct inode *inode,
612
	       struct nameidata *nd, int do_udba)
613
{
614
	int err, plus, locked, unhashed, is_root, h_plus;
615
	aufs_bindex_t bindex, btail, bstart, ibs, ibe;
616
	struct super_block *sb;
617
	struct inode *first, *h_inode, *h_cached_inode;
618
	umode_t mode, h_mode;
619
	struct dentry *h_dentry;
620
	struct qstr *name;
621
622
	LKTRTrace("%.*s, nd %d\n", AuDLNPair(dentry), !!nd);
623
	AuDebugOn(inode && au_digen(dentry) != au_iigen(inode));
624
625
	err = 0;
626
	sb = dentry->d_sb;
627
	plus = 0;
628
	mode = 0;
629
	first = NULL;
630
	ibs = -1;
631
	ibe = -1;
632
	unhashed = d_unhashed(dentry);
633
	is_root = IS_ROOT(dentry);
634
	name = &dentry->d_name;
635
636
	/*
637
	 * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
638
	 * But inotify doesn't fire some necessary events,
639
	 *	IN_ATTRIB for atime/nlink/pageio
640
	 *	IN_DELETE for NFS dentry
641
	 * Let's do REVAL test too.
642
	 */
643
	if (do_udba && inode) {
644
		mode = (inode->i_mode & S_IFMT);
645
		plus = (inode->i_nlink > 0);
646
		first = au_h_iptr(inode, au_ibstart(inode));
647
		ibs = au_ibstart(inode);
648
		ibe = au_ibend(inode);
649
	}
650
651
	bstart = au_dbstart(dentry);
652
	btail = bstart;
653
	if (inode && S_ISDIR(inode->i_mode))
654
		btail = au_dbtaildir(dentry);
655
	locked = au_lock_nd(dentry, nd);
656
	for (bindex = bstart; bindex <= btail; bindex++) {
657
		h_dentry = au_h_dptr(dentry, bindex);
658
		if (!h_dentry)
659
			continue;
660
661
		LKTRTrace("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
662
#ifdef TestingFuse
663
		/* force re-lookup for fuse, in order to update attributes */
664
		if (unlikely(au_test_fuse(h_dentry->d_sb)))
665
			goto err;
666
#endif
667
668
		if (unlikely(do_udba
669
			     && !is_root
670
			     && (unhashed != d_unhashed(h_dentry)
671
				 || name->len != h_dentry->d_name.len
672
				 || memcmp(name->name, h_dentry->d_name.name,
673
					   name->len)
674
				     ))) {
675
			LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n",
676
				  unhashed, d_unhashed(h_dentry),
677
				  AuDLNPair(dentry), AuDLNPair(h_dentry));
678
			goto err;
679
		}
680
681
		err = au_do_h_d_reval(dentry, bindex, nd, h_dentry);
682
		if (unlikely(err))
683
			/* do not goto err, to keep the errno */
684
			break;
685
686
		if (unlikely(!do_udba))
687
			continue;
688
689
		/* UDBA tests */
690
		h_inode = h_dentry->d_inode;
691
		if (unlikely(!!inode != !!h_inode)) {
692
			//AuDbg("here\n");
693
			goto err;
694
		}
695
696
		h_plus = plus;
697
		h_mode = mode;
698
		h_cached_inode = h_inode;
699
		if (h_inode) {
700
			h_mode = (h_inode->i_mode & S_IFMT);
701
			h_plus = (h_inode->i_nlink > 0);
702
			//AuDbgInode(inode);
703
			//AuDbgInode(h_inode);
704
		}
705
		if (inode && ibs <= bindex && bindex <= ibe)
706
			h_cached_inode = au_h_iptr(inode, bindex);
707
708
		LKTRTrace("{%d, 0%o, %d}, h{%d, 0%o, %d}\n",
709
			  plus, mode, !!h_cached_inode,
710
			  h_plus, h_mode, !!h_inode);
711
		if (unlikely(plus != h_plus
712
			     || mode != h_mode
713
			     || h_cached_inode != h_inode))
714
			goto err;
715
		continue;
716
717
	err:
718
		err = -EINVAL;
719
		break;
720
	}
721
	au_unlock_nd(locked, nd);
722
723
	/*
724
	 * judging by timestamps is meaningless since some filesystem uses
725
	 * CURRENT_TIME_SEC instead of CURRENT_TIME.
726
	 */
727
	/*
728
	 * NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED.
729
	 */
730
731
	AuTraceErr(err);
732
	return err;
733
}
734
735
static noinline_for_stack int
736
simple_reval_dpath(struct dentry *dentry, au_gen_t sgen)
737
{
738
	int err;
739
	mode_t type;
740
	struct dentry *parent;
741
	struct inode *inode;
742
743
	LKTRTrace("%.*s, sgen %d\n", AuDLNPair(dentry), sgen);
744
	SiMustAnyLock(dentry->d_sb);
745
	DiMustWriteLock(dentry);
746
	inode = dentry->d_inode;
747
	AuDebugOn(!inode);
748
749
	if (au_digen(dentry) == sgen && au_iigen(inode) == sgen)
750
		return 0;
751
752
	parent = dget_parent(dentry);
753
	di_read_lock_parent(parent, AuLock_IR);
754
	AuDebugOn(au_digen(parent) != sgen
755
		  || au_iigen(parent->d_inode) != sgen);
756
#ifdef CONFIG_AUFS_DEBUG
757
	{
758
		int i, j;
759
		struct au_dcsub_pages dpages;
760
		struct au_dpage *dpage;
761
		struct dentry **dentries;
762
763
		err = au_dpages_init(&dpages, GFP_TEMPORARY);
764
		AuDebugOn(err);
765
		err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL,
766
					 NULL);
767
		AuDebugOn(err);
768
		for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
769
			dpage = dpages.dpages + i;
770
			dentries = dpage->dentries;
771
			for (j = dpage->ndentry - 1; !err && j >= 0; j--)
772
				AuDebugOn(au_digen(dentries[j]) != sgen);
773
		}
774
		au_dpages_free(&dpages);
775
	}
776
#endif
777
	type = (inode->i_mode & S_IFMT);
778
	/* returns a number of positive dentries */
779
	err = au_refresh_hdentry(dentry, type);
780
	if (err >= 0)
781
		err = au_refresh_hinode(inode, dentry);
782
	di_read_unlock(parent, AuLock_IR);
783
	dput(parent);
784
	AuTraceErr(err);
785
	return err;
786
}
787
788
int au_reval_dpath(struct dentry *dentry, au_gen_t sgen)
789
{
790
	int err;
791
	struct dentry *d, *parent;
792
	struct inode *inode;
793
794
	LKTRTrace("%.*s, sgen %d\n", AuDLNPair(dentry), sgen);
795
	AuDebugOn(!dentry->d_inode);
796
	DiMustWriteLock(dentry);
797
798
	if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
799
		return simple_reval_dpath(dentry, sgen);
800
801
	/* slow loop, keep it simple and stupid */
802
	/* cf: au_cpup_dirs() */
803
	err = 0;
804
	parent = NULL;
805
	while (au_digen(dentry) != sgen || au_iigen(dentry->d_inode) != sgen) {
806
		d = dentry;
807
		while (1) {
808
			dput(parent);
809
			parent = dget_parent(d);
810
			if (au_digen(parent) == sgen
811
			    && au_iigen(parent->d_inode) == sgen)
812
				break;
813
			d = parent;
814
		}
815
816
		inode = d->d_inode;
817
		if (d != dentry) {
818
			//mutex_lock(&inode->i_mutex);
819
			di_write_lock_child(d);
820
		}
821
822
		/* someone might update our dentry while we were sleeping */
823
		if (au_digen(d) != sgen || au_iigen(d->d_inode) != sgen) {
824
			di_read_lock_parent(parent, AuLock_IR);
825
			/* returns a number of positive dentries */
826
			err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
827
			//err = -1;
828
			if (err >= 0)
829
				err = au_refresh_hinode(inode, d);
830
			//err = -1;
831
			di_read_unlock(parent, AuLock_IR);
832
		}
833
834
		if (d != dentry) {
835
			di_write_unlock(d);
836
			//mutex_unlock(&inode->i_mutex);
837
		}
838
		dput(parent);
839
		if (unlikely(err))
840
			break;
841
	}
842
843
	AuTraceErr(err);
844
	return err;
845
}
846
847
/*
848
 * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise.
849
 * nfsd passes NULL as nameidata.
850
 */
851
static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
852
{
853
	int valid, err, do_udba;
854
	struct super_block *sb;
855
	au_gen_t sgen;
856
	struct inode *inode;
857
	struct nameidata tmp_nd, *ndp;
858
859
	LKTRTrace("dentry %.*s\n", AuDLNPair(dentry));
860
	if (nd && nd->path.dentry)
861
		LKTRTrace("nd{%.*s, 0x%x}\n",
862
			  AuDLNPair(nd->path.dentry), nd->flags);
863
	//dir case: AuDebugOn(dentry->d_parent != nd->dentry);
864
	//remove failure case:AuDebugOn(!IS_ROOT(dentry) && d_unhashed(dentry));
865
	AuDebugOn(!dentry->d_fsdata);
866
	//AuDbgDentry(dentry);
867
868
	err = -EINVAL;
869
	inode = dentry->d_inode;
870
	sb = dentry->d_sb;
871
	si_read_lock(sb, AuLock_FLUSH);
872
873
	sgen = au_sigen(sb);
874
	if (au_digen(dentry) == sgen)
875
		di_read_lock_child(dentry, !AuLock_IR);
876
	else {
877
		AuDebugOn(IS_ROOT(dentry));
878
#ifdef ForceInotify
879
		AuDbg("UDBA or digen, %.*s\n", AuDLNPair(dentry));
880
#endif
881
		di_write_lock_child(dentry);
882
		if (inode)
883
			err = au_reval_dpath(dentry, sgen);
884
		//err = -1;
885
		di_downgrade_lock(dentry, AuLock_IR);
886
		if (unlikely(err))
887
			goto out;
888
		if (inode)
889
			ii_read_unlock(inode);
890
		AuDebugOn(au_digen(dentry) != sgen);
891
	}
892
893
	if (inode) {
894
		if (au_iigen(inode) == sgen)
895
			ii_read_lock_child(inode);
896
		else {
897
			AuDebugOn(IS_ROOT(dentry));
898
#ifdef ForceInotify
899
			AuDbg("UDBA or survived, %.*s\n", AuDLNPair(dentry));
900
			//au_debug_on();
901
			//AuDbgInode(inode);
902
			//au_debug_off();
903
#endif
904
			ii_write_lock_child(inode);
905
			err = au_refresh_hinode(inode, dentry);
906
			ii_downgrade_lock(inode);
907
			if (unlikely(err))
908
				goto out;
909
			AuDebugOn(au_iigen(inode) != sgen);
910
		}
911
	}
912
913
	AuDebugOn(au_digen(dentry) != sgen);
914
	AuDebugOn(inode && au_iigen(inode) != sgen);
915
	err = -EINVAL;
916
	do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
917
	if (do_udba && inode) {
918
		aufs_bindex_t bstart = au_ibstart(inode);
919
		if (bstart >= 0
920
		    && au_test_higen(inode, au_h_iptr(inode, bstart)))
921
			goto out;
922
	}
923
	ndp = au_dup_nd(au_sbi(sb), &tmp_nd, nd);
924
	err = h_d_revalidate(dentry, inode, ndp, do_udba);
925
	//err = -1;
926
927
 out:
928
	au_store_fmode_exec(nd, inode);
929
930
	if (inode)
931
		ii_read_unlock(inode);
932
	di_read_unlock(dentry, !AuLock_IR);
933
	si_read_unlock(sb);
934
	AuTraceErr(err);
935
	valid = !err;
936
	if (!valid)
937
		LKTRTrace("%.*s invalid\n", AuDLNPair(dentry));
938
	return valid;
939
}
940
941
static void aufs_d_release(struct dentry *dentry)
942
{
943
	struct au_dinfo *dinfo;
944
	aufs_bindex_t bend, bindex;
945
946
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
947
	AuDebugOn(!d_unhashed(dentry));
948
949
	dinfo = dentry->d_fsdata;
950
	if (unlikely(!dinfo))
951
		return;
952
953
	/* dentry may not be revalidated */
954
	bindex = dinfo->di_bstart;
955
	if (bindex >= 0) {
956
		struct au_hdentry *p;
957
		bend = dinfo->di_bend;
958
		AuDebugOn(bend < bindex);
959
		p = dinfo->di_hdentry + bindex;
960
		while (bindex++ <= bend) {
961
			if (p->hd_dentry)
962
				au_hdput(p, /*do_free*/1);
963
			p++;
964
		}
965
	}
966
	kfree(dinfo->di_hdentry);
967
	au_cache_free_dinfo(dinfo);
968
}
969
970
struct dentry_operations aufs_dop = {
971
	.d_revalidate	= aufs_d_revalidate,
972
	.d_release	= aufs_d_release,
973
	/* never use d_delete, especially in case of nfs server */
974
	//.d_delete	= aufs_d_delete
975
	//.d_iput		= aufs_d_iput
976
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dentry.h (+381 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * lookup and dentry operations
21
 *
22
 * $Id: dentry.h,v 1.4 2008/05/04 23:54:53 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_DENTRY_H__
26
#define __AUFS_DENTRY_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/namei.h>
32
#include <linux/aufs_type.h>
33
#include "misc.h"
34
#include "super.h"
35
#include "vfsub.h"
36
37
/* nameidata open_intent */
38
enum {
39
	AuIntent_AUFS,
40
	AuIntent_BRANCH,
41
	AuIntent_Last
42
};
43
44
struct au_hdintent {
45
	struct list_head	hdi_list;
46
	struct file		*hdi_file[AuIntent_Last];
47
};
48
49
struct au_hdentry {
50
	struct dentry		*hd_dentry;
51
52
#ifdef CONFIG_AUFS_BR_NFS
53
	spinlock_t		hd_lock; /* intest_list */
54
	struct list_head	*hd_intent_list;
55
#endif
56
};
57
58
struct au_dinfo {
59
	atomic_t		di_generation;
60
61
	struct au_rwsem		di_rwsem;
62
	aufs_bindex_t		di_bstart, di_bend, di_bwh, di_bdiropq;
63
	struct au_hdentry	*di_hdentry;
64
};
65
66
/* nameidata extension flags */
67
#define AuNdx_DLGT	1
68
#define AuNdx_DIRPERM1	(1 << 1)
69
#define au_ftest_ndx(flags, name)	((flags) & AuNdx_##name)
70
#define au_fset_ndx(flags, name)	{ (flags) |= AuNdx_##name; }
71
#define au_fclr_ndx(flags, name)	{ (flags) &= ~AuNdx_##name; }
72
#ifndef CONFIG_AUFS_DLGT
73
#undef AuNdx_DLGT
74
#define AuNdx_DLGT	0
75
#undef AuNdx_DIRPERM1
76
#define AuNdx_DIRPERM1	0
77
#endif
78
79
struct au_ndx {
80
	struct vfsmount *nfsmnt;
81
	unsigned int flags;
82
	struct nameidata *nd;
83
	struct au_branch *br;
84
	struct file *nd_file;
85
};
86
87
/* ---------------------------------------------------------------------- */
88
89
static inline void au_do_h_dentry_init(struct au_hdentry *hdentry)
90
{
91
	hdentry->hd_dentry = NULL;
92
}
93
94
#ifdef CONFIG_AUFS_BR_NFS
95
static inline void au_h_dentry_init(struct au_hdentry *hdentry)
96
{
97
	au_do_h_dentry_init(hdentry);
98
	spin_lock_init(&hdentry->hd_lock);
99
}
100
101
static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n)
102
{
103
	while (n--)
104
		spin_lock_init(&hdentry[n].hd_lock);
105
}
106
107
/* br_nfs.c */
108
struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
109
			 struct file *file);
110
int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
111
		       aufs_bindex_t bindex, struct nameidata *nd);
112
void au_hintent_put(struct au_hdentry *hd, int do_free);
113
int au_fake_intent(struct nameidata *nd, int perm);
114
int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
115
		       aufs_bindex_t bindex, struct file *file);
116
struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len,
117
			    struct au_ndx *ndx);
118
#else
119
120
static inline void au_h_dentry_init(struct au_hdentry *hdentry)
121
{
122
	au_do_h_dentry_init(hdentry);
123
}
124
125
static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n)
126
{
127
	/* nothing */
128
}
129
130
static inline
131
struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
132
			 struct file *file)
133
{
134
	//return ERR_PTR(-ENOSYS);
135
	return NULL;
136
}
137
138
static inline
139
int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
140
		       aufs_bindex_t bindex, struct nameidata *nd)
141
{
142
	return 0;
143
}
144
145
static inline void au_hintent_put(struct au_hdentry *hd, int do_free)
146
{
147
	/* empty */
148
}
149
150
static inline int au_fake_intent(struct nameidata *nd, int perm)
151
{
152
	return 0;
153
}
154
155
static inline
156
int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
157
		       aufs_bindex_t bindex, struct file *file)
158
{
159
	return 0;
160
}
161
162
#ifdef CONFIG_AUFS_DLGT
163
static inline
164
struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len,
165
			    struct au_ndx *ndx)
166
{
167
	//return ERR_PTR(-ENOSYS);
168
	return vfsub_lookup_one_len(name, parent, len);
169
}
170
#endif
171
#endif /* CONFIG_AUFS_BR_NFS */
172
173
#ifdef CONFIG_AUFS_DLGT
174
/* dlgt.c */
175
struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
176
				int len, unsigned int flags);
177
#elif defined(CONFIG_AUFS_BR_NFS)
178
/* regardelss kernel version */
179
static inline
180
struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
181
				int len, unsigned int flags)
182
{
183
	return vfsub_lookup_one_len(name, parent, len);
184
}
185
#endif
186
187
/* dentry.c */
188
extern struct dentry_operations aufs_dop;
189
#if defined(CONFIG_AUFS_BR_NFS) || defined(CONFIG_AUFS_DLGT)
190
struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
191
			   struct au_ndx *ndx);
192
#else
193
static inline
194
struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
195
			   struct au_ndx *ndx)
196
{
197
	//todo: ndx->nd_file = NULL;
198
	return vfsub_lookup_one_len(name, parent, len);
199
}
200
#endif
201
struct dentry *au_sio_lkup_one(const char *name, struct dentry *parent, int len,
202
			       struct au_ndx *ndx);
203
int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
204
		   struct nameidata *nd);
205
int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
206
int au_refresh_hdentry(struct dentry *dentry, mode_t type);
207
int au_reval_dpath(struct dentry *dentry, au_gen_t sgen);
208
209
/* dinfo.c */
210
int au_alloc_dinfo(struct dentry *dentry);
211
struct au_dinfo *au_di(struct dentry *dentry);
212
213
void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
214
void di_read_unlock(struct dentry *d, int flags);
215
void di_downgrade_lock(struct dentry *d, int flags);
216
void di_write_lock(struct dentry *d, unsigned int lsc);
217
void di_write_unlock(struct dentry *d);
218
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
219
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
220
void di_write_unlock2(struct dentry *d1, struct dentry *d2);
221
222
struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
223
224
aufs_bindex_t au_dbtail(struct dentry *dentry);
225
aufs_bindex_t au_dbtaildir(struct dentry *dentry);
226
227
void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex);
228
void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
229
		   struct dentry *h_dentry);
230
231
void au_update_dbrange(struct dentry *dentry, int do_put_zero);
232
void au_update_dbstart(struct dentry *dentry);
233
void au_update_dbend(struct dentry *dentry);
234
int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
235
236
/* ---------------------------------------------------------------------- */
237
238
//todo: memory barrier?
239
static inline au_gen_t au_digen(struct dentry *d)
240
{
241
	return atomic_read(&au_di(d)->di_generation);
242
}
243
244
#ifdef CONFIG_AUFS_HINOTIFY
245
static inline au_gen_t au_digen_dec(struct dentry *d)
246
{
247
	return atomic_dec_return(&au_di(d)->di_generation);
248
}
249
#endif /* CONFIG_AUFS_HINOTIFY */
250
251
/* ---------------------------------------------------------------------- */
252
253
/* lock subclass for dinfo */
254
enum {
255
	AuLsc_DI_CHILD,		/* child first */
256
	AuLsc_DI_CHILD2,	/* rename(2), link(2), and cpup at hinotify */
257
	AuLsc_DI_CHILD3,	/* copyup dirs */
258
	AuLsc_DI_PARENT,
259
	AuLsc_DI_PARENT2,
260
	AuLsc_DI_PARENT3
261
};
262
263
/*
264
 * di_read_lock_child, di_write_lock_child,
265
 * di_read_lock_child2, di_write_lock_child2,
266
 * di_read_lock_child3, di_write_lock_child3,
267
 * di_read_lock_parent, di_write_lock_parent,
268
 * di_read_lock_parent2, di_write_lock_parent2,
269
 * di_read_lock_parent3, di_write_lock_parent3,
270
 */
271
#define AuReadLockFunc(name, lsc) \
272
static inline void di_read_lock_##name(struct dentry *d, int flags) \
273
{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
274
275
#define AuWriteLockFunc(name, lsc) \
276
static inline void di_write_lock_##name(struct dentry *d) \
277
{ di_write_lock(d, AuLsc_DI_##lsc); }
278
279
#define AuRWLockFuncs(name, lsc) \
280
	AuReadLockFunc(name, lsc) \
281
	AuWriteLockFunc(name, lsc)
282
283
AuRWLockFuncs(child, CHILD);
284
AuRWLockFuncs(child2, CHILD2);
285
AuRWLockFuncs(child3, CHILD3);
286
AuRWLockFuncs(parent, PARENT);
287
AuRWLockFuncs(parent2, PARENT2);
288
AuRWLockFuncs(parent3, PARENT3);
289
290
#undef AuReadLockFunc
291
#undef AuWriteLockFunc
292
#undef AuRWLockFuncs
293
294
/* to debug easier, do not make them inlined functions */
295
#define DiMustReadLock(d) do { \
296
	SiMustAnyLock((d)->d_sb); \
297
	AuRwMustReadLock(&au_di(d)->di_rwsem); \
298
} while (0)
299
300
#define DiMustWriteLock(d) do { \
301
	SiMustAnyLock((d)->d_sb); \
302
	AuRwMustWriteLock(&au_di(d)->di_rwsem); \
303
} while (0)
304
305
#define DiMustAnyLock(d) do { \
306
	SiMustAnyLock((d)->d_sb); \
307
	AuRwMustAnyLock(&au_di(d)->di_rwsem); \
308
} while (0)
309
310
#define DiMustNoWaiters(d)	AuRwMustNoWaiters(&au_di(d)->di_rwsem)
311
312
/* ---------------------------------------------------------------------- */
313
314
static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
315
{
316
	DiMustAnyLock(dentry);
317
	return au_di(dentry)->di_bstart;
318
}
319
320
static inline aufs_bindex_t au_dbend(struct dentry *dentry)
321
{
322
	DiMustAnyLock(dentry);
323
	return au_di(dentry)->di_bend;
324
}
325
326
static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
327
{
328
	DiMustAnyLock(dentry);
329
	return au_di(dentry)->di_bwh;
330
}
331
332
static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
333
{
334
	DiMustAnyLock(dentry);
335
	AuDebugOn(dentry->d_inode
336
		  && dentry->d_inode->i_mode
337
		  && !S_ISDIR(dentry->d_inode->i_mode));
338
	return au_di(dentry)->di_bdiropq;
339
}
340
341
// hard/soft set
342
static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
343
{
344
	DiMustWriteLock(dentry);
345
	AuDebugOn(au_sbend(dentry->d_sb) < bindex);
346
	/* */
347
	au_di(dentry)->di_bstart = bindex;
348
}
349
350
static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
351
{
352
	DiMustWriteLock(dentry);
353
	AuDebugOn(au_sbend(dentry->d_sb) < bindex
354
		  || bindex < au_dbstart(dentry));
355
	au_di(dentry)->di_bend = bindex;
356
}
357
358
static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
359
{
360
	DiMustWriteLock(dentry);
361
	AuDebugOn(au_sbend(dentry->d_sb) < bindex);
362
	/* dbwh can be outside of bstart - bend range */
363
	au_di(dentry)->di_bwh = bindex;
364
}
365
366
static inline void au_hdput(struct au_hdentry *hd, int do_free)
367
{
368
	au_hintent_put(hd, do_free);
369
	dput(hd->hd_dentry);
370
}
371
372
static inline void au_update_digen(struct dentry *dentry)
373
{
374
	//DiMustWriteLock(dentry);
375
	AuDebugOn(!dentry->d_sb);
376
	atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
377
	//smp_mb(); /* atomic_set */
378
}
379
380
#endif /* __KERNEL__ */
381
#endif /* __AUFS_DENTRY_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dinfo.c (+412 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * dentry private data
21
 *
22
 * $Id: dinfo.c,v 1.3 2008/04/28 03:04:23 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
int au_alloc_dinfo(struct dentry *dentry)
28
{
29
	struct au_dinfo *dinfo;
30
	struct super_block *sb;
31
	int nbr;
32
33
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
34
	AuDebugOn(dentry->d_fsdata);
35
36
	dinfo = au_cache_alloc_dinfo();
37
	//if (LktrCond) {au_cache_free_dinfo(dinfo); dinfo = NULL;}
38
	if (dinfo) {
39
		sb = dentry->d_sb;
40
		nbr = au_sbend(sb) + 1;
41
		if (unlikely(nbr <= 0))
42
			nbr = 1;
43
		dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
44
					    GFP_KERNEL);
45
		//if (LktrCond)
46
		//{kfree(dinfo->di_hdentry); dinfo->di_hdentry = NULL;}
47
		if (dinfo->di_hdentry) {
48
			au_h_dentry_init_all(dinfo->di_hdentry, nbr);
49
			atomic_set(&dinfo->di_generation, au_sigen(sb));
50
			//smp_mb(); /* atomic_set */
51
			au_rw_init_wlock_nested(&dinfo->di_rwsem,
52
						AuLsc_DI_PARENT);
53
			dinfo->di_bstart = -1;
54
			dinfo->di_bend = -1;
55
			dinfo->di_bwh = -1;
56
			dinfo->di_bdiropq = -1;
57
58
			dentry->d_fsdata = dinfo;
59
			dentry->d_op = &aufs_dop;
60
			return 0; /* success */
61
		}
62
		au_cache_free_dinfo(dinfo);
63
	}
64
	AuTraceErr(-ENOMEM);
65
	return -ENOMEM;
66
}
67
68
struct au_dinfo *au_di(struct dentry *dentry)
69
{
70
	struct au_dinfo *dinfo = dentry->d_fsdata;
71
	AuDebugOn(!dinfo
72
		 || !dinfo->di_hdentry
73
		 /* || au_sbi(dentry->d_sb)->si_bend < dinfo->di_bend */
74
		 || dinfo->di_bend < dinfo->di_bstart
75
		 /* dbwh can be outside of this range */
76
		 || (0 <= dinfo->di_bdiropq
77
		     && (dinfo->di_bdiropq < dinfo->di_bstart
78
			 /* || dinfo->di_bend < dinfo->di_bdiropq */))
79
		);
80
	return dinfo;
81
}
82
83
/* ---------------------------------------------------------------------- */
84
85
static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
86
{
87
	switch (lsc) {
88
	case AuLsc_DI_CHILD:
89
		ii_write_lock_child(inode);
90
		break;
91
	case AuLsc_DI_CHILD2:
92
		ii_write_lock_child2(inode);
93
		break;
94
	case AuLsc_DI_CHILD3:
95
		ii_write_lock_child3(inode);
96
		break;
97
	case AuLsc_DI_PARENT:
98
		//AuDebugOn(!S_ISDIR(inode->i_mode));
99
		ii_write_lock_parent(inode);
100
		break;
101
	case AuLsc_DI_PARENT2:
102
		//AuDebugOn(!S_ISDIR(inode->i_mode));
103
		ii_write_lock_parent2(inode);
104
		break;
105
	case AuLsc_DI_PARENT3:
106
		//AuDebugOn(!S_ISDIR(inode->i_mode));
107
		ii_write_lock_parent3(inode);
108
		break;
109
	default:
110
		BUG();
111
	}
112
}
113
114
static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
115
{
116
	switch (lsc) {
117
	case AuLsc_DI_CHILD:
118
		ii_read_lock_child(inode);
119
		break;
120
	case AuLsc_DI_CHILD2:
121
		ii_read_lock_child2(inode);
122
		break;
123
	case AuLsc_DI_CHILD3:
124
		ii_read_lock_child3(inode);
125
		break;
126
	case AuLsc_DI_PARENT:
127
		//AuDebugOn(!S_ISDIR(inode->i_mode));
128
		ii_read_lock_parent(inode);
129
		break;
130
	case AuLsc_DI_PARENT2:
131
		//AuDebugOn(!S_ISDIR(inode->i_mode));
132
		ii_read_lock_parent2(inode);
133
		break;
134
	case AuLsc_DI_PARENT3:
135
		//AuDebugOn(!S_ISDIR(inode->i_mode));
136
		ii_read_lock_parent3(inode);
137
		break;
138
	default:
139
		BUG();
140
	}
141
}
142
143
void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
144
{
145
	SiMustAnyLock(d->d_sb);
146
	// todo: always nested?
147
	au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
148
	if (d->d_inode) {
149
		if (au_ftest_lock(flags, IW))
150
			do_ii_write_lock(d->d_inode, lsc);
151
		else if (au_ftest_lock(flags, IR))
152
			do_ii_read_lock(d->d_inode, lsc);
153
	}
154
}
155
156
void di_read_unlock(struct dentry *d, int flags)
157
{
158
	SiMustAnyLock(d->d_sb);
159
	if (d->d_inode) {
160
		if (au_ftest_lock(flags, IW))
161
			ii_write_unlock(d->d_inode);
162
		else if (au_ftest_lock(flags, IR))
163
			ii_read_unlock(d->d_inode);
164
	}
165
	au_rw_read_unlock(&au_di(d)->di_rwsem);
166
}
167
168
void di_downgrade_lock(struct dentry *d, int flags)
169
{
170
	SiMustAnyLock(d->d_sb);
171
	au_rw_dgrade_lock(&au_di(d)->di_rwsem);
172
	if (d->d_inode && au_ftest_lock(flags, IR))
173
		ii_downgrade_lock(d->d_inode);
174
}
175
176
void di_write_lock(struct dentry *d, unsigned int lsc)
177
{
178
	SiMustAnyLock(d->d_sb);
179
	// todo: always nested?
180
	au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
181
	if (d->d_inode)
182
		do_ii_write_lock(d->d_inode, lsc);
183
}
184
185
void di_write_unlock(struct dentry *d)
186
{
187
	SiMustAnyLock(d->d_sb);
188
	if (d->d_inode)
189
		ii_write_unlock(d->d_inode);
190
	au_rw_write_unlock(&au_di(d)->di_rwsem);
191
}
192
193
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
194
{
195
	AuTraceEnter();
196
	AuDebugOn(d1 == d2
197
		  || d1->d_inode == d2->d_inode
198
		  || d1->d_sb != d2->d_sb);
199
200
	if (isdir && au_test_subdir(d1, d2)) {
201
		di_write_lock_child(d1);
202
		di_write_lock_child2(d2);
203
	} else {
204
		/* there should be no races */
205
		di_write_lock_child(d2);
206
		di_write_lock_child2(d1);
207
	}
208
}
209
210
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
211
{
212
	AuTraceEnter();
213
	AuDebugOn(d1 == d2
214
		  || d1->d_inode == d2->d_inode
215
		  || d1->d_sb != d2->d_sb);
216
217
	if (isdir && au_test_subdir(d1, d2)) {
218
		di_write_lock_parent(d1);
219
		di_write_lock_parent2(d2);
220
	} else {
221
		/* there should be no races */
222
		di_write_lock_parent(d2);
223
		di_write_lock_parent2(d1);
224
	}
225
}
226
227
void di_write_unlock2(struct dentry *d1, struct dentry *d2)
228
{
229
	di_write_unlock(d1);
230
	if (d1->d_inode == d2->d_inode)
231
		au_rw_write_unlock(&au_di(d2)->di_rwsem);
232
	else
233
		di_write_unlock(d2);
234
}
235
236
/* ---------------------------------------------------------------------- */
237
238
struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
239
{
240
	struct dentry *d;
241
242
	DiMustAnyLock(dentry);
243
	if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
244
		return NULL;
245
	AuDebugOn(bindex < 0
246
		  /* || bindex > au_sbend(dentry->d_sb) */);
247
	d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
248
	AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
249
	return d;
250
}
251
252
aufs_bindex_t au_dbtail(struct dentry *dentry)
253
{
254
	aufs_bindex_t bend, bwh;
255
256
	bend = au_dbend(dentry);
257
	if (0 <= bend) {
258
		bwh = au_dbwh(dentry);
259
		//AuDebugOn(bend < bwh);
260
		if (!bwh)
261
			return bwh;
262
		if (0 < bwh && bwh < bend)
263
			return bwh - 1;
264
	}
265
	return bend;
266
}
267
268
aufs_bindex_t au_dbtaildir(struct dentry *dentry)
269
{
270
	aufs_bindex_t bend, bopq;
271
272
	AuDebugOn(dentry->d_inode
273
		  && dentry->d_inode->i_mode
274
		  && !S_ISDIR(dentry->d_inode->i_mode));
275
276
	bend = au_dbtail(dentry);
277
	if (0 <= bend) {
278
		bopq = au_dbdiropq(dentry);
279
		AuDebugOn(bend < bopq);
280
		if (0 <= bopq && bopq < bend)
281
			bend = bopq;
282
	}
283
	return bend;
284
}
285
286
/* ---------------------------------------------------------------------- */
287
288
void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
289
{
290
	DiMustWriteLock(dentry);
291
	AuDebugOn(au_sbend(dentry->d_sb) < bindex);
292
	AuDebugOn((bindex >= 0
293
		   && (bindex < au_dbstart(dentry)
294
		       || au_dbend(dentry) < bindex))
295
		  || (dentry->d_inode
296
		      && dentry->d_inode->i_mode
297
		      && !S_ISDIR(dentry->d_inode->i_mode)));
298
	au_di(dentry)->di_bdiropq = bindex;
299
}
300
301
void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
302
		   struct dentry *h_dentry)
303
{
304
	struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
305
	DiMustWriteLock(dentry);
306
	AuDebugOn(bindex < au_di(dentry)->di_bstart
307
		  || bindex > au_di(dentry)->di_bend
308
		  || (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
309
		  || (h_dentry && hd->hd_dentry)
310
		);
311
	if (hd->hd_dentry)
312
		au_hdput(hd, /*do_free*/0);
313
	hd->hd_dentry = h_dentry;
314
}
315
316
/* ---------------------------------------------------------------------- */
317
318
void au_update_dbrange(struct dentry *dentry, int do_put_zero)
319
{
320
	struct au_dinfo *dinfo;
321
	aufs_bindex_t bindex;
322
	struct dentry *h_d;
323
324
	LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), do_put_zero);
325
	DiMustWriteLock(dentry);
326
327
	dinfo = au_di(dentry);
328
	if (unlikely(!dinfo) || dinfo->di_bstart < 0)
329
		return;
330
331
	if (do_put_zero) {
332
		for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend;
333
		     bindex++) {
334
			h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
335
			if (h_d && !h_d->d_inode)
336
				au_set_h_dptr(dentry, bindex, NULL);
337
		}
338
	}
339
340
	dinfo->di_bstart = -1;
341
	while (++dinfo->di_bstart <= dinfo->di_bend)
342
		if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
343
			break;
344
	if (dinfo->di_bstart > dinfo->di_bend) {
345
		dinfo->di_bstart = -1;
346
		dinfo->di_bend = -1;
347
		return;
348
	}
349
350
	dinfo->di_bend++;
351
	while (0 <= --dinfo->di_bend)
352
		if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
353
			break;
354
	AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
355
}
356
357
void au_update_dbstart(struct dentry *dentry)
358
{
359
	aufs_bindex_t bindex,
360
		bstart = au_dbstart(dentry),
361
		bend = au_dbend(dentry);
362
	struct dentry *h_dentry;
363
364
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
365
	DiMustWriteLock(dentry);
366
367
	for (bindex = bstart; bindex <= bend; bindex++) {
368
		h_dentry = au_h_dptr(dentry, bindex);
369
		if (!h_dentry)
370
			continue;
371
		if (h_dentry->d_inode) {
372
			au_set_dbstart(dentry, bindex);
373
			return;
374
		}
375
		au_set_h_dptr(dentry, bindex, NULL);
376
	}
377
	//au_set_dbstart(dentry, -1);
378
	//au_set_dbend(dentry, -1);
379
}
380
381
void au_update_dbend(struct dentry *dentry)
382
{
383
	aufs_bindex_t bindex,
384
		bstart = au_dbstart(dentry),
385
		bend = au_dbend(dentry);
386
	struct dentry *h_dentry;
387
388
	DiMustWriteLock(dentry);
389
	for (bindex = bend; bindex <= bstart; bindex--) {
390
		h_dentry = au_h_dptr(dentry, bindex);
391
		if (!h_dentry)
392
			continue;
393
		if (h_dentry->d_inode) {
394
			au_set_dbend(dentry, bindex);
395
			return;
396
		}
397
		au_set_h_dptr(dentry, bindex, NULL);
398
	}
399
	//au_set_dbstart(dentry, -1);
400
	//au_set_dbend(dentry, -1);
401
}
402
403
int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
404
{
405
	aufs_bindex_t bindex, bend;
406
407
	bend = au_dbend(dentry);
408
	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
409
		if (au_h_dptr(dentry, bindex) == h_dentry)
410
			return bindex;
411
	return -1;
412
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dir.c (+553 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * directory operations
21
 *
22
 * $Id: dir.c,v 1.4 2008/05/12 00:27:58 sfjro Exp $
23
 */
24
25
#include <linux/fs_stack.h>
26
#include "aufs.h"
27
28
static int reopen_dir(struct file *file)
29
{
30
	int err;
31
	struct dentry *dentry, *h_dentry;
32
	aufs_bindex_t bindex, btail, bstart;
33
	struct file *h_file;
34
35
	dentry = file->f_dentry;
36
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
37
	AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
38
39
	/* open all hidden dirs */
40
	bstart = au_dbstart(dentry);
41
	for (bindex = au_fbstart(file); bindex < bstart; bindex++)
42
		au_set_h_fptr(file, bindex, NULL);
43
	au_set_fbstart(file, bstart);
44
	btail = au_dbtaildir(dentry);
45
	for (bindex = au_fbend(file); btail < bindex; bindex--)
46
		au_set_h_fptr(file, bindex, NULL);
47
	au_set_fbend(file, btail);
48
	for (bindex = bstart; bindex <= btail; bindex++) {
49
		h_dentry = au_h_dptr(dentry, bindex);
50
		if (!h_dentry)
51
			continue;
52
		h_file = au_h_fptr(file, bindex);
53
		if (h_file) {
54
			AuDebugOn(h_file->f_dentry != h_dentry);
55
			continue;
56
		}
57
58
		h_file = au_h_open(dentry, bindex, file->f_flags, file);
59
		// unavailable
60
		//if (LktrCond) {fput(h_file);
61
		//au_br_put(au_sbr(dentry->d_sb, bindex));h_file=ERR_PTR(-1);}
62
		err = PTR_ERR(h_file);
63
		if (IS_ERR(h_file))
64
			goto out; // close all?
65
		//cpup_file_flags(h_file, file);
66
		au_set_h_fptr(file, bindex, h_file);
67
	}
68
	au_update_figen(file);
69
	//file->f_ra = h_file->f_ra; //??
70
	err = 0;
71
72
 out:
73
	AuTraceErr(err);
74
	return err;
75
}
76
77
static int do_open_dir(struct file *file, int flags)
78
{
79
	int err;
80
	aufs_bindex_t bindex, btail;
81
	struct dentry *dentry, *h_dentry;
82
	struct file *h_file;
83
84
	dentry = file->f_dentry;
85
	LKTRTrace("%.*s, 0x%x\n", AuDLNPair(dentry), flags);
86
	AuDebugOn(!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode));
87
88
	err = 0;
89
	au_set_fvdir_cache(file, NULL);
90
	file->f_version = dentry->d_inode->i_version;
91
	bindex = au_dbstart(dentry);
92
	au_set_fbstart(file, bindex);
93
	btail = au_dbtaildir(dentry);
94
	au_set_fbend(file, btail);
95
	for (; !err && bindex <= btail; bindex++) {
96
		h_dentry = au_h_dptr(dentry, bindex);
97
		if (!h_dentry)
98
			continue;
99
100
		h_file = au_h_open(dentry, bindex, flags, file);
101
		//if (LktrCond) {fput(h_file);
102
		//au_br_put(au_sbr(dentry->d_sb, bindex));h_file=ERR_PTR(-1);}
103
		if (!IS_ERR(h_file)) {
104
			au_set_h_fptr(file, bindex, h_file);
105
			continue;
106
		}
107
		err = PTR_ERR(h_file);
108
	}
109
	au_update_figen(file);
110
	//file->f_ra = h_file->f_ra; //??
111
	if (!err)
112
		return 0; /* success */
113
114
	/* close all */
115
	for (bindex = au_fbstart(file); !err && bindex <= btail; bindex++)
116
		au_set_h_fptr(file, bindex, NULL);
117
	au_set_fbstart(file, -1);
118
	au_set_fbend(file, -1);
119
	return err;
120
}
121
122
static int aufs_open_dir(struct inode *inode, struct file *file)
123
{
124
	return au_do_open(inode, file, do_open_dir);
125
}
126
127
static int aufs_release_dir(struct inode *inode, struct file *file)
128
{
129
	struct au_vdir *vdir_cache;
130
	struct super_block *sb;
131
132
	LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
133
134
	sb = file->f_dentry->d_sb;
135
	si_noflush_read_lock(sb);
136
	fi_write_lock(file);
137
	vdir_cache = au_fvdir_cache(file);
138
	if (vdir_cache)
139
		au_vdir_free(vdir_cache);
140
	fi_write_unlock(file);
141
	au_finfo_fin(file);
142
	si_read_unlock(sb);
143
	return 0;
144
}
145
146
static int fsync_dir(struct dentry *dentry, int datasync)
147
{
148
	int err;
149
	struct inode *inode;
150
	struct super_block *sb;
151
	aufs_bindex_t bend, bindex;
152
153
	LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync);
154
	DiMustAnyLock(dentry);
155
	sb = dentry->d_sb;
156
	SiMustAnyLock(sb);
157
	inode = dentry->d_inode;
158
	IMustLock(inode);
159
	IiMustAnyLock(inode);
160
161
	err = 0;
162
	bend = au_dbend(dentry);
163
	for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
164
		struct dentry *h_dentry;
165
		struct inode *h_inode;
166
		struct file_operations *fop;
167
168
		if (au_test_ro(sb, bindex, inode))
169
			continue;
170
		h_dentry = au_h_dptr(dentry, bindex);
171
		if (!h_dentry)
172
			continue;
173
		h_inode = h_dentry->d_inode;
174
		if (!h_inode)
175
			continue;
176
177
		/* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
178
		//au_hdir_lock(h_inode, inode, bindex);
179
		mutex_lock(&h_inode->i_mutex);
180
		fop = (void *)h_inode->i_fop;
181
		err = filemap_fdatawrite(h_inode->i_mapping);
182
		if (!err && fop && fop->fsync)
183
			err = fop->fsync(NULL, h_dentry, datasync);
184
		if (!err)
185
			err = filemap_fdatawrite(h_inode->i_mapping);
186
		if (!err)
187
			au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
188
		//au_hdir_unlock(h_inode, inode, bindex);
189
		mutex_unlock(&h_inode->i_mutex);
190
	}
191
192
	AuTraceErr(err);
193
	return err;
194
}
195
196
/*
197
 * @file may be NULL
198
 */
199
static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
200
			  int datasync)
201
{
202
	int err;
203
	struct inode *inode;
204
	struct file *h_file;
205
	struct super_block *sb;
206
	aufs_bindex_t bend, bindex;
207
208
	LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync);
209
	inode = dentry->d_inode;
210
	IMustLock(inode);
211
212
	err = 0;
213
	sb = dentry->d_sb;
214
	si_noflush_read_lock(sb);
215
	if (file) {
216
		err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
217
					      /*locked*/1);
218
		//err = -1;
219
		if (unlikely(err))
220
			goto out;
221
	} else
222
		di_read_lock_child(dentry, !AuLock_IW);
223
224
	ii_write_lock_child(inode);
225
	if (file) {
226
		bend = au_fbend(file);
227
		for (bindex = au_fbstart(file); !err && bindex <= bend;
228
		     bindex++) {
229
			h_file = au_h_fptr(file, bindex);
230
			if (!h_file || au_test_ro(sb, bindex, inode))
231
				continue;
232
233
			err = -EINVAL;
234
			if (h_file->f_op && h_file->f_op->fsync) {
235
				// todo: try do_fsync() in fs/sync.c
236
				mutex_lock(&h_file->f_mapping->host->i_mutex);
237
				err = h_file->f_op->fsync
238
					(h_file, h_file->f_dentry, datasync);
239
				//err = -1;
240
				if (!err)
241
					au_update_fuse_h_inode
242
						(h_file->f_vfsmnt,
243
						 h_file->f_dentry);
244
				/*ignore*/
245
				mutex_unlock(&h_file->f_mapping->host->i_mutex);
246
			}
247
		}
248
	} else
249
		err = fsync_dir(dentry, datasync);
250
	au_cpup_attr_timesizes(inode);
251
	ii_write_unlock(inode);
252
	if (file)
253
		fi_write_unlock(file);
254
	else
255
		di_read_unlock(dentry, !AuLock_IW);
256
257
 out:
258
	si_read_unlock(sb);
259
	AuTraceErr(err);
260
	return err;
261
}
262
263
/* ---------------------------------------------------------------------- */
264
265
static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
266
{
267
	int err;
268
	struct dentry *dentry;
269
	struct inode *inode;
270
	struct super_block *sb;
271
272
	dentry = file->f_dentry;
273
	LKTRTrace("%.*s, pos %Ld\n", AuDLNPair(dentry), file->f_pos);
274
	inode = dentry->d_inode;
275
	IMustLock(inode);
276
277
	au_nfsd_lockdep_off();
278
	sb = dentry->d_sb;
279
	si_read_lock(sb, AuLock_FLUSH);
280
	err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
281
				      /*locked*/1);
282
	if (unlikely(err))
283
		goto out;
284
285
	ii_write_lock_child(inode);
286
	err = au_vdir_init(file);
287
	if (unlikely(err)) {
288
		ii_write_unlock(inode);
289
		goto out_unlock;
290
	}
291
	//DbgVdir(au_fvdir_cache(file));// goto out_unlock;
292
293
	/* nfsd filldir calls lookup_one_len(). */
294
	ii_downgrade_lock(inode);
295
	err = au_vdir_fill_de(file, dirent, filldir);
296
	//DbgVdir(au_fvdir_cache(file));// goto out_unlock;
297
298
	fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
299
	ii_read_unlock(inode);
300
301
 out_unlock:
302
	fi_write_unlock(file);
303
 out:
304
	si_read_unlock(sb);
305
	au_nfsd_lockdep_on();
306
	AuTraceErr(err);
307
	return err;
308
}
309
310
/* ---------------------------------------------------------------------- */
311
312
#define AuTestEmpty_WHONLY	1
313
#define AuTestEmpty_DLGT	(1 << 1)
314
#define AuTestEmpty_DIRPERM1	(1 << 2)
315
#define AuTestEmpty_CALLED	(1 << 3)
316
#define AuTestEmpty_SHWH	(1 << 4)
317
#define au_ftest_testempty(flags, name)	((flags) & AuTestEmpty_##name)
318
#define au_fset_testempty(flags, name)	{ (flags) |= AuTestEmpty_##name; }
319
#define au_fclr_testempty(flags, name)	{ (flags) &= ~AuTestEmpty_##name; }
320
#ifndef CONFIG_AUFS_DLGT
321
#undef AuTestEmpty_DLGT
322
#define AuTestEmpty_DLGT	0
323
#undef AuTestEmpty_DIRPERM1
324
#define AuTestEmpty_DIRPERM1	0
325
#endif
326
#ifndef CONFIG_AUFS_SHWH
327
#undef AuTestEmpty_SHWH
328
#define AuTestEmpty_SHWH	0
329
#endif
330
331
struct test_empty_arg {
332
	struct au_nhash *whlist;
333
	unsigned int flags;
334
	int err;
335
	aufs_bindex_t bindex;
336
};
337
338
static int test_empty_cb(void *__arg, const char *__name, int namelen,
339
			 loff_t offset, u64 ino, unsigned int d_type)
340
{
341
	struct test_empty_arg *arg = __arg;
342
	char *name = (void *)__name;
343
344
	LKTRTrace("%.*s\n", namelen, name);
345
346
	arg->err = 0;
347
	au_fset_testempty(arg->flags, CALLED);
348
	//smp_mb();
349
	if (name[0] == '.'
350
	    && (namelen == 1 || (name[1] == '.' && namelen == 2)))
351
		return 0; /* success */
352
353
	if (namelen <= AUFS_WH_PFX_LEN
354
	    || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
355
		if (au_ftest_testempty(arg->flags, WHONLY)
356
		    && !au_nhash_test_known_wh(arg->whlist, name, namelen))
357
			arg->err = -ENOTEMPTY;
358
		goto out;
359
	}
360
361
	name += AUFS_WH_PFX_LEN;
362
	namelen -= AUFS_WH_PFX_LEN;
363
	if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
364
		arg->err = au_nhash_append_wh
365
			(arg->whlist, name, namelen, ino, d_type, arg->bindex,
366
			 au_ftest_testempty(arg->flags, SHWH));
367
368
 out:
369
	//smp_mb();
370
	AuTraceErr(arg->err);
371
	return arg->err;
372
}
373
374
static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
375
{
376
	int err, dlgt;
377
	struct file *h_file;
378
379
	LKTRTrace("%.*s, {%p, 0x%x, %d}\n",
380
		  AuDLNPair(dentry), arg->whlist, arg->flags, arg->bindex);
381
382
	h_file = au_h_open(dentry, arg->bindex,
383
			   O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
384
			   /*file*/NULL);
385
	err = PTR_ERR(h_file);
386
	if (IS_ERR(h_file))
387
		goto out;
388
	err = 0;
389
	if (unlikely(au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY)
390
		     && !h_file->f_dentry->d_inode->i_nlink))
391
		goto out_put;
392
393
	dlgt = au_ftest_testempty(arg->flags, DLGT);
394
	//h_file->f_pos = 0;
395
	do {
396
		arg->err = 0;
397
		au_fclr_testempty(arg->flags, CALLED);
398
		//smp_mb();
399
		err = vfsub_readdir(h_file, test_empty_cb, arg, dlgt);
400
		if (err >= 0)
401
			err = arg->err;
402
	} while (!err && au_ftest_testempty(arg->flags, CALLED));
403
404
 out_put:
405
	fput(h_file);
406
	au_sbr_put(dentry->d_sb, arg->bindex);
407
 out:
408
	AuTraceErr(err);
409
	return err;
410
}
411
412
struct do_test_empty_args {
413
	int *errp;
414
	struct dentry *dentry;
415
	struct test_empty_arg *arg;
416
};
417
418
static void call_do_test_empty(void *args)
419
{
420
	struct do_test_empty_args *a = args;
421
	*a->errp = do_test_empty(a->dentry, a->arg);
422
}
423
424
static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
425
{
426
	int err, wkq_err;
427
	struct dentry *h_dentry;
428
	struct inode *h_inode;
429
430
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
431
	h_dentry = au_h_dptr(dentry, arg->bindex);
432
	AuDebugOn(!h_dentry);
433
	h_inode = h_dentry->d_inode;
434
	AuDebugOn(!h_inode || !S_ISDIR(h_inode->i_mode));
435
436
	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
437
	err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ,
438
				 au_opt_test_dlgt(au_mntflags(dentry->d_sb)));
439
	mutex_unlock(&h_inode->i_mutex);
440
	if (!err)
441
		err = do_test_empty(dentry, arg);
442
	else {
443
		struct do_test_empty_args args = {
444
			.errp	= &err,
445
			.dentry	= dentry,
446
			.arg	= arg
447
		};
448
		unsigned int flags = arg->flags;
449
		au_fclr_testempty(arg->flags, DLGT);
450
		au_fclr_testempty(arg->flags, DIRPERM1);
451
		wkq_err = au_wkq_wait(call_do_test_empty, &args, /*dlgt*/0);
452
		if (unlikely(wkq_err))
453
			err = wkq_err;
454
		arg->flags = flags;
455
	}
456
457
	AuTraceErr(err);
458
	return err;
459
}
460
461
int au_test_empty_lower(struct dentry *dentry)
462
{
463
	int err;
464
	struct inode *inode;
465
	struct test_empty_arg arg;
466
	struct au_nhash *whlist;
467
	aufs_bindex_t bindex, bstart, btail;
468
	unsigned int mnt_flags;
469
470
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
471
	inode = dentry->d_inode;
472
	AuDebugOn(!inode || !S_ISDIR(inode->i_mode));
473
474
	whlist = au_nhash_new(GFP_TEMPORARY);
475
	err = PTR_ERR(whlist);
476
	if (IS_ERR(whlist))
477
		goto out;
478
479
	bstart = au_dbstart(dentry);
480
	mnt_flags = au_mntflags(dentry->d_sb);
481
	arg.whlist = whlist;
482
	arg.flags = 0;
483
	if (unlikely(au_opt_test_dlgt(mnt_flags)))
484
		au_fset_testempty(arg.flags, DLGT);
485
	if (unlikely(au_opt_test(mnt_flags, SHWH)))
486
		au_fset_testempty(arg.flags, SHWH);
487
	arg.bindex = bstart;
488
	err = do_test_empty(dentry, &arg);
489
	if (unlikely(err))
490
		goto out_whlist;
491
492
	au_fset_testempty(arg.flags, WHONLY);
493
	if (unlikely(au_opt_test_dirperm1(mnt_flags)))
494
		au_fset_testempty(arg.flags, DIRPERM1);
495
	btail = au_dbtaildir(dentry);
496
	for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
497
		struct dentry *h_dentry;
498
		h_dentry = au_h_dptr(dentry, bindex);
499
		if (h_dentry && h_dentry->d_inode) {
500
			AuDebugOn(!S_ISDIR(h_dentry->d_inode->i_mode));
501
			arg.bindex = bindex;
502
			err = do_test_empty(dentry, &arg);
503
		}
504
	}
505
506
 out_whlist:
507
	au_nhash_del(whlist);
508
 out:
509
	AuTraceErr(err);
510
	return err;
511
}
512
513
int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
514
{
515
	int err;
516
	struct inode *inode;
517
	struct test_empty_arg arg;
518
	aufs_bindex_t bindex, btail;
519
520
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
521
	inode = dentry->d_inode;
522
	AuDebugOn(!inode || !S_ISDIR(inode->i_mode));
523
524
	err = 0;
525
	arg.whlist = whlist;
526
	arg.flags = AuTestEmpty_WHONLY;
527
	if (unlikely(au_opt_test(au_mntflags(dentry->d_sb), SHWH)))
528
		au_fset_testempty(arg.flags, SHWH);
529
	btail = au_dbtaildir(dentry);
530
	for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
531
		struct dentry *h_dentry;
532
		h_dentry = au_h_dptr(dentry, bindex);
533
		if (h_dentry && h_dentry->d_inode) {
534
			AuDebugOn(!S_ISDIR(h_dentry->d_inode->i_mode));
535
			arg.bindex = bindex;
536
			err = sio_test_empty(dentry, &arg);
537
		}
538
	}
539
540
	AuTraceErr(err);
541
	return err;
542
}
543
544
/* ---------------------------------------------------------------------- */
545
546
struct file_operations aufs_dir_fop = {
547
	.read		= generic_read_dir,
548
	.readdir	= aufs_readdir,
549
	.open		= aufs_open_dir,
550
	.release	= aufs_release_dir,
551
	.flush		= aufs_flush,
552
	.fsync		= aufs_fsync_dir,
553
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dir.h (+146 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * directory operations
21
 *
22
 * $Id: dir.h,v 1.2 2008/04/21 01:34:26 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_DIR_H__
26
#define __AUFS_DIR_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/aufs_type.h>
32
33
/* ---------------------------------------------------------------------- */
34
35
/* need to be faster and smaller */
36
37
#define AuSize_DEBLK	512 // todo: changeable
38
#define AuSize_NHASH	32 // todo: changeable
39
#if AuSize_DEBLK < NAME_MAX || PAGE_SIZE < AuSize_DEBLK
40
#error invalid size AuSize_DEBLK
41
#endif
42
43
typedef char au_vdir_deblk_t[AuSize_DEBLK];
44
45
struct au_nhash {
46
	struct hlist_head heads[AuSize_NHASH];
47
};
48
49
struct au_vdir_destr {
50
	unsigned char	len;
51
	char		name[0];
52
} __packed;
53
54
struct au_vdir_dehstr {
55
	struct hlist_node	hash;
56
	struct au_vdir_destr	*str;
57
};
58
59
struct au_vdir_de {
60
	ino_t			de_ino;
61
	unsigned char		de_type;
62
	/* caution: packed */
63
	struct au_vdir_destr	de_str;
64
} __packed;
65
66
struct au_vdir_wh {
67
	struct hlist_node	wh_hash;
68
	aufs_bindex_t		wh_bindex;
69
#ifdef CONFIG_AUFS_SHWH
70
	ino_t			wh_ino;
71
	unsigned char		wh_type;
72
	/* caution: packed */
73
#endif
74
	struct au_vdir_destr	wh_str;
75
} __packed;
76
77
union au_vdir_deblk_p {
78
	unsigned char		*p;
79
	au_vdir_deblk_t		*deblk;
80
	struct au_vdir_de	*de;
81
};
82
83
struct au_vdir {
84
	au_vdir_deblk_t	**vd_deblk;
85
	int		vd_nblk;
86
	struct {
87
		int			i;
88
		union au_vdir_deblk_p	p;
89
	} vd_last;
90
91
	unsigned long	vd_version;
92
	unsigned long	vd_jiffy;
93
};
94
95
/* ---------------------------------------------------------------------- */
96
97
/* dir.c */
98
extern struct file_operations aufs_dir_fop;
99
int au_test_empty_lower(struct dentry *dentry);
100
int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
101
102
/* vdir.c */
103
struct au_nhash *au_nhash_new(gfp_t gfp);
104
void au_nhash_del(struct au_nhash *nhash);
105
void au_nhash_init(struct au_nhash *nhash);
106
void au_nhash_move(struct au_nhash *dst, struct au_nhash *src);
107
void au_nhash_fin(struct au_nhash *nhash);
108
int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
109
			    int limit);
110
int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int namelen);
111
int au_nhash_append_wh(struct au_nhash *whlist, char *name, int namelen,
112
		       ino_t ino, unsigned int d_type, aufs_bindex_t bindex,
113
		    unsigned char shwh);
114
void au_vdir_free(struct au_vdir *vdir);
115
int au_vdir_init(struct file *file);
116
int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
117
118
/* ---------------------------------------------------------------------- */
119
120
static inline
121
void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, unsigned char d_type)
122
{
123
#ifdef CONFIG_AUFS_SHWH
124
	wh->wh_ino = ino;
125
	wh->wh_type = d_type;
126
#endif
127
}
128
129
static inline void au_add_nlink(struct inode *dir, struct inode *h_dir)
130
{
131
	AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
132
	dir->i_nlink += h_dir->i_nlink - 2;
133
	if (unlikely(h_dir->i_nlink < 2))
134
		dir->i_nlink += 2;
135
}
136
137
static inline void au_sub_nlink(struct inode *dir, struct inode *h_dir)
138
{
139
	AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
140
	dir->i_nlink -= h_dir->i_nlink - 2;
141
	if (unlikely(h_dir->i_nlink < 2))
142
		dir->i_nlink -= 2;
143
}
144
145
#endif /* __KERNEL__ */
146
#endif /* __AUFS_DIR_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/dlgt.c (+113 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 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
 * lookup functions in 'delegate' mode
21
 *
22
 * $Id: dlgt.c,v 1.2 2008/04/21 02:00:37 sfjro Exp $
23
 */
24
25
//#include <linux/security.h>
26
#include "aufs.h"
27
28
/* ---------------------------------------------------------------------- */
29
30
struct au_lookup_one_len_args {
31
	struct dentry **errp;
32
	const char *name;
33
	struct dentry *parent;
34
	int len;
35
};
36
37
static void au_call_lookup_one_len(void *args)
38
{
39
	struct au_lookup_one_len_args *a = args;
40
	*a->errp = vfsub_lookup_one_len(a->name, a->parent, a->len);
41
}
42
43
struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
44
				int len, unsigned int flags)
45
{
46
	struct dentry *dentry;
47
	int dirperm1;
48
49
	LKTRTrace("%.*s/%.*s, 0x%x\n", AuDLNPair(parent), len, name, flags);
50
51
	dirperm1 = au_ftest_ndx(flags, DIRPERM1);
52
	if (!dirperm1 && !au_ftest_ndx(flags, DLGT))
53
		dentry = vfsub_lookup_one_len(name, parent, len);
54
	else {
55
		int wkq_err;
56
		struct au_lookup_one_len_args args = {
57
			.errp	= &dentry,
58
			.name	= name,
59
			.parent	= parent,
60
			.len	= len
61
		};
62
		wkq_err = au_wkq_wait(au_call_lookup_one_len, &args,
63
				      /*dlgt*/!dirperm1);
64
		if (unlikely(wkq_err))
65
			dentry = ERR_PTR(wkq_err);
66
	}
67
68
	AuTraceErrPtr(dentry);
69
	return dentry;
70
}
71
72
/* ---------------------------------------------------------------------- */
73
74
struct security_inode_permission_args {
75
	int *errp;
76
	struct inode *h_inode;
77
	int mask;
78
	struct nameidata *fake_nd;
79
};
80
81
static void call_security_inode_permission(void *args)
82
{
83
	struct security_inode_permission_args *a = args;
84
	LKTRTrace("fsuid %d\n", current->fsuid);
85
	*a->errp = security_inode_permission(a->h_inode, a->mask, a->fake_nd);
86
}
87
88
int au_security_inode_permission(struct inode *h_inode, int mask,
89
				 struct nameidata *fake_nd, int dlgt)
90
{
91
	int err;
92
93
	AuTraceEnter();
94
95
	if (!dlgt)
96
		err = security_inode_permission(h_inode, mask, fake_nd);
97
	else {
98
		int wkq_err;
99
		struct security_inode_permission_args args = {
100
			.errp		= &err,
101
			.h_inode	= h_inode,
102
			.mask		= mask,
103
			.fake_nd	= fake_nd
104
		};
105
		wkq_err = au_wkq_wait(call_security_inode_permission, &args,
106
				      /*dlgt*/1);
107
		if (unlikely(wkq_err))
108
			err = wkq_err;
109
	}
110
111
	AuTraceErr(err);
112
	return err;
113
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/export.c (+578 lines)
Line 0 Link Here
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
 * export via nfs
21
 *
22
 * $Id: export.c,v 1.4 2008/05/04 23:52:08 sfjro Exp $
23
 */
24
25
#include <linux/exportfs.h>
26
#include "aufs.h"
27
28
union conv {
29
#if BITS_PER_LONG == 32
30
	__u32 a[1];
31
#else
32
	__u32 a[2];
33
#endif
34
	ino_t ino;
35
};
36
37
static ino_t decode_ino(__u32 *a)
38
{
39
	union conv u;
40
41
	u.a[0] = a[0];
42
#if BITS_PER_LONG == 64
43
	u.a[1] = a[1];
44
#endif
45
	return u.ino;
46
}
47
48
static void encode_ino(__u32 *a, ino_t ino)
49
{
50
	union conv u;
51
52
	u.ino = ino;
53
	a[0] = u.a[0];
54
#if BITS_PER_LONG == 64
55
	a[1] = u.a[1];
56
#endif
57
}
58
59
/* NFS file handle */
60
enum {
61
	Fh_br_id,
62
	Fh_sigen,
63
#if BITS_PER_LONG == 64
64
	/* support 64bit inode number */
65
	Fh_ino1,
66
	Fh_ino2,
67
	Fh_dir_ino1,
68
	Fh_dir_ino2,
69
	Fh_h_ino1,
70
	Fh_h_ino2,
71
#else
72
	Fh_ino1,
73
	Fh_dir_ino1,
74
	Fh_h_ino1,
75
#endif
76
	Fh_h_igen,
77
	Fh_h_type,
78
	Fh_tail,
79
80
	Fh_ino = Fh_ino1,
81
	Fh_dir_ino = Fh_dir_ino1,
82
	Fh_h_ino = Fh_h_ino1,
83
};
84
85
static int au_test_anon(struct dentry *dentry)
86
{
87
	return !!(dentry->d_flags & DCACHE_DISCONNECTED);
88
}
89
90
/* ---------------------------------------------------------------------- */
91
92
static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
93
				    ino_t dir_ino)
94
{
95
	struct dentry *dentry, *parent;
96
	struct inode *inode;
97
98
	LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
99
100
	dentry = NULL;
101
	inode = ilookup(sb, ino);
102
	if (unlikely(!inode))
103
		goto out;
104
105
	dentry = ERR_PTR(-ESTALE);
106
	if (unlikely(is_bad_inode(inode)))
107
		goto out_iput;
108
109
	dentry = NULL;
110
	if (!S_ISDIR(inode->i_mode)) {
111
		struct dentry *d;
112
		spin_lock(&dcache_lock);
113
		list_for_each_entry(d, &inode->i_dentry, d_alias)
114
			if (!au_test_anon(d)
115
			    && d->d_parent->d_inode->i_ino == dir_ino) {
116
				dentry = dget_locked(d);
117
				break;
118
			}
119
		spin_unlock(&dcache_lock);
120
	} else {
121
		dentry = d_find_alias(inode);
122
		if (dentry && !au_test_anon(dentry)) {
123
			int same_ino;
124
			parent = dget_parent(dentry);
125
			same_ino = (parent->d_inode->i_ino == dir_ino);
126
			dput(parent);
127
			if (same_ino)
128
				goto out_iput; /* success */
129
		}
130
131
		dput(dentry);
132
		dentry = NULL;
133
	}
134
135
 out_iput:
136
	iput(inode);
137
 out:
138
	AuTraceErrPtr(dentry);
139
	return dentry;
140
}
141
142
/* ---------------------------------------------------------------------- */
143
144
struct find_name_by_ino {
145
	int called, found;
146
	ino_t ino;
147
	char *name;
148
	int namelen;
149
};
150
151
static int
152
find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
153
		 u64 ino, unsigned int d_type)
154
{
155
	struct find_name_by_ino *a = arg;
156
157
	a->called++;
158
	if (a->ino != ino)
159
		return 0;
160
161
	memcpy(a->name, name, namelen);
162
	a->namelen = namelen;
163
	a->found = 1;
164
	return 1;
165
}
166
167
static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
168
					ino_t dir_ino)
169
{
170
	struct dentry *dentry, *parent;
171
	struct inode *dir;
172
	struct find_name_by_ino arg;
173
	struct file *file;
174
	int err;
175
176
	LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
177
178
	dentry = NULL;
179
	dir = ilookup(sb, dir_ino);
180
	if (unlikely(!dir))
181
		goto out;
182
183
	dentry = ERR_PTR(-ESTALE);
184
	if (unlikely(is_bad_inode(dir)))
185
		goto out_iput;
186
187
	dentry = NULL;
188
	parent = d_find_alias(dir);
189
	if (parent) {
190
		if (unlikely(au_test_anon(parent))) {
191
			dput(parent);
192
			goto out_iput;
193
		}
194
	} else
195
		goto out_iput;
196
197
	file = dentry_open(parent, au_mntcache_get(sb), au_dir_roflags);
198
	dentry = (void *)file;
199
	if (IS_ERR(file))
200
		goto out_iput;
201
202
	dentry = ERR_PTR(-ENOMEM);
203
	arg.name = __getname();
204
	if (unlikely(!arg.name))
205
		goto out_fput;
206
	arg.ino = ino;
207
	arg.found = 0;
208
209
	do {
210
		arg.called = 0;
211
		//smp_mb();
212
		err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
213
	} while (!err && !arg.found && arg.called);
214
	dentry = ERR_PTR(err);
215
	if (arg.found) {
216
		/* do not call au_lkup_one(), nor dlgt */
217
		mutex_lock(&dir->i_mutex);
218
		dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
219
		mutex_unlock(&dir->i_mutex);
220
		AuTraceErrPtr(dentry);
221
	}
222
223
	//out_putname:
224
	__putname(arg.name);
225
 out_fput:
226
	fput(file);
227
 out_iput:
228
	iput(dir);
229
 out:
230
	AuTraceErrPtr(dentry);
231
	return dentry;
232
}
233
234
/* ---------------------------------------------------------------------- */
235
236
struct append_name {
237
	int found, called, len;
238
	char *h_path;
239
	ino_t h_ino;
240
};
241
242
static int append_name(void *arg, const char *name, int len, loff_t pos,
243
		       u64 ino, unsigned int d_type)
244
{
245
	struct append_name *a = arg;
246
	char *p;
247
248
	a->called++;
249
	if (ino != a->h_ino)
250
		return 0;
251
252
	AuDebugOn(len == 1 && *name == '.');
253
	AuDebugOn(len == 2 && name[0] == '.' && name[1] == '.');
254
	a->len = strlen(a->h_path);
255
	memmove(a->h_path - len - 1, a->h_path, a->len);
256
	a->h_path -= len + 1;
257
	p = a->h_path + a->len;
258
	*p++ = '/';
259
	memcpy(p, name, len);
260
	a->len += 1 + len;
261
	a->found++;
262
	return 1;
263
}
264
265
static int h_acceptable(void *expv, struct dentry *dentry)
266
{
267
	return 1;
268
}
269
270
static char *au_build_path(struct super_block *sb, __u32 *fh, char *path,
271
			     struct vfsmount *h_mnt, struct dentry *h_root,
272
			     struct dentry *h_parent)
273
{
274
	char *ret;
275
	int err, len;
276
	struct file *h_file;
277
	struct append_name arg;
278
	struct path dm_path = {
279
		.mnt	= h_mnt,
280
		.dentry	= h_root
281
	};
282
283
	AuTraceEnter();
284
285
	arg.h_path = d_path(&dm_path, path, PATH_MAX);
286
	ret = arg.h_path;
287
	if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
288
		goto out;
289
290
	len = strlen(arg.h_path);
291
	dm_path.dentry = h_parent;
292
	arg.h_path = d_path(&dm_path, path, PATH_MAX);
293
	ret = arg.h_path;
294
	if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
295
		goto out;
296
	LKTRTrace("%s\n", arg.h_path);
297
	if (len != 1)
298
		arg.h_path += len;
299
	LKTRTrace("%p, %s, %ld\n",
300
		  arg.h_path, arg.h_path, (long)(arg.h_path - path));
301
302
	/* cf. fs/exportfs/expfs.c */
303
	h_file = dentry_open(dget(h_parent), mntget(h_mnt), au_dir_roflags);
304
	ret = (void *)h_file;
305
	if (IS_ERR(h_file))
306
		goto out;
307
308
	arg.found = 0;
309
	arg.h_ino = decode_ino(fh + Fh_h_ino);
310
	do {
311
		arg.called = 0;
312
		err = vfsub_readdir(h_file, append_name, &arg, /*dlgt*/0);
313
	} while (!err && !arg.found && arg.called);
314
	LKTRTrace("%p, %s, %d\n", arg.h_path, arg.h_path, arg.len);
315
	fput(h_file);
316
	ret = ERR_PTR(err);
317
	if (unlikely(err))
318
		goto out;
319
320
	dm_path.mnt = au_mntcache_get(sb);
321
	dm_path.dentry = sb->s_root;
322
	ret = d_path(&dm_path, path, PATH_MAX - arg.len);
323
	mntput(dm_path.mnt);
324
	if (unlikely(!ret || IS_ERR(ret)))
325
		goto out;
326
	ret[strlen(ret)] = '/';
327
	LKTRTrace("%s\n", ret);
328
329
 out:
330
	AuTraceErrPtr(ret);
331
	return ret;
332
}
333
334
static struct dentry *
335
decode_by_path(struct super_block *sb, aufs_bindex_t bindex, __u32 *fh,
336
	       int fh_len, void *context)
337
{
338
	struct dentry *dentry, *h_parent, *root, *h_root;
339
	struct super_block *h_sb;
340
	char *path, *p;
341
	struct vfsmount *h_mnt;
342
	int err;
343
	struct nameidata nd;
344
	struct au_branch *br;
345
346
	LKTRTrace("b%d\n", bindex);
347
	SiMustAnyLock(sb);
348
349
	br = au_sbr(sb, bindex);
350
	/* au_br_get(br); */
351
	h_mnt = br->br_mnt;
352
	h_sb = h_mnt->mnt_sb;
353
	LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb));
354
	/* in linux-2.6.24, it takes struct fid * as file handle */
355
	//todo: call lower fh_to_dentry()? fh_to_parent()?
356
	h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
357
				      fh_len - Fh_tail, fh[Fh_h_type],
358
				      h_acceptable, /*context*/NULL);
359
	dentry = h_parent;
360
	if (unlikely(!h_parent || IS_ERR(h_parent))) {
361
		AuWarn1("%s decode_fh failed\n", au_sbtype(h_sb));
362
		goto out;
363
	}
364
	dentry = NULL;
365
	if (unlikely(au_test_anon(h_parent))) {
366
		AuWarn1("%s decode_fh returned a disconnected dentry\n",
367
			au_sbtype(h_sb));
368
		dput(h_parent);
369
		goto out;
370
	}
371
372
	dentry = ERR_PTR(-ENOMEM);
373
	path = __getname();
374
	if (unlikely(!path)) {
375
		dput(h_parent);
376
		goto out;
377
	}
378
379
	root = sb->s_root;
380
	di_read_lock_parent(root, !AuLock_IR);
381
	h_root = au_h_dptr(root, bindex);
382
	di_read_unlock(root, !AuLock_IR);
383
	p = au_build_path(sb, fh, path, h_mnt, h_root, h_parent);
384
	dput(h_parent);
385
	if (IS_ERR(p))
386
		goto out_putname;
387
388
	err = vfsub_path_lookup(p, LOOKUP_FOLLOW, &nd);
389
	dentry = ERR_PTR(err);
390
	if (!err) {
391
		dentry = dget(nd.path.dentry);
392
		if (unlikely(au_test_anon(dentry))) {
393
			dput(dentry);
394
			dentry = ERR_PTR(-ESTALE);
395
		}
396
		path_put(&nd.path);
397
	}
398
399
 out_putname:
400
	__putname(path);
401
 out:
402
	/* au_br_put(br); */
403
	AuTraceErrPtr(dentry);
404
	return dentry;
405
}
406
407
/* ---------------------------------------------------------------------- */
408
409
static noinline_for_stack struct dentry *
410
aufs_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
411
	       int (*acceptable)(void *context, struct dentry *de),
412
	       void *context)
413
{
414
	struct dentry *dentry;
415
	ino_t ino, dir_ino;
416
	aufs_bindex_t bindex, br_id;
417
	struct inode *inode, *h_inode;
418
	au_gen_t sigen;
419
420
	//au_debug_on();
421
	LKTRTrace("%d, fh{i%u, br_id %u, sigen %u, hi%u}\n",
422
		  fh_type, fh[Fh_ino], fh[Fh_br_id], fh[Fh_sigen],
423
		  fh[Fh_h_ino]);
424
	AuDebugOn(fh_len < Fh_tail);
425
426
	si_read_lock(sb, AuLock_FLUSH);
427
	lockdep_off();
428
429
	/* branch id may be wrapped around */
430
	dentry = ERR_PTR(-ESTALE);
431
	br_id = fh[Fh_br_id];
432
	sigen = fh[Fh_sigen];
433
	bindex = au_br_index(sb, br_id);
434
	if (unlikely(bindex < 0 || sigen + AUFS_BRANCH_MAX <= au_sigen(sb)))
435
		goto out;
436
437
	/* is this inode still cached? */
438
	ino = decode_ino(fh + Fh_ino);
439
	dir_ino = decode_ino(fh + Fh_dir_ino);
440
	dentry = decode_by_ino(sb, ino, dir_ino);
441
	if (IS_ERR(dentry))
442
		goto out;
443
	if (dentry)
444
		goto accept;
445
446
	/* is the parent dir cached? */
447
	dentry = decode_by_dir_ino(sb, ino, dir_ino);
448
	if (IS_ERR(dentry))
449
		goto out;
450
	if (dentry)
451
		goto accept;
452
453
	/* lookup path */
454
	dentry = decode_by_path(sb, bindex, fh, fh_len, context);
455
	if (IS_ERR(dentry))
456
		goto out;
457
	if (unlikely(!dentry))
458
		goto out_stale;
459
	if (unlikely(dentry->d_inode->i_ino != ino))
460
		goto out_dput;
461
462
 accept:
463
	inode = dentry->d_inode;
464
	h_inode = NULL;
465
	ii_read_lock_child(inode);
466
	if (au_ibstart(inode) <= bindex && bindex <= au_ibend(inode))
467
		h_inode = au_h_iptr(inode, bindex);
468
	ii_read_unlock(inode);
469
	if (h_inode
470
	    && h_inode->i_generation == fh[Fh_h_igen]
471
	    && acceptable(context, dentry))
472
		goto out; /* success */
473
 out_dput:
474
	dput(dentry);
475
 out_stale:
476
	dentry = ERR_PTR(-ESTALE);
477
 out:
478
	lockdep_on();
479
	si_read_unlock(sb);
480
	AuTraceErrPtr(dentry);
481
	//au_debug_off();
482
	return dentry;
483
}
484
485
static struct dentry *
486
aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
487
		  int fh_type)
488
{
489
	return aufs_decode_fh(sb, fid->raw, fh_len, fh_type, h_acceptable,
490
			      /*context*/NULL);
491
}
492
493
/* ---------------------------------------------------------------------- */
494
495
static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
496
			  int connectable)
497
{
498
	int err;
499
	struct super_block *sb, *h_sb;
500
	struct inode *inode, *h_inode, *dir;
501
	aufs_bindex_t bindex;
502
	union conv u;
503
	struct dentry *parent, *h_parent;
504
505
	//au_debug_on();
506
	BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
507
	LKTRTrace("%.*s, max %d, conn %d\n",
508
		  AuDLNPair(dentry), *max_len, connectable);
509
	AuDebugOn(au_test_anon(dentry));
510
	inode = dentry->d_inode;
511
	AuDebugOn(!inode);
512
	parent = dget_parent(dentry);
513
	AuDebugOn(au_test_anon(parent));
514
515
	err = -ENOSPC;
516
	if (unlikely(*max_len <= Fh_tail)) {
517
		AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
518
		goto out;
519
	}
520
521
	sb = dentry->d_sb;
522
	si_read_lock(sb, AuLock_FLUSH);
523
	di_read_lock_child(dentry, AuLock_IR);
524
	di_read_lock_parent(parent, AuLock_IR);
525
#ifdef CONFIG_AUFS_DEBUG
526
	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
527
		AuWarn1("NFS-exporting requires xino\n");
528
#endif
529
530
	err = -EPERM;
531
	bindex = au_dbstart(dentry);
532
	h_sb = au_sbr_sb(sb, bindex);
533
	if (unlikely(!h_sb->s_export_op)) {
534
		AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
535
		goto out_unlock;
536
	}
537
538
	fh[Fh_br_id] = au_sbr_id(sb, bindex);
539
	fh[Fh_sigen] = au_sigen(sb);
540
	encode_ino(fh + Fh_ino, inode->i_ino);
541
	dir = parent->d_inode;
542
	encode_ino(fh + Fh_dir_ino, dir->i_ino);
543
	h_inode = au_h_dptr(dentry, bindex)->d_inode;
544
	encode_ino(fh + Fh_h_ino, h_inode->i_ino);
545
	fh[Fh_h_igen] = h_inode->i_generation;
546
547
	*max_len -= Fh_tail;
548
	//LKTRTrace("Fh_tail %d, max_len %d\n", Fh_tail, *max_len);
549
	h_parent = au_h_dptr(parent, bindex);
550
	AuDebugOn(au_test_anon(h_parent));
551
	/* in linux-2.6.24, it takes struct fid * as file handle */
552
	fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
553
					   max_len, connectable);
554
	err = fh[Fh_h_type];
555
	*max_len += Fh_tail;
556
	if (err != 255)
557
		err = 2; //??
558
	else
559
		AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
560
561
 out_unlock:
562
	di_read_unlock(parent, AuLock_IR);
563
	aufs_read_unlock(dentry, AuLock_IR);
564
 out:
565
	dput(parent);
566
	AuTraceErr(err);
567
	//au_debug_off();
568
	if (unlikely(err < 0))
569
		err = 255;
570
	return err;
571
}
572
573
/* ---------------------------------------------------------------------- */
574
575
struct export_operations aufs_export_op = {
576
	.fh_to_dentry	= aufs_fh_to_dentry,
577
	.encode_fh	= aufs_encode_fh
578
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/file.c (+755 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * handling file/dir, and address_space operation
21
 *
22
 * $Id: file.c,v 1.4 2008/05/04 23:54:53 sfjro Exp $
23
 */
24
25
//#include <linux/fsnotify.h>
26
#include <linux/pagemap.h>
27
//#include <linux/poll.h>
28
//#include <linux/security.h>
29
#include "aufs.h"
30
31
/*
32
 * a dirty trick for handling FMODE_EXEC and deny_write_access().
33
 * because FMODE_EXEC flag is not passed to f_op->open(),
34
 * set it to file->private_data temporary.
35
 */
36
#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH)
37
int au_store_fmode_exec(struct nameidata *nd, struct inode *inode)
38
{
39
	int err;
40
	union {
41
		void *p;
42
		unsigned long ul;
43
	} u;
44
45
	err = 0;
46
	if (nd
47
	    && (nd->flags & LOOKUP_OPEN)
48
	    && nd->intent.open.file
49
	    && (nd->intent.open.flags & FMODE_EXEC)
50
	    && inode
51
	    && S_ISREG(inode->i_mode)) {
52
		u.ul = nd->intent.open.flags;
53
		nd->intent.open.file->private_data = u.p;
54
		//smp_mb();
55
		err = 1;
56
	}
57
58
	return err;
59
}
60
#endif
61
62
/* drop flags for writing */
63
unsigned int au_file_roflags(unsigned int flags)
64
{
65
	flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
66
	flags |= O_RDONLY | O_NOATIME;
67
	return flags;
68
}
69
70
/* common functions to regular file and dir */
71
struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
72
		       struct file *file)
73
{
74
	struct file *h_file;
75
	struct dentry *h_dentry;
76
	struct inode *h_inode;
77
	struct super_block *sb;
78
	struct au_branch *br;
79
	int hinotify, err;
80
81
	LKTRTrace("%.*s, b%d, flags 0%o, f %d\n",
82
		  AuDLNPair(dentry), bindex, flags, !!file);
83
	AuDebugOn(!dentry);
84
	h_dentry = au_h_dptr(dentry, bindex);
85
	AuDebugOn(!h_dentry);
86
	h_inode = h_dentry->d_inode;
87
	AuDebugOn(!h_inode);
88
89
	sb = dentry->d_sb;
90
	hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY);
91
92
	br = au_sbr(sb, bindex);
93
	au_br_get(br);
94
	/* drop flags for writing */
95
	if (au_test_ro(sb, bindex, dentry->d_inode))
96
		flags = au_file_roflags(flags);
97
	flags &= ~O_CREAT;
98
99
	h_file = NULL;
100
	if (unlikely(file && au_test_nfs(h_dentry->d_sb)))
101
		h_file = au_h_intent(dentry, bindex, file);
102
	if (!h_file) {
103
		//DbgSleep(3);
104
		h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags);
105
		//if (LktrCond) {fput(h_file); h_file = ERR_PTR(-1);}
106
	}
107
108
	/*
109
	 * a dirty trick for handling FMODE_EXEC and deny_write_access().
110
	 */
111
	if (file && (file->f_mode & FMODE_EXEC)) {
112
		h_file->f_mode |= FMODE_EXEC;
113
		smp_mb(); /* flush f_mode */
114
		err = au_deny_write_access(h_file);
115
		if (unlikely(err)) {
116
			fput(h_file);
117
			h_file = ERR_PTR(err);
118
		}
119
	}
120
	if (!IS_ERR(h_file))
121
		return h_file;
122
123
	au_br_put(br);
124
	AuTraceErrPtr(h_file);
125
	return h_file;
126
}
127
128
static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
129
{
130
	int err;
131
	struct dentry *parent, *h_parent, *h_dentry, *gparent;
132
	aufs_bindex_t bcpup;
133
	struct inode *h_dir, *h_inode, *dir;
134
	struct super_block *sb;
135
136
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
137
	AuDebugOn(IS_ROOT(dentry));
138
	DiMustWriteLock(dentry);
139
140
	parent = dget_parent(dentry);
141
	di_write_lock_parent(parent);
142
	sb = dentry->d_sb;
143
	err = AuWbrCopyup(au_sbi(sb), dentry);
144
	bcpup = err;
145
	if (err < 0) {
146
		err = 0; /* stop copyup, it is not an error */
147
		goto out;
148
	}
149
	err = 0;
150
151
	h_parent = au_h_dptr(parent, bcpup);
152
	if (!h_parent) {
153
		err = au_cpup_dirs(dentry, bcpup, NULL);
154
		if (unlikely(err))
155
			goto out;
156
		h_parent = au_h_dptr(parent, bcpup);
157
	}
158
159
	h_dir = h_parent->d_inode;
160
	h_dentry = au_h_dptr(dentry, bstart);
161
	h_inode = h_dentry->d_inode;
162
	dir = parent->d_inode;
163
	//todo: meaningless lock if CONFIG_AUFS_DEBUG is disabled.
164
	gparent = NULL;
165
	if (unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY)
166
		     && !IS_ROOT(parent))) {
167
		gparent = dget_parent(parent);
168
		ii_read_lock_parent2(gparent->d_inode);
169
	}
170
	au_hdir_lock(h_dir, dir, bcpup);
171
	//todo: test parent-gparent relationship
172
	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
173
	AuDebugOn(au_h_dptr(dentry, bcpup));
174
	err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
175
	AuTraceErr(err);
176
	mutex_unlock(&h_inode->i_mutex);
177
	au_hdir_unlock(h_dir, dir, bcpup);
178
	if (unlikely(gparent)) {
179
		ii_read_unlock(gparent->d_inode);
180
		dput(gparent);
181
	}
182
183
 out:
184
	di_write_unlock(parent);
185
	dput(parent);
186
	AuTraceErr(err);
187
	return err;
188
}
189
190
int au_do_open(struct inode *inode, struct file *file,
191
	       int (*open)(struct file *file, int flags))
192
{
193
	int err, coo;
194
	struct dentry *dentry;
195
	struct super_block *sb;
196
	aufs_bindex_t bstart;
197
	//struct inode *h_dir, *dir;
198
199
	dentry = file->f_dentry;
200
	LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
201
202
	sb = dentry->d_sb;
203
	si_read_lock(sb, AuLock_FLUSH);
204
	coo = 0;
205
	switch (au_mntflags(sb) & AuOptMask_COO) {
206
	case AuOpt_COO_LEAF:
207
		coo = !S_ISDIR(inode->i_mode);
208
		break;
209
	case AuOpt_COO_ALL:
210
		coo = 1;
211
		break;
212
	}
213
	err = au_finfo_init(file);
214
	//if (LktrCond) {fi_write_unlock(file); fin_finfo(file); err = -1;}
215
	if (unlikely(err))
216
		goto out;
217
218
	if (!coo) {
219
		di_read_lock_child(dentry, AuLock_IR);
220
		bstart = au_dbstart(dentry);
221
	} else {
222
		di_write_lock_child(dentry);
223
		bstart = au_dbstart(dentry);
224
		if (au_test_ro(sb, bstart, dentry->d_inode)) {
225
			err = do_coo(dentry, bstart);
226
			if (err) {
227
				di_write_unlock(dentry);
228
				goto out_finfo;
229
			}
230
			bstart = au_dbstart(dentry);
231
		}
232
		di_downgrade_lock(dentry, AuLock_IR);
233
	}
234
235
	err = open(file, file->f_flags);
236
	//if (LktrCond) err = -1;
237
	di_read_unlock(dentry, AuLock_IR);
238
239
 out_finfo:
240
	fi_write_unlock(file);
241
	if (unlikely(err))
242
		au_finfo_fin(file);
243
	//DbgFile(file);
244
 out:
245
	si_read_unlock(sb);
246
	AuTraceErr(err);
247
	return err;
248
}
249
250
int au_reopen_nondir(struct file *file)
251
{
252
	int err;
253
	struct dentry *dentry;
254
	aufs_bindex_t bstart, bindex, bend;
255
	struct file *h_file, *h_file_tmp;
256
257
	dentry = file->f_dentry;
258
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
259
	bstart = au_dbstart(dentry);
260
	AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
261
		  || !au_h_dptr(dentry, bstart)->d_inode);
262
263
	h_file_tmp = NULL;
264
	if (au_fbstart(file) == bstart) {
265
		h_file = au_h_fptr(file, bstart);
266
		if (file->f_mode == h_file->f_mode)
267
			return 0; /* success */
268
		h_file_tmp = h_file;
269
		get_file(h_file_tmp);
270
		au_set_h_fptr(file, bstart, NULL);
271
	}
272
	AuDebugOn(au_fbstart(file) < bstart
273
		  || au_fi(file)->fi_hfile[0 + bstart].hf_file);
274
275
	h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file);
276
	//if (LktrCond) {fput(h_file); au_br_put(au_sbr(dentry->d_sb, bstart));
277
	//h_file = ERR_PTR(-1);}
278
	err = PTR_ERR(h_file);
279
	if (IS_ERR(h_file))
280
		goto out; // close all?
281
	err = 0;
282
	//cpup_file_flags(h_file, file);
283
	au_set_fbstart(file, bstart);
284
	au_set_h_fptr(file, bstart, h_file);
285
	au_update_figen(file);
286
	//file->f_ra = h_file->f_ra; //??
287
288
	/* close lower files */
289
	bend = au_fbend(file);
290
	for (bindex = bstart + 1; bindex <= bend; bindex++)
291
		au_set_h_fptr(file, bindex, NULL);
292
	au_set_fbend(file, bstart);
293
294
 out:
295
	if (h_file_tmp)
296
		fput(h_file_tmp);
297
	AuTraceErr(err);
298
	return err;
299
}
300
301
/* ---------------------------------------------------------------------- */
302
303
/*
304
 * prepare the @file for writing.
305
 */
306
int au_ready_to_write(struct file *file, loff_t len)
307
{
308
	int err;
309
	struct dentry *dentry, *parent, *h_dentry, *h_parent, *hi_wh,
310
		*old_h_dentry, *gparent;
311
	struct inode *h_inode, *h_dir, *inode, *dir;
312
	struct super_block *sb;
313
	aufs_bindex_t bstart, bcpup, old_bstart;
314
	struct au_dinfo *dinfo;
315
316
	dentry = file->f_dentry;
317
	LKTRTrace("%.*s, len %Ld\n", AuDLNPair(dentry), len);
318
	FiMustWriteLock(file);
319
320
	sb = dentry->d_sb;
321
	bstart = au_fbstart(file);
322
	AuDebugOn(au_fbr(file, bstart) != au_sbr(sb, bstart));
323
324
	inode = dentry->d_inode;
325
	AuDebugOn(S_ISDIR(inode->i_mode));
326
	ii_read_lock_child(inode);
327
	LKTRTrace("rdonly %d, bstart %d\n",
328
		  au_test_ro(sb, bstart, inode), bstart);
329
	err = au_test_ro(sb, bstart, inode);
330
	ii_read_unlock(inode);
331
	if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE))
332
		return 0;
333
334
	/* need to cpup */
335
	di_write_lock_child(dentry);
336
	parent = dget_parent(dentry);
337
	di_write_lock_parent(parent);
338
	err = AuWbrCopyup(au_sbi(sb), dentry);
339
	bcpup = err;
340
	if (unlikely(err < 0))
341
		goto out_unlock;
342
	err = 0;
343
344
	h_parent = au_h_dptr(parent, bcpup);
345
	if (!h_parent) {
346
		err = au_cpup_dirs(dentry, bcpup, NULL);
347
		//if (LktrCond) err = -1;
348
		if (unlikely(err))
349
			goto out_unlock;
350
		h_parent = au_h_dptr(parent, bcpup);
351
	}
352
353
	//todo: meaningless lock if CONFIG_AUFS_DEBUG is disabled.
354
	gparent = NULL;
355
	if (unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY)
356
		     && !IS_ROOT(parent))) {
357
		gparent = dget_parent(parent);
358
		ii_read_lock_parent2(gparent->d_inode);
359
	}
360
	h_dir = h_parent->d_inode;
361
	h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
362
	h_inode = h_dentry->d_inode;
363
	dir = parent->d_inode;
364
	au_hdir_lock(h_dir, dir, bcpup);
365
	//todo: test parent-gparent relationship
366
	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
367
	if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
368
	    /* || !h_inode->i_nlink */) {
369
		hi_wh = au_hi_wh(inode, bcpup);
370
		if (!hi_wh)
371
			err = au_sio_cpup_wh(dentry, bcpup, len, file);
372
		else {
373
			/* already copied-up after unlink */
374
			dinfo = au_di(dentry);
375
			old_bstart = dinfo->di_bstart;
376
			dinfo->di_bstart = bcpup;
377
			old_h_dentry = dinfo->di_hdentry[0 + bcpup].hd_dentry;
378
			dinfo->di_hdentry[0 + bcpup].hd_dentry = hi_wh;
379
			err = au_reopen_nondir(file);
380
			dinfo->di_hdentry[0 + bcpup].hd_dentry = old_h_dentry;
381
			dinfo->di_bstart = old_bstart;
382
		}
383
		//if (LktrCond) err = -1;
384
		AuTraceErr(err);
385
	} else {
386
		if (!au_h_dptr(dentry, bcpup))
387
			err = au_sio_cpup_simple(dentry, bcpup, len,
388
						 AuCpup_DTIME);
389
		//if (LktrCond) err = -1;
390
		AuTraceErr(err);
391
		if (!err)
392
			err = au_reopen_nondir(file);
393
		//if (LktrCond) err = -1;
394
		AuTraceErr(err);
395
	}
396
	mutex_unlock(&h_inode->i_mutex);
397
	au_hdir_unlock(h_dir, dir, bcpup);
398
	if (unlikely(gparent)) {
399
		ii_read_unlock(gparent->d_inode);
400
		dput(gparent);
401
	}
402
403
 out_unlock:
404
	di_write_unlock(parent);
405
	di_write_unlock(dentry);
406
	dput(parent);
407
	AuTraceErr(err);
408
	return err;
409
410
}
411
412
/* ---------------------------------------------------------------------- */
413
414
static int refresh_file_by_inode(struct file *file, int *need_reopen)
415
{
416
	int err;
417
	struct au_finfo *finfo;
418
	struct dentry *dentry, *parent, *old_h_dentry, *hi_wh;
419
	struct inode *inode, *dir, *h_dir;
420
	aufs_bindex_t bstart, new_bstart, old_bstart;
421
	struct super_block *sb;
422
	struct au_dinfo *dinfo;
423
424
	dentry = file->f_dentry;
425
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
426
	FiMustWriteLock(file);
427
428
	err = 0;
429
	finfo = au_fi(file);
430
	inode = dentry->d_inode;
431
	sb = dentry->d_sb;
432
 again:
433
	bstart = au_ibstart(inode);
434
	if (bstart == finfo->fi_bstart)
435
		goto out;
436
437
	new_bstart = bstart;
438
	parent = dget_parent(dentry);
439
	dir = parent->d_inode;
440
	if (au_test_ro(sb, bstart, inode)) {
441
		di_read_lock_parent(parent, !AuLock_IR);
442
		err = AuWbrCopyup(au_sbi(sb), dentry);
443
		new_bstart = err;
444
		di_read_unlock(parent, !AuLock_IR);
445
		//todo: err = -1;
446
		if (unlikely(err < 0))
447
			goto out_put;
448
	}
449
	di_read_unlock(dentry, AuLock_IR);
450
	di_write_lock_child(dentry);
451
	/* someone else might change our inode while we were sleeping */
452
	if (bstart != au_ibstart(inode)) { // todo
453
		di_downgrade_lock(dentry, AuLock_IR);
454
		err = 0;
455
		dput(parent);
456
		goto again;
457
	}
458
	di_read_lock_parent(parent, AuLock_IR);
459
	bstart = new_bstart;
460
461
	hi_wh = au_hi_wh(inode, bstart);
462
	if (au_opt_test(au_mntflags(sb), PLINK)
463
	    && au_plink_test(sb, inode)
464
	    && !d_unhashed(dentry)) {
465
		err = au_test_and_cpup_dirs(dentry, bstart, NULL);
466
467
		/* always superio. */
468
		h_dir = au_h_dptr(parent, bstart)->d_inode;
469
		au_hdir_lock(h_dir, dir, bstart);
470
		err = au_sio_cpup_simple(dentry, bstart, -1, AuCpup_DTIME);
471
		au_hdir_unlock(h_dir, dir, bstart);
472
	} else if (hi_wh) {
473
		/* already copied-up after unlink */
474
		dinfo = au_di(dentry);
475
		old_bstart = dinfo->di_bstart;
476
		dinfo->di_bstart = bstart;
477
		old_h_dentry = dinfo->di_hdentry[0 + bstart].hd_dentry;
478
		dinfo->di_hdentry[0 + bstart].hd_dentry = hi_wh;
479
		err = au_reopen_nondir(file);
480
		dinfo->di_hdentry[0 + bstart].hd_dentry = old_h_dentry;
481
		dinfo->di_bstart = old_bstart;
482
		*need_reopen = 0;
483
	}
484
	di_read_unlock(parent, AuLock_IR);
485
	di_downgrade_lock(dentry, AuLock_IR);
486
487
 out_put:
488
	dput(parent);
489
 out:
490
	AuTraceErr(err);
491
	return err;
492
}
493
494
/*
495
 * after branch manipulating, refresh the file.
496
 */
497
static int refresh_file(struct file *file, int (*reopen)(struct file *file))
498
{
499
	int err, new_sz, need_reopen;
500
	struct dentry *dentry;
501
	aufs_bindex_t bend, bindex, bstart, brid;
502
	struct au_hfile *p;
503
	struct au_finfo *finfo;
504
	struct super_block *sb;
505
	struct inode *inode;
506
	struct file *hidden_file;
507
508
	dentry = file->f_dentry;
509
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
510
	FiMustWriteLock(file);
511
	DiMustReadLock(dentry);
512
	inode = dentry->d_inode;
513
	IiMustReadLock(inode);
514
515
	err = -ENOMEM;
516
	sb = dentry->d_sb;
517
	finfo = au_fi(file);
518
	bstart = finfo->fi_bstart;
519
	bend = finfo->fi_bstart;
520
	new_sz = sizeof(*finfo->fi_hfile) * (au_sbend(sb) + 1);
521
	p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1),
522
			 new_sz, GFP_KERNEL);
523
	//p = NULL;
524
	if (unlikely(!p))
525
		goto out;
526
	finfo->fi_hfile = p;
527
	hidden_file = p[0 + bstart].hf_file;
528
529
	p = finfo->fi_hfile + finfo->fi_bstart;
530
	brid = p->hf_br->br_id;
531
	bend = finfo->fi_bend;
532
	for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
533
		struct au_hfile tmp, *q;
534
		aufs_bindex_t new_bindex;
535
536
		if (!p->hf_file)
537
			continue;
538
		new_bindex = au_find_bindex(sb, p->hf_br);
539
		if (new_bindex == bindex)
540
			continue;
541
		if (new_bindex < 0) { // test here
542
			au_set_h_fptr(file, bindex, NULL);
543
			continue;
544
		}
545
546
		/* swap two hidden inode, and loop again */
547
		q = finfo->fi_hfile + new_bindex;
548
		tmp = *q;
549
		*q = *p;
550
		*p = tmp;
551
		if (tmp.hf_file) {
552
			bindex--;
553
			p--;
554
		}
555
	}
556
	{
557
		aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend;
558
		finfo->fi_bstart = 0;
559
		finfo->fi_bend = au_sbend(sb);
560
		finfo->fi_bstart = s;
561
		finfo->fi_bend = e;
562
	}
563
564
	p = finfo->fi_hfile;
565
	if (!au_test_mmapped(file) && !d_unhashed(dentry)) {
566
		bend = au_sbend(sb);
567
		for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
568
		     finfo->fi_bstart++, p++)
569
			if (p->hf_file) {
570
				if (p->hf_file->f_dentry
571
				    && p->hf_file->f_dentry->d_inode)
572
					break;
573
				else
574
					au_hfput(p);
575
			}
576
	} else {
577
		bend = au_br_index(sb, brid);
578
		//LKTRTrace("%d\n", bend);
579
		for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
580
		     finfo->fi_bstart++, p++)
581
			if (p->hf_file)
582
				au_hfput(p);
583
		//LKTRTrace("%d\n", finfo->fi_bstart);
584
		bend = au_sbend(sb);
585
	}
586
587
	p = finfo->fi_hfile + bend;
588
	for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
589
	     finfo->fi_bend--, p--)
590
		if (p->hf_file) {
591
			if (p->hf_file->f_dentry
592
			    && p->hf_file->f_dentry->d_inode)
593
				break;
594
			else
595
				au_hfput(p);
596
		}
597
	AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
598
	//DbgFile(file);
599
	//DbgDentry(file->f_dentry);
600
601
	err = 0;
602
	need_reopen = 1;
603
	if (!au_test_mmapped(file))
604
		err = refresh_file_by_inode(file, &need_reopen);
605
	if (!err && need_reopen && !d_unhashed(dentry))
606
		err = reopen(file);
607
		//err = -1;
608
	if (!err) {
609
		au_update_figen(file);
610
		//DbgFile(file);
611
		return 0; /* success */
612
	}
613
614
	/* error, close all hidden files */
615
	bend = au_fbend(file);
616
	for (bindex = au_fbstart(file); bindex <= bend; bindex++)
617
		au_set_h_fptr(file, bindex, NULL);
618
619
 out:
620
	AuTraceErr(err);
621
	return err;
622
}
623
624
/* common function to regular file and dir */
625
int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
626
			    int wlock, int locked)
627
{
628
	int err, pseudo_link;
629
	struct dentry *dentry;
630
	struct super_block *sb;
631
	aufs_bindex_t bstart;
632
	au_gen_t sgen, fgen;
633
634
	dentry = file->f_dentry;
635
	LKTRTrace("%.*s, w %d, l %d\n", AuDLNPair(dentry), wlock, locked);
636
	sb = dentry->d_sb;
637
	SiMustAnyLock(sb);
638
639
	err = 0;
640
	sgen = au_sigen(sb);
641
	fi_write_lock(file);
642
	fgen = au_figen(file);
643
	di_read_lock_child(dentry, AuLock_IR);
644
	bstart = au_dbstart(dentry);
645
	pseudo_link = (bstart != au_ibstart(dentry->d_inode));
646
	di_read_unlock(dentry, AuLock_IR);
647
	if (sgen == fgen && !pseudo_link && au_fbstart(file) == bstart) {
648
		if (!wlock)
649
			fi_downgrade_lock(file);
650
		return 0; /* success */
651
	}
652
653
	LKTRTrace("sgen %d, fgen %d\n", sgen, fgen);
654
	if (unlikely(sgen != au_digen(dentry)
655
		     || sgen != au_iigen(dentry->d_inode))) {
656
		/*
657
		 * d_path() and path_lookup() is a simple and good approach
658
		 * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a
659
		 * deadlock. removed the code.
660
		 */
661
		di_write_lock_child(dentry);
662
		err = au_reval_dpath(dentry, sgen);
663
		//if (LktrCond) err = -1;
664
		di_write_unlock(dentry);
665
		if (unlikely(err < 0))
666
			goto out;
667
		AuDebugOn(au_digen(dentry) != sgen
668
			  || au_iigen(dentry->d_inode) != sgen);
669
	}
670
671
	di_read_lock_child(dentry, AuLock_IR);
672
	err = refresh_file(file, reopen
673
			   /* , au_opt_test(au_mnt_flags(sb), REFROF) */);
674
	//if (LktrCond) err = -1;
675
	di_read_unlock(dentry, AuLock_IR);
676
	if (!err) {
677
		if (!wlock)
678
			fi_downgrade_lock(file);
679
	} else
680
		fi_write_unlock(file);
681
682
 out:
683
	AuTraceErr(err);
684
	return err;
685
}
686
687
/* ---------------------------------------------------------------------- */
688
689
/* cf. aufs_nopage() */
690
/* for madvise(2) */
691
static int aufs_readpage(struct file *file, struct page *page)
692
{
693
	AuTraceEnter();
694
	unlock_page(page);
695
	return 0;
696
}
697
698
/* they will never be called. */
699
#ifdef CONFIG_AUFS_DEBUG
700
static int aufs_prepare_write(struct file *file, struct page *page,
701
			      unsigned from, unsigned to)
702
{ AuUnsupport(); return 0; }
703
static int aufs_commit_write(struct file *file, struct page *page,
704
			     unsigned from, unsigned to)
705
{ AuUnsupport(); return 0; }
706
static int aufs_write_begin(struct file *file, struct address_space *mapping,
707
			    loff_t pos, unsigned len, unsigned flags,
708
			    struct page **pagep, void **fsdata)
709
{ AuUnsupport(); return 0; }
710
static int aufs_write_end(struct file *file, struct address_space *mapping,
711
			  loff_t pos, unsigned len, unsigned copied,
712
			  struct page *page, void *fsdata)
713
{ AuUnsupport(); return 0; }
714
static int aufs_writepage(struct page *page, struct writeback_control *wbc)
715
{ AuUnsupport(); return 0; }
716
static void aufs_sync_page(struct page *page)
717
{ AuUnsupport(); }
718
719
static int aufs_set_page_dirty(struct page *page)
720
{ AuUnsupport(); return 0; }
721
static void aufs_invalidatepage(struct page *page, unsigned long offset)
722
{ AuUnsupport(); }
723
static int aufs_releasepage(struct page *page, gfp_t gfp)
724
{ AuUnsupport(); return 0; }
725
static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
726
			      const struct iovec *iov, loff_t offset,
727
			      unsigned long nr_segs)
728
{ AuUnsupport(); return 0; }
729
static struct page *aufs_get_xip_page(struct address_space *mapping,
730
				      sector_t offset, int create)
731
{ AuUnsupport(); return NULL; }
732
//static int aufs_migratepage (struct page *newpage, struct page *page)
733
//{ AuUnsupport(); return 0; }
734
#endif /* CONFIG_AUFS_DEBUG */
735
736
struct address_space_operations aufs_aop = {
737
	.readpage	= aufs_readpage,
738
#ifdef CONFIG_AUFS_DEBUG
739
	.writepage	= aufs_writepage,
740
	.sync_page	= aufs_sync_page,
741
	//.writepages	= aufs_writepages,
742
	.set_page_dirty	= aufs_set_page_dirty,
743
	//.readpages	= aufs_readpages,
744
	.prepare_write	= aufs_prepare_write,
745
	.commit_write	= aufs_commit_write,
746
	.write_begin	= aufs_write_begin,
747
	.write_end	= aufs_write_end,
748
	//.bmap		= aufs_bmap,
749
	.invalidatepage	= aufs_invalidatepage,
750
	.releasepage	= aufs_releasepage,
751
	.direct_IO	= aufs_direct_IO,
752
	.get_xip_page	= aufs_get_xip_page,
753
	//.migratepage	= aufs_migratepage
754
#endif /* CONFIG_AUFS_DEBUG */
755
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/file.h (+246 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * file operations
21
 *
22
 * $Id: file.h,v 1.3 2008/05/19 01:48:04 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_FILE_H__
26
#define __AUFS_FILE_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/file.h>
31
#include <linux/fs.h>
32
#include <linux/mm.h>
33
#include <linux/aufs_type.h>
34
#include "dentry.h"
35
#include "misc.h"
36
#include "super.h"
37
38
/* ---------------------------------------------------------------------- */
39
40
struct au_branch;
41
struct au_hfile {
42
	struct file		*hf_file;
43
	struct au_branch	*hf_br;
44
};
45
46
struct au_vdir;
47
struct au_finfo {
48
	atomic_t		fi_generation;
49
50
	struct au_rwsem		fi_rwsem;
51
	struct au_hfile		*fi_hfile;
52
	aufs_bindex_t		fi_bstart, fi_bend;
53
54
	union {
55
		struct vm_operations_struct	*fi_h_vm_ops;
56
		struct au_vdir			*fi_vdir_cache;
57
	};
58
};
59
60
/* ---------------------------------------------------------------------- */
61
62
/* file.c */
63
extern struct address_space_operations aufs_aop;
64
unsigned int au_file_roflags(unsigned int flags);
65
struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
66
		       struct file *file);
67
int au_do_open(struct inode *inode, struct file *file,
68
	       int (*open)(struct file *file, int flags));
69
int au_reopen_nondir(struct file *file);
70
int au_ready_to_write(struct file *file, loff_t len);
71
int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
72
			    int wlock, int locked);
73
74
/* f_op.c */
75
extern struct file_operations aufs_file_fop;
76
int aufs_flush(struct file *file, fl_owner_t id);
77
78
/* finfo.c */
79
struct au_finfo *au_fi(struct file *file);
80
struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex);
81
struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex);
82
83
void au_hfput(struct au_hfile *hf);
84
void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
85
		   struct file *h_file);
86
87
void au_finfo_fin(struct file *file);
88
int au_finfo_init(struct file *file);
89
90
#ifdef CONFIG_AUFS_ROBR
91
/* robr.c */
92
struct file *au_robr_safe_file(struct vm_area_struct *vma);
93
void au_robr_reset_file(struct vm_area_struct *vma, struct file *file);
94
#else
95
static inline struct file *au_robr_safe_file(struct vm_area_struct *vma)
96
{
97
	struct file *file;
98
99
	file = vma->vm_file;
100
	if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
101
		return file;
102
	return NULL;
103
}
104
105
static inline
106
void au_robr_reset_file(struct vm_area_struct *vma, struct file *file)
107
{
108
	vma->vm_file = file;
109
	//smp_mb(); /* flush vm_file */
110
}
111
#endif /* CONFIG_AUFS_ROBR */
112
113
/* ---------------------------------------------------------------------- */
114
115
//todo: memory barrier?
116
static inline au_gen_t au_figen(struct file *f)
117
{
118
	return atomic_read(&au_fi(f)->fi_generation);
119
}
120
121
static inline int au_test_mmapped(struct file *f)
122
{
123
	return !!(au_fi(f)->fi_h_vm_ops);
124
}
125
126
static inline int au_test_aufs_file(struct file *f)
127
{
128
	return !(f->f_dentry->d_inode->i_mode
129
		 & (S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK));
130
}
131
132
/* ---------------------------------------------------------------------- */
133
134
#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH)
135
int au_store_fmode_exec(struct nameidata *nd, struct inode *inode);
136
137
static inline int au_deny_write_access(struct file *h_file)
138
{
139
	LKTRTrace("%.*s\n", AuDLNPair(h_file->f_dentry));
140
	return deny_write_access(h_file);
141
}
142
143
static inline void au_allow_write_access(struct file *h_file)
144
{
145
	allow_write_access(h_file);
146
}
147
148
#else
149
150
static inline int au_store_fmode_exec(struct nameidata *nd, struct inode *inode)
151
{
152
	/* nothing */
153
	return 0;
154
}
155
156
static inline int au_deny_write_access(struct file *h_file)
157
{
158
	/* nothing */
159
	return 0;
160
}
161
162
static inline void au_allow_write_access(struct file *h_file)
163
{
164
	/* nothing */
165
}
166
#endif /* CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH */
167
168
/* ---------------------------------------------------------------------- */
169
170
/*
171
 * fi_read_lock, fi_write_lock,
172
 * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
173
 */
174
AuSimpleRwsemFuncs(fi, struct file *f, au_fi(f)->fi_rwsem);
175
176
/* to debug easier, do not make them inlined functions */
177
#define FiMustReadLock(f) do { \
178
	SiMustAnyLock((f)->f_dentry->d_sb); \
179
	AuRwMustReadLock(&au_fi(f)->fi_rwsem); \
180
} while (0)
181
182
#define FiMustWriteLock(f) do { \
183
	SiMustAnyLock((f)->f_dentry->d_sb); \
184
	AuRwMustWriteLock(&au_fi(f)->fi_rwsem); \
185
} while (0)
186
187
#define FiMustAnyLock(f) do { \
188
	SiMustAnyLock((f)->f_dentry->d_sb); \
189
	AuRwMustAnyLock(&au_fi(f)->fi_rwsem); \
190
} while (0)
191
192
#define FiMustNoWaiters(f)	AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
193
194
/* ---------------------------------------------------------------------- */
195
196
// hard/soft set
197
static inline aufs_bindex_t au_fbstart(struct file *file)
198
{
199
	FiMustAnyLock(file);
200
	return au_fi(file)->fi_bstart;
201
}
202
203
static inline aufs_bindex_t au_fbend(struct file *file)
204
{
205
	FiMustAnyLock(file);
206
	return au_fi(file)->fi_bend;
207
}
208
209
static inline struct au_vdir *au_fvdir_cache(struct file *file)
210
{
211
	FiMustAnyLock(file);
212
	return au_fi(file)->fi_vdir_cache;
213
}
214
215
static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
216
{
217
	FiMustWriteLock(file);
218
	AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex);
219
	au_fi(file)->fi_bstart = bindex;
220
}
221
222
static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
223
{
224
	FiMustWriteLock(file);
225
	AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex
226
		  || bindex < au_fbstart(file));
227
	au_fi(file)->fi_bend = bindex;
228
}
229
230
static inline void au_set_fvdir_cache(struct file *file,
231
				      struct au_vdir *vdir_cache)
232
{
233
	FiMustWriteLock(file);
234
	AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode)
235
		  || (au_fi(file)->fi_vdir_cache && vdir_cache));
236
	au_fi(file)->fi_vdir_cache = vdir_cache;
237
}
238
239
static inline void au_update_figen(struct file *file)
240
{
241
	atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
242
	//smp_mb(); /* atomic_set */
243
}
244
245
#endif /* __KERNEL__ */
246
#endif /* __AUFS_FILE_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/finfo.c (+185 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * file private data
21
 *
22
 * $Id: finfo.c,v 1.2 2008/04/21 01:35:14 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
struct au_finfo *au_fi(struct file *file)
28
{
29
	struct au_finfo *finfo = file->private_data;
30
	AuDebugOn(!finfo
31
		  || !finfo->fi_hfile
32
		  || (0 < finfo->fi_bend
33
		      && (/* au_sbi(file->f_dentry->d_sb)->si_bend
34
			     < finfo->fi_bend
35
			     || */ finfo->fi_bend < finfo->fi_bstart)));
36
	return finfo;
37
}
38
39
struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex)
40
{
41
	struct au_finfo *finfo = au_fi(file);
42
	struct au_hfile *hf;
43
44
	FiMustAnyLock(file);
45
	AuDebugOn(!finfo
46
		  || finfo->fi_bstart < 0
47
		  || bindex < finfo->fi_bstart
48
		  || finfo->fi_bend < bindex);
49
	hf = finfo->fi_hfile + bindex;
50
	AuDebugOn(hf->hf_br && au_br_count(hf->hf_br) <= 0);
51
	return hf->hf_br;
52
}
53
54
struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
55
{
56
	struct au_finfo *finfo = au_fi(file);
57
	struct au_hfile *hf;
58
59
	FiMustAnyLock(file);
60
	AuDebugOn(!finfo
61
		  || finfo->fi_bstart < 0
62
		  || bindex < finfo->fi_bstart
63
		  || finfo->fi_bend < bindex);
64
	hf = finfo->fi_hfile + bindex;
65
	AuDebugOn(hf->hf_file
66
		  && file_count(hf->hf_file) <= 0
67
		  && au_br_count(hf->hf_br) <= 0);
68
	return hf->hf_file;
69
}
70
71
void au_hfput(struct au_hfile *hf)
72
{
73
	if (hf->hf_file->f_mode & FMODE_EXEC)
74
		au_allow_write_access(hf->hf_file);
75
	fput(hf->hf_file);
76
	hf->hf_file = NULL;
77
	AuDebugOn(!hf->hf_br);
78
	au_br_put(hf->hf_br);
79
	hf->hf_br = NULL;
80
}
81
82
void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
83
{
84
	struct au_finfo *finfo = au_fi(file);
85
	struct au_hfile *hf;
86
87
	FiMustWriteLock(file);
88
	AuDebugOn(!finfo
89
		  || finfo->fi_bstart < 0
90
		  || bindex < finfo->fi_bstart
91
		  || finfo->fi_bend < bindex);
92
	AuDebugOn(val && file_count(val) <= 0);
93
	hf = finfo->fi_hfile + bindex;
94
	AuDebugOn(val && hf->hf_file);
95
	if (hf->hf_file)
96
		au_hfput(hf);
97
	if (val) {
98
		hf->hf_file = val;
99
		hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
100
	}
101
}
102
103
void au_finfo_fin(struct file *file)
104
{
105
	struct au_finfo *finfo;
106
	struct dentry *dentry;
107
	aufs_bindex_t bindex, bend;
108
109
	dentry = file->f_dentry;
110
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
111
	SiMustAnyLock(dentry->d_sb);
112
113
	fi_write_lock(file);
114
	bend = au_fbend(file);
115
	bindex = au_fbstart(file);
116
	if (bindex >= 0)
117
		for (; bindex <= bend; bindex++)
118
			au_set_h_fptr(file, bindex, NULL);
119
120
	finfo = au_fi(file);
121
#ifdef CONFIG_AUFS_DEBUG
122
	if (finfo->fi_bstart >= 0) {
123
		bend = au_fbend(file);
124
		for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
125
			struct au_hfile *hf;
126
			hf = finfo->fi_hfile + bindex;
127
			AuDebugOn(hf->hf_file || hf->hf_br);
128
		}
129
	}
130
#endif
131
132
	kfree(finfo->fi_hfile);
133
	fi_write_unlock(file);
134
	au_cache_free_finfo(finfo);
135
	//file->private_data = NULL;
136
}
137
138
int au_finfo_init(struct file *file)
139
{
140
	struct au_finfo *finfo;
141
	struct dentry *dentry;
142
	union {
143
		void *p;
144
		unsigned long ul;
145
	} u;
146
147
	dentry = file->f_dentry;
148
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
149
	AuDebugOn(!dentry->d_inode);
150
151
	finfo = au_cache_alloc_finfo();
152
	if (finfo) {
153
		finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
154
					  sizeof(*finfo->fi_hfile), GFP_KERNEL);
155
		if (finfo->fi_hfile) {
156
			au_rw_init_wlock(&finfo->fi_rwsem);
157
			finfo->fi_bstart = -1;
158
			finfo->fi_bend = -1;
159
			atomic_set(&finfo->fi_generation, au_digen(dentry));
160
			//smp_mb(); /* atomic_set */
161
162
			/*
163
			 * a dirty trick for handling FMODE_EXEC and
164
			 * deny_write_access().
165
			 * because FMODE_EXEC flag is not passed to
166
			 * f_op->open(),
167
			 * aufs set it to file->private_data temporary in lookup
168
			 * or dentry revalidation operations.
169
			 * restore the flag to f_mode here.
170
			 */
171
			u.p = file->private_data;
172
			if (u.ul & FMODE_EXEC) {
173
				file->f_mode |= FMODE_EXEC;
174
				smp_mb(); /* flush f_mode */
175
			}
176
177
			file->private_data = finfo;
178
			return 0; /* success */
179
		}
180
		au_cache_free_finfo(finfo);
181
	}
182
183
	AuTraceErr(-ENOMEM);
184
	return -ENOMEM;
185
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/f_op.c (+651 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * file and vm operations
21
 *
22
 * $Id: f_op.c,v 1.5 2008/05/19 01:48:04 sfjro Exp $
23
 */
24
25
//#include <linux/fsnotify.h>
26
#include <linux/fs_stack.h>
27
//#include <linux/pagemap.h>
28
#include <linux/poll.h>
29
//#include <linux/security.h>
30
#include "aufs.h"
31
32
/* common function to regular file and dir */
33
int aufs_flush(struct file *file, fl_owner_t id)
34
{
35
	int err;
36
	struct dentry *dentry;
37
	aufs_bindex_t bindex, bend;
38
39
	dentry = file->f_dentry;
40
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
41
42
	// aufs_read_lock_file()
43
	si_noflush_read_lock(dentry->d_sb);
44
	fi_read_lock(file);
45
	di_read_lock_child(dentry, AuLock_IW);
46
47
	err = 0;
48
	bend = au_fbend(file);
49
	for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
50
		struct file *h_file;
51
		h_file = au_h_fptr(file, bindex);
52
		if (h_file && h_file->f_op && h_file->f_op->flush) {
53
			err = h_file->f_op->flush(h_file, id);
54
			if (!err)
55
				au_update_fuse_h_inode
56
					(h_file->f_vfsmnt, h_file->f_dentry);
57
			/*ignore*/
58
		}
59
	}
60
	au_cpup_attr_timesizes(dentry->d_inode);
61
62
	di_read_unlock(dentry, AuLock_IW);
63
	fi_read_unlock(file);
64
	si_read_unlock(dentry->d_sb);
65
	AuTraceErr(err);
66
	return err;
67
}
68
69
/* ---------------------------------------------------------------------- */
70
71
static int do_open_nondir(struct file *file, int flags)
72
{
73
	int err;
74
	aufs_bindex_t bindex;
75
	struct super_block *sb;
76
	struct file *h_file;
77
	struct dentry *dentry;
78
	struct inode *inode;
79
	struct au_finfo *finfo;
80
81
	dentry = file->f_dentry;
82
	LKTRTrace("%.*s, flags 0%o\n", AuDLNPair(dentry), flags);
83
	FiMustWriteLock(file);
84
	inode = dentry->d_inode;
85
	AuDebugOn(!inode || S_ISDIR(inode->i_mode));
86
87
	err = 0;
88
	finfo = au_fi(file);
89
	finfo->fi_h_vm_ops = NULL;
90
	sb = dentry->d_sb;
91
	bindex = au_dbstart(dentry);
92
	AuDebugOn(!au_h_dptr(dentry, bindex)->d_inode);
93
	/* O_TRUNC is processed already */
94
	BUG_ON(au_test_ro(sb, bindex, inode) && (flags & O_TRUNC));
95
96
	h_file = au_h_open(dentry, bindex, flags, file);
97
	//if (LktrCond) {fput(h_file); au_br_put(au_sbr(dentry->d_sb, bindex));
98
	//h_file = ERR_PTR(-1);}
99
	if (!IS_ERR(h_file)) {
100
		au_set_fbstart(file, bindex);
101
		au_set_fbend(file, bindex);
102
		au_set_h_fptr(file, bindex, h_file);
103
		au_update_figen(file);
104
		//file->f_ra = h_file->f_ra; //??
105
		//AuDbgFile(file);
106
		return 0; /* success */
107
	}
108
	err = PTR_ERR(h_file);
109
	AuTraceErr(err);
110
	return err;
111
}
112
113
static int aufs_open_nondir(struct inode *inode, struct file *file)
114
{
115
	return au_do_open(inode, file, do_open_nondir);
116
}
117
118
static int aufs_release_nondir(struct inode *inode, struct file *file)
119
{
120
	struct super_block *sb = file->f_dentry->d_sb;
121
122
	LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
123
124
	si_noflush_read_lock(sb);
125
	au_finfo_fin(file);
126
	si_read_unlock(sb);
127
	return 0;
128
}
129
130
/* ---------------------------------------------------------------------- */
131
132
static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
133
			 loff_t *ppos)
134
{
135
	ssize_t err;
136
	struct dentry *dentry;
137
	struct file *h_file;
138
	struct super_block *sb;
139
	struct inode *h_inode;
140
141
	dentry = file->f_dentry;
142
	LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
143
		  AuDLNPair(dentry), (unsigned long)count, *ppos);
144
	//AuDbgDentry(dentry);
145
146
	sb = dentry->d_sb;
147
	si_read_lock(sb, AuLock_FLUSH);
148
	err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
149
				      /*locked*/0);
150
	//if (LktrCond) {fi_read_unlock(file); err = -1;}
151
	if (unlikely(err))
152
		goto out;
153
154
	/* support LSM and notify */
155
	h_file = au_h_fptr(file, au_fbstart(file));
156
	h_inode = h_file->f_dentry->d_inode;
157
	err = vfsub_read_u(h_file, buf, count, ppos,
158
			   au_opt_test_dlgt(au_mntflags(sb)));
159
	//file->f_ra = h_file->f_ra; //??
160
	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
161
162
	fi_read_unlock(file);
163
 out:
164
	si_read_unlock(sb);
165
	AuTraceErr(err);
166
	return err;
167
}
168
169
static ssize_t aufs_write(struct file *file, const char __user *ubuf,
170
			  size_t count, loff_t *ppos)
171
{
172
	ssize_t err;
173
	struct dentry *dentry, *parent;
174
	struct inode *inode, *dir;
175
	struct super_block *sb;
176
	unsigned int mnt_flags;
177
	struct file *h_file;
178
	char __user *buf = (char __user *)ubuf;
179
	struct au_hin_ignore ign;
180
	struct vfsub_args vargs;
181
182
	dentry = file->f_dentry;
183
	LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
184
		  AuDLNPair(dentry), (unsigned long)count, *ppos);
185
186
	inode = dentry->d_inode;
187
	mutex_lock(&inode->i_mutex);
188
	sb = dentry->d_sb;
189
	si_read_lock(sb, AuLock_FLUSH);
190
	err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
191
				      /*locked*/1);
192
	//if (LktrCond) {fi_write_unlock(file); err = -1;}
193
	if (unlikely(err))
194
		goto out;
195
	err = au_ready_to_write(file, -1);
196
	//if (LktrCond) err = -1;
197
	if (unlikely(err))
198
		goto out_unlock;
199
200
	/* support LSM and notify */
201
	mnt_flags = au_mntflags(sb);
202
	vfsub_args_init(&vargs, &ign, au_opt_test_dlgt(mnt_flags), 0);
203
	h_file = au_h_fptr(file, au_fbstart(file));
204
	if (!au_opt_test(mnt_flags, UDBA_INOTIFY))
205
		err = vfsub_write_u(h_file, buf, count, ppos, &vargs);
206
	else {
207
		parent = dget_parent(dentry);
208
		dir = parent->d_inode;
209
		ii_read_lock_parent(dir);
210
		vfsub_ign_hinode(&vargs, IN_MODIFY,
211
				 au_hi(dir, au_fbstart(file)));
212
		err = vfsub_write_u(h_file, buf, count, ppos, &vargs);
213
		ii_read_unlock(dir);
214
		dput(parent);
215
	}
216
	ii_write_lock_child(inode);
217
	au_cpup_attr_timesizes(inode);
218
	ii_write_unlock(inode);
219
220
 out_unlock:
221
	fi_write_unlock(file);
222
 out:
223
	si_read_unlock(sb);
224
	mutex_unlock(&inode->i_mutex);
225
	AuTraceErr(err);
226
	return err;
227
}
228
229
#ifdef CONFIG_AUFS_SPLICE_PATCH
230
static int au_test_loopback(void)
231
{
232
	const char c = current->comm[4];
233
	/* true if a kernel thread named 'loop[0-9].*' accesses a file */
234
	const int loopback = (current->mm == NULL
235
			      && '0' <= c && c <= '9'
236
			      && strncmp(current->comm, "loop", 4) == 0);
237
	return loopback;
238
}
239
240
static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
241
				struct pipe_inode_info *pipe, size_t len,
242
				unsigned int flags)
243
{
244
	ssize_t err;
245
	struct file *h_file;
246
	struct dentry *dentry;
247
	struct super_block *sb;
248
249
	dentry = file->f_dentry;
250
	LKTRTrace("%.*s, pos %Ld, len %lu\n",
251
		  AuDLNPair(dentry), *ppos, (unsigned long)len);
252
253
	sb = dentry->d_sb;
254
	si_read_lock(sb, AuLock_FLUSH);
255
	err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
256
				      /*locked*/0);
257
	if (unlikely(err))
258
		goto out;
259
260
	err = -EINVAL;
261
	/* support LSM and notify */
262
	h_file = au_h_fptr(file, au_fbstart(file));
263
	if (/* unlikely */(au_test_loopback())) {
264
		file->f_mapping = h_file->f_mapping;
265
		smp_mb(); /* unnecessary? */
266
	}
267
	err = vfsub_splice_to(h_file, ppos, pipe, len, flags,
268
			      au_opt_test_dlgt(au_mntflags(sb)));
269
	//file->f_ra = h_file->f_ra; //??
270
	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
271
	fi_read_unlock(file);
272
273
 out:
274
	si_read_unlock(sb);
275
	AuTraceErr(err);
276
	return err;
277
}
278
279
static ssize_t
280
aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
281
		  size_t len, unsigned int flags)
282
{
283
	ssize_t err;
284
	struct dentry *dentry;
285
	struct inode *inode, *h_inode;
286
	struct super_block *sb;
287
	struct file *h_file;
288
	struct au_hin_ignore ign;
289
	struct vfsub_args vargs;
290
	unsigned int mnt_flags;
291
292
	dentry = file->f_dentry;
293
	LKTRTrace("%.*s, len %lu, pos %Ld\n",
294
		  AuDLNPair(dentry), (unsigned long)len, *ppos);
295
296
	inode = dentry->d_inode;
297
	mutex_lock(&inode->i_mutex);
298
	sb = dentry->d_sb;
299
	si_read_lock(sb, AuLock_FLUSH);
300
	err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
301
				      /*locked*/1);
302
	//if (LktrCond) {fi_write_unlock(file); err = -1;}
303
	if (unlikely(err))
304
		goto out;
305
	err = au_ready_to_write(file, -1);
306
	//if (LktrCond) err = -1;
307
	if (unlikely(err))
308
		goto out_unlock;
309
310
	/* support LSM and notify */
311
	mnt_flags = au_mntflags(sb);
312
	vfsub_args_init(&vargs, &ign, au_opt_test_dlgt(mnt_flags), 0);
313
	h_file = au_h_fptr(file, au_fbstart(file));
314
	h_inode = h_file->f_dentry->d_inode;
315
	/* current vfs_splice_from() doesn't fire up the inotify event */
316
	if (1 || !au_opt_test(mnt_flags, UDBA_INOTIFY))
317
		err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs);
318
	else {
319
		//struct dentry *parent = dget_parent(dentry);
320
		//vfsub_ign_hinode(&vargs, IN_MODIFY,
321
		//au_hi(parent->d_inode, au_fbstart(file));
322
		err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs);
323
		//dput(parent);
324
	}
325
	ii_write_lock_child(inode);
326
	au_cpup_attr_timesizes(inode);
327
	ii_write_unlock(inode);
328
329
 out_unlock:
330
	fi_write_unlock(file);
331
 out:
332
	si_read_unlock(sb);
333
	mutex_unlock(&inode->i_mutex);
334
	AuTraceErr(err);
335
	return err;
336
}
337
#endif /* CONFIG_AUFS_SPLICE_PATCH */
338
339
/* ---------------------------------------------------------------------- */
340
341
static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
342
{
343
	int err;
344
	struct dentry *dentry;
345
	struct file *file, *h_file;
346
	struct inode *inode;
347
	static DECLARE_WAIT_QUEUE_HEAD(wq);
348
	struct au_finfo *finfo;
349
	//struct page *page;
350
351
	AuTraceEnter();
352
	AuDebugOn(!vma || !vma->vm_file);
353
	//todo: non-robr mode, user vm_file as it is.
354
	wait_event(wq, (file = au_robr_safe_file(vma)));
355
	AuDebugOn(!au_test_aufs(file->f_dentry->d_sb));
356
	dentry = file->f_dentry;
357
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
358
	inode = dentry->d_inode;
359
	AuDebugOn(!S_ISREG(inode->i_mode));
360
361
	/* do not revalidate, nor si lock */
362
	finfo = au_fi(file);
363
	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
364
	AuDebugOn(!h_file || !au_test_mmapped(file));
365
	fi_write_lock(file);
366
	vma->vm_file = h_file;
367
	err = finfo->fi_h_vm_ops->fault(vma, vmf);
368
	//file->f_ra = h_file->f_ra; //??
369
	au_robr_reset_file(vma, file);
370
	fi_write_unlock(file);
371
	wake_up(&wq);
372
373
	if (!(err & VM_FAULT_ERROR)) {
374
		//page->mapping = file->f_mapping;
375
		//get_page(page);
376
		//file->f_mapping = h_file->f_mapping;
377
		//touch_atime(NULL, dentry);
378
		//inode->i_atime = h_file->f_dentry->d_inode->i_atime;
379
	}
380
	AuTraceErr(err);
381
	//AuDbg("err %d\n", err);
382
	return err;
383
}
384
385
static struct vm_operations_struct aufs_vm_ops = {
386
	//.open		= aufs_vmaopen,
387
	//.close		= aufs_vmaclose,
388
	.fault		= aufs_fault,
389
};
390
391
/* ---------------------------------------------------------------------- */
392
393
static struct vm_operations_struct *au_vm_ops(struct file *h_file,
394
					      struct vm_area_struct *vma)
395
{
396
	struct vm_operations_struct *vm_ops;
397
	int err;
398
399
	AuTraceEnter();
400
401
	if (!au_test_nfs(h_file->f_vfsmnt->mnt_sb))
402
		err = h_file->f_op->mmap(h_file, vma);
403
	else {
404
		lockdep_off();
405
		err = h_file->f_op->mmap(h_file, vma);
406
		lockdep_on();
407
	}
408
	vm_ops = ERR_PTR(err);
409
	if (unlikely(err))
410
		goto out;
411
	vm_ops = vma->vm_ops;
412
	err = do_munmap(current->mm, vma->vm_start,
413
			vma->vm_end - vma->vm_start);
414
	if (unlikely(err)) {
415
		AuIOErr("failed internal unmapping %.*s, %d\n",
416
			AuDLNPair(h_file->f_dentry), err);
417
		vm_ops = ERR_PTR(-EIO);
418
	}
419
420
 out:
421
	AuTraceErrPtr(vm_ops);
422
	return vm_ops;
423
}
424
425
static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
426
{
427
	int err, wlock, mmapped;
428
	struct dentry *dentry;
429
	struct super_block *sb;
430
	struct file *h_file;
431
	struct vm_operations_struct *vm_ops;
432
433
	dentry = file->f_dentry;
434
	LKTRTrace("%.*s, %lx, len %lu\n",
435
		  AuDLNPair(dentry), vma->vm_start,
436
		  vma->vm_end - vma->vm_start);
437
	AuDebugOn(!S_ISREG(dentry->d_inode->i_mode));
438
	AuDebugOn(down_write_trylock(&vma->vm_mm->mmap_sem));
439
440
	mmapped = au_test_mmapped(file); /* can be harmless race condition */
441
	wlock = !!(file->f_mode & FMODE_WRITE);
442
	sb = dentry->d_sb;
443
	si_read_lock(sb, AuLock_FLUSH);
444
	err = au_reval_and_lock_finfo(file, au_reopen_nondir,
445
				      wlock | !mmapped, /*locked*/0);
446
	//err = -1;
447
	if (unlikely(err))
448
		goto out;
449
450
	if (wlock) {
451
		err = au_ready_to_write(file, -1);
452
		//err = -1;
453
		if (unlikely(err))
454
			goto out_unlock;
455
	}
456
457
	h_file = au_h_fptr(file, au_fbstart(file));
458
	if (unlikely(au_test_fuse(h_file->f_dentry->d_sb))) {
459
		/*
460
		 * by this assignment, f_mapping will differs from aufs inode
461
		 * i_mapping.
462
		 * if someone else mixes the use of f_dentry->d_inode and
463
		 * f_mapping->host, then a problem may arise.
464
		 */
465
		file->f_mapping = h_file->f_mapping;
466
	}
467
468
	if (0 && h_file->f_op->mmap == generic_file_mmap) {
469
		err = generic_file_mmap(file, vma); /* instead of h_file */
470
		if (unlikely(err))
471
			goto out_unlock;
472
		au_fi(file)->fi_h_vm_ops = vma->vm_ops;
473
	} else {
474
		vm_ops = NULL;
475
		if (!mmapped) {
476
			vm_ops = au_vm_ops(h_file, vma);
477
			err = PTR_ERR(vm_ops);
478
			if (IS_ERR(vm_ops))
479
				goto out_unlock;
480
		}
481
482
		err = generic_file_mmap(file, vma);
483
		if (unlikely(err))
484
			goto out_unlock;
485
		vma->vm_ops = &aufs_vm_ops;
486
		/* test again */
487
		if (!au_test_mmapped(file)) {
488
			FiMustWriteLock(file);
489
			au_fi(file)->fi_h_vm_ops = vm_ops;
490
		}
491
	}
492
493
	file_accessed(h_file);
494
	au_update_fuse_h_inode(h_file->f_vfsmnt, h_file->f_dentry); /*ignore*/
495
	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
496
497
 out_unlock:
498
	if (!wlock && mmapped)
499
		fi_read_unlock(file);
500
	else
501
		fi_write_unlock(file);
502
 out:
503
	si_read_unlock(sb);
504
	AuTraceErr(err);
505
	return err;
506
}
507
508
/* ---------------------------------------------------------------------- */
509
510
static unsigned int aufs_poll(struct file *file, poll_table *wait)
511
{
512
	unsigned int mask;
513
	struct file *h_file;
514
	int err;
515
	struct dentry *dentry;
516
	struct super_block *sb;
517
518
	dentry = file->f_dentry;
519
	LKTRTrace("%.*s, wait %p\n", AuDLNPair(dentry), wait);
520
	AuDebugOn(S_ISDIR(dentry->d_inode->i_mode));
521
522
	/* We should pretend an error happened. */
523
	mask = POLLERR /* | POLLIN | POLLOUT */;
524
	sb = dentry->d_sb;
525
	si_read_lock(sb, AuLock_FLUSH);
526
	err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
527
				      /*locked*/0);
528
	//err = -1;
529
	if (unlikely(err))
530
		goto out;
531
532
	/* it is not an error of hidden_file has no operation */
533
	mask = DEFAULT_POLLMASK;
534
	h_file = au_h_fptr(file, au_fbstart(file));
535
	if (h_file->f_op && h_file->f_op->poll)
536
		mask = h_file->f_op->poll(h_file, wait);
537
	fi_read_unlock(file);
538
539
 out:
540
	si_read_unlock(sb);
541
	AuTraceErr((int)mask);
542
	return mask;
543
}
544
545
static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
546
			     int datasync)
547
{
548
	int err;
549
	struct inode *inode;
550
	struct file *h_file;
551
	struct super_block *sb;
552
553
	LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync);
554
	inode = dentry->d_inode;
555
556
	IMustLock(file->f_mapping->host);
557
	if (unlikely(inode != file->f_mapping->host)) {
558
		mutex_unlock(&file->f_mapping->host->i_mutex);
559
		mutex_lock(&inode->i_mutex);
560
	}
561
	IMustLock(inode);
562
563
	sb = dentry->d_sb;
564
	si_read_lock(sb, AuLock_FLUSH);
565
	err = 0; //-EBADF; // posix?
566
	if (unlikely(!(file->f_mode & FMODE_WRITE)))
567
		goto out;
568
	err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
569
				      /*locked*/1);
570
	//err = -1;
571
	if (unlikely(err))
572
		goto out;
573
	err = au_ready_to_write(file, -1);
574
	//err = -1;
575
	if (unlikely(err))
576
		goto out_unlock;
577
578
	err = -EINVAL;
579
	h_file = au_h_fptr(file, au_fbstart(file));
580
	if (h_file->f_op && h_file->f_op->fsync) {
581
		ii_write_lock_child(inode);
582
		mutex_lock_nested(&h_file->f_dentry->d_inode->i_mutex,
583
				  AuLsc_I_CHILD);
584
		err = h_file->f_op->fsync(h_file, h_file->f_dentry, datasync);
585
		//err = -1;
586
		if (!err)
587
			au_update_fuse_h_inode(h_file->f_vfsmnt,
588
					       h_file->f_dentry);
589
		au_cpup_attr_timesizes(inode);
590
		mutex_unlock(&h_file->f_dentry->d_inode->i_mutex);
591
		ii_write_unlock(inode);
592
	}
593
594
 out_unlock:
595
	fi_write_unlock(file);
596
 out:
597
	si_read_unlock(sb);
598
	if (unlikely(inode != file->f_mapping->host)) {
599
		mutex_unlock(&inode->i_mutex);
600
		mutex_lock(&file->f_mapping->host->i_mutex);
601
	}
602
	AuTraceErr(err);
603
	return err;
604
}
605
606
static int aufs_fasync(int fd, struct file *file, int flag)
607
{
608
	int err;
609
	struct file *h_file;
610
	struct dentry *dentry;
611
	struct super_block *sb;
612
613
	dentry = file->f_dentry;
614
	LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), flag);
615
616
	sb = dentry->d_sb;
617
	si_read_lock(sb, AuLock_FLUSH);
618
	err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
619
				      /*locked*/0);
620
	//err = -1;
621
	if (unlikely(err))
622
		goto out;
623
624
	h_file = au_h_fptr(file, au_fbstart(file));
625
	if (h_file->f_op && h_file->f_op->fasync)
626
		err = h_file->f_op->fasync(fd, h_file, flag);
627
	fi_read_unlock(file);
628
629
 out:
630
	si_read_unlock(sb);
631
	AuTraceErr(err);
632
	return err;
633
}
634
635
/* ---------------------------------------------------------------------- */
636
637
struct file_operations aufs_file_fop = {
638
	.read		= aufs_read,
639
	.write		= aufs_write,
640
	.poll		= aufs_poll,
641
	.mmap		= aufs_mmap,
642
	.open		= aufs_open_nondir,
643
	.flush		= aufs_flush,
644
	.release	= aufs_release_nondir,
645
	.fsync		= aufs_fsync_nondir,
646
	.fasync		= aufs_fasync,
647
#ifdef CONFIG_AUFS_SPLICE_PATCH
648
	.splice_write	= aufs_splice_write,
649
	.splice_read	= aufs_splice_read,
650
#endif
651
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/hinode.h (+188 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * lower (branch filesystem) inode and setting inotify
21
 *
22
 * $Id: hinode.h,v 1.3 2008/04/28 03:08:37 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_HINODE_H__
26
#define __AUFS_HINODE_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/inotify.h>
32
#include <linux/aufs_type.h>
33
//#include "branch.h"
34
//#include "inode.h"
35
#include "super.h"
36
#include "vfsub.h"
37
38
/* ---------------------------------------------------------------------- */
39
40
struct au_hinotify {
41
#ifdef CONFIG_AUFS_HINOTIFY
42
	struct inotify_watch	hin_watch;
43
	struct inode		*hin_aufs_inode;	/* no get/put */
44
45
	/* an array of atomic_t X au_hin_nignore */
46
	atomic_t		hin_ignore[0];
47
#endif
48
};
49
50
struct au_hinode {
51
	struct inode		*hi_inode;
52
	aufs_bindex_t		hi_id;
53
#ifdef CONFIG_AUFS_HINOTIFY
54
	struct au_hinotify	*hi_notify;
55
#endif
56
57
	/* reference to the copied-up whiteout with get/put */
58
	struct dentry		*hi_whdentry;
59
};
60
61
struct au_hin_ignore {
62
#ifdef CONFIG_AUFS_HINOTIFY
63
	__u32			ign_events;
64
	struct au_hinode	*ign_hinode;
65
#endif
66
};
67
68
/* ---------------------------------------------------------------------- */
69
70
#ifdef CONFIG_AUFS_HINOTIFY
71
static inline
72
void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
73
{
74
	hinode->hi_notify = val;
75
}
76
77
/* hinotify.c */
78
int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
79
		 struct inode *h_inode);
80
void au_hin_free(struct au_hinode *hinode);
81
void au_do_hdir_lock(struct inode *h_dir, struct inode *dir,
82
		     aufs_bindex_t bindex, unsigned int lsc);
83
void au_hdir_unlock(struct inode *h_dir, struct inode *dir,
84
		    aufs_bindex_t bindex);
85
struct dentry *au_hdir_lock_rename(struct dentry **h_parents,
86
				   struct inode **dirs, aufs_bindex_t bindex,
87
				   int issamedir);
88
void au_hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
89
			   aufs_bindex_t bindex, int issamedir);
90
void au_reset_hinotify(struct inode *inode, unsigned int flags);
91
92
void au_hin_ignore(struct au_hinode *hinode, __u32 events);
93
void au_hin_unignore(struct au_hinode *hinode, __u32 events);
94
95
int __init au_inotify_init(void);
96
void au_inotify_fin(void);
97
98
#else
99
100
static inline
101
void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
102
{
103
	/* empty */
104
}
105
106
static inline
107
int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
108
		 struct inode *h_inode)
109
{
110
	return -EOPNOTSUPP;
111
}
112
113
static inline void au_hin_free(struct au_hinode *hinode)
114
{
115
	/* nothing */
116
}
117
118
static inline
119
void au_do_hdir_lock(struct inode *h_dir, struct inode *dir,
120
		     aufs_bindex_t bindex, unsigned int lsc)
121
{
122
	mutex_lock_nested(&h_dir->i_mutex, lsc);
123
}
124
125
static inline
126
void au_hdir_unlock(struct inode *h_dir, struct inode *dir,
127
		    aufs_bindex_t bindex)
128
{
129
	mutex_unlock(&h_dir->i_mutex);
130
}
131
132
static inline
133
struct dentry *au_hdir_lock_rename(struct dentry **h_parents,
134
				   struct inode **dirs, aufs_bindex_t bindex,
135
				   int issamedir)
136
{
137
	return vfsub_lock_rename(h_parents[0], h_parents[1]);
138
}
139
140
static inline
141
void au_hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
142
			   aufs_bindex_t bindex, int issamedir)
143
{
144
	vfsub_unlock_rename(h_parents[0], h_parents[1]);
145
}
146
147
static inline void au_reset_hinotify(struct inode *inode, unsigned int flags)
148
{
149
	/* nothing */
150
}
151
152
static inline void au_hin_ignore(struct au_hinotify *hinotify, __u32 events)
153
{
154
	/* nothing */
155
}
156
157
static inline void au_hin_unignore(struct au_hinotify *hinotify, __u32 events)
158
{
159
	/* nothing */
160
}
161
162
static inline int au_inotify_init(void)
163
{
164
	return 0;
165
}
166
167
#define au_inotify_fin()	do {} while (0)
168
#endif /* CONFIG_AUFS_HINOTIFY */
169
170
/* ---------------------------------------------------------------------- */
171
172
/*
173
 * au_hdir_lock, au_hdir2_lock
174
 */
175
#define AuLockFunc(name, lsc) \
176
static inline \
177
void name##_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex) \
178
{ au_do_hdir_lock(h_dir, dir, bindex, AuLsc_I_##lsc); }
179
180
AuLockFunc(au_hdir, PARENT);
181
AuLockFunc(au_hdir2, PARENT2);
182
183
#undef AuLockFunc
184
185
/* ---------------------------------------------------------------------- */
186
187
#endif /* __KERNEL__ */
188
#endif /* __AUFS_HINODE_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/hin_or_dlgt.c (+708 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 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
 * sub-routines for vfs in hinotify or dlgt mode
21
 *
22
 * $Id: hin_or_dlgt.c,v 1.2 2008/04/21 02:00:37 sfjro Exp $
23
 */
24
// I'm going to slightly mad
25
26
#include <linux/uaccess.h>
27
#include "aufs.h"
28
29
#if !defined(CONFIG_AUFS_HINOTIFY) && !defined(CONFIG_AUFS_DLGT)
30
#error mis-configuraion or Makefile
31
#endif
32
33
/* ---------------------------------------------------------------------- */
34
35
struct permission_args {
36
	int *errp;
37
	struct inode *inode;
38
	int mask;
39
	struct nameidata *nd;
40
};
41
42
static void call_permission(void *args)
43
{
44
	struct permission_args *a = args;
45
	*a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
46
}
47
48
int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
49
		     int dlgt)
50
{
51
	if (!dlgt)
52
		return do_vfsub_permission(inode, mask, nd);
53
	else {
54
		int err, wkq_err;
55
		struct permission_args args = {
56
			.errp	= &err,
57
			.inode	= inode,
58
			.mask	= mask,
59
			.nd	= nd
60
		};
61
		wkq_err = au_wkq_wait(call_permission, &args, /*dlgt*/1);
62
		if (unlikely(wkq_err))
63
			err = wkq_err;
64
		return err;
65
	}
66
}
67
68
/* ---------------------------------------------------------------------- */
69
70
struct create_args {
71
	int *errp;
72
	struct inode *dir;
73
	struct dentry *dentry;
74
	int mode;
75
	struct nameidata *nd;
76
};
77
78
static void call_create(void *args)
79
{
80
	struct create_args *a = args;
81
	*a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
82
}
83
84
int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
85
		 struct nameidata *nd, int dlgt)
86
{
87
	if (!dlgt)
88
		return do_vfsub_create(dir, dentry, mode, nd);
89
	else {
90
		int err, wkq_err;
91
		struct create_args args = {
92
			.errp	= &err,
93
			.dir	= dir,
94
			.dentry	= dentry,
95
			.mode	= mode,
96
			.nd	= nd
97
		};
98
		wkq_err = au_wkq_wait(call_create, &args, /*dlgt*/1);
99
		if (unlikely(wkq_err))
100
			err = wkq_err;
101
		return err;
102
	}
103
}
104
105
struct symlink_args {
106
	int *errp;
107
	struct inode *dir;
108
	struct dentry *dentry;
109
	const char *symname;
110
	int mode;
111
};
112
113
static void call_symlink(void *args)
114
{
115
	struct symlink_args *a = args;
116
	*a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
117
}
118
119
int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
120
		  int mode, int dlgt)
121
{
122
	if (!dlgt)
123
		return do_vfsub_symlink(dir, dentry, symname, mode);
124
	else {
125
		int err, wkq_err;
126
		struct symlink_args args = {
127
			.errp		= &err,
128
			.dir		= dir,
129
			.dentry		= dentry,
130
			.symname	= symname,
131
			.mode		= mode
132
		};
133
		wkq_err = au_wkq_wait(call_symlink, &args, /*dlgt*/1);
134
		if (unlikely(wkq_err))
135
			err = wkq_err;
136
		return err;
137
	}
138
}
139
140
struct mknod_args {
141
	int *errp;
142
	struct inode *dir;
143
	struct dentry *dentry;
144
	int mode;
145
	dev_t dev;
146
};
147
148
static void call_mknod(void *args)
149
{
150
	struct mknod_args *a = args;
151
	*a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
152
}
153
154
int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
155
		int dlgt)
156
{
157
	if (!dlgt)
158
		return do_vfsub_mknod(dir, dentry, mode, dev);
159
	else {
160
		int err, wkq_err;
161
		struct mknod_args args = {
162
			.errp	= &err,
163
			.dir	= dir,
164
			.dentry	= dentry,
165
			.mode	= mode,
166
			.dev	= dev
167
		};
168
		wkq_err = au_wkq_wait(call_mknod, &args, /*dlgt*/1);
169
		if (unlikely(wkq_err))
170
			err = wkq_err;
171
		return err;
172
	}
173
}
174
175
struct mkdir_args {
176
	int *errp;
177
	struct inode *dir;
178
	struct dentry *dentry;
179
	int mode;
180
};
181
182
static void call_mkdir(void *args)
183
{
184
	struct mkdir_args *a = args;
185
	*a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
186
}
187
188
int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt)
189
{
190
	if (!dlgt)
191
		return do_vfsub_mkdir(dir, dentry, mode);
192
	else {
193
		int err, wkq_err;
194
		struct mkdir_args args = {
195
			.errp	= &err,
196
			.dir	= dir,
197
			.dentry	= dentry,
198
			.mode	= mode
199
		};
200
		wkq_err = au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
201
		if (unlikely(wkq_err))
202
			err = wkq_err;
203
		return err;
204
	}
205
}
206
207
/* ---------------------------------------------------------------------- */
208
209
struct link_args {
210
	int *errp;
211
	struct inode *dir;
212
	struct dentry *src_dentry, *dentry;
213
};
214
215
static void call_link(void *args)
216
{
217
	struct link_args *a = args;
218
	*a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
219
}
220
221
int vfsub_link(struct dentry *src_dentry, struct inode *dir,
222
	       struct dentry *dentry, int dlgt)
223
{
224
	if (!dlgt)
225
		return do_vfsub_link(src_dentry, dir, dentry);
226
	else {
227
		int err, wkq_err;
228
		struct link_args args = {
229
			.errp		= &err,
230
			.src_dentry	= src_dentry,
231
			.dir		= dir,
232
			.dentry		= dentry
233
		};
234
		wkq_err = au_wkq_wait(call_link, &args, /*dlgt*/1);
235
		if (unlikely(wkq_err))
236
			err = wkq_err;
237
		return err;
238
	}
239
}
240
241
struct rename_args {
242
	int *errp;
243
	struct inode *src_dir, *dir;
244
	struct dentry *src_dentry, *dentry;
245
	struct vfsub_args *vargs;
246
};
247
248
static void call_rename(void *args)
249
{
250
	struct rename_args *a = args;
251
	vfsub_ignore(a->vargs);
252
	*a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
253
				   a->dentry);
254
	if (unlikely(*a->errp))
255
		vfsub_unignore(a->vargs);
256
}
257
258
int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
259
		 struct inode *dir, struct dentry *dentry,
260
		 struct vfsub_args *vargs)
261
{
262
	int err;
263
264
	if (!vfsub_ftest(vargs->flags, DLGT)) {
265
		vfsub_ignore(vargs);
266
		err = do_vfsub_rename(src_dir, src_dentry, dir, dentry);
267
		if (unlikely(err))
268
			vfsub_unignore(vargs);
269
	} else {
270
		int wkq_err;
271
		struct rename_args args = {
272
			.errp		= &err,
273
			.src_dir	= src_dir,
274
			.src_dentry	= src_dentry,
275
			.dir		= dir,
276
			.dentry		= dentry,
277
			.vargs		= vargs
278
		};
279
		wkq_err = au_wkq_wait(call_rename, &args, /*dlgt*/1);
280
		if (unlikely(wkq_err))
281
			err = wkq_err;
282
	}
283
	return err;
284
}
285
286
struct rmdir_args {
287
	int *errp;
288
	struct inode *dir;
289
	struct dentry *dentry;
290
	struct vfsub_args *vargs;
291
};
292
293
static void call_rmdir(void *args)
294
{
295
	struct rmdir_args *a = args;
296
	vfsub_ignore(a->vargs);
297
	*a->errp = do_vfsub_rmdir(a->dir, a->dentry);
298
	if (unlikely(*a->errp))
299
		vfsub_unignore(a->vargs);
300
}
301
302
int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
303
		struct vfsub_args *vargs)
304
{
305
	int err;
306
307
	if (!vfsub_ftest(vargs->flags, DLGT)) {
308
		vfsub_ignore(vargs);
309
		err = do_vfsub_rmdir(dir, dentry);
310
		if (unlikely(err))
311
			vfsub_unignore(vargs);
312
	} else {
313
		int wkq_err;
314
		struct rmdir_args args = {
315
			.errp	= &err,
316
			.dir	= dir,
317
			.dentry	= dentry,
318
			.vargs	= vargs
319
		};
320
		wkq_err = au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
321
		if (unlikely(wkq_err))
322
			err = wkq_err;
323
	}
324
	return err;
325
}
326
327
/* ---------------------------------------------------------------------- */
328
329
struct read_args {
330
	ssize_t *errp;
331
	struct file *file;
332
	union {
333
		void *kbuf;
334
		char __user *ubuf;
335
	};
336
	size_t count;
337
	loff_t *ppos;
338
};
339
340
static void call_read_k(void *args)
341
{
342
	struct read_args *a = args;
343
	LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
344
		  AuDLNPair(a->file->f_dentry), (unsigned long)a->count,
345
		  *a->ppos);
346
	*a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
347
}
348
349
ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
350
		     loff_t *ppos, int dlgt)
351
{
352
	if (!dlgt)
353
		return do_vfsub_read_u(file, ubuf, count, ppos);
354
	else {
355
		int wkq_err;
356
		ssize_t err, read;
357
		struct read_args args = {
358
			.errp	= &err,
359
			.file	= file,
360
			.count	= count,
361
			.ppos	= ppos
362
		};
363
364
		if (unlikely(!count))
365
			return 0;
366
367
		/*
368
		 * workaround an application bug.
369
		 * generally, read(2) or write(2) may return the value shorter
370
		 * than requested. But many applications don't support it,
371
		 * for example bash.
372
		 */
373
		err = -ENOMEM;
374
		if (args.count > PAGE_SIZE)
375
			args.count = PAGE_SIZE;
376
		args.kbuf = kmalloc(args.count, GFP_TEMPORARY);
377
		if (unlikely(!args.kbuf))
378
			goto out;
379
380
		read = 0;
381
		do {
382
			wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
383
			if (unlikely(wkq_err))
384
				err = wkq_err;
385
			if (unlikely(err > 0
386
				     && copy_to_user(ubuf, args.kbuf, err))) {
387
				err = -EFAULT;
388
				goto out_free;
389
			} else if (!err)
390
				break;
391
			else if (unlikely(err < 0))
392
				goto out_free;
393
			count -= err;
394
			/* do not read too much because of file i/o pointer */
395
			if (count < args.count)
396
				args.count = count;
397
			ubuf += err;
398
			read += err;
399
		} while (count);
400
		smp_mb(); /* flush ubuf */
401
		err = read;
402
403
	out_free:
404
		kfree(args.kbuf);
405
	out:
406
		return err;
407
	}
408
}
409
410
ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
411
		     int dlgt)
412
{
413
	if (!dlgt)
414
		return do_vfsub_read_k(file, kbuf, count, ppos);
415
	else {
416
		ssize_t err;
417
		int wkq_err;
418
		struct read_args args = {
419
			.errp	= &err,
420
			.file	= file,
421
			.count	= count,
422
			.ppos	= ppos
423
		};
424
		args.kbuf = kbuf;
425
		wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
426
		if (unlikely(wkq_err))
427
			err = wkq_err;
428
		return err;
429
	}
430
}
431
432
struct write_args {
433
	ssize_t *errp;
434
	struct file *file;
435
	union {
436
		void *kbuf;
437
		const char __user *ubuf;
438
	};
439
	void *buf;
440
	size_t count;
441
	loff_t *ppos;
442
	struct vfsub_args *vargs;
443
};
444
445
static void call_write_k(void *args)
446
{
447
	struct write_args *a = args;
448
	LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
449
		  AuDLNPair(a->file->f_dentry), (unsigned long)a->count,
450
		  *a->ppos);
451
	vfsub_ignore(a->vargs);
452
	*a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
453
	if (unlikely(*a->errp < 0))
454
		vfsub_unignore(a->vargs);
455
}
456
457
ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
458
		      loff_t *ppos, struct vfsub_args *vargs)
459
{
460
	ssize_t err;
461
462
	if (!vfsub_ftest(vargs->flags, DLGT)) {
463
		vfsub_ignore(vargs);
464
		err = do_vfsub_write_u(file, ubuf, count, ppos);
465
		if (unlikely(err < 0))
466
			vfsub_unignore(vargs);
467
	} else {
468
		ssize_t written;
469
		int wkq_err;
470
		struct write_args args = {
471
			.errp	= &err,
472
			.file	= file,
473
			.count	= count,
474
			.ppos	= ppos,
475
			.vargs	= vargs
476
		};
477
478
		if (unlikely(!count))
479
			return 0;
480
481
		/*
482
		 * workaround an application bug.
483
		 * generally, read(2) or write(2) may return the value shorter
484
		 * than requested. But many applications don't support it,
485
		 * for example bash.
486
		 */
487
		err = -ENOMEM;
488
		if (args.count > PAGE_SIZE)
489
			args.count = PAGE_SIZE;
490
		args.kbuf = kmalloc(args.count, GFP_TEMPORARY);
491
		if (unlikely(!args.kbuf))
492
			goto out;
493
494
		written = 0;
495
		do {
496
			if (unlikely(copy_from_user(args.kbuf, ubuf,
497
						    args.count))) {
498
				err = -EFAULT;
499
				goto out_free;
500
			}
501
502
			wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
503
			if (unlikely(wkq_err))
504
				err = wkq_err;
505
			if (err > 0) {
506
				count -= err;
507
				if (count < args.count)
508
					args.count = count;
509
				ubuf += err;
510
				written += err;
511
			} else if (!err)
512
				break;
513
			else if (unlikely(err < 0))
514
				goto out_free;
515
		} while (count);
516
		err = written;
517
518
	out_free:
519
		kfree(args.kbuf);
520
	}
521
 out:
522
	return err;
523
}
524
525
ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
526
		      struct vfsub_args *vargs)
527
{
528
	ssize_t err;
529
530
	if (!vfsub_ftest(vargs->flags, DLGT)) {
531
		vfsub_ignore(vargs);
532
		err = do_vfsub_write_k(file, kbuf, count, ppos);
533
		if (unlikely(err < 0))
534
			vfsub_unignore(vargs);
535
	} else {
536
		int wkq_err;
537
		struct write_args args = {
538
			.errp	= &err,
539
			.file	= file,
540
			.count	= count,
541
			.ppos	= ppos,
542
			.vargs	= vargs
543
		};
544
		args.kbuf = kbuf;
545
		wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
546
		if (unlikely(wkq_err))
547
			err = wkq_err;
548
	}
549
	return err;
550
}
551
552
struct readdir_args {
553
	int *errp;
554
	struct file *file;
555
	filldir_t filldir;
556
	void *arg;
557
};
558
559
static void call_readdir(void *args)
560
{
561
	struct readdir_args *a = args;
562
	*a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
563
}
564
565
int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
566
{
567
	if (!dlgt)
568
		return do_vfsub_readdir(file, filldir, arg);
569
	else {
570
		int err, wkq_err;
571
		struct readdir_args args = {
572
			.errp		= &err,
573
			.file		= file,
574
			.filldir	= filldir,
575
			.arg		= arg
576
		};
577
		wkq_err = au_wkq_wait(call_readdir, &args, /*dlgt*/1);
578
		if (unlikely(wkq_err))
579
			err = wkq_err;
580
		return err;
581
	}
582
}
583
584
/* ---------------------------------------------------------------------- */
585
586
struct splice_to_args {
587
	long *errp;
588
	struct file *in;
589
	loff_t *ppos;
590
	struct pipe_inode_info *pipe;
591
	size_t len;
592
	unsigned int flags;
593
};
594
595
static void call_splice_to(void *args)
596
{
597
	struct splice_to_args *a = args;
598
	*a->errp = do_vfsub_splice_to(a->in, a->ppos, a->pipe, a->len,
599
				      a->flags);
600
}
601
602
long vfsub_splice_to(struct file *in, loff_t *ppos,
603
		     struct pipe_inode_info *pipe, size_t len,
604
		     unsigned int flags, int dlgt)
605
{
606
	if (!dlgt)
607
		return do_vfsub_splice_to(in, ppos, pipe, len, flags);
608
	else {
609
		long err;
610
		int wkq_err;
611
		struct splice_to_args args = {
612
			.errp	= &err,
613
			.in	= in,
614
			.ppos	= ppos,
615
			.pipe	= pipe,
616
			.len	= len,
617
			.flags	= flags
618
		};
619
		wkq_err = au_wkq_wait(call_splice_to, &args, /*dlgt*/1);
620
		if (unlikely(wkq_err))
621
			err = wkq_err;
622
		return err;
623
	}
624
}
625
626
struct splice_from_args {
627
	long *errp;
628
	struct pipe_inode_info *pipe;
629
	struct file *out;
630
	loff_t *ppos;
631
	size_t len;
632
	unsigned int flags;
633
	struct vfsub_args *vargs;
634
};
635
636
static void call_splice_from(void *args)
637
{
638
	struct splice_from_args *a = args;
639
	vfsub_ignore(a->vargs);
640
	*a->errp = do_vfsub_splice_from(a->pipe, a->out, a->ppos, a->len,
641
					a->flags);
642
	if (unlikely(*a->errp < 0))
643
		vfsub_unignore(a->vargs);
644
}
645
646
long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
647
		       loff_t *ppos, size_t len, unsigned int flags,
648
		       struct vfsub_args *vargs)
649
{
650
	long err;
651
652
	if (!vfsub_ftest(vargs->flags, DLGT)) {
653
		vfsub_ignore(vargs);
654
		err = do_vfsub_splice_from(pipe, out, ppos, len, flags);
655
		if (unlikely(err < 0))
656
			vfsub_unignore(vargs);
657
	} else {
658
		int wkq_err;
659
		struct splice_from_args args = {
660
			.errp	= &err,
661
			.pipe	= pipe,
662
			.out	= out,
663
			.ppos	= ppos,
664
			.len	= len,
665
			.flags	= flags,
666
			.vargs	= vargs
667
		};
668
		wkq_err = au_wkq_wait(call_splice_from, &args, /*dlgt*/1);
669
		if (unlikely(wkq_err))
670
			err = wkq_err;
671
	}
672
	return err;
673
}
674
675
/* ---------------------------------------------------------------------- */
676
677
struct getattr_args {
678
	int *errp;
679
	struct vfsmount *mnt;
680
	struct dentry *dentry;
681
	struct kstat *st;
682
};
683
684
static void call_getattr(void *args)
685
{
686
	struct getattr_args *a = args;
687
	*a->errp = do_vfsub_getattr(a->mnt, a->dentry, a->st);
688
}
689
690
int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
691
		  int dlgt)
692
{
693
	if (!dlgt)
694
		return do_vfsub_getattr(mnt, dentry, st);
695
	else {
696
		int err, wkq_err;
697
		struct getattr_args args = {
698
			.errp	= &err,
699
			.mnt	= mnt,
700
			.dentry	= dentry,
701
			.st	= st
702
		};
703
		wkq_err = au_wkq_wait(call_getattr, &args, /*dlgt*/1);
704
		if (unlikely(wkq_err))
705
			err = wkq_err;
706
		return err;
707
	}
708
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/hinotify.c (+1053 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2006-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
 * internal/hidden inotify handler
21
 *
22
 * $Id: hinotify.c,v 1.5 2008/05/19 01:49:11 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
/* inotify events */
28
static const __u32 AuInMask = (IN_MOVE | IN_DELETE | IN_CREATE
29
			       /* | IN_ACCESS */
30
			       | IN_MODIFY | IN_ATTRIB
31
			       /* | IN_DELETE_SELF | IN_MOVE_SELF */
32
	);
33
static struct inotify_handle *in_handle;
34
35
/* the size of an array for ignore counter */
36
static int au_hin_nignore;
37
38
AuCacheFuncs(hinotify, AuCache_HINOTIFY);
39
40
int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
41
		 struct inode *hidden_inode)
42
{
43
	int err, i;
44
	struct au_hinotify *hin;
45
	s32 wd;
46
47
	LKTRTrace("i%lu, hi%lu\n", inode->i_ino, hidden_inode->i_ino);
48
49
	err = -ENOMEM;
50
	hin = au_cache_alloc_hinotify();
51
	if (hin) {
52
		AuDebugOn(hinode->hi_notify);
53
		hinode->hi_notify = hin;
54
		hin->hin_aufs_inode = inode;
55
		for (i = 0; i < au_hin_nignore; i++)
56
			atomic_set(hin->hin_ignore + i, 0);
57
58
		inotify_init_watch(&hin->hin_watch);
59
		wd = inotify_add_watch(in_handle, &hin->hin_watch, hidden_inode,
60
				       AuInMask);
61
		if (wd >= 0)
62
			return 0; /* success */
63
64
		err = wd;
65
		put_inotify_watch(&hin->hin_watch);
66
		au_cache_free_hinotify(hin);
67
		hinode->hi_notify = NULL;
68
	}
69
70
	AuTraceErr(err);
71
	return err;
72
}
73
74
void au_hin_free(struct au_hinode *hinode)
75
{
76
	int err;
77
	struct au_hinotify *hin;
78
79
	AuTraceEnter();
80
81
	hin = hinode->hi_notify;
82
	if (unlikely(hin)) {
83
		err = 0;
84
		if (atomic_read(&hin->hin_watch.count))
85
			err = inotify_rm_watch(in_handle, &hin->hin_watch);
86
		if (unlikely(err))
87
			/* it means the watch is already removed */
88
			LKTRTrace("failed inotify_rm_watch() %d\n", err);
89
		au_cache_free_hinotify(hin);
90
		hinode->hi_notify = NULL;
91
	}
92
}
93
94
/* ---------------------------------------------------------------------- */
95
96
static void ctl_hinotify(struct au_hinode *hinode, const __u32 mask)
97
{
98
	struct inode *h_inode;
99
	struct inotify_watch *watch;
100
101
	h_inode = hinode->hi_inode;
102
	LKTRTrace("hi%lu, sb %p, 0x%x\n", h_inode->i_ino, h_inode->i_sb, mask);
103
	IMustLock(h_inode);
104
	if (!hinode->hi_notify)
105
		return;
106
107
	watch = &hinode->hi_notify->hin_watch;
108
	/* struct inotify_handle is hidden */
109
	mutex_lock(&h_inode->inotify_mutex);
110
	//mutex_lock(&watch->ih->mutex);
111
	watch->mask = mask;
112
	//mutex_unlock(&watch->ih->mutex);
113
	mutex_unlock(&h_inode->inotify_mutex);
114
	LKTRTrace("watch %p, mask %u\n", watch, watch->mask);
115
}
116
117
#define suspend_hinotify(hi)	ctl_hinotify(hi, 0)
118
#define resume_hinotify(hi)	ctl_hinotify(hi, AuInMask)
119
120
void au_do_hdir_lock(struct inode *h_dir, struct inode *dir,
121
		     aufs_bindex_t bindex, unsigned int lsc)
122
{
123
	struct au_hinode *hinode;
124
125
	LKTRTrace("i%lu, b%d, lsc %d\n", dir->i_ino, bindex, lsc);
126
	AuDebugOn(!S_ISDIR(dir->i_mode));
127
	hinode = au_ii(dir)->ii_hinode + bindex;
128
	AuDebugOn(h_dir != hinode->hi_inode);
129
130
	mutex_lock_nested(&h_dir->i_mutex, lsc);
131
	suspend_hinotify(hinode);
132
}
133
134
void au_hdir_unlock(struct inode *h_dir, struct inode *dir,
135
		    aufs_bindex_t bindex)
136
{
137
	struct au_hinode *hinode;
138
139
	LKTRTrace("i%lu, b%d\n", dir->i_ino, bindex);
140
	AuDebugOn(!S_ISDIR(dir->i_mode));
141
	hinode = au_ii(dir)->ii_hinode + bindex;
142
	AuDebugOn(h_dir != hinode->hi_inode);
143
144
	resume_hinotify(hinode);
145
	mutex_unlock(&h_dir->i_mutex);
146
}
147
148
struct dentry *au_hdir_lock_rename(struct dentry **h_parents,
149
				   struct inode **dirs, aufs_bindex_t bindex,
150
				   int issamedir)
151
{
152
	struct dentry *h_trap;
153
	struct au_hinode *hinode;
154
155
	LKTRTrace("%.*s, %.*s\n",
156
		  AuDLNPair(h_parents[0]), AuDLNPair(h_parents[1]));
157
158
	h_trap = vfsub_lock_rename(h_parents[0], h_parents[1]);
159
	hinode = au_ii(dirs[0])->ii_hinode + bindex;
160
	AuDebugOn(h_parents[0]->d_inode != hinode->hi_inode);
161
	suspend_hinotify(hinode);
162
	if (!issamedir) {
163
		hinode = au_ii(dirs[1])->ii_hinode + bindex;
164
		AuDebugOn(h_parents[1]->d_inode != hinode->hi_inode);
165
		suspend_hinotify(hinode);
166
	}
167
168
	return h_trap;
169
}
170
171
void au_hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
172
			   aufs_bindex_t bindex, int issamedir)
173
{
174
	struct au_hinode *hinode;
175
176
	LKTRTrace("%.*s, %.*s\n",
177
		  AuDLNPair(h_parents[0]), AuDLNPair(h_parents[1]));
178
179
	hinode = au_ii(dirs[0])->ii_hinode + bindex;
180
	AuDebugOn(h_parents[0]->d_inode != hinode->hi_inode);
181
	resume_hinotify(hinode);
182
	if (!issamedir) {
183
		hinode = au_ii(dirs[1])->ii_hinode + bindex;
184
		AuDebugOn(h_parents[1]->d_inode != hinode->hi_inode);
185
		resume_hinotify(hinode);
186
	}
187
	vfsub_unlock_rename(h_parents[0], h_parents[1]);
188
}
189
190
void au_reset_hinotify(struct inode *inode, unsigned int flags)
191
{
192
	aufs_bindex_t bindex, bend;
193
	struct inode *hi;
194
	struct dentry *iwhdentry;
195
196
	LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags);
197
198
	bend = au_ibend(inode);
199
	for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
200
		hi = au_h_iptr(inode, bindex);
201
		if (hi) {
202
			//mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD);
203
			iwhdentry = au_hi_wh(inode, bindex);
204
			if (unlikely(iwhdentry))
205
				dget(iwhdentry);
206
			igrab(hi);
207
			au_set_h_iptr(inode, bindex, NULL, 0);
208
			au_set_h_iptr(inode, bindex, igrab(hi),
209
				      flags & ~AuHi_XINO);
210
			iput(hi);
211
			dput(iwhdentry);
212
			//mutex_unlock(&hi->i_mutex);
213
		}
214
	}
215
}
216
217
/* ---------------------------------------------------------------------- */
218
219
/* cf. fsnotify_change() */
220
__u32 vfsub_events_notify_change(struct iattr *ia)
221
{
222
	__u32 events;
223
	const unsigned int amtime = (ATTR_ATIME | ATTR_MTIME);
224
225
	events = 0;
226
	if ((ia->ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE))
227
	    || (ia->ia_valid & amtime) == amtime)
228
		events |= IN_ATTRIB;
229
	if ((ia->ia_valid & ATTR_SIZE)
230
	    || (ia->ia_valid & amtime) == ATTR_MTIME)
231
		events |= IN_MODIFY;
232
	return events;
233
}
234
235
void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
236
		      struct au_hinode *hinode)
237
{
238
	struct au_hin_ignore *ign;
239
240
	AuDebugOn(!hinode);
241
242
	ign = vargs->ignore + vargs->nignore++;
243
	ign->ign_events = events;
244
	ign->ign_hinode = hinode;
245
}
246
247
void vfsub_ignore(struct vfsub_args *vargs)
248
{
249
	int n;
250
	struct au_hin_ignore *ign;
251
252
	n = vargs->nignore;
253
	ign = vargs->ignore;
254
	while (n-- > 0) {
255
		au_hin_ignore(ign->ign_hinode, ign->ign_events);
256
		ign++;
257
	}
258
}
259
260
void vfsub_unignore(struct vfsub_args *vargs)
261
{
262
	int n;
263
	struct au_hin_ignore *ign;
264
265
	n = vargs->nignore;
266
	ign = vargs->ignore;
267
	while (n-- > 0) {
268
		au_hin_unignore(ign->ign_hinode, ign->ign_events);
269
		ign++;
270
	}
271
}
272
273
/* ---------------------------------------------------------------------- */
274
275
void au_hin_ignore(struct au_hinode *hinode, __u32 events)
276
{
277
	int i;
278
	atomic_t *ign;
279
280
	LKTRTrace("0x%x\n", events);
281
	AuDebugOn(!hinode || !events);
282
	if (unlikely(!hinode->hi_inode || !hinode->hi_notify)) {
283
		/*
284
		 * it may happen by this scenario.
285
		 * - a file and its parent dir exist on two branches
286
		 * - a file on the upper branch is opened
287
		 * - the parent dir and the file are removed by udba
288
		 * - the parent is re-accessed, and new dentry/inode in
289
		 *   aufs is generated for it, based upon the one on the lower
290
		 *   branch
291
		 * - the opened file is re-accessed, re-validated, and it may be
292
		 *   re-connected to the new parent dentry
293
		 * it means the file in aufs cannot get the actual removed
294
		 * parent dir on the branch.
295
		 */
296
		return;
297
	}
298
	LKTRTrace("hi%lu\n", hinode->hi_inode->i_ino);
299
#ifdef DbgInotify
300
	AuDbg("hi%lu, 0x%x\n", hinode->hi_inode->i_ino, events);
301
#endif
302
	AuDebugOn(!hinode->hi_notify);
303
304
	ign = hinode->hi_notify->hin_ignore;
305
	for (i = 0; i < au_hin_nignore; i++)
306
		if (1U << i & events)
307
			atomic_inc_return(ign + i);
308
}
309
310
void au_hin_unignore(struct au_hinode *hinode, __u32 events)
311
{
312
	int i;
313
	atomic_t *ign;
314
315
	LKTRTrace("0x%x\n", events);
316
	AuDebugOn(!hinode || !events);
317
	if (unlikely(!hinode->hi_inode || !hinode->hi_notify))
318
		return;
319
	LKTRTrace("hi%lu\n", hinode->hi_inode->i_ino);
320
#ifdef DbgInotify
321
	AuDbg("hi%lu, 0x%x\n", hinode->hi_inode->i_ino, events);
322
#endif
323
	AuDebugOn(!hinode->hi_notify);
324
325
	ign = hinode->hi_notify->hin_ignore;
326
	for (i = 0; i < au_hin_nignore; i++)
327
		if (1U << i & events)
328
			atomic_dec_return(ign + i);
329
}
330
331
/* ---------------------------------------------------------------------- */
332
333
static char *in_name(u32 mask)
334
{
335
#ifdef CONFIG_AUFS_DEBUG
336
#define test_ret(flag)	if (mask & flag) return #flag;
337
	test_ret(IN_ACCESS);
338
	test_ret(IN_MODIFY);
339
	test_ret(IN_ATTRIB);
340
	test_ret(IN_CLOSE_WRITE);
341
	test_ret(IN_CLOSE_NOWRITE);
342
	test_ret(IN_OPEN);
343
	test_ret(IN_MOVED_FROM);
344
	test_ret(IN_MOVED_TO);
345
	test_ret(IN_CREATE);
346
	test_ret(IN_DELETE);
347
	test_ret(IN_DELETE_SELF);
348
	test_ret(IN_MOVE_SELF);
349
	test_ret(IN_UNMOUNT);
350
	test_ret(IN_Q_OVERFLOW);
351
	test_ret(IN_IGNORED);
352
	return "";
353
#undef test_ret
354
#else
355
	return "??";
356
#endif
357
}
358
359
/* ---------------------------------------------------------------------- */
360
361
static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
362
					   struct inode *dir)
363
{
364
	struct dentry *dentry, *d, *parent;
365
	struct qstr *dname;
366
367
	LKTRTrace("%.*s, dir%lu\n", nlen, name, dir->i_ino);
368
369
	parent = d_find_alias(dir);
370
	if (!parent)
371
		return NULL;
372
373
	dentry = NULL;
374
	spin_lock(&dcache_lock);
375
	list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
376
		LKTRTrace("%.*s\n", AuDLNPair(d));
377
		dname = &d->d_name;
378
		if (dname->len != nlen || memcmp(dname->name, name, nlen))
379
			continue;
380
		if (!atomic_read(&d->d_count)) {
381
			spin_lock(&d->d_lock);
382
			__d_drop(d);
383
			spin_unlock(&d->d_lock);
384
			continue;
385
		}
386
387
		dentry = dget(d);
388
		break;
389
	}
390
	spin_unlock(&dcache_lock);
391
	dput(parent);
392
393
	if (dentry)
394
		di_write_lock_child(dentry);
395
	return dentry;
396
}
397
398
static struct inode *lookup_wlock_by_ino(struct super_block *sb,
399
					 aufs_bindex_t bindex, ino_t h_ino)
400
{
401
	struct inode *inode;
402
	struct au_xino_entry xinoe;
403
	int err;
404
405
	LKTRTrace("b%d, hi%lu\n", bindex, h_ino);
406
	AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
407
408
	inode = NULL;
409
	err = au_xino_read(sb, bindex, h_ino, &xinoe);
410
	if (!err && xinoe.ino)
411
		inode = ilookup(sb, xinoe.ino);
412
	if (!inode)
413
		goto out;
414
	if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
415
		AuWarn("wrong root branch\n");
416
		iput(inode);
417
		inode = NULL;
418
		goto out;
419
	}
420
421
	ii_write_lock_child(inode);
422
423
 out:
424
	return inode;
425
}
426
427
static int hin_xino(struct inode *inode, struct inode *h_inode)
428
{
429
	int err;
430
	aufs_bindex_t bindex, bend, bfound, bstart;
431
	struct inode *h_i;
432
433
	LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
434
435
	err = 0;
436
	if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
437
		AuWarn("branch root dir was changed\n");
438
		goto out;
439
	}
440
441
	bfound = -1;
442
	bend = au_ibend(inode);
443
	bstart = au_ibstart(inode);
444
	for (bindex = bstart; bindex <= bend; bindex++) {
445
		if (au_h_iptr(inode, bindex) == h_inode) {
446
			bfound = bindex;
447
			break;
448
		}
449
	}
450
	if (bfound < 0)
451
		goto out;
452
453
	for (bindex = bstart; bindex <= bend; bindex++) {
454
		h_i = au_h_iptr(inode, bindex);
455
		if (h_i)
456
			err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino,
457
					     0);
458
		/* ignore this error */
459
		/* bad action? */
460
	}
461
462
	/* children inode number will be broken */
463
464
 out:
465
	AuTraceErr(err);
466
	return err;
467
}
468
469
static int hin_gen_tree(struct dentry *dentry)
470
{
471
	int err, i, j, ndentry;
472
	struct au_dcsub_pages dpages;
473
	struct au_dpage *dpage;
474
	struct dentry **dentries;
475
476
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
477
478
	err = au_dpages_init(&dpages, GFP_TEMPORARY);
479
	if (unlikely(err))
480
		goto out;
481
	err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
482
	if (unlikely(err))
483
		goto out_dpages;
484
485
	for (i = 0; i < dpages.ndpage; i++) {
486
		dpage = dpages.dpages + i;
487
		dentries = dpage->dentries;
488
		ndentry = dpage->ndentry;
489
		for (j = 0; j < ndentry; j++) {
490
			struct dentry *d;
491
			d = dentries[j];
492
			LKTRTrace("%.*s\n", AuDLNPair(d));
493
			if (IS_ROOT(d))
494
				continue;
495
496
			d_drop(d);
497
			au_digen_dec(d);
498
			if (d->d_inode)
499
				//reset children xino? cached children only?
500
				au_iigen_dec(d->d_inode);
501
		}
502
	}
503
504
 out_dpages:
505
	au_dpages_free(&dpages);
506
507
	/* discard children */
508
	dentry_unhash(dentry);
509
	dput(dentry);
510
 out:
511
	AuTraceErr(err);
512
	return err;
513
}
514
515
/*
516
 * return 0 if processed.
517
 */
518
static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
519
			    const unsigned int isdir)
520
{
521
	int err;
522
	struct dentry *d;
523
	struct qstr *dname;
524
525
	LKTRTrace("%.*s, i%lu\n", nlen, name, inode->i_ino);
526
527
	err = 1;
528
	if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
529
		AuWarn("branch root dir was changed\n");
530
		err = 0;
531
		goto out;
532
	}
533
534
	if (!isdir) {
535
		AuDebugOn(!name);
536
		au_iigen_dec(inode);
537
		spin_lock(&dcache_lock);
538
		list_for_each_entry(d, &inode->i_dentry, d_alias) {
539
			dname = &d->d_name;
540
			if (dname->len != nlen
541
			    && memcmp(dname->name, name, nlen))
542
				continue;
543
			err = 0;
544
			spin_lock(&d->d_lock);
545
			__d_drop(d);
546
			au_digen_dec(d);
547
			spin_unlock(&d->d_lock);
548
			break;
549
		}
550
		spin_unlock(&dcache_lock);
551
	} else {
552
		au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
553
		d = d_find_alias(inode);
554
		if (!d) {
555
			au_iigen_dec(inode);
556
			goto out;
557
		}
558
559
		dname = &d->d_name;
560
		if (dname->len == nlen && !memcmp(dname->name, name, nlen))
561
			err = hin_gen_tree(d);
562
		dput(d);
563
	}
564
565
 out:
566
	AuTraceErr(err);
567
	return err;
568
}
569
570
static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
571
{
572
	int err;
573
	struct inode *inode;
574
575
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
576
577
	inode = dentry->d_inode;
578
	if (IS_ROOT(dentry)
579
	    //|| (inode && inode->i_ino == AUFS_ROOT_INO)
580
		) {
581
		AuWarn("branch root dir was changed\n");
582
		return 0;
583
	}
584
585
	err = 0;
586
	if (!isdir) {
587
		d_drop(dentry);
588
		au_digen_dec(dentry);
589
		if (inode)
590
			au_iigen_dec(inode);
591
	} else {
592
		au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
593
		if (inode)
594
			err = hin_gen_tree(dentry);
595
	}
596
597
	AuTraceErr(err);
598
	return err;
599
}
600
601
static void hin_attr(struct inode *inode, struct inode *h_inode)
602
{
603
	struct dentry *h_dentry;
604
605
	LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
606
607
	if (au_h_iptr(inode, au_ibstart(inode)) != h_inode)
608
		return;
609
610
	h_dentry = d_find_alias(h_inode);
611
	if (h_dentry) {
612
		au_update_fuse_h_inode(NULL, h_dentry);
613
		/* ignore an error*/
614
		dput(h_dentry);
615
	}
616
617
	au_cpup_attr_all(inode);
618
}
619
620
/* ---------------------------------------------------------------------- */
621
622
/* hinotify job flags */
623
#define AuHinJob_XINO0	1
624
#define AuHinJob_GEN	(1 << 1)
625
#define AuHinJob_DIRENT	(1 << 2)
626
#define AuHinJob_ATTR	(1 << 3)
627
#define AuHinJob_ISDIR	(1 << 4)
628
#define AuHinJob_TRYXINO0 (1 << 5)
629
#define AuHinJob_MNTPNT	(1 << 6)
630
#define au_ftest_hinjob(flags, name)	((flags) & AuHinJob_##name)
631
#define au_fset_hinjob(flags, name)	{ (flags) |= AuHinJob_##name; }
632
#define au_fclr_hinjob(flags, name)	{ (flags) &= ~AuHinJob_##name; }
633
634
struct hin_job_args {
635
	unsigned int flags;
636
	struct inode *inode, *h_inode, *dir, *h_dir;
637
	struct dentry *dentry;
638
	char *h_name;
639
	int h_nlen;
640
};
641
642
static int hin_job(struct hin_job_args *a)
643
{
644
	const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
645
646
	/* reset xino */
647
	if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
648
		hin_xino(a->inode, a->h_inode);
649
	/* ignore this error */
650
651
	if (au_ftest_hinjob(a->flags, TRYXINO0)
652
	    && a->inode
653
	    && a->h_inode) {
654
		mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
655
		if (!a->h_inode->i_nlink)
656
			hin_xino(a->inode, a->h_inode);
657
		/* ignore this error */
658
		mutex_unlock(&a->h_inode->i_mutex);
659
	}
660
661
	/* make the generation obsolete */
662
	if (au_ftest_hinjob(a->flags, GEN)) {
663
		int err = -1;
664
		if (a->inode)
665
			err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
666
					       isdir);
667
		if (err && a->dentry)
668
			hin_gen_by_name(a->dentry, isdir);
669
		/* ignore this error */
670
	}
671
672
	/* make dir entries obsolete */
673
	if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
674
		struct au_vdir *vdir;
675
		IiMustWriteLock(a->inode);
676
		vdir = au_ivdir(a->inode);
677
		if (vdir)
678
			vdir->vd_jiffy = 0;
679
		//IMustLock(a->inode);
680
		//a->inode->i_version++;
681
	}
682
683
	/* update the attr */
684
	if (au_ftest_hinjob(a->flags, ATTR) && a->inode && a->h_inode)
685
		hin_attr(a->inode, a->h_inode);
686
687
	/* can do nothing but warn */
688
	if (au_ftest_hinjob(a->flags, MNTPNT)
689
	    && a->dentry
690
	    && d_mountpoint(a->dentry))
691
		AuWarn("mount-point %.*s is removed or renamed\n",
692
		       AuDLNPair(a->dentry));
693
694
	return 0;
695
}
696
697
/* ---------------------------------------------------------------------- */
698
699
enum { CHILD, PARENT };
700
struct postproc_args {
701
	struct inode *h_dir, *dir, *h_child_inode;
702
	u32 mask;
703
	unsigned int flags[2];
704
	unsigned int h_child_nlen;
705
	char h_child_name[];
706
};
707
708
static void postproc(void *_args)
709
{
710
	struct postproc_args *a = _args;
711
	struct super_block *sb;
712
	aufs_bindex_t bindex, bend, bfound;
713
	int xino, err;
714
	struct inode *inode;
715
	ino_t h_ino;
716
	struct hin_job_args args;
717
	struct dentry *dentry;
718
	struct au_sbinfo *sbinfo;
719
720
	AuDebugOn(!_args);
721
	AuDebugOn(!a->h_dir);
722
	AuDebugOn(!a->dir);
723
	AuDebugOn(!a->mask);
724
	//au_debug_on();
725
	LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
726
		  a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
727
		  a->h_child_inode ? a->h_child_inode->i_ino : 0);
728
729
	inode = NULL;
730
	dentry = NULL;
731
	// do not lock here because of d_revalidate() may cause a deadlock.
732
	//mutex_lock(&a->dir->i_mutex);
733
	sb = a->dir->i_sb;
734
	AuDebugOn(!sb);
735
	sbinfo = au_sbi(sb);
736
	AuDebugOn(!sbinfo);
737
	/* big aufs lock */
738
	si_noflush_write_lock(sb);
739
740
	ii_read_lock_parent(a->dir);
741
	bfound = -1;
742
	bend = au_ibend(a->dir);
743
	for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
744
		if (au_h_iptr(a->dir, bindex) == a->h_dir) {
745
			bfound = bindex;
746
			break;
747
		}
748
	ii_read_unlock(a->dir);
749
	if (unlikely(bfound < 0))
750
		goto out;
751
752
	xino = !!au_opt_test(au_mntflags(sb), XINO);
753
	h_ino = 0;
754
	if (a->h_child_inode)
755
		h_ino = a->h_child_inode->i_ino;
756
	//AuDbg("here\n");
757
758
	if (a->h_child_nlen
759
	    && (au_ftest_hinjob(a->flags[CHILD], GEN)
760
		|| au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
761
		dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
762
					      a->dir);
763
	//AuDbg("here\n");
764
	if (dentry)
765
		inode = dentry->d_inode;
766
	if (xino && !inode && h_ino
767
	    && (au_ftest_hinjob(a->flags[CHILD], XINO0)
768
		|| au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
769
		|| au_ftest_hinjob(a->flags[CHILD], GEN)
770
		|| au_ftest_hinjob(a->flags[CHILD], ATTR)))
771
		inode = lookup_wlock_by_ino(sb, bfound, h_ino);
772
	//AuDbg("here\n");
773
774
	args.flags = a->flags[CHILD];
775
	args.dentry = dentry;
776
	args.inode = inode;
777
	args.h_inode = a->h_child_inode;
778
	args.dir = a->dir;
779
	args.h_dir = a->h_dir;
780
	args.h_name = a->h_child_name;
781
	args.h_nlen = a->h_child_nlen;
782
	err = hin_job(&args);
783
	if (dentry) {
784
		di_write_unlock(dentry);
785
		dput(dentry);
786
	} else if (inode) {
787
		ii_write_unlock(inode);
788
		iput(inode);
789
	}
790
	//AuDbg("here\n");
791
792
	ii_write_lock_parent(a->dir);
793
	args.flags = a->flags[PARENT];
794
	args.dentry = NULL;
795
	args.inode = a->dir;
796
	args.h_inode = a->h_dir;
797
	args.dir = NULL;
798
	args.h_dir = NULL;
799
	args.h_name = NULL;
800
	args.h_nlen = 0;
801
	err = hin_job(&args);
802
	ii_write_unlock(a->dir);
803
	//AuDbg("here\n");
804
805
 out:
806
	si_write_unlock(sb);
807
	//mutex_unlock(&a->dir->i_mutex);
808
	au_nwt_dec(&sbinfo->si_nowait);
809
810
	iput(a->h_child_inode);
811
	iput(a->h_dir);
812
	iput(a->dir);
813
	kfree(a);
814
	//au_debug_off();
815
}
816
817
//todo: endian?
818
#ifndef ilog2
819
#define ilog2(n) ffz(~(n))
820
#endif
821
822
static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask,
823
			 u32 cookie, const char *h_child_name,
824
			 struct inode *h_child_inode)
825
{
826
	struct au_hinotify *hinotify;
827
	struct postproc_args *args;
828
	int len, wkq_err, isdir, isroot, wh, idx;
829
	char *p;
830
	struct inode *dir;
831
	unsigned int flags[2];
832
	struct super_block *sb;
833
	atomic_t *cnt;
834
835
	LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
836
		  watch->inode->i_ino, wd, mask, in_name(mask), cookie,
837
		  h_child_name ? h_child_name : "",
838
		  h_child_inode ? h_child_inode->i_ino : 0);
839
	/* if IN_UNMOUNT happens, there must be another bug */
840
	if (mask & (IN_IGNORED | IN_UNMOUNT)) {
841
		//WARN_ON(watch->inode->i_ino == 15);
842
		put_inotify_watch(watch);
843
		return;
844
	}
845
846
#ifdef DbgInotify
847
	if (!h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME))
848
		AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
849
		      " hi%lu\n",
850
		      watch->inode->i_ino, wd, mask, in_name(mask), cookie,
851
		      h_child_name ? h_child_name : "",
852
		      h_child_inode ? h_child_inode->i_ino : 0);
853
	//WARN_ON(1);
854
#endif
855
856
	hinotify = container_of(watch, struct au_hinotify, hin_watch);
857
	AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
858
	idx = ilog2(mask & IN_ALL_EVENTS);
859
	AuDebugOn(au_hin_nignore <= idx);
860
	cnt = hinotify->hin_ignore + idx;
861
	if (0 <= atomic_dec_return(cnt))
862
		return;
863
	atomic_inc_return(cnt);
864
865
	dir = igrab(hinotify->hin_aufs_inode);
866
	if (!dir)
867
		return;
868
	isroot = (dir->i_ino == AUFS_ROOT_INO);
869
	len = 0;
870
	wh = 0;
871
	if (h_child_name) {
872
		len = strlen(h_child_name);
873
		if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
874
			h_child_name += AUFS_WH_PFX_LEN;
875
			len -= AUFS_WH_PFX_LEN;
876
			wh = 1;
877
		}
878
	}
879
880
	isdir = 0;
881
	if (h_child_inode)
882
		isdir = !!S_ISDIR(h_child_inode->i_mode);
883
	flags[PARENT] = AuHinJob_ISDIR;
884
	flags[CHILD] = 0;
885
	if (isdir)
886
		flags[CHILD] = AuHinJob_ISDIR;
887
	switch (mask & IN_ALL_EVENTS) {
888
	case IN_MODIFY:
889
		/*FALLTHROUGH*/
890
	case IN_ATTRIB:
891
		if (h_child_inode) {
892
			if (!wh)
893
				au_fset_hinjob(flags[CHILD], ATTR);
894
		} else
895
			au_fset_hinjob(flags[PARENT], ATTR);
896
		break;
897
898
		/* IN_MOVED_FROM is the first event in rename(2) */
899
	case IN_MOVED_FROM:
900
	case IN_MOVED_TO:
901
		AuDebugOn(!h_child_name || !h_child_inode);
902
		au_fset_hinjob(flags[CHILD], GEN);
903
		au_fset_hinjob(flags[CHILD], ATTR);
904
		if (1 || isdir)
905
			au_fset_hinjob(flags[CHILD], XINO0);
906
		au_fset_hinjob(flags[CHILD], MNTPNT);
907
908
		au_fset_hinjob(flags[PARENT], ATTR);
909
		au_fset_hinjob(flags[PARENT], DIRENT);
910
		break;
911
912
	case IN_CREATE:
913
		AuDebugOn(!h_child_name || !h_child_inode);
914
		au_fset_hinjob(flags[PARENT], ATTR);
915
		au_fset_hinjob(flags[PARENT], DIRENT);
916
		au_fset_hinjob(flags[CHILD], GEN);
917
		/* hard link */
918
		if (!isdir && h_child_inode->i_nlink > 1)
919
			au_fset_hinjob(flags[CHILD], ATTR);
920
		break;
921
922
	case IN_DELETE:
923
		/*
924
		 * aufs never be able to get this child inode.
925
		 * revalidation should be in d_revalidate()
926
		 * by checking i_nlink, i_generation or d_unhashed().
927
		 */
928
		AuDebugOn(!h_child_name);
929
		au_fset_hinjob(flags[PARENT], ATTR);
930
		au_fset_hinjob(flags[PARENT], DIRENT);
931
		au_fset_hinjob(flags[CHILD], GEN);
932
		au_fset_hinjob(flags[CHILD], TRYXINO0);
933
		au_fset_hinjob(flags[CHILD], MNTPNT);
934
		break;
935
936
	case IN_DELETE_SELF:
937
		if (!isroot)
938
			au_fset_hinjob(flags[PARENT], GEN);
939
		/*FALLTHROUGH*/
940
941
	case IN_MOVE_SELF:
942
		/*
943
		 * when an inotify is set to an aufs inode,
944
		 * such inode can be isolated and this event can be fired
945
		 * solely.
946
		 */
947
		AuDebugOn(h_child_name || h_child_inode);
948
		if (unlikely(isroot)) {
949
			AuWarn("root branch was moved\n");
950
			iput(dir);
951
			return;
952
		}
953
		au_fset_hinjob(flags[PARENT], XINO0);
954
		au_fset_hinjob(flags[PARENT], GEN);
955
		au_fset_hinjob(flags[PARENT], ATTR);
956
		au_fset_hinjob(flags[PARENT], DIRENT);
957
		//au_fset_hinjob(flags[PARENT], MNTPNT);
958
		break;
959
	case IN_ACCESS:
960
	default:
961
		AuDebugOn(1);
962
	}
963
964
	if (wh)
965
		h_child_inode = NULL;
966
967
	/* iput() and kfree() will be called in postproc() */
968
	/*
969
	 * inotify_mutex is already acquired and kmalloc/prune_icache may lock
970
	 * iprune_mutex. strange.
971
	 */
972
	lockdep_off();
973
	args = kmalloc(sizeof(*args) + len + 1, GFP_TEMPORARY);
974
	lockdep_on();
975
	if (unlikely(!args)) {
976
		AuErr1("no memory\n");
977
		iput(dir);
978
		return;
979
	}
980
	args->flags[PARENT] = flags[PARENT];
981
	args->flags[CHILD] = flags[CHILD];
982
	args->mask = mask;
983
	args->dir = dir;
984
	args->h_dir = igrab(watch->inode);
985
	if (h_child_inode)
986
		igrab(h_child_inode);
987
	args->h_child_inode = h_child_inode;
988
	args->h_child_nlen = len;
989
	if (len) {
990
		p = (void *)args;
991
		p += sizeof(*args);
992
		memcpy(p, h_child_name, len + 1);
993
	}
994
995
	sb = dir->i_sb;
996
	au_nwt_inc(&au_sbi(sb)->si_nowait);
997
	lockdep_off();
998
	wkq_err = au_wkq_nowait(postproc, args, sb, /*dlgt*/0);
999
	lockdep_on();
1000
	if (unlikely(wkq_err)) {
1001
		AuErr("wkq %d\n", wkq_err);
1002
		au_nwt_dec(&au_sbi(sb)->si_nowait);
1003
	}
1004
}
1005
1006
static void aufs_inotify_destroy(struct inotify_watch *watch)
1007
{
1008
	return;
1009
}
1010
1011
static struct inotify_operations aufs_inotify_ops = {
1012
	.handle_event	= aufs_inotify,
1013
	.destroy_watch	= aufs_inotify_destroy
1014
};
1015
1016
/* ---------------------------------------------------------------------- */
1017
1018
static void au_hin_destroy_cache(void)
1019
{
1020
	kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
1021
	au_cachep[AuCache_HINOTIFY] = NULL;
1022
}
1023
1024
int __init au_inotify_init(void)
1025
{
1026
	au_hin_nignore = 6;
1027
	while (1U << au_hin_nignore < AuInMask)
1028
		au_hin_nignore++;
1029
	//AuDbg("au_hin_nignore %d\n", au_hin_nignore);
1030
	AuDebugOn(au_hin_nignore != 10);
1031
1032
	in_handle = ERR_PTR(-ENOMEM);
1033
	au_cachep[AuCache_HINOTIFY]
1034
		= AuCacheX(au_hinotify, sizeof(atomic_t) * au_hin_nignore);
1035
	if (unlikely(!au_cachep[AuCache_HINOTIFY]))
1036
		goto out;
1037
1038
	in_handle = inotify_init(&aufs_inotify_ops);
1039
	if (!IS_ERR(in_handle))
1040
		return 0;
1041
1042
	au_hin_destroy_cache();
1043
 out:
1044
	AuTraceErrPtr(in_handle);
1045
	return PTR_ERR(in_handle);
1046
}
1047
1048
void au_inotify_fin(void)
1049
{
1050
	inotify_destroy(in_handle);
1051
	if (au_cachep[AuCache_HINOTIFY])
1052
		au_hin_destroy_cache();
1053
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/iinfo.c (+282 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * inode private data
21
 *
22
 * $Id: iinfo.c,v 1.2 2008/04/21 01:32:05 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
struct au_iinfo *au_ii(struct inode *inode)
28
{
29
	struct au_iinfo *iinfo;
30
31
	iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
32
	/* bad_inode case */
33
	if (unlikely(!iinfo->ii_hinode))
34
		return NULL;
35
	AuDebugOn(!iinfo->ii_hinode
36
		  /* || au_sbi(inode->i_sb)->si_bend < iinfo->ii_bend */
37
		  || iinfo->ii_bend < iinfo->ii_bstart);
38
	return iinfo;
39
}
40
41
struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
42
{
43
	struct inode *hidden_inode;
44
45
	IiMustAnyLock(inode);
46
	AuDebugOn(bindex < 0 || au_ibend(inode) < bindex);
47
	hidden_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
48
	AuDebugOn(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
49
	return hidden_inode;
50
}
51
52
aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex)
53
{
54
	IiMustAnyLock(inode);
55
	AuDebugOn(bindex < 0
56
		  || au_ibend(inode) < bindex
57
		  || !au_ii(inode)->ii_hinode[0 + bindex].hi_inode);
58
	return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
59
}
60
61
// hard/soft set
62
void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
63
{
64
	struct au_iinfo *iinfo = au_ii(inode);
65
	struct inode *h_inode;
66
67
	IiMustWriteLock(inode);
68
	AuDebugOn(au_sbend(inode->i_sb) < bindex);
69
	iinfo->ii_bstart = bindex;
70
	h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
71
	if (h_inode)
72
		au_cpup_igen(inode, h_inode);
73
}
74
75
unsigned int au_hi_flags(struct inode *inode, int isdir)
76
{
77
	unsigned int flags;
78
	const unsigned int mnt_flags = au_mntflags(inode->i_sb);
79
80
	flags = 0;
81
	if (au_opt_test(mnt_flags, XINO))
82
		au_fset_hi(flags, XINO);
83
	if (unlikely(isdir && au_opt_test(mnt_flags, UDBA_INOTIFY)))
84
		au_fset_hi(flags, NOTIFY);
85
	return flags;
86
}
87
88
void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
89
		   struct inode *h_inode, unsigned int flags)
90
{
91
	struct au_hinode *hinode;
92
	struct inode *hi;
93
	struct au_iinfo *iinfo = au_ii(inode);
94
95
	LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
96
		  inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
97
	IiMustWriteLock(inode);
98
	hinode = iinfo->ii_hinode + bindex;
99
	hi = hinode->hi_inode;
100
	AuDebugOn(bindex < au_ibstart(inode) || au_ibend(inode) < bindex
101
		  || (h_inode && atomic_read(&h_inode->i_count) <= 0)
102
		  || (h_inode && hi));
103
104
	if (hi) {
105
		au_hiput(hinode);
106
	}
107
	hinode->hi_inode = h_inode;
108
	if (h_inode) {
109
		int err;
110
		struct super_block *sb = inode->i_sb;
111
112
		if (bindex == iinfo->ii_bstart)
113
			au_cpup_igen(inode, h_inode);
114
		hinode->hi_id = au_sbr_id(sb, bindex);
115
		if (au_ftest_hi(flags, XINO)) {
116
			struct au_xino_entry xinoe = {
117
				.ino	= inode->i_ino,
118
				//.h_gen	= h_inode->i_generation
119
			};
120
			err = au_xino_write(sb, bindex, h_inode->i_ino, &xinoe);
121
			if (unlikely(err))
122
				AuIOErr1("failed au_xino_write() %d\n", err);
123
		}
124
125
		if (unlikely(au_ftest_hi(flags, NOTIFY)
126
			     && au_br_hinotifyable(au_sbr_perm(sb, bindex)))) {
127
			err = au_hin_alloc(hinode, inode, h_inode);
128
			if (unlikely(err))
129
				AuIOErr1("au_hin_alloc() %d\n", err);
130
		}
131
	}
132
}
133
134
void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
135
		  struct dentry *h_wh)
136
{
137
	struct au_hinode *hinode;
138
139
	IiMustWriteLock(inode);
140
	hinode = au_ii(inode)->ii_hinode + bindex;
141
	AuDebugOn(hinode->hi_whdentry);
142
	hinode->hi_whdentry = h_wh;
143
}
144
145
void au_update_iigen(struct inode *inode)
146
{
147
	//IiMustWriteLock(inode);
148
	AuDebugOn(!inode->i_sb);
149
	atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
150
	//smp_mb(); /* atomic_set */
151
}
152
153
/* it may be called at remount time, too */
154
void au_update_brange(struct inode *inode, int do_put_zero)
155
{
156
	struct au_iinfo *iinfo;
157
158
	LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
159
	IiMustWriteLock(inode);
160
161
	iinfo = au_ii(inode);
162
	if (unlikely(!iinfo) || iinfo->ii_bstart < 0)
163
		return;
164
165
	if (do_put_zero) {
166
		aufs_bindex_t bindex;
167
		for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
168
		     bindex++) {
169
			struct inode *h_i;
170
			h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
171
			if (h_i && !h_i->i_nlink)
172
				au_set_h_iptr(inode, bindex, NULL, 0);
173
		}
174
	}
175
176
	iinfo->ii_bstart = -1;
177
	while (++iinfo->ii_bstart <= iinfo->ii_bend)
178
		if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
179
			break;
180
	if (iinfo->ii_bstart > iinfo->ii_bend) {
181
		iinfo->ii_bstart = -1;
182
		iinfo->ii_bend = -1;
183
		return;
184
	}
185
186
	iinfo->ii_bend++;
187
	while (0 <= --iinfo->ii_bend)
188
		if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
189
			break;
190
	AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
191
}
192
193
/* ---------------------------------------------------------------------- */
194
195
int au_iinfo_init(struct inode *inode)
196
{
197
	struct au_iinfo *iinfo;
198
	struct super_block *sb;
199
	int nbr, i;
200
201
	sb = inode->i_sb;
202
	AuDebugOn(!sb);
203
	iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
204
	AuDebugOn(iinfo->ii_hinode);
205
	nbr = au_sbend(sb) + 1;
206
	if (unlikely(nbr <= 0))
207
		nbr = 1;
208
	iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_KERNEL);
209
	//iinfo->ii_hinode = NULL;
210
	if (iinfo->ii_hinode) {
211
		for (i = 0; i < nbr; i++)
212
			iinfo->ii_hinode[i].hi_id = -1;
213
		atomic_set(&iinfo->ii_generation, au_sigen(sb));
214
		//smp_mb(); /* atomic_set */
215
		au_rw_init_nolock(&iinfo->ii_rwsem);
216
		iinfo->ii_bstart = -1;
217
		iinfo->ii_bend = -1;
218
		iinfo->ii_vdir = NULL;
219
		return 0;
220
	}
221
	return -ENOMEM;
222
}
223
224
static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
225
			   ino_t ino)
226
{
227
	int err, locked;
228
	aufs_bindex_t bindex;
229
230
	err = 0;
231
	locked = si_read_trylock(sb, !AuLock_FLUSH); // crucio!
232
	bindex = au_br_index(sb, hinode->hi_id);
233
	if (bindex >= 0)
234
		err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
235
	/* error action? */
236
	if (locked)
237
		si_read_unlock(sb);
238
	return err;
239
}
240
241
void au_iinfo_fin(struct inode *inode)
242
{
243
	struct au_iinfo *iinfo;
244
	aufs_bindex_t bend;
245
	struct au_hinode *hi;
246
	struct super_block *sb;
247
	int unlinked;
248
	ino_t ino;
249
250
	iinfo = au_ii(inode);
251
	/* bad_inode case */
252
	if (unlikely(!iinfo))
253
		return;
254
255
	if (unlikely(iinfo->ii_vdir))
256
		au_vdir_free(iinfo->ii_vdir);
257
258
	if (iinfo->ii_bstart >= 0) {
259
		sb = inode->i_sb;
260
		unlinked = !inode->i_nlink;
261
		ino = 0;
262
		if (unlinked)
263
			ino = inode->i_ino;
264
		hi = iinfo->ii_hinode + iinfo->ii_bstart;
265
		bend = iinfo->ii_bend;
266
		while (iinfo->ii_bstart++ <= bend) {
267
			if (hi->hi_inode) {
268
				if (unlinked || !hi->hi_inode->i_nlink) {
269
					au_iinfo_write0(sb, hi, ino);
270
					/* ignore this error */
271
					ino = 0;
272
				}
273
				au_hiput(hi);
274
			}
275
			hi++;
276
		}
277
		//iinfo->ii_bstart = iinfo->ii_bend = -1;
278
	}
279
280
	kfree(iinfo->ii_hinode);
281
	//iinfo->ii_hinode = NULL;
282
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/inode.c (+405 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * inode functions
21
 *
22
 * $Id: inode.c,v 1.3 2008/04/28 03:04:12 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
int au_refresh_hinode_self(struct inode *inode)
28
{
29
	int err, new_sz, update;
30
	struct inode *first;
31
	struct au_hinode *p, *q, tmp;
32
	struct super_block *sb;
33
	struct au_iinfo *iinfo;
34
	aufs_bindex_t bindex, bend, new_bindex;
35
36
	LKTRTrace("i%lu\n", inode->i_ino);
37
	IiMustWriteLock(inode);
38
39
	err = -ENOMEM;
40
	update = 0;
41
	sb = inode->i_sb;
42
	bend = au_sbend(sb);
43
	new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1);
44
	iinfo = au_ii(inode);
45
	p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1),
46
			 new_sz, GFP_KERNEL);
47
	//p = NULL;
48
	if (unlikely(!p))
49
		goto out;
50
51
	iinfo->ii_hinode = p;
52
	p = iinfo->ii_hinode + iinfo->ii_bstart;
53
	first = p->hi_inode;
54
	err = 0;
55
	for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
56
	     bindex++, p++) {
57
		if (!p->hi_inode)
58
			continue;
59
60
		new_bindex = au_br_index(sb, p->hi_id);
61
		if (new_bindex == bindex)
62
			continue;
63
		if (new_bindex < 0) {
64
			update++;
65
			au_hiput(p);
66
			p->hi_inode = NULL;
67
			continue;
68
		}
69
70
		if (new_bindex < iinfo->ii_bstart)
71
			iinfo->ii_bstart = new_bindex;
72
		if (iinfo->ii_bend < new_bindex)
73
			iinfo->ii_bend = new_bindex;
74
		/* swap two hidden inode, and loop again */
75
		q = iinfo->ii_hinode + new_bindex;
76
		tmp = *q;
77
		*q = *p;
78
		*p = tmp;
79
		if (tmp.hi_inode) {
80
			bindex--;
81
			p--;
82
		}
83
	}
84
	au_update_brange(inode, /*do_put_zero*/0);
85
86
	if (unlikely(err))
87
		goto out;
88
89
	if (1 || first != au_h_iptr(inode, iinfo->ii_bstart))
90
		au_cpup_attr_all(inode);
91
	if (update && S_ISDIR(inode->i_mode))
92
		inode->i_version++;
93
	au_update_iigen(inode);
94
95
 out:
96
	AuTraceErr(err);
97
	return err;
98
}
99
100
int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
101
{
102
	int err, update, isdir;
103
	struct inode *first;
104
	struct au_hinode *p;
105
	struct super_block *sb;
106
	struct au_iinfo *iinfo;
107
	aufs_bindex_t bindex, bend;
108
	unsigned int flags;
109
110
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
111
	IiMustWriteLock(inode);
112
113
	err = au_refresh_hinode_self(inode);
114
	if (unlikely(err))
115
		goto out;
116
117
	sb = dentry->d_sb;
118
	bend = au_sbend(sb);
119
	iinfo = au_ii(inode);
120
	update = 0;
121
	p = iinfo->ii_hinode + iinfo->ii_bstart;
122
	first = p->hi_inode;
123
	isdir = S_ISDIR(inode->i_mode);
124
	flags = au_hi_flags(inode, isdir);
125
	bend = au_dbend(dentry);
126
	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
127
		struct inode *hi;
128
		struct dentry *hd;
129
130
		hd = au_h_dptr(dentry, bindex);
131
		if (!hd || !hd->d_inode)
132
			continue;
133
134
		if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
135
			hi = au_h_iptr(inode, bindex);
136
			if (hi) {
137
				if (hi == hd->d_inode)
138
					continue;
139
				err = -ESTALE;
140
				break;
141
			}
142
		}
143
		if (bindex < iinfo->ii_bstart)
144
			iinfo->ii_bstart = bindex;
145
		if (iinfo->ii_bend < bindex)
146
			iinfo->ii_bend = bindex;
147
		au_set_h_iptr(inode, bindex, igrab(hd->d_inode), flags);
148
		update++;
149
	}
150
	au_update_brange(inode, /*do_put_zero*/0);
151
152
	if (unlikely(err))
153
		goto out;
154
155
	if (1 || first != au_h_iptr(inode, iinfo->ii_bstart))
156
		au_cpup_attr_all(inode);
157
	if (update && isdir)
158
		inode->i_version++;
159
	au_update_iigen(inode);
160
161
 out:
162
	AuTraceErr(err);
163
	return err;
164
}
165
166
static int set_inode(struct inode *inode, struct dentry *dentry)
167
{
168
	int err, isdir;
169
	struct dentry *h_dentry;
170
	struct inode *h_inode;
171
	umode_t mode;
172
	aufs_bindex_t bindex, bstart, btail;
173
	struct au_iinfo *iinfo;
174
	unsigned int flags;
175
176
	LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
177
	AuDebugOn(!(inode->i_state & I_NEW));
178
	IiMustWriteLock(inode);
179
	bstart = au_dbstart(dentry);
180
	h_dentry = au_h_dptr(dentry, bstart);
181
	AuDebugOn(!h_dentry);
182
	h_inode = h_dentry->d_inode;
183
	AuDebugOn(!h_inode);
184
185
	err = 0;
186
	isdir = 0;
187
	mode = h_inode->i_mode;
188
	switch (mode & S_IFMT) {
189
	case S_IFREG:
190
		btail = au_dbtail(dentry);
191
		break;
192
	case S_IFDIR:
193
		isdir = 1;
194
		btail = au_dbtaildir(dentry);
195
		inode->i_op = &aufs_dir_iop;
196
		inode->i_fop = &aufs_dir_fop;
197
		break;
198
	case S_IFLNK:
199
		btail = au_dbtail(dentry);
200
		inode->i_op = &aufs_symlink_iop;
201
		break;
202
	case S_IFBLK:
203
	case S_IFCHR:
204
	case S_IFIFO:
205
	case S_IFSOCK:
206
		btail = au_dbtail(dentry);
207
		init_special_inode(inode, mode,
208
				   au_h_rdev(h_inode, /*h_mnt*/NULL, h_dentry));
209
		break;
210
	default:
211
		AuIOErr("Unknown file type 0%o\n", mode);
212
		err = -EIO;
213
		goto out;
214
	}
215
216
	flags = au_hi_flags(inode, isdir);
217
	iinfo = au_ii(inode);
218
	iinfo->ii_bstart = bstart;
219
	iinfo->ii_bend = btail;
220
	for (bindex = bstart; bindex <= btail; bindex++) {
221
		h_dentry = au_h_dptr(dentry, bindex);
222
		if (!h_dentry)
223
			continue;
224
		AuDebugOn(!h_dentry->d_inode);
225
		au_set_h_iptr(inode, bindex, igrab(h_dentry->d_inode), flags);
226
	}
227
	au_cpup_attr_all(inode);
228
229
 out:
230
	AuTraceErr(err);
231
	return err;
232
}
233
234
/* successful returns with iinfo write_locked */
235
//todo: return with unlocked?
236
static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
237
{
238
	int err;
239
	struct inode *h_inode, *h_dinode;
240
	aufs_bindex_t bindex, bend;
241
242
	LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
243
244
	*matched = 0;
245
246
	/*
247
	 * before this function, if aufs got any iinfo lock, it must be only
248
	 * one, the parent dir.
249
	 * it can happen by UDBA and the obsoleted inode number.
250
	 */
251
	err = -EIO;
252
	if (unlikely(inode->i_ino == parent_ino(dentry)))
253
		goto out;
254
255
	err = 0;
256
	h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
257
	mutex_lock_nested(&inode->i_mutex, AuLsc_I_CHILD);
258
	ii_write_lock_new(inode);
259
	bend = au_ibend(inode);
260
	for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
261
		h_inode = au_h_iptr(inode, bindex);
262
		if (h_inode && h_inode == h_dinode) {
263
			//&& (ibs != bstart || !au_test_higen(inode, h_inode)));
264
			*matched = 1;
265
			err = 0;
266
			if (unlikely(au_iigen(inode) != au_digen(dentry)))
267
				err = au_refresh_hinode(inode, dentry);
268
			break;
269
		}
270
	}
271
	if (unlikely(err))
272
		ii_write_unlock(inode);
273
	mutex_unlock(&inode->i_mutex);
274
275
 out:
276
	AuTraceErr(err);
277
	return err;
278
}
279
280
/* successful returns with iinfo write_locked */
281
//todo: return with unlocked?
282
struct inode *au_new_inode(struct dentry *dentry)
283
{
284
	struct inode *inode, *h_inode;
285
	struct dentry *h_dentry;
286
	ino_t h_ino;
287
	struct super_block *sb;
288
	int err, match;
289
	aufs_bindex_t bstart;
290
	struct au_xino_entry xinoe;
291
292
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
293
	sb = dentry->d_sb;
294
	bstart = au_dbstart(dentry);
295
	h_dentry = au_h_dptr(dentry, bstart);
296
	AuDebugOn(!h_dentry);
297
	h_inode = h_dentry->d_inode;
298
	AuDebugOn(!h_inode);
299
300
	h_ino = h_inode->i_ino;
301
	err = au_xino_read(sb, bstart, h_ino, &xinoe);
302
	//err = -1;
303
	inode = ERR_PTR(err);
304
	if (unlikely(err))
305
		goto out;
306
 new_ino:
307
	if (!xinoe.ino) {
308
		xinoe.ino = au_xino_new_ino(sb);
309
		if (!xinoe.ino) {
310
			inode = ERR_PTR(-EIO);
311
			goto out;
312
		}
313
	}
314
315
	LKTRTrace("i%lu\n", xinoe.ino);
316
	inode = au_iget_locked(sb, xinoe.ino);
317
	err = PTR_ERR(inode);
318
	if (IS_ERR(inode))
319
		goto out;
320
321
	LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
322
	if (inode->i_state & I_NEW) {
323
		ii_write_lock_new(inode);
324
		err = set_inode(inode, dentry);
325
		//err = -1;
326
		unlock_new_inode(inode);
327
		if (!err)
328
			goto out; /* success */
329
		iget_failed(inode);
330
		ii_write_unlock(inode);
331
		goto out_iput;
332
	} else {
333
		//todo: remove this
334
		AuDebugOn(inode->i_state & I_LOCK);
335
		err = reval_inode(inode, dentry, &match);
336
		if (!err)
337
			goto out; /* success */
338
		else if (match)
339
			goto out_iput;
340
	}
341
342
	if (unlikely(au_test_unique_ino(h_dentry, h_ino)))
343
		AuWarn1("Un-notified UDBA or repeatedly renamed dir,"
344
			" b%d, %s, %.*s, hi%lu, i%lu.\n",
345
			bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
346
			h_ino, xinoe.ino);
347
	xinoe.ino = 0;
348
	err = au_xino_write0(sb, bstart, h_ino, 0);
349
	if (!err) {
350
		iput(inode);
351
		goto new_ino;
352
	}
353
	/* force noxino? */
354
355
 out_iput:
356
	iput(inode);
357
	inode = ERR_PTR(err);
358
 out:
359
	AuTraceErrPtr(inode);
360
	return inode;
361
}
362
363
/* ---------------------------------------------------------------------- */
364
365
int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
366
	       struct inode *inode)
367
{
368
	int err;
369
370
	err = au_br_rdonly(au_sbr(sb, bindex));
371
372
	/* pseudo-link after flushed may out of bounds */
373
	if (!err
374
	    && inode
375
	    && au_ibstart(inode) <= bindex
376
	    && bindex <= au_ibend(inode)) {
377
		/*
378
		 * permission check is unnecessary since vfsub routine
379
		 * will be called later
380
		 */
381
		struct inode *hi = au_h_iptr(inode, bindex);
382
		if (hi)
383
			err = IS_IMMUTABLE(hi) ? -EROFS : 0;
384
	}
385
386
	AuTraceErr(err);
387
	return err;
388
}
389
390
int au_test_h_perm(struct inode *h_inode, int mask, int dlgt)
391
{
392
	if (!current->fsuid)
393
		return 0;
394
	//todo: fake nameidata
395
	return vfsub_permission(h_inode, mask, NULL, dlgt);
396
}
397
398
int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt)
399
{
400
	if (unlikely(au_test_nfs(h_inode->i_sb)
401
		     && (mask & MAY_WRITE)
402
		     && S_ISDIR(h_inode->i_mode)))
403
		mask |= MAY_READ; /* force permission check */
404
	return au_test_h_perm(h_inode, mask, dlgt);
405
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/inode.h (+326 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * inode operations
21
 *
22
 * $Id: inode.h,v 1.2 2008/04/21 01:32:05 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_INODE_H__
26
#define __AUFS_INODE_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/namei.h>
32
#include <linux/security.h>
33
#include <linux/aufs_type.h>
34
#include "hinode.h"
35
#include "misc.h"
36
#include "super.h"
37
38
struct au_hinode;
39
struct au_vdir;
40
struct au_iinfo {
41
	atomic_t		ii_generation;
42
	struct super_block	*ii_hsb1;	/* no get/put */
43
44
	struct au_rwsem		ii_rwsem;
45
	aufs_bindex_t		ii_bstart, ii_bend;
46
	struct au_hinode	*ii_hinode;
47
	struct au_vdir		*ii_vdir;
48
};
49
50
struct aufs_icntnr {
51
	struct au_iinfo iinfo;
52
	struct inode vfs_inode;
53
};
54
55
/* ---------------------------------------------------------------------- */
56
57
/* inode.c */
58
int au_refresh_hinode_self(struct inode *inode);
59
int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
60
struct inode *au_new_inode(struct dentry *dentry);
61
int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
62
	       struct inode *inode);
63
int au_test_h_perm(struct inode *h_inode, int mask, int dlgt);
64
int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt);
65
66
/* i_op.c */
67
extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
68
69
/* au_wr_dir flags */
70
#define AuWrDir_ADD_ENTRY	1
71
#define AuWrDir_LOCK_SRCDIR	(1 << 1)
72
#define AuWrDir_ISDIR		(1 << 2)
73
#define au_ftest_wrdir(flags, name)	((flags) & AuWrDir_##name)
74
#define au_fset_wrdir(flags, name)	{ (flags) |= AuWrDir_##name; }
75
#define au_fclr_wrdir(flags, name)	{ (flags) &= ~AuWrDir_##name; }
76
77
struct au_wr_dir_args {
78
	aufs_bindex_t force_btgt;
79
	unsigned int flags;
80
};
81
int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
82
	      struct au_wr_dir_args *args);
83
84
/* i_op_add.c */
85
struct au_ndx;
86
int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
87
	       struct dentry *h_parent, int isdir, struct au_ndx *ndx);
88
int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
89
int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
90
int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
91
		struct nameidata *nd);
92
int aufs_link(struct dentry *src_dentry, struct inode *dir,
93
	      struct dentry *dentry);
94
int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
95
96
/* i_op_del.c */
97
int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
98
		      struct dentry *locked);
99
int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
100
	       struct dentry *h_parent, int isdir, struct au_ndx *ndx);
101
int aufs_unlink(struct inode *dir, struct dentry *dentry);
102
int aufs_rmdir(struct inode *dir, struct dentry *dentry);
103
104
/* i_op_ren.c */
105
int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
106
int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
107
		struct inode *dir, struct dentry *dentry);
108
109
#ifdef CONFIG_AUFS_DLGT
110
/* dlgt.c */
111
int au_security_inode_permission(struct inode *h_inode, int mask,
112
				 struct nameidata *fake_nd, int dlgt);
113
#else
114
static inline
115
int au_security_inode_permission(struct inode *h_inode, int mask,
116
				 struct nameidata *fake_nd, int dlgt)
117
{
118
	return security_inode_permission(h_inode, mask, fake_nd);
119
}
120
#endif /* CONFIG_AUFS_DLGT */
121
122
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
123
/* br_fuse.c */
124
int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st);
125
#endif
126
127
/* iinfo.c */
128
struct au_iinfo *au_ii(struct inode *inode);
129
struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
130
aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex);
131
132
void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
133
void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
134
		  struct dentry *h_wh);
135
unsigned int au_hi_flags(struct inode *inode, int isdir);
136
137
/* hinode flags */
138
#define AuHi_XINO	1
139
#define AuHi_NOTIFY	(1 << 1)
140
#define au_ftest_hi(flags, name)	((flags) & AuHi_##name)
141
#define au_fset_hi(flags, name)		{ (flags) |= AuHi_##name; }
142
#define au_fclr_hi(flags, name)		{ (flags) &= ~AuHi_##name; }
143
#ifndef CONFIG_AUFS_HINOTIFY
144
#undef AuHi_NOTIFY
145
#define AuHi_NOTIFY	0
146
#endif
147
148
void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
149
		   struct inode *h_inode, unsigned int flags);
150
151
void au_update_iigen(struct inode *inode);
152
void au_update_brange(struct inode *inode, int do_put_zero);
153
154
int au_iinfo_init(struct inode *inode);
155
void au_iinfo_fin(struct inode *inode);
156
157
/* plink.c */
158
#ifdef CONFIG_AUFS_DEBUG
159
void au_plink_list(struct super_block *sb);
160
#else
161
static inline void au_plink_list(struct super_block *sb)
162
{
163
	/* nothing */
164
}
165
#endif
166
int au_plink_test(struct super_block *sb, struct inode *inode);
167
struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex,
168
			     struct inode *inode);
169
void au_plink_append(struct super_block *sb, struct inode *inode,
170
		     struct dentry *h_dentry, aufs_bindex_t bindex);
171
void au_plink_put(struct super_block *sb);
172
void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
173
174
/* ---------------------------------------------------------------------- */
175
176
/* lock subclass for iinfo */
177
enum {
178
	AuLsc_II_CHILD,		/* child first */
179
	AuLsc_II_CHILD2,	/* rename(2), link(2), and cpup at hinotify */
180
	AuLsc_II_CHILD3,	/* copyup dirs */
181
	AuLsc_II_PARENT,
182
	AuLsc_II_PARENT2,
183
	AuLsc_II_PARENT3,
184
	AuLsc_II_PARENT4,
185
	AuLsc_II_NEW		/* new inode */
186
};
187
188
/*
189
 * ii_read_lock_child, ii_write_lock_child,
190
 * ii_read_lock_child2, ii_write_lock_child2,
191
 * ii_read_lock_child3, ii_write_lock_child3,
192
 * ii_read_lock_parent, ii_write_lock_parent,
193
 * ii_read_lock_parent2, ii_write_lock_parent2,
194
 * ii_read_lock_parent3, ii_write_lock_parent3,
195
 * ii_read_lock_parent4, ii_write_lock_parent4,
196
 * ii_read_lock_new, ii_write_lock_new
197
 */
198
#define AuReadLockFunc(name, lsc) \
199
static inline void ii_read_lock_##name(struct inode *i) \
200
{ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); }
201
202
#define AuWriteLockFunc(name, lsc) \
203
static inline void ii_write_lock_##name(struct inode *i) \
204
{ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); }
205
206
#define AuRWLockFuncs(name, lsc) \
207
	AuReadLockFunc(name, lsc) \
208
	AuWriteLockFunc(name, lsc)
209
210
AuRWLockFuncs(child, CHILD);
211
AuRWLockFuncs(child2, CHILD2);
212
AuRWLockFuncs(child3, CHILD3);
213
AuRWLockFuncs(parent, PARENT);
214
AuRWLockFuncs(parent2, PARENT2);
215
AuRWLockFuncs(parent3, PARENT3);
216
AuRWLockFuncs(parent4, PARENT4);
217
AuRWLockFuncs(new, NEW);
218
219
#undef AuReadLockFunc
220
#undef AuWriteLockFunc
221
#undef AuRWLockFuncs
222
223
/*
224
 * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
225
 */
226
AuSimpleUnlockRwsemFuncs(ii, struct inode *i, au_ii(i)->ii_rwsem);
227
228
/* to debug easier, do not make them inlined functions */
229
#define IiMustReadLock(i) do { \
230
	SiMustAnyLock((i)->i_sb); \
231
	AuRwMustReadLock(&au_ii(i)->ii_rwsem); \
232
} while (0)
233
234
#define IiMustWriteLock(i) do { \
235
	SiMustAnyLock((i)->i_sb); \
236
	AuRwMustWriteLock(&au_ii(i)->ii_rwsem); \
237
} while (0)
238
239
#define IiMustAnyLock(i) do { \
240
	SiMustAnyLock((i)->i_sb); \
241
	AuRwMustAnyLock(&au_ii(i)->ii_rwsem); \
242
} while (0)
243
244
#define IiMustNoWaiters(i)	AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
245
246
/* ---------------------------------------------------------------------- */
247
248
static inline aufs_bindex_t au_ibstart(struct inode *inode)
249
{
250
	IiMustAnyLock(inode);
251
	return au_ii(inode)->ii_bstart;
252
}
253
254
static inline aufs_bindex_t au_ibend(struct inode *inode)
255
{
256
	IiMustAnyLock(inode);
257
	return au_ii(inode)->ii_bend;
258
}
259
260
static inline struct au_vdir *au_ivdir(struct inode *inode)
261
{
262
	IiMustAnyLock(inode);
263
	AuDebugOn(!S_ISDIR(inode->i_mode));
264
	return au_ii(inode)->ii_vdir;
265
}
266
267
static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
268
{
269
	struct au_hinode *hinode;
270
	IiMustAnyLock(inode);
271
	hinode = au_ii(inode)->ii_hinode + bindex;
272
	return hinode->hi_whdentry;
273
}
274
275
static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
276
{
277
	IiMustWriteLock(inode);
278
	AuDebugOn(au_sbend(inode->i_sb) < bindex || bindex < au_ibstart(inode));
279
	au_ii(inode)->ii_bend = bindex;
280
}
281
282
static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
283
{
284
	IiMustWriteLock(inode);
285
	AuDebugOn(!S_ISDIR(inode->i_mode) || (au_ii(inode)->ii_vdir && vdir));
286
	au_ii(inode)->ii_vdir = vdir;
287
}
288
289
static inline void au_hiput(struct au_hinode *hinode)
290
{
291
	au_hin_free(hinode);
292
	dput(hinode->hi_whdentry);
293
	iput(hinode->hi_inode);
294
}
295
296
static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
297
{
298
	//todo: this lock check causes some unnecessary locks in callers.
299
	IiMustAnyLock(inode);
300
	return au_ii(inode)->ii_hinode + bindex;
301
}
302
303
/* tiny test for inode number */
304
/* tmpfs generation is too rough */
305
static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
306
{
307
	IiMustAnyLock(inode);
308
	return !(au_ii(inode)->ii_hsb1 == h_inode->i_sb
309
		 && inode->i_generation == h_inode->i_generation);
310
}
311
312
static inline au_gen_t au_iigen(struct inode *inode)
313
{
314
	return atomic_read(&au_ii(inode)->ii_generation);
315
}
316
317
#ifdef CONFIG_AUFS_HINOTIFY
318
static inline au_gen_t au_iigen_dec(struct inode *inode)
319
{
320
	//AuDbg("i%lu\n", inode->i_ino);
321
	return atomic_dec_return(&au_ii(inode)->ii_generation);
322
}
323
#endif
324
325
#endif /* __KERNEL__ */
326
#endif /* __AUFS_INODE_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/i_op_add.c (+777 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * inode operations (add entry)
21
 *
22
 * $Id: i_op_add.c,v 1.4 2008/05/04 23:54:53 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
/*
28
 * final procedure of adding a new entry, except link(2).
29
 * remove whiteout, instantiate, copyup the parent dir's times and size
30
 * and update version.
31
 * if it failed, re-create the removed whiteout.
32
 */
33
static int epilog(struct inode *dir, struct dentry *wh_dentry,
34
		  struct dentry *dentry)
35
{
36
	int err, rerr;
37
	aufs_bindex_t bwh;
38
	struct inode *inode, *h_dir;
39
	struct dentry *wh;
40
	struct au_ndx ndx;
41
	struct super_block *sb;
42
43
	LKTRTrace("wh %p, %.*s\n", wh_dentry, AuDLNPair(dentry));
44
45
	bwh = -1;
46
	if (wh_dentry) {
47
		h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
48
		IMustLock(h_dir);
49
		bwh = au_dbwh(dentry);
50
		err = au_wh_unlink_dentry(h_dir, wh_dentry, dentry, dir,
51
					  /*dlgt*/0);
52
		//err = -1;
53
		if (unlikely(err))
54
			goto out;
55
	}
56
57
	inode = au_new_inode(dentry);
58
	//inode = ERR_PTR(-1);
59
	if (!IS_ERR(inode)) {
60
		d_instantiate(dentry, inode);
61
		dir = dentry->d_parent->d_inode; /* dir inode is locked */
62
		IMustLock(dir);
63
		/* or always cpup dir mtime? */
64
		if (au_ibstart(dir) == au_dbstart(dentry))
65
			au_cpup_attr_timesizes(dir);
66
		dir->i_version++;
67
		return 0; /* success */
68
	}
69
70
	err = PTR_ERR(inode);
71
	if (!wh_dentry)
72
		goto out;
73
74
	/* revert */
75
	sb = dentry->d_sb;
76
	ndx.flags = 0;
77
	if (unlikely(au_opt_test_dlgt(au_mntflags(sb))))
78
		au_fset_ndx(ndx.flags, DLGT);
79
	ndx.nfsmnt = au_nfsmnt(sb, bwh);
80
	ndx.nd = NULL;
81
	//ndx.br = NULL;
82
	/* dir inode is locked */
83
	wh = au_wh_create(dir, dentry, bwh, wh_dentry->d_parent, &ndx);
84
	//wh = ERR_PTR(-1);
85
	rerr = PTR_ERR(wh);
86
	if (!IS_ERR(wh)) {
87
		dput(wh);
88
		goto out;
89
	}
90
	AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
91
		AuDLNPair(dentry), err, rerr);
92
	err = -EIO;
93
94
 out:
95
	AuTraceErr(err);
96
	return err;
97
}
98
99
/*
100
 * simple tests for the adding inode operations.
101
 * following the checks in vfs, plus the parent-child relationship.
102
 */
103
int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
104
	       struct dentry *h_parent, int isdir, struct au_ndx *ndx)
105
{
106
	int err, exist;
107
	struct dentry *h_dentry;
108
	struct inode *h_inode;
109
	umode_t h_mode;
110
111
	LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
112
		  AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);
113
114
	exist = !!dentry->d_inode;
115
	h_dentry = au_h_dptr(dentry, bindex);
116
	h_inode = h_dentry->d_inode;
117
	if (!exist) {
118
		err = -EEXIST;
119
		if (unlikely(h_inode))
120
			goto out;
121
	} else {
122
		/* rename(2) case */
123
		err = -EIO;
124
		if (unlikely(!h_inode || !h_inode->i_nlink))
125
			goto out;
126
127
		h_mode = h_inode->i_mode;
128
		if (!isdir) {
129
			err = -EISDIR;
130
			if (unlikely(S_ISDIR(h_mode)))
131
				goto out;
132
		} else if (unlikely(!S_ISDIR(h_mode))) {
133
			err = -ENOTDIR;
134
			goto out;
135
		}
136
	}
137
138
	err = -EIO;
139
	/* expected parent dir is locked */
140
	if (unlikely(h_parent != h_dentry->d_parent))
141
		goto out;
142
	err = 0;
143
144
	if (unlikely(au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY))) {
145
		struct dentry *h_latest;
146
		struct qstr *qstr = &dentry->d_name;
147
148
		err = -EACCES;
149
		if (unlikely(au_test_h_perm
150
			     (h_parent->d_inode, MAY_EXEC | MAY_WRITE,
151
			      au_ftest_ndx(ndx->flags, DLGT))))
152
			goto out;
153
154
		err = -EIO;
155
		h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
156
					   ndx);
157
		err = PTR_ERR(h_latest);
158
		if (IS_ERR(h_latest))
159
			goto out;
160
		err = -EIO;
161
		dput(h_latest);
162
		if (h_latest == h_dentry)
163
			err = 0;
164
	}
165
166
 out:
167
	AuTraceErr(err);
168
	return err;
169
}
170
171
/*
172
 * initial procedure of adding a new entry.
173
 * prepare writable branch and the parent dir, lock it,
174
 * lookup whiteout for the new entry.
175
 */
176
static struct dentry *
177
lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
178
		  struct dentry *src_dentry, struct au_wr_dir_args *wr_dir_args)
179
{
180
	struct dentry *wh_dentry, *parent, *h_parent, *gparent;
181
	int err;
182
	aufs_bindex_t bstart, bcpup;
183
	struct inode *dir, *h_dir, *gdir;
184
	struct au_ndx ndx;
185
	struct super_block *sb;
186
	struct au_hinode *hgdir;
187
	unsigned int mnt_flags;
188
189
	LKTRTrace("%.*s, src %p\n", AuDLNPair(dentry), src_dentry);
190
191
	parent = dentry->d_parent; /* dir inode is locked */
192
	IMustLock(parent->d_inode);
193
	bstart = au_dbstart(dentry);
194
	err = au_wr_dir(dentry, src_dentry, wr_dir_args);
195
	bcpup = err;
196
	//err = -1;
197
	wh_dentry = ERR_PTR(err);
198
	if (unlikely(err < 0))
199
		goto out;
200
201
	sb = parent->d_sb;
202
	mnt_flags = au_mntflags(sb);
203
	//todo: meaningless lock if CONFIG_AUFS_DEBUG is disabled.
204
	hgdir = NULL;
205
	if (unlikely(dt && au_opt_test(mnt_flags, UDBA_INOTIFY)
206
		     && !IS_ROOT(parent))) {
207
		gparent = dget_parent(parent);
208
		gdir = gparent->d_inode;
209
		ii_read_lock_parent2(gdir);
210
		hgdir = au_hi(gdir, bcpup);
211
		ii_read_unlock(gdir);
212
		dput(gparent);
213
	}
214
	dir = parent->d_inode;
215
	h_parent = au_h_dptr(parent, bcpup);
216
	h_dir = h_parent->d_inode;
217
218
	AuDbgSleep_UdbaRace();
219
	au_hdir_lock(h_dir, dir, bcpup);
220
	//todo: revalidate the lower dentry?
221
222
	ndx.nfsmnt = au_nfsmnt(sb, bcpup);
223
	ndx.flags = 0;
224
	if (unlikely(au_opt_test_dlgt(mnt_flags)))
225
		au_fset_ndx(ndx.flags, DLGT);
226
	ndx.nd = NULL;
227
	//ndx.br = NULL;
228
	//ndx.nd_file = NULL;
229
230
	if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) {
231
		struct nameidata nd;
232
233
		if (unlikely(ndx.nfsmnt)) {
234
			//todo: dirty
235
			ndx.nd = &nd;
236
			ndx.br = au_sbr(sb, bcpup);
237
			memset(&nd, 0, sizeof(nd));
238
			nd.flags = LOOKUP_CREATE;
239
			nd.intent.open.flags = O_EXCL;
240
		}
241
		err = au_may_add(dentry, bcpup, h_parent,
242
				 au_ftest_wrdir(wr_dir_args->flags, ISDIR),
243
				 &ndx);
244
		wh_dentry = ERR_PTR(err);
245
		if (unlikely(err))
246
			goto out_dir;
247
		ndx.nd = NULL;
248
		ndx.br = NULL;
249
	}
250
251
	if (dt)
252
		au_dtime_store(dt, parent, h_parent, hgdir);
253
	wh_dentry = NULL;
254
	if (/* bcpup != bstart || */ bcpup != au_dbwh(dentry))
255
		goto out; /* success */
256
257
	wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, &ndx);
258
	//wh_dentry = ERR_PTR(-1);
259
260
 out_dir:
261
	if (IS_ERR(wh_dentry))
262
		au_hdir_unlock(h_dir, dir, bcpup);
263
 out:
264
	AuTraceErrPtr(wh_dentry);
265
	return wh_dentry;
266
}
267
268
/* ---------------------------------------------------------------------- */
269
270
enum { Mknod, Symlink, Creat };
271
struct simple_arg {
272
	int type;
273
	union {
274
		struct {
275
			int mode;
276
			struct nameidata *nd;
277
		} c;
278
		struct {
279
			const char *symname;
280
		} s;
281
		struct {
282
			int mode;
283
			dev_t dev;
284
		} m;
285
	} u;
286
};
287
288
static int add_simple(struct inode *dir, struct dentry *dentry,
289
		      struct simple_arg *arg)
290
{
291
	int err, dlgt, created;
292
	struct dentry *h_dentry, *h_parent, *wh_dentry, *parent;
293
	struct inode *h_dir;
294
	struct au_dtime dt;
295
	struct vfsub_args vargs;
296
	struct super_block *sb;
297
	aufs_bindex_t bstart;
298
	struct au_wr_dir_args wr_dir_args = {
299
		.force_btgt	= -1,
300
		.flags		= AuWrDir_ADD_ENTRY
301
	};
302
303
	LKTRTrace("type %d, %.*s\n", arg->type, AuDLNPair(dentry));
304
	IMustLock(dir);
305
306
	aufs_read_lock(dentry, AuLock_DW);
307
	parent = dentry->d_parent; /* dir inode is locked */
308
	di_write_lock_parent(parent);
309
	wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
310
				      &wr_dir_args);
311
	//wh_dentry = ERR_PTR(-1);
312
	err = PTR_ERR(wh_dentry);
313
	if (IS_ERR(wh_dentry))
314
		goto out;
315
316
	bstart = au_dbstart(dentry);
317
	h_dentry = au_h_dptr(dentry, bstart);
318
	h_parent = h_dentry->d_parent; /* dir inode is locked */
319
	h_dir = h_parent->d_inode;
320
	IMustLock(h_dir);
321
	sb = dir->i_sb;
322
	dlgt = !!au_opt_test_dlgt(au_mntflags(sb));
323
324
	switch (arg->type) {
325
	case Creat:
326
		AuDebugOn(au_test_nfs(h_dir->i_sb) && !arg->u.c.nd);
327
		err = au_h_create(h_dir, h_dentry, arg->u.c.mode, dlgt,
328
				  arg->u.c.nd, au_nfsmnt(sb, bstart));
329
		break;
330
	case Symlink:
331
		err = vfsub_symlink(h_dir, h_dentry, arg->u.s.symname,
332
				    S_IALLUGO, dlgt);
333
		break;
334
	case Mknod:
335
		err = vfsub_mknod(h_dir, h_dentry, arg->u.m.mode, arg->u.m.dev,
336
				  dlgt);
337
		break;
338
	default:
339
		BUG();
340
	}
341
	created = !err;
342
	if (!err)
343
		err = epilog(dir, wh_dentry, dentry);
344
	//err = -1;
345
346
	/* revert */
347
	if (unlikely(created && err && h_dentry->d_inode)) {
348
		int rerr;
349
		vfsub_args_init(&vargs, NULL, dlgt, 0);
350
		rerr = vfsub_unlink(h_dir, h_dentry, &vargs);
351
		//rerr = -1;
352
		if (rerr) {
353
			AuIOErr("%.*s revert failure(%d, %d)\n",
354
				AuDLNPair(dentry), err, rerr);
355
			err = -EIO;
356
		}
357
		//todo: inotify will be fired to the grand parent dir
358
		au_dtime_revert(&dt);
359
		d_drop(dentry);
360
	}
361
362
	au_hdir_unlock(h_dir, dir, bstart);
363
	dput(wh_dentry);
364
365
 out:
366
	if (unlikely(err)) {
367
		au_update_dbstart(dentry);
368
		d_drop(dentry);
369
	}
370
	di_write_unlock(parent);
371
	aufs_read_unlock(dentry, AuLock_DW);
372
	AuTraceErr(err);
373
	return err;
374
}
375
376
int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
377
{
378
	struct simple_arg arg = {
379
		.type = Mknod,
380
		.u.m = {
381
			.mode	= mode,
382
			.dev	= dev
383
		}
384
	};
385
	return add_simple(dir, dentry, &arg);
386
}
387
388
int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
389
{
390
	struct simple_arg arg = {
391
		.type = Symlink,
392
		.u.s.symname = symname
393
	};
394
	return add_simple(dir, dentry, &arg);
395
}
396
397
int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
398
		struct nameidata *nd)
399
{
400
	struct simple_arg arg = {
401
		.type = Creat,
402
		.u.c = {
403
			.mode	= mode,
404
			.nd	= nd
405
		}
406
	};
407
	return add_simple(dir, dentry, &arg);
408
}
409
410
/* ---------------------------------------------------------------------- */
411
412
struct link_arg {
413
	aufs_bindex_t bdst, bsrc;
414
	int issamedir, dlgt;
415
	struct dentry *src_parent, *parent, *h_dentry;
416
	struct inode *h_dir, *inode, *dir;
417
};
418
419
static int cpup_before_link(struct dentry *src_dentry, struct inode *dir,
420
			    struct link_arg *a)
421
{
422
	int err;
423
	struct inode *hi, *h_dir, *src_dir, *gdir;
424
	struct dentry *gparent;
425
426
	AuTraceEnter();
427
428
	gparent = NULL;
429
	gdir = NULL;
430
	if (unlikely(au_opt_test(au_mntflags(src_dentry->d_sb), UDBA_INOTIFY)
431
		     && !IS_ROOT(a->src_parent))) {
432
		gparent = dget_parent(a->src_parent);
433
		gdir = gparent->d_inode;
434
		if (gdir == dir) {
435
			dput(gparent);
436
			gparent = NULL;
437
		}
438
	}
439
	src_dir = a->src_parent->d_inode;
440
	h_dir = NULL;
441
442
	if (!a->issamedir) {
443
		/* this temporary unlock/lock is safe */
444
		au_hdir_unlock(a->h_dir, dir, a->bdst);
445
		di_read_lock_parent2(a->src_parent, AuLock_IR);
446
		err = au_test_and_cpup_dirs(src_dentry, a->bdst, a->parent);
447
		//err = -1;
448
		if (unlikely(err)) {
449
			au_hdir_lock(a->h_dir, dir, a->bdst);
450
			goto out;
451
		}
452
453
		//todo: meaningless lock if CONFIG_AUFS_DEBUG is disabled.
454
		if (unlikely(gparent))
455
			ii_read_lock_parent3(gdir);
456
		h_dir = au_h_iptr(src_dir, a->bdst);
457
		au_hdir_lock(h_dir, src_dir, a->bdst);
458
	} else if (unlikely(gparent)) {
459
		/* this temporary unlock/lock is safe */
460
		au_hdir_unlock(a->h_dir, dir, a->bdst);
461
		ii_read_lock_parent3(gdir);
462
		au_hdir_lock(a->h_dir, dir, a->bdst);
463
	}
464
	//todo: test parent-gparent relationship
465
466
	AuDebugOn(au_dbstart(src_dentry) != a->bsrc);
467
	hi = au_h_dptr(src_dentry, a->bsrc)->d_inode;
468
	mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD);
469
	err = au_sio_cpup_simple(src_dentry, a->bdst, -1, AuCpup_DTIME);
470
	//err = -1;
471
	mutex_unlock(&hi->i_mutex);
472
473
	if (unlikely(gparent)) {
474
		ii_read_unlock(gdir);
475
		dput(gparent);
476
	}
477
478
 out:
479
	if (h_dir) {
480
		au_hdir_unlock(h_dir, src_dir, a->bdst);
481
		au_hdir_lock(a->h_dir, dir, a->bdst);
482
	}
483
	if (!a->issamedir)
484
		di_read_unlock(a->src_parent, AuLock_IR);
485
486
	AuTraceErr(err);
487
	return err;
488
}
489
490
static int cpup_or_link(struct dentry *src_dentry, struct link_arg *a)
491
{
492
	int err;
493
	struct inode *inode, *h_inode, *h_dst_inode;
494
	struct dentry *h_dentry;
495
	aufs_bindex_t bstart;
496
	struct super_block *sb;
497
498
	AuTraceEnter();
499
500
	sb = src_dentry->d_sb;
501
	inode = src_dentry->d_inode;
502
	AuDebugOn(au_dbstart(src_dentry) != a->bsrc);
503
	h_dentry = au_h_dptr(src_dentry, a->bsrc);
504
	h_inode = h_dentry->d_inode;
505
	bstart = au_ibstart(inode);
506
	h_dst_inode = NULL;
507
	if (bstart <= a->bdst)
508
		h_dst_inode = au_h_iptr(inode, a->bdst);
509
510
	if (!h_dst_inode || !h_dst_inode->i_nlink) {
511
		/* copyup src_dentry as the name of dentry. */
512
		au_set_dbstart(src_dentry, a->bdst);
513
		au_set_h_dptr(src_dentry, a->bdst, dget(a->h_dentry));
514
		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
515
		err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
516
					 !AuCpup_DTIME);
517
		//err = -1;
518
		mutex_unlock(&h_inode->i_mutex);
519
		au_set_h_dptr(src_dentry, a->bdst, NULL);
520
		au_set_dbstart(src_dentry, a->bsrc);
521
	} else {
522
		/* the inode of src_dentry already exists on a.bdst branch */
523
		h_dentry = d_find_alias(h_dst_inode);
524
		if (h_dentry) {
525
			err = vfsub_link(h_dentry, a->h_dir,
526
					 a->h_dentry, a->dlgt);
527
			dput(h_dentry);
528
		} else {
529
			AuIOErr("no dentry found for i%lu on b%d\n",
530
				h_dst_inode->i_ino, a->bdst);
531
			err = -EIO;
532
		}
533
	}
534
535
	if (!err)
536
		au_plink_append(sb, a->inode, a->h_dentry, a->bdst);
537
538
	AuTraceErr(err);
539
	return err;
540
}
541
542
int aufs_link(struct dentry *src_dentry, struct inode *dir,
543
	      struct dentry *dentry)
544
{
545
	int err, rerr;
546
	struct dentry *h_parent, *wh_dentry, *h_src_dentry;
547
	struct au_dtime dt;
548
	struct link_arg a;
549
	struct super_block *sb;
550
	unsigned int mnt_flags;
551
	struct vfsub_args vargs;
552
	struct au_wr_dir_args wr_dir_args = {
553
		//.force_btgt	= -1,
554
		.flags		= AuWrDir_ADD_ENTRY
555
	};
556
557
	LKTRTrace("src %.*s, i%lu, dst %.*s\n",
558
		  AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
559
	IMustLock(dir);
560
	IMustLock(src_dentry->d_inode);
561
	AuDebugOn(S_ISDIR(src_dentry->d_inode->i_mode));
562
563
	aufs_read_and_write_lock2(dentry, src_dentry, /*flags*/0);
564
	sb = dentry->d_sb;
565
	a.dir = dir;
566
	a.src_parent = dget_parent(src_dentry);
567
	a.parent = dentry->d_parent; /* dir inode is locked */
568
	a.issamedir = (a.src_parent == a.parent);
569
	if (!a.issamedir)
570
		au_fset_wrdir(wr_dir_args.flags, LOCK_SRCDIR);
571
	wr_dir_args.force_btgt = au_dbstart(src_dentry);
572
	di_write_lock_parent(a.parent);
573
	wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
574
	wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &wr_dir_args);
575
	//wh_dentry = ERR_PTR(-1);
576
	err = PTR_ERR(wh_dentry);
577
	if (IS_ERR(wh_dentry))
578
		goto out;
579
580
	a.inode = src_dentry->d_inode;
581
	a.bdst = au_dbstart(dentry);
582
	a.h_dentry = au_h_dptr(dentry, a.bdst);
583
	h_parent = a.h_dentry->d_parent; /* dir inode is locked */
584
	a.h_dir = h_parent->d_inode;
585
	IMustLock(a.h_dir);
586
587
	err = 0;
588
	mnt_flags = au_mntflags(sb);
589
	a.dlgt = !!au_opt_test_dlgt(mnt_flags);
590
591
	//todo: minor optimize, their sb may be same while their bindex differs.
592
	a.bsrc = au_dbstart(src_dentry);
593
	h_src_dentry = au_h_dptr(src_dentry, a.bsrc);
594
	if (unlikely(!au_opt_test(mnt_flags, PLINK))) {
595
		/*
596
		 * copyup src_dentry to the branch we process,
597
		 * and then link(2) to it.
598
		 * gave up 'pseudo link by cpup' approach,
599
		 * since nlink may be one and some applications will not work.
600
		 */
601
		if (a.bdst < a.bsrc
602
		    /* && h_src_dentry->d_sb != a.h_dentry->d_sb */)
603
			err = cpup_before_link(src_dentry, dir, &a);
604
		if (!err) {
605
			h_src_dentry = au_h_dptr(src_dentry, a.bdst);
606
			err = vfsub_link(h_src_dentry, a.h_dir, a.h_dentry,
607
					 a.dlgt);
608
			//err = -1;
609
		}
610
	} else {
611
		if (a.bdst < a.bsrc
612
		    /* && h_src_dentry->d_sb != a.h_dentry->d_sb */)
613
			err = cpup_or_link(src_dentry, &a);
614
		else {
615
			h_src_dentry = au_h_dptr(src_dentry, a.bdst);
616
			err = vfsub_link(h_src_dentry, a.h_dir, a.h_dentry,
617
					 a.dlgt);
618
			//err = -1;
619
		}
620
	}
621
	if (unlikely(err))
622
		goto out_unlock;
623
	if (wh_dentry) {
624
		err = au_wh_unlink_dentry(a.h_dir, wh_dentry, dentry,
625
					  dir, /*dlgt*/0);
626
		//err = -1;
627
		if (unlikely(err))
628
			goto out_revert;
629
	}
630
631
	dir->i_version++;
632
	if (au_ibstart(dir) == au_dbstart(dentry))
633
		au_cpup_attr_timesizes(dir);
634
	if (!d_unhashed(a.h_dentry)
635
	    /* || h_old_inode->i_nlink <= nlink */
636
	    /* || SB_NFS(h_src_dentry->d_sb) */) {
637
		dentry->d_inode = igrab(a.inode);
638
		d_instantiate(dentry, a.inode);
639
		inc_nlink(a.inode);
640
		a.inode->i_ctime = dir->i_ctime;
641
	} else
642
		/* nfs case (< 2.6.15) */
643
		d_drop(dentry);
644
	goto out_unlock; /* success */
645
646
 out_revert:
647
	vfsub_args_init(&vargs, NULL, a.dlgt, 0);
648
	rerr = vfsub_unlink(a.h_dir, a.h_dentry, &vargs);
649
	//rerr = -1;
650
	if (!rerr)
651
		goto out_dt;
652
// out_rerr:
653
	AuIOErr("%.*s reverting failed(%d, %d)\n",
654
		AuDLNPair(dentry), err, rerr);
655
	err = -EIO;
656
 out_dt:
657
	d_drop(dentry);
658
	au_dtime_revert(&dt);
659
 out_unlock:
660
	au_hdir_unlock(a.h_dir, dir, a.bdst);
661
	dput(wh_dentry);
662
 out:
663
	if (unlikely(err)) {
664
		au_update_dbstart(dentry);
665
		d_drop(dentry);
666
	}
667
	di_write_unlock(a.parent);
668
	dput(a.src_parent);
669
	aufs_read_and_write_unlock2(dentry, src_dentry);
670
	AuTraceErr(err);
671
	return err;
672
}
673
674
int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
675
{
676
	int err, rerr, diropq, dlgt;
677
	struct dentry *h_dentry, *h_parent, *wh_dentry, *parent, *opq_dentry;
678
	struct inode *h_dir, *h_inode;
679
	struct au_dtime dt;
680
	aufs_bindex_t bindex;
681
	struct super_block *sb;
682
	unsigned int mnt_flags;
683
	struct vfsub_args vargs;
684
	struct au_wr_dir_args wr_dir_args = {
685
		.force_btgt	= -1,
686
		.flags		= AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
687
	};
688
689
	LKTRTrace("i%lu, %.*s, mode 0%o\n",
690
		  dir->i_ino, AuDLNPair(dentry), mode);
691
	IMustLock(dir);
692
693
	aufs_read_lock(dentry, AuLock_DW);
694
	parent = dentry->d_parent; /* dir inode is locked */
695
	di_write_lock_parent(parent);
696
	wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
697
				      &wr_dir_args);
698
	//wh_dentry = ERR_PTR(-1);
699
	err = PTR_ERR(wh_dentry);
700
	if (IS_ERR(wh_dentry))
701
		goto out;
702
703
	sb = dentry->d_sb;
704
	bindex = au_dbstart(dentry);
705
	h_dentry = au_h_dptr(dentry, bindex);
706
	h_parent = h_dentry->d_parent; /* dir inode is locked */
707
	h_dir = h_parent->d_inode;
708
	IMustLock(h_dir);
709
	mnt_flags = au_mntflags(sb);
710
	dlgt = !!au_opt_test_dlgt(mnt_flags);
711
712
	err = vfsub_mkdir(h_dir, h_dentry, mode, dlgt);
713
	//err = -1;
714
	if (unlikely(err))
715
		goto out_unlock;
716
	h_inode = h_dentry->d_inode;
717
718
	/* make the dir opaque */
719
	diropq = 0;
720
	if (wh_dentry || au_opt_test(mnt_flags, ALWAYS_DIROPQ)) {
721
		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
722
		opq_dentry = au_diropq_create(dentry, bindex, /*dlgt*/0);
723
		//opq_dentry = ERR_PTR(-1);
724
		mutex_unlock(&h_inode->i_mutex);
725
		err = PTR_ERR(opq_dentry);
726
		if (IS_ERR(opq_dentry))
727
			goto out_dir;
728
		dput(opq_dentry);
729
		diropq = 1;
730
	}
731
732
	err = epilog(dir, wh_dentry, dentry);
733
	//err = -1;
734
	if (!err) {
735
		inc_nlink(dir);
736
		goto out_unlock; /* success */
737
	}
738
739
	/* revert */
740
	if (diropq) {
741
		LKTRLabel(revert opq);
742
		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
743
		rerr = au_diropq_remove(dentry, bindex, dlgt);
744
		//rerr = -1;
745
		mutex_unlock(&h_inode->i_mutex);
746
		if (rerr) {
747
			AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
748
				AuDLNPair(dentry), err, rerr);
749
			err = -EIO;
750
		}
751
	}
752
753
 out_dir:
754
	LKTRLabel(revert dir);
755
	vfsub_args_init(&vargs, NULL, dlgt, 0);
756
	rerr = vfsub_rmdir(h_dir, h_dentry, &vargs);
757
	//rerr = -1;
758
	if (rerr) {
759
		AuIOErr("%.*s reverting dir failed(%d, %d)\n",
760
			AuDLNPair(dentry), err, rerr);
761
		err = -EIO;
762
	}
763
	d_drop(dentry);
764
	au_dtime_revert(&dt);
765
 out_unlock:
766
	au_hdir_unlock(h_dir, dir, bindex);
767
	dput(wh_dentry);
768
 out:
769
	if (unlikely(err)) {
770
		au_update_dbstart(dentry);
771
		d_drop(dentry);
772
	}
773
	di_write_unlock(parent);
774
	aufs_read_unlock(dentry, AuLock_DW);
775
	AuTraceErr(err);
776
	return err;
777
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/i_op.c (+732 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * inode operations (except add/del/rename)
21
 *
22
 * $Id: i_op.c,v 1.5 2008/05/19 01:46:53 sfjro Exp $
23
 */
24
25
//#include <linux/fs.h>
26
#include <linux/fs_stack.h>
27
//#include <linux/namei.h>
28
//#include <linux/mm.h>
29
#include <linux/uaccess.h>
30
#include "aufs.h"
31
32
static int h_permission(struct inode *h_inode, int mask,
33
			struct nameidata *fake_nd, int brperm, int dlgt)
34
{
35
	int err, submask;
36
	const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
37
38
	LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
39
		  h_inode->i_ino, mask, brperm);
40
41
	err = -EACCES;
42
	if (unlikely((write_mask && IS_IMMUTABLE(h_inode))
43
		     || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode)
44
			 && fake_nd && fake_nd->path.mnt
45
			 && (fake_nd->path.mnt->mnt_flags & MNT_NOEXEC))
46
		    ))
47
		goto out;
48
49
	/* skip hidden fs test in the case of write to ro branch */
50
	submask = mask & ~MAY_APPEND;
51
	if (unlikely((write_mask && !au_br_writable(brperm))
52
		     || !h_inode->i_op
53
		     || !h_inode->i_op->permission)) {
54
		//LKTRLabel(generic_permission);
55
		err = generic_permission(h_inode, submask, NULL);
56
	} else {
57
		//LKTRLabel(h_inode->permission);
58
		err = h_inode->i_op->permission(h_inode, submask, fake_nd);
59
		AuTraceErr(err);
60
	}
61
62
	if (!err)
63
		err = au_security_inode_permission(h_inode, mask, fake_nd,
64
						   dlgt);
65
66
 out:
67
	AuTraceErr(err);
68
	return err;
69
}
70
71
static int silly_lock(struct inode *inode, struct nameidata *nd)
72
{
73
	int locked = 0;
74
	struct super_block *sb = inode->i_sb;
75
76
	LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
77
78
	if (!nd || !nd->path.dentry) {
79
		si_read_lock(sb, AuLock_FLUSH);
80
		ii_read_lock_child(inode);
81
	} else if (nd->path.dentry->d_inode != inode) {
82
		locked = 1;
83
		/* lock child first, then parent */
84
		si_read_lock(sb, AuLock_FLUSH);
85
		ii_read_lock_child(inode);
86
		di_read_lock_parent(nd->path.dentry, 0);
87
	} else {
88
		locked = 2;
89
		aufs_read_lock(nd->path.dentry, AuLock_FLUSH | AuLock_IR);
90
	}
91
	return locked;
92
}
93
94
static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd)
95
{
96
	struct super_block *sb = inode->i_sb;
97
98
	LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd);
99
100
	switch (locked) {
101
	case 0:
102
		ii_read_unlock(inode);
103
		si_read_unlock(sb);
104
		break;
105
	case 1:
106
		di_read_unlock(nd->path.dentry, 0);
107
		ii_read_unlock(inode);
108
		si_read_unlock(sb);
109
		break;
110
	case 2:
111
		aufs_read_unlock(nd->path.dentry, AuLock_FLUSH | AuLock_IR);
112
		break;
113
	default:
114
		BUG();
115
	}
116
}
117
118
static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
119
{
120
	int err, locked, dlgt;
121
	aufs_bindex_t bindex, bend;
122
	struct inode *h_inode;
123
	struct super_block *sb;
124
	unsigned int mnt_flags;
125
	struct nameidata fake_nd, *p;
126
	const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
127
	const int nondir = !S_ISDIR(inode->i_mode);
128
129
	LKTRTrace("ino %lu, mask 0x%x, nondir %d, write_mask %d, "
130
		  "nd %d{%d, %d}\n",
131
		  inode->i_ino, mask, nondir, write_mask,
132
		  !!nd, nd ? !!nd->path.dentry : 0, nd ? !!nd->path.mnt : 0);
133
134
	sb = inode->i_sb;
135
	locked = silly_lock(inode, nd);
136
	mnt_flags = au_mntflags(sb);
137
	dlgt = !!au_opt_test_dlgt(mnt_flags);
138
139
	if (nd)
140
		fake_nd = *nd;
141
	if (/* unlikely */(nondir || write_mask
142
			   || au_opt_test_dirperm1(mnt_flags))) {
143
		h_inode = au_h_iptr(inode, au_ibstart(inode));
144
		AuDebugOn(!h_inode
145
			  || ((h_inode->i_mode & S_IFMT)
146
			      != (inode->i_mode & S_IFMT)));
147
		err = 0;
148
		bindex = au_ibstart(inode);
149
		p = au_fake_dm(&fake_nd, nd, sb, bindex);
150
		/* actual test will be delegated to LSM */
151
		if (IS_ERR(p))
152
			AuDebugOn(PTR_ERR(p) != -ENOENT);
153
		else {
154
			LKTRTrace("b%d\n", bindex);
155
			err = h_permission(h_inode, mask, p,
156
					   au_sbr_perm(sb, bindex), dlgt);
157
			au_fake_dm_release(p);
158
		}
159
		if (write_mask && !err) {
160
			/* test whether the upper writable branch exists */
161
			err = -EROFS;
162
			for (; bindex >= 0; bindex--)
163
				if (!au_br_rdonly(au_sbr(sb, bindex))) {
164
					err = 0;
165
					break;
166
				}
167
		}
168
		goto out;
169
	}
170
171
	/* non-write to dir */
172
	err = 0;
173
	bend = au_ibend(inode);
174
	for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
175
		h_inode = au_h_iptr(inode, bindex);
176
		if (!h_inode)
177
			continue;
178
		AuDebugOn(!S_ISDIR(h_inode->i_mode));
179
180
		p = au_fake_dm(&fake_nd, nd, sb, bindex);
181
		/* actual test will be delegated to LSM */
182
		if (IS_ERR(p))
183
			AuDebugOn(PTR_ERR(p) != -ENOENT);
184
		else {
185
			LKTRTrace("b%d\n", bindex);
186
			err = h_permission(h_inode, mask, p,
187
					   au_sbr_perm(sb, bindex), dlgt);
188
			au_fake_dm_release(p);
189
		}
190
	}
191
192
 out:
193
	silly_unlock(locked, inode, nd);
194
	AuTraceErr(err);
195
	return err;
196
}
197
198
/* ---------------------------------------------------------------------- */
199
200
static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
201
				  struct nameidata *nd)
202
{
203
	struct dentry *ret, *parent;
204
	int err, npositive;
205
	struct inode *inode, *h_inode;
206
	struct nameidata tmp_nd, *ndp;
207
208
	LKTRTrace("dir %lu, %.*s, nd{0x%x}\n",
209
		  dir->i_ino, AuDLNPair(dentry), nd ? nd->flags : 0);
210
	AuDebugOn(IS_ROOT(dentry));
211
	IMustLock(dir);
212
213
	/* nd can be NULL */
214
	parent = dentry->d_parent; /* dir inode is locked */
215
	aufs_read_lock(parent, AuLock_FLUSH);
216
	err = au_alloc_dinfo(dentry);
217
	//if (LktrCond) err = -1;
218
	ret = ERR_PTR(err);
219
	if (unlikely(err))
220
		goto out;
221
222
	ndp = au_dup_nd(au_sbi(dir->i_sb), &tmp_nd, nd);
223
	npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, ndp);
224
	err = npositive;
225
	//err = -1;
226
	ret = ERR_PTR(err);
227
	if (unlikely(err < 0))
228
		goto out_unlock;
229
	inode = NULL;
230
	if (npositive) {
231
		/*
232
		 * stop 'race'-ing between hardlinks under different parents.
233
		 */
234
		h_inode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
235
		AuDebugOn(!h_inode);
236
		if (h_inode->i_nlink == 1 || S_ISDIR(h_inode->i_mode))
237
			inode = au_new_inode(dentry);
238
		else {
239
			static DEFINE_MUTEX(mtx);
240
			mutex_lock(&mtx);
241
			inode = au_new_inode(dentry);
242
			mutex_unlock(&mtx);
243
		}
244
		ret = (void *)inode;
245
	}
246
	if (!IS_ERR(inode)) {
247
		/* d_splice_alias() also supports d_add() */
248
		ret = d_splice_alias(inode, dentry);
249
		if (unlikely(IS_ERR(ret) && inode))
250
			ii_write_unlock(inode);
251
		//AuDbgDentry(dentry);
252
		AuDebugOn(nd
253
			  && (nd->flags & LOOKUP_OPEN)
254
			  && nd->intent.open.file
255
			  && nd->intent.open.file->f_dentry);
256
		au_store_fmode_exec(nd, inode);
257
	}
258
259
 out_unlock:
260
	di_write_unlock(dentry);
261
 out:
262
	aufs_read_unlock(parent, !AuLock_IR);
263
	AuTraceErrPtr(ret);
264
	return ret;
265
}
266
267
/* ---------------------------------------------------------------------- */
268
269
/*
270
 * decide the branch and the parent dir where we will create a new entry.
271
 * returns new bindex or an error.
272
 * copyup the parent dir if needed.
273
 */
274
int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
275
	      struct au_wr_dir_args *args)
276
{
277
	int err;
278
	aufs_bindex_t bcpup, bstart, src_bstart;
279
	struct super_block *sb;
280
	struct dentry *parent, *src_parent;
281
	struct au_sbinfo *sbinfo;
282
	const int add_entry = au_ftest_wrdir(args->flags, ADD_ENTRY);
283
	const int lock_srcdir = au_ftest_wrdir(args->flags, LOCK_SRCDIR);
284
285
	LKTRTrace("%.*s, src %p, {%d, 0x%x}\n",
286
		  AuDLNPair(dentry), src_dentry, args->force_btgt, args->flags);
287
	//AuDbgDentry(dentry);
288
289
	src_parent = NULL;
290
	sb = dentry->d_sb;
291
	sbinfo = au_sbi(sb);
292
	parent = dget_parent(dentry);
293
	bstart = au_dbstart(dentry);
294
	bcpup = bstart;
295
	if (args->force_btgt < 0) {
296
		if (src_dentry) {
297
			src_bstart = au_dbstart(src_dentry);
298
			if (src_bstart < bstart)
299
				bcpup = src_bstart;
300
		} else if (add_entry) {
301
			err = AuWbrCreate(sbinfo, dentry,
302
					  au_ftest_wrdir(args->flags, ISDIR));
303
			bcpup = err;
304
		}
305
306
		if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
307
			if (add_entry)
308
				err = AuWbrCopyup(sbinfo, dentry);
309
			else {
310
				di_read_lock_parent(parent, !AuLock_IR);
311
				err = AuWbrCopyup(sbinfo, dentry);
312
				di_read_unlock(parent, !AuLock_IR);
313
			}
314
			//err = -1;
315
			bcpup = err;
316
			if (unlikely(err < 0))
317
				goto out;
318
		}
319
	} else {
320
		bcpup = args->force_btgt;
321
		AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
322
	}
323
	LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
324
	if (bstart < bcpup)
325
		au_update_dbrange(dentry, /*do_put_zero*/1);
326
327
	err = bcpup;
328
	if (bcpup == bstart)
329
		goto out; /* success */
330
331
	/* copyup the new parent into the branch we process */
332
	if (src_dentry) {
333
		src_parent = dget_parent(src_dentry);
334
		if (lock_srcdir)
335
			di_write_lock_parent2(src_parent);
336
	}
337
338
	if (add_entry) {
339
		au_update_dbstart(dentry);
340
		IMustLock(parent->d_inode);
341
		DiMustWriteLock(parent);
342
		IiMustWriteLock(parent->d_inode);
343
	} else
344
		di_write_lock_parent(parent);
345
346
	err = 0;
347
	if (!au_h_dptr(parent, bcpup)) {
348
		if (bstart < bcpup)
349
			err = au_cpdown_dirs(dentry, bcpup, src_parent);
350
		else
351
			err = au_cpup_dirs(dentry, bcpup, src_parent);
352
	}
353
	//err = -1;
354
	if (!err && add_entry) {
355
		struct dentry *h_parent;
356
		struct inode *h_dir;
357
358
		h_parent = au_h_dptr(parent, bcpup);
359
		AuDebugOn(!h_parent);
360
		h_dir = h_parent->d_inode;
361
		AuDebugOn(!h_dir);
362
		mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
363
		err = au_lkup_neg(dentry, bcpup);
364
		//err = -1;
365
		mutex_unlock(&h_dir->i_mutex);
366
		if (bstart < bcpup && au_dbstart(dentry) < 0) {
367
			au_set_dbstart(dentry, 0);
368
			au_update_dbrange(dentry, /*do_put_zero*/0);
369
		}
370
	}
371
372
	if (!add_entry)
373
		di_write_unlock(parent);
374
	if (lock_srcdir)
375
		di_write_unlock(src_parent);
376
	dput(src_parent);
377
	if (!err)
378
		err = bcpup; /* success */
379
	//err = -EPERM;
380
 out:
381
	dput(parent);
382
	LKTRTrace("err %d\n", err);
383
	AuTraceErr(err);
384
	return err;
385
}
386
387
/* ---------------------------------------------------------------------- */
388
389
static void au_hi_lock(struct inode *h_inode, int isdir, struct inode *inode,
390
		       aufs_bindex_t bindex)
391
{
392
	if (!isdir)
393
		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
394
	else
395
		au_hdir2_lock(h_inode, inode, bindex);
396
}
397
398
static void au_hi_unlock(struct inode *h_inode, int isdir, struct inode *inode,
399
			 aufs_bindex_t bindex)
400
{
401
	if (!isdir)
402
		mutex_unlock(&h_inode->i_mutex);
403
	else
404
		au_hdir_unlock(h_inode, inode, bindex);
405
}
406
407
struct au_icpup_args {
408
	aufs_bindex_t btgt;
409
	unsigned char isdir, did_cpup; /* flags */
410
	unsigned char hinotify;
411
	struct dentry *parent, *gparent, *h_dentry;
412
	struct inode *dir, *gdir, *h_inode, *h_dir;
413
};
414
415
static int au_lock_and_icpup(struct dentry *dentry, loff_t sz,
416
			     struct au_icpup_args *rargs)
417
{
418
	int err;
419
	aufs_bindex_t bstart;
420
	struct super_block *sb;
421
	struct dentry *hi_wh;
422
	struct inode *inode;
423
	struct au_wr_dir_args wr_dir_args = {
424
		.force_btgt	= -1,
425
		.flags		= 0
426
	};
427
428
	LKTRTrace("%.*s, %lld\n", AuDLNPair(dentry), sz);
429
430
	di_write_lock_child(dentry);
431
	bstart = au_dbstart(dentry);
432
	sb = dentry->d_sb;
433
	inode = dentry->d_inode;
434
	rargs->isdir = S_ISDIR(inode->i_mode);
435
	if (rargs->isdir)
436
		au_fset_wrdir(wr_dir_args.flags, ISDIR);
437
	err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
438
	//err = -1;
439
	if (unlikely(err < 0))
440
		goto out_dentry;
441
	rargs->btgt = err;
442
	rargs->did_cpup = (err != bstart);
443
	err = 0;
444
445
	/* crazy udba locks */
446
	rargs->hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY);
447
	if (unlikely(!IS_ROOT(dentry))) {
448
		rargs->parent = dget_parent(dentry);
449
		rargs->dir = rargs->parent->d_inode;
450
		di_read_lock_parent(rargs->parent, AuLock_IR);
451
	}
452
	rargs->h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
453
	rargs->h_inode = rargs->h_dentry->d_inode;
454
	AuDebugOn(!rargs->h_inode);
455
456
	if (!rargs->did_cpup) {
457
		au_hi_lock(rargs->h_inode, rargs->isdir, inode, rargs->btgt);
458
		//todo: revalidate the lower dentry?
459
		goto out; /* success */
460
	}
461
462
	if (unlikely(rargs->hinotify
463
		     && rargs->parent
464
		     && !IS_ROOT(rargs->parent))) {
465
		rargs->gparent = dget_parent(rargs->parent);
466
		rargs->gdir = rargs->gparent->d_inode;
467
		ii_read_lock_parent2(rargs->gdir);
468
	}
469
470
	hi_wh = NULL;
471
	rargs->h_dir = au_h_iptr(rargs->dir, rargs->btgt);
472
	au_hdir_lock(rargs->h_dir, rargs->dir, rargs->btgt);
473
	//todo: revalidate the lower dentry?
474
	au_hi_lock(rargs->h_inode, rargs->isdir, inode, bstart);
475
	if (!d_unhashed(dentry)) {
476
		err = au_sio_cpup_simple(dentry, rargs->btgt, sz, AuCpup_DTIME);
477
		if (!err)
478
			rargs->h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
479
	} else {
480
		hi_wh = au_hi_wh(inode, rargs->btgt);
481
		if (!hi_wh) {
482
			err = au_sio_cpup_wh(dentry, rargs->btgt, sz,
483
					     /*file*/NULL);
484
			if (!err)
485
				hi_wh = au_hi_wh(inode, rargs->btgt);
486
		}
487
		if (!hi_wh)
488
			rargs->h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
489
		else
490
			rargs->h_dentry = hi_wh; /* do not dget here */
491
	}
492
493
	//err = -1;
494
	au_hi_unlock(rargs->h_inode, rargs->isdir, inode, bstart);
495
	rargs->h_inode = rargs->h_dentry->d_inode;
496
	AuDebugOn(!rargs->h_inode);
497
	if (!err)
498
		au_hi_lock(rargs->h_inode, rargs->isdir, inode, rargs->btgt);
499
	au_hdir_unlock(rargs->h_dir, rargs->dir, rargs->btgt);
500
	if (!err)
501
		goto out; /* success */
502
503
	au_hi_unlock(rargs->h_inode, rargs->isdir, inode, rargs->btgt);
504
	if (unlikely(rargs->gdir)) {
505
		ii_read_unlock(rargs->gdir);
506
		dput(rargs->gparent);
507
	}
508
	if (unlikely(rargs->dir)) {
509
		di_read_unlock(rargs->parent, AuLock_IR);
510
		dput(rargs->parent);
511
	}
512
513
 out_dentry:
514
	di_write_unlock(dentry);
515
 out:
516
	AuTraceErr(err);
517
	return err;
518
}
519
520
static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
521
{
522
	int err;
523
	struct inode *inode;
524
	struct au_hin_ignore ign;
525
	struct vfsub_args vargs;
526
	struct super_block *sb;
527
	__u32 events;
528
	struct file *file;
529
	loff_t sz;
530
	struct au_icpup_args rargs;
531
532
	LKTRTrace("%.*s, ia_valid 0x%x\n", AuDLNPair(dentry), ia->ia_valid);
533
	inode = dentry->d_inode;
534
	IMustLock(inode);
535
536
	sb = dentry->d_sb;
537
	si_read_lock(sb, AuLock_FLUSH);
538
539
	file = NULL;
540
	if (ia->ia_valid & ATTR_FILE) {
541
		/* currently ftruncate(2) only */
542
		file = ia->ia_file;
543
		fi_write_lock(file);
544
		ia->ia_file = au_h_fptr(file, au_fbstart(file));
545
	}
546
547
	sz = -1;
548
	if ((ia->ia_valid & ATTR_SIZE)
549
	    && ia->ia_size < i_size_read(inode))
550
		sz = ia->ia_size;
551
	memset(&rargs, 0, sizeof(rargs));
552
	err = au_lock_and_icpup(dentry, sz, &rargs);
553
	if (unlikely(err < 0))
554
		goto out;
555
556
	if ((ia->ia_valid & ATTR_SIZE)
557
	    && ia->ia_size < i_size_read(inode)) {
558
		err = vmtruncate(inode, ia->ia_size);
559
		if (unlikely(err))
560
			goto out_unlock;
561
	}
562
563
	if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
564
		ia->ia_valid &= ~ATTR_MODE;
565
566
	events = 0;
567
	vfsub_args_init(&vargs, &ign, au_opt_test_dlgt(au_mntflags(sb)), 0);
568
	if (unlikely(rargs.hinotify && rargs.dir)) {
569
		events = vfsub_events_notify_change(ia);
570
		if (events)
571
			vfsub_ign_hinode(&vargs, events,
572
					 au_hi(rargs.dir, rargs.btgt));
573
	}
574
	err = vfsub_notify_change(rargs.h_dentry, ia, &vargs);
575
	//err = -1;
576
	if (!err)
577
		au_cpup_attr_changeable(inode);
578
579
 out_unlock:
580
	au_hi_unlock(rargs.h_inode, rargs.isdir, inode, rargs.btgt);
581
	if (unlikely(rargs.gdir)) {
582
		ii_read_unlock(rargs.gdir);
583
		dput(rargs.gparent);
584
	}
585
	if (unlikely(rargs.dir)) {
586
		di_read_unlock(rargs.parent, AuLock_IR);
587
		dput(rargs.parent);
588
	}
589
	di_write_unlock(dentry);
590
 out:
591
	if (file) {
592
		ia->ia_file = file;
593
		//ia->ia_valid |= ATTR_FILE;
594
		fi_write_unlock(file);
595
	}
596
	si_read_unlock(sb);
597
	AuTraceErr(err);
598
	return err;
599
}
600
601
/* ---------------------------------------------------------------------- */
602
603
static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
604
		      int bufsiz)
605
{
606
	struct super_block *sb;
607
	struct dentry *h_dentry;
608
609
	LKTRTrace("%.*s, b%d, %d\n", AuDLNPair(dentry), bindex, bufsiz);
610
611
	h_dentry = au_h_dptr(dentry, bindex);
612
	if (unlikely(!h_dentry->d_inode->i_op
613
		     || !h_dentry->d_inode->i_op->readlink))
614
		return -EINVAL;
615
616
	sb = dentry->d_sb;
617
	if (!au_test_ro(sb, bindex, dentry->d_inode)) {
618
		touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
619
		au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
620
		fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
621
	}
622
	return h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
623
}
624
625
static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
626
{
627
	int err;
628
629
	LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), bufsiz);
630
631
	aufs_read_lock(dentry, AuLock_IR);
632
	err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
633
	//err = -1;
634
	aufs_read_unlock(dentry, AuLock_IR);
635
	AuTraceErr(err);
636
	return err;
637
}
638
639
static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
640
{
641
	int err;
642
	char *buf;
643
	mm_segment_t old_fs;
644
645
	LKTRTrace("%.*s, nd %.*s\n",
646
		  AuDLNPair(dentry), AuDLNPair(nd->path.dentry));
647
648
	err = -ENOMEM;
649
	buf = __getname();
650
	//buf = NULL;
651
	if (unlikely(!buf))
652
		goto out;
653
654
	aufs_read_lock(dentry, AuLock_IR);
655
	old_fs = get_fs();
656
	set_fs(KERNEL_DS);
657
	err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
658
			 PATH_MAX);
659
	//err = -1;
660
	set_fs(old_fs);
661
	aufs_read_unlock(dentry, AuLock_IR);
662
663
	if (err >= 0) {
664
		buf[err] = 0;
665
		/* will be freed by put_link */
666
		nd_set_link(nd, buf);
667
		return NULL; /* success */
668
	}
669
	__putname(buf);
670
671
 out:
672
	path_put(&nd->path);
673
	AuTraceErr(err);
674
	return ERR_PTR(err);
675
}
676
677
static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
678
			  void *cookie)
679
{
680
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
681
	__putname(nd_get_link(nd));
682
}
683
684
/* ---------------------------------------------------------------------- */
685
686
static void aufs_truncate_range(struct inode *inode, loff_t start, loff_t end)
687
{
688
	AuUnsupport();
689
}
690
691
/* ---------------------------------------------------------------------- */
692
693
struct inode_operations aufs_symlink_iop = {
694
	.permission	= aufs_permission,
695
	.setattr	= aufs_setattr,
696
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
697
	.getattr	= aufs_getattr,
698
#endif
699
700
	.readlink	= aufs_readlink,
701
	.follow_link	= aufs_follow_link,
702
	.put_link	= aufs_put_link
703
};
704
705
struct inode_operations aufs_dir_iop = {
706
	.create		= aufs_create,
707
	.lookup		= aufs_lookup,
708
	.link		= aufs_link,
709
	.unlink		= aufs_unlink,
710
	.symlink	= aufs_symlink,
711
	.mkdir		= aufs_mkdir,
712
	.rmdir		= aufs_rmdir,
713
	.mknod		= aufs_mknod,
714
	.rename		= aufs_rename,
715
716
	.permission	= aufs_permission,
717
	.setattr	= aufs_setattr,
718
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
719
	.getattr	= aufs_getattr,
720
#endif
721
};
722
723
struct inode_operations aufs_iop = {
724
	.permission	= aufs_permission,
725
	.setattr	= aufs_setattr,
726
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
727
	.getattr	= aufs_getattr,
728
#endif
729
730
	//void (*truncate) (struct inode *);
731
	.truncate_range	= aufs_truncate_range,
732
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/i_op_del.c (+566 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * inode operations (del entry)
21
 *
22
 * $Id: i_op_del.c,v 1.4 2008/05/04 23:54:53 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
/* returns,
28
 * 0: wh is unnecessary
29
 * plus: wh is necessary
30
 * minus: error
31
 */
32
int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
33
		      struct dentry *locked)
34
{
35
	int need_wh, err;
36
	aufs_bindex_t bstart;
37
	struct dentry *h_dentry;
38
	struct super_block *sb;
39
40
	LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
41
		  AuDLNPair(dentry), isdir, *bcpup, locked);
42
	sb = dentry->d_sb;
43
44
	bstart = au_dbstart(dentry);
45
	LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
46
	h_dentry = au_h_dptr(dentry, bstart);
47
	if (*bcpup < 0) {
48
		*bcpup = bstart;
49
		if (au_test_ro(sb, bstart, dentry->d_inode)) {
50
			err = AuWbrCopyup(au_sbi(sb), dentry);
51
			*bcpup = err;
52
			//err = -1;
53
			if (unlikely(err < 0))
54
				goto out;
55
		}
56
	} else
57
		AuDebugOn(bstart < *bcpup
58
			  || au_test_ro(sb, *bcpup, dentry->d_inode));
59
	LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
60
61
	if (*bcpup != bstart) {
62
		err = au_cpup_dirs(dentry, *bcpup, locked);
63
		//err = -1;
64
		if (unlikely(err))
65
			goto out;
66
		need_wh = 1;
67
	} else {
68
		//struct nameidata nd;
69
		aufs_bindex_t old_bend, new_bend, bdiropq = -1;
70
		old_bend = au_dbend(dentry);
71
		if (isdir) {
72
			bdiropq = au_dbdiropq(dentry);
73
			au_set_dbdiropq(dentry, -1);
74
		}
75
		need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
76
					 /*nd*/NULL);
77
		err = need_wh;
78
		//err = -1;
79
		if (isdir)
80
			au_set_dbdiropq(dentry, bdiropq);
81
		if (unlikely(err < 0))
82
			goto out;
83
		new_bend = au_dbend(dentry);
84
		if (!need_wh && old_bend != new_bend) {
85
			au_set_h_dptr(dentry, new_bend, NULL);
86
			au_set_dbend(dentry, old_bend);
87
		}
88
	}
89
	LKTRTrace("need_wh %d\n", need_wh);
90
	err = need_wh;
91
92
 out:
93
	AuTraceErr(err);
94
	return err;
95
}
96
97
/*
98
 * simple tests for the removal inode operations.
99
 * following the checks in vfs, plus the parent-child relationship.
100
 */
101
int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
102
	       struct dentry *h_parent, int isdir, struct au_ndx *ndx)
103
{
104
	int err, exist;
105
	struct super_block *sb;
106
	struct dentry *h_dentry;
107
	struct inode *h_inode;
108
	umode_t h_mode;
109
110
	LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
111
		  AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);
112
113
	sb = dentry->d_sb;
114
	exist = !!dentry->d_inode;
115
	h_dentry = au_h_dptr(dentry, bindex);
116
	h_inode = h_dentry->d_inode;
117
	if (exist) {
118
		err = -ENOENT;
119
		if (unlikely(!h_inode || !h_inode->i_nlink))
120
			goto out;
121
122
		h_mode = h_inode->i_mode;
123
		if (!isdir) {
124
			err = -EISDIR;
125
			if (unlikely(S_ISDIR(h_mode)))
126
				goto out;
127
		} else if (unlikely(!S_ISDIR(h_mode))) {
128
			err = -ENOTDIR;
129
			goto out;
130
		}
131
	} else {
132
		/* rename(2) case */
133
		err = -EIO;
134
		if (unlikely(h_inode))
135
			goto out;
136
	}
137
138
	err = -ENOENT;
139
	/* expected parent dir is locked */
140
	if (unlikely(h_parent != h_dentry->d_parent))
141
		goto out;
142
	err = 0;
143
144
	/*
145
	 * some filesystem may unlink a dir and corrupt its consistency.
146
	 * so let's try heavy test.
147
	 */
148
	if (1 /*unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY))*/) {
149
		struct dentry *h_latest;
150
		struct qstr *qstr = &dentry->d_name;
151
152
		err = -EACCES;
153
		if (unlikely(au_test_h_perm(h_parent->d_inode,
154
					    MAY_EXEC | MAY_WRITE,
155
					    au_ftest_ndx(ndx->flags, DLGT))))
156
			goto out;
157
158
		h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
159
					   ndx);
160
		//err = PTR_ERR(h_latest);
161
		err = -EIO;
162
		if (IS_ERR(h_latest))
163
			goto out;
164
		dput(h_latest);
165
		if (h_latest == h_dentry)
166
			err = 0;
167
	}
168
169
 out:
170
	AuTraceErr(err);
171
	return err;
172
}
173
174
static struct dentry *
175
lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
176
		    struct au_dtime *dt)
177
{
178
	struct dentry *wh_dentry;
179
	int err, need_wh;
180
	struct dentry *h_parent, *parent, *gparent;
181
	struct inode *dir, *h_dir, *gdir;
182
	struct au_ndx ndx;
183
	struct super_block *sb;
184
	struct au_hinode *hgdir;
185
	aufs_bindex_t bcpup;
186
	unsigned int mnt_flags;
187
188
	LKTRTrace("%.*s, isdir %d\n", AuDLNPair(dentry), isdir);
189
190
	need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup, NULL);
191
	err = need_wh;
192
	//err = -1;
193
	wh_dentry = ERR_PTR(err);
194
	if (unlikely(err < 0))
195
		goto out;
196
197
	//todo: meaningless lock if CONFIG_AUFS_DEBUG is disabled.
198
	hgdir = NULL;
199
	bcpup = *rbcpup;
200
	sb = dentry->d_sb;
201
	mnt_flags = au_mntflags(sb);
202
	parent = dentry->d_parent; /* dir inode is locked */
203
	if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
204
		     && !IS_ROOT(parent))) {
205
		gparent = dget_parent(parent);
206
		gdir = gparent->d_inode;
207
		ii_read_lock_parent2(gdir);
208
		hgdir = au_hi(gdir, bcpup);
209
		ii_read_unlock(gdir);
210
		dput(gparent);
211
	}
212
	dir = parent->d_inode;
213
	IMustLock(dir);
214
	h_parent = au_h_dptr(parent, bcpup);
215
	h_dir = h_parent->d_inode;
216
217
	AuDbgSleep_UdbaRace();
218
	au_hdir_lock(h_dir, dir, bcpup);
219
	//todo: revalidate the lower dentry?
220
221
	if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) {
222
		ndx.nfsmnt = au_nfsmnt(sb, bcpup);
223
		ndx.flags = 0;
224
		if (unlikely(au_opt_test_dlgt(mnt_flags)))
225
			au_fset_ndx(ndx.flags, DLGT);
226
		ndx.nd = NULL;
227
		//ndx.br = au_sbr(sb, bcpup);
228
		//ndx.nd_file = NULL;
229
		err = au_may_del(dentry, bcpup, h_parent, isdir, &ndx);
230
		wh_dentry = ERR_PTR(err);
231
		if (unlikely(err))
232
			goto out_dir;
233
	}
234
235
	au_dtime_store(dt, parent, h_parent, hgdir);
236
	wh_dentry = NULL;
237
	if (!need_wh)
238
		goto out; /* success, no need to create whiteout */
239
240
	ndx.nfsmnt = au_nfsmnt(sb, bcpup);
241
	ndx.flags = 0;
242
	if (unlikely(au_opt_test_dlgt(mnt_flags)))
243
		au_fset_ndx(ndx.flags, DLGT);
244
	ndx.nd = NULL;
245
	//ndx.br = NULL;
246
	wh_dentry = au_wh_create(dir, dentry, bcpup, h_parent, &ndx);
247
	//wh_dentry = ERR_PTR(-1);
248
	if (!IS_ERR(wh_dentry))
249
		goto out; /* success */
250
	/* returns with the parent is locked and wh_dentry is DGETed */
251
252
 out_dir:
253
	au_hdir_unlock(h_dir, dir, bcpup);
254
 out:
255
	AuTraceErrPtr(wh_dentry);
256
	return wh_dentry;
257
}
258
259
static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
260
			   struct au_nhash *whlist, struct inode *dir)
261
{
262
	int rmdir_later, err;
263
	struct dentry *h_dentry;
264
	struct inode *inode, *h_inode;
265
	struct super_block *sb;
266
267
	LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
268
269
	inode = NULL;
270
	h_inode = NULL;
271
	sb = dentry->d_sb;
272
	if (unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY))) {
273
		inode = dentry->d_inode;
274
		h_inode = au_h_iptr(inode, bindex);
275
		au_hdir2_lock(h_inode, inode, bindex);
276
	}
277
	err = au_whtmp_ren(dir, dentry, bindex, /*noself*/1);
278
	if (unlikely(inode))
279
		au_hdir_unlock(h_inode, inode, bindex);
280
	//err = -1;
281
	if (unlikely(err))
282
		goto out;
283
284
	h_dentry = au_h_dptr(dentry, bindex);
285
	if (!au_test_nfs(h_dentry->d_sb)) {
286
		const int dirwh = au_sbi(sb)->si_dirwh;
287
		rmdir_later = (dirwh <= 1);
288
		if (!rmdir_later)
289
			rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
290
							      dirwh);
291
		if (rmdir_later)
292
			return rmdir_later;
293
	}
294
295
	err = au_whtmp_rmdir(h_dentry, whlist, bindex, dir, dentry->d_inode,
296
			     /*noself*/1);
297
	//err = -1;
298
	if (unlikely(err)) {
299
		AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
300
			AuDLNPair(h_dentry), bindex, err);
301
		err = 0;
302
	}
303
304
 out:
305
	AuTraceErr(err);
306
	return err;
307
}
308
309
static void epilog(struct inode *dir, struct dentry *dentry,
310
		   aufs_bindex_t bindex)
311
{
312
	//todo: unnecessary?
313
	d_drop(dentry);
314
	dentry->d_inode->i_ctime = dir->i_ctime;
315
316
	if (atomic_read(&dentry->d_count) == 1) {
317
		au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
318
		au_update_dbstart(dentry);
319
	}
320
	if (au_ibstart(dir) == bindex)
321
		au_cpup_attr_timesizes(dir);
322
	dir->i_version++;
323
}
324
325
/* revert flags */
326
#define AuRev_DLGT	1
327
#define au_ftest_rev(flags, name)	((flags) & AuRev_##name)
328
#define au_fset_rev(flags, name)	{ (flags) |= AuRev_##name; }
329
#define au_fclr_rev(flags, name)	{ (flags) &= ~AuRev_##name; }
330
#ifndef CONFIG_AUFS_DLGT
331
#undef AuRev_DLGT
332
#define AuRev_DLGT	0
333
#endif
334
335
static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
336
		     aufs_bindex_t bwh, struct au_dtime *dt, unsigned int flags)
337
{
338
	int rerr;
339
	struct inode *dir;
340
341
	dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
342
	IMustLock(dir);
343
	rerr = au_wh_unlink_dentry(dir, wh_dentry, dentry, dir,
344
				   au_ftest_rev(flags, DLGT));
345
	//rerr = -1;
346
	if (!rerr) {
347
		au_set_dbwh(dentry, bwh);
348
		au_dtime_revert(dt);
349
		return 0;
350
	}
351
352
	AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
353
		AuDLNPair(dentry), err, rerr);
354
	return -EIO;
355
}
356
357
/* ---------------------------------------------------------------------- */
358
359
int aufs_unlink(struct inode *dir, struct dentry *dentry)
360
{
361
	int err, dlgt;
362
	struct inode *inode, *h_dir;
363
	struct dentry *parent, *wh_dentry, *h_dentry;
364
	struct au_dtime dt;
365
	aufs_bindex_t bwh, bindex, bstart;
366
	struct super_block *sb;
367
	struct vfsub_args vargs;
368
369
	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
370
	IMustLock(dir);
371
	inode = dentry->d_inode;
372
	if (unlikely(!inode))
373
		return -ENOENT; /* possible? */
374
	IMustLock(inode);
375
376
	aufs_read_lock(dentry, AuLock_DW);
377
	parent = dentry->d_parent; /* dir inode is locked */
378
	di_write_lock_parent(parent);
379
380
	bstart = au_dbstart(dentry);
381
	bwh = au_dbwh(dentry);
382
	bindex = -1;
383
	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt);
384
	//wh_dentry = ERR_PTR(-1);
385
	err = PTR_ERR(wh_dentry);
386
	if (IS_ERR(wh_dentry))
387
		goto out;
388
389
	sb = dir->i_sb;
390
	dlgt = !!au_opt_test_dlgt(au_mntflags(sb));
391
	AuDebugOn(au_dbstart(dentry) != bstart);
392
	h_dentry = au_h_dptr(dentry, bstart);
393
	dget(h_dentry);
394
395
	if (bindex == bstart) {
396
		vfsub_args_init(&vargs, NULL, dlgt, 0);
397
		h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
398
		IMustLock(h_dir);
399
		err = vfsub_unlink(h_dir, h_dentry, &vargs);
400
		//err = -1;
401
	} else {
402
		/* dir inode is locked */
403
		AuDebugOn(!wh_dentry
404
			  || wh_dentry->d_parent != au_h_dptr(parent, bindex));
405
		h_dir = wh_dentry->d_parent->d_inode;
406
		IMustLock(h_dir);
407
		err = 0;
408
	}
409
410
	if (!err) {
411
		drop_nlink(inode);
412
		epilog(dir, dentry, bindex);
413
414
		/* update target timestamps */
415
		if (bindex == bstart) {
416
			au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
417
			inode->i_ctime = h_dentry->d_inode->i_ctime;
418
		} else
419
			//todo: this timestamp may be reverted later
420
			inode->i_ctime = h_dir->i_ctime;
421
		goto out_unlock; /* success */
422
	}
423
424
	/* revert */
425
	if (wh_dentry) {
426
		int rerr;
427
		unsigned int rev_flags;
428
429
		rev_flags = 0;
430
		if (unlikely(dlgt))
431
			au_fset_rev(rev_flags, DLGT);
432
		rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, rev_flags);
433
		if (rerr)
434
			err = rerr;
435
	}
436
437
 out_unlock:
438
	au_hdir_unlock(h_dir, dir, bindex);
439
	dput(wh_dentry);
440
	dput(h_dentry);
441
 out:
442
	di_write_unlock(parent);
443
	aufs_read_unlock(dentry, AuLock_DW);
444
	AuTraceErr(err);
445
	return err;
446
}
447
448
int aufs_rmdir(struct inode *dir, struct dentry *dentry)
449
{
450
	int err, rmdir_later;
451
	struct inode *inode, *h_dir;
452
	struct dentry *parent, *wh_dentry, *h_dentry;
453
	struct au_dtime dt;
454
	aufs_bindex_t bwh, bindex, bstart;
455
	struct au_whtmp_rmdir_args *args;
456
	struct au_nhash *whlist;
457
	struct super_block *sb;
458
	unsigned int mnt_flags;
459
460
	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
461
	IMustLock(dir);
462
	inode = dentry->d_inode;
463
	if (unlikely(!inode))
464
		return -ENOENT; /* possible? */
465
	IMustLock(inode);
466
467
	whlist = au_nhash_new(GFP_TEMPORARY);
468
	err = PTR_ERR(whlist);
469
	if (IS_ERR(whlist))
470
		goto out;
471
472
	err = -ENOMEM;
473
	args = kmalloc(sizeof(*args), GFP_TEMPORARY);
474
	//args = NULL;
475
	if (unlikely(!args))
476
		goto out_whlist;
477
478
	aufs_read_lock(dentry, AuLock_DW);
479
	parent = dentry->d_parent; /* dir inode is locked */
480
	di_write_lock_parent(parent);
481
	err = au_test_empty(dentry, whlist);
482
	//err = -1;
483
	if (unlikely(err))
484
		goto out_args;
485
486
	bstart = au_dbstart(dentry);
487
	bwh = au_dbwh(dentry);
488
	bindex = -1;
489
	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt);
490
	//wh_dentry = ERR_PTR(-1);
491
	err = PTR_ERR(wh_dentry);
492
	if (IS_ERR(wh_dentry))
493
		goto out_args;
494
495
	AuDebugOn(au_dbstart(dentry) != bstart);
496
	h_dentry = au_h_dptr(dentry, bstart);
497
	dget(h_dentry);
498
499
	rmdir_later = 0;
500
	if (bindex == bstart) {
501
		h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
502
		IMustLock(h_dir);
503
		err = renwh_and_rmdir(dentry, bstart, whlist, dir);
504
		//err = -1;
505
		if (err > 0) {
506
			rmdir_later = err;
507
			err = 0;
508
		}
509
	} else {
510
		/* dir inode is locked */
511
		AuDebugOn(!wh_dentry
512
			  || wh_dentry->d_parent != au_h_dptr(parent, bindex));
513
		h_dir = wh_dentry->d_parent->d_inode;
514
		IMustLock(h_dir);
515
		err = 0;
516
	}
517
518
	sb = dentry->d_sb;
519
	mnt_flags = au_mntflags(sb);
520
	if (!err) {
521
		//aufs_bindex_t bi, bend;
522
523
		if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
524
			     && rmdir_later))
525
			au_reset_hinotify(inode, /*flags*/0);
526
		clear_nlink(inode);
527
		au_set_dbdiropq(dentry, -1);
528
		epilog(dir, dentry, bindex);
529
530
		if (rmdir_later) {
531
			au_whtmp_kick_rmdir(h_dentry, whlist, bstart, dir,
532
					    inode, /*noself*/1, args);
533
			args = NULL;
534
		}
535
536
		goto out_unlock; /* success */
537
	}
538
539
	/* revert */
540
	LKTRLabel(revert);
541
	if (wh_dentry) {
542
		int rerr;
543
		unsigned int rev_flags;
544
545
		rev_flags = 0;
546
		if (unlikely(au_opt_test_dlgt(mnt_flags)))
547
			au_fset_rev(rev_flags, DLGT);
548
		rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, rev_flags);
549
		if (rerr)
550
			err = rerr;
551
	}
552
553
 out_unlock:
554
	au_hdir_unlock(h_dir, dir, bindex);
555
	dput(wh_dentry);
556
	dput(h_dentry);
557
 out_args:
558
	di_write_unlock(parent);
559
	aufs_read_unlock(dentry, AuLock_DW);
560
	kfree(args);
561
 out_whlist:
562
	au_nhash_del(whlist);
563
 out:
564
	AuTraceErr(err);
565
	return err;
566
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/i_op_ren.c (+812 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * inode operation (rename entry)
21
 * todo: this is monster
22
 *
23
 * $Id: i_op_ren.c,v 1.4 2008/05/04 23:51:40 sfjro Exp $
24
 */
25
26
#include "aufs.h"
27
28
enum { SRC, DST };
29
30
#define AuRen_ISDIR	1
31
#define AuRen_ISSAMEDIR	(1 << 1)
32
#define AuRen_WHSRC	(1 << 2)
33
#define AuRen_WHDST	(1 << 3)
34
#define AuRen_DLGT	(1 << 4)
35
#define au_ftest_ren(flags, name)	((flags) & AuRen_##name)
36
#define au_fset_ren(flags, name)	{ (flags) |= AuRen_##name; }
37
#define au_fclr_ren(flags, name)	{ (flags) &= ~AuRen_##name; }
38
#ifndef CONFIG_AUFS_DLGT
39
#undef AuRen_DLGT
40
#define AuRen_DLGT	0
41
#endif
42
43
struct rename_args {
44
	struct dentry *h_dentry[2], *parent[2], *h_parent[2], *h_trap;
45
	struct au_nhash whlist;
46
	aufs_bindex_t btgt, bstart[2];
47
	struct super_block *sb;
48
	unsigned int flags;
49
	unsigned int mnt_flags;
50
};
51
52
static noinline_for_stack int
53
do_rename(struct inode *src_dir, struct dentry *src_dentry,
54
	  struct inode *dir, struct dentry *dentry, struct rename_args *a)
55
{
56
	int err, need_diropq, bycpup, rerr;
57
	struct au_whtmp_rmdir_args *thargs;
58
	struct dentry *wh_dentry[2], *h_dst, *h_src;
59
	struct inode *h_dir[2];
60
	aufs_bindex_t bindex, bend;
61
	struct au_hin_ignore ign;
62
	struct vfsub_args vargs;
63
	struct au_ndx ndx = {
64
		.flags	= 0,
65
		.nd	= NULL,
66
		//.br	= NULL
67
	};
68
69
	LKTRTrace("%.*s/%.*s, %.*s/%.*s, "
70
		  "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, "
71
		  "flags 0x%x\n",
72
		  AuDLNPair(a->parent[SRC]), AuDLNPair(src_dentry),
73
		  AuDLNPair(a->parent[DST]), AuDLNPair(dentry),
74
		  a->h_dentry[SRC], a->h_dentry[DST],
75
		  a->h_parent[SRC], a->h_parent[DST],
76
		  &a->whlist, a->btgt,
77
		  a->bstart[SRC], a->bstart[DST],
78
		  a->flags);
79
80
	h_dir[SRC] = a->h_parent[SRC]->d_inode;
81
	h_dir[DST] = a->h_parent[DST]->d_inode;
82
83
	/* prepare workqueue args */
84
	h_dst = NULL;
85
	thargs = NULL;
86
	if (au_ftest_ren(a->flags, ISDIR) && a->h_dentry[DST]->d_inode) {
87
		err = -ENOMEM;
88
		thargs = kmalloc(sizeof(*thargs), GFP_TEMPORARY);
89
		//thargs = NULL;
90
		if (unlikely(!thargs))
91
			goto out;
92
		h_dst = dget(a->h_dentry[DST]);
93
	}
94
95
	wh_dentry[SRC] = NULL;
96
	wh_dentry[DST] = NULL;
97
	ndx.nfsmnt = au_nfsmnt(a->sb, a->btgt);
98
	if (unlikely(au_ftest_ren(a->flags, DLGT)))
99
		au_fset_ndx(ndx.flags, DLGT);
100
101
	/* create whiteout for src_dentry */
102
	if (au_ftest_ren(a->flags, WHSRC)) {
103
		wh_dentry[SRC] = au_wh_create(src_dir, src_dentry, a->btgt,
104
					      a->h_parent[SRC], &ndx);
105
		//wh_dentry[SRC] = ERR_PTR(-1);
106
		err = PTR_ERR(wh_dentry[SRC]);
107
		if (IS_ERR(wh_dentry[SRC]))
108
			goto out_thargs;
109
	}
110
111
	/* lookup whiteout for dentry */
112
	if (au_ftest_ren(a->flags, WHDST)) {
113
		struct dentry *d;
114
115
		d = au_wh_lkup(a->h_parent[DST], &dentry->d_name, &ndx);
116
		//d = ERR_PTR(-1);
117
		err = PTR_ERR(d);
118
		if (IS_ERR(d))
119
			goto out_whsrc;
120
		if (!d->d_inode)
121
			dput(d);
122
		else
123
			wh_dentry[DST] = d;
124
	}
125
126
	/* rename dentry to tmpwh */
127
	if (thargs) {
128
		err = au_whtmp_ren(dir, dentry, a->btgt, /*noself*/0);
129
		//err = -1;
130
		if (unlikely(err))
131
			goto out_whdst;
132
		au_set_h_dptr(dentry, a->btgt, NULL);
133
		err = au_lkup_neg(dentry, a->btgt);
134
		//err = -1;
135
		if (unlikely(err))
136
			goto out_whtmp;
137
		a->h_dentry[DST] = au_h_dptr(dentry, a->btgt);
138
	}
139
140
	/* cpup src */
141
	if (a->h_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) {
142
		mutex_lock_nested(&a->h_dentry[SRC]->d_inode->i_mutex,
143
				  AuLsc_I_CHILD);
144
		err = au_sio_cpup_simple(src_dentry, a->btgt, -1,
145
					 !AuCpup_DTIME);
146
		//err = -1; // untested dir
147
		mutex_unlock(&a->h_dentry[SRC]->d_inode->i_mutex);
148
		if (unlikely(err))
149
			goto out_whtmp;
150
	}
151
152
	/* rename by vfs_rename or cpup */
153
	need_diropq = au_ftest_ren(a->flags, ISDIR)
154
		&& (wh_dentry[DST]
155
		    || au_dbdiropq(dentry) == a->btgt
156
		    /* hide the lower to keep xino */
157
		    || a->btgt < au_dbend(dentry)
158
		    || au_opt_test(a->mnt_flags, ALWAYS_DIROPQ));
159
	bycpup = 0;
160
	if (au_dbstart(src_dentry) == a->btgt) {
161
		if (need_diropq && au_dbdiropq(src_dentry) == a->btgt)
162
			need_diropq = 0;
163
		vfsub_args_init(&vargs, &ign, au_ftest_ren(a->flags, DLGT), 0);
164
		if (unlikely(au_opt_test(a->mnt_flags, UDBA_INOTIFY)
165
			     && au_ftest_ren(a->flags, ISDIR)))
166
			vfsub_ign_hinode(&vargs, IN_MOVE_SELF,
167
					 au_hi(src_dentry->d_inode, a->btgt));
168
		AuDebugOn(au_dbstart(src_dentry) != a->btgt);
169
		err = vfsub_rename(h_dir[SRC], au_h_dptr(src_dentry, a->btgt),
170
				   h_dir[DST], a->h_dentry[DST], &vargs);
171
		//err = -1;
172
	} else {
173
		bycpup = 1;
174
		mutex_lock_nested(&a->h_dentry[SRC]->d_inode->i_mutex,
175
				  AuLsc_I_CHILD);
176
		au_set_dbstart(src_dentry, a->btgt);
177
		au_set_h_dptr(src_dentry, a->btgt, dget(a->h_dentry[DST]));
178
		err = au_sio_cpup_single(src_dentry, a->btgt, a->bstart[SRC],
179
					 -1, !AuCpup_DTIME);
180
		//err = -1; // untested dir
181
		if (unlikely(err)) {
182
			au_set_h_dptr(src_dentry, a->btgt, NULL);
183
			au_set_dbstart(src_dentry, a->bstart[SRC]);
184
		}
185
		mutex_unlock(&a->h_dentry[SRC]->d_inode->i_mutex);
186
	}
187
	if (unlikely(err))
188
		goto out_whtmp;
189
190
	/* make dir opaque */
191
	if (need_diropq) {
192
		struct dentry *diropq;
193
		struct inode *h_inode;
194
195
		h_inode = au_h_dptr(src_dentry, a->btgt)->d_inode;
196
		au_hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
197
		diropq = au_diropq_create(src_dentry, a->btgt,
198
					  au_ftest_ren(a->flags, DLGT));
199
		//diropq = ERR_PTR(-1);
200
		au_hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
201
		err = PTR_ERR(diropq);
202
		if (IS_ERR(diropq))
203
			goto out_rename;
204
		dput(diropq);
205
	}
206
207
	/* update target timestamps */
208
	AuDebugOn(au_dbstart(src_dentry) != a->btgt);
209
	h_src = au_h_dptr(src_dentry, a->btgt);
210
	au_update_fuse_h_inode(NULL, h_src); /*ignore*/
211
	//fsstack_copy_attr_atime(src_dentry->d_inode, h_src->d_inode);
212
	src_dentry->d_inode->i_ctime = h_src->d_inode->i_ctime;
213
214
	/* remove whiteout for dentry */
215
	if (wh_dentry[DST]) {
216
		err = au_wh_unlink_dentry(h_dir[DST], wh_dentry[DST],
217
					  dentry, dir, /*dlgt*/0);
218
		//err = -1;
219
		if (unlikely(err))
220
			goto out_diropq;
221
	}
222
223
	/* remove whtmp */
224
	if (thargs) {
225
		if (au_test_nfs(h_dst->d_sb)
226
		    || !au_nhash_test_longer_wh(&a->whlist, a->btgt,
227
						au_sbi(a->sb)->si_dirwh)) {
228
			err = au_whtmp_rmdir(h_dst, &a->whlist, a->btgt, dir,
229
					     dentry->d_inode, /*noself*/0);
230
			if (unlikely(err))
231
				AuWarn("failed removing whtmp dir %.*s (%d), "
232
				       "ignored.\n", AuDLNPair(h_dst), err);
233
		} else {
234
			au_whtmp_kick_rmdir(h_dst, &a->whlist, a->btgt, dir,
235
					    dentry->d_inode, /*noself*/0,
236
					    thargs);
237
			dput(h_dst);
238
			thargs = NULL;
239
		}
240
	}
241
	err = 0;
242
	goto out_success;
243
244
#define RevertFailure(fmt, args...) do { \
245
		AuIOErrWhck("revert failure: " fmt " (%d, %d)\n", \
246
			    ##args, err, rerr); \
247
		err = -EIO; \
248
	} while (0)
249
250
 out_diropq:
251
	if (need_diropq) {
252
		struct inode *h_inode;
253
254
		h_inode = au_h_dptr(src_dentry, a->btgt)->d_inode;
255
		//br_wh_read_lock(au_sbr(a->sb, a->btgt));
256
		/* i_lock simply since inotify is not set to h_inode. */
257
		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_PARENT);
258
		//au_hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
259
		rerr = au_diropq_remove(src_dentry, a->btgt,
260
					au_ftest_ren(a->flags, DLGT));
261
		//rerr = -1;
262
		//au_hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
263
		mutex_unlock(&h_inode->i_mutex);
264
		//br_wh_read_unlock(au_sbr(a->sb, a->btgt));
265
		if (rerr)
266
			RevertFailure("remove diropq %.*s",
267
				      AuDLNPair(src_dentry));
268
	}
269
 out_rename:
270
	if (!bycpup) {
271
		struct dentry *d;
272
		struct qstr *name = &src_dentry->d_name;
273
274
		d = au_lkup_one(name->name, a->h_parent[SRC], name->len, &ndx);
275
		//d = ERR_PTR(-1);
276
		rerr = PTR_ERR(d);
277
		if (IS_ERR(d)) {
278
			RevertFailure("au_lkup_one %.*s",
279
				      AuDLNPair(src_dentry));
280
			goto out_whtmp;
281
		}
282
		AuDebugOn(d->d_inode);
283
		vfsub_args_init(&vargs, &ign, au_ftest_ren(a->flags, DLGT), 0);
284
		if (unlikely(au_opt_test(a->mnt_flags, UDBA_INOTIFY)
285
			     && au_ftest_ren(a->flags, ISDIR)))
286
			vfsub_ign_hinode(&vargs, IN_MOVE_SELF,
287
					 au_hi(src_dentry->d_inode, a->btgt));
288
		rerr = vfsub_rename(h_dir[DST], au_h_dptr(src_dentry, a->btgt),
289
				    h_dir[SRC], d, &vargs);
290
		//rerr = -1;
291
		d_drop(d);
292
		dput(d);
293
		//au_set_h_dptr(src_dentry, a->btgt, NULL);
294
		if (rerr)
295
			RevertFailure("rename %.*s", AuDLNPair(src_dentry));
296
	} else {
297
		vfsub_args_init(&vargs, NULL, au_ftest_ren(a->flags, DLGT), 0);
298
		rerr = vfsub_unlink(h_dir[DST], a->h_dentry[DST], &vargs);
299
		//rerr = -1;
300
		au_set_h_dptr(src_dentry, a->btgt, NULL);
301
		au_set_dbstart(src_dentry, a->bstart[SRC]);
302
		if (rerr)
303
			RevertFailure("unlink %.*s",
304
				      AuDLNPair(a->h_dentry[DST]));
305
	}
306
 out_whtmp:
307
	if (thargs) {
308
		struct dentry *d;
309
		struct qstr *name = &dentry->d_name;
310
311
		d = au_lkup_one(name->name, a->h_parent[DST], name->len, &ndx);
312
		//d = ERR_PTR(-1);
313
		rerr = PTR_ERR(d);
314
		if (IS_ERR(d)) {
315
			RevertFailure("lookup %.*s", AuLNPair(name));
316
			goto out_whdst;
317
		}
318
		if (d->d_inode) {
319
			d_drop(d);
320
			dput(d);
321
			goto out_whdst;
322
		}
323
		AuDebugOn(d->d_inode);
324
		vfsub_args_init(&vargs, &ign, au_ftest_ren(a->flags, DLGT), 0);
325
		if (unlikely(0 && au_opt_test(a->mnt_flags, UDBA_INOTIFY)
326
			     && au_ftest_ren(a->flags, ISDIR)))
327
			vfsub_ign_hinode(&vargs, IN_MOVE_SELF,
328
					 au_hi(dentry->d_inode, a->btgt));
329
		rerr = vfsub_rename(h_dir[DST], h_dst, h_dir[DST], d, &vargs);
330
		//rerr = -1;
331
		d_drop(d);
332
		dput(d);
333
		if (rerr) {
334
			RevertFailure("rename %.*s", AuDLNPair(h_dst));
335
			goto out_whdst;
336
		}
337
		au_set_h_dptr(dentry, a->btgt, NULL);
338
		au_set_h_dptr(dentry, a->btgt, dget(h_dst));
339
	}
340
 out_whdst:
341
	dput(wh_dentry[DST]);
342
	wh_dentry[DST] = NULL;
343
 out_whsrc:
344
	if (wh_dentry[SRC]) {
345
		rerr = au_wh_unlink_dentry(h_dir[SRC], wh_dentry[SRC],
346
					   src_dentry, src_dir, /*dlgt*/0);
347
		//rerr = -1;
348
		if (rerr)
349
			RevertFailure("unlink %.*s", AuDLNPair(wh_dentry[SRC]));
350
	}
351
#undef RevertFailure
352
	d_drop(src_dentry);
353
	bend = au_dbend(src_dentry);
354
	for (bindex = au_dbstart(src_dentry); bindex <= bend; bindex++) {
355
		struct dentry *hd;
356
357
		hd = au_h_dptr(src_dentry, bindex);
358
		if (hd)
359
			d_drop(hd);
360
	}
361
	d_drop(dentry);
362
	bend = au_dbend(dentry);
363
	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
364
		struct dentry *hd;
365
366
		hd = au_h_dptr(dentry, bindex);
367
		if (hd)
368
			d_drop(hd);
369
	}
370
	au_update_dbstart(dentry);
371
	if (thargs)
372
		d_drop(h_dst);
373
 out_success:
374
	dput(wh_dentry[SRC]);
375
	dput(wh_dentry[DST]);
376
 out_thargs:
377
	if (thargs) {
378
		dput(h_dst);
379
		kfree(thargs);
380
	}
381
 out:
382
	AuTraceErr(err);
383
	return err;
384
}
385
386
/*
387
 * test if @dentry dir can be rename destination or not.
388
 * success means, it is a logically empty dir.
389
 */
390
static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt,
391
			     struct au_nhash *whlist)
392
{
393
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
394
395
	return au_test_empty(dentry, whlist);
396
}
397
398
/*
399
 * test if @dentry dir can be rename source or not.
400
 * if it can, return 0 and @children is filled.
401
 * success means,
402
 * - or, it is a logically empty dir.
403
 * - or, it exists on writable branch and has no children including whiteouts
404
 *       on the lower branch.
405
 */
406
static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
407
{
408
	int err;
409
	aufs_bindex_t bstart;
410
411
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
412
413
	bstart = au_dbstart(dentry);
414
	if (bstart != btgt) {
415
		struct au_nhash *whlist;
416
417
		whlist = au_nhash_new(GFP_TEMPORARY);
418
		err = PTR_ERR(whlist);
419
		if (IS_ERR(whlist))
420
			goto out;
421
		err = au_test_empty(dentry, whlist);
422
		au_nhash_del(whlist);
423
		goto out;
424
	}
425
426
	if (bstart == au_dbtaildir(dentry))
427
		return 0; /* success */
428
429
	err = au_test_empty_lower(dentry);
430
431
 out:
432
	if (/* unlikely */(err == -ENOTEMPTY)) {
433
		AuWarn1("renaming dir who has child(ren) on multiple branches,"
434
		      " is not supported\n");
435
		err = -EXDEV;
436
	}
437
	AuTraceErr(err);
438
	return err;
439
}
440
441
/* mainly for link(2) and rename(2) */
442
int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
443
{
444
	aufs_bindex_t bdiropq, bwh;
445
	struct dentry *parent;
446
447
	LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), btgt);
448
	parent = dentry->d_parent;
449
	IMustLock(parent->d_inode); /* dir is locked */
450
451
	bdiropq = au_dbdiropq(parent);
452
	bwh = au_dbwh(dentry);
453
	if (au_br_rdonly(au_sbr(dentry->d_sb, btgt))
454
		     || (0 <= bdiropq && bdiropq < btgt)
455
		     || (0 <= bwh && bwh < btgt))
456
		btgt = -1;
457
458
	LKTRTrace("btgt %d\n", btgt);
459
	return btgt;
460
}
461
462
//todo: meaningless lock if CONFIG_AUFS_DEBUG is disabled.
463
static void au_hgdirs(struct au_hinode **hgdir, struct rename_args *a)
464
{
465
	struct dentry *gparent[2];
466
	struct inode *gdir;
467
468
	if (!au_opt_test(a->mnt_flags, UDBA_INOTIFY))
469
		return;
470
471
	gparent[SRC] = NULL;
472
	if (!IS_ROOT(a->parent[SRC])) {
473
		gparent[SRC] = dget_parent(a->parent[SRC]);
474
		gdir = gparent[SRC]->d_inode;
475
		if (gparent[SRC] != a->parent[DST]) {
476
			ii_read_lock_parent3(gdir);
477
			hgdir[SRC] = au_hi(gdir, a->btgt);
478
			ii_read_unlock(gdir);
479
		} else
480
			hgdir[SRC] = au_hi(gdir, a->btgt);
481
		dput(gparent[SRC]);
482
	}
483
484
	if (!au_ftest_ren(a->flags, ISSAMEDIR)
485
	    && !IS_ROOT(a->parent[DST])
486
	    && a->parent[DST] != gparent[SRC]) {
487
		gparent[DST] = dget_parent(a->parent[DST]);
488
		gdir = gparent[DST]->d_inode;
489
		if (gparent[DST] != a->parent[SRC]) {
490
			ii_read_lock_parent3(gdir);
491
			hgdir[DST] = au_hi(gdir, a->btgt);
492
			ii_read_unlock(gdir);
493
		} else
494
			hgdir[DST] = au_hi(gdir, a->btgt);
495
		dput(gparent[DST]);
496
	}
497
}
498
499
/*
500
 * simple tests for rename.
501
 * following the checks in vfs, plus the parent-child relationship.
502
 */
503
static int au_may_ren(struct inode *src_dir, struct dentry *src_dentry,
504
		      struct inode *dir, struct dentry *dentry,
505
		      struct rename_args *a, struct au_ndx *ndx)
506
{
507
	int err;
508
	struct inode *h_inode;
509
510
	AuTraceEnter();
511
512
	if (a->bstart[SRC] == a->btgt) {
513
		err = au_may_del(src_dentry, a->btgt, a->h_parent[SRC],
514
				 au_ftest_ren(a->flags, ISDIR), ndx);
515
		if (unlikely(err))
516
			goto out;
517
		err = -EINVAL;
518
		if (unlikely(a->h_dentry[SRC] == a->h_trap))
519
			goto out;
520
	}
521
522
	err = 0;
523
	if (a->bstart[DST] != a->btgt)
524
		goto out;
525
526
	err = -EIO;
527
	h_inode = a->h_dentry[DST]->d_inode;
528
	if (!dentry->d_inode) {
529
		if (unlikely(h_inode))
530
			goto out;
531
		err = au_may_add(dentry, a->btgt, a->h_parent[DST],
532
				 au_ftest_ren(a->flags, ISDIR), ndx);
533
	} else {
534
		if (unlikely(!h_inode || !h_inode->i_nlink))
535
			goto out;
536
		err = au_may_del(dentry, a->btgt, a->h_parent[DST],
537
				 au_ftest_ren(a->flags, ISDIR), ndx);
538
		if (unlikely(err))
539
			goto out;
540
		err = -ENOTEMPTY;
541
		if (unlikely(a->h_dentry[DST] == a->h_trap))
542
			goto out;
543
		err = 0;
544
	}
545
546
 out:
547
	if (unlikely(err == -ENOENT || err == -EEXIST))
548
		err = -EIO;
549
	AuTraceErr(err);
550
	return err;
551
}
552
553
int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
554
		struct inode *dir, struct dentry *dentry)
555
{
556
	int err, do_dt_dstdir, flags;
557
	aufs_bindex_t bend, bindex;
558
	struct inode *inode[2], *dirs[2];
559
	struct au_hinode *hgdir[2], *hdir;
560
	enum { PARENT, CHILD };
561
	/* reduce stack space */
562
	struct {
563
		struct rename_args a;
564
		struct au_dtime dt[2][2];
565
	} *p;
566
	struct au_wr_dir_args wr_dir_args = {
567
		//.force_btgt	= -1,
568
		.flags		= AuWrDir_ADD_ENTRY
569
	};
570
571
	LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
572
		  src_dir->i_ino, AuDLNPair(src_dentry),
573
		  dir->i_ino, AuDLNPair(dentry));
574
	IMustLock(src_dir);
575
	IMustLock(dir);
576
	inode[DST] = dentry->d_inode;
577
	if (inode[DST]) {
578
		IMustLock(inode[DST]);
579
		igrab(inode[DST]);
580
	}
581
582
	err = -ENOMEM;
583
	BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE);
584
	p = kmalloc(sizeof(*p), GFP_TEMPORARY);
585
	if (unlikely(!p))
586
		goto out;
587
588
	err = -ENOTDIR;
589
	p->a.sb = src_dentry->d_sb;
590
	inode[SRC] = src_dentry->d_inode;
591
	flags = 0;
592
	p->a.flags = 0;
593
	if (S_ISDIR(inode[SRC]->i_mode)) {
594
		flags = AuLock_DIR;
595
		au_fset_ren(p->a.flags, ISDIR);
596
		if (unlikely(inode[DST] && !S_ISDIR(inode[DST]->i_mode)))
597
			goto out_free;
598
	}
599
600
	aufs_read_and_write_lock2(dentry, src_dentry, flags);
601
	p->a.mnt_flags = au_mntflags(p->a.sb);
602
	if (unlikely(au_opt_test_dlgt(p->a.mnt_flags)))
603
		au_fset_ren(p->a.flags, DLGT);
604
	p->a.parent[SRC] = src_dentry->d_parent; /* dir inode is locked */
605
	p->a.parent[DST] = dentry->d_parent; /* dir inode is locked */
606
	if (src_dir == dir) {
607
		au_fset_ren(p->a.flags, ISSAMEDIR);
608
		di_write_lock_parent(p->a.parent[DST]);
609
	} else
610
		di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST],
611
				      /*isdir*/1);
612
613
	/* which branch we process */
614
	p->a.bstart[SRC] = au_dbstart(src_dentry);
615
	p->a.bstart[DST] = au_dbstart(dentry);
616
	if (au_ftest_ren(p->a.flags, ISDIR))
617
		au_fset_wrdir(wr_dir_args.flags, ISDIR);
618
	wr_dir_args.force_btgt = p->a.bstart[SRC];
619
	if (dentry->d_inode && p->a.bstart[DST] < p->a.bstart[SRC])
620
		wr_dir_args.force_btgt = p->a.bstart[DST];
621
	wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
622
	err = au_wr_dir(dentry, src_dentry, &wr_dir_args);
623
	p->a.btgt = err;
624
	if (unlikely(err < 0))
625
		goto out_unlock;
626
627
	/* are they available to be renamed */
628
	err = 0;
629
	au_nhash_init(&p->a.whlist);
630
	if (au_ftest_ren(p->a.flags, ISDIR) && inode[DST]) {
631
		au_set_dbstart(dentry, p->a.bstart[DST]);
632
		err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist);
633
		au_set_dbstart(dentry, p->a.btgt);
634
	}
635
	p->a.h_dentry[DST] = au_h_dptr(dentry, au_dbstart(dentry));
636
	if (unlikely(err))
637
		goto out_unlock;
638
	//todo: minor optimize, their sb may be same while their bindex differs.
639
	p->a.h_dentry[SRC] = au_h_dptr(src_dentry, au_dbstart(src_dentry));
640
	if (au_ftest_ren(p->a.flags, ISDIR)) {
641
		err = may_rename_srcdir(src_dentry, p->a.btgt);
642
		if (unlikely(err))
643
			goto out_children;
644
	}
645
646
	/* prepare the writable parent dir on the same branch */
647
	err = au_wr_dir_need_wh(src_dentry, au_ftest_ren(p->a.flags, ISDIR),
648
				&p->a.btgt,
649
				au_ftest_ren(p->a.flags, ISSAMEDIR)
650
				? NULL : p->a.parent[DST]);
651
	if (unlikely(err < 0))
652
		goto out_children;
653
	if (err)
654
		au_fset_ren(p->a.flags, WHSRC);
655
	if (p->a.bstart[DST] == p->a.btgt) {
656
		au_fset_ren(p->a.flags, WHDST);
657
	} else {
658
		err = au_cpup_dirs(dentry, p->a.btgt,
659
				   au_ftest_ren(p->a.flags, ISSAMEDIR)
660
				   ? NULL : p->a.parent[SRC]);
661
		if (unlikely(err))
662
			goto out_children;
663
	}
664
665
	hgdir[SRC] = NULL;
666
	hgdir[DST] = NULL;
667
	au_hgdirs(hgdir, &p->a);
668
	p->a.h_parent[SRC] = au_h_dptr(p->a.parent[SRC], p->a.btgt);
669
	p->a.h_parent[DST] = au_h_dptr(p->a.parent[DST], p->a.btgt);
670
	dirs[0] = src_dir;
671
	dirs[1] = dir;
672
673
	AuDbgSleep_UdbaRace();
674
	p->a.h_trap = au_hdir_lock_rename(p->a.h_parent, dirs, p->a.btgt,
675
					  au_ftest_ren(p->a.flags, ISSAMEDIR));
676
	//todo: revalidate the lower dentries?
677
678
	if (!au_opt_test(p->a.mnt_flags, UDBA_NONE)) {
679
		struct au_ndx ndx = {
680
			.nfsmnt	= au_nfsmnt(p->a.sb, p->a.btgt),
681
			.flags	= 0,
682
			.nd	= NULL,
683
			//.br	= NULL
684
		};
685
		if (unlikely(au_ftest_ren(p->a.flags, DLGT)))
686
			au_fset_ndx(ndx.flags, DLGT);
687
		err = au_may_ren(src_dir, src_dentry, dir, dentry, &p->a, &ndx);
688
		if (unlikely(err))
689
			goto out_hdir;
690
	}
691
692
	/* store timestamps to be revertible */
693
	au_dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC],
694
		       p->a.h_parent[SRC], hgdir[SRC]);
695
	if (!au_ftest_ren(p->a.flags, ISSAMEDIR))
696
		au_dtime_store(p->dt[PARENT] + DST, p->a.parent[DST],
697
			       p->a.h_parent[DST], hgdir[DST]);
698
	do_dt_dstdir = 0;
699
	if (au_ftest_ren(p->a.flags, ISDIR)) {
700
		hdir = NULL;
701
		if (unlikely(au_opt_test(p->a.mnt_flags, UDBA_INOTIFY)))
702
			hdir = au_hi(p->a.parent[SRC]->d_inode, p->a.btgt);
703
		au_dtime_store(p->dt[CHILD] + SRC, src_dentry,
704
			       p->a.h_dentry[SRC], hdir);
705
		if (p->a.h_dentry[DST]->d_inode) {
706
			do_dt_dstdir = 1;
707
			if (unlikely(au_opt_test(p->a.mnt_flags, UDBA_INOTIFY)))
708
				hdir = au_hi(p->a.parent[DST]->d_inode,
709
					     p->a.btgt);
710
			au_dtime_store(p->dt[CHILD] + DST, dentry,
711
				       p->a.h_dentry[DST], hdir);
712
		}
713
	}
714
715
	err = do_rename(src_dir, src_dentry, dir, dentry, &p->a);
716
	if (unlikely(err))
717
		goto out_dt;
718
	au_hdir_unlock_rename(p->a.h_parent, dirs, p->a.btgt,
719
			      au_ftest_ren(p->a.flags, ISSAMEDIR));
720
721
	/* update dir attributes */
722
	dir->i_version++;
723
	if (au_ftest_ren(p->a.flags, ISDIR)) {
724
		/* is this updating defined in POSIX? */
725
		//mutex_lock(&inode[SRC]->i_mutex);
726
		au_cpup_attr_timesizes(inode[SRC]);
727
		//mutex_unlock(&inode[SRC]->i_mutex);
728
729
		au_cpup_attr_nlink(dir);
730
		if (inode[DST]) {
731
			clear_nlink(inode[DST]);
732
			au_cpup_attr_timesizes(inode[DST]);
733
		}
734
	}
735
	if (au_ibstart(dir) == p->a.btgt)
736
		au_cpup_attr_timesizes(dir);
737
738
	if (!au_ftest_ren(p->a.flags, ISSAMEDIR)) {
739
		src_dir->i_version++;
740
		if (au_ftest_ren(p->a.flags, ISDIR))
741
			au_cpup_attr_nlink(src_dir);
742
		if (au_ibstart(src_dir) == p->a.btgt)
743
			au_cpup_attr_timesizes(src_dir);
744
	}
745
746
	/* dput/iput all lower dentries */
747
	au_set_dbwh(src_dentry, -1);
748
	bend = au_dbend(src_dentry);
749
	for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
750
		struct dentry *hd;
751
		hd = au_h_dptr(src_dentry, bindex);
752
		if (hd)
753
			au_set_h_dptr(src_dentry, bindex, NULL);
754
	}
755
	au_set_dbend(src_dentry, p->a.btgt);
756
757
	bend = au_ibend(inode[SRC]);
758
	for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
759
		struct inode *hi;
760
		hi = au_h_iptr(inode[SRC], bindex);
761
		if (hi) {
762
			//AuDbg("hi%lu, i%lu\n", hi->i_ino, 0LU);
763
			au_xino_write0(p->a.sb, bindex, hi->i_ino, 0);
764
			/* ignore this error */
765
			au_set_h_iptr(inode[SRC], bindex, NULL, 0);
766
		}
767
	}
768
	au_set_ibend(inode[SRC], p->a.btgt);
769
770
	goto out_children; /* success */
771
772
 out_dt:
773
	au_dtime_revert(p->dt[PARENT] + SRC);
774
	if (!au_ftest_ren(p->a.flags, ISSAMEDIR))
775
		au_dtime_revert(p->dt[PARENT] + DST);
776
	if (au_ftest_ren(p->a.flags, ISDIR) && err != -EIO) {
777
		struct dentry *hd;
778
779
		hd = p->dt[CHILD][SRC].dt_h_dentry;
780
		mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD);
781
		au_dtime_revert(p->dt[CHILD] + SRC);
782
		mutex_unlock(&hd->d_inode->i_mutex);
783
		if (do_dt_dstdir) {
784
			hd = p->dt[CHILD][DST].dt_h_dentry;
785
			mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD);
786
			au_dtime_revert(p->dt[CHILD] + DST);
787
			mutex_unlock(&hd->d_inode->i_mutex);
788
		}
789
	}
790
 out_hdir:
791
	au_hdir_unlock_rename(p->a.h_parent, dirs, p->a.btgt,
792
			      au_ftest_ren(p->a.flags, ISSAMEDIR));
793
 out_children:
794
	au_nhash_fin(&p->a.whlist);
795
 out_unlock:
796
	//if (unlikely(err /* && au_ftest_ren(p->a.flags, ISDIR) */)) {
797
	if (unlikely(err && au_ftest_ren(p->a.flags, ISDIR))) {
798
		au_update_dbstart(dentry);
799
		d_drop(dentry);
800
	}
801
	if (au_ftest_ren(p->a.flags, ISSAMEDIR))
802
		di_write_unlock(p->a.parent[DST]);
803
	else
804
		di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]);
805
	aufs_read_and_write_unlock2(dentry, src_dentry);
806
 out_free:
807
	kfree(p);
808
 out:
809
	iput(inode[DST]);
810
	AuTraceErr(err);
811
	return err;
812
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/Kconfig (+284 lines)
Line 0 Link Here
1
config AUFS
2
	tristate "Another unionfs"
3
	help
4
	Aufs is a stackable unification filesystem such as Unionfs,
5
	which unifies several directories and provides a merged single
6
	directory.
7
	In the early days, aufs was entirely re-designed and
8
	re-implemented Unionfs Version 1.x series. After many original
9
	ideas, approaches and improvements, it becomes totally
10
	different from Unionfs while keeping the basic features.
11
	See Unionfs for the basic features.
12
13
if AUFS
14
15
config AUFS_FAKE_DM
16
	bool "Use simplified (fake) nameidata"
17
	depends on AUFS
18
	default y
19
	help
20
	Faking nameidata (linux kernel internal data), you can get
21
	better performance in some cases.
22
	When you use NFS as an aufs branch or dlgt /* /dirperm1 */ aufs mount option,
23
	you need to disable this configuration.
24
25
choice
26
	prompt "Maximum number of branches"
27
	depends on AUFS
28
	default AUFS_BRANCH_MAX_127
29
	help
30
	Specifies the maximum number of branches (or member directories) in a \
31
	single aufs. The larger value consumes more system resources and has \
32
	an impact to performance.
33
config AUFS_BRANCH_MAX_127
34
	bool "127"
35
	help
36
	Specifies the maximum number of branches (or member directories) in a \
37
	single aufs. The larger value consumes more system resources and has \
38
	an impact to performance.
39
config AUFS_BRANCH_MAX_511
40
	bool "511"
41
	help
42
	Specifies the maximum number of branches (or member directories) in a \
43
	single aufs. The larger value consumes more system resources and has \
44
	an impact to performance.
45
config AUFS_BRANCH_MAX_1023
46
	bool "1023"
47
	help
48
	Specifies the maximum number of branches (or member directories) in a \
49
	single aufs. The larger value consumes more system resources and has \
50
	an impact to performance.
51
config AUFS_BRANCH_MAX_32767
52
	bool "32767"
53
	help
54
	Specifies the maximum number of branches (or member directories) in a \
55
	single aufs. The larger value consumes more system resources and has \
56
	an impact to performance.
57
endchoice
58
59
config AUFS_HINOTIFY
60
	bool "Use inotify to detect actions on a branch"
61
	depends on AUFS
62
	depends on INOTIFY
63
	default n
64
	help
65
	If you want to modify files on branches directly, eg. bypassing aufs,
66
	and want aufs to detect the changes of them fully, then enable this
67
	option and use 'udba=inotify' mount option.
68
	It will damage the performance.
69
	See detail in aufs.5.
70
71
comment "INOTIFY and AUFS_HINOTIFY are disabled"
72
	depends on INOTIFY = n
73
74
config AUFS_EXPORT
75
	bool "NFS-exportable aufs"
76
	depends on AUFS
77
	depends on (AUFS = y && EXPORTFS = y) || (AUFS = m && EXPORTFS)
78
	default n
79
	help
80
	If you want to export your mounted aufs, then enable this
81
	option. There are several requirements to export aufs.
82
	See detail in aufs.5.
83
84
comment "EXPORTFS and AUFS_EXPORT are disabled"
85
	depends on AUFS
86
	depends on EXPORTFS = n
87
88
comment "AUFS_EXPORT is disabled since EXPORTFS is a module but AUFS"
89
	depends on AUFS
90
	depends on EXPORTFS = m && AUFS = y
91
92
config AUFS_ROBR
93
	bool "Aufs as an readonly branch of another aufs"
94
	depends on AUFS
95
	default n
96
	help
97
	If you want make your aufs to be a part of another aufs, then
98
	enable this option. In other words, you can specify your aufs
99
	path in 'br:' mount option for another aufs, but cannot
100
	specify 'rw' as the branch permission.
101
	It will damage the performance.
102
	See detail in aufs.5.
103
104
config AUFS_DLGT
105
	bool "Delegate the internal branch access the kernel thread"
106
	depends on AUFS
107
	default n
108
	help
109
	If you want /*to use 'dirperm1' mount option, or */ aufs to delegate
110
	the internal access to the branches which is made by aufs, to
111
	the kernel thread, in order to hide the access issued by your
112
	application from your LSM or something or make your
113
	application to be traced strictly by the task I/O accounting,
114
	then enable this option and use 'dlgt' mount option.
115
	It will damage the performance.
116
	See detail in aufs.5.
117
118
config AUFS_RR_SQUASHFS
119
	bool "Make squashfs branch RR (real readonly) by default"
120
	depends on AUFS
121
	default y
122
	help
123
	If you use squashfs or LZMA patched squashfs as an aufs branch
124
	and want to set '=rr' to it by default, then enable this
125
	configuration.
126
	'rr' stands for real readonly and it optimizes some aspects of
127
	'ro.'
128
	See detail in aufs.5.
129
130
config AUFS_SEC_PERM_PATCH
131
	bool "sec_perm-2.6.24.patch was applied or not"
132
	depends on AUFS
133
	depends on AUFS = m
134
	depends on SECURITY
135
	default n
136
	help
137
	If you build aufs as a module and enabled CONFIG_SECURITY,
138
	then you need to apply the patch
139
	'CVS_TREE/aufs/patch/sec_perm-2.6.24.patch' to your kernel
140
	source, and enable this configuration.
141
	The sec_perm-2.6.24.patch exports a kernel function
142
	security_inode_permission() to modules.
143
144
comment "SECURITY and AUFS_SEC_PERM_PATCH are disabled"
145
	depends on AUFS
146
	depends on SECURITY = n
147
148
config AUFS_SPLICE_PATCH
149
	bool "splice.patch for sendfile(2) and splice(2)"
150
	depends on AUFS
151
	default n
152
	help
153
	If you use 'loopback mount' on a fs-image file, or use
154
	splice(2) or sendfile(2) systemcall in aufs, then you need to
155
	apply the patch 'CVS_TREE/aufs/patch/splice.patch' to your
156
	kernel source, and enable this configuration.
157
	The splice.patch makes the kernel function vfs_splice_to/from()
158
	global and exports them to modules.
159
160
config AUFS_PUT_FILP_PATCH
161
	bool "put_filp.patch for NFS branch"
162
	depends on AUFS
163
	depends on AUFS = m
164
	depends on NFS_FS
165
	depends on AUFS_FAKE_DM = n
166
	default n
167
	help
168
	If you build aufs as a module and use mounted NFS as an aufs
169
	branch filesystem, then you need to apply the patch
170
	'CVS_TREE/aufs/patch/put_filp.patch' to your kernel source,
171
	and enable this configuration.
172
	The put_filp.patch exports a kernel function put_filp() to
173
	modules.
174
175
comment "NFS_FS and AUFS_PUT_FILP_PATCH are disabled"
176
	depends on AUFS
177
	depends on NFS_FS = n
178
179
comment "AUFS_FILP_PATCH is disabled since AUFS_FAKE_DM is enabled"
180
	depends on AUFS
181
	depends on AUFS_FAKE_DM
182
183
config AUFS_LHASH_PATCH
184
	bool "lhash.patch for NFS branch"
185
	depends on AUFS
186
	depends on NFS_FS
187
	depends on AUFS_FAKE_DM = n
188
	default n
189
	help
190
	If you use mounted NFS as an aufs branch filesystem, then you
191
	need to apply the patch 'CVS_TREE/aufs/patch/lhash.patch' (or
192
	lhash-2.6.22.patch for linux-2.6.22 and later) to your kernel
193
	source, and enable this configuration.
194
	The patch file makes the kernel function __lookup_hash() global
195
	and exports it to modules.
196
197
comment "NFS_FS and AUFS_LHASH_PATCH are disabled"
198
	depends on AUFS
199
	depends on NFS_FS = n
200
201
comment "AUFS_LHASH_PATCH is disabled since AUFS_FAKE_DM is enabled"
202
	depends on AUFS
203
	depends on AUFS_FAKE_DM
204
205
config AUFS_FSYNC_SUPER_PATCH
206
	bool "fsync_super-2.6.xx.patch was applied or not"
207
	depends on AUFS
208
	depends on AUFS = m
209
	default n
210
	help
211
	If you build aufs as a module and want to flush everything for
212
	branch filesystems which are not marked as 'rr' nor 'rr+wh' at
213
	umount or remount time, then you need to apply the patch
214
	'CVS_TREE/aufs/patch/fsync_super-2.6.16.patch' or
215
	'...-2.6.19.patch' to your kernel source, and enable this
216
	configuration.
217
	It may be helpful at shutdown time in case of your aufs is a
218
	root filesystem. But this behaviour will not guarantee the
219
	consistency of branch filesystems. To gurantee it, try the
220
	approach described in the aufs manual, and don't forget
221
	installing auplink script.
222
	The fsync_super-2.6.xx.patch does nothing but exports a kernel
223
	function fsync_super() to modules.
224
225
config AUFS_DENY_WRITE_ACCESS_PATCH
226
	bool "deny_write_access.patch was applied or not"
227
	depends on AUFS
228
	depends on AUFS = m
229
	default n
230
	help
231
	A security enhancement to deny writing to a running executable
232
	which exists on an aufs branch filesystem and executed through
233
	aufs. If you applied
234
	'CVS_TREE/aufs/patch/deny_write_access.patch' to your kernel
235
	and you are compiling aufs as a module, then enable this
236
	option.
237
	The write_deny_access.patch does nothing but export the
238
	function.
239
240
config AUFS_WORKAROUND_FUSE
241
	bool "Special handling for FUSE-based filesystem"
242
	depends on AUFS && FUSE_FS
243
	default n
244
	help
245
	A FUSE-based filesystem may not initialize its inode
246
	attributes and the FUSE developer thinks the inode attributes
247
	in a positive dentry which is returned by VFS lookup operation
248
	are not reliable.
249
	If you use a FUSE-based filesystem as an aufs branch, and it
250
	customizes the inode attribute on it without overriding
251
	fuse_lowlevel_ops.lookup, probably you need to enable this
252
	configuration.
253
	If you enable this configuration, aufs calls getattr operation
254
	in every lookup and revalidate operation for the FUSE-based
255
	filesystem branch.
256
	It will damage the performance even if you don't use a
257
	FUSE-based filesystem branch.
258
259
config AUFS_DEBUG
260
	bool "Debug aufs"
261
	depends on AUFS
262
	default y
263
	help
264
	Enable this to compile aufs internal debug code.
265
	The performance will be damaged.
266
267
config AUFS_COMPAT
268
	bool "Compatibility with Unionfs (obsolete)"
269
	depends on AUFS
270
	default n
271
	help
272
	This makes aufs compatible with unionfs-style mount options and some
273
	behaviours.
274
	The dirs= mount option and =nfsro branch permission flag are always
275
	interpreted as br: mount option and =ro flag respectively. The
276
	'debug', 'delete' and 'imap' mount options are ignored.
277
	If you disable this option, you will get,
278
	- aufs issues a warning about the ignored mount options
279
	- the default branch permission flag is set. RW for the first branch,
280
	  and RO for the rests.
281
	- the name of a internal file which represents the directory is
282
	  'opaque', becomes '.wh..wh..opq'
283
	- the 'diropq=w' mount option is set by default
284
endif
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/Makefile (+65 lines)
Line 0 Link Here
1
# AUFS Makefile for the Linux 2.6.25 and later
2
# $Id: Makefile,v 1.3 2008/04/28 03:03:10 sfjro Exp $
3
4
# the environment variables are not inherited since 2.6.23
5
ifdef AUFS_EXTRA_CFLAGS
6
EXTRA_CFLAGS += ${AUFS_EXTRA_CFLAGS}
7
endif
8
9
########################################
10
11
ifdef CONFIG_AUFS_RR_SQUASHFS
12
# cf. squashfs3.2-r2 and sqlzma patch.
13
EXTRA_CFLAGS += -DSQUASHFS_MAGIC=0x73717368
14
EXTRA_CFLAGS += -DSQUASHFS_MAGIC_SWAP=0x68737173
15
EXTRA_CFLAGS += -DSQUASHFS_MAGIC_LZMA=0x71736873
16
EXTRA_CFLAGS += -DSQUASHFS_MAGIC_LZMA_SWAP=0x73687371
17
endif
18
19
ifdef CONFIG_AUFS_WORKAROUND_FUSE
20
# defined in ${srctree}/fs/fuse/inode.c
21
EXTRA_CFLAGS += -DFUSE_SUPER_MAGIC=0x65735546
22
endif
23
24
ifdef CONFIG_XFS_FS
25
# defined in ${srctree}/fs/xfs/xfs_sb.h
26
EXTRA_CFLAGS += -DXFS_SB_MAGIC=0x58465342
27
endif
28
29
ifdef CONFIG_TMPFS
30
# defined in ${srctree}/mm/shmem.c
31
EXTRA_CFLAGS += -DTMPFS_MAGIC=0x01021994
32
endif
33
34
-include $(dir $(lastword ${MAKEFILE_LIST}))priv.mk
35
#$(warning ${EXTRA_CFLAGS})
36
37
########################################
38
39
obj-$(CONFIG_AUFS) += aufs.o
40
aufs-y := module.o super.o sbinfo.o branch.o xino.o sysaufs.o opts.o \
41
	wkq.o vfsub.o dcsub.o \
42
	cpup.o whout.o plink.o wbr_policy.o \
43
	dentry.o dinfo.o \
44
	file.o f_op.o finfo.o \
45
	dir.o vdir.o \
46
	inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \
47
	misc.o
48
49
#xattr.o
50
aufs-$(CONFIG_SYSFS) += sysfs.o
51
aufs-$(CONFIG_AUFS_BR_NFS) += br_nfs.o
52
aufs-$(CONFIG_AUFS_BR_XFS) += br_xfs.o
53
aufs-$(CONFIG_AUFS_WORKAROUND_FUSE) += br_fuse.o
54
55
aufs-$(CONFIG_AUFS_DLGT) += dlgt.o
56
aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o hin_or_dlgt.o
57
# dirty
58
ifndef CONFIG_AUFS_HINOTIFY
59
aufs-$(CONFIG_AUFS_DLGT) += hin_or_dlgt.o
60
endif
61
62
aufs-$(CONFIG_AUFS_EXPORT) += export.o
63
aufs-$(CONFIG_AUFS_ROBR) += robr.o
64
aufs-$(CONFIG_AUFS_DEBUG) += debug.o
65
aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/misc.c (+271 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * $Id: misc.c,v 1.6 2008/05/19 01:46:53 sfjro Exp $
21
 */
22
23
//#include <linux/fs.h>
24
//#include <linux/namei.h>
25
//#include <linux/mm.h>
26
//#include <asm/uaccess.h>
27
#include "aufs.h"
28
29
void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
30
{
31
	void *q;
32
33
	LKTRTrace("p %p, nused %d, sz %d\n", p, nused, new_sz);
34
	AuDebugOn(new_sz <= 0);
35
	if (new_sz <= nused)
36
		return p;
37
38
	q = krealloc(p, new_sz, gfp);
39
	if (q)
40
		memset(q + nused, 0, new_sz - nused);
41
	return q;
42
}
43
44
/* ---------------------------------------------------------------------- */
45
46
struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst,
47
			    struct nameidata *src)
48
{
49
	LKTRTrace("src %p\n", src);
50
51
	if (src) {
52
		*dst = *src;
53
		dst->flags &= ~LOOKUP_PARENT;
54
		if (sbinfo->si_wbr_create == AuWbrCreate_TDP) {
55
			if ((dst->flags & LOOKUP_CREATE)
56
			    && !(dst->intent.open.flags & O_CREAT))
57
				dst->flags &= ~LOOKUP_CREATE;
58
		} else {
59
			dst->flags &= ~LOOKUP_CREATE;
60
			dst->intent.open.flags &= ~O_CREAT;
61
		}
62
	} else
63
		dst = NULL;
64
65
	return dst;
66
}
67
68
struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
69
			     struct super_block *sb, aufs_bindex_t bindex)
70
{
71
	LKTRTrace("nd %p, b%d\n", nd, bindex);
72
73
	if (!nd)
74
		return NULL;
75
76
	DiMustAnyLock(nd->path.dentry);
77
78
	fake_nd->path.dentry = NULL;
79
	fake_nd->path.mnt = NULL;
80
81
	if (bindex <= au_dbend(nd->path.dentry))
82
		fake_nd->path.dentry = au_h_dptr(nd->path.dentry, bindex);
83
	if (fake_nd->path.dentry) {
84
		fake_nd->path.mnt = au_sbr_mnt(sb, bindex);
85
		AuDebugOn(!fake_nd->path.mnt);
86
		path_get(&fake_nd->path);
87
	} else
88
		fake_nd = ERR_PTR(-ENOENT);
89
90
	AuTraceErrPtr(fake_nd);
91
	return fake_nd;
92
}
93
94
void au_fake_dm_release(struct nameidata *fake_nd)
95
{
96
	if (fake_nd)
97
		path_put(&fake_nd->path);
98
}
99
100
int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
101
		int dlgt, struct nameidata *nd, struct vfsmount *nfsmnt)
102
{
103
	int err;
104
105
	LKTRTrace("hi%lu, %.*s, 0%o, nd %d, nfsmnt %d\n",
106
		  h_dir->i_ino, AuDLNPair(h_dentry), mode, !!nd, !!nfsmnt);
107
108
	err = -ENOSYS;
109
	if (!nfsmnt)
110
		err = vfsub_create(h_dir, h_dentry, mode, /*nd*/NULL, dlgt);
111
	else {
112
		struct nameidata fake_nd;
113
114
		if (nd)
115
			fake_nd = *nd;
116
		else
117
			memset(&fake_nd, 0, sizeof(fake_nd));
118
		fake_nd.path.dentry = h_dentry;
119
		fake_nd.path.mnt = nfsmnt;
120
		path_get(&fake_nd.path);
121
		fake_nd.flags = LOOKUP_CREATE;
122
		fake_nd.intent.open.flags = O_CREAT | FMODE_READ;
123
		fake_nd.intent.open.create_mode = mode;
124
125
		err = vfsub_create(h_dir, h_dentry, mode, &fake_nd, dlgt);
126
		path_put(&fake_nd.path);
127
	}
128
129
	AuTraceErr(err);
130
	return err;
131
}
132
133
/* ---------------------------------------------------------------------- */
134
135
int au_copy_file(struct file *dst, struct file *src, loff_t len,
136
		 struct super_block *sb)
137
{
138
	int err, all_zero;
139
	unsigned long blksize;
140
	char *buf;
141
	struct vfsub_args vargs;
142
	/* reduce stack space */
143
	struct iattr *ia;
144
145
	LKTRTrace("%.*s, %.*s\n",
146
		  AuDLNPair(dst->f_dentry), AuDLNPair(src->f_dentry));
147
	AuDebugOn(!(dst->f_mode & FMODE_WRITE));
148
#ifdef CONFIG_AUFS_DEBUG
149
	{
150
		struct dentry *parent;
151
		parent = dget_parent(dst->f_dentry);
152
		IMustLock(parent->d_inode);
153
		dput(parent);
154
	}
155
#endif
156
157
	err = -ENOMEM;
158
	blksize = dst->f_dentry->d_sb->s_blocksize;
159
	if (!blksize || PAGE_SIZE < blksize)
160
		blksize = PAGE_SIZE;
161
	LKTRTrace("blksize %lu\n", blksize);
162
	buf = kmalloc(blksize, GFP_TEMPORARY);
163
	//buf = NULL;
164
	if (unlikely(!buf))
165
		goto out;
166
	ia = kmalloc(sizeof(*ia), GFP_TEMPORARY);
167
	if (unlikely(!ia))
168
		goto out_buf;
169
170
#ifdef CONFIG_AUFS_DEBUG
171
	if (len > (1 << 22))
172
		AuWarn("copying a large file %Ld\n", (long long)len);
173
#endif
174
	vfsub_args_init(&vargs, NULL, au_opt_test_dlgt(au_mntflags(sb)), 0);
175
	err = 0;
176
	all_zero = 0;
177
	src->f_pos = 0;
178
	dst->f_pos = 0;
179
	while (len) {
180
		size_t sz, rbytes, wbytes, i;
181
		char *p;
182
183
		LKTRTrace("len %lld\n", len);
184
		sz = blksize;
185
		if (len < blksize)
186
			sz = len;
187
188
		/* support LSM and notify */
189
		rbytes = 0;
190
		// signal_pending
191
		while (!rbytes || err == -EAGAIN || err == -EINTR) {
192
			rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
193
					      vfsub_ftest(vargs.flags, DLGT));
194
			err = rbytes;
195
		}
196
		if (unlikely(err < 0))
197
			break;
198
199
		all_zero = 0;
200
		if (len >= rbytes && rbytes == blksize) {
201
			//todo: try bitmap or memcmp()/get_zeroed_page()
202
			unsigned long *ulp;
203
			size_t n;
204
205
			all_zero = 1;
206
			ulp = (void *)buf;
207
			n = rbytes / sizeof(*ulp);
208
			i = n;
209
			while (n-- > 0 && all_zero)
210
				all_zero = !*ulp++;
211
			p = (void *)ulp;
212
			i *= sizeof(*ulp);
213
			for (; all_zero && i < rbytes; i++)
214
				all_zero = !*p++;
215
		}
216
		if (!all_zero) {
217
			wbytes = rbytes;
218
			p = buf;
219
			while (wbytes) {
220
				size_t b;
221
				/* support LSM and notify */
222
				b = vfsub_write_k(dst, p, wbytes, &dst->f_pos,
223
						  &vargs);
224
				err = b;
225
				// signal_pending
226
				if (unlikely(err == -EAGAIN || err == -EINTR))
227
					continue;
228
				if (unlikely(err < 0))
229
					break;
230
				wbytes -= b;
231
				p += b;
232
			}
233
		} else {
234
			loff_t res;
235
			LKTRLabel(hole);
236
			res = vfsub_llseek(dst, rbytes, SEEK_CUR);
237
			err = res;
238
			if (unlikely(res < 0))
239
				break;
240
		}
241
		len -= rbytes;
242
		err = 0;
243
	}
244
245
	/* the last block may be a hole */
246
	if (unlikely(!err && all_zero)) {
247
		struct dentry *h_d = dst->f_dentry;
248
		struct inode *h_i = h_d->d_inode;
249
250
		LKTRLabel(last hole);
251
		do {
252
			// signal_pending
253
			err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, &vargs);
254
		} while (err == -EAGAIN || err == -EINTR);
255
		if (err == 1) {
256
			ia->ia_size = dst->f_pos;
257
			ia->ia_valid = ATTR_SIZE | ATTR_FILE;
258
			ia->ia_file = dst;
259
			mutex_lock_nested(&h_i->i_mutex, AuLsc_I_CHILD2);
260
			err = vfsub_notify_change(h_d, ia, &vargs);
261
			mutex_unlock(&h_i->i_mutex);
262
		}
263
	}
264
265
	kfree(ia);
266
 out_buf:
267
	kfree(buf);
268
 out:
269
	AuTraceErr(err);
270
	return err;
271
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/misc.h (+201 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * $Id: misc.h,v 1.2 2008/04/21 01:33:00 sfjro Exp $
21
 */
22
23
#ifndef __AUFS_MISC_H__
24
#define __AUFS_MISC_H__
25
26
#ifdef __KERNEL__
27
28
#include <linux/fs.h>
29
#include <linux/namei.h>
30
#include <linux/aufs_type.h>
31
32
/* ---------------------------------------------------------------------- */
33
34
typedef unsigned int au_gen_t;
35
/* see linux/include/linux/jiffies.h */
36
#define AuGenYounger(a, b)	((int)(b) - (int)(a) < 0)
37
#define AuGenOlder(a, b)	AufsGenYounger(b, a)
38
39
/* ---------------------------------------------------------------------- */
40
41
struct au_rwsem {
42
	struct rw_semaphore	rwsem;
43
#ifdef CONFIG_AUFS_DEBUG
44
	atomic_t		rcnt;
45
#endif
46
};
47
48
#ifdef CONFIG_AUFS_DEBUG
49
#define AuDbgRcntInit(rw) do { \
50
	atomic_set(&(rw)->rcnt, 0); \
51
	smp_mb(); \
52
} while (0)
53
54
#define AuDbgRcntInc(rw)	atomic_inc_return(&(rw)->rcnt)
55
#define AuDbgRcntDec(rw)	WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
56
#else
57
#define AuDbgRcntInit(rw)	do {} while (0)
58
#define AuDbgRcntInc(rw)	do {} while (0)
59
#define AuDbgRcntDec(rw)	do {} while (0)
60
#endif /* CONFIG_AUFS_DEBUG */
61
62
static inline void au_rw_init_nolock(struct au_rwsem *rw)
63
{
64
	AuDbgRcntInit(rw);
65
	init_rwsem(&rw->rwsem);
66
}
67
68
static inline void au_rw_init_wlock(struct au_rwsem *rw)
69
{
70
	au_rw_init_nolock(rw);
71
	down_write(&rw->rwsem);
72
}
73
74
static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
75
					   unsigned int lsc)
76
{
77
	au_rw_init_nolock(rw);
78
	down_write_nested(&rw->rwsem, lsc);
79
}
80
81
static inline void au_rw_read_lock(struct au_rwsem *rw)
82
{
83
	down_read(&rw->rwsem);
84
	AuDbgRcntInc(rw);
85
}
86
87
static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
88
{
89
	down_read_nested(&rw->rwsem, lsc);
90
	AuDbgRcntInc(rw);
91
}
92
93
static inline void au_rw_read_unlock(struct au_rwsem *rw)
94
{
95
	AuDbgRcntDec(rw);
96
	up_read(&rw->rwsem);
97
}
98
99
static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
100
{
101
	AuDbgRcntInc(rw);
102
	downgrade_write(&rw->rwsem);
103
}
104
105
static inline void au_rw_write_lock(struct au_rwsem *rw)
106
{
107
	down_write(&rw->rwsem);
108
}
109
110
static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
111
					   unsigned int lsc)
112
{
113
	down_write_nested(&rw->rwsem, lsc);
114
}
115
116
static inline void au_rw_write_unlock(struct au_rwsem *rw)
117
{
118
	up_write(&rw->rwsem);
119
}
120
121
/* why is not _nested version defined */
122
static inline int au_rw_read_trylock(struct au_rwsem *rw)
123
{
124
	int ret = down_read_trylock(&rw->rwsem);
125
	if (ret)
126
		AuDbgRcntInc(rw);
127
	return ret;
128
}
129
130
static inline int au_rw_write_trylock(struct au_rwsem *rw)
131
{
132
	return down_write_trylock(&rw->rwsem);
133
}
134
135
#undef AuDbgRcntInit
136
#undef AuDbgRcntInc
137
#undef AuDbgRcntDec
138
139
/* to debug easier, do not make them inlined functions */
140
#define AuRwMustNoWaiters(rw)	AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
141
#define AuRwMustAnyLock(rw)	AuDebugOn(down_write_trylock(&(rw)->rwsem))
142
#ifdef CONFIG_AUFS_DEBUG
143
#define AuRwMustReadLock(rw) do { \
144
	AuRwMustAnyLock(rw); \
145
	AuDebugOn(!atomic_read(&(rw)->rcnt)); \
146
} while (0)
147
148
#define AuRwMustWriteLock(rw) do { \
149
	AuRwMustAnyLock(rw); \
150
	AuDebugOn(atomic_read(&(rw)->rcnt)); \
151
} while (0)
152
#else
153
#define AuRwMustReadLock(rw)	AuRwMustAnyLock(rw)
154
#define AuRwMustWriteLock(rw)	AuRwMustAnyLock(rw)
155
#endif /* CONFIG_AUFS_DEBUG */
156
157
#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
158
static inline void prefix##_read_lock(param) \
159
{ au_rw_read_lock(&(rwsem)); } \
160
static inline void prefix##_write_lock(param) \
161
{ au_rw_write_lock(&(rwsem)); } \
162
static inline int prefix##_read_trylock(param) \
163
{ return au_rw_read_trylock(&(rwsem)); } \
164
static inline int prefix##_write_trylock(param) \
165
{ return au_rw_write_trylock(&(rwsem)); }
166
//static inline void prefix##_read_trylock_nested(param, lsc)
167
//{au_rw_read_trylock_nested(&(rwsem, lsc));}
168
//static inline void prefix##_write_trylock_nestd(param, lsc)
169
//{au_rw_write_trylock_nested(&(rwsem), nested);}
170
171
#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
172
static inline void prefix##_read_unlock(param) \
173
{ au_rw_read_unlock(&(rwsem)); } \
174
static inline void prefix##_write_unlock(param) \
175
{ au_rw_write_unlock(&(rwsem)); } \
176
static inline void prefix##_downgrade_lock(param) \
177
{ au_rw_dgrade_lock(&(rwsem)); }
178
179
#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
180
	AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
181
	AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
182
183
/* ---------------------------------------------------------------------- */
184
185
void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
186
187
struct au_sbinfo;
188
struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst,
189
			    struct nameidata *src);
190
191
struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
192
			     struct super_block *sb, aufs_bindex_t bindex);
193
void au_fake_dm_release(struct nameidata *fake_nd);
194
int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
195
		int dlgt, struct nameidata *nd, struct vfsmount *nfsmnt);
196
197
int au_copy_file(struct file *dst, struct file *src, loff_t len,
198
		 struct super_block *sb);
199
200
#endif /* __KERNEL__ */
201
#endif /* __AUFS_MISC_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/module.c (+237 lines)
Line 0 Link Here
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
/*
20
 * module global variables and operations
21
 *
22
 * $Id: module.c,v 1.4 2008/05/19 01:49:24 sfjro Exp $
23
 */
24
25
#include <linux/module.h>
26
#include "aufs.h"
27
28
/* ---------------------------------------------------------------------- */
29
30
/*
31
 * aufs caches
32
 */
33
struct kmem_cache *au_cachep[AuCache_Last];
34
static int __init create_cache(void)
35
{
36
	au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
37
	if (au_cachep[AuCache_DINFO])
38
		au_cachep[AuCache_ICNTNR] = AuCache(aufs_icntnr);
39
	if (au_cachep[AuCache_ICNTNR])
40
		au_cachep[AuCache_FINFO] = AuCache(au_finfo);
41
	//au_cachep[AuCache_FINFO] = NULL;
42
	if (au_cachep[AuCache_FINFO])
43
		au_cachep[AuCache_VDIR] = AuCache(au_vdir);
44
	if (au_cachep[AuCache_VDIR])
45
		au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
46
	if (au_cachep[AuCache_DEHSTR])
47
		return 0;
48
49
	return -ENOMEM;
50
}
51
52
static void destroy_cache(void)
53
{
54
	int i;
55
	for (i = 0; i < AuCache_Last; i++)
56
		if (au_cachep[i]) {
57
			kmem_cache_destroy(au_cachep[i]);
58
			au_cachep[i] = NULL;
59
		}
60
}
61
62
/* ---------------------------------------------------------------------- */
63
64
char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
65
int au_dir_roflags;
66
67
/*
68
 * functions for module interface.
69
 */
70
MODULE_LICENSE("GPL");
71
MODULE_AUTHOR("Junjiro Okajima");
72
MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs");
73
MODULE_VERSION(AUFS_VERSION);
74
75
/* it should be 'byte', but param_set_byte() prints it by "%c" */
76
short aufs_nwkq = AUFS_NWKQ_DEF;
77
MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
78
module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
79
80
int sysaufs_brs;
81
MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
82
module_param_named(brs, sysaufs_brs, int, S_IRUGO);
83
84
/* ---------------------------------------------------------------------- */
85
86
static int __init aufs_init(void)
87
{
88
	int err, i;
89
	char *p;
90
91
	au_debug_init();
92
93
	p = au_esc_chars;
94
	for (i = 1; i <= ' '; i++)
95
		*p++ = i;
96
	*p++ = '\\';
97
	*p++ = '\x7f';
98
	*p = 0;
99
100
	au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
101
102
	err = -EINVAL;
103
	if (unlikely(aufs_nwkq <= 0))
104
		goto out;
105
106
	err = sysaufs_init();
107
	if (unlikely(err))
108
		goto out;
109
	err = au_wkq_init();
110
	if (unlikely(err))
111
		goto out_sysaufs;
112
	err = au_inotify_init();
113
	if (unlikely(err))
114
		goto out_wkq;
115
	err = au_sysrq_init();
116
	if (unlikely(err))
117
		goto out_inotify;
118
119
	err = create_cache();
120
	if (unlikely(err))
121
		goto out_sysrq;
122
123
	err = register_filesystem(&aufs_fs_type);
124
	if (unlikely(err))
125
		goto out_cache;
126
	pr_info(AUFS_NAME " " AUFS_VERSION "\n");
127
	return 0; /* success */
128
129
 out_cache:
130
	destroy_cache();
131
 out_sysrq:
132
	au_sysrq_fin();
133
 out_inotify:
134
	au_inotify_fin();
135
 out_wkq:
136
	au_wkq_fin();
137
 out_sysaufs:
138
	sysaufs_fin();
139
 out:
140
	AuTraceErr(err);
141
	return err;
142
}
143
144
static void __exit aufs_exit(void)
145
{
146
	unregister_filesystem(&aufs_fs_type);
147
	destroy_cache();
148
149
	au_sysrq_fin();
150
	au_inotify_fin();
151
	au_wkq_fin();
152
	sysaufs_fin();
153
}
154
155
module_init(aufs_init);
156
module_exit(aufs_exit);
157
158
/* ---------------------------------------------------------------------- */
159
160
/* fake Kconfig */
161
#if 1
162
163
#ifdef CONFIG_AUFS_HINOTIFY
164
#ifndef CONFIG_INOTIFY
165
#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY.
166
#endif
167
#endif /* CONFIG_AUFS_HINOTIFY */
168
169
#if AUFS_BRANCH_MAX > 511 && PAGE_SIZE > 4096
170
#warning pagesize is larger than 4kb, \
171
	CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended.
172
#endif
173
174
#ifdef CONFIG_AUFS_STAT
175
#ifndef CONFIG_SYSFS
176
#error CONFIG_AUFS_STAT requires CONFIG_SYSFS.
177
#endif
178
#endif /* CONFIG_AUFS_STAT */
179
180
#ifdef CONFIG_AUFS_EXPORT
181
#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE)
182
#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS
183
#endif
184
#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS)
185
#error need CONFIG_EXPORTFS = y to link aufs statically with CONFIG_AUFS_EXPORT
186
#endif
187
#endif /* CONFIG_AUFS_EXPORT */
188
189
#ifdef CONFIG_AUFS_SEC_PERM_PATCH
190
#ifndef CONFIG_SECURITY
191
#warning CONFIG_AUFS_SEC_PERM_PATCH is unnecessary since CONFIG_SECURITY is disabled.
192
#endif
193
#ifdef CONFIG_AUFS
194
#warning CONFIG_AUFS_SEC_PERM_PATCH is unnecessary since CONFIG_AUFS is not a module.
195
#endif
196
#endif
197
198
#ifdef CONFIG_AUFS_FAKE_DM
199
#warning CONFIG_AUFS_FAKE_DM is obsoleted in linux-2.6.24 and later.
200
#endif
201
202
#ifdef CONFIG_AUFS_PUT_FILP_PATCH
203
#if !defined(CONFIG_NFS_FS) && !defined(CONFIG_NFS_FS_MODULE)
204
#warning CONFIG_AUFS_PUT_FILP_PATCH is unnecessary since CONFIG_NFS_FS is disabled.
205
#endif
206
#ifdef CONFIG_AUFS
207
#warning CONFIG_AUFS_PUT_FILP_PATCH is unnecessary since CONFIG_AUFS is not a module.
208
#endif
209
#endif /* CONFIG_AUFS_PUT_FILP_PATCH */
210
211
#ifdef CONFIG_AUFS_LHASH_PATCH
212
#if !defined(CONFIG_NFS_FS) && !defined(CONFIG_NFS_FS_MODULE)
213
#warning CONFIG_AUFS_LHASH_PATCH is unnecessary since CONFIG_NFS_FS is disabled.
214
#endif
215
#endif
216
217
#ifdef CONFIG_AUFS_KSIZE_PATCH
218
#warning CONFIG_AUFS_KSIZE_PATCH is unnecessary for linux-2.6.22 and later.
219
#endif
220
221
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
222
#if !defined(CONFIG_FUSE_FS) && !defined(CONFIG_FUSE_FS_MODULE)
223
#warning CONFIG_AUFS_WORKAROUND_FUSE is enabled while FUSE is disabled.
224
#endif
225
#endif
226
227
#ifdef CONFIG_DEBUG_PROVE_LOCKING
228
#if MAX_LOCKDEP_SUBCLASSES < AuLsc_I_End
229
#warning lockdep will not work since aufs uses deeper locks.
230
#endif
231
#endif
232
233
#ifdef CONFIG_AUFS_COMPAT
234
#warning CONFIG_AUFS_COMPAT will be removed in the near future.
235
#endif
236
237
#endif
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/module.h (+78 lines)
Line 0 Link Here
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
 * module initialization and module-global
21
 *
22
 * $Id: module.h,v 1.2 2008/04/21 01:33:00 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_MODULE_H__
26
#define __AUFS_MODULE_H__
27
28
#ifdef __KERNEL__
29
30
//#include <linux/slab.h>
31
32
/* ---------------------------------------------------------------------- */
33
34
/* module parameters */
35
extern short aufs_nwkq;
36
extern int sysaufs_brs;
37
38
/* ---------------------------------------------------------------------- */
39
40
extern char au_esc_chars[];
41
extern int au_dir_roflags;
42
43
/* kmem cache */
44
enum {
45
	AuCache_DINFO,
46
	AuCache_ICNTNR,
47
	AuCache_FINFO,
48
	AuCache_VDIR,
49
	AuCache_DEHSTR,
50
#ifdef CONFIG_AUFS_HINOTIFY
51
	AuCache_HINOTIFY,
52
#endif
53
	AuCache_Last
54
};
55
56
extern struct kmem_cache *au_cachep[];
57
58
#define AuCacheArgs(type, sz)	(type), (sz), 0, SLAB_RECLAIM_ACCOUNT, NULL
59
#define AuCacheX(type, extra) \
60
	kmem_cache_create(AuCacheArgs(#type, sizeof(struct type) + extra))
61
#define AuCache(type)		AuCacheX(type, 0)
62
63
/* ---------------------------------------------------------------------- */
64
65
#define AuCacheFuncs(name, index) \
66
static inline void *au_cache_alloc_##name(void) \
67
{ return kmem_cache_alloc(au_cachep[index], GFP_KERNEL); } \
68
static inline void au_cache_free_##name(void *p) \
69
{ kmem_cache_free(au_cachep[index], p); }
70
71
AuCacheFuncs(dinfo, AuCache_DINFO);
72
AuCacheFuncs(icntnr, AuCache_ICNTNR);
73
AuCacheFuncs(finfo, AuCache_FINFO);
74
AuCacheFuncs(vdir, AuCache_VDIR);
75
AuCacheFuncs(dehstr, AuCache_DEHSTR);
76
77
#endif /* __KERNEL__ */
78
#endif /* __AUFS_MODULE_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/opts.c (+1465 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * mount options/flags
21
 *
22
 * $Id: opts.c,v 1.5 2008/05/19 01:49:36 sfjro Exp $
23
 */
24
25
#include <linux/types.h> /* a distribution requires */
26
#include <linux/parser.h>
27
#include "aufs.h"
28
29
/* ---------------------------------------------------------------------- */
30
31
enum {
32
	Opt_br,
33
	Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
34
	Opt_idel, Opt_imod, Opt_ireorder,
35
	Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash, Opt_rendir,
36
	Opt_xino, Opt_zxino, Opt_noxino,
37
	Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
38
	Opt_trunc_xino_path, Opt_itrunc_xino,
39
	Opt_xinodir, Opt_xinonames, Opt_ixinonames,
40
	Opt_trunc_xib, Opt_notrunc_xib,
41
	Opt_dirperm1, Opt_nodirperm1,
42
	Opt_shwh, Opt_noshwh,
43
	Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink,
44
	Opt_udba,
45
	//Opt_lock, Opt_unlock,
46
	Opt_cmd, Opt_cmd_args,
47
	Opt_diropq_a, Opt_diropq_w,
48
	Opt_warn_perm, Opt_nowarn_perm,
49
	Opt_wbr_copyup, Opt_wbr_create,
50
	Opt_coo,
51
	Opt_dlgt, Opt_nodlgt,
52
	Opt_refrof, Opt_norefrof,
53
	Opt_verbose, Opt_noverbose,
54
	Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
55
};
56
57
static match_table_t options = {
58
	{Opt_br, "br=%s"},
59
	{Opt_br, "br:%s"},
60
61
	{Opt_add, "add=%d:%s"},
62
	{Opt_add, "add:%d:%s"},
63
	{Opt_add, "ins=%d:%s"},
64
	{Opt_add, "ins:%d:%s"},
65
	{Opt_append, "append=%s"},
66
	{Opt_append, "append:%s"},
67
	{Opt_prepend, "prepend=%s"},
68
	{Opt_prepend, "prepend:%s"},
69
70
	{Opt_del, "del=%s"},
71
	{Opt_del, "del:%s"},
72
	//{Opt_idel, "idel:%d"},
73
	{Opt_mod, "mod=%s"},
74
	{Opt_mod, "mod:%s"},
75
	{Opt_imod, "imod:%d:%s"},
76
77
	{Opt_dirwh, "dirwh=%d"},
78
	{Opt_dirwh, "dirwh:%d"},
79
80
	{Opt_xino, "xino=%s"},
81
	{Opt_xino, "xino:%s"},
82
	{Opt_xinodir, "xinodir=%s"},
83
	{Opt_xinodir, "xinodir:%s"},
84
	{Opt_noxino, "noxino"},
85
	{Opt_trunc_xino, "trunc_xino"},
86
	{Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
87
	{Opt_notrunc_xino, "notrunc_xino"},
88
	{Opt_trunc_xino_path, "trunc_xino=%s"},
89
	{Opt_trunc_xino_path, "trunc_xino:%s"},
90
	{Opt_itrunc_xino, "itrunc_xino=%d"},
91
	{Opt_itrunc_xino, "itrunc_xino:%d"},
92
	//{Opt_zxino, "zxino=%s"},
93
	{Opt_trunc_xib, "trunc_xib"},
94
	{Opt_notrunc_xib, "notrunc_xib"},
95
96
	{Opt_plink, "plink"},
97
	{Opt_noplink, "noplink"},
98
#ifdef CONFIG_AUFS_DEBUG
99
	{Opt_list_plink, "list_plink"},
100
#endif
101
	{Opt_clean_plink, "clean_plink"},
102
103
	{Opt_udba, "udba=%s"},
104
105
	{Opt_diropq_a, "diropq=always"},
106
	{Opt_diropq_a, "diropq=a"},
107
	{Opt_diropq_w, "diropq=whiteouted"},
108
	{Opt_diropq_w, "diropq=w"},
109
110
	{Opt_warn_perm, "warn_perm"},
111
	{Opt_nowarn_perm, "nowarn_perm"},
112
113
#ifdef CONFIG_AUFS_DLGT
114
	{Opt_dlgt, "dlgt"},
115
	{Opt_nodlgt, "nodlgt"},
116
117
	{Opt_dirperm1, "dirperm1"},
118
	{Opt_nodirperm1, "nodirperm1"},
119
#endif
120
121
#ifdef CONFIG_AUFS_SHWH
122
	{Opt_shwh, "shwh"},
123
	{Opt_noshwh, "noshwh"},
124
#endif
125
126
	{Opt_rendir, "rendir=%d"},
127
	{Opt_rendir, "rendir:%d"},
128
129
	{Opt_refrof, "refrof"},
130
	{Opt_norefrof, "norefrof"},
131
132
	{Opt_verbose, "verbose"},
133
	{Opt_verbose, "v"},
134
	{Opt_noverbose, "noverbose"},
135
	{Opt_noverbose, "quiet"},
136
	{Opt_noverbose, "q"},
137
	{Opt_noverbose, "silent"},
138
139
	{Opt_rdcache, "rdcache=%d"},
140
	{Opt_rdcache, "rdcache:%d"},
141
142
	{Opt_coo, "coo=%s"},
143
144
	{Opt_wbr_create, "create=%s"},
145
	{Opt_wbr_create, "create:%s"},
146
	{Opt_wbr_create, "create_policy=%s"},
147
	{Opt_wbr_create, "create_policy:%s"},
148
	{Opt_wbr_copyup, "cpup=%s"},
149
	{Opt_wbr_copyup, "cpup:%s"},
150
	{Opt_wbr_copyup, "copyup=%s"},
151
	{Opt_wbr_copyup, "copyup:%s"},
152
	{Opt_wbr_copyup, "copyup_policy=%s"},
153
	{Opt_wbr_copyup, "copyup_policy:%s"},
154
155
	/* internal use for the scripts */
156
	{Opt_ignore_silent, "si=%s"},
157
158
	{Opt_br, "dirs=%s"},
159
	{Opt_ignore, "debug=%d"},
160
	{Opt_ignore, "delete=whiteout"},
161
	{Opt_ignore, "delete=all"},
162
	{Opt_ignore, "imap=%s"},
163
164
	{Opt_err, NULL}
165
};
166
167
/* ---------------------------------------------------------------------- */
168
169
static const char *au_parser_pattern(int val, struct match_token *token)
170
{
171
	while (token->pattern) {
172
		if (token->token == val)
173
			return token->pattern;
174
		token++;
175
	}
176
	BUG();
177
	return "??";
178
}
179
180
/* ---------------------------------------------------------------------- */
181
182
#define RW		"rw"
183
#define RO		"ro"
184
#define WH		"wh"
185
#define RR		"rr"
186
#define NoLinkWH	"nolwh"
187
188
static match_table_t brperms = {
189
	{AuBr_RR, RR},
190
	{AuBr_RO, RO},
191
	{AuBr_RW, RW},
192
193
	{AuBr_RRWH, RR "+" WH},
194
	{AuBr_ROWH, RO "+" WH},
195
	{AuBr_RWNoLinkWH, RW "+" NoLinkWH},
196
197
	{AuBr_ROWH, "nfsro"},
198
	{AuBr_RO, NULL}
199
};
200
201
static noinline_for_stack int br_perm_val(char *perm)
202
{
203
	int val;
204
	substring_t args[MAX_OPT_ARGS];
205
206
	AuDebugOn(!perm || !*perm);
207
	LKTRTrace("perm %s\n", perm);
208
	val = match_token(perm, brperms, args);
209
	AuTraceErr(val);
210
	return val;
211
}
212
213
const char *au_optstr_br_perm(int brperm)
214
{
215
	return au_parser_pattern(brperm, brperms);
216
}
217
218
/* ---------------------------------------------------------------------- */
219
220
static match_table_t udbalevel = {
221
	{AuOpt_UDBA_REVAL, "reval"},
222
#ifdef CONFIG_AUFS_HINOTIFY
223
	{AuOpt_UDBA_INOTIFY, "inotify"},
224
#endif
225
	{AuOpt_UDBA_NONE, "none"},
226
	{-1, NULL}
227
};
228
229
static noinline_for_stack int udba_val(char *str)
230
{
231
	substring_t args[MAX_OPT_ARGS];
232
	return match_token(str, udbalevel, args);
233
}
234
235
const char *au_optstr_udba(int udba)
236
{
237
	return au_parser_pattern(udba, udbalevel);
238
}
239
240
/* ---------------------------------------------------------------------- */
241
242
static match_table_t coolevel = {
243
	{AuOpt_COO_NONE, "none"},
244
	{AuOpt_COO_LEAF, "leaf"},
245
	{AuOpt_COO_ALL, "all"},
246
	{-1, NULL}
247
};
248
249
static noinline_for_stack int coo_val(char *str)
250
{
251
	substring_t args[MAX_OPT_ARGS];
252
	return match_token(str, coolevel, args);
253
}
254
255
const char *au_optstr_coo(int coo)
256
{
257
	return au_parser_pattern(coo, coolevel);
258
}
259
260
/* ---------------------------------------------------------------------- */
261
262
static match_table_t au_wbr_create_policy = {
263
	{AuWbrCreate_TDP, "tdp"},
264
	{AuWbrCreate_TDP, "top-down-parent"},
265
	{AuWbrCreate_RR, "rr"},
266
	{AuWbrCreate_RR, "round-robin"},
267
	{AuWbrCreate_MFS, "mfs"},
268
	{AuWbrCreate_MFS, "most-free-space"},
269
	{AuWbrCreate_MFSV, "mfs:%d"},
270
	{AuWbrCreate_MFSV, "most-free-space:%d"},
271
272
	{AuWbrCreate_MFSRR, "mfsrr:%d"},
273
	{AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
274
	{AuWbrCreate_PMFS, "pmfs"},
275
	{AuWbrCreate_PMFSV, "pmfs:%d"},
276
277
	{-1, NULL}
278
};
279
280
/* cf. linux/lib/parser.c */
281
static int au_match_ull(substring_t *s, unsigned long long *result, int base)
282
{
283
	char *endp;
284
	char *buf;
285
	int ret;
286
287
	buf = kmalloc(s->to - s->from + 1, GFP_KERNEL);
288
	if (!buf)
289
		return -ENOMEM;
290
	memcpy(buf, s->from, s->to - s->from);
291
	buf[s->to - s->from] = '\0';
292
	*result = simple_strtoull(buf, &endp, base);
293
	ret = 0;
294
	if (endp == buf)
295
		ret = -EINVAL;
296
	kfree(buf);
297
	return ret;
298
}
299
300
static int au_wbr_mfs_wmark(substring_t *arg, char *str,
301
			    struct au_opt_wbr_create *create)
302
{
303
	int err;
304
	u64 ull;
305
306
	err = 0;
307
	if (!au_match_ull(arg, &ull, 0))
308
		create->mfsrr_watermark = ull;
309
	else {
310
		AuErr("bad integer in %s\n", str);
311
		err = -EINVAL;
312
	}
313
314
	AuTraceErr(err);
315
	return err;
316
}
317
318
static int au_wbr_mfs_sec(substring_t *arg, char *str,
319
			  struct au_opt_wbr_create *create)
320
{
321
	int n, err;
322
323
	err = 0;
324
	if (!match_int(arg, &n) && 0 <= n)
325
		create->mfs_second = n;
326
	else {
327
		AuErr("bad integer in %s\n", str);
328
		err = -EINVAL;
329
	}
330
331
	AuTraceErr(err);
332
	return err;
333
}
334
335
static noinline_for_stack int
336
au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
337
{
338
	int err, e;
339
	substring_t args[MAX_OPT_ARGS];
340
341
	err = match_token(str, au_wbr_create_policy, args);
342
	create->wbr_create = err;
343
	switch (err) {
344
	case AuWbrCreate_MFSRRV:
345
		e = au_wbr_mfs_wmark(&args[0], str, create);
346
		if (!e)
347
			e = au_wbr_mfs_sec(&args[1], str, create);
348
		if (unlikely(e))
349
			err = e;
350
		break;
351
	case AuWbrCreate_MFSRR:
352
		e = au_wbr_mfs_wmark(&args[0], str, create);
353
		if (unlikely(e)) {
354
			err = e;
355
			break;
356
		}
357
		/*FALLTHROUGH*/
358
	case AuWbrCreate_MFS:
359
	case AuWbrCreate_PMFS:
360
		create->mfs_second = AUFS_MFS_SECOND_DEF;
361
		break;
362
	case AuWbrCreate_MFSV:
363
	case AuWbrCreate_PMFSV:
364
		e = au_wbr_mfs_sec(&args[0], str, create);
365
		if (unlikely(e))
366
			err = e;
367
		break;
368
	}
369
370
	return err;
371
}
372
373
const char *au_optstr_wbr_create(int wbr_create)
374
{
375
	return au_parser_pattern(wbr_create, au_wbr_create_policy);
376
}
377
378
static match_table_t au_wbr_copyup_policy = {
379
	{AuWbrCopyup_TDP, "tdp"},
380
	{AuWbrCopyup_TDP, "top-down-parent"},
381
	{AuWbrCopyup_BUP, "bup"},
382
	{AuWbrCopyup_BUP, "bottom-up-parent"},
383
	{AuWbrCopyup_BU, "bu"},
384
	{AuWbrCopyup_BU, "bottom-up"},
385
	{-1, NULL}
386
};
387
388
static noinline_for_stack int au_wbr_copyup_val(char *str)
389
{
390
	substring_t args[MAX_OPT_ARGS];
391
	return match_token(str, au_wbr_copyup_policy, args);
392
}
393
394
const char *au_optstr_wbr_copyup(int wbr_copyup)
395
{
396
	return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
397
}
398
399
/* ---------------------------------------------------------------------- */
400
401
static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
402
403
static noinline_for_stack void dump_opts(struct au_opts *opts)
404
{
405
#ifdef CONFIG_AUFS_DEBUG
406
	/* reduce stack space */
407
	union {
408
		struct au_opt_add *add;
409
		struct au_opt_del *del;
410
		struct au_opt_mod *mod;
411
		struct au_opt_xino *xino;
412
		struct au_opt_xino_itrunc *xino_itrunc;
413
		struct au_opt_wbr_create *create;
414
	} u;
415
	struct au_opt *opt;
416
417
	AuTraceEnter();
418
419
	opt = opts->opt;
420
	while (/* opt < opts_tail && */ opt->type != Opt_tail) {
421
		switch (opt->type) {
422
		case Opt_add:
423
			u.add = &opt->add;
424
			LKTRTrace("add {b%d, %s, 0x%x, %p}\n",
425
				  u.add->bindex, u.add->path, u.add->perm,
426
				  u.add->nd.path.dentry);
427
			break;
428
		case Opt_del:
429
		case Opt_idel:
430
			u.del = &opt->del;
431
			LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root);
432
			break;
433
		case Opt_mod:
434
		case Opt_imod:
435
			u.mod = &opt->mod;
436
			LKTRTrace("mod {%s, 0x%x, %p}\n",
437
				  u.mod->path, u.mod->perm, u.mod->h_root);
438
			break;
439
		case Opt_append:
440
			u.add = &opt->add;
441
			LKTRTrace("append {b%d, %s, 0x%x, %p}\n",
442
				  u.add->bindex, u.add->path, u.add->perm,
443
				  u.add->nd.path.dentry);
444
			break;
445
		case Opt_prepend:
446
			u.add = &opt->add;
447
			LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n",
448
				  u.add->bindex, u.add->path, u.add->perm,
449
				  u.add->nd.path.dentry);
450
			break;
451
		case Opt_dirwh:
452
			LKTRTrace("dirwh %d\n", opt->dirwh);
453
			break;
454
		case Opt_rdcache:
455
			LKTRTrace("rdcache %d\n", opt->rdcache);
456
			break;
457
		case Opt_xino:
458
			u.xino = &opt->xino;
459
			LKTRTrace("xino {%s %.*s}\n",
460
				  u.xino->path,
461
				  AuDLNPair(u.xino->file->f_dentry));
462
			break;
463
		case Opt_trunc_xino:
464
			LKTRLabel(trunc_xino);
465
			break;
466
		case Opt_notrunc_xino:
467
			LKTRLabel(notrunc_xino);
468
			break;
469
		case Opt_trunc_xino_path:
470
		case Opt_itrunc_xino:
471
			u.xino_itrunc = &opt->xino_itrunc;
472
			LKTRTrace("trunc_xino %d\n", u.xino_itrunc->bindex);
473
			break;
474
475
		case Opt_noxino:
476
			LKTRLabel(noxino);
477
			break;
478
		case Opt_trunc_xib:
479
			LKTRLabel(trunc_xib);
480
			break;
481
		case Opt_notrunc_xib:
482
			LKTRLabel(notrunc_xib);
483
			break;
484
		case Opt_dirperm1:
485
			LKTRLabel(dirperm1);
486
			break;
487
		case Opt_nodirperm1:
488
			LKTRLabel(nodirperm1);
489
			break;
490
		case Opt_shwh:
491
			LKTRLabel(shwh);
492
			break;
493
		case Opt_noshwh:
494
			LKTRLabel(noshwh);
495
			break;
496
		case Opt_plink:
497
			LKTRLabel(plink);
498
			break;
499
		case Opt_noplink:
500
			LKTRLabel(noplink);
501
			break;
502
		case Opt_list_plink:
503
			LKTRLabel(list_plink);
504
			break;
505
		case Opt_clean_plink:
506
			LKTRLabel(clean_plink);
507
			break;
508
		case Opt_udba:
509
			LKTRTrace("udba %d, %s\n",
510
				  opt->udba, au_optstr_udba(opt->udba));
511
			break;
512
		case Opt_diropq_a:
513
			LKTRLabel(diropq_a);
514
			break;
515
		case Opt_diropq_w:
516
			LKTRLabel(diropq_w);
517
			break;
518
		case Opt_warn_perm:
519
			LKTRLabel(warn_perm);
520
			break;
521
		case Opt_nowarn_perm:
522
			LKTRLabel(nowarn_perm);
523
			break;
524
		case Opt_dlgt:
525
			LKTRLabel(dlgt);
526
			break;
527
		case Opt_nodlgt:
528
			LKTRLabel(nodlgt);
529
			break;
530
		case Opt_refrof:
531
			LKTRLabel(refrof);
532
			break;
533
		case Opt_norefrof:
534
			LKTRLabel(norefrof);
535
			break;
536
		case Opt_verbose:
537
			LKTRLabel(verbose);
538
			break;
539
		case Opt_noverbose:
540
			LKTRLabel(noverbose);
541
			break;
542
		case Opt_coo:
543
			LKTRTrace("coo %d, %s\n",
544
				  opt->coo, au_optstr_coo(opt->coo));
545
			break;
546
		case Opt_wbr_create:
547
			u.create = &opt->wbr_create;
548
			LKTRTrace("create %d, %s\n", u.create->wbr_create,
549
				  au_optstr_wbr_create(u.create->wbr_create));
550
			switch (u.create->wbr_create) {
551
			case AuWbrCreate_MFSV:
552
			case AuWbrCreate_PMFSV:
553
				LKTRTrace("%d sec\n", u.create->mfs_second);
554
				break;
555
			case AuWbrCreate_MFSRR:
556
				LKTRTrace("%Lu watermark\n",
557
					  u.create->mfsrr_watermark);
558
				break;
559
			case AuWbrCreate_MFSRRV:
560
				LKTRTrace("%Lu watermark, %d sec\n",
561
					  u.create->mfsrr_watermark,
562
					  u.create->mfs_second);
563
				break;
564
			}
565
			break;
566
		case Opt_wbr_copyup:
567
			LKTRTrace("copyup %d, %s\n", opt->wbr_copyup,
568
				  au_optstr_wbr_copyup(opt->wbr_copyup));
569
			break;
570
		default:
571
			BUG();
572
		}
573
		opt++;
574
	}
575
#endif
576
}
577
578
void au_opts_free(struct au_opts *opts)
579
{
580
	struct au_opt *opt;
581
582
	AuTraceEnter();
583
584
	opt = opts->opt;
585
	while (opt->type != Opt_tail) {
586
		switch (opt->type) {
587
		case Opt_add:
588
		case Opt_append:
589
		case Opt_prepend:
590
			path_put(&opt->add.nd.path);
591
			break;
592
		case Opt_del:
593
		case Opt_idel:
594
			dput(opt->del.h_root);
595
			break;
596
		case Opt_mod:
597
		case Opt_imod:
598
			dput(opt->mod.h_root);
599
			break;
600
		case Opt_xino:
601
			fput(opt->xino.file);
602
			break;
603
		}
604
		opt++;
605
	}
606
}
607
608
static int opt_add(struct au_opt *opt, char *opt_str, struct super_block *sb,
609
		   aufs_bindex_t bindex)
610
{
611
	int err;
612
	struct au_opt_add *add = &opt->add;
613
	char *p;
614
615
	LKTRTrace("%s, b%d\n", opt_str, bindex);
616
617
	add->bindex = bindex;
618
	add->perm = AuBr_Last;
619
	add->path = opt_str;
620
	p = strchr(opt_str, '=');
621
	if (unlikely(p)) {
622
		*p++ = 0;
623
		if (*p)
624
			add->perm = br_perm_val(p);
625
	}
626
627
	/* LSM may detect it */
628
	/* do not superio. */
629
	err = vfsub_path_lookup(add->path, lkup_dirflags, &add->nd);
630
	//err = -1;
631
	if (!err) {
632
		if (!p /* && add->perm == AuBr_Last */) {
633
			add->perm = AuBr_RO;
634
			if (au_test_def_rr(add->nd.path.dentry->d_sb))
635
				add->perm = AuBr_RR;
636
			if (!bindex && !(sb->s_flags & MS_RDONLY))
637
				add->perm = AuBr_RW;
638
#ifdef CONFIG_AUFS_COMPAT
639
			add->perm = AuBr_RW;
640
#endif
641
		}
642
		opt->type = Opt_add;
643
		goto out;
644
	}
645
	AuErr("lookup failed %s (%d)\n", add->path, err);
646
	err = -EINVAL;
647
648
 out:
649
	AuTraceErr(err);
650
	return err;
651
}
652
653
/* called without aufs lock */
654
int au_opts_parse(struct super_block *sb, unsigned long flags, char *str,
655
		  struct au_opts *opts)
656
{
657
	int err, n, token, skipped;
658
	struct dentry *root;
659
	struct au_opt *opt, *opt_tail;
660
	char *opt_str, *p;
661
	substring_t args[MAX_OPT_ARGS];
662
	aufs_bindex_t bindex, bend;
663
	struct nameidata nd;
664
	union {
665
		struct au_opt_del *del;
666
		struct au_opt_mod *mod;
667
		struct au_opt_xino *xino;
668
		struct au_opt_xino_itrunc *xino_itrunc;
669
		struct au_opt_wbr_create *create;
670
	} u;
671
	struct file *file;
672
673
	LKTRTrace("%s, nopts %d\n", str, opts->max_opt);
674
675
	root = sb->s_root;
676
	err = 0;
677
	bindex = 0;
678
	opt = opts->opt;
679
	opt_tail = opt + opts->max_opt - 1;
680
	opt->type = Opt_tail;
681
	while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
682
		err = -EINVAL;
683
		token = match_token(opt_str, options, args);
684
		LKTRTrace("%s, token %d, args[0]{%p, %p}\n",
685
			  opt_str, token, args[0].from, args[0].to);
686
687
		skipped = 0;
688
		switch (token) {
689
		case Opt_br:
690
			err = 0;
691
			while (!err && (opt_str = strsep(&args[0].from, ":"))
692
			       && *opt_str) {
693
				err = opt_add(opt, opt_str, sb, bindex++);
694
				//if (LktrCond) err = -1;
695
				if (unlikely(!err && ++opt > opt_tail)) {
696
					err = -E2BIG;
697
					break;
698
				}
699
				opt->type = Opt_tail;
700
				skipped = 1;
701
			}
702
			break;
703
		case Opt_add:
704
			if (unlikely(match_int(&args[0], &n))) {
705
				AuErr("bad integer in %s\n", opt_str);
706
				break;
707
			}
708
			bindex = n;
709
			err = opt_add(opt, args[1].from, sb, bindex);
710
			break;
711
		case Opt_append:
712
			err = opt_add(opt, args[0].from, sb, /*dummy bindex*/1);
713
			if (!err)
714
				opt->type = token;
715
			break;
716
		case Opt_prepend:
717
			err = opt_add(opt, args[0].from, sb, /*bindex*/0);
718
			if (!err)
719
				opt->type = token;
720
			break;
721
		case Opt_del:
722
			u.del = &opt->del;
723
			u.del->path = args[0].from;
724
			LKTRTrace("del path %s\n", u.del->path);
725
			/* LSM may detect it */
726
			/* do not superio. */
727
			err = vfsub_path_lookup(u.del->path, lkup_dirflags,
728
						&nd);
729
			if (unlikely(err)) {
730
				AuErr("lookup failed %s (%d)\n",
731
				      u.del->path, err);
732
				break;
733
			}
734
			u.del->h_root = dget(nd.path.dentry);
735
			path_put(&nd.path);
736
			opt->type = token;
737
			break;
738
		case Opt_mod:
739
			u.mod = &opt->mod;
740
			u.mod->path = args[0].from;
741
			p = strchr(u.mod->path, '=');
742
			if (unlikely(!p)) {
743
				AuErr("no permssion %s\n", opt_str);
744
				break;
745
			}
746
			*p++ = 0;
747
			u.mod->perm = br_perm_val(p);
748
			LKTRTrace("mod path %s, perm 0x%x, %s\n",
749
				  u.mod->path, u.mod->perm, p);
750
			/* LSM may detect it */
751
			/* do not superio. */
752
			err = vfsub_path_lookup(u.mod->path, lkup_dirflags,
753
						&nd);
754
			if (unlikely(err)) {
755
				AuErr("lookup failed %s (%d)\n",
756
				      u.mod->path, err);
757
				break;
758
			}
759
			u.mod->h_root = dget(nd.path.dentry);
760
			path_put(&nd.path);
761
			opt->type = token;
762
			break;
763
#ifdef IMOD
764
		case Opt_imod:
765
			u.mod = &opt->mod;
766
			u.mod->path = "(indexed)";
767
			if (unlikely(match_int(&args[0], &n))) {
768
				AuErr("bad integer in %s\n", opt_str);
769
				break;
770
			}
771
			bindex = n;
772
			aufs_read_lock(root, AuLock_FLUSH);
773
			if (bindex < 0 || au_sbend(sb) < bindex) {
774
				AuErr("out of bounds, %d\n", bindex);
775
				aufs_read_unlock(root, !AuLock_IR);
776
				break;
777
			}
778
			u.mod->perm = br_perm_val(args[1].from);
779
			LKTRTrace("mod path %s, perm 0x%x, %s\n",
780
				  u.mod->path, u.mod->perm, args[1].from);
781
			err = 0;
782
			u.mod->h_root = dget(au_h_dptr(root, bindex));
783
			opt->type = token;
784
			aufs_read_unlock(root, !AuLock_IR);
785
			break;
786
#endif
787
		case Opt_xino:
788
			u.xino = &opt->xino;
789
			file = au_xino_create(sb, args[0].from, /*silent*/0,
790
					      /*parent*/NULL);
791
			err = PTR_ERR(file);
792
			if (IS_ERR(file))
793
				break;
794
			err = -EINVAL;
795
			if (unlikely(file->f_dentry->d_sb == sb)) {
796
				fput(file);
797
				AuErr("%s must be outside\n", args[0].from);
798
				break;
799
			}
800
			err = 0;
801
			u.xino->file = file;
802
			u.xino->path = args[0].from;
803
			opt->type = token;
804
			break;
805
806
		case Opt_trunc_xino_path:
807
			u.xino_itrunc = &opt->xino_itrunc;
808
			p = args[0].from;
809
			LKTRTrace("trunc_xino path %s\n", p);
810
			/* LSM may detect it */
811
			/* do not superio. */
812
			err = vfsub_path_lookup(p, lkup_dirflags, &nd);
813
			if (unlikely(err)) {
814
				AuErr("lookup failed %s (%d)\n", p , err);
815
				break;
816
			}
817
			u.xino_itrunc->bindex = -1;
818
			aufs_read_lock(root, AuLock_FLUSH);
819
			bend = au_sbend(sb);
820
			for (bindex = 0; bindex <= bend; bindex++) {
821
				if (au_h_dptr(root, bindex) == nd.path.dentry) {
822
					u.xino_itrunc->bindex = bindex;
823
					break;
824
				}
825
			}
826
			aufs_read_unlock(root, !AuLock_IR);
827
			path_put(&nd.path);
828
			if (unlikely(u.xino_itrunc->bindex < 0)) {
829
				AuErr("no such branch %s\n", p);
830
				err = -EINVAL;
831
				break;
832
			}
833
			opt->type = token;
834
			break;
835
836
		case Opt_itrunc_xino:
837
			u.xino_itrunc = &opt->xino_itrunc;
838
			if (unlikely(match_int(&args[0], &n))) {
839
				AuErr("bad integer in %s\n", opt_str);
840
				break;
841
			}
842
			u.xino_itrunc->bindex = n;
843
			aufs_read_lock(root, AuLock_FLUSH);
844
			if (n < 0 || au_sbend(sb) < n) {
845
				AuErr("out of bounds, %d\n", n);
846
				aufs_read_unlock(root, !AuLock_IR);
847
				break;
848
			}
849
			aufs_read_unlock(root, !AuLock_IR);
850
			err = 0;
851
			opt->type = token;
852
			break;
853
854
		case Opt_dirwh:
855
			if (unlikely(match_int(&args[0], &opt->dirwh)))
856
				break;
857
			err = 0;
858
			opt->type = token;
859
			break;
860
861
		case Opt_rdcache:
862
			if (unlikely(match_int(&args[0], &opt->rdcache)))
863
				break;
864
			err = 0;
865
			opt->type = token;
866
			break;
867
868
		case Opt_shwh:
869
			if (flags & MS_RDONLY) {
870
				err = 0;
871
				opt->type = token;
872
			} else
873
				AuErr("shwh requires ro\n");
874
			break;
875
876
		case Opt_trunc_xino:
877
		case Opt_notrunc_xino:
878
		case Opt_noxino:
879
		case Opt_trunc_xib:
880
		case Opt_notrunc_xib:
881
		case Opt_dirperm1:
882
		case Opt_nodirperm1:
883
		case Opt_noshwh:
884
		case Opt_plink:
885
		case Opt_noplink:
886
		case Opt_list_plink:
887
		case Opt_clean_plink:
888
		case Opt_diropq_a:
889
		case Opt_diropq_w:
890
		case Opt_warn_perm:
891
		case Opt_nowarn_perm:
892
		case Opt_dlgt:
893
		case Opt_nodlgt:
894
		case Opt_refrof:
895
		case Opt_norefrof:
896
		case Opt_verbose:
897
		case Opt_noverbose:
898
			err = 0;
899
			opt->type = token;
900
			break;
901
902
		case Opt_udba:
903
			opt->udba = udba_val(args[0].from);
904
			if (opt->udba >= 0) {
905
				err = 0;
906
				opt->type = token;
907
			}
908
			break;
909
910
		case Opt_wbr_create:
911
			u.create = &opt->wbr_create;
912
			u.create->wbr_create
913
				= au_wbr_create_val(args[0].from, u.create);
914
			if (u.create->wbr_create >= 0) {
915
				err = 0;
916
				opt->type = token;
917
			}
918
			break;
919
		case Opt_wbr_copyup:
920
			opt->wbr_copyup = au_wbr_copyup_val(args[0].from);
921
			if (opt->wbr_copyup >= 0) {
922
				err = 0;
923
				opt->type = token;
924
			}
925
			break;
926
927
		case Opt_coo:
928
			opt->coo = coo_val(args[0].from);
929
			if (opt->coo >= 0) {
930
				err = 0;
931
				opt->type = token;
932
			}
933
			break;
934
935
		case Opt_ignore:
936
#ifndef CONFIG_AUFS_COMPAT
937
			AuWarn("ignored %s\n", opt_str);
938
#endif
939
		case Opt_ignore_silent:
940
			skipped = 1;
941
			err = 0;
942
			break;
943
		case Opt_err:
944
			AuErr("unknown option %s\n", opt_str);
945
			break;
946
		}
947
948
		if (!err && !skipped) {
949
			if (unlikely(++opt > opt_tail)) {
950
				err = -E2BIG;
951
				opt--;
952
				opt->type = Opt_tail;
953
				break;
954
			}
955
			opt->type = Opt_tail;
956
		}
957
	}
958
959
	dump_opts(opts);
960
	if (unlikely(err))
961
		au_opts_free(opts);
962
	AuTraceErr(err);
963
	return err;
964
}
965
966
/*
967
 * returns,
968
 * plus: processed without an error
969
 * zero: unprocessed
970
 */
971
static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
972
			 struct au_opts *opts)
973
{
974
	int err;
975
	struct au_sbinfo *sbinfo;
976
	struct au_opt_wbr_create *create;
977
978
	AuTraceEnter();
979
980
	err = 1; /* handled */
981
	sbinfo = au_sbi(sb);
982
	switch (opt->type) {
983
	case Opt_udba:
984
		sbinfo->si_mntflags &= ~AuOptMask_UDBA;
985
		sbinfo->si_mntflags |= opt->udba;
986
		opts->given_udba |= opt->udba;
987
		break;
988
989
	case Opt_plink:
990
		au_opt_set(sbinfo->si_mntflags, PLINK);
991
		break;
992
	case Opt_noplink:
993
		if (au_opt_test(sbinfo->si_mntflags, PLINK))
994
			au_plink_put(sb);
995
		au_opt_clr(sbinfo->si_mntflags, PLINK);
996
		break;
997
	case Opt_list_plink:
998
		if (au_opt_test(sbinfo->si_mntflags, PLINK))
999
			au_plink_list(sb);
1000
		break;
1001
	case Opt_clean_plink:
1002
		if (au_opt_test(sbinfo->si_mntflags, PLINK))
1003
			au_plink_put(sb);
1004
		break;
1005
1006
	case Opt_diropq_a:
1007
		au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1008
		break;
1009
	case Opt_diropq_w:
1010
		au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1011
		break;
1012
1013
	case Opt_dlgt:
1014
		au_opt_set(sbinfo->si_mntflags, DLGT);
1015
		break;
1016
	case Opt_nodlgt:
1017
		au_opt_clr(sbinfo->si_mntflags, DLGT);
1018
		break;
1019
1020
	case Opt_warn_perm:
1021
		au_opt_set(sbinfo->si_mntflags, WARN_PERM);
1022
		break;
1023
	case Opt_nowarn_perm:
1024
		au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
1025
		break;
1026
1027
	case Opt_refrof:
1028
		au_opt_set(sbinfo->si_mntflags, REFROF);
1029
		break;
1030
	case Opt_norefrof:
1031
		//au_opt_set(sbinfo->si_mntflags, COO_LEAF);
1032
		au_opt_clr(sbinfo->si_mntflags, REFROF);
1033
		break;
1034
1035
	case Opt_verbose:
1036
		au_opt_set(sbinfo->si_mntflags, VERBOSE);
1037
		break;
1038
	case Opt_noverbose:
1039
		au_opt_clr(sbinfo->si_mntflags, VERBOSE);
1040
		break;
1041
1042
	case Opt_wbr_create:
1043
		create = &opt->wbr_create;
1044
		if (sbinfo->si_wbr_create_ops->fin) {
1045
			err = sbinfo->si_wbr_create_ops->fin(sb);
1046
			if (!err)
1047
				err = 1;
1048
		}
1049
		sbinfo->si_wbr_create = create->wbr_create;
1050
		sbinfo->si_wbr_create_ops
1051
			= au_wbr_create_ops + create->wbr_create;
1052
		switch (create->wbr_create) {
1053
		case AuWbrCreate_MFSRRV:
1054
		case AuWbrCreate_MFSRR:
1055
			sbinfo->si_wbr_mfs.mfsrr_watermark
1056
				= create->mfsrr_watermark;
1057
			/*FALLTHROUGH*/
1058
		case AuWbrCreate_MFS:
1059
		case AuWbrCreate_MFSV:
1060
		case AuWbrCreate_PMFS:
1061
		case AuWbrCreate_PMFSV:
1062
			sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
1063
			break;
1064
		}
1065
		if (sbinfo->si_wbr_create_ops->init)
1066
			sbinfo->si_wbr_create_ops->init(sb); /* ignore */
1067
		break;
1068
	case Opt_wbr_copyup:
1069
		sbinfo->si_wbr_copyup = opt->wbr_copyup;
1070
		sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
1071
		break;
1072
1073
	case Opt_coo:
1074
		sbinfo->si_mntflags &= ~AuOptMask_COO;
1075
		sbinfo->si_mntflags |= opt->coo;
1076
		break;
1077
1078
	case Opt_dirwh:
1079
		sbinfo->si_dirwh = opt->dirwh;
1080
		break;
1081
1082
	case Opt_rdcache:
1083
		sbinfo->si_rdcache = opt->rdcache * HZ;
1084
		break;
1085
1086
	case Opt_trunc_xino:
1087
		au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
1088
		break;
1089
	case Opt_notrunc_xino:
1090
		au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
1091
		break;
1092
1093
	case Opt_dirperm1:
1094
		au_opt_set(sbinfo->si_mntflags, DIRPERM1);
1095
		break;
1096
	case Opt_nodirperm1:
1097
		au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
1098
		break;
1099
1100
	case Opt_shwh:
1101
		au_opt_set(sbinfo->si_mntflags, SHWH);
1102
		break;
1103
	case Opt_noshwh:
1104
		au_opt_clr(sbinfo->si_mntflags, SHWH);
1105
		break;
1106
1107
	case Opt_trunc_xino_path:
1108
	case Opt_itrunc_xino:
1109
		err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
1110
		if (!err)
1111
			err = 1;
1112
		break;
1113
1114
	case Opt_trunc_xib:
1115
		au_fset_opts(opts->flags, TRUNC_XIB);
1116
		break;
1117
	case Opt_notrunc_xib:
1118
		au_fclr_opts(opts->flags, TRUNC_XIB);
1119
		break;
1120
1121
	default:
1122
		err = 0;
1123
		break;
1124
	}
1125
1126
	AuTraceErr(err);
1127
	return err;
1128
}
1129
1130
/*
1131
 * returns tri-state.
1132
 * plus: processed without an error
1133
 * zero: unprocessed
1134
 * minus: error
1135
 */
1136
static int au_opt_br(struct super_block *sb, struct au_opt *opt,
1137
		     struct au_opts *opts)
1138
{
1139
	int err, do_refresh;
1140
1141
	AuTraceEnter();
1142
1143
	err = 0;
1144
	switch (opt->type) {
1145
	case Opt_append:
1146
		opt->add.bindex = au_sbend(sb) + 1;
1147
		if (unlikely(opt->add.bindex < 0))
1148
			opt->add.bindex = 0;
1149
		goto add;
1150
	case Opt_prepend:
1151
		opt->add.bindex = 0;
1152
	add:
1153
	case Opt_add:
1154
		err = au_br_add(sb, &opt->add,
1155
				au_ftest_opts(opts->flags, REMOUNT));
1156
		if (!err) {
1157
			err = 1;
1158
			au_fset_opts(opts->flags, REFRESH_DIR);
1159
			if (unlikely(au_br_whable(opt->add.perm)))
1160
				au_fset_opts(opts->flags, REFRESH_NONDIR);
1161
		}
1162
		break;
1163
1164
	case Opt_del:
1165
	case Opt_idel:
1166
		err = au_br_del(sb, &opt->del,
1167
				au_ftest_opts(opts->flags, REMOUNT));
1168
		if (!err) {
1169
			err = 1;
1170
			au_fset_opts(opts->flags, TRUNC_XIB);
1171
			au_fset_opts(opts->flags, REFRESH_DIR);
1172
			au_fset_opts(opts->flags, REFRESH_NONDIR);
1173
		}
1174
		break;
1175
1176
	case Opt_mod:
1177
	case Opt_imod:
1178
		err = au_br_mod(sb, &opt->mod,
1179
				au_ftest_opts(opts->flags, REMOUNT),
1180
				&do_refresh);
1181
		if (!err) {
1182
			err = 1;
1183
			if (unlikely(do_refresh)) {
1184
				au_fset_opts(opts->flags, REFRESH_DIR);
1185
				au_fset_opts(opts->flags, REFRESH_NONDIR);
1186
			}
1187
		}
1188
		break;
1189
	}
1190
1191
	AuTraceErr(err);
1192
	return err;
1193
}
1194
1195
static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
1196
		       struct au_opt_xino **opt_xino, struct au_opts *opts)
1197
{
1198
	int err;
1199
1200
	AuTraceEnter();
1201
1202
	err = 0;
1203
	switch (opt->type) {
1204
	case Opt_xino:
1205
		err = au_xino_set(sb, &opt->xino,
1206
				  au_ftest_opts(opts->flags, REMOUNT));
1207
		if (!err)
1208
			*opt_xino = &opt->xino;
1209
		break;
1210
	case Opt_noxino:
1211
		au_xino_clr(sb);
1212
		*opt_xino = (void *)-1;
1213
		break;
1214
	}
1215
1216
	AuTraceErr(err);
1217
	return err;
1218
}
1219
1220
static noinline_for_stack int
1221
verify_opts(struct super_block *sb, unsigned int pending, int remount)
1222
{
1223
	int err;
1224
	aufs_bindex_t bindex, bend;
1225
	struct au_branch *br;
1226
	struct dentry *root;
1227
	struct inode *dir;
1228
	unsigned int do_plink;
1229
	unsigned int mnt_flags;
1230
1231
	AuTraceEnter();
1232
	mnt_flags = au_mntflags(sb);
1233
	AuDebugOn(!(mnt_flags & AuOptMask_COO));
1234
	AuDebugOn(!(mnt_flags & AuOptMask_UDBA));
1235
1236
	if (!(sb->s_flags & MS_RDONLY)) {
1237
		if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
1238
			AuWarn("first branch should be rw\n");
1239
		if (unlikely(au_opt_test(mnt_flags, SHWH)))
1240
			AuWarn("shwh should be used with ro\n");
1241
	}
1242
1243
	if (unlikely(au_opt_test(mnt_flags | pending, UDBA_INOTIFY)
1244
		     && !au_opt_test(mnt_flags, XINO)))
1245
		AuWarn("udba=inotify requires xino\n");
1246
1247
	err = 0;
1248
	root = sb->s_root;
1249
	dir = sb->s_root->d_inode;
1250
	do_plink = !!au_opt_test(mnt_flags, PLINK);
1251
	bend = au_sbend(sb);
1252
	for (bindex = 0; !err && bindex <= bend; bindex++) {
1253
		struct inode *h_dir;
1254
		int skip;
1255
1256
		skip = 0;
1257
		h_dir = au_h_iptr(dir, bindex);
1258
		br = au_sbr(sb, bindex);
1259
		br_wh_read_lock(br);
1260
		switch (br->br_perm) {
1261
		case AuBr_RR:
1262
		case AuBr_RO:
1263
		case AuBr_RRWH:
1264
		case AuBr_ROWH:
1265
			skip = (!br->br_wh && !br->br_plink);
1266
			break;
1267
1268
		case AuBr_RWNoLinkWH:
1269
			skip = !br->br_wh;
1270
			if (skip) {
1271
				if (do_plink)
1272
					skip = !!br->br_plink;
1273
				else
1274
					skip = !br->br_plink;
1275
			}
1276
			break;
1277
1278
		case AuBr_RW:
1279
			skip = !!br->br_wh;
1280
			if (skip) {
1281
				if (do_plink)
1282
					skip = !!br->br_plink;
1283
				else
1284
					skip = !br->br_plink;
1285
			}
1286
			break;
1287
1288
		default:
1289
			BUG();
1290
		}
1291
		br_wh_read_unlock(br);
1292
1293
		if (skip)
1294
			continue;
1295
1296
		au_hdir_lock(h_dir, dir, bindex);
1297
		br_wh_write_lock(br);
1298
		err = au_wh_init(au_h_dptr(root, bindex), br,
1299
				 au_nfsmnt(sb, bindex), sb);
1300
		br_wh_write_unlock(br);
1301
		au_hdir_unlock(h_dir, dir, bindex);
1302
	}
1303
1304
	AuTraceErr(err);
1305
	return err;
1306
}
1307
1308
int au_opts_mount(struct super_block *sb, struct au_opts *opts)
1309
{
1310
	int err;
1311
	struct inode *dir;
1312
	struct au_opt *opt;
1313
	struct au_opt_xino *opt_xino;
1314
	aufs_bindex_t bend;
1315
	struct au_sbinfo *sbinfo;
1316
	unsigned int tmp;
1317
1318
	AuTraceEnter();
1319
	SiMustWriteLock(sb);
1320
	DiMustWriteLock(sb->s_root);
1321
	dir = sb->s_root->d_inode;
1322
	IiMustWriteLock(dir);
1323
1324
	err = 0;
1325
	opt_xino = NULL;
1326
	opt = opts->opt;
1327
	while (err >= 0 && opt->type != Opt_tail)
1328
		err = au_opt_simple(sb, opt++, opts);
1329
	if (err > 0)
1330
		err = 0;
1331
	else if (unlikely(err < 0))
1332
		goto out;
1333
1334
	/* disable xino, hinotify, dlgt temporary */
1335
	sbinfo = au_sbi(sb);
1336
	tmp = sbinfo->si_mntflags;
1337
	au_opt_clr(sbinfo->si_mntflags, XINO);
1338
	au_opt_clr(sbinfo->si_mntflags, DLGT);
1339
	au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
1340
1341
	opt = opts->opt;
1342
	while (err >= 0 && opt->type != Opt_tail)
1343
		err = au_opt_br(sb, opt++, opts);
1344
	if (err > 0)
1345
		err = 0;
1346
	else if (unlikely(err < 0))
1347
		goto out;
1348
1349
	bend = au_sbend(sb);
1350
	if (unlikely(bend < 0)) {
1351
		err = -EINVAL;
1352
		AuErr("no branches\n");
1353
		goto out;
1354
	}
1355
1356
	if (au_opt_test(tmp, XINO))
1357
		au_opt_set(sbinfo->si_mntflags, XINO);
1358
	opt = opts->opt;
1359
	while (!err && opt->type != Opt_tail)
1360
		err = au_opt_xino(sb, opt++, &opt_xino, opts);
1361
	if (unlikely(err))
1362
		goto out;
1363
1364
	//todo: test this error case.
1365
	err = verify_opts(sb, tmp, /*remount*/0);
1366
	if (unlikely(err))
1367
		goto out;
1368
1369
	/* enable xino */
1370
	if (au_opt_test(tmp, XINO) && !opt_xino) {
1371
		struct au_opt_xino xino;
1372
1373
		xino.file = au_xino_def(sb);
1374
		err = PTR_ERR(xino.file);
1375
		if (IS_ERR(xino.file))
1376
			goto out;
1377
1378
		err = au_xino_set(sb, &xino, /*remount*/0);
1379
		fput(xino.file);
1380
		if (unlikely(err))
1381
			goto out;
1382
	}
1383
1384
	/* restore hinotify */
1385
	sbinfo->si_mntflags &= ~AuOptMask_UDBA;
1386
	sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
1387
	if (au_opt_test(tmp, UDBA_INOTIFY))
1388
		au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AuHi_XINO);
1389
1390
	/* restore dlgt */
1391
	if (au_opt_test_dlgt(tmp))
1392
		au_opt_set(sbinfo->si_mntflags, DLGT);
1393
1394
 out:
1395
	AuTraceErr(err);
1396
	return err;
1397
}
1398
1399
int au_opts_remount(struct super_block *sb, struct au_opts *opts)
1400
{
1401
	int err, rerr;
1402
	struct inode *dir;
1403
	struct au_opt_xino *opt_xino;
1404
	struct au_opt *opt;
1405
	unsigned int dlgt;
1406
	struct au_sbinfo *sbinfo;
1407
1408
	AuTraceEnter();
1409
	SiMustWriteLock(sb);
1410
	DiMustWriteLock(sb->s_root);
1411
	dir = sb->s_root->d_inode;
1412
	IiMustWriteLock(dir);
1413
	sbinfo = au_sbi(sb);
1414
	//AuDebugOn(au_opt_test(sbifno->si_mntflags, UDBA_INOTIFY));
1415
1416
	err = 0;
1417
	dlgt = !!au_opt_test_dlgt(sbinfo->si_mntflags);
1418
	opt_xino = NULL;
1419
	opt = opts->opt;
1420
	while (err >= 0 && opt->type != Opt_tail) {
1421
		err = au_opt_simple(sb, opt, opts);
1422
1423
		/* disable it temporary */
1424
		dlgt = !!au_opt_test_dlgt(sbinfo->si_mntflags);
1425
		au_opt_clr(sbinfo->si_mntflags, DLGT);
1426
1427
		if (!err)
1428
			err = au_opt_br(sb, opt, opts);
1429
		if (!err)
1430
			err = au_opt_xino(sb, opt, &opt_xino, opts);
1431
1432
		/* restore it */
1433
		if (unlikely(dlgt))
1434
			au_opt_set(sbinfo->si_mntflags, DLGT);
1435
		opt++;
1436
	}
1437
	if (err > 0)
1438
		err = 0;
1439
	AuTraceErr(err);
1440
1441
	/* go on even err */
1442
1443
	//todo: test this error case.
1444
	au_opt_clr(sbinfo->si_mntflags, DLGT);
1445
	rerr = verify_opts(sb, sbinfo->si_mntflags, /*remount*/1);
1446
	if (unlikely(dlgt))
1447
		au_opt_set(sbinfo->si_mntflags, DLGT);
1448
	if (unlikely(rerr && !err))
1449
		err = rerr;
1450
1451
	if (unlikely(au_ftest_opts(opts->flags, TRUNC_XIB))) {
1452
		rerr = au_xib_trunc(sb);
1453
		if (unlikely(rerr && !err))
1454
			err = rerr;
1455
	}
1456
1457
	/* they are handled by the caller */
1458
	if (!au_ftest_opts(opts->flags, REFRESH_DIR)
1459
	    && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
1460
		au_fset_opts(opts->flags, REFRESH_DIR);
1461
1462
	LKTRTrace("status 0x%x\n", opts->flags);
1463
	AuTraceErr(err);
1464
	return err;
1465
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/opts.h (+245 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * mount options/flags
21
 *
22
 * $Id: opts.h,v 1.2 2008/04/21 01:46:26 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_OPTS_H__
26
#define __AUFS_OPTS_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/namei.h>
32
#include <linux/aufs_type.h>
33
#include "wkq.h"
34
35
/* ---------------------------------------------------------------------- */
36
/* mount flags */
37
38
/* external inode number bitmap and translation table */
39
#define AuOpt_XINO		1
40
#define AuOpt_TRUNC_XINO	(1 << 1)
41
#define AuOpt_LINO		(1 << 2)
42
#define AuOpt_UDBA_NONE		(1 << 3)	/* users direct branch access */
43
#define AuOpt_UDBA_REVAL	(1 << 4)
44
#define AuOpt_UDBA_INOTIFY	(1 << 5)
45
#define AuOpt_SHWH		(1 << 6)
46
#define AuOpt_PLINK		(1 << 7)
47
#define AuOpt_WARN_PERM		(1 << 8)
48
#define AuOpt_DIRPERM1		(1 << 9)
49
#define AuOpt_DLGT		(1 << 10)
50
#define AuOpt_COO_NONE		(1 << 11)	/* copyup on open */
51
#define AuOpt_COO_LEAF		(1 << 12)
52
#define AuOpt_COO_ALL		(1 << 13)
53
#define AuOpt_ALWAYS_DIROPQ	(1 << 14)
54
#define AuOpt_REFROF		(1 << 15)
55
#define AuOpt_VERBOSE		(1 << 16)
56
#ifndef CONFIG_AUFS_HINOTIFY
57
#undef AuOpt_UDBA_INOTIFY
58
#define AuOpt_UDBA_INOTIFY	0
59
#endif
60
#ifndef CONFIG_AUFS_SHWH
61
#undef AuOpt_SHWH
62
#define AuOpt_SHWH		0
63
#endif
64
#ifndef CONFIG_AUFS_DLGT
65
#undef AuOpt_DIRPERM1
66
#define AuOpt_DIRPERM1		0
67
#undef AuOpt_DLGT
68
#define AuOpt_DLGT		0
69
#endif
70
71
/* policies to select one among multiple writable branches */
72
enum {
73
	AuWbrCreate_TDP,	/* top down parent */
74
	AuWbrCreate_RR,		/* round robin */
75
	AuWbrCreate_MFS,	/* most free space */
76
	AuWbrCreate_MFSV,	/* mfs with seconds */
77
	AuWbrCreate_MFSRR,	/* mfs then rr */
78
	AuWbrCreate_MFSRRV,	/* mfs then rr with seconds */
79
	AuWbrCreate_PMFS,	/* parent and mfs */
80
	AuWbrCreate_PMFSV,	/* parent and mfs with seconds */
81
82
	AuWbrCreate_Def = AuWbrCreate_TDP
83
};
84
85
enum {
86
	AuWbrCopyup_TDP,	/* top down parent */
87
	AuWbrCopyup_BUP,	/* bottom up parent */
88
	AuWbrCopyup_BU,		/* bottom up */
89
90
	AuWbrCopyup_Def = AuWbrCopyup_TDP
91
};
92
93
#define AuOptMask_COO		(AuOpt_COO_NONE \
94
				 | AuOpt_COO_LEAF \
95
				 | AuOpt_COO_ALL)
96
#define AuOptMask_UDBA		(AuOpt_UDBA_NONE \
97
				 | AuOpt_UDBA_REVAL \
98
				 | AuOpt_UDBA_INOTIFY)
99
100
#ifdef CONFIG_AUFS_COMPAT
101
#define AuOpt_DefExtra1	AuOpt_ALWAYS_DIROPQ
102
#else
103
#define AuOpt_DefExtra1	0
104
#endif
105
106
#define AuOpt_Def	(AuOpt_XINO \
107
			 | AuOpt_UDBA_REVAL \
108
			 | AuOpt_WARN_PERM \
109
			 | AuOpt_COO_NONE \
110
			 | AuOpt_PLINK \
111
			 | AuOpt_DefExtra1)
112
113
/* ---------------------------------------------------------------------- */
114
115
struct au_opt_add {
116
	aufs_bindex_t		bindex;
117
	char			*path;
118
	int			perm;
119
	struct nameidata	nd;
120
};
121
122
struct au_opt_del {
123
	char		*path;
124
	struct dentry	*h_root;
125
};
126
127
struct au_opt_mod {
128
	char		*path;
129
	int		perm;
130
	struct dentry	*h_root;
131
};
132
133
struct au_opt_xino {
134
	char		*path;
135
	struct file	*file;
136
};
137
138
struct au_opt_xino_itrunc {
139
	aufs_bindex_t	bindex;
140
};
141
142
struct au_opt_xino_trunc_v {
143
	u64		upper;
144
	int		step;
145
};
146
147
struct au_opt_wbr_create {
148
	int wbr_create;
149
	int mfs_second;
150
	u64 mfsrr_watermark;
151
};
152
153
struct au_opt {
154
	int type;
155
	union {
156
		struct au_opt_xino	xino;
157
		struct au_opt_xino_itrunc xino_itrunc;
158
		struct au_opt_add	add;
159
		struct au_opt_del	del;
160
		struct au_opt_mod	mod;
161
		int			dirwh;
162
		int			rdcache;
163
		int			deblk;
164
		int			nhash;
165
		int			udba;
166
		int			coo;
167
		struct au_opt_wbr_create wbr_create;
168
		int			wbr_copyup;
169
	};
170
};
171
172
/* opts flags */
173
#define AuOpts_REMOUNT		1
174
#define AuOpts_REFRESH_DIR	(1 << 1)
175
#define AuOpts_REFRESH_NONDIR	(1 << 2)
176
#define AuOpts_TRUNC_XIB	(1 << 3)
177
#define au_ftest_opts(flags, name)	((flags) & AuOpts_##name)
178
#define au_fset_opts(flags, name)	{ (flags) |= AuOpts_##name; }
179
#define au_fclr_opts(flags, name)	{ (flags) &= ~AuOpts_##name; }
180
181
struct au_opts {
182
	struct au_opt	*opt;
183
	int		max_opt;
184
185
	unsigned int	given_udba;
186
	unsigned int	flags;
187
};
188
189
/* ---------------------------------------------------------------------- */
190
191
const char *au_optstr_br_perm(int brperm);
192
const char *au_optstr_udba(int udba);
193
const char *au_optstr_coo(int coo);
194
const char *au_optstr_wbr_copyup(int wbr_copyup);
195
const char *au_optstr_wbr_create(int wbr_create);
196
197
void au_opts_free(struct au_opts *opts);
198
int au_opts_parse(struct super_block *sb, unsigned long flags, char *str,
199
		  struct au_opts *opts);
200
int au_opts_mount(struct super_block *sb, struct au_opts *opts);
201
int au_opts_remount(struct super_block *sb, struct au_opts *opts);
202
203
/* ---------------------------------------------------------------------- */
204
205
static inline unsigned int au_opt_do_test(unsigned int flags, unsigned int bit)
206
{
207
	AuDebugOn(bit & (AuOpt_DLGT | AuOpt_DIRPERM1));
208
	return (flags & bit);
209
}
210
211
#define au_opt_test(flags, name)	au_opt_do_test(flags, AuOpt_##name)
212
213
#define au_opt_set(flags, name) do { \
214
	BUILD_BUG_ON(AuOpt_##name & (AuOptMask_COO | AuOptMask_UDBA)); \
215
	((flags) |= AuOpt_##name); \
216
} while (0)
217
218
#define au_opt_clr(flags, name)		{ ((flags) &= ~AuOpt_##name); }
219
220
#define au_opt_set_coo(flags, name) do { \
221
	(flags) &= ~AuOptMask_COO; \
222
	((flags) |= AuOpt_##name); \
223
} while(0)
224
225
#define au_opt_set_udba(flags, name) do { \
226
	(flags) &= ~AuOptMask_UDBA; \
227
	((flags) |= AuOpt_##name); \
228
} while(0)
229
230
static inline unsigned int au_opt_test_dlgt(unsigned int flags)
231
{
232
	if (!au_test_wkq(current))
233
		return (flags & AuOpt_DLGT);
234
	return 0;
235
}
236
237
static inline unsigned int au_opt_test_dirperm1(unsigned int flags)
238
{
239
	if (!au_test_wkq(current))
240
		return (flags & AuOpt_DIRPERM1);
241
	return 0;
242
}
243
244
#endif /* __KERNEL__ */
245
#endif /* __AUFS_OPTS_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/plink.c (+345 lines)
Line 0 Link Here
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
 * pseudo-link
21
 *
22
 * $Id: plink.c,v 1.2 2008/04/21 01:45:16 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
struct pseudo_link {
28
	struct list_head list;
29
	struct inode *inode;
30
};
31
32
#ifdef CONFIG_AUFS_DEBUG
33
void au_plink_list(struct super_block *sb)
34
{
35
	struct au_sbinfo *sbinfo;
36
	struct list_head *plink_list;
37
	struct pseudo_link *plink;
38
39
	AuTraceEnter();
40
	SiMustAnyLock(sb);
41
	sbinfo = au_sbi(sb);
42
	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
43
44
	plink_list = &sbinfo->si_plink;
45
	spin_lock(&sbinfo->si_plink_lock);
46
	list_for_each_entry(plink, plink_list, list)
47
		AuDbg("%lu\n", plink->inode->i_ino);
48
	spin_unlock(&sbinfo->si_plink_lock);
49
}
50
#endif
51
52
int au_plink_test(struct super_block *sb, struct inode *inode)
53
{
54
	int found;
55
	struct au_sbinfo *sbinfo;
56
	struct list_head *plink_list;
57
	struct pseudo_link *plink;
58
59
	LKTRTrace("i%lu\n", inode->i_ino);
60
	SiMustAnyLock(sb);
61
	sbinfo = au_sbi(sb);
62
	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
63
64
	found = 0;
65
	plink_list = &sbinfo->si_plink;
66
	spin_lock(&sbinfo->si_plink_lock);
67
	list_for_each_entry(plink, plink_list, list)
68
		if (plink->inode == inode) {
69
			found = 1;
70
			break;
71
		}
72
	spin_unlock(&sbinfo->si_plink_lock);
73
	return found;
74
}
75
76
/* 20 is max digits length of ulong 64 */
77
#define PLINK_NAME_LEN	((20 + 1) * 2)
78
79
static int plink_name(char *name, int len, struct inode *inode,
80
		      aufs_bindex_t bindex)
81
{
82
	int rlen;
83
	struct inode *h_inode;
84
85
	LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex);
86
	AuDebugOn(len != PLINK_NAME_LEN);
87
	h_inode = au_h_iptr(inode, bindex);
88
	AuDebugOn(!h_inode);
89
	rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
90
	AuDebugOn(rlen >= len);
91
	return rlen;
92
}
93
94
struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex,
95
			     struct inode *inode)
96
{
97
	struct dentry *h_dentry, *h_parent;
98
	struct au_branch *br;
99
	struct inode *h_dir;
100
	char tgtname[PLINK_NAME_LEN];
101
	int len;
102
	struct au_ndx ndx = {
103
		.flags	= 0,
104
		.nd	= NULL,
105
		//.br	= NULL
106
	};
107
108
	LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino);
109
	br = au_sbr(sb, bindex);
110
	h_parent = br->br_plink;
111
	AuDebugOn(!h_parent);
112
	h_dir = h_parent->d_inode;
113
	AuDebugOn(!h_dir);
114
115
	len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
116
117
	/* always superio. */
118
	ndx.nfsmnt = au_do_nfsmnt(br->br_mnt);
119
	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
120
	h_dentry = au_sio_lkup_one(tgtname, h_parent, len, &ndx);
121
	mutex_unlock(&h_dir->i_mutex);
122
	return h_dentry;
123
}
124
125
static int do_whplink(char *tgt, int len, struct dentry *h_parent,
126
		      struct dentry *h_dentry, struct vfsmount *nfsmnt,
127
		      struct super_block *sb)
128
{
129
	int err, dlgt;
130
	struct dentry *h_tgt;
131
	struct inode *h_dir;
132
	struct vfsub_args vargs;
133
	struct au_ndx ndx = {
134
		.nfsmnt	= nfsmnt,
135
		.flags	= 0,
136
		.nd	= NULL,
137
		//.br	= NULL
138
	};
139
140
	dlgt = !!au_opt_test_dlgt(au_mntflags(sb));
141
	if (unlikely(dlgt))
142
		au_fset_ndx(ndx.flags, DLGT);
143
	h_tgt = au_lkup_one(tgt, h_parent, len, &ndx);
144
	err = PTR_ERR(h_tgt);
145
	if (IS_ERR(h_tgt))
146
		goto out;
147
148
	err = 0;
149
	vfsub_args_init(&vargs, NULL, dlgt, 0);
150
	h_dir = h_parent->d_inode;
151
	if (unlikely(h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode))
152
		err = vfsub_unlink(h_dir, h_tgt, &vargs);
153
	if (!err && !h_tgt->d_inode) {
154
		err = vfsub_link(h_dentry, h_dir, h_tgt, dlgt);
155
		//inode->i_nlink++;
156
	}
157
	dput(h_tgt);
158
159
 out:
160
	AuTraceErr(err);
161
	return err;
162
}
163
164
struct do_whplink_args {
165
	int *errp;
166
	char *tgt;
167
	int len;
168
	struct dentry *h_parent;
169
	struct dentry *h_dentry;
170
	struct vfsmount *nfsmnt;
171
	struct super_block *sb;
172
};
173
174
static void call_do_whplink(void *args)
175
{
176
	struct do_whplink_args *a = args;
177
	*a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry,
178
			      a->nfsmnt, a->sb);
179
}
180
181
static int whplink(struct dentry *h_dentry, struct inode *inode,
182
		   aufs_bindex_t bindex, struct super_block *sb)
183
{
184
	int err, len, wkq_err;
185
	struct au_branch *br;
186
	struct dentry *h_parent;
187
	struct inode *h_dir;
188
	char tgtname[PLINK_NAME_LEN];
189
190
	LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
191
	br = au_sbr(inode->i_sb, bindex);
192
	h_parent = br->br_plink;
193
	AuDebugOn(!h_parent);
194
	h_dir = h_parent->d_inode;
195
	AuDebugOn(!h_dir);
196
197
	len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
198
199
	/* always superio. */
200
	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
201
	if (!au_test_wkq(current)) {
202
		struct do_whplink_args args = {
203
			.errp		= &err,
204
			.tgt		= tgtname,
205
			.len		= len,
206
			.h_parent	= h_parent,
207
			.h_dentry	= h_dentry,
208
			.nfsmnt		= au_do_nfsmnt(br->br_mnt),
209
			.sb		= sb
210
		};
211
		wkq_err = au_wkq_wait(call_do_whplink, &args, /*dlgt*/0);
212
		if (unlikely(wkq_err))
213
			err = wkq_err;
214
	} else
215
		err = do_whplink(tgtname, len, h_parent, h_dentry,
216
				 au_do_nfsmnt(br->br_mnt), sb);
217
	mutex_unlock(&h_dir->i_mutex);
218
219
	AuTraceErr(err);
220
	return err;
221
}
222
223
void au_plink_append(struct super_block *sb, struct inode *inode,
224
		     struct dentry *h_dentry, aufs_bindex_t bindex)
225
{
226
	struct au_sbinfo *sbinfo;
227
	struct list_head *plink_list;
228
	struct pseudo_link *plink;
229
	int found, err, cnt;
230
231
	LKTRTrace("i%lu\n", inode->i_ino);
232
	SiMustAnyLock(sb);
233
	sbinfo = au_sbi(sb);
234
	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
235
236
	cnt = 0;
237
	found = 0;
238
	plink_list = &sbinfo->si_plink;
239
	spin_lock(&sbinfo->si_plink_lock);
240
	list_for_each_entry(plink, plink_list, list) {
241
		cnt++;
242
		if (plink->inode == inode) {
243
			found = 1;
244
			break;
245
		}
246
	}
247
248
	err = 0;
249
	if (!found) {
250
		plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
251
		if (plink) {
252
			plink->inode = igrab(inode);
253
			list_add(&plink->list, plink_list);
254
			cnt++;
255
		} else
256
			err = -ENOMEM;
257
	}
258
	spin_unlock(&sbinfo->si_plink_lock);
259
260
	if (!err)
261
		err = whplink(h_dentry, inode, bindex, sb);
262
263
	if (unlikely(cnt > AUFS_PLINK_WARN))
264
		AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
265
	if (unlikely(err))
266
		AuWarn("err %d, damaged pseudo link. ignored.\n", err);
267
}
268
269
static void do_put_plink(struct pseudo_link *plink, int do_del)
270
{
271
	AuTraceEnter();
272
273
	iput(plink->inode);
274
	if (do_del)
275
		list_del(&plink->list);
276
	kfree(plink);
277
}
278
279
void au_plink_put(struct super_block *sb)
280
{
281
	struct au_sbinfo *sbinfo;
282
	struct list_head *plink_list;
283
	struct pseudo_link *plink, *tmp;
284
285
	AuTraceEnter();
286
	SiMustWriteLock(sb);
287
	sbinfo = au_sbi(sb);
288
	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
289
290
	plink_list = &sbinfo->si_plink;
291
	//spin_lock(&sbinfo->si_plink_lock);
292
	list_for_each_entry_safe(plink, tmp, plink_list, list)
293
		do_put_plink(plink, 0);
294
	INIT_LIST_HEAD(plink_list);
295
	//spin_unlock(&sbinfo->si_plink_lock);
296
}
297
298
void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
299
{
300
	struct au_sbinfo *sbinfo;
301
	struct list_head *plink_list;
302
	struct pseudo_link *plink, *tmp;
303
	struct inode *inode;
304
	aufs_bindex_t bstart, bend, bindex;
305
	int do_put;
306
307
	AuTraceEnter();
308
	SiMustWriteLock(sb);
309
	sbinfo = au_sbi(sb);
310
	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
311
312
	plink_list = &sbinfo->si_plink;
313
	//spin_lock(&sbinfo->si_plink_lock);
314
	list_for_each_entry_safe(plink, tmp, plink_list, list) {
315
		do_put = 0;
316
		inode = igrab(plink->inode);
317
		ii_write_lock_child(inode);
318
		bstart = au_ibstart(inode);
319
		bend = au_ibend(inode);
320
		if (bstart >= 0) {
321
			for (bindex = bstart; bindex <= bend; bindex++) {
322
				if (!au_h_iptr(inode, bindex)
323
				    || au_ii_br_id(inode, bindex) != br_id)
324
					continue;
325
				au_set_h_iptr(inode, bindex, NULL, 0);
326
				do_put = 1;
327
				break;
328
			}
329
		} else
330
			do_put_plink(plink, 1);
331
332
		if (do_put) {
333
			for (bindex = bstart; bindex <= bend; bindex++)
334
				if (au_h_iptr(inode, bindex)) {
335
					do_put = 0;
336
					break;
337
				}
338
			if (do_put)
339
				do_put_plink(plink, 1);
340
		}
341
		ii_write_unlock(inode);
342
		iput(inode);
343
	}
344
	//spin_unlock(&sbinfo->si_plink_lock);
345
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/robr.c (+111 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 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
 * 'robr', aufs as readonly branch of another aufs
21
 *
22
 * $Id: robr.c,v 1.3 2008/05/19 01:48:04 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
/* ---------------------------------------------------------------------- */
28
29
int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
30
		    struct qstr *wh_name, int try_sio, struct au_ndx *ndx)
31
{
32
	if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
33
		return au_wh_test(h_parent, wh_name, try_sio, ndx);
34
	return -EPERM;
35
}
36
37
int au_test_robr_shwh(struct super_block *sb, const struct qstr *name)
38
{
39
	return 0;
40
}
41
42
/* ---------------------------------------------------------------------- */
43
44
struct au_robr_lvma {
45
	struct list_head list;
46
	struct vm_area_struct *vma;
47
};
48
49
struct file *au_robr_safe_file(struct vm_area_struct *vma)
50
{
51
	struct file *file = vma->vm_file;
52
	struct super_block *sb = file->f_dentry->d_sb;
53
	struct au_robr_lvma *lvma, *entry;
54
	struct au_sbinfo *sbinfo;
55
	int found, warn;
56
57
	AuTraceEnter();
58
	AuDebugOn(!au_test_aufs(sb));
59
60
	warn = 0;
61
	found = 0;
62
	sbinfo = au_sbi(sb);
63
	spin_lock(&sbinfo->si_lvma_lock);
64
	list_for_each_entry(entry, &sbinfo->si_lvma, list) {
65
		found = (entry->vma == vma);
66
		if (unlikely(found))
67
			break;
68
	}
69
	if (!found) {
70
		lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC);
71
		if (lvma) {
72
			lvma->vma = vma;
73
			list_add(&lvma->list, &sbinfo->si_lvma);
74
		} else {
75
			warn = 1;
76
			file = NULL;
77
		}
78
	} else
79
		file = NULL;
80
	spin_unlock(&sbinfo->si_lvma_lock);
81
82
	if (unlikely(warn))
83
		AuWarn1("no memory for lvma\n");
84
	return file;
85
}
86
87
void au_robr_reset_file(struct vm_area_struct *vma, struct file *file)
88
{
89
	struct super_block *sb = file->f_dentry->d_sb;
90
	struct au_robr_lvma *entry, *found;
91
	struct au_sbinfo *sbinfo;
92
93
	AuTraceEnter();
94
	AuDebugOn(!au_test_aufs(sb));
95
96
	vma->vm_file = file;
97
	//smp_mb(); /* flush vm_file */
98
99
	found = NULL;
100
	sbinfo = au_sbi(sb);
101
	spin_lock(&sbinfo->si_lvma_lock);
102
	list_for_each_entry(entry, &sbinfo->si_lvma, list)
103
		if (entry->vma == vma) {
104
			found = entry;
105
			break;
106
		}
107
	AuDebugOn(!found);
108
	list_del(&found->list);
109
	spin_unlock(&sbinfo->si_lvma_lock);
110
	kfree(found);
111
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/sbinfo.c (+268 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * superblock private data
21
 *
22
 * $Id: sbinfo.c,v 1.5 2008/05/19 01:49:56 sfjro Exp $
23
 */
24
25
#include <linux/mnt_namespace.h>
26
#include <linux/smp_lock.h>
27
#include "aufs.h"
28
29
/*
30
 * they are necessary regardless sysfs is disabled.
31
 */
32
void au_si_free(struct kobject *kobj)
33
{
34
	struct au_sbinfo *sbinfo;
35
	struct super_block *sb;
36
37
	LKTRTrace("kobj %p\n", kobj);
38
	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
39
	LKTRTrace("sbinfo %p\n", sbinfo);
40
	AuDebugOn(!list_empty(&sbinfo->si_plink));
41
42
	sb = sbinfo->si_sb;
43
	if (unlikely(!au_ftest_si(sbinfo, FAILED_INIT))) {
44
		au_sbilist_lock();
45
		au_sbilist_del(sbinfo);
46
		au_sbilist_unlock();
47
	}
48
49
	si_write_lock(sb);
50
	au_xino_clr(sb);
51
	au_br_free(sbinfo);
52
	kfree(sbinfo->si_branch);
53
	si_write_unlock(sb);
54
55
	//AuDbg("free\n");
56
 	kfree(sbinfo);
57
}
58
59
int au_si_alloc(struct super_block *sb)
60
{
61
	int err;
62
	struct au_sbinfo *sbinfo;
63
64
	AuTraceEnter();
65
66
	err = -ENOMEM;
67
	sbinfo = kmalloc(sizeof(*sbinfo), GFP_KERNEL);
68
	//if (LktrCond) {kfree(sbinfo); sbinfo = NULL;}
69
	if (unlikely(!sbinfo))
70
		goto out;
71
	sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_KERNEL);
72
	//if (LktrCond) {kfree(sbinfo->si_branch); sbinfo->si_branch = NULL;}
73
	if (unlikely(!sbinfo->si_branch))
74
		goto out_sbinfo;
75
76
	memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
77
	err = sysaufs_si_init(sbinfo);
78
	if (unlikely(err))
79
		goto out_br;
80
81
	au_rw_init_wlock(&sbinfo->si_rwsem);
82
	sbinfo->si_generation = 0;
83
	//sbinfo->si_generation = INT_MAX - 2;
84
	sbinfo->au_si_status = 0;
85
	sbinfo->si_bend = -1;
86
	sbinfo->si_last_br_id = 0;
87
88
	sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
89
	sbinfo->si_wbr_create = AuWbrCreate_Def;
90
	sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
91
	sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
92
93
	sbinfo->si_mntflags = AuOpt_Def;
94
95
	sbinfo->si_xread = NULL;
96
	sbinfo->si_xwrite = NULL;
97
	sbinfo->si_xib = NULL;
98
	mutex_init(&sbinfo->si_xib_mtx);
99
	sbinfo->si_xib_buf = NULL;
100
	/* leave si_xib_last_pindex and si_xib_next_bit */
101
102
	au_nwt_init(&sbinfo->si_nowait);
103
104
	sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
105
	sbinfo->si_dirwh = AUFS_DIRWH_DEF;
106
107
	spin_lock_init(&sbinfo->si_plink_lock);
108
	INIT_LIST_HEAD(&sbinfo->si_plink);
109
110
	au_robr_lvma_init(sbinfo);
111
112
	/* leave other members for sysaufs and si_mnt. */
113
	sbinfo->si_sb = sb;
114
115
	sb->s_fs_info = sbinfo;
116
	//sysaufs_si_get(sb);
117
118
	au_debug_sbinfo_init(sbinfo);
119
	return 0; /* success */
120
121
 out_br:
122
	kfree(sbinfo->si_branch);
123
 out_sbinfo:
124
	kfree(sbinfo);
125
 out:
126
	AuTraceErr(err);
127
	return err;
128
}
129
130
/* ---------------------------------------------------------------------- */
131
132
struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex)
133
{
134
	struct au_branch *br;
135
136
	SiMustAnyLock(sb);
137
	AuDebugOn(bindex < 0 || au_sbend(sb) < bindex);
138
	br = au_sbi(sb)->si_branch[0 + bindex];
139
	AuDebugOn(!br);
140
	return br;
141
}
142
143
au_gen_t au_sigen_inc(struct super_block *sb)
144
{
145
	au_gen_t gen;
146
147
	SiMustWriteLock(sb);
148
	gen = ++au_sbi(sb)->si_generation;
149
	au_update_digen(sb->s_root);
150
	au_update_iigen(sb->s_root->d_inode);
151
	sb->s_root->d_inode->i_version++;
152
	return gen;
153
}
154
155
int au_find_bindex(struct super_block *sb, struct au_branch *br)
156
{
157
	aufs_bindex_t bindex, bend;
158
159
	bend = au_sbend(sb);
160
	for (bindex = 0; bindex <= bend; bindex++)
161
		if (au_sbr(sb, bindex) == br)
162
			return bindex;
163
	return -1;
164
}
165
166
/* ---------------------------------------------------------------------- */
167
168
/* dentry and super_block lock. call at entry point */
169
void aufs_read_lock(struct dentry *dentry, int flags)
170
{
171
	si_read_lock(dentry->d_sb, flags);
172
	if (au_ftest_lock(flags, DW))
173
		di_write_lock_child(dentry);
174
	else
175
		di_read_lock_child(dentry, flags);
176
}
177
178
void aufs_read_unlock(struct dentry *dentry, int flags)
179
{
180
	if (au_ftest_lock(flags, DW))
181
		di_write_unlock(dentry);
182
	else
183
		di_read_unlock(dentry, flags);
184
	si_read_unlock(dentry->d_sb);
185
}
186
187
void aufs_write_lock(struct dentry *dentry)
188
{
189
	si_write_lock(dentry->d_sb);
190
	di_write_lock_child(dentry);
191
}
192
193
void aufs_write_unlock(struct dentry *dentry)
194
{
195
	di_write_unlock(dentry);
196
	si_write_unlock(dentry->d_sb);
197
}
198
199
void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
200
{
201
	AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb);
202
	si_read_lock(d1->d_sb, flags);
203
	di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
204
}
205
206
void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
207
{
208
	AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb);
209
	di_write_unlock2(d1, d2);
210
	si_read_unlock(d1->d_sb);
211
}
212
213
/* ---------------------------------------------------------------------- */
214
215
aufs_bindex_t au_new_br_id(struct super_block *sb)
216
{
217
	aufs_bindex_t br_id;
218
	struct au_sbinfo *sbinfo;
219
220
	AuTraceEnter();
221
	SiMustWriteLock(sb);
222
223
	sbinfo = au_sbi(sb);
224
	while (1) {
225
		br_id = ++sbinfo->si_last_br_id;
226
		if (br_id && au_br_index(sb, br_id) < 0)
227
			return br_id;
228
	}
229
}
230
231
//todo: dirty
232
/*
233
 * when you mntput() for the return value of this function,
234
 * you have to store it to your local var.
235
 * ie. never mntput si_mntcache directly.
236
 */
237
struct vfsmount *au_mntcache_get(struct super_block *sb)
238
{
239
	struct au_sbinfo *sbinfo;
240
	struct mnt_namespace *ns;
241
	struct vfsmount *pos, *mnt;
242
243
	AuTraceEnter();
244
245
	sbinfo = au_sbi(sb);
246
247
	spin_lock(&sbinfo->si_mntcache_lock);
248
	if (sbinfo->si_mntcache)
249
		goto out;
250
251
	/* vfsmount_lock is not exported */
252
	//root_mnt = current->fs->root.mnt;
253
	/* no get/put */
254
	AuDebugOn(!current->nsproxy);
255
	ns = current->nsproxy->mnt_ns;
256
	AuDebugOn(!ns);
257
	list_for_each_entry(pos, &ns->list, mnt_list)
258
		if (pos->mnt_sb == sb) {
259
			sbinfo->si_mntcache = pos;
260
			break;
261
		}
262
	AuDebugOn(!sbinfo->si_mntcache);
263
264
 out:
265
	mnt = mntget(sbinfo->si_mntcache);
266
	spin_unlock(&sbinfo->si_mntcache_lock);
267
	return mnt;
268
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/super.c (+877 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * mount and super_block operations
21
 *
22
 * $Id: super.c,v 1.6 2008/05/19 01:50:10 sfjro Exp $
23
 */
24
25
#include <linux/module.h>
26
#include <linux/buffer_head.h>
27
#include <linux/seq_file.h>
28
#include <linux/smp_lock.h>
29
#include <linux/statfs.h>
30
31
#include "aufs.h"
32
33
/*
34
 * super_operations
35
 */
36
static struct inode *aufs_alloc_inode(struct super_block *sb)
37
{
38
	struct aufs_icntnr *c;
39
40
	AuTraceEnter();
41
42
	c = au_cache_alloc_icntnr();
43
	//if (LktrCond) {au_cache_free_icntnr(c); c = NULL;}
44
	if (c) {
45
		inode_init_once(&c->vfs_inode);
46
		c->vfs_inode.i_version = 1; //sigen(sb);
47
		c->iinfo.ii_hinode = NULL;
48
		return &c->vfs_inode;
49
	}
50
	return NULL;
51
}
52
53
static void aufs_destroy_inode(struct inode *inode)
54
{
55
	LKTRTrace("i%lu\n", inode->i_ino);
56
	au_iinfo_fin(inode);
57
	au_cache_free_icntnr(container_of(inode, struct aufs_icntnr,
58
					  vfs_inode));
59
}
60
61
struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
62
{
63
	struct inode *inode;
64
	int err;
65
66
	LKTRTrace("i%lu\n", ino);
67
68
	inode = iget_locked(sb, ino);
69
	if (unlikely(!inode)) {
70
		inode = ERR_PTR(-ENOMEM);
71
		goto out;
72
	}
73
	AuDebugOn(IS_ERR(inode));
74
	if (unlikely(!(inode->i_state & I_NEW)))
75
		goto out;
76
77
	err = au_iinfo_init(inode);
78
	//if (LktrCond) err = -1;
79
	if (!err) {
80
		inode->i_version++;
81
		inode->i_op = &aufs_iop;
82
		inode->i_fop = &aufs_file_fop;
83
		inode->i_mapping->a_ops = &aufs_aop;
84
		//inode->i_mapping->backing_dev_info = &bdi;
85
	} else {
86
		iget_failed(inode);
87
		inode = ERR_PTR(err);
88
	}
89
90
 out:
91
	/* never return NULL */
92
	AuDebugOn(!inode);
93
	AuTraceErrPtr(inode);
94
	return inode;
95
}
96
97
static int au_show_brs(struct seq_file *seq, struct super_block *sb)
98
{
99
	int err;
100
	aufs_bindex_t bindex, bend;
101
	struct dentry *root;
102
	struct path path;
103
104
	AuTraceEnter();
105
106
	err = 0;
107
	root = sb->s_root;
108
	bend = au_sbend(sb);
109
	for (bindex = 0; !err && bindex <= bend; bindex++) {
110
		path.mnt = au_sbr_mnt(sb, bindex);
111
		path.dentry = au_h_dptr(root, bindex);
112
		err = seq_path(seq, &path, au_esc_chars);
113
		if (err > 0)
114
			err = seq_printf
115
				(seq, "=%s",
116
				 au_optstr_br_perm(au_sbr_perm(sb, bindex)));
117
		if (!err && bindex != bend)
118
			err = seq_putc(seq, ':');
119
	}
120
121
	AuTraceErr(err);
122
	return err;
123
}
124
125
static void au_show_wbr_create(struct seq_file *m, int v,
126
			       struct au_sbinfo *sbinfo)
127
{
128
	const char *pat;
129
130
	AuDebugOn(v == AuWbrCreate_Def);
131
132
	seq_printf(m, ",create=");
133
	pat = au_optstr_wbr_create(v);
134
	switch (v) {
135
	case AuWbrCreate_TDP:
136
	case AuWbrCreate_RR:
137
	case AuWbrCreate_MFS:
138
	case AuWbrCreate_PMFS:
139
		seq_printf(m, pat);
140
		break;
141
	case AuWbrCreate_MFSV:
142
		seq_printf(m, /*pat*/"mfs:%lu",
143
			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
144
		break;
145
	case AuWbrCreate_PMFSV:
146
		seq_printf(m, /*pat*/"pmfs:%lu",
147
			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
148
		break;
149
	case AuWbrCreate_MFSRR:
150
		seq_printf(m, /*pat*/"mfsrr:%Lu",
151
			   sbinfo->si_wbr_mfs.mfsrr_watermark);
152
		break;
153
	case AuWbrCreate_MFSRRV:
154
		seq_printf(m, /*pat*/"mfsrr:%Lu:%lu",
155
			   sbinfo->si_wbr_mfs.mfsrr_watermark,
156
			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
157
		break;
158
	}
159
}
160
161
/* seq_file will re-call me in case of too long string */
162
static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
163
{
164
	int err, n;
165
	struct super_block *sb;
166
	struct au_sbinfo *sbinfo;
167
	struct dentry *root;
168
	struct file *xino;
169
	unsigned int mnt_flags, v;
170
	struct path path;
171
172
	//au_debug_on();
173
	AuTraceEnter();
174
175
	sb = mnt->mnt_sb;
176
	root = sb->s_root;
177
	if (!sysaufs_brs)
178
		aufs_read_lock(root, !AuLock_IR);
179
	else
180
		si_noflush_read_lock(sb);
181
	sbinfo = au_sbi(sb);
182
	seq_printf(m, ",si=%p", sbinfo);
183
	mnt_flags = au_mntflags(sb);
184
	if (au_opt_test(mnt_flags, XINO)) {
185
		seq_puts(m, ",xino=");
186
		xino = sbinfo->si_xib;
187
		path.mnt = xino->f_vfsmnt;
188
		path.dentry = xino->f_dentry;
189
		err = seq_path(m, &path, au_esc_chars);
190
		if (unlikely(err <= 0))
191
			goto out;
192
		err = 0;
193
#define Deleted "\\040(deleted)"
194
		m->count -= sizeof(Deleted) - 1;
195
		AuDebugOn(memcmp(m->buf + m->count, Deleted,
196
				 sizeof(Deleted) - 1));
197
#undef Deleted
198
	} else
199
		seq_puts(m, ",noxino");
200
201
#define AuBool(name, str) do { \
202
	v = au_opt_test(mnt_flags, name); \
203
	if (v != au_opt_test(AuOpt_Def, name)) \
204
		seq_printf(m, ",%s" #str, v ? "" : "no"); \
205
} while (0)
206
207
#define AuStr(name, str) do { \
208
	v = mnt_flags & AuOptMask_##name; \
209
	if (v != (AuOpt_Def & AuOptMask_##name)) \
210
		seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
211
} while (0)
212
213
#ifdef CONFIG_AUFS_COMPAT
214
#define AuStr_BrOpt	"dirs="
215
#else
216
#define AuStr_BrOpt	"br:"
217
#endif
218
219
	AuBool(TRUNC_XINO, trunc_xino);
220
	AuBool(DIRPERM1, dirperm1);
221
	AuBool(SHWH, shwh);
222
	AuBool(PLINK, plink);
223
	AuStr(UDBA, udba);
224
225
	v = sbinfo->si_wbr_create;
226
	if (v != AuWbrCreate_Def)
227
		au_show_wbr_create(m, v, sbinfo);
228
229
	v = sbinfo->si_wbr_copyup;
230
	if (v != AuWbrCopyup_Def)
231
		seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
232
233
	v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
234
	if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
235
		seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
236
	AuBool(REFROF, refrof);
237
	AuBool(DLGT, dlgt);
238
	AuBool(WARN_PERM, warn_perm);
239
	AuBool(VERBOSE, verbose);
240
241
	n = sbinfo->si_dirwh;
242
	if (n != AUFS_DIRWH_DEF)
243
		seq_printf(m, ",dirwh=%d", n);
244
	n = sbinfo->si_rdcache / HZ;
245
	if (n != AUFS_RDCACHE_DEF)
246
		seq_printf(m, ",rdcache=%d", n);
247
248
	AuStr(COO, coo);
249
250
 out:
251
	if (!sysaufs_brs) {
252
		seq_puts(m, "," AuStr_BrOpt);
253
		au_show_brs(m, sb);
254
		aufs_read_unlock(root, !AuLock_IR);
255
	} else
256
		si_read_unlock(sb);
257
	//au_debug_off();
258
	return 0;
259
260
#undef AuBool
261
#undef AuStr
262
#undef AuStr_BrOpt
263
}
264
265
static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
266
{
267
	int err;
268
269
	AuTraceEnter();
270
271
	aufs_read_lock(dentry->d_sb->s_root, 0);
272
	err = vfsub_statfs(au_h_dptr(dentry->d_sb->s_root, 0), buf,
273
			   !!au_opt_test_dlgt(au_mntflags(dentry->d_sb)));
274
	//if (LktrCond) err = -1;
275
	aufs_read_unlock(dentry->d_sb->s_root, 0);
276
	if (!err) {
277
		buf->f_type = AUFS_SUPER_MAGIC;
278
		buf->f_namelen -= AUFS_WH_PFX_LEN;
279
		//todo: support uuid?
280
		memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
281
	}
282
	/* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
283
284
	AuTraceErr(err);
285
	return err;
286
}
287
288
static void au_fsync_br(struct super_block *sb)
289
{
290
#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
291
	aufs_bindex_t bend, bindex;
292
	int brperm;
293
	struct super_block *h_sb;
294
295
	AuTraceEnter();
296
297
	si_write_lock(sb);
298
	bend = au_sbend(sb);
299
	for (bindex = 0; bindex < bend; bindex++) {
300
		brperm = au_sbr_perm(sb, bindex);
301
		if (brperm == AuBr_RR || brperm == AuBr_RRWH)
302
			continue;
303
		h_sb = au_sbr_sb(sb, bindex);
304
		if (bdev_read_only(h_sb->s_bdev))
305
			continue;
306
307
		lockdep_off();
308
		down_write(&h_sb->s_umount);
309
		shrink_dcache_sb(h_sb);
310
		fsync_super(h_sb);
311
		up_write(&h_sb->s_umount);
312
		lockdep_on();
313
	}
314
	si_write_unlock(sb);
315
#endif
316
}
317
318
static void aufs_umount_begin(struct vfsmount *mnt, int flags)
319
{
320
	struct super_block *sb = mnt->mnt_sb;
321
	struct au_sbinfo *sbinfo;
322
323
	AuTraceEnter();
324
	//todo: dont trust BKL.
325
	AuDebugOn(!kernel_locked());
326
327
	sbinfo = au_sbi(sb);
328
	if (unlikely(!sbinfo))
329
		return;
330
331
	au_fsync_br(sb);
332
333
	si_write_lock(sb);
334
	if (au_opt_test(au_mntflags(sb), PLINK))
335
		au_plink_put(sb);
336
	spin_lock(&sbinfo->si_mntcache_lock);
337
	sbinfo->si_mntcache = NULL;
338
	spin_unlock(&sbinfo->si_mntcache_lock);
339
	si_write_unlock(sb);
340
}
341
342
/* final actions when unmounting a file system */
343
static void aufs_put_super(struct super_block *sb)
344
{
345
	struct au_sbinfo *sbinfo;
346
347
	AuTraceEnter();
348
349
	sbinfo = au_sbi(sb);
350
	if (unlikely(!sbinfo))
351
		return;
352
	kobject_put(&sbinfo->si_kobj);
353
}
354
355
/* ---------------------------------------------------------------------- */
356
357
/*
358
 * refresh dentry and inode at remount time.
359
 */
360
static int do_refresh(struct dentry *dentry, mode_t type,
361
		      unsigned int dir_flags)
362
{
363
	int err;
364
	struct dentry *parent;
365
	struct inode *inode;
366
367
	LKTRTrace("%.*s, 0%o\n", AuDLNPair(dentry), type);
368
	inode = dentry->d_inode;
369
	AuDebugOn(!inode);
370
371
	di_write_lock_child(dentry);
372
	parent = dget_parent(dentry);
373
	di_read_lock_parent(parent, AuLock_IR);
374
	/* returns a number of positive dentries */
375
	err = au_refresh_hdentry(dentry, type);
376
	//err = -1;
377
	if (err >= 0) {
378
		err = au_refresh_hinode(inode, dentry);
379
		//err = -1;
380
		if (!err && type == S_IFDIR)
381
			au_reset_hinotify(inode, dir_flags);
382
	}
383
	if (unlikely(err))
384
		AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
385
	di_read_unlock(parent, AuLock_IR);
386
	dput(parent);
387
	di_write_unlock(dentry);
388
389
	AuTraceErr(err);
390
	return err;
391
}
392
393
static int test_dir(struct dentry *dentry, void *arg)
394
{
395
	return S_ISDIR(dentry->d_inode->i_mode);
396
}
397
398
//todo: merge with refresh_nondir()
399
static int refresh_dir(struct dentry *root, au_gen_t sgen)
400
{
401
	int err, i, j, ndentry, e;
402
	const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
403
	struct au_dcsub_pages dpages;
404
	struct au_dpage *dpage;
405
	struct dentry **dentries;
406
	struct inode *inode;
407
408
	LKTRTrace("sgen %d\n", sgen);
409
	SiMustWriteLock(root->d_sb);
410
	//todo: dont trust BKL.
411
	AuDebugOn(au_digen(root) != sgen || !kernel_locked());
412
413
	err = 0;
414
	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
415
		if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
416
			ii_write_lock_child(inode);
417
			e = au_refresh_hinode_self(inode);
418
			//e = -1;
419
			ii_write_unlock(inode);
420
			if (unlikely(e)) {
421
				LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
422
				if (!err)
423
					err = e;
424
				/* go on even if err */
425
			}
426
		}
427
428
	e = au_dpages_init(&dpages, GFP_TEMPORARY);
429
	if (unlikely(e)) {
430
		if (!err)
431
			err = e;
432
		goto out;
433
	}
434
	e = au_dcsub_pages(&dpages, root, test_dir, NULL);
435
	if (unlikely(e)) {
436
		if (!err)
437
			err = e;
438
		goto out_dpages;
439
	}
440
441
	for (i = 0; !e && i < dpages.ndpage; i++) {
442
		dpage = dpages.dpages + i;
443
		dentries = dpage->dentries;
444
		ndentry = dpage->ndentry;
445
		for (j = 0; !e && j < ndentry; j++) {
446
			struct dentry *d;
447
			d = dentries[j];
448
#ifdef CONFIG_AUFS_DEBUG
449
			{
450
				struct dentry *parent;
451
				parent = dget_parent(d);
452
				AuDebugOn(!S_ISDIR(d->d_inode->i_mode)
453
					  || IS_ROOT(d)
454
					  || au_digen(parent) != sgen);
455
				dput(parent);
456
			}
457
#endif
458
			if (au_digen(d) != sgen) {
459
				e = do_refresh(d, S_IFDIR, flags);
460
				//e = -1;
461
				if (unlikely(e && !err))
462
					err = e;
463
				/* break on err */
464
			}
465
		}
466
	}
467
468
 out_dpages:
469
	au_dpages_free(&dpages);
470
 out:
471
	AuTraceErr(err);
472
	return err;
473
}
474
475
static int test_nondir(struct dentry *dentry, void *arg)
476
{
477
	return !S_ISDIR(dentry->d_inode->i_mode);
478
}
479
480
static int refresh_nondir(struct dentry *root, au_gen_t sgen, int do_dentry)
481
{
482
	int err, i, j, ndentry, e;
483
	struct au_dcsub_pages dpages;
484
	struct au_dpage *dpage;
485
	struct dentry **dentries;
486
	struct inode *inode;
487
488
	LKTRTrace("sgen %d\n", sgen);
489
	SiMustWriteLock(root->d_sb);
490
	//todo: dont trust BKL.
491
	AuDebugOn(au_digen(root) != sgen || !kernel_locked());
492
493
	err = 0;
494
	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
495
		if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
496
			ii_write_lock_child(inode);
497
			e = au_refresh_hinode_self(inode);
498
			//e = -1;
499
			ii_write_unlock(inode);
500
			if (unlikely(e)) {
501
				LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
502
				if (!err)
503
					err = e;
504
				/* go on even if err */
505
			}
506
		}
507
508
	if (!do_dentry)
509
		goto out;
510
511
	e = au_dpages_init(&dpages, GFP_TEMPORARY);
512
	if (unlikely(e)) {
513
		if (!err)
514
			err = e;
515
		goto out;
516
	}
517
	e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
518
	if (unlikely(e)) {
519
		if (!err)
520
			err = e;
521
		goto out_dpages;
522
	}
523
524
	for (i = 0; i < dpages.ndpage; i++) {
525
		dpage = dpages.dpages + i;
526
		dentries = dpage->dentries;
527
		ndentry = dpage->ndentry;
528
		for (j = 0; j < ndentry; j++) {
529
			struct dentry *d;
530
			d = dentries[j];
531
#ifdef CONFIG_AUFS_DEBUG
532
			{
533
				struct dentry *parent;
534
				parent = dget_parent(d);
535
				AuDebugOn(S_ISDIR(d->d_inode->i_mode)
536
					  || au_digen(parent) != sgen);
537
				dput(parent);
538
			}
539
#endif
540
			inode = d->d_inode;
541
			if (inode && au_digen(d) != sgen) {
542
				e = do_refresh(d, inode->i_mode & S_IFMT, 0);
543
				//e = -1;
544
				if (unlikely(e && !err))
545
					err = e;
546
				/* go on even err */
547
			}
548
		}
549
	}
550
551
 out_dpages:
552
	au_dpages_free(&dpages);
553
 out:
554
	AuTraceErr(err);
555
	return err;
556
}
557
558
/* stop extra interpretation of errno in mount(8), and strange error messages */
559
static int cvt_err(int err)
560
{
561
	AuTraceErr(err);
562
563
	switch (err) {
564
	case -ENOENT:
565
	case -ENOTDIR:
566
	case -EEXIST:
567
	case -EIO:
568
		err = -EINVAL;
569
	}
570
	return err;
571
}
572
573
/* protected by s_umount */
574
static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
575
{
576
	int err;
577
	struct dentry *root;
578
	struct inode *inode;
579
	struct au_opts opts;
580
	unsigned int dlgt;
581
	struct au_sbinfo *sbinfo;
582
583
	//au_debug_on();
584
	LKTRTrace("flags 0x%x, data %s, len %lu\n",
585
		  *flags, data ? data : "NULL",
586
		  (unsigned long)(data ? strlen(data) : 0));
587
588
	au_fsync_br(sb);
589
	err = 0;
590
	if (!data || !*data)
591
		goto out; /* success */
592
593
	err = -ENOMEM;
594
	memset(&opts, 0, sizeof(opts));
595
	opts.opt = (void *)__get_free_page(GFP_TEMPORARY);
596
	//if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
597
	if (unlikely(!opts.opt))
598
		goto out;
599
	opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
600
	opts.flags = AuOpts_REMOUNT;
601
602
	/* parse it before aufs lock */
603
	err = au_opts_parse(sb, *flags, data, &opts);
604
	//if (LktrCond) {au_free_opts(&opts); err = -1;}
605
	if (unlikely(err))
606
		goto out_opts;
607
608
	sbinfo = au_sbi(sb);
609
	root = sb->s_root;
610
	inode = root->d_inode;
611
	mutex_lock(&inode->i_mutex);
612
	aufs_write_lock(root);
613
614
	//DbgSleep(3);
615
616
	/* au_do_opts() may return an error */
617
	err = au_opts_remount(sb, &opts);
618
	//if (LktrCond) err = -1;
619
	au_opts_free(&opts);
620
621
	if (au_ftest_opts(opts.flags, REFRESH_DIR)
622
	    || au_ftest_opts(opts.flags, REFRESH_NONDIR)) {
623
		int rerr;
624
		au_gen_t sigen;
625
626
		dlgt = !!au_opt_test_dlgt(sbinfo->si_mntflags);
627
		au_opt_clr(sbinfo->si_mntflags, DLGT);
628
		au_sigen_inc(sb);
629
		au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
630
		sigen = au_sigen(sb);
631
		au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
632
633
		DiMustNoWaiters(root);
634
		IiMustNoWaiters(root->d_inode);
635
		di_write_unlock(root);
636
637
		rerr = refresh_dir(root, sigen);
638
		if (unlikely(rerr)) {
639
			au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
640
			AuWarn("Refreshing directories failed, ignores (%d)\n",
641
			       rerr);
642
		}
643
644
		if (unlikely(au_ftest_opts(opts.flags, REFRESH_NONDIR))) {
645
			//au_debug_on();
646
			rerr = refresh_nondir(root, sigen, !rerr);
647
			if (unlikely(rerr))
648
				AuWarn("Refreshing non-directories failed,"
649
				       " ignores (%d)\n", rerr);
650
			//au_debug_off();
651
		}
652
653
		/* aufs_write_lock() calls ..._child() */
654
		di_write_lock_child(root);
655
656
		au_cpup_attr_all(inode);
657
		if (unlikely(dlgt))
658
			au_opt_set(sbinfo->si_mntflags, DLGT);
659
	}
660
661
	aufs_write_unlock(root);
662
	mutex_unlock(&inode->i_mutex);
663
664
 out_opts:
665
	free_page((unsigned long)opts.opt);
666
 out:
667
	err = cvt_err(err);
668
	AuTraceErr(err);
669
	//au_debug_off();
670
	return err;
671
}
672
673
static struct super_operations aufs_sop = {
674
	.alloc_inode	= aufs_alloc_inode,
675
	.destroy_inode	= aufs_destroy_inode,
676
	//.dirty_inode	= aufs_dirty_inode,
677
	//.write_inode	= aufs_write_inode,
678
	//void (*put_inode) (struct inode *);
679
	.drop_inode	= generic_delete_inode,
680
	//.delete_inode	= aufs_delete_inode,
681
	//.clear_inode	= aufs_clear_inode,
682
683
	.show_options	= aufs_show_options,
684
	.statfs		= aufs_statfs,
685
686
	.put_super	= aufs_put_super,
687
	//void (*write_super) (struct super_block *);
688
	//int (*sync_fs)(struct super_block *sb, int wait);
689
	//void (*write_super_lockfs) (struct super_block *);
690
	//void (*unlockfs) (struct super_block *);
691
	.remount_fs	= aufs_remount_fs,
692
	/* depends upon umount flags. also use put_super() (< 2.6.18) */
693
	.umount_begin	= aufs_umount_begin
694
};
695
696
/* ---------------------------------------------------------------------- */
697
698
static int alloc_root(struct super_block *sb)
699
{
700
	int err;
701
	struct inode *inode;
702
	struct dentry *root;
703
704
	AuTraceEnter();
705
706
	err = -ENOMEM;
707
	inode = au_iget_locked(sb, AUFS_ROOT_INO);
708
	//if (LktrCond) {iput(inode); inode = NULL;}
709
	err = PTR_ERR(inode);
710
	if (IS_ERR(inode))
711
		goto out;
712
	unlock_new_inode(inode);
713
	inode->i_mode = S_IFDIR;
714
	root = d_alloc_root(inode);
715
	//if (LktrCond) {igrab(inode); dput(root); root = NULL;}
716
	if (unlikely(!root))
717
		goto out_iput;
718
	err = PTR_ERR(root);
719
	if (IS_ERR(root))
720
		goto out_iput;
721
722
	err = au_alloc_dinfo(root);
723
	//if (LktrCond){au_rw_write_unlock(&au_di(root)->di_rwsem);err=-1;}
724
	if (!err) {
725
		sb->s_root = root;
726
		return 0; /* success */
727
	}
728
	dput(root);
729
	goto out; /* do not iput */
730
731
 out_iput:
732
	iget_failed(inode);
733
	iput(inode);
734
 out:
735
	AuTraceErr(err);
736
	return err;
737
738
}
739
740
static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
741
{
742
	int err;
743
	struct dentry *root;
744
	struct inode *inode;
745
	struct au_opts opts;
746
	char *arg = raw_data;
747
748
	//au_debug_on();
749
	if (unlikely(!arg || !*arg)) {
750
		err = -EINVAL;
751
		AuErr("no arg\n");
752
		goto out;
753
	}
754
	LKTRTrace("%s, silent %d\n", arg, silent);
755
756
	err = -ENOMEM;
757
	memset(&opts, 0, sizeof(opts));
758
	opts.opt = (void *)__get_free_page(GFP_TEMPORARY);
759
	//if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
760
	if (unlikely(!opts.opt))
761
		goto out;
762
	opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
763
764
	err = au_si_alloc(sb);
765
	//if (LktrCond) {si_write_unlock(sb);free_sbinfo(sb);err=-1;}
766
	if (unlikely(err))
767
		goto out_opts;
768
	SiMustWriteLock(sb);
769
	/* all timestamps always follow the ones on the branch */
770
	sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
771
	sb->s_op = &aufs_sop;
772
	sb->s_magic = AUFS_SUPER_MAGIC;
773
	au_init_export_op(sb);
774
775
	err = alloc_root(sb);
776
	//if (LktrCond) {au_rw_write_unlock(&au_di(sb->s_root)->di_rwsem);
777
	//dput(sb->s_root);sb->s_root=NULL;err=-1;}
778
	if (unlikely(err)) {
779
		AuDebugOn(sb->s_root);
780
		si_write_unlock(sb);
781
		goto out_info;
782
	}
783
	root = sb->s_root;
784
	DiMustWriteLock(root);
785
	inode = root->d_inode;
786
	inode->i_nlink = 2;
787
788
	/*
789
	 * actually we can parse options regardless aufs lock here.
790
	 * but at remount time, parsing must be done before aufs lock.
791
	 * so we follow the same rule.
792
	 */
793
	ii_write_lock_parent(inode);
794
	aufs_write_unlock(root);
795
	err = au_opts_parse(sb, sb->s_flags, arg, &opts);
796
	//if (LktrCond) {au_opts_free(&opts); err = -1;}
797
	if (unlikely(err))
798
		goto out_root;
799
800
	/* lock vfs_inode first, then aufs. */
801
	mutex_lock(&inode->i_mutex);
802
	inode->i_op = &aufs_dir_iop;
803
	inode->i_fop = &aufs_dir_fop;
804
	aufs_write_lock(root);
805
806
	sb->s_maxbytes = 0;
807
	err = au_opts_mount(sb, &opts);
808
	//if (LktrCond) err = -1;
809
	au_opts_free(&opts);
810
	if (unlikely(err))
811
		goto out_unlock;
812
	AuDebugOn(!sb->s_maxbytes);
813
814
	//AuDbgDentry(root);
815
	aufs_write_unlock(root);
816
	mutex_unlock(&inode->i_mutex);
817
	//AuDbgSb(sb);
818
	goto out_opts; /* success */
819
820
 out_unlock:
821
	aufs_write_unlock(root);
822
	mutex_unlock(&inode->i_mutex);
823
 out_root:
824
	dput(root);
825
	sb->s_root = NULL;
826
 out_info:
827
	au_fset_si(au_sbi(sb), FAILED_INIT);
828
	kobject_put(&au_sbi(sb)->si_kobj);
829
	sb->s_fs_info = NULL;
830
 out_opts:
831
	free_page((unsigned long)opts.opt);
832
 out:
833
	AuTraceErr(err);
834
	err = cvt_err(err);
835
	AuTraceErr(err);
836
	//au_debug_off();
837
	return err;
838
}
839
840
/* ---------------------------------------------------------------------- */
841
842
static int aufs_get_sb(struct file_system_type *fs_type, int flags,
843
		       const char *dev_name, void *raw_data,
844
		       struct vfsmount *mnt)
845
{
846
	int err;
847
848
	/* all timestamps always follow the ones on the branch */
849
	/* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
850
	err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
851
	if (!err) {
852
		struct super_block *sb = mnt->mnt_sb;
853
		struct au_sbinfo *sbinfo = au_sbi(sb);
854
855
		/* no get/put */
856
		spin_lock_init(&sbinfo->si_mntcache_lock);
857
		sbinfo->si_mntcache = mnt;
858
859
		au_sbilist_lock();
860
		au_sbilist_add(sbinfo);
861
		si_write_lock(sb);
862
		sysaufs_brs_add(sb, 0);
863
		si_write_unlock(sb);
864
		au_sbilist_unlock();
865
	}
866
	return err;
867
}
868
869
struct file_system_type aufs_fs_type = {
870
	.name		= AUFS_FSTYPE,
871
	.fs_flags	= FS_REVAL_DOT, /* for UDBA and NFS branch */
872
	.get_sb		= aufs_get_sb,
873
	.kill_sb	= generic_shutdown_super,
874
	//.kill_sb	= kill_anon_super,
875
	/* no need to __module_get() and module_put(). */
876
	.owner		= THIS_MODULE,
877
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/super.h (+410 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * super_block operations
21
 *
22
 * $Id: super.h,v 1.5 2008/05/19 01:50:18 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_SUPER_H__
26
#define __AUFS_SUPER_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/cramfs_fs.h>
32
#include <linux/kobject.h>
33
#include <linux/magic.h>
34
#include <linux/aufs_type.h>
35
//#include "hinode.h"
36
#include "misc.h"
37
//#include "opts.h"
38
#include "wkq.h"
39
40
typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
41
typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
42
			       loff_t *);
43
44
struct au_wbr_copyup_operations {
45
	int (*copyup)(struct dentry *dentry);
46
};
47
48
struct au_wbr_create_operations {
49
	int (*create)(struct dentry *dentry, int isdir);
50
	int (*init)(struct super_block *sb);
51
	int (*fin)(struct super_block *sb);
52
};
53
54
struct au_wbr_mfs {
55
	struct mutex	mfs_lock; /* protect this structure */
56
	unsigned long	mfs_jiffy;
57
	unsigned long	mfs_expire;
58
	aufs_bindex_t	mfs_bindex;
59
60
	u64		mfsrr_bytes;
61
	u64		mfsrr_watermark;
62
};
63
64
/* sbinfo status flags */
65
/*
66
 * set true when refresh_dirs() failed at remount time.
67
 * then try refreshing dirs at access time again.
68
 * if it is false, refreshing dirs at access time is unnecesary
69
 */
70
#define AuSi_FAILED_REFRESH_DIRS	1
71
#define AuSi_FAILED_INIT		(1 << 1)
72
#define au_ftest_si(sbinfo, name)	((sbinfo)->au_si_status & AuSi_##name)
73
#define au_fset_si(sbinfo, name) \
74
	{ (sbinfo)->au_si_status |= AuSi_##name; }
75
#define au_fclr_si(sbinfo, name) \
76
	{ (sbinfo)->au_si_status &= ~AuSi_##name; }
77
78
struct au_branch;
79
struct au_sbinfo {
80
	/* nowait tasks in the system-wide workqueue */
81
	struct au_nowait_tasks	si_nowait;
82
83
	struct au_rwsem		si_rwsem;
84
85
	/* branch management */
86
	au_gen_t		si_generation;
87
88
	/* see above flags */
89
	unsigned char		au_si_status;
90
91
	aufs_bindex_t		si_bend;
92
	aufs_bindex_t		si_last_br_id;
93
	struct au_branch	**si_branch;
94
95
	/* policy to select a writable branch */
96
	unsigned char		si_wbr_copyup;
97
	unsigned char		si_wbr_create;
98
	struct au_wbr_copyup_operations *si_wbr_copyup_ops;
99
	struct au_wbr_create_operations *si_wbr_create_ops;
100
101
	/* round robin */
102
	atomic_t		si_wbr_rr_next;
103
104
	/* most free space */
105
	struct au_wbr_mfs	si_wbr_mfs;
106
107
	/* mount flags */
108
	/* include/asm-ia64/siginfo.h defines a macro named si_flags */
109
	unsigned int		si_mntflags;
110
111
	/* external inode number (bitmap and translation table) */
112
	au_readf_t		si_xread;
113
	au_writef_t		si_xwrite;
114
	struct file		*si_xib;
115
	struct mutex		si_xib_mtx; /* protect xib members */
116
	unsigned long		*si_xib_buf;
117
	unsigned long		si_xib_last_pindex;
118
	int			si_xib_next_bit;
119
	//unsigned long long	si_xib_limit;	/* Max xib file size */
120
121
	/* readdir cache time, max, in HZ */
122
	unsigned long		si_rdcache;
123
124
	/*
125
	 * If the number of whiteouts are larger than si_dirwh, leave all of
126
	 * them after au_whtmp_ren to reduce the cost of rmdir(2).
127
	 * future fsck.aufs or kernel thread will remove them later.
128
	 * Otherwise, remove all whiteouts and the dir in rmdir(2).
129
	 */
130
	unsigned int		si_dirwh;
131
132
	/*
133
	 * rename(2) a directory with all children.
134
	 */
135
	//int			si_rendir;
136
137
	/* pseudo_link list */ // dirty
138
	spinlock_t		si_plink_lock;
139
	struct list_head	si_plink;
140
141
	/* dirty, for export, async ops, and sysfs */
142
	spinlock_t		si_mntcache_lock;
143
	struct vfsmount		*si_mntcache;	/* no get/put */
144
145
	/*
146
	 * sysfs and lifetime management.
147
	 * this is not a small structure and it may be a waste of memory in case
148
	 * of sysfs is disabled, particulary when many aufs-es are mounted.
149
	 */
150
	struct kobject		si_kobj;
151
152
	//todo: remove this list.
153
	/* super_blocks list is not exported */
154
	struct list_head	si_list;
155
156
#ifdef CONFIG_AUFS_ROBR
157
	/* locked vma list for mmap() */ // dirty
158
	spinlock_t		si_lvma_lock;
159
	struct list_head	si_lvma;
160
#endif
161
162
	/* dirty, necessary for unmounting, sysfs and sysrq */
163
	struct super_block	*si_sb;
164
};
165
166
/* ---------------------------------------------------------------------- */
167
168
/* policy to select one among writable branches */
169
#define AuWbrCopyup(sbinfo, args... ) \
170
	(sbinfo)->si_wbr_copyup_ops->copyup(args)
171
#define AuWbrCreate(sbinfo, args... ) \
172
	(sbinfo)->si_wbr_create_ops->create(args)
173
174
/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
175
#define AuLock_DW		1		/* write-lock dentry */
176
#define AuLock_IR		(1 << 1)	/* read-lock inode */
177
#define AuLock_IW		(1 << 2)	/* write-lock inode */
178
#define AuLock_FLUSH		(1 << 3)	/* wait for 'nowait' tasks */
179
#define AuLock_DIR		(1 << 4)	/* target is a dir */
180
#define au_ftest_lock(flags, name)	((flags) & AuLock_##name)
181
#define au_fset_lock(flags, name)	{ (flags) |= AuLock_##name; }
182
#define au_fclr_lock(flags, name)	{ (flags) &= ~AuLock_##name; }
183
184
/* ---------------------------------------------------------------------- */
185
186
/* super.c */
187
extern struct file_system_type aufs_fs_type;
188
struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
189
190
/* sbinfo.c */
191
void au_si_free(struct kobject *kobj);
192
int au_si_alloc(struct super_block *sb);
193
struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex);
194
au_gen_t au_sigen_inc(struct super_block *sb);
195
int au_find_bindex(struct super_block *sb, struct au_branch *br);
196
197
void aufs_read_lock(struct dentry *dentry, int flags);
198
void aufs_read_unlock(struct dentry *dentry, int flags);
199
void aufs_write_lock(struct dentry *dentry);
200
void aufs_write_unlock(struct dentry *dentry);
201
void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
202
void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
203
204
aufs_bindex_t au_new_br_id(struct super_block *sb);
205
struct vfsmount *au_mntcache_get(struct super_block *sb);
206
207
/* wbr_policy.c */
208
extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
209
extern struct au_wbr_create_operations au_wbr_create_ops[];
210
int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst,
211
		   struct dentry *locked);
212
213
/* ---------------------------------------------------------------------- */
214
215
static inline struct au_sbinfo *au_sbi(struct super_block *sb)
216
{
217
	return sb->s_fs_info;
218
}
219
220
static inline const char *au_sbtype(struct super_block *sb)
221
{
222
	return sb->s_type->name;
223
}
224
225
static inline int au_test_aufs(struct super_block *sb)
226
{
227
	return (sb->s_magic == AUFS_SUPER_MAGIC);
228
}
229
230
static inline int au_test_nfs(struct super_block *sb)
231
{
232
#ifdef CONFIG_AUFS_BR_NFS
233
	return (sb->s_magic == NFS_SUPER_MAGIC);
234
#else
235
	return 0;
236
#endif
237
}
238
239
static inline int au_test_fuse(struct super_block *sb)
240
{
241
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
242
#ifdef FUSE_SUPER_MAGIC
243
	BUILD_BUG_ON(FUSE_SUPER_MAGIC != 0x65735546);
244
	return (sb->s_magic == FUSE_SUPER_MAGIC);
245
#else
246
	return !strcmp(au_sbtype(sb), "fuse");
247
#endif
248
#endif
249
	return 0;
250
}
251
252
static inline int au_test_xfs(struct super_block *sb)
253
{
254
#ifdef CONFIG_AUFS_BR_XFS
255
#ifdef XFS_SB_MAGIC
256
	BUILD_BUG_ON(XFS_SB_MAGIC != 0x58465342);
257
	return (sb->s_magic == XFS_SB_MAGIC);
258
#else
259
	return !strcmp(au_sbtype(sb), "xfs");
260
#endif
261
#endif
262
	return 0;
263
}
264
265
static inline int au_test_tmpfs(struct super_block *sb)
266
{
267
#ifdef CONFIG_TMPFS
268
#ifdef TMPFS_MAGIC
269
	BUILD_BUG_ON(TMPFS_MAGIC != 0x01021994);
270
	return (sb->s_magic == TMPFS_MAGIC);
271
#else
272
	return !strcmp(au_sbtype(sb), "tmpfs");
273
#endif
274
#endif
275
	return 0;
276
}
277
278
/* ---------------------------------------------------------------------- */
279
280
#ifdef CONFIG_AUFS_EXPORT
281
extern struct export_operations aufs_export_op;
282
static inline void au_init_export_op(struct super_block *sb)
283
{
284
	sb->s_export_op = &aufs_export_op;
285
}
286
287
static inline int au_test_nfsd(struct task_struct *tsk)
288
{
289
	return (!tsk->mm && !strcmp(tsk->comm, "nfsd"));
290
}
291
292
static inline void au_nfsd_lockdep_off(void)
293
{
294
	if (au_test_nfsd(current))
295
		lockdep_off();
296
}
297
298
static inline void au_nfsd_lockdep_on(void)
299
{
300
	if (au_test_nfsd(current))
301
		lockdep_on();
302
}
303
#else
304
static inline int au_test_nfsd(struct task_struct *tsk)
305
{
306
	return 0;
307
}
308
309
static inline void au_init_export_op(struct super_block *sb)
310
{
311
	/* nothing */
312
}
313
314
#define au_nfsd_lockdep_off()	do {} while (0)
315
#define au_nfsd_lockdep_on()	do {} while (0)
316
#endif /* CONFIG_AUFS_EXPORT */
317
318
#ifdef CONFIG_AUFS_ROBR
319
static inline int au_test_nested(struct super_block *h_sb)
320
{
321
	return 0;
322
}
323
324
static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo)
325
{
326
	spin_lock_init(&sbinfo->si_lvma_lock);
327
	INIT_LIST_HEAD(&sbinfo->si_lvma);
328
}
329
#else
330
static inline int au_test_nested(struct super_block *h_sb)
331
{
332
	int err = 0;
333
	if (unlikely(au_test_aufs(h_sb))) {
334
		err = -EINVAL;
335
		AuTraceErr(err);
336
	}
337
	return err;
338
}
339
340
static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo)
341
{
342
	/* empty */
343
}
344
#endif /* CONFIG_AUFS_ROBR */
345
346
/* ---------------------------------------------------------------------- */
347
348
/* lock superblock. mainly for entry point functions */
349
/*
350
 * si_noflush_read_lock, si_noflush_write_lock,
351
 * si_read_unlock, si_write_unlock, si_downgrade_lock
352
 */
353
AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
354
		       au_sbi(sb)->si_rwsem);
355
AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, au_sbi(sb)->si_rwsem);
356
357
static inline void si_read_lock(struct super_block *sb, int flags)
358
{
359
	if (au_ftest_lock(flags, FLUSH))
360
		au_nwt_flush(&au_sbi(sb)->si_nowait);
361
	si_noflush_read_lock(sb);
362
}
363
364
static inline void si_write_lock(struct super_block *sb)
365
{
366
	au_nwt_flush(&au_sbi(sb)->si_nowait);
367
	si_noflush_write_lock(sb);
368
}
369
370
static inline int si_read_trylock(struct super_block *sb, int flags)
371
{
372
	if (au_ftest_lock(flags, FLUSH))
373
		au_nwt_flush(&au_sbi(sb)->si_nowait);
374
	return si_noflush_read_trylock(sb);
375
}
376
377
static inline int si_write_trylock(struct super_block *sb, int flags)
378
{
379
	if (au_ftest_lock(flags, FLUSH))
380
		au_nwt_flush(&au_sbi(sb)->si_nowait);
381
	return si_noflush_write_trylock(sb);
382
}
383
384
/* to debug easier, do not make them inlined functions */
385
#define SiMustReadLock(sb)	AuRwMustReadLock(&au_sbi(sb)->si_rwsem)
386
#define SiMustWriteLock(sb)	AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
387
#define SiMustAnyLock(sb)	AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
388
389
/* ---------------------------------------------------------------------- */
390
391
static inline aufs_bindex_t au_sbend(struct super_block *sb)
392
{
393
	SiMustAnyLock(sb);
394
	return au_sbi(sb)->si_bend;
395
}
396
397
static inline unsigned int au_mntflags(struct super_block *sb)
398
{
399
	SiMustAnyLock(sb);
400
	return au_sbi(sb)->si_mntflags;
401
}
402
403
static inline au_gen_t au_sigen(struct super_block *sb)
404
{
405
	SiMustAnyLock(sb);
406
	return au_sbi(sb)->si_generation;
407
}
408
409
#endif /* __KERNEL__ */
410
#endif /* __AUFS_SUPER_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/sysaufs.c (+104 lines)
Line 0 Link Here
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
 * sysfs interface and lifetime management
21
 * they are necessary regardless sysfs is disabled.
22
 *
23
 * $Id: sysaufs.c,v 1.5 2008/05/19 01:50:47 sfjro Exp $
24
 */
25
26
#include <linux/fs.h>
27
#include <linux/module.h>
28
#include <linux/sysfs.h>
29
#include "aufs.h"
30
31
/* ---------------------------------------------------------------------- */
32
33
/* super_blocks list is not exported */
34
DEFINE_MUTEX(au_sbilist_mtx);
35
LIST_HEAD(au_sbilist);
36
37
/* ---------------------------------------------------------------------- */
38
39
static struct kset au_kset;
40
41
#define AuSbiAttr(_name) { \
42
	.attr   = { .name = __stringify(_name), .mode = 0444 },	\
43
	.show   = sysaufs_sbi_##_name,				\
44
}
45
46
static struct au_sbi_attr au_sbi_attr_xino = AuSbiAttr(xino);
47
struct attribute *au_sbi_attrs[] = {
48
	&au_sbi_attr_xino.attr,
49
	NULL,
50
};
51
52
static struct sysfs_ops au_sbi_ops = {
53
	.show   = sysaufs_sbi_show
54
};
55
56
static struct kobj_type au_sbi_ktype = {
57
	.release	= au_si_free,
58
	.sysfs_ops	= &au_sbi_ops,
59
	.default_attrs	= au_sbi_attrs,
60
};
61
62
/* ---------------------------------------------------------------------- */
63
64
int sysaufs_si_init(struct au_sbinfo *sbinfo)
65
{
66
	int err;
67
68
	sbinfo->si_kobj.kset = &au_kset;
69
	err = kobject_init_and_add(&sbinfo->si_kobj, &au_sbi_ktype,
70
				   NULL/*&au_kset.kobj*/,
71
				   SysaufsSb_PREFIX "%p", sbinfo);
72
	AuTraceErr(err);
73
	return err;
74
}
75
76
77
/* ---------------------------------------------------------------------- */
78
79
void sysaufs_fin(void)
80
{
81
	AuDebugOn(!list_empty(&au_sbilist));
82
	sysfs_remove_group(&au_kset.kobj, au_attr_group);
83
	kset_unregister(&au_kset);
84
}
85
86
int __init sysaufs_init(void)
87
{
88
	int err;
89
90
	sysaufs_brs_init();
91
	au_kset.kobj.parent = fs_kobj;
92
	kobject_set_name(&au_kset.kobj, AUFS_NAME);
93
	au_kset.kobj.ktype = au_ktype;
94
	err = kset_register(&au_kset);
95
	if (unlikely(err))
96
		goto out;
97
	err = sysfs_create_group(&au_kset.kobj, au_attr_group);
98
	if (unlikely(err))
99
		kset_unregister(&au_kset);
100
101
 out:
102
	AuTraceErr(err);
103
	return err;
104
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/sysaufs.h (+146 lines)
Line 0 Link Here
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
 * sysfs interface and lifetime management
21
 *
22
 * $Id: sysaufs.h,v 1.6 2008/05/19 01:50:47 sfjro Exp $
23
 */
24
25
#ifndef __SYSAUFS_H__
26
#define __SYSAUFS_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/sysfs.h>
32
#include "module.h"
33
#include "super.h"
34
35
/* entries under sysfs per super block */
36
enum {
37
	SysaufsSb_XINO,
38
	SysaufsSb_MNTPNT1,
39
	SysaufsSb_Last
40
};
41
42
#define SysaufsSb_PREFIX	"si_"	/* followed by %p */
43
44
struct au_sbi_attr {
45
	struct attribute attr;
46
	int (*show)(struct seq_file *seq, struct super_block *sb);
47
};
48
49
/* ---------------------------------------------------------------------- */
50
51
/* sysaufs.c */
52
extern struct mutex au_sbilist_mtx;
53
extern struct list_head au_sbilist;
54
extern struct attribute *au_sbi_attrs[];
55
int sysaufs_si_init(struct au_sbinfo *sbinfo);
56
int __init sysaufs_init(void);
57
void sysaufs_fin(void);
58
59
/* ---------------------------------------------------------------------- */
60
61
static inline void au_sbilist_lock(void)
62
{
63
	mutex_lock(&au_sbilist_mtx);
64
}
65
66
static inline void au_sbilist_unlock(void)
67
{
68
	mutex_unlock(&au_sbilist_mtx);
69
}
70
71
static inline void au_sbilist_del(struct au_sbinfo *sbinfo)
72
{
73
	list_del(&sbinfo->si_list);
74
}
75
76
static inline void au_sbilist_add(struct au_sbinfo *sbinfo)
77
{
78
	/* the order in this list is important */
79
	list_add_tail(&sbinfo->si_list, &au_sbilist);
80
}
81
82
/* ---------------------------------------------------------------------- */
83
84
struct au_branch;
85
#ifdef CONFIG_SYSFS
86
/* sysfs.c */
87
extern struct attribute_group *au_attr_group;
88
extern struct kobj_type *au_ktype;
89
90
int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb);
91
int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb);
92
ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
93
			 char *buf);
94
95
void sysaufs_br_init(struct au_branch *br);
96
void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
97
void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
98
99
#define sysaufs_brs_init()	do {} while (0)
100
101
#else
102
#define au_attr_group	NULL
103
#define au_ktype	NULL
104
105
static inline
106
int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb)
107
{
108
	return 0;
109
}
110
111
static inline
112
int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb)
113
{
114
	return 0;
115
}
116
117
static inline
118
ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
119
			 char *buf)
120
{
121
	return 0;
122
}
123
124
static inline void sysaufs_br_init(struct au_branch *br)
125
{
126
	/* empty */
127
}
128
129
static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
130
{
131
	/* nothing */
132
}
133
134
static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
135
{
136
	/* nothing */
137
}
138
139
static inline void sysaufs_brs_init(void)
140
{
141
	sysaufs_brs = 0;
142
}
143
#endif /* CONFIG_SYSFS */
144
145
#endif /* __KERNEL__ */
146
#endif /* __SYSAUFS_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/sysfs.c (+456 lines)
Line 0 Link Here
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
 * sysfs interface
21
 *
22
 * $Id: sysfs.c,v 1.4 2008/05/19 01:51:16 sfjro Exp $
23
 */
24
25
#include <linux/fs.h>
26
#include <linux/module.h>
27
#include <linux/seq_file.h>
28
#include <linux/sysfs.h>
29
#include "aufs.h"
30
31
32
#ifdef CONFIG_AUFS_LOCAL
33
static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
34
			   char *buf)
35
{
36
#define conf_bool(name)	"CONFIG_AUFS_" #name "=y\n"
37
	static const char opt[] =
38
#ifdef CONFIG_AUFS
39
		"CONFIG_AUFS=y\n"
40
#else
41
		"CONFIG_AUFS=m\n"
42
#endif
43
#ifdef CONFIG_AUFS_BRANCH_MAX_127
44
		conf_bool(BRANCH_MAX_127)
45
#elif defined(CONFIG_AUFS_BRANCH_MAX_511)
46
		conf_bool(BRANCH_MAX_511)
47
#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
48
		conf_bool(BRANCH_MAX_1023)
49
#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
50
		conf_bool(BRANCH_MAX_32767)
51
#endif
52
#ifdef CONFIG_AUFS_HINOTIFY
53
		conf_bool(HINOTIFY)
54
#endif
55
#ifdef CONFIG_AUFS_EXPORT
56
		conf_bool(EXPORT)
57
#endif
58
#ifdef CONFIG_AUFS_ROBR
59
		conf_bool(ROBR)
60
#endif
61
#ifdef CONFIG_AUFS_SHWH
62
		conf_bool(SHWH)
63
#endif
64
#ifdef CONFIG_AUFS_DLGT
65
		conf_bool(DLGT)
66
#endif
67
#ifdef CONFIG_AUFS_RR_SQUASHFS
68
		conf_bool(RR_SQUASHFS)
69
#endif
70
#ifdef CONFIG_AUFS_SEC_PERM_PATCH
71
		conf_bool(SEC_PERM_PATCH)
72
#endif
73
#ifdef CONFIG_AUFS_SPLICE_PATCH
74
		conf_bool(SPLICE_PATCH)
75
#endif
76
#ifdef CONFIG_AUFS_PUT_FILP_PATCH
77
		conf_bool(PUT_FILP_PATCH)
78
#endif
79
#ifdef CONFIG_AUFS_LHASH_PATCH
80
		conf_bool(LHASH_PATCH)
81
#endif
82
#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
83
		conf_bool(FSYNC_SUPER_PATCH)
84
#endif
85
#ifdef CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH
86
		conf_bool(DENY_WRITE_ACCESS_PATCH)
87
#endif
88
#ifdef CONFIG_AUFS_KSIZE_PATCH
89
		conf_bool(KSIZE_PATCH)
90
#endif
91
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
92
		conf_bool(WORKAROUND_FUSE)
93
#endif
94
#ifdef CONFIG_AUFS_STAT
95
		conf_bool(STAT)
96
#endif
97
#ifdef CONFIG_AUFS_DEBUG
98
		conf_bool(DEBUG)
99
#endif
100
#ifdef CONFIG_AUFS_COMPAT
101
		conf_bool(COMPAT)
102
#endif
103
104
/* automatic configurations */
105
#ifdef CONFIG_AUFS_BR_NFS
106
		conf_bool(BR_NFS)
107
#endif
108
#ifdef CONFIG_AUFS_MAGIC_SYSRQ
109
		conf_bool(MAGIC_SYSRQ)
110
#endif
111
		;
112
#undef conf_bool
113
114
	char *p = buf;
115
	const char *end = buf + PAGE_SIZE;
116
117
	p += snprintf(p, end - p, "%s", opt);
118
#ifdef DbgUdbaRace
119
	if (p < end)
120
		p += snprintf(p, end - p, "DbgUdbaRace=%d\n", DbgUdbaRace);
121
#endif
122
	if (p < end)
123
		return p - buf;
124
	else
125
		return -EFBIG;
126
}
127
128
static struct kobj_attribute au_config_attr = __ATTR_RO(config);
129
#endif
130
131
#ifdef CONFIG_AUFS_STAT
132
static ssize_t stat_show(struct kobject *kobj, struct kobj_attribute *attr,
133
			 char *buf)
134
{
135
	char *p = buf;
136
	const char *end = buf + PAGE_SIZE;
137
	int i;
138
139
	p += snprintf(p, end - p, "wkq max_busy:");
140
	for (i = 0; p < end && i < aufs_nwkq; i++)
141
		p += snprintf(p, end - p, " %u", au_wkq[i].max_busy);
142
	if (p < end)
143
		p += snprintf(p, end - p, ", %u(generic)\n",
144
			      au_wkq[aufs_nwkq].max_busy);
145
146
	if (p < end)
147
		return p - buf;
148
	else
149
		return -EFBIG;
150
}
151
152
static struct kobj_attribute au_stat_attr = __ATTR_RO(stat);
153
#endif
154
155
#ifdef CONFIG_AUFS_DEBUG
156
static ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr,
157
			  char *buf)
158
{
159
	return sprintf(buf, "%d\n", au_debug_test());
160
}
161
162
static ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr,
163
			   const char *buf, size_t sz)
164
{
165
	LKTRTrace("%.*s\n", (unsigned int)sz, buf);
166
167
	if (unlikely(!sz || (*buf != '0' && *buf != '1')))
168
		return -EOPNOTSUPP;
169
170
	if (*buf == '0')
171
		au_debug_off();
172
	else if (*buf == '1')
173
		au_debug_on();
174
	return sz;
175
}
176
177
static struct kobj_attribute au_debug_attr = __ATTR(debug, S_IRUGO | S_IWUSR,
178
						    debug_show, debug_store);
179
#endif
180
181
static struct attribute *au_attr[] = {
182
#ifdef CONFIG_AUFS_LOCAL
183
	&au_config_attr.attr,
184
#endif
185
#ifdef CONFIG_AUFS_STAT
186
	&au_stat_attr.attr,
187
#endif
188
#ifdef CONFIG_AUFS_DEBUG
189
	&au_debug_attr.attr,
190
#endif
191
	NULL,	/* need to NULL terminate the list of attributes */
192
};
193
194
static struct attribute_group au_attr_group_body = {
195
	.attrs = au_attr
196
};
197
198
struct attribute_group *au_attr_group = &au_attr_group_body;
199
200
/* ---------------------------------------------------------------------- */
201
202
/*
203
 * they are copied from linux/lib/kobject.c,
204
 * and will be exported in the future.
205
 */
206
static ssize_t au_attr_show(struct kobject *kobj, struct attribute *attr,
207
			    char *buf)
208
{
209
	struct kobj_attribute *kattr;
210
	ssize_t ret = -EIO;
211
212
	kattr = container_of(attr, struct kobj_attribute, attr);
213
	if (kattr->show)
214
		ret = kattr->show(kobj, kattr, buf);
215
	return ret;
216
}
217
218
#ifdef CONFIG_AUFS_DEBUG
219
static ssize_t au_attr_store(struct kobject *kobj, struct attribute *attr,
220
			     const char *buf, size_t count)
221
{
222
	struct kobj_attribute *kattr;
223
	ssize_t ret = -EIO;
224
225
	kattr = container_of(attr, struct kobj_attribute, attr);
226
	if (kattr->store)
227
		ret = kattr->store(kobj, kattr, buf, count);
228
	return ret;
229
}
230
#endif
231
232
static struct sysfs_ops sysaufs_ops = {
233
	.show   = au_attr_show,
234
#ifdef CONFIG_AUFS_DEBUG
235
	.store  = au_attr_store
236
#endif
237
};
238
239
static struct kobj_type au_ktype_body = {
240
	.sysfs_ops = &sysaufs_ops
241
};
242
struct kobj_type *au_ktype = &au_ktype_body;
243
244
/* ---------------------------------------------------------------------- */
245
246
int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb)
247
{
248
	int err, dlgt;
249
	struct au_sbinfo *sbinfo;
250
	unsigned int mnt_flags;
251
	aufs_bindex_t bend, bindex;
252
	struct file *xf;
253
	struct kstat st;
254
255
	AuTraceEnter();
256
257
	sbinfo = au_sbi(sb);
258
	mnt_flags = au_mntflags(sb);
259
	if (unlikely(!au_opt_test(mnt_flags, XINO))) {
260
#ifdef CONFIG_AUFS_DEBUG
261
		AuDebugOn(sbinfo->si_xib);
262
		bend = au_sbend(sb);
263
		for (bindex = 0; bindex <= bend; bindex++)
264
			AuDebugOn(au_sbr(sb, bindex)->br_xino);
265
#endif
266
		err = 0;
267
		goto out; /* success */
268
	}
269
270
	dlgt = !!au_opt_test_dlgt(mnt_flags);
271
	xf = sbinfo->si_xib;
272
	err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt);
273
	if (!err)
274
		seq_printf(seq, "%Lux%lu %Ld\n",
275
			   st.blocks, st.blksize, (long long)st.size);
276
	else
277
		seq_printf(seq, "err %d\n", err);
278
279
	bend = au_sbend(sb);
280
	for (bindex = 0; !err && bindex <= bend; bindex++) {
281
		xf = au_sbr(sb, bindex)->br_xino;
282
		if (!xf)
283
			continue;
284
		seq_printf(seq, "%d: ", bindex);
285
		err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt);
286
		if (!err)
287
			seq_printf(seq, "%d, %Lux%lu %Ld\n",
288
				   file_count(xf), st.blocks, st.blksize,
289
				   (long long)st.size);
290
		else
291
			seq_printf(seq, "err %d\n", err);
292
	}
293
294
 out:
295
	AuTraceErr(err);
296
	return err;
297
}
298
299
/*
300
 * the lifetime of branch is independent from the entry under sysfs.
301
 * sysfs handles the lifetime of the entry, and never call ->show() after it is
302
 * unlinked.
303
 */
304
#define SysaufsBr_PREFIX "br"
305
static int sysaufs_sbi_br(struct seq_file *seq, struct super_block *sb,
306
			  aufs_bindex_t bindex)
307
{
308
	int err;
309
	struct dentry *root;
310
	struct au_branch *br;
311
	struct path path;
312
313
	LKTRTrace("b%d\n", bindex);
314
315
	err = -ENOENT;
316
	if (unlikely(au_sbend(sb) < bindex))
317
		goto out;
318
319
	err = 0;
320
	root = sb->s_root;
321
	di_read_lock_parent(root, !AuLock_IR);
322
	br = au_sbr(sb, bindex);
323
	path.mnt = br->br_mnt;
324
	path.dentry = au_h_dptr(root, bindex);
325
	seq_path(seq, &path, au_esc_chars);
326
	di_read_unlock(root, !AuLock_IR);
327
	seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
328
329
 out:
330
	AuTraceErr(err);
331
	return err;
332
}
333
334
/* ---------------------------------------------------------------------- */
335
336
static struct seq_file *au_seq(char *p, ssize_t len)
337
{
338
	struct seq_file *seq;
339
340
	seq = kzalloc(sizeof(*seq), GFP_TEMPORARY);
341
	if (seq) {
342
		//mutex_init(&seq.lock);
343
		seq->buf = p;
344
		seq->count = 0;
345
		seq->size = len;
346
		return seq; /* success */
347
	}
348
349
	seq = ERR_PTR(-ENOMEM);
350
	AuTraceErrPtr(seq);
351
	return seq;
352
}
353
354
//todo: file size may exceed PAGE_SIZE
355
ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
356
			 char *buf)
357
{
358
	ssize_t err;
359
	struct au_sbinfo *sbinfo;
360
	struct super_block *sb;
361
	struct seq_file *seq;
362
	char *name;
363
	struct attribute **cattr;
364
365
	LKTRTrace("%s/%s\n", kobject_name(kobj), attr->name);
366
367
	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
368
	sb = sbinfo->si_sb;
369
	si_noflush_read_lock(sb);
370
371
	seq = au_seq(buf, PAGE_SIZE);
372
	err = PTR_ERR(seq);
373
	if (IS_ERR(seq))
374
		goto out;
375
376
	name = (void *)attr->name;
377
	cattr = au_sbi_attrs;
378
	while (*cattr) {
379
		if (!strcmp(name, (*cattr)->name)) {
380
			err = container_of(*cattr, struct au_sbi_attr, attr)
381
				->show(seq, sb);
382
			goto out_seq;
383
		}
384
		cattr++;
385
	}
386
387
	if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
388
		name += sizeof(SysaufsBr_PREFIX) - 1;
389
		err = sysaufs_sbi_br(seq, sb, simple_strtol(name, NULL, 10));
390
		goto out_seq;
391
	}
392
	BUG();
393
394
 out_seq:
395
	if (!err) {
396
		err = seq->count;
397
		/* sysfs limit */
398
		if (unlikely(err == PAGE_SIZE))
399
			err = -EFBIG;
400
	}
401
	kfree(seq);
402
 out:
403
	si_read_unlock(sb);
404
	AuTraceErr(err);
405
	return err;
406
}
407
408
/* ---------------------------------------------------------------------- */
409
410
void sysaufs_br_init(struct au_branch *br)
411
{
412
	br->br_attr.name = br->br_name;
413
	br->br_attr.mode = S_IRUGO;
414
	br->br_attr.owner = THIS_MODULE;
415
}
416
417
void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
418
{
419
	struct au_sbinfo *sbinfo;
420
	aufs_bindex_t bend;
421
422
	LKTRTrace("b%d\n", bindex);
423
424
	if (!sysaufs_brs)
425
		return;
426
427
	sbinfo = au_sbi(sb);
428
	bend = au_sbend(sb);
429
	for (; bindex <= bend; bindex++)
430
		sysfs_remove_file(&sbinfo->si_kobj,
431
				  &au_sbr(sb, bindex)->br_attr);
432
}
433
434
void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
435
{
436
	int err;
437
	struct kobject *kobj;
438
	aufs_bindex_t bend;
439
	struct au_branch *br;
440
441
	LKTRTrace("b%d\n", bindex);
442
443
	if (!sysaufs_brs)
444
		return;
445
446
	kobj = &au_sbi(sb)->si_kobj;
447
	bend = au_sbend(sb);
448
	for (; bindex <= bend; bindex++) {
449
		br = au_sbr(sb, bindex);
450
		snprintf(br->br_name, sizeof(br->br_name),
451
			 SysaufsBr_PREFIX "%d", bindex);
452
		err = sysfs_create_file(kobj, &br->br_attr);
453
		if (unlikely(err))
454
			AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
455
	}
456
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/sysrq.c (+99 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 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
 * magic sysrq hanlder
21
 *
22
 * $Id: sysrq.c,v 1.4 2008/05/04 23:53:27 sfjro Exp $
23
 */
24
25
#include <linux/fs.h>
26
#include <linux/module.h>
27
#include <linux/moduleparam.h>
28
#include <linux/sysrq.h>
29
#include "aufs.h"
30
31
static void sysrq_sb(struct super_block *sb)
32
{
33
	char *plevel;
34
	struct inode *i;
35
36
	plevel = au_plevel;
37
	au_plevel = KERN_WARNING;
38
	au_debug_on();
39
40
	pr_warning(AUFS_NAME ": superblock\n");
41
	au_dpri_sb(sb);
42
	pr_warning(AUFS_NAME ": root dentry\n");
43
	au_dpri_dentry(sb->s_root);
44
	pr_warning(AUFS_NAME ": isolated inode\n");
45
	list_for_each_entry(i, &sb->s_inodes, i_sb_list)
46
		if (list_empty(&i->i_dentry))
47
			au_dpri_inode(i);
48
49
	au_plevel = plevel;
50
	au_debug_off();
51
}
52
53
/* ---------------------------------------------------------------------- */
54
55
/* module parameter */
56
static char *aufs_sysrq_key = "a";
57
module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
58
MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
59
60
static void au_sysrq(int key, struct tty_struct *tty)
61
{
62
	struct au_sbinfo *sbinfo;
63
64
	//mutex_lock(&au_sbilist_mtx);
65
	list_for_each_entry(sbinfo, &au_sbilist, si_list)
66
		sysrq_sb(sbinfo->si_sb);
67
	//mutex_unlock(&au_sbilist_mtx);
68
}
69
70
static struct sysrq_key_op au_sysrq_op = {
71
	.handler	= au_sysrq,
72
	.help_msg	= "Aufs",
73
	.action_msg	= "Aufs",
74
	.enable_mask	= SYSRQ_ENABLE_DUMP //??
75
};
76
77
/* ---------------------------------------------------------------------- */
78
79
int __init au_sysrq_init(void)
80
{
81
	int err;
82
	char key;
83
84
	err = -1;
85
	key = *aufs_sysrq_key;
86
	if ('a' <= key && key <= 'z')
87
		err = register_sysrq_key(key, &au_sysrq_op);
88
	if (unlikely(err))
89
		AuErr("err %d, sysrq=%c\n", err, key);
90
	return err;
91
}
92
93
void au_sysrq_fin(void)
94
{
95
	int err;
96
	err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
97
	if (unlikely(err))
98
		AuErr("err %d (ignored)\n", err);
99
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/vdir.c (+934 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * virtual or vertical directory
21
 *
22
 * $Id: vdir.c,v 1.3 2008/04/28 03:05:48 sfjro Exp $
23
 */
24
25
#include "aufs.h"
26
27
static int calc_size(int namelen)
28
{
29
	int sz;
30
31
	sz = sizeof(struct au_vdir_de) + namelen;
32
	if (sizeof(ino_t) == sizeof(long)) {
33
		const int mask = sizeof(ino_t) - 1;
34
		if (sz & mask) {
35
			sz += sizeof(ino_t);
36
			sz &= ~mask;
37
		}
38
	} else {
39
	}
40
41
	AuDebugOn(sz % sizeof(ino_t));
42
	return sz;
43
}
44
45
static int set_deblk_end(union au_vdir_deblk_p *p,
46
			 union au_vdir_deblk_p *deblk_end)
47
{
48
	if (calc_size(0) <= deblk_end->p - p->p) {
49
		p->de->de_str.len = 0;
50
		//smp_mb();
51
		return 0;
52
	}
53
	return -1; /* error */
54
}
55
56
/* returns true or false */
57
static int is_deblk_end(union au_vdir_deblk_p *p,
58
			union au_vdir_deblk_p *deblk_end)
59
{
60
	if (calc_size(0) <= deblk_end->p - p->p)
61
		return !p->de->de_str.len;
62
	return 1;
63
}
64
65
static au_vdir_deblk_t *last_deblk(struct au_vdir *vdir)
66
{
67
	return vdir->vd_deblk[vdir->vd_nblk - 1];
68
}
69
70
void au_nhash_init(struct au_nhash *nhash)
71
{
72
	int i;
73
	for (i = 0; i < AuSize_NHASH; i++)
74
		INIT_HLIST_HEAD(nhash->heads + i);
75
}
76
77
struct au_nhash *au_nhash_new(gfp_t gfp)
78
{
79
	struct au_nhash *nhash;
80
81
	nhash = kmalloc(sizeof(*nhash), gfp);
82
	if (nhash) {
83
		au_nhash_init(nhash);
84
		return nhash;
85
	}
86
	return ERR_PTR(-ENOMEM);
87
}
88
89
void au_nhash_del(struct au_nhash *nhash)
90
{
91
	au_nhash_fin(nhash);
92
	kfree(nhash);
93
}
94
95
void au_nhash_move(struct au_nhash *dst, struct au_nhash *src)
96
{
97
	int i;
98
99
	AuTraceEnter();
100
101
	//DbgWhlist(src);
102
	*dst = *src;
103
	for (i = 0; i < AuSize_NHASH; i++) {
104
		struct hlist_head *h;
105
		h = dst->heads + i;
106
		if (h->first)
107
			h->first->pprev = &h->first;
108
		INIT_HLIST_HEAD(src->heads + i);
109
	}
110
	//DbgWhlist(src);
111
	//DbgWhlist(dst);
112
	//smp_mb();
113
}
114
115
/* ---------------------------------------------------------------------- */
116
117
void au_nhash_fin(struct au_nhash *whlist)
118
{
119
	int i;
120
	struct hlist_head *head;
121
	struct au_vdir_wh *tpos;
122
	struct hlist_node *pos, *n;
123
124
	AuTraceEnter();
125
126
	for (i = 0; i < AuSize_NHASH; i++) {
127
		head = whlist->heads + i;
128
		hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
129
			//hlist_del(pos);
130
			kfree(tpos);
131
		}
132
	}
133
}
134
135
int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
136
			    int limit)
137
{
138
	int n, i;
139
	struct hlist_head *head;
140
	struct au_vdir_wh *tpos;
141
	struct hlist_node *pos;
142
143
	LKTRTrace("limit %d\n", limit);
144
	//return 1;
145
146
	n = 0;
147
	for (i = 0; i < AuSize_NHASH; i++) {
148
		head = whlist->heads + i;
149
		hlist_for_each_entry(tpos, pos, head, wh_hash)
150
			if (tpos->wh_bindex == btgt && ++n > limit)
151
				return 1;
152
	}
153
	return 0;
154
}
155
156
static unsigned int au_name_hash(const unsigned char *name, unsigned int len)
157
{
158
	return (full_name_hash(name, len) % AuSize_NHASH);
159
}
160
161
/* returns found(true) or not */
162
int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int namelen)
163
{
164
	struct hlist_head *head;
165
	struct au_vdir_wh *tpos;
166
	struct hlist_node *pos;
167
	struct au_vdir_destr *str;
168
169
	LKTRTrace("%.*s\n", namelen, name);
170
171
	head = whlist->heads + au_name_hash(name, namelen);
172
	hlist_for_each_entry(tpos, pos, head, wh_hash) {
173
		str = &tpos->wh_str;
174
		LKTRTrace("%.*s\n", str->len, str->name);
175
		if (str->len == namelen && !memcmp(str->name, name, namelen))
176
			return 1;
177
	}
178
	return 0;
179
}
180
181
int au_nhash_append_wh(struct au_nhash *whlist, char *name, int namelen,
182
		       ino_t ino, unsigned int d_type, aufs_bindex_t bindex,
183
		       unsigned char shwh)
184
{
185
	int err;
186
	struct au_vdir_destr *str;
187
	struct au_vdir_wh *wh;
188
189
	LKTRTrace("%.*s\n", namelen, name);
190
191
	err = -ENOMEM;
192
	wh = kmalloc(sizeof(*wh) + namelen, GFP_TEMPORARY);
193
	if (unlikely(!wh))
194
		goto out;
195
	err = 0;
196
	wh->wh_bindex = bindex;
197
	if (unlikely(shwh))
198
		au_shwh_init_wh(wh, ino, d_type);
199
	str = &wh->wh_str;
200
	str->len = namelen;
201
	memcpy(str->name, name, namelen);
202
	hlist_add_head(&wh->wh_hash,
203
		       whlist->heads + au_name_hash(name, namelen));
204
	//smp_mb();
205
206
 out:
207
	AuTraceErr(err);
208
	return err;
209
}
210
211
/* ---------------------------------------------------------------------- */
212
213
void au_vdir_free(struct au_vdir *vdir)
214
{
215
	au_vdir_deblk_t **deblk;
216
217
	AuTraceEnter();
218
219
	deblk = vdir->vd_deblk;
220
	while (vdir->vd_nblk--) {
221
		kfree(*deblk);
222
		deblk++;
223
	}
224
	kfree(vdir->vd_deblk);
225
	au_cache_free_vdir(vdir);
226
}
227
228
static int append_deblk(struct au_vdir *vdir)
229
{
230
	int err, sz, i;
231
	au_vdir_deblk_t **o;
232
	union au_vdir_deblk_p p, deblk_end;
233
234
	AuTraceEnter();
235
236
	err = -ENOMEM;
237
	sz = sizeof(*o) * vdir->vd_nblk;
238
	o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_KERNEL);
239
	if (unlikely(!o))
240
		goto out;
241
	vdir->vd_deblk = o;
242
	p.deblk = kmalloc(sizeof(*p.deblk), GFP_KERNEL);
243
	if (p.deblk) {
244
		i = vdir->vd_nblk++;
245
		vdir->vd_deblk[i] = p.deblk;
246
		vdir->vd_last.i = i;
247
		vdir->vd_last.p.p = p.p;
248
		deblk_end.deblk = p.deblk + 1;
249
		err = set_deblk_end(&p, &deblk_end);
250
		AuDebugOn(err);
251
	}
252
253
 out:
254
	AuTraceErr(err);
255
	return err;
256
}
257
258
static struct au_vdir *alloc_vdir(void)
259
{
260
	struct au_vdir *vdir;
261
	int err;
262
263
	AuTraceEnter();
264
265
	err = -ENOMEM;
266
	vdir = au_cache_alloc_vdir();
267
	if (unlikely(!vdir))
268
		goto out;
269
	vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_KERNEL);
270
	if (unlikely(!vdir->vd_deblk))
271
		goto out_free;
272
273
	vdir->vd_nblk = 0;
274
	vdir->vd_version = 0;
275
	vdir->vd_jiffy = 0;
276
	err = append_deblk(vdir);
277
	if (!err)
278
		return vdir; /* success */
279
280
	kfree(vdir->vd_deblk);
281
282
 out_free:
283
	au_cache_free_vdir(vdir);
284
 out:
285
	vdir = ERR_PTR(err);
286
	AuTraceErrPtr(vdir);
287
	return vdir;
288
}
289
290
static int reinit_vdir(struct au_vdir *vdir)
291
{
292
	int err;
293
	union au_vdir_deblk_p p, deblk_end;
294
295
	AuTraceEnter();
296
297
	while (vdir->vd_nblk > 1) {
298
		kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
299
		vdir->vd_deblk[vdir->vd_nblk - 1] = NULL;
300
		vdir->vd_nblk--;
301
	}
302
	p.deblk = vdir->vd_deblk[0];
303
	deblk_end.deblk = p.deblk + 1;
304
	err = set_deblk_end(&p, &deblk_end);
305
	AuDebugOn(err);
306
	vdir->vd_version = 0;
307
	vdir->vd_jiffy = 0;
308
	vdir->vd_last.i = 0;
309
	vdir->vd_last.p.deblk = vdir->vd_deblk[0];
310
	//smp_mb();
311
	//DbgVdir(vdir);
312
	return err;
313
}
314
315
/* ---------------------------------------------------------------------- */
316
317
static void free_dehlist(struct au_nhash *dehlist)
318
{
319
	int i;
320
	struct hlist_head *head;
321
	struct au_vdir_dehstr *tpos;
322
	struct hlist_node *pos, *n;
323
324
	AuTraceEnter();
325
326
	for (i = 0; i < AuSize_NHASH; i++) {
327
		head = dehlist->heads + i;
328
		hlist_for_each_entry_safe(tpos, pos, n, head, hash) {
329
			//hlist_del(pos);
330
			au_cache_free_dehstr(tpos);
331
		}
332
	}
333
}
334
335
/* returns found(true) or not */
336
static int test_known(struct au_nhash *delist, char *name, int namelen)
337
{
338
	struct hlist_head *head;
339
	struct au_vdir_dehstr *tpos;
340
	struct hlist_node *pos;
341
	struct au_vdir_destr *str;
342
343
	LKTRTrace("%.*s\n", namelen, name);
344
345
	head = delist->heads + au_name_hash(name, namelen);
346
	hlist_for_each_entry(tpos, pos, head, hash) {
347
		str = tpos->str;
348
		LKTRTrace("%.*s\n", str->len, str->name);
349
		if (str->len == namelen && !memcmp(str->name, name, namelen))
350
			return 1;
351
	}
352
	return 0;
353
354
}
355
356
static int append_de(struct au_vdir *vdir, char *name, int namelen, ino_t ino,
357
		     unsigned int d_type, struct au_nhash *delist)
358
{
359
	int err, sz;
360
	union au_vdir_deblk_p p, *room, deblk_end;
361
	struct au_vdir_dehstr *dehstr;
362
363
	LKTRTrace("%.*s %d, i%lu, dt%u\n", namelen, name, namelen, ino, d_type);
364
365
	p.deblk = last_deblk(vdir);
366
	deblk_end.deblk = p.deblk + 1;
367
	room = &vdir->vd_last.p;
368
	AuDebugOn(room->p < p.p || deblk_end.p <= room->p
369
		  || !is_deblk_end(room, &deblk_end));
370
371
	sz = calc_size(namelen);
372
	if (unlikely(sz > deblk_end.p - room->p)) {
373
		err = append_deblk(vdir);
374
		if (unlikely(err))
375
			goto out;
376
		p.deblk = last_deblk(vdir);
377
		deblk_end.deblk = p.deblk + 1;
378
		//smp_mb();
379
		AuDebugOn(room->p != p.p);
380
	}
381
382
	err = -ENOMEM;
383
	dehstr = au_cache_alloc_dehstr();
384
	if (unlikely(!dehstr))
385
		goto out;
386
	dehstr->str = &room->de->de_str;
387
	hlist_add_head(&dehstr->hash,
388
		       delist->heads + au_name_hash(name, namelen));
389
390
	room->de->de_ino = ino;
391
	room->de->de_type = d_type;
392
	room->de->de_str.len = namelen;
393
	memcpy(room->de->de_str.name, name, namelen);
394
395
	err = 0;
396
	room->p += sz;
397
	if (unlikely(set_deblk_end(room, &deblk_end)))
398
		err = append_deblk(vdir);
399
	//smp_mb();
400
401
 out:
402
	AuTraceErr(err);
403
	return err;
404
}
405
406
/* ---------------------------------------------------------------------- */
407
408
static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
409
		  ino_t *ino)
410
{
411
	int err;
412
	struct au_xino_entry xinoe;
413
	static DEFINE_MUTEX(mtx);
414
415
	/* a race condition for hardlinks */
416
	mutex_lock(&mtx);
417
	err = au_xino_read(sb, bindex, h_ino, &xinoe);
418
	if (unlikely(err))
419
		goto out;
420
421
	if (!xinoe.ino) {
422
		//struct inode *h_inode;
423
		err = -EIO;
424
		xinoe.ino = au_xino_new_ino(sb);
425
		if (unlikely(!xinoe.ino))
426
			goto out;
427
		err = au_xino_write(sb, bindex, h_ino, &xinoe);
428
		if (unlikely(err))
429
			goto out;
430
	}
431
432
	*ino = xinoe.ino;
433
434
 out:
435
	mutex_unlock(&mtx);
436
	AuTraceErr(err);
437
	return err;
438
}
439
440
static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
441
		     ino_t *ino)
442
{
443
#ifdef CONFIG_AUFS_SHWH
444
	return au_ino(sb, bindex, h_ino, ino);
445
#else
446
	return 0;
447
#endif
448
}
449
450
#define AuFillVdir_CALLED	1
451
#define AuFillVdir_SHWH		(1 << 1)
452
#define au_ftest_fillvdir(flags, name)	((flags) & AuFillVdir_##name)
453
#define au_fset_fillvdir(flags, name)	{ (flags) |= AuFillVdir_##name; }
454
#define au_fclr_fillvdir(flags, name)	{ (flags) &= ~AuFillVdir_##name; }
455
#ifndef CONFIG_AUFS_SHWH
456
#undef AuFillVdir_SHWH
457
#define AuFillVdir_SHWH		0
458
#endif
459
460
struct fillvdir_arg {
461
	struct file		*file;
462
	struct au_vdir 	*vdir;
463
	struct au_nhash	*delist;
464
	struct au_nhash	*whlist;
465
	aufs_bindex_t		bindex;
466
	unsigned int		flags;
467
	int			err;
468
};
469
470
static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset,
471
		    u64 h_ino, unsigned int d_type)
472
{
473
	struct fillvdir_arg *arg = __arg;
474
	char *name = (void *)__name;
475
	aufs_bindex_t bindex, bend;
476
	struct super_block *sb;
477
	ino_t ino;
478
479
	LKTRTrace("%.*s, namelen %d, i%Lu, dt%u\n",
480
		  namelen, name, namelen, (u64)h_ino, d_type);
481
482
	sb = arg->file->f_dentry->d_sb;
483
	bend = arg->bindex;
484
	arg->err = 0;
485
	au_fset_fillvdir(arg->flags, CALLED);
486
	//smp_mb();
487
	if (namelen <= AUFS_WH_PFX_LEN
488
	    || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
489
		for (bindex = 0; bindex < bend; bindex++)
490
			if (test_known(arg->delist + bindex, name, namelen)
491
			    || au_nhash_test_known_wh(arg->whlist + bindex,
492
						      name, namelen))
493
				goto out; /* already exists or whiteouted */
494
495
		ino = 1; /* why does gcc warns? */
496
		arg->err = au_ino(sb, bend, h_ino, &ino);
497
		if (!arg->err)
498
			arg->err = append_de(arg->vdir, name, namelen, ino,
499
					     d_type, arg->delist + bend);
500
	} else {
501
		name += AUFS_WH_PFX_LEN;
502
		namelen -= AUFS_WH_PFX_LEN;
503
		for (bindex = 0; bindex < bend; bindex++)
504
			if (au_nhash_test_known_wh(arg->whlist + bend, name,
505
						   namelen))
506
				goto out; /* already whiteouted */
507
508
		ino = 1; /* dummy */
509
		if (unlikely(au_ftest_fillvdir(arg->flags, SHWH)))
510
			arg->err = au_wh_ino(sb, bend, h_ino, &ino);
511
		if (!arg->err)
512
			arg->err = au_nhash_append_wh
513
				(arg->whlist + bend, name, namelen, ino, d_type,
514
				 bend, au_ftest_fillvdir(arg->flags, SHWH));
515
	}
516
517
 out:
518
	if (!arg->err)
519
		arg->vdir->vd_jiffy = jiffies;
520
	//smp_mb();
521
	AuTraceErr(arg->err);
522
	return arg->err;
523
}
524
525
static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
526
			  aufs_bindex_t bstart, aufs_bindex_t bend,
527
			  struct au_nhash *_whlist, struct au_nhash *_delist)
528
{
529
#ifdef CONFIG_AUFS_SHWH
530
	int err, i;
531
	struct hlist_head *head;
532
	struct au_vdir_wh *tpos;
533
	struct hlist_node *pos, *n;
534
	char *p, *o;
535
	struct au_nhash *whlist, *delist;
536
	struct au_vdir_destr *destr;
537
	aufs_bindex_t bindex;
538
539
	AuTraceEnter();
540
	AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
541
542
	err = -ENOMEM;
543
	o = p = __getname();
544
	if (unlikely(!p))
545
		goto out;
546
547
	err = 0;
548
	memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
549
	p += AUFS_WH_PFX_LEN;
550
	for (bindex = bstart; !err && bindex <= bend; bindex++) {
551
		whlist = _whlist + bindex;
552
		delist = _delist + bindex;
553
554
		for (i = 0; i < AuSize_NHASH; i++) {
555
			head = whlist->heads + i;
556
			hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
557
				destr = &tpos->wh_str;
558
				memcpy(p, destr->name, destr->len);
559
				err = append_de(vdir, o,
560
						destr->len + AUFS_WH_PFX_LEN,
561
						tpos->wh_ino, tpos->wh_type,
562
						delist);
563
				if (unlikely(err))
564
					break;
565
			}
566
		}
567
	}
568
569
	__putname(o);
570
571
 out:
572
	AuTraceErr(err);
573
	return err;
574
#else
575
	return 0;
576
#endif
577
}
578
579
static int au_do_read_vdir(struct fillvdir_arg *arg)
580
{
581
	int err, dlgt, shwh;
582
	aufs_bindex_t bend, bindex, bstart;
583
	struct super_block *sb;
584
	unsigned int mnt_flags;
585
	struct file *hf;
586
	loff_t offset;
587
588
	AuTraceEnter();
589
590
	err = -ENOMEM;
591
	bend = au_fbend(arg->file);
592
	arg->delist = kmalloc(sizeof(*arg->delist) * (bend + 1), GFP_TEMPORARY);
593
	if (unlikely(!arg->delist))
594
		goto out;
595
	arg->whlist = kmalloc(sizeof(*arg->whlist) * (bend + 1), GFP_TEMPORARY);
596
	if (unlikely(!arg->whlist))
597
		goto out_delist;
598
	err = 0;
599
	for (bindex = 0; bindex <= bend; bindex++) {
600
		au_nhash_init(arg->delist + bindex);
601
		au_nhash_init(arg->whlist + bindex);
602
	}
603
604
	sb = arg->file->f_dentry->d_sb;
605
	mnt_flags = au_mntflags(sb);
606
	dlgt = !!au_opt_test_dlgt(mnt_flags);
607
	arg->flags = 0;
608
	shwh = 0;
609
	if (unlikely(au_opt_test(mnt_flags, SHWH))) {
610
		shwh = 1;
611
		au_fset_fillvdir(arg->flags, SHWH);
612
	}
613
	bstart = au_fbstart(arg->file);
614
	for (bindex = bstart; !err && bindex <= bend; bindex++) {
615
		hf = au_h_fptr(arg->file, bindex);
616
		if (!hf)
617
			continue;
618
619
		offset = vfsub_llseek(hf, 0, SEEK_SET);
620
		err = offset;
621
		if (unlikely(offset))
622
			break;
623
		arg->bindex = bindex;
624
		do {
625
			arg->err = 0;
626
			au_fclr_fillvdir(arg->flags, CALLED);
627
			//smp_mb();
628
			err = vfsub_readdir(hf, fillvdir, arg, dlgt);
629
			if (err >= 0)
630
				err = arg->err;
631
		} while (!err && au_ftest_fillvdir(arg->flags, CALLED));
632
	}
633
634
	if (unlikely(!err && shwh))
635
		err = au_handle_shwh(sb, arg->vdir, bstart, bend, arg->whlist,
636
				     arg->delist);
637
638
	for (bindex = bstart; bindex <= bend; bindex++) {
639
		free_dehlist(arg->delist + bindex);
640
		au_nhash_fin(arg->whlist + bindex);
641
	}
642
	kfree(arg->whlist);
643
644
 out_delist:
645
	kfree(arg->delist);
646
 out:
647
	AuTraceErr(err);
648
	return err;
649
}
650
651
static int read_vdir(struct file *file, int may_read)
652
{
653
	int err, do_read;
654
	struct dentry *dentry;
655
	struct inode *inode;
656
	struct au_vdir *vdir, *allocated;
657
	unsigned long expire;
658
	struct fillvdir_arg arg;
659
	struct super_block *sb;
660
661
	dentry = file->f_dentry;
662
	LKTRTrace("%.*s, may %d\n", AuDLNPair(dentry), may_read);
663
	FiMustWriteLock(file);
664
	inode = dentry->d_inode;
665
	IMustLock(inode);
666
	IiMustWriteLock(inode);
667
	AuDebugOn(!S_ISDIR(inode->i_mode));
668
669
	err = 0;
670
	allocated = NULL;
671
	do_read = 0;
672
	sb = inode->i_sb;
673
	expire = au_sbi(sb)->si_rdcache;
674
	vdir = au_ivdir(inode);
675
	if (!vdir) {
676
		AuDebugOn(au_fvdir_cache(file));
677
		do_read = 1;
678
		vdir = alloc_vdir();
679
		err = PTR_ERR(vdir);
680
		if (IS_ERR(vdir))
681
			goto out;
682
		err = 0;
683
		allocated = vdir;
684
	} else if (may_read
685
		   && (inode->i_version != vdir->vd_version
686
		       || time_after(jiffies, vdir->vd_jiffy + expire))) {
687
		LKTRTrace("iver %Lu, vdver %lu, exp %lu\n",
688
			  inode->i_version, vdir->vd_version,
689
			  vdir->vd_jiffy + expire);
690
		do_read = 1;
691
		err = reinit_vdir(vdir);
692
		if (unlikely(err))
693
			goto out;
694
	}
695
	//AuDbgVdir(vdir); goto out;
696
697
	if (!do_read)
698
		return 0; /* success */
699
700
	arg.file = file;
701
	arg.vdir = vdir;
702
	err = au_do_read_vdir(&arg);
703
	if (!err) {
704
		//file->f_pos = 0;
705
		vdir->vd_version = inode->i_version;
706
		vdir->vd_last.i = 0;
707
		vdir->vd_last.p.deblk = vdir->vd_deblk[0];
708
		if (allocated)
709
			au_set_ivdir(inode, allocated);
710
		//AuDbgVdir(vdir);
711
	} else if (allocated)
712
		au_vdir_free(allocated);
713
714
 out:
715
	AuTraceErr(err);
716
	return err;
717
}
718
719
static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
720
{
721
	int err, i, rerr, n;
722
723
	AuTraceEnter();
724
	AuDebugOn(tgt->vd_nblk != 1);
725
	//AuDbgVdir(tgt);
726
727
	err = -ENOMEM;
728
	if (tgt->vd_nblk < src->vd_nblk) {
729
		au_vdir_deblk_t **p;
730
		p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk,
731
				 sizeof(*p) * src->vd_nblk, GFP_KERNEL);
732
		if (unlikely(!p))
733
			goto out;
734
		tgt->vd_deblk = p;
735
	}
736
737
	tgt->vd_nblk = src->vd_nblk;
738
	n = src->vd_nblk;
739
	memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AuSize_DEBLK);
740
	//tgt->vd_last.i = 0;
741
	//tgt->vd_last.p.deblk = tgt->vd_deblk[0];
742
	tgt->vd_version = src->vd_version;
743
	tgt->vd_jiffy = src->vd_jiffy;
744
745
	for (i = 1; i < n; i++) {
746
		tgt->vd_deblk[i] = kmalloc(AuSize_DEBLK, GFP_KERNEL);
747
		if (tgt->vd_deblk[i])
748
			memcpy(tgt->vd_deblk[i], src->vd_deblk[i],
749
			       AuSize_DEBLK);
750
		else
751
			goto out;
752
	}
753
	//smp_mb();
754
	//AuDbgVdir(tgt);
755
	return 0; /* success */
756
757
 out:
758
	rerr = reinit_vdir(tgt);
759
	BUG_ON(rerr);
760
	AuTraceErr(err);
761
	return err;
762
}
763
764
int au_vdir_init(struct file *file)
765
{
766
	int err;
767
	struct dentry *dentry;
768
	struct inode *inode;
769
	struct au_vdir *vdir_cache, *allocated;
770
771
	dentry = file->f_dentry;
772
	LKTRTrace("%.*s, pos %Ld\n", AuDLNPair(dentry), file->f_pos);
773
	FiMustWriteLock(file);
774
	inode = dentry->d_inode;
775
	IiMustWriteLock(inode);
776
	AuDebugOn(!S_ISDIR(inode->i_mode));
777
778
	err = read_vdir(file, !file->f_pos);
779
	if (unlikely(err))
780
		goto out;
781
	//AuDbgVdir(au_ivdir(inode)); goto out;
782
783
	allocated = NULL;
784
	vdir_cache = au_fvdir_cache(file);
785
	if (!vdir_cache) {
786
		vdir_cache = alloc_vdir();
787
		err = PTR_ERR(vdir_cache);
788
		if (IS_ERR(vdir_cache))
789
			goto out;
790
		allocated = vdir_cache;
791
	} else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
792
		err = reinit_vdir(vdir_cache);
793
		if (unlikely(err))
794
			goto out;
795
	} else
796
		return 0; /* success */
797
	//err = 0; AuDbgVdir(vdir_cache); goto out;
798
799
	err = copy_vdir(vdir_cache, au_ivdir(inode));
800
	if (!err) {
801
		file->f_version = inode->i_version;
802
		if (allocated)
803
			au_set_fvdir_cache(file, allocated);
804
	} else if (allocated)
805
		au_vdir_free(allocated);
806
807
 out:
808
	//au_debug_on();
809
	AuTraceErr(err);
810
	//au_debug_off();
811
	return err;
812
}
813
814
static loff_t calc_offset(struct au_vdir *vdir)
815
{
816
	loff_t offset;
817
	union au_vdir_deblk_p p;
818
819
	p.deblk = vdir->vd_deblk[vdir->vd_last.i];
820
	offset = vdir->vd_last.p.p - p.p;
821
	offset += sizeof(*p.deblk) * vdir->vd_last.i;
822
	return offset;
823
}
824
825
/* returns true or false */
826
static int seek_vdir(struct file *file)
827
{
828
	int valid, i, n;
829
	struct dentry *dentry;
830
	struct au_vdir *vdir_cache;
831
	loff_t offset;
832
	union au_vdir_deblk_p p, deblk_end;
833
834
	dentry = file->f_dentry;
835
	LKTRTrace("%.*s, pos %Ld\n", AuDLNPair(dentry), file->f_pos);
836
	vdir_cache = au_fvdir_cache(file);
837
	AuDebugOn(!vdir_cache);
838
	//AuDbgVdir(vdir_cache);
839
840
	valid = 1;
841
	offset = calc_offset(vdir_cache);
842
	LKTRTrace("offset %Ld\n", offset);
843
	if (file->f_pos == offset)
844
		goto out;
845
846
	vdir_cache->vd_last.i = 0;
847
	vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
848
	if (!file->f_pos)
849
		goto out;
850
851
	valid = 0;
852
	i = file->f_pos / AuSize_DEBLK;
853
	LKTRTrace("i %d\n", i);
854
	if (i >= vdir_cache->vd_nblk)
855
		goto out;
856
857
	n = vdir_cache->vd_nblk;
858
	for (; i < n; i++) {
859
		p.deblk = vdir_cache->vd_deblk[i];
860
		deblk_end.deblk = p.deblk + 1;
861
		offset = i;
862
		offset *= AuSize_DEBLK;
863
		while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
864
			int l;
865
			l = calc_size(p.de->de_str.len);
866
			offset += l;
867
			p.p += l;
868
		}
869
		if (!is_deblk_end(&p, &deblk_end)) {
870
			valid = 1;
871
			vdir_cache->vd_last.i = i;
872
			vdir_cache->vd_last.p = p;
873
			break;
874
		}
875
	}
876
877
 out:
878
	//smp_mb();
879
	AuTraceErr(!valid);
880
	return valid;
881
}
882
883
int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
884
{
885
	int err, l;
886
	struct dentry *dentry;
887
	struct au_vdir *vdir_cache;
888
	struct au_vdir_de *de;
889
	union au_vdir_deblk_p deblk_end;
890
891
	dentry = file->f_dentry;
892
	LKTRTrace("%.*s, pos %Ld\n", AuDLNPair(dentry), file->f_pos);
893
	vdir_cache = au_fvdir_cache(file);
894
	AuDebugOn(!vdir_cache);
895
	//AuDbgVdir(vdir_cache);
896
897
	if (!seek_vdir(file))
898
		return 0;
899
900
	while (1) {
901
		deblk_end.deblk
902
			= vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1;
903
		while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
904
			de = vdir_cache->vd_last.p.de;
905
			LKTRTrace("%.*s, off%Ld, i%lu, dt%d\n",
906
				  de->de_str.len, de->de_str.name,
907
				  file->f_pos, de->de_ino, de->de_type);
908
			err = filldir(dirent, de->de_str.name, de->de_str.len,
909
				      file->f_pos, de->de_ino, de->de_type);
910
			if (unlikely(err)) {
911
				AuTraceErr(err);
912
				//return err;
913
				//todo: ignore the error caused by udba.
914
				return 0;
915
			}
916
917
			l = calc_size(de->de_str.len);
918
			vdir_cache->vd_last.p.p += l;
919
			file->f_pos += l;
920
		}
921
		if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) {
922
			vdir_cache->vd_last.i++;
923
			vdir_cache->vd_last.p.deblk
924
				= vdir_cache->vd_deblk[vdir_cache->vd_last.i];
925
			file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk)
926
				* vdir_cache->vd_last.i;
927
			continue;
928
		}
929
		break;
930
	}
931
932
	//smp_mb();
933
	return 0;
934
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/vfsub.c (+642 lines)
Line 0 Link Here
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
 * sub-routines for VFS
21
 *
22
 * $Id: vfsub.c,v 1.3 2008/05/12 00:29:11 sfjro Exp $
23
 */
24
// I'm going to slightly mad
25
26
#include <linux/uaccess.h>
27
#include "aufs.h"
28
29
/* ---------------------------------------------------------------------- */
30
31
void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign,
32
		     int dlgt, int force_unlink)
33
{
34
	do_vfsub_args_reinit(vargs, ign);
35
	vargs->flags = 0;
36
	if (unlikely(dlgt))
37
		vfsub_fset(vargs->flags, DLGT);
38
	if (force_unlink)
39
		vfsub_fset(vargs->flags, FORCE_UNLINK);
40
}
41
42
/* ---------------------------------------------------------------------- */
43
44
struct file *vfsub_filp_open(const char *path, int oflags, int mode)
45
{
46
	struct file *err;
47
48
	LKTRTrace("%s\n", path);
49
50
	lockdep_off();
51
	err = filp_open(path, oflags, mode);
52
	lockdep_on();
53
	if (!IS_ERR(err))
54
		au_update_fuse_h_inode(err->f_vfsmnt, err->f_dentry); /*ignore*/
55
	return err;
56
}
57
58
int vfsub_path_lookup(const char *name, unsigned int flags,
59
		      struct nameidata *nd)
60
{
61
	int err;
62
63
	LKTRTrace("%s\n", name);
64
65
	/* lockdep_off(); */
66
	err = path_lookup(name, flags, nd);
67
	/* lockdep_on(); */
68
	if (!err)
69
		au_update_fuse_h_inode(nd->path.mnt, nd->path.dentry);
70
	/*ignore*/
71
	return err;
72
}
73
74
struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
75
				    int len)
76
{
77
	struct dentry *d;
78
79
	LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
80
	IMustLock(parent->d_inode);
81
82
	d = lookup_one_len(name, parent, len);
83
	if (!IS_ERR(d))
84
		au_update_fuse_h_inode(NULL, d); /*ignore*/
85
	return d;
86
}
87
88
#ifdef CONFIG_AUFS_LHASH_PATCH
89
struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
90
				  struct nameidata *nd)
91
{
92
	struct dentry *d;
93
94
	LKTRTrace("%.*s/%.*s, nd %d\n",
95
		  AuDLNPair(parent), AuLNPair(name), !!nd);
96
	if (nd)
97
		LKTRTrace("nd{0x%x}\n", nd->flags);
98
	IMustLock(parent->d_inode);
99
100
	d = __lookup_hash(name, parent, nd);
101
	if (!IS_ERR(d))
102
		au_update_fuse_h_inode(NULL, d); /*ignore*/
103
	return d;
104
}
105
#endif
106
107
/* ---------------------------------------------------------------------- */
108
109
int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
110
		    struct nameidata *nd)
111
{
112
	int err;
113
	struct vfsmount *mnt;
114
115
	LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
116
	IMustLock(dir);
117
118
	err = vfs_create(dir, dentry, mode, nd);
119
	if (!err) {
120
		mnt = NULL;
121
		if (nd)
122
			mnt = nd->path.mnt;
123
		/* dir inode is locked */
124
		au_update_fuse_h_inode(mnt, dentry->d_parent); /*ignore*/
125
		au_update_fuse_h_inode(mnt, dentry); /*ignore*/
126
	}
127
	return err;
128
}
129
130
int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
131
		     const char *symname, int mode)
132
{
133
	int err;
134
135
	LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
136
		  dir->i_ino, AuDLNPair(dentry), symname, mode);
137
	IMustLock(dir);
138
139
	err = vfs_symlink(dir, dentry, symname, mode);
140
	if (!err) {
141
		/* dir inode is locked */
142
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
143
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
144
	}
145
	return err;
146
}
147
148
int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
149
		   dev_t dev)
150
{
151
	int err;
152
153
	LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
154
	IMustLock(dir);
155
156
	err = vfs_mknod(dir, dentry, mode, dev);
157
	if (!err) {
158
		/* dir inode is locked */
159
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
160
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
161
	}
162
	return err;
163
}
164
165
int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
166
		  struct dentry *dentry)
167
{
168
	int err;
169
170
	LKTRTrace("%.*s, i%lu, %.*s\n",
171
		  AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
172
	IMustLock(dir);
173
174
	lockdep_off();
175
	err = vfs_link(src_dentry, dir, dentry);
176
	lockdep_on();
177
	if (!err) {
178
		LKTRTrace("src_i %p, dst_i %p\n",
179
			  src_dentry->d_inode, dentry->d_inode);
180
		/* fuse has different memory inode for the same inumber */
181
		au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
182
		/* dir inode is locked */
183
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
184
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
185
	}
186
	return err;
187
}
188
189
int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
190
		    struct inode *dir, struct dentry *dentry)
191
{
192
	int err;
193
194
	LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
195
		  src_dir->i_ino, AuDLNPair(src_dentry),
196
		  dir->i_ino, AuDLNPair(dentry));
197
	IMustLock(dir);
198
	IMustLock(src_dir);
199
200
	lockdep_off();
201
	err = vfs_rename(src_dir, src_dentry, dir, dentry);
202
	lockdep_on();
203
	if (!err) {
204
		/* dir inode is locked */
205
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
206
		au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/
207
		au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
208
	}
209
	return err;
210
}
211
212
int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
213
{
214
	int err;
215
216
	LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
217
	IMustLock(dir);
218
219
	err = vfs_mkdir(dir, dentry, mode);
220
	if (!err) {
221
		/* dir inode is locked */
222
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
223
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
224
	}
225
	return err;
226
}
227
228
int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
229
{
230
	int err;
231
232
	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
233
	IMustLock(dir);
234
235
	lockdep_off();
236
	err = vfs_rmdir(dir, dentry);
237
	lockdep_on();
238
	/* dir inode is locked */
239
	if (!err)
240
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
241
	return err;
242
}
243
244
int do_vfsub_unlink(struct inode *dir, struct dentry *dentry)
245
{
246
	int err;
247
248
	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
249
	IMustLock(dir);
250
251
	/* vfs_unlink() locks inode */
252
	lockdep_off();
253
	err = vfs_unlink(dir, dentry);
254
	lockdep_on();
255
	/* dir inode is locked */
256
	if (!err)
257
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
258
	return err;
259
}
260
261
/* ---------------------------------------------------------------------- */
262
263
ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
264
			loff_t *ppos)
265
{
266
	ssize_t err;
267
268
	LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
269
		  AuDLNPair(file->f_dentry), (unsigned long)count, *ppos);
270
271
	if (0 /*!au_test_nfs(file->f_vfsmnt->mnt_sb)*/)
272
		err = vfs_read(file, ubuf, count, ppos);
273
	else {
274
		lockdep_off();
275
		err = vfs_read(file, ubuf, count, ppos);
276
		lockdep_on();
277
	}
278
	if (err >= 0)
279
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
280
	/*ignore*/
281
	return err;
282
}
283
284
// kernel_read() ??
285
ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
286
			loff_t *ppos)
287
{
288
	ssize_t err;
289
	mm_segment_t oldfs;
290
291
	oldfs = get_fs();
292
	set_fs(KERNEL_DS);
293
	err = do_vfsub_read_u(file, (char __user *)kbuf, count, ppos);
294
	set_fs(oldfs);
295
	return err;
296
}
297
298
ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
299
			 size_t count, loff_t *ppos)
300
{
301
	ssize_t err;
302
303
	LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
304
		  AuDLNPair(file->f_dentry), (unsigned long)count, *ppos);
305
306
	lockdep_off();
307
	err = vfs_write(file, ubuf, count, ppos);
308
	lockdep_on();
309
	if (err >= 0)
310
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
311
	/*ignore*/
312
	return err;
313
}
314
315
ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
316
			 loff_t *ppos)
317
{
318
	ssize_t err;
319
	mm_segment_t oldfs;
320
321
	oldfs = get_fs();
322
	set_fs(KERNEL_DS);
323
	err = do_vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
324
	set_fs(oldfs);
325
	return err;
326
}
327
328
int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
329
{
330
	int err;
331
332
	LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
333
334
	lockdep_off();
335
	err = vfs_readdir(file, filldir, arg);
336
	lockdep_on();
337
	if (err >= 0)
338
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
339
	/*ignore*/
340
	return err;
341
}
342
343
#ifdef CONFIG_AUFS_SPLICE_PATCH
344
long do_vfsub_splice_to(struct file *in, loff_t *ppos,
345
			struct pipe_inode_info *pipe, size_t len,
346
			unsigned int flags)
347
{
348
	long err;
349
350
	LKTRTrace("%.*s, pos %Ld, len %lu, 0x%x\n",
351
		  AuDLNPair(in->f_dentry), *ppos, (unsigned long)len, flags);
352
353
	lockdep_off();
354
	err = vfs_splice_to(in, ppos, pipe, len, flags);
355
	lockdep_on();
356
	if (err >= 0)
357
		au_update_fuse_h_inode(in->f_vfsmnt, in->f_dentry); /*ignore*/
358
	return err;
359
}
360
361
long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
362
			  loff_t *ppos, size_t len, unsigned int flags)
363
{
364
	long err;
365
366
	LKTRTrace("%.*s, pos %Ld, len %lu, 0x%x\n",
367
		  AuDLNPair(out->f_dentry), *ppos, (unsigned long)len, flags);
368
369
	lockdep_off();
370
	err = vfs_splice_from(pipe, out, ppos, len, flags);
371
	lockdep_on();
372
	if (err >= 0)
373
		au_update_fuse_h_inode(out->f_vfsmnt, out->f_dentry); /*ignore*/
374
	return err;
375
}
376
#endif
377
378
/* ---------------------------------------------------------------------- */
379
380
struct au_vfsub_mkdir_args {
381
	int *errp;
382
	struct inode *dir;
383
	struct dentry *dentry;
384
	int mode;
385
	int dlgt;
386
};
387
388
static void au_call_vfsub_mkdir(void *args)
389
{
390
	struct au_vfsub_mkdir_args *a = args;
391
	*a->errp = vfsub_mkdir(a->dir, a->dentry, a->mode, a->dlgt);
392
}
393
394
int vfsub_sio_mkdir(struct inode *dir, struct dentry *dentry, int mode,
395
		    int dlgt)
396
{
397
	int err, do_sio, wkq_err;
398
399
	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
400
401
	do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
402
	if (!do_sio)
403
		err = vfsub_mkdir(dir, dentry, mode, dlgt);
404
	else {
405
		struct au_vfsub_mkdir_args args = {
406
			.errp	= &err,
407
			.dir	= dir,
408
			.dentry	= dentry,
409
			.mode	= mode,
410
			.dlgt	= dlgt
411
		};
412
		wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args, /*dlgt*/0);
413
		if (unlikely(wkq_err))
414
			err = wkq_err;
415
	}
416
417
	AuTraceErr(err);
418
	return err;
419
}
420
421
struct au_vfsub_rmdir_args {
422
	int *errp;
423
	struct inode *dir;
424
	struct dentry *dentry;
425
	struct vfsub_args *vargs;
426
};
427
428
static void au_call_vfsub_rmdir(void *args)
429
{
430
	struct au_vfsub_rmdir_args *a = args;
431
	*a->errp = vfsub_rmdir(a->dir, a->dentry, a->vargs);
432
}
433
434
int vfsub_sio_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
435
{
436
	int err, do_sio, wkq_err;
437
	struct vfsub_args vargs;
438
439
	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
440
441
	vfsub_args_init(&vargs, /*ign*/NULL, dlgt, /*force_unlink*/0);
442
	do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
443
	if (!do_sio)
444
		err = vfsub_rmdir(dir, dentry, &vargs);
445
	else {
446
		struct au_vfsub_rmdir_args args = {
447
			.errp		= &err,
448
			.dir		= dir,
449
			.dentry		= dentry,
450
			.vargs		= &vargs
451
		};
452
		wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args, /*dlgt*/0);
453
		if (unlikely(wkq_err))
454
			err = wkq_err;
455
	}
456
457
	AuTraceErr(err);
458
	return err;
459
}
460
461
/* ---------------------------------------------------------------------- */
462
463
struct notify_change_args {
464
	int *errp;
465
	struct dentry *h_dentry;
466
	struct iattr *ia;
467
	struct vfsub_args *vargs;
468
};
469
470
static void call_notify_change(void *args)
471
{
472
	struct notify_change_args *a = args;
473
	struct inode *h_inode;
474
475
	LKTRTrace("%.*s, ia_valid 0x%x\n",
476
		  AuDLNPair(a->h_dentry), a->ia->ia_valid);
477
	h_inode = a->h_dentry->d_inode;
478
	IMustLock(h_inode);
479
480
	*a->errp = -EPERM;
481
	if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
482
		vfsub_ignore(a->vargs);
483
		lockdep_off();
484
		*a->errp = notify_change(a->h_dentry, a->ia);
485
		lockdep_on();
486
		if (!*a->errp)
487
			au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/
488
		else
489
			vfsub_unignore(a->vargs);
490
	}
491
	AuTraceErr(*a->errp);
492
}
493
494
#ifdef CONFIG_AUFS_DLGT
495
static void vfsub_notify_change_dlgt(struct notify_change_args *args,
496
				     unsigned int flags)
497
{
498
	if (!vfsub_ftest(flags, DLGT))
499
		call_notify_change(args);
500
	else {
501
		int wkq_err;
502
		wkq_err = au_wkq_wait(call_notify_change, args, /*dlgt*/1);
503
		if (unlikely(wkq_err))
504
			*args->errp = wkq_err;
505
	}
506
}
507
#else
508
static void vfsub_notify_change_dlgt(struct notify_change_args *args,
509
				     unsigned int flags)
510
{
511
	call_notify_change(args);
512
}
513
#endif
514
515
int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
516
			struct vfsub_args *vargs)
517
{
518
	int err;
519
	struct notify_change_args args = {
520
		.errp		= &err,
521
		.h_dentry	= dentry,
522
		.ia		= ia,
523
		.vargs		= vargs
524
	};
525
526
	vfsub_notify_change_dlgt(&args, vargs->flags);
527
528
	AuTraceErr(err);
529
	return err;
530
}
531
532
/* ---------------------------------------------------------------------- */
533
534
struct unlink_args {
535
	int *errp;
536
	struct inode *dir;
537
	struct dentry *dentry;
538
	struct vfsub_args *vargs;
539
};
540
541
static void call_unlink(void *args)
542
{
543
	struct unlink_args *a = args;
544
	struct inode *h_inode;
545
	const int stop_sillyrename = (au_test_nfs(a->dentry->d_sb)
546
				      && atomic_read(&a->dentry->d_count) == 1);
547
548
	LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
549
		  AuDLNPair(a->dentry), stop_sillyrename,
550
		  atomic_read(&a->dentry->d_count));
551
	//IMustLock(a->dir);
552
553
	if (!stop_sillyrename)
554
		dget(a->dentry);
555
	h_inode = a->dentry->d_inode;
556
	if (h_inode)
557
		atomic_inc_return(&h_inode->i_count);
558
	*a->errp = do_vfsub_unlink(a->dir, a->dentry);
559
560
	if (!stop_sillyrename)
561
		dput(a->dentry);
562
	if (h_inode)
563
		iput(h_inode);
564
565
	AuTraceErr(*a->errp);
566
}
567
568
/*
569
 * @dir: must be locked.
570
 * @dentry: target dentry.
571
 */
572
int vfsub_unlink(struct inode *dir, struct dentry *dentry,
573
		 struct vfsub_args *vargs)
574
{
575
	int err;
576
	struct unlink_args args = {
577
		.errp	= &err,
578
		.dir	= dir,
579
		.dentry	= dentry,
580
		.vargs	= vargs
581
	};
582
583
	if (!vfsub_ftest(vargs->flags, DLGT)
584
	    && !vfsub_ftest(vargs->flags, FORCE_UNLINK))
585
		call_unlink(&args);
586
	else {
587
		int wkq_err;
588
		wkq_err = au_wkq_wait(call_unlink, &args,
589
				      vfsub_ftest(vargs->flags, DLGT));
590
		if (unlikely(wkq_err))
591
			err = wkq_err;
592
	}
593
594
	return err;
595
}
596
597
/* ---------------------------------------------------------------------- */
598
599
struct statfs_args {
600
	int *errp;
601
	void *arg;
602
	struct kstatfs *buf;
603
};
604
605
static void call_statfs(void *args)
606
{
607
	struct statfs_args *a = args;
608
	*a->errp = vfs_statfs(a->arg, a->buf);
609
}
610
611
#ifdef CONFIG_AUFS_DLGT
612
static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
613
{
614
	if (!dlgt)
615
		call_statfs(args);
616
	else {
617
		int wkq_err;
618
		wkq_err = au_wkq_wait(call_statfs, args, /*dlgt*/1);
619
		if (unlikely(wkq_err))
620
			*args->errp = wkq_err;
621
	}
622
}
623
#else
624
static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
625
{
626
	call_statfs(args);
627
}
628
#endif
629
630
int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
631
{
632
	int err;
633
	struct statfs_args args = {
634
		.errp	= &err,
635
		.arg	= arg,
636
		.buf	= buf
637
	};
638
639
	vfsub_statfs_dlgt(&args, dlgt);
640
641
	return err;
642
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/vfsub.h (+493 lines)
Line 0 Link Here
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
 * sub-routines for VFS
21
 *
22
 * $Id: vfsub.h,v 1.2 2008/04/21 01:49:22 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_VFSUB_H__
26
#define __AUFS_VFSUB_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/namei.h>
32
#include <linux/splice.h>
33
#include <linux/inotify.h>
34
35
/* ---------------------------------------------------------------------- */
36
37
/* vfsub flags */
38
#define Vfsub_DLGT		1		/* operation with delegation */
39
#define Vfsub_FORCE_UNLINK	(1 << 1)	/* force unlinking */
40
#define vfsub_ftest(flags, name)	((flags) & Vfsub_##name)
41
#define vfsub_fset(flags, name)		{ (flags) |= Vfsub_##name; }
42
#define vfsub_fclr(flags, name)		{ (flags) &= ~Vfsub_##name; }
43
#ifndef CONFIG_AUFS_DLGT
44
#undef Vfsub_DLGT
45
#define Vfsub_DLGT	0
46
#endif
47
48
struct au_hin_ignore;
49
struct vfsub_args {
50
#ifdef CONFIG_AUFS_HINOTIFY
51
	/* inotify events to be ignored */
52
	int			nignore;
53
	struct au_hin_ignore	*ignore;
54
#endif
55
56
	unsigned int		flags;
57
};
58
59
struct au_hinode;
60
#ifdef CONFIG_AUFS_HINOTIFY
61
static inline
62
void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign)
63
{
64
	vargs->nignore = 0;
65
	vargs->ignore = ign;
66
}
67
68
static inline void vfsub_args_reinit(struct vfsub_args *vargs)
69
{
70
	vargs->nignore = 0;
71
}
72
73
__u32 vfsub_events_notify_change(struct iattr *ia);
74
void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
75
		      struct au_hinode *hinode);
76
void vfsub_ign_inode(struct vfsub_args *vargs, __u32 events,
77
		     struct inode *inode, struct inode *h_inode);
78
79
void vfsub_ignore(struct vfsub_args *vargs);
80
void vfsub_unignore(struct vfsub_args *vargs);
81
#else
82
static inline
83
void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign)
84
{
85
	/* empty */
86
}
87
88
static inline void vfsub_args_reinit(struct vfsub_args *vargs)
89
{
90
	/* empty */
91
}
92
93
static inline __u32 vfsub_events_notify_change(struct iattr *ia)
94
{
95
	return 0;
96
}
97
98
static inline void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
99
				    struct au_hinode *hinode)
100
{
101
	/* empty */
102
}
103
104
static inline void vfsub_ign_inode(struct vfsub_args *vargs, __u32 events,
105
				   struct inode *inode, struct inode *h_inode)
106
{
107
	/* empty */
108
}
109
110
static inline void vfsub_ignore(struct vfsub_args *vargs)
111
{
112
	/* empty */
113
}
114
115
static inline void vfsub_unignore(struct vfsub_args *vargs)
116
{
117
	/* empty */
118
}
119
#endif /* CONFIG_AUFS_HINOTIFY */
120
121
void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign,
122
		     int dlgt, int force_unlink);
123
124
/* ---------------------------------------------------------------------- */
125
126
/* inotify_inode_watched() is not exported */
127
static inline int au_test_inotify(struct inode *inode)
128
{
129
#ifdef CONFIG_INOTIFY
130
	return !list_empty(&inode->inotify_watches);
131
#endif
132
	return 0;
133
}
134
135
/* ---------------------------------------------------------------------- */
136
137
/* lock subclass for hidden inode */
138
/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
139
// todo: reduce it
140
enum {
141
	AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
142
	AuLsc_I_PARENT,		/* hidden inode, parent first */
143
	AuLsc_I_CHILD,
144
	AuLsc_I_PARENT2,	/* copyup dirs */
145
	AuLsc_I_CHILD2,
146
	AuLsc_I_End
147
};
148
149
#define IMustLock(i)	MtxMustLock(&(i)->i_mutex)
150
151
static inline
152
struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2)
153
{
154
	struct dentry *d;
155
156
	lockdep_off();
157
	d = lock_rename(d1, d2);
158
	lockdep_on();
159
	return d;
160
}
161
162
static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2)
163
{
164
	lockdep_off();
165
	unlock_rename(d1, d2);
166
	lockdep_on();
167
}
168
169
/* ---------------------------------------------------------------------- */
170
171
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
172
/* br_fuse.c */
173
int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry);
174
#else
175
static inline
176
int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry)
177
{
178
	return 0;
179
}
180
#endif
181
182
#ifdef CONFIG_AUFS_BR_XFS
183
/* br_xfs.c */
184
dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
185
		struct dentry *h_dentry);
186
#else
187
static inline
188
dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
189
		struct dentry *h_dentry)
190
{
191
	return h_inode->i_rdev;
192
}
193
#endif
194
195
/* simple abstractions, for future use */
196
static inline
197
int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)
198
{
199
	LKTRTrace("i%lu, mask 0x%x, nd %d\n", inode->i_ino, mask, !!nd);
200
	IMustLock(inode);
201
	return permission(inode, mask, nd);
202
}
203
204
/* ---------------------------------------------------------------------- */
205
206
struct file *vfsub_filp_open(const char *path, int oflags, int mode);
207
int vfsub_path_lookup(const char *name, unsigned int flags,
208
		      struct nameidata *nd);
209
struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
210
				    int len);
211
212
#ifdef CONFIG_AUFS_LHASH_PATCH
213
struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
214
				  struct nameidata *nd);
215
#endif
216
217
/* ---------------------------------------------------------------------- */
218
219
int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
220
		    struct nameidata *nd);
221
int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
222
		     const char *symname, int mode);
223
int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
224
		   dev_t dev);
225
int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
226
		  struct dentry *dentry);
227
int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
228
		    struct inode *dir, struct dentry *dentry);
229
int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode);
230
int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry);
231
int do_vfsub_unlink(struct inode *dir, struct dentry *dentry);
232
233
/* ---------------------------------------------------------------------- */
234
235
ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
236
			loff_t *ppos);
237
// kernel_read() ??
238
ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
239
			loff_t *ppos);
240
ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
241
			 size_t count, loff_t *ppos);
242
ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
243
			 loff_t *ppos);
244
int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
245
246
/* ---------------------------------------------------------------------- */
247
248
#ifdef CONFIG_AUFS_SPLICE_PATCH
249
long do_vfsub_splice_to(struct file *in, loff_t *ppos,
250
			struct pipe_inode_info *pipe, size_t len,
251
			unsigned int flags);
252
long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
253
			  loff_t *ppos, size_t len, unsigned int flags);
254
#else
255
static inline
256
long do_vfsub_splice_to(struct file *in, loff_t *ppos,
257
			struct pipe_inode_info *pipe, size_t len,
258
			unsigned int flags)
259
{
260
	return -ENOSYS;
261
}
262
263
static inline
264
long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
265
			  loff_t *ppos, size_t len, unsigned int flags)
266
{
267
	return -ENOSYS;
268
}
269
#endif /* CONFIG_AUFS_SPLICE_PATCH */
270
271
/* ---------------------------------------------------------------------- */
272
273
static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
274
{
275
	loff_t err;
276
277
	LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
278
279
	lockdep_off();
280
	err = vfs_llseek(file, offset, origin);
281
	lockdep_on();
282
	return err;
283
}
284
285
static inline int do_vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry,
286
				   struct kstat *st)
287
{
288
	LKTRTrace("%.*s\n", AuDLNPair(dentry));
289
	return vfs_getattr(mnt, dentry, st);
290
}
291
292
/* ---------------------------------------------------------------------- */
293
294
#if defined(CONFIG_AUFS_HINOTIFY) || defined(CONFIG_AUFS_DLGT)
295
/* hin_or_dlgt.c */
296
int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
297
		     int dlgt);
298
299
int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
300
		 struct nameidata *nd, int dlgt);
301
int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
302
		  int mode, int dlgt);
303
int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
304
		int dlgt);
305
int vfsub_link(struct dentry *src_dentry, struct inode *dir,
306
	       struct dentry *dentry, int dlgt);
307
int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
308
		 struct inode *dir, struct dentry *dentry,
309
		 struct vfsub_args *vargs);
310
int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt);
311
int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
312
		struct vfsub_args *vargs);
313
314
ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
315
		     loff_t *ppos, int dlgt);
316
ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
317
		     int dlgt);
318
ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
319
		      loff_t *ppos, struct vfsub_args *vargs);
320
ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
321
		      struct vfsub_args *vargs);
322
int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt);
323
long vfsub_splice_to(struct file *in, loff_t *ppos,
324
		     struct pipe_inode_info *pipe, size_t len,
325
		     unsigned int flags, int dlgt);
326
long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
327
		       loff_t *ppos, size_t len, unsigned int flags,
328
		       struct vfsub_args *vargs);
329
330
int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
331
		  int dlgt);
332
#else
333
334
static inline
335
int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
336
		     int dlgt)
337
{
338
	return do_vfsub_permission(inode, mask, nd);
339
}
340
341
static inline
342
int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
343
		 struct nameidata *nd, int dlgt)
344
{
345
	return do_vfsub_create(dir, dentry, mode, nd);
346
}
347
348
static inline
349
int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
350
		  int mode, int dlgt)
351
{
352
	return do_vfsub_symlink(dir, dentry, symname, mode);
353
}
354
355
static inline
356
int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
357
		int dlgt)
358
{
359
	return do_vfsub_mknod(dir, dentry, mode, dev);
360
}
361
362
static inline
363
int vfsub_link(struct dentry *src_dentry, struct inode *dir,
364
	       struct dentry *dentry, int dlgt)
365
{
366
	return do_vfsub_link(src_dentry, dir, dentry);
367
}
368
369
static inline
370
int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
371
		 struct inode *dir, struct dentry *dentry,
372
		 struct vfsub_args *vargs)
373
{
374
	int err;
375
376
	vfsub_ignore(vargs);
377
	err = do_vfsub_rename(src_dir, src_dentry, dir, dentry);
378
	if (unlikely(err))
379
		vfsub_unignore(vargs);
380
	return err;
381
}
382
383
static inline
384
int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt)
385
{
386
	return do_vfsub_mkdir(dir, dentry, mode);
387
}
388
389
static inline
390
int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
391
		struct vfsub_args *vargs)
392
{
393
	int err;
394
395
	vfsub_ignore(vargs);
396
	err = do_vfsub_rmdir(dir, dentry);
397
	if (unlikely(err))
398
		vfsub_unignore(vargs);
399
	return err;
400
}
401
402
static inline
403
ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
404
		     loff_t *ppos, int dlgt)
405
{
406
	return do_vfsub_read_u(file, ubuf, count, ppos);
407
}
408
409
static inline
410
ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
411
		     int dlgt)
412
{
413
	return do_vfsub_read_k(file, kbuf, count, ppos);
414
}
415
416
static inline
417
ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
418
		      loff_t *ppos, struct vfsub_args *vargs)
419
{
420
	int err;
421
422
	vfsub_ignore(vargs);
423
	err = do_vfsub_write_u(file, ubuf, count, ppos);
424
	if (unlikely(err < 0))
425
		vfsub_unignore(vargs);
426
	return err;
427
}
428
429
static inline
430
ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
431
		      struct vfsub_args *vargs)
432
{
433
	int err;
434
435
	vfsub_ignore(vargs);
436
	err = do_vfsub_write_k(file, kbuf, count, ppos);
437
	if (unlikely(err < 0))
438
		vfsub_unignore(vargs);
439
	return err;
440
}
441
442
static inline
443
int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
444
{
445
	return do_vfsub_readdir(file, filldir, arg);
446
}
447
448
static inline
449
long vfsub_splice_to(struct file *in, loff_t *ppos,
450
		     struct pipe_inode_info *pipe, size_t len,
451
		     unsigned int flags, int dlgt)
452
{
453
	return do_vfsub_splice_to(in, ppos, pipe, len, flags);
454
}
455
456
static inline
457
long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
458
		       loff_t *ppos, size_t len, unsigned int flags,
459
		       struct vfsub_args *vargs)
460
{
461
	long err;
462
463
	vfsub_ignore(vargs);
464
	err = do_vfsub_splice_from(pipe, out, ppos, len, flags);
465
	if (unlikely(err < 0))
466
		vfsub_unignore(vargs);
467
	return err;
468
}
469
470
static inline
471
int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
472
		  int dlgt)
473
{
474
	return do_vfsub_getattr(mnt, dentry, st);
475
}
476
#endif /* CONFIG_AUFS_DLGT || CONFIG_AUFS_HINOTIFY */
477
478
/* ---------------------------------------------------------------------- */
479
480
int vfsub_sio_mkdir(struct inode *dir, struct dentry *dentry, int mode,
481
		    int dlgt);
482
int vfsub_sio_rmdir(struct inode *dir, struct dentry *dentry, int dlgt);
483
484
/* ---------------------------------------------------------------------- */
485
486
int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
487
			struct vfsub_args *vargs);
488
int vfsub_unlink(struct inode *dir, struct dentry *dentry,
489
		 struct vfsub_args *vargs);
490
int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt);
491
492
#endif /* __KERNEL__ */
493
#endif /* __AUFS_VFSUB_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/wbr_policy.c (+693 lines)
Line 0 Link Here
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
};
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/whout.c (+1052 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * whiteout for logical deletion and opaque directory
21
 *
22
 * $Id: whout.c,v 1.4 2008/05/12 00:27:58 sfjro Exp $
23
 */
24
25
#include <linux/fs.h>
26
#include <linux/namei.h>
27
//#include <linux/random.h>
28
//#include <linux/security.h>
29
#include "aufs.h"
30
31
#define WH_MASK			S_IRUGO
32
33
/* If a directory contains this file, then it is opaque.  We start with the
34
 * .wh. flag so that it is blocked by lookup.
35
 */
36
static struct qstr diropq_name = {
37
	.name = AUFS_WH_DIROPQ,
38
	.len = sizeof(AUFS_WH_DIROPQ) - 1
39
};
40
41
/*
42
 * generate whiteout name, which is NOT terminated by NULL.
43
 * @name: original d_name.name
44
 * @len: original d_name.len
45
 * @wh: whiteout qstr
46
 * returns zero when succeeds, otherwise error.
47
 * succeeded value as wh->name should be freed by au_wh_name_free().
48
 */
49
int au_wh_name_alloc(const char *name, int len, struct qstr *wh)
50
{
51
	char *p;
52
53
	AuDebugOn(!name || !len || !wh);
54
55
	if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
56
		return -ENAMETOOLONG;
57
58
	wh->len = len + AUFS_WH_PFX_LEN;
59
	p = kmalloc(wh->len, GFP_KERNEL);
60
	wh->name = p;
61
	//if (LktrCond) {kfree(p); wh->name = p = NULL;}
62
	if (p) {
63
		memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
64
		memcpy(p + AUFS_WH_PFX_LEN, name, len);
65
		//smp_mb();
66
		return 0;
67
	}
68
	return -ENOMEM;
69
}
70
71
void au_wh_name_free(struct qstr *wh)
72
{
73
	AuDebugOn(!wh || !wh->name);
74
	kfree(wh->name);
75
#ifdef CONFIG_AUFS_DEBUG
76
	wh->name = NULL;
77
#endif
78
}
79
80
/* ---------------------------------------------------------------------- */
81
82
/*
83
 * test if the @wh_name exists under @h_parent.
84
 * @try_sio specifies the necessary of super-io.
85
 */
86
int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
87
	       struct au_ndx *ndx)
88
{
89
	int err;
90
	struct dentry *wh_dentry;
91
	struct inode *h_dir;
92
	unsigned int flags;
93
94
	LKTRTrace("%.*s/%.*s, ndx{%p, 0x%x}\n", AuDLNPair(h_parent),
95
		  wh_name->len, wh_name->name, ndx->nfsmnt, ndx->flags);
96
	h_dir = h_parent->d_inode;
97
	AuDebugOn(!S_ISDIR(h_dir->i_mode));
98
99
	flags = 0;
100
	if (ndx && ndx->nd) {
101
		flags = ndx->nd->flags;
102
		ndx->nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE);
103
	}
104
105
	if (!try_sio)
106
		wh_dentry = au_lkup_one(wh_name->name, h_parent,
107
					wh_name->len, ndx);
108
	else
109
		wh_dentry = au_sio_lkup_one(wh_name->name, h_parent,
110
					    wh_name->len, ndx);
111
	if (flags)
112
		ndx->nd->flags = flags;
113
	//if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
114
	err = PTR_ERR(wh_dentry);
115
	if (IS_ERR(wh_dentry))
116
		goto out;
117
118
	err = 0;
119
	if (!wh_dentry->d_inode)
120
		goto out_wh; /* success */
121
122
	err = 1;
123
	if (S_ISREG(wh_dentry->d_inode->i_mode))
124
		goto out_wh; /* success */
125
126
	err = -EIO;
127
	AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
128
		AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
129
130
 out_wh:
131
	dput(wh_dentry);
132
 out:
133
	AuTraceErr(err);
134
	return err;
135
}
136
137
/*
138
 * test if the @h_dentry sets opaque or not.
139
 */
140
int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx)
141
{
142
	int err, try_sio;
143
	struct inode *h_dir;
144
145
	LKTRTrace("dentry %.*s\n", AuDLNPair(h_dentry));
146
	h_dir = h_dentry->d_inode;
147
	AuDebugOn(!S_ISDIR(h_dir->i_mode));
148
149
	try_sio = au_test_h_perm_sio(h_dir, MAY_EXEC,
150
				     au_ftest_ndx(ndx->flags, DLGT));
151
	err = au_wh_test(h_dentry, &diropq_name, try_sio, ndx);
152
	AuTraceErr(err);
153
	return err;
154
}
155
156
/*
157
 * returns a negative dentry whose name is unique and temporary.
158
 */
159
struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
160
			     struct au_ndx *ndx)
161
{
162
#define HEX_LEN 4
163
	struct dentry *dentry;
164
	int len, i;
165
	char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
166
		     + HEX_LEN + 1], *name, *p;
167
	static unsigned char cnt;
168
169
	LKTRTrace("hp %.*s, prefix %.*s\n",
170
		  AuDLNPair(h_parent), prefix->len, prefix->name);
171
	AuDebugOn(!h_parent->d_inode);
172
173
	name = defname;
174
	len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
175
	if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
176
		dentry = ERR_PTR(-ENAMETOOLONG);
177
		if (unlikely(len >= PATH_MAX))
178
			goto out;
179
		dentry = ERR_PTR(-ENOMEM);
180
		name = kmalloc(len + 1, GFP_KERNEL);
181
		//if (LktrCond) {kfree(name); name = NULL;}
182
		if (unlikely(!name))
183
			goto out;
184
	}
185
186
	/* doubly whiteout-ed */
187
	memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
188
	p = name + AUFS_WH_PFX_LEN * 2;
189
	memcpy(p, prefix->name, prefix->len);
190
	p += prefix->len;
191
	*p++ = '.';
192
	AuDebugOn(name + len + 1 - p <= HEX_LEN);
193
194
	for (i = 0; i < 3; i++) {
195
		sprintf(p, "%.*d", HEX_LEN, cnt++);
196
		dentry = au_sio_lkup_one(name, h_parent, len, ndx);
197
		//if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
198
		if (IS_ERR(dentry) || !dentry->d_inode)
199
			goto out_name;
200
		dput(dentry);
201
	}
202
	/* AuWarn("could not get random name\n"); */
203
	dentry = ERR_PTR(-EEXIST);
204
	AuDbg("%.*s\n", len, name);
205
	BUG();
206
207
 out_name:
208
	if (unlikely(name != defname))
209
		kfree(name);
210
 out:
211
	AuTraceErrPtr(dentry);
212
	return dentry;
213
#undef HEX_LEN
214
}
215
216
/*
217
 * rename the @dentry of @bindex to the whiteouted temporary name.
218
 */
219
int au_whtmp_ren(struct inode *dir, struct dentry *dentry, aufs_bindex_t bindex,
220
		 int noself)
221
{
222
	int err, dlgt;
223
	struct inode *h_dir;
224
	struct dentry *h_dentry, *h_parent, *tmp_dentry;
225
	struct super_block *sb;
226
	unsigned int mnt_flags;
227
	struct au_hin_ignore ign;
228
	struct vfsub_args vargs;
229
	struct au_ndx ndx = {
230
		.flags	= 0,
231
		.nd	= NULL,
232
		//.br	= NULL
233
	};
234
235
	LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
236
	h_dentry = au_h_dptr(dentry, bindex);
237
	AuDebugOn(!h_dentry || !h_dentry->d_inode);
238
	h_parent = h_dentry->d_parent; /* dir inode is locked */
239
	h_dir = h_parent->d_inode;
240
	IMustLock(h_dir);
241
242
	sb = dentry->d_sb;
243
	mnt_flags = au_mntflags(sb);
244
	dlgt = !!au_opt_test_dlgt(mnt_flags);
245
	if (unlikely(dlgt))
246
		au_fset_ndx(ndx.flags, DLGT);
247
	ndx.nfsmnt = au_nfsmnt(sb, bindex);
248
	tmp_dentry = au_whtmp_lkup(h_parent, &h_dentry->d_name, &ndx);
249
	//if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
250
	err = PTR_ERR(tmp_dentry);
251
	if (!IS_ERR(tmp_dentry)) {
252
		/* under the same dir, no need to lock_rename() */
253
		vfsub_args_init(&vargs, &ign, dlgt, 0);
254
		AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
255
		if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY) && !noself))
256
			vfsub_ign_hinode(&vargs, IN_MOVE_SELF,
257
					 au_hi(dentry->d_inode, bindex));
258
		err = vfsub_rename(h_dir, h_dentry, h_dir, tmp_dentry, &vargs);
259
		//if (LktrCond) err = -1; //unavailable
260
		AuTraceErr(err);
261
		dput(tmp_dentry);
262
	}
263
264
	AuTraceErr(err);
265
	return err;
266
}
267
268
/* ---------------------------------------------------------------------- */
269
270
static int do_unlink_wh(struct inode *h_dir, struct dentry *wh_dentry,
271
			struct inode *dir, int dlgt)
272
{
273
	struct vfsub_args vargs;
274
275
	LKTRTrace("hi%lu, wh %.*s\n", h_dir->i_ino, AuDLNPair(wh_dentry));
276
	AuDebugOn(!wh_dentry->d_inode || !S_ISREG(wh_dentry->d_inode->i_mode));
277
278
	/*
279
	 * forces superio when the dir has a sticky bit.
280
	 * this may be a violation of unix fs semantics.
281
	 */
282
	vfsub_args_init(&vargs, NULL, dlgt,
283
			(h_dir->i_mode & S_ISVTX)
284
			&& wh_dentry->d_inode->i_uid != current->fsuid);
285
	return vfsub_unlink(h_dir, wh_dentry, &vargs);
286
}
287
288
int au_wh_unlink_dentry(struct inode *h_dir, struct dentry *wh_dentry,
289
			struct dentry *dentry, struct inode *dir, int dlgt)
290
{
291
	int err;
292
293
	LKTRTrace("hi%lu, wh %.*s, d %p\n", h_dir->i_ino,
294
		  AuDLNPair(wh_dentry), dentry);
295
	AuDebugOn((dentry && au_dbwh(dentry) < 0)
296
		  || !wh_dentry->d_inode
297
		  || !S_ISREG(wh_dentry->d_inode->i_mode));
298
299
	err = do_unlink_wh(h_dir, wh_dentry, dir, dlgt);
300
	//if (LktrCond) err = -1; // unavailable
301
	if (!err && dentry)
302
		au_set_dbwh(dentry, -1);
303
304
	AuTraceErr(err);
305
	return err;
306
}
307
308
static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
309
			  struct inode *dir, struct au_ndx *ndx)
310
{
311
	int err;
312
	struct inode *h_dir;
313
	struct dentry *h_dentry;
314
315
	LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(wh));
316
	h_dir = h_parent->d_inode;
317
318
	/* au_test_h_perm() is already done */
319
	h_dentry = au_lkup_one(wh->name, h_parent, wh->len, ndx);
320
	//if (LktrCond) {dput(h_dentry); h_dentry = ERR_PTR(-1);}
321
	if (!IS_ERR(h_dentry)) {
322
		err = 0;
323
		if (h_dentry->d_inode && S_ISREG(h_dentry->d_inode->i_mode))
324
			err = do_unlink_wh(h_dir, h_dentry, dir,
325
					   au_ftest_ndx(ndx->flags, DLGT));
326
		dput(h_dentry);
327
	} else
328
		err = PTR_ERR(h_dentry);
329
330
	AuTraceErr(err);
331
	return err;
332
}
333
334
/* ---------------------------------------------------------------------- */
335
336
static void clean_wh(struct inode *h_dir, struct dentry *wh)
337
{
338
	int err;
339
	struct vfsub_args vargs;
340
341
	AuTraceEnter();
342
343
	if (wh->d_inode) {
344
		vfsub_args_init(&vargs, NULL, 0, 0);
345
		err = vfsub_unlink(h_dir, wh, &vargs);
346
		if (unlikely(err))
347
			AuWarn("failed unlink %.*s (%d), ignored.\n",
348
			       AuDLNPair(wh), err);
349
	}
350
}
351
352
static void clean_plink(struct inode *h_dir, struct dentry *plink)
353
{
354
	int err;
355
	struct vfsub_args vargs;
356
357
	AuTraceEnter();
358
359
	if (plink->d_inode) {
360
		vfsub_args_init(&vargs, NULL, 0, 0);
361
		err = vfsub_rmdir(h_dir, plink, &vargs);
362
		if (unlikely(err))
363
			AuWarn("failed rmdir %.*s (%d), ignored.\n",
364
			       AuDLNPair(plink), err);
365
	}
366
}
367
368
static int test_linkable(struct inode *h_dir)
369
{
370
	if (h_dir->i_op && h_dir->i_op->link)
371
		return 0;
372
	return -ENOSYS;
373
}
374
375
static int plink_dir(struct inode *h_dir, struct dentry *plink)
376
{
377
	int err;
378
379
	err = -EEXIST;
380
	if (!plink->d_inode) {
381
		int mode = S_IRWXU;
382
		if (unlikely(au_test_nfs(plink->d_sb)))
383
			mode |= S_IXUGO;
384
		err = vfsub_mkdir(h_dir, plink, mode, /*dlgt*/0);
385
	} else if (S_ISDIR(plink->d_inode->i_mode))
386
		err = 0;
387
	else
388
		AuErr("unknown %.*s exists\n", AuDLNPair(plink));
389
390
	return err;
391
}
392
393
/*
394
 * initialize the whiteout base file/dir for @br.
395
 */
396
int au_wh_init(struct dentry *h_root, struct au_branch *br,
397
	       struct vfsmount *nfsmnt, struct super_block *sb)
398
{
399
	int err;
400
	struct dentry *wh, *plink;
401
	struct inode *h_dir;
402
	static struct qstr base_name[] = {
403
		{
404
			.name	= AUFS_WH_BASENAME,
405
			.len	= sizeof(AUFS_WH_BASENAME) - 1
406
		},
407
		{
408
			.name	= AUFS_WH_PLINKDIR,
409
			.len	= sizeof(AUFS_WH_PLINKDIR) - 1
410
		}
411
	};
412
	struct au_ndx ndx = {
413
		.nfsmnt	= nfsmnt,
414
		.flags	= 0, /* always no dlgt */
415
		.nd	= NULL,
416
		//.br	= NULL
417
	};
418
	const int do_plink = au_opt_test(au_mntflags(sb), PLINK);
419
420
	LKTRTrace("nfsmnt %p\n", nfsmnt);
421
	BrWhMustWriteLock(br);
422
	SiMustWriteLock(sb);
423
	h_dir = h_root->d_inode;
424
425
	/* doubly whiteouted */
426
	wh = au_wh_lkup(h_root, base_name + 0, &ndx);
427
	//if (LktrCond) {dput(wh); wh = ERR_PTR(-1);}
428
	err = PTR_ERR(wh);
429
	if (IS_ERR(wh))
430
		goto out;
431
	AuDebugOn(br->br_wh && br->br_wh != wh);
432
433
	plink = au_wh_lkup(h_root, base_name + 1, &ndx);
434
	err = PTR_ERR(plink);
435
	if (IS_ERR(plink))
436
		goto out_dput_wh;
437
	AuDebugOn(br->br_plink && br->br_plink != plink);
438
439
	dput(br->br_wh);
440
	dput(br->br_plink);
441
	br->br_wh = NULL;
442
	br->br_plink = NULL;
443
444
	err = 0;
445
	switch (br->br_perm) {
446
	case AuBr_RR:
447
	case AuBr_RO:
448
	case AuBr_RRWH:
449
	case AuBr_ROWH:
450
		clean_wh(h_dir, wh);
451
		clean_plink(h_dir, plink);
452
		break;
453
454
	case AuBr_RWNoLinkWH:
455
		clean_wh(h_dir, wh);
456
		if (do_plink) {
457
			err = test_linkable(h_dir);
458
			if (unlikely(err))
459
				goto out_nolink;
460
461
			err = plink_dir(h_dir, plink);
462
			if (unlikely(err))
463
				goto out_err;
464
			br->br_plink = dget(plink);
465
		} else
466
			clean_plink(h_dir, plink);
467
		break;
468
469
	case AuBr_RW:
470
		/*
471
		 * for the moment, aufs supports the branch filesystem
472
		 * which does not support link(2).
473
		 * testing on FAT which does not support i_op->setattr() fully
474
		 * either, copyup failed.
475
		 * finally, such filesystem will not be used as the writable
476
		 * branch.
477
		 */
478
		err = test_linkable(h_dir);
479
		if (unlikely(err))
480
			goto out_nolink;
481
482
		err = -EEXIST;
483
		if (!wh->d_inode)
484
			err = au_h_create(h_dir, wh, WH_MASK, /*dlgt*/0,
485
					  /*nd*/NULL, nfsmnt);
486
		else if (S_ISREG(wh->d_inode->i_mode))
487
			err = 0;
488
		else
489
			AuErr("unknown %.*s/%.*s exists\n",
490
			      AuDLNPair(h_root), AuDLNPair(wh));
491
		if (unlikely(err))
492
			goto out_err;
493
494
		if (do_plink) {
495
			err = plink_dir(h_dir, plink);
496
			if (unlikely(err))
497
				goto out_err;
498
			br->br_plink = dget(plink);
499
		} else
500
			clean_plink(h_dir, plink);
501
		br->br_wh = dget(wh);
502
		break;
503
504
	default:
505
		BUG();
506
	}
507
508
 out_dput:
509
	dput(plink);
510
 out_dput_wh:
511
	dput(wh);
512
 out:
513
	AuTraceErr(err);
514
	return err;
515
 out_nolink:
516
	AuErr("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
517
	      AuDLNPair(h_root));
518
	goto out_dput;
519
 out_err:
520
	AuErr("an error(%d) on the writable branch %.*s(%s)\n",
521
	      err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
522
	goto out_dput;
523
}
524
525
struct reinit_br_wh {
526
	struct super_block *sb;
527
	struct au_branch *br;
528
};
529
530
static void reinit_br_wh(void *arg)
531
{
532
	int err;
533
	struct reinit_br_wh *a = arg;
534
	struct inode *h_dir, *dir;
535
	struct dentry *h_root;
536
	aufs_bindex_t bindex;
537
	struct vfsub_args vargs;
538
539
	AuTraceEnter();
540
	AuDebugOn(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
541
542
	err = 0;
543
	/* big aufs lock */
544
	si_write_lock(a->sb);
545
	if (unlikely(!au_br_writable(a->br->br_perm)))
546
		goto out;
547
	bindex = au_br_index(a->sb, a->br->br_id);
548
	if (unlikely(bindex < 0))
549
		goto out;
550
551
	dir = a->sb->s_root->d_inode;
552
	h_root = dget_parent(a->br->br_wh);
553
	h_dir = h_root->d_inode;
554
	AuDebugOn(!h_dir->i_op || !h_dir->i_op->link);
555
	vfsub_args_init(&vargs, NULL, /*dlgt*/0, 0);
556
	au_hdir_lock(h_dir, dir, bindex);
557
	br_wh_write_lock(a->br);
558
	err = vfsub_unlink(h_dir, a->br->br_wh, &vargs);
559
	//if (LktrCond) err = -1;
560
	dput(a->br->br_wh);
561
	a->br->br_wh = NULL;
562
	if (!err)
563
		err = au_wh_init(h_root, a->br, au_do_nfsmnt(a->br->br_mnt),
564
				 a->sb);
565
	br_wh_write_unlock(a->br);
566
	au_hdir_unlock(h_dir, dir, bindex);
567
	dput(h_root);
568
569
 out:
570
	atomic_dec_return(&a->br->br_wh_running);
571
	au_br_put(a->br);
572
	si_write_unlock(a->sb);
573
	kfree(arg);
574
	if (unlikely(err))
575
		AuIOErr("err %d\n", err);
576
}
577
578
static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
579
{
580
	int do_dec, wkq_err;
581
	struct reinit_br_wh *arg;
582
583
	do_dec = 1;
584
	if (atomic_inc_return(&br->br_wh_running) != 1)
585
		goto out;
586
587
	/* ignore ENOMEM */
588
	arg = kmalloc(sizeof(*arg), GFP_TEMPORARY);
589
	if (arg) {
590
		/*
591
		 * dec(wh_running), kfree(arg) and au_br_put()
592
		 * in reinit function
593
		 */
594
		arg->sb = sb;
595
		arg->br = br;
596
		au_br_get(br);
597
		wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*dlgt*/0);
598
		if (unlikely(wkq_err)) {
599
			atomic_dec_return(&br->br_wh_running);
600
			au_br_put(br);
601
			kfree(arg);
602
		}
603
		do_dec = 0;
604
	}
605
606
 out:
607
	if (do_dec)
608
		atomic_dec_return(&br->br_wh_running);
609
}
610
611
/*
612
 * create the whiteout @wh.
613
 */
614
static int link_or_create_wh(struct dentry *wh, struct super_block *sb,
615
			     aufs_bindex_t bindex, struct inode *dir)
616
{
617
	int err, dlgt;
618
	struct au_branch *br;
619
	struct dentry *h_parent;
620
	struct inode *h_dir;
621
622
	LKTRTrace("%.*s\n", AuDLNPair(wh));
623
	SiMustReadLock(sb);
624
	h_parent = wh->d_parent; /* dir inode is locked */
625
	h_dir = h_parent->d_inode;
626
	IMustLock(h_dir);
627
628
	dlgt = !!au_opt_test_dlgt(au_mntflags(sb));
629
	br = au_sbr(sb, bindex);
630
	br_wh_read_lock(br);
631
	if (br->br_wh) {
632
		err = vfsub_link(br->br_wh, h_dir, wh, dlgt);
633
		if (!err || err != -EMLINK)
634
			goto out;
635
636
		/* link count full. re-initialize br_wh. */
637
		kick_reinit_br_wh(sb, br);
638
	}
639
640
	/* return this error in this context */
641
	err = au_h_create(h_dir, wh, WH_MASK, dlgt, /*nd*/NULL,
642
			  au_do_nfsmnt(br->br_mnt));
643
644
 out:
645
	br_wh_read_unlock(br);
646
	AuTraceErr(err);
647
	return err;
648
}
649
650
/* ---------------------------------------------------------------------- */
651
652
/*
653
 * create or remove the diropq.
654
 */
655
static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
656
				unsigned int flags)
657
{
658
	struct dentry *opq_dentry, *h_dentry;
659
	struct inode *h_dir;
660
	int err, dlgt;
661
	struct super_block *sb;
662
	struct au_ndx ndx = {
663
		.flags	= 0,
664
		.nd	= NULL,
665
		//.br	= NULL
666
	};
667
668
	LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
669
		  AuDLNPair(dentry), bindex, flags);
670
	h_dentry = au_h_dptr(dentry, bindex);
671
	AuDebugOn(!h_dentry);
672
	h_dir = h_dentry->d_inode;
673
	AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode));
674
675
	/* already checked by au_test_h_perm(). */
676
	sb = dentry->d_sb;
677
	ndx.nfsmnt = au_nfsmnt(sb, bindex);
678
	dlgt = 0;
679
	if (unlikely(au_ftest_diropq(flags, DLGT))) {
680
		dlgt = 1;
681
		au_fset_ndx(ndx.flags, DLGT);
682
	}
683
	opq_dentry = au_lkup_one(diropq_name.name, h_dentry, diropq_name.len,
684
				 &ndx);
685
	//if (LktrCond) {dput(opq_dentry); opq_dentry = ERR_PTR(-1);}
686
	if (IS_ERR(opq_dentry))
687
		goto out;
688
689
	if (au_ftest_diropq(flags, CREATE)) {
690
		AuDebugOn(opq_dentry->d_inode);
691
		err = link_or_create_wh(opq_dentry, sb, bindex,
692
					dentry->d_inode);
693
		//if (LktrCond) {vfs_unlink(h_dir, opq_dentry); err = -1;}
694
		if (!err) {
695
			au_set_dbdiropq(dentry, bindex);
696
			goto out; /* success */
697
		}
698
	} else {
699
		AuDebugOn(/* !S_ISDIR(dentry->d_inode->i_mode)
700
			   * ||  */!opq_dentry->d_inode);
701
		err = do_unlink_wh(h_dir, opq_dentry, dentry->d_inode, dlgt);
702
		//if (LktrCond) err = -1;
703
		if (!err)
704
			au_set_dbdiropq(dentry, -1);
705
	}
706
	dput(opq_dentry);
707
	opq_dentry = ERR_PTR(err);
708
709
 out:
710
	AuTraceErrPtr(opq_dentry);
711
	return opq_dentry;
712
}
713
714
struct do_diropq_args {
715
	struct dentry **errp;
716
	struct dentry *dentry;
717
	aufs_bindex_t bindex;
718
	unsigned int flags;
719
};
720
721
static void call_do_diropq(void *args)
722
{
723
	struct do_diropq_args *a = args;
724
	*a->errp = do_diropq(a->dentry, a->bindex, a->flags);
725
}
726
727
struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
728
			     unsigned int flags)
729
{
730
	struct dentry *diropq, *h_dentry;
731
732
	LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
733
		  AuDLNPair(dentry), bindex, flags);
734
735
	h_dentry = au_h_dptr(dentry, bindex);
736
	if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE,
737
				au_ftest_diropq(flags, DLGT)))
738
		diropq = do_diropq(dentry, bindex, flags);
739
	else {
740
		int wkq_err;
741
		struct do_diropq_args args = {
742
			.errp		= &diropq,
743
			.dentry		= dentry,
744
			.bindex		= bindex,
745
			.flags		= flags
746
		};
747
		wkq_err = au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
748
		if (unlikely(wkq_err))
749
			diropq = ERR_PTR(wkq_err);
750
	}
751
752
	AuTraceErrPtr(diropq);
753
	return diropq;
754
}
755
756
/* ---------------------------------------------------------------------- */
757
758
/*
759
 * lookup whiteout dentry.
760
 * @h_parent: hidden parent dentry which must exist and be locked
761
 * @base_name: name of dentry which will be whiteouted
762
 * returns dentry for whiteout.
763
 */
764
struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
765
			  struct au_ndx *ndx)
766
{
767
	int err;
768
	struct qstr wh_name;
769
	struct dentry *wh_dentry;
770
771
	LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(base_name));
772
773
	err = au_wh_name_alloc(base_name->name, base_name->len, &wh_name);
774
	//if (LktrCond) {au_wh_name_free(&wh_name); err = -1;}
775
	wh_dentry = ERR_PTR(err);
776
	if (!err) {
777
		/* do not superio. */
778
		wh_dentry = au_lkup_one(wh_name.name, h_parent,
779
					wh_name.len, ndx);
780
		au_wh_name_free(&wh_name);
781
	}
782
	AuTraceErrPtr(wh_dentry);
783
	return wh_dentry;
784
}
785
786
/*
787
 * link/create a whiteout for @dentry on @bindex.
788
 */
789
struct dentry *au_wh_create(struct inode *dir, struct dentry *dentry,
790
			    aufs_bindex_t bindex, struct dentry *h_parent,
791
			    struct au_ndx *ndx)
792
{
793
	struct dentry *wh_dentry;
794
	int err;
795
	struct super_block *sb;
796
797
	LKTRTrace("%.*s/%.*s on b%d\n", AuDLNPair(h_parent),
798
		  AuDLNPair(dentry), bindex);
799
800
	sb = dentry->d_sb;
801
	wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, ndx);
802
	//au_nfsmnt(sb, bindex), need_dlgt(sb));
803
	//if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
804
	if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
805
		err = link_or_create_wh(wh_dentry, sb, bindex, dir);
806
		if (!err)
807
			au_set_dbwh(dentry, bindex);
808
		else {
809
			dput(wh_dentry);
810
			wh_dentry = ERR_PTR(err);
811
		}
812
	}
813
814
	AuTraceErrPtr(wh_dentry);
815
	return wh_dentry;
816
}
817
818
/* ---------------------------------------------------------------------- */
819
820
/* Delete all whiteouts in this directory on branch bindex. */
821
static int del_wh_children(struct au_nhash *whlist, struct dentry *h_parent,
822
			   aufs_bindex_t bindex, struct inode *inode,
823
			   struct au_ndx *ndx)
824
{
825
	int err, i;
826
	struct qstr wh_name;
827
	char *p;
828
	struct inode *h_dir;
829
	struct hlist_head *head;
830
	struct au_vdir_wh *tpos;
831
	struct hlist_node *pos;
832
	struct au_vdir_destr *str;
833
834
	LKTRTrace("%.*s\n", AuDLNPair(h_parent));
835
	h_dir = h_parent->d_inode;
836
	AuDebugOn(IS_RDONLY(h_dir));
837
	//SiMustReadLock(??);
838
839
	err = -ENOMEM;
840
	p = __getname();
841
	wh_name.name = p;
842
	//if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
843
	if (unlikely(!wh_name.name))
844
		goto out;
845
	memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
846
	p += AUFS_WH_PFX_LEN;
847
848
	/* already checked by au_test_h_perm(). */
849
	err = 0;
850
	for (i = 0; !err && i < AuSize_NHASH; i++) {
851
		head = whlist->heads + i;
852
		hlist_for_each_entry(tpos, pos, head, wh_hash) {
853
			if (tpos->wh_bindex != bindex)
854
				continue;
855
			str = &tpos->wh_str;
856
			if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
857
				memcpy(p, str->name, str->len);
858
				wh_name.len = AUFS_WH_PFX_LEN + str->len;
859
				err = unlink_wh_name(h_parent, &wh_name, inode,
860
						     ndx);
861
				//if (LktrCond) err = -1;
862
				if (!err)
863
					continue;
864
				break;
865
			}
866
			AuIOErr("whiteout name too long %.*s\n",
867
				str->len, str->name);
868
			err = -EIO;
869
			break;
870
		}
871
	}
872
	__putname(wh_name.name);
873
874
 out:
875
	AuTraceErr(err);
876
	return err;
877
}
878
879
struct del_wh_children_args {
880
	int *errp;
881
	struct au_nhash *whlist;
882
	struct dentry *h_parent;
883
	aufs_bindex_t bindex;
884
	struct inode *inode;
885
	struct au_ndx *ndx;
886
};
887
888
static void call_del_wh_children(void *args)
889
{
890
	struct del_wh_children_args *a = args;
891
	*a->errp = del_wh_children(a->whlist, a->h_parent, a->bindex,
892
				   a->inode, a->ndx);
893
}
894
895
/* ---------------------------------------------------------------------- */
896
897
/*
898
 * rmdir the whiteouted temporary named dir @h_dentry.
899
 * @whlist: whiteouted children.
900
 */
901
int au_whtmp_rmdir(struct dentry *h_dentry, struct au_nhash *whlist,
902
		   aufs_bindex_t bindex, struct inode *dir, struct inode *inode,
903
		   int noself)
904
{
905
	int err, dlgt;
906
	struct inode *h_inode, *h_dir;
907
	struct super_block *sb;
908
	unsigned int mnt_flags;
909
	struct au_hin_ignore ign;
910
	struct vfsub_args vargs;
911
	struct au_ndx ndx = {
912
		.flags	= 0,
913
		.nd	= NULL,
914
		//.br	= NULL
915
	};
916
917
	LKTRTrace("hd %.*s, b%d, i%lu\n",
918
		  AuDLNPair(h_dentry), bindex, dir->i_ino);
919
	IMustLock(dir);
920
	IiMustAnyLock(dir);
921
	h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
922
	IMustLock(h_dir);
923
924
	sb = inode->i_sb;
925
	mnt_flags = au_mntflags(sb);
926
	dlgt = !!au_opt_test_dlgt(mnt_flags);
927
	if (unlikely(dlgt))
928
		au_fset_ndx(ndx.flags, DLGT);
929
	ndx.nfsmnt = au_nfsmnt(sb, bindex);
930
	h_inode = h_dentry->d_inode;
931
	AuDebugOn(h_inode != au_h_iptr(inode, bindex));
932
	au_hdir2_lock(h_inode, inode, bindex);
933
934
	/*
935
	 * someone else might change some whiteouts while we were sleeping.
936
	 * it means this whlist may have an obsoleted entry.
937
	 */
938
	if (!au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_WRITE, dlgt))
939
		err = del_wh_children(whlist, h_dentry, bindex, inode, &ndx);
940
	else {
941
		int wkq_err;
942
		/* ugly */
943
		unsigned int flags = ndx.flags;
944
		struct del_wh_children_args args = {
945
			.errp		= &err,
946
			.whlist		= whlist,
947
			.h_parent	= h_dentry,
948
			.bindex		= bindex,
949
			.inode		= inode,
950
			.ndx		= &ndx
951
		};
952
953
		ndx.flags = 0;
954
		wkq_err = au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
955
		if (unlikely(wkq_err))
956
			err = wkq_err;
957
		ndx.flags = flags;
958
	}
959
	au_hdir_unlock(h_inode, inode, bindex);
960
961
	if (!err) {
962
		vfsub_args_init(&vargs, &ign, dlgt, 0);
963
		if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY) && !noself))
964
			vfsub_ign_hinode(&vargs, IN_DELETE_SELF,
965
					 au_hi(inode, bindex));
966
		err = vfsub_rmdir(h_dir, h_dentry, &vargs);
967
		//d_drop(h_dentry);
968
		//if (LktrCond) err = -1;
969
	}
970
971
	if (!err) {
972
		if (au_ibstart(dir) == bindex) {
973
			au_cpup_attr_timesizes(dir);
974
			//au_cpup_attr_nlink(dir);
975
			drop_nlink(dir);
976
		}
977
		return 0; /* success */
978
	}
979
980
	AuWarn("failed removing %.*s(%d), ignored\n", AuDLNPair(h_dentry), err);
981
	return err;
982
}
983
984
static void au_whtmp_rmdir_free_args(struct au_whtmp_rmdir_args *args)
985
{
986
	dput(args->h_dentry);
987
	au_nhash_fin(&args->whlist);
988
	iput(args->inode);
989
	mutex_unlock(&args->dir->i_mutex);
990
	iput(args->dir);
991
	kfree(args);
992
}
993
994
static void do_rmdir_whtmp(void *args)
995
{
996
	int err;
997
	struct au_whtmp_rmdir_args *a = args;
998
	struct super_block *sb;
999
1000
	LKTRTrace("%.*s, b%d, dir i%lu\n",
1001
		  AuDLNPair(a->h_dentry), a->bindex, a->dir->i_ino);
1002
1003
	mutex_lock(&a->dir->i_mutex);
1004
	sb = a->dir->i_sb;
1005
	//AuDbgSleep(3);
1006
	si_noflush_read_lock(sb);
1007
	err = au_test_ro(sb, a->bindex, NULL);
1008
	if (!err) {
1009
		struct dentry *h_parent = dget_parent(a->h_dentry);
1010
		struct inode *h_dir = h_parent->d_inode;
1011
1012
		ii_write_lock_child(a->inode);
1013
		ii_write_lock_parent(a->dir);
1014
		au_hdir_lock(h_dir, a->dir, a->bindex);
1015
		err = au_whtmp_rmdir(a->h_dentry, &a->whlist, a->bindex,
1016
				     a->dir, a->inode, a->noself);
1017
		au_hdir_unlock(h_dir, a->dir, a->bindex);
1018
		ii_write_unlock(a->dir);
1019
		ii_write_unlock(a->inode);
1020
		dput(h_parent);
1021
	}
1022
	si_read_unlock(sb);
1023
	au_whtmp_rmdir_free_args(a);
1024
	if (unlikely(err))
1025
		AuIOErr("err %d\n", err);
1026
}
1027
1028
void au_whtmp_kick_rmdir(struct dentry *h_dentry, struct au_nhash *whlist,
1029
			 aufs_bindex_t bindex, struct inode *dir,
1030
			 struct inode *inode, int noself,
1031
			 struct au_whtmp_rmdir_args *args)
1032
{
1033
	int wkq_err;
1034
1035
	LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
1036
	IMustLock(dir);
1037
1038
	/* all post-process will be done in do_rmdir_whtmp(). */
1039
	args->h_dentry = dget(h_dentry);
1040
	au_nhash_init(&args->whlist);
1041
	au_nhash_move(&args->whlist, whlist);
1042
	args->bindex = bindex;
1043
	args->dir = igrab(dir);
1044
	args->inode = igrab(inode);
1045
	args->noself = noself;
1046
	wkq_err = au_wkq_nowait(do_rmdir_whtmp, args, dir->i_sb, /*dlgt*/0);
1047
	if (unlikely(wkq_err)) {
1048
		AuWarn("rmdir error %.*s (%d), ignored\n",
1049
		       AuDLNPair(h_dentry), wkq_err);
1050
		au_whtmp_rmdir_free_args(args);
1051
	}
1052
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/whout.h (+140 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * whiteout for logical deletion and opaque directory
21
 *
22
 * $Id: whout.h,v 1.2 2008/04/21 02:00:37 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_WHOUT_H__
26
#define __AUFS_WHOUT_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/aufs_type.h>
32
#include "dir.h"
33
#include "opts.h"
34
#include "super.h"
35
36
int au_wh_name_alloc(const char *name, int len, struct qstr *wh);
37
void au_wh_name_free(struct qstr *wh);
38
39
struct au_ndx;
40
int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
41
	       struct au_ndx *ndx);
42
int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx);
43
44
struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
45
			     struct au_ndx *ndx);
46
int au_whtmp_ren(struct inode *dir, struct dentry *dentry, aufs_bindex_t bindex,
47
		 int noself);
48
int au_wh_unlink_dentry(struct inode *h_dir, struct dentry *wh_dentry,
49
			struct dentry *dentry, struct inode *dir, int dlgt);
50
51
struct au_branch;
52
int au_wh_init(struct dentry *h_parent, struct au_branch *br,
53
	       struct vfsmount *nfsmnt, struct super_block *sb);
54
55
/* diropq flags */
56
#define AuDiropq_CREATE	1
57
#define AuDiropq_DLGT	(1 << 1)
58
#define au_ftest_diropq(flags, name)	((flags) & AuDiropq_##name)
59
#define au_fset_diropq(flags, name)	{ (flags) |= AuDiropq_##name; }
60
#define au_fclr_diropq(flags, name)	{ (flags) &= ~AuDiropq_##name; }
61
#ifndef CONFIG_AUFS_DLGT
62
#undef AuDiropq_DLGT
63
#define AuDiropq_DLGT	0
64
#endif
65
66
struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
67
			     unsigned int flags);
68
69
struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
70
			  struct au_ndx *ndx);
71
struct dentry *au_wh_create(struct inode *dir, struct dentry *dentry,
72
			    aufs_bindex_t bindex, struct dentry *h_parent,
73
			    struct au_ndx *ndx);
74
75
/* real rmdir the whiteout-ed dir */
76
struct au_whtmp_rmdir_args {
77
	struct dentry *h_dentry;
78
	struct au_nhash whlist;
79
	aufs_bindex_t bindex;
80
	struct inode *dir, *inode;
81
	int noself;
82
};
83
84
struct au_nhash;
85
int au_whtmp_rmdir(struct dentry *h_dentry, struct au_nhash *whlist,
86
		   aufs_bindex_t bindex, struct inode *dir, struct inode *inode,
87
		   int noself);
88
void au_whtmp_kick_rmdir(struct dentry *h_dentry, struct au_nhash *whlist,
89
			 aufs_bindex_t bindex, struct inode *dir,
90
			 struct inode *inode, int noself,
91
			 struct au_whtmp_rmdir_args *args);
92
93
/* ---------------------------------------------------------------------- */
94
95
static inline
96
struct dentry *au_diropq_create(struct dentry *dentry, aufs_bindex_t bindex,
97
				int dlgt)
98
{
99
	unsigned int flags = AuDiropq_CREATE;
100
	if (unlikely(dlgt))
101
		au_fset_diropq(flags, DLGT);
102
	return au_diropq_sio(dentry, bindex, flags);
103
}
104
105
static inline
106
int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex, int dlgt)
107
{
108
	unsigned int flags = !AuDiropq_CREATE;
109
	if (unlikely(dlgt))
110
		au_fset_diropq(flags, DLGT);
111
	return PTR_ERR(au_diropq_sio(dentry, bindex, flags));
112
}
113
114
/* ---------------------------------------------------------------------- */
115
116
#ifdef CONFIG_AUFS_ROBR
117
/* robr.c */
118
int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
119
		    struct qstr *wh_name, int try_sio, struct au_ndx *ndx);
120
int au_test_robr_shwh(struct super_block *sb, const struct qstr *name);
121
#else
122
static inline
123
int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
124
		    struct qstr *wh_name, int try_sio, struct au_ndx *ndx)
125
{
126
	return au_wh_test(h_parent, wh_name, try_sio, ndx);
127
}
128
129
static inline
130
int au_test_robr_shwh(struct super_block *sb, const struct qstr *name)
131
{
132
	if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
133
		     && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
134
		return -EPERM;
135
	return 0;
136
}
137
#endif /* CONFIG_AUFS_ROBR */
138
139
#endif /* __KERNEL__ */
140
#endif /* __AUFS_WHOUT_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/wkq.c (+297 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * workqueue for asynchronous/super-io/delegated operations
21
 *
22
 * $Id: wkq.c,v 1.4 2008/05/04 23:53:38 sfjro Exp $
23
 */
24
25
#include <linux/module.h>
26
#include "aufs.h"
27
28
struct au_wkq *au_wkq;
29
30
struct au_cred {
31
#ifdef CONFIG_AUFS_DLGT
32
	int umask;
33
	uid_t fsuid;
34
	gid_t fsgid;
35
	kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
36
	//unsigned keep_capabilities:1;
37
	//struct user_struct *user;
38
	//struct fs_struct *fs;
39
	//struct nsproxy *nsproxy;
40
#endif
41
};
42
43
struct au_wkinfo {
44
	struct work_struct wk;
45
	struct vfsmount *mnt;
46
47
	unsigned int flags;
48
	struct au_cred cred;
49
50
	au_wkq_func_t func;
51
	void *args;
52
53
	atomic_t *busyp;
54
	struct completion *comp;
55
};
56
57
/* ---------------------------------------------------------------------- */
58
59
#ifdef CONFIG_AUFS_DLGT
60
static void cred_store(struct au_cred *cred)
61
{
62
	cred->umask = current->fs->umask;
63
	cred->fsuid = current->fsuid;
64
	cred->fsgid = current->fsgid;
65
	cred->cap_effective = current->cap_effective;
66
	cred->cap_inheritable = current->cap_inheritable;
67
	cred->cap_permitted = current->cap_permitted;
68
}
69
70
static void cred_revert(struct au_cred *cred)
71
{
72
	AuDebugOn(!au_test_wkq(current));
73
	current->fs->umask = cred->umask;
74
	current->fsuid = cred->fsuid;
75
	current->fsgid = cred->fsgid;
76
	current->cap_effective = cred->cap_effective;
77
	current->cap_inheritable = cred->cap_inheritable;
78
	current->cap_permitted = cred->cap_permitted;
79
}
80
81
static void cred_switch(struct au_cred *old, struct au_cred *new)
82
{
83
	cred_store(old);
84
	cred_revert(new);
85
}
86
87
static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo)
88
{
89
	if (unlikely(au_ftest_wkq(flags, DLGT)))
90
		cred_store(&wkinfo->cred);
91
}
92
93
static void dlgt_func(struct au_wkinfo *wkinfo)
94
{
95
	if (!au_ftest_wkq(wkinfo->flags, DLGT))
96
		wkinfo->func(wkinfo->args);
97
	else {
98
		struct au_cred cred;
99
		cred_switch(&cred, &wkinfo->cred);
100
		wkinfo->func(wkinfo->args);
101
		cred_revert(&cred);
102
	}
103
}
104
#else
105
static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo)
106
{
107
	/* empty */
108
}
109
110
static void dlgt_func(struct au_wkinfo *wkinfo)
111
{
112
	wkinfo->func(wkinfo->args);
113
}
114
#endif /* CONFIG_AUFS_DLGT */
115
116
/* ---------------------------------------------------------------------- */
117
118
static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
119
{
120
#ifdef CONFIG_AUFS_STAT
121
	unsigned int new, old;
122
123
	do {
124
		new = atomic_read(wkinfo->busyp);
125
		old = wkq->max_busy;
126
		if (new <= old)
127
			break;
128
	} while (cmpxchg(&wkq->max_busy, old, new) == old);
129
#endif
130
}
131
132
static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
133
{
134
	AuTraceEnter();
135
	wkinfo->busyp = &wkq->busy;
136
	update_busy(wkq, wkinfo);
137
	if (au_ftest_wkq(wkinfo->flags, WAIT))
138
		return !queue_work(wkq->q, &wkinfo->wk);
139
	else
140
		return !schedule_work(&wkinfo->wk);
141
}
142
143
static void do_wkq(struct au_wkinfo *wkinfo)
144
{
145
	unsigned int idle, n;
146
	int i, idle_idx;
147
148
	AuTraceEnter();
149
150
	while (1) {
151
		if (au_ftest_wkq(wkinfo->flags, WAIT)) {
152
			idle_idx = 0;
153
			idle = UINT_MAX;
154
			for (i = 0; i < aufs_nwkq; i++) {
155
				n = atomic_inc_return(&au_wkq[i].busy);
156
				if (n == 1 && !enqueue(au_wkq + i, wkinfo))
157
					return; /* success */
158
159
				if (n < idle) {
160
					idle_idx = i;
161
					idle = n;
162
				}
163
				atomic_dec_return(&au_wkq[i].busy);
164
			}
165
		} else
166
			idle_idx = aufs_nwkq;
167
168
		atomic_inc_return(&au_wkq[idle_idx].busy);
169
		if (!enqueue(au_wkq + idle_idx, wkinfo))
170
			return; /* success */
171
172
		/* impossible? */
173
		AuWarn1("failed to queue_work()\n");
174
		yield();
175
	}
176
}
177
178
static void wkq_func(struct work_struct *wk)
179
{
180
	struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
181
182
	LKTRTrace("wkinfo{0x%x, %p, %p, %p}\n",
183
		  wkinfo->flags, wkinfo->func, wkinfo->busyp, wkinfo->comp);
184
185
	dlgt_func(wkinfo);
186
	atomic_dec_return(wkinfo->busyp);
187
	if (au_ftest_wkq(wkinfo->flags, WAIT))
188
		complete(wkinfo->comp);
189
	else {
190
		mntput(wkinfo->mnt);
191
		module_put(THIS_MODULE);
192
		kfree(wkinfo);
193
	}
194
}
195
196
int au_wkq_run(au_wkq_func_t func, void *args, struct super_block *sb,
197
	       unsigned int flags)
198
{
199
	int err;
200
	//int queued;
201
	//struct workqueue_struct *wkq;
202
	DECLARE_COMPLETION_ONSTACK(comp);
203
	struct au_wkinfo _wkinfo = {
204
		//.sb	= sb,
205
		.flags	= flags,
206
		.func	= func,
207
		.args	= args,
208
		.comp	= &comp
209
	}, *wkinfo = &_wkinfo;
210
211
	LKTRTrace("0x%x\n", flags);
212
	AuDebugOn(au_test_wkq(current));
213
214
	err = 0;
215
	if (unlikely(!au_ftest_wkq(flags, WAIT))) {
216
		AuDebugOn(!sb);
217
		/*
218
		 * wkq_func() must free this wkinfo.
219
		 * it highly depends upon the implementation of workqueue.
220
		 */
221
		err = -ENOMEM;
222
		wkinfo = kmalloc(sizeof(*wkinfo), GFP_TEMPORARY);
223
		if (unlikely(!wkinfo))
224
			goto out;
225
		err = 0;
226
		/* prohibit umount */
227
		wkinfo->mnt = au_mntcache_get(sb);
228
		wkinfo->flags = flags;
229
		wkinfo->func = func;
230
		wkinfo->args = args;
231
		wkinfo->comp = NULL;
232
		__module_get(THIS_MODULE);
233
	}
234
235
	INIT_WORK(&wkinfo->wk, wkq_func);
236
	dlgt_cred_store(flags, wkinfo);
237
	do_wkq(wkinfo);
238
	if (au_ftest_wkq(flags, WAIT))
239
		/* no timeout, no interrupt */
240
		wait_for_completion(wkinfo->comp);
241
 out:
242
	AuTraceErr(err);
243
	return err;
244
}
245
246
/* ---------------------------------------------------------------------- */
247
248
void au_wkq_fin(void)
249
{
250
	int i;
251
252
	AuTraceEnter();
253
254
	for (i = 0; i < aufs_nwkq; i++)
255
		if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
256
			destroy_workqueue(au_wkq[i].q);
257
	kfree(au_wkq);
258
}
259
260
int __init au_wkq_init(void)
261
{
262
	int err, i;
263
	struct au_wkq *nowaitq;
264
265
	LKTRTrace("%d\n", aufs_nwkq);
266
267
	/* '+1' is for accounting  of nowait queue */
268
	err = -ENOMEM;
269
	au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_KERNEL);
270
	if (unlikely(!au_wkq))
271
		goto out;
272
273
	err = 0;
274
	for (i = 0; i < aufs_nwkq; i++) {
275
		au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
276
		if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
277
			atomic_set(&au_wkq[i].busy, 0);
278
			au_wkq[i].max_busy = 0;
279
			continue;
280
		}
281
282
		err = PTR_ERR(au_wkq[i].q);
283
		au_wkq_fin();
284
		break;
285
	}
286
287
	/* nowait accounting */
288
	nowaitq = au_wkq + aufs_nwkq;
289
	atomic_set(&nowaitq->busy, 0);
290
	nowaitq->max_busy = 0;
291
	nowaitq->q = NULL;
292
	//smp_mb(); /* atomic_set */
293
294
 out:
295
	AuTraceErr(err);
296
	return err;
297
}
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/wkq.h (+155 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * workqueue for asynchronous/super-io/delegated operations
21
 *
22
 * $Id: wkq.h,v 1.3 2008/04/28 03:18:21 sfjro Exp $
23
 */
24
25
#ifndef __AUFS_WKQ_H__
26
#define __AUFS_WKQ_H__
27
28
#ifdef __KERNEL__
29
30
#include <linux/fs.h>
31
#include <linux/sched.h>
32
#include <linux/workqueue.h>
33
#include <linux/aufs_type.h>
34
35
/* ---------------------------------------------------------------------- */
36
37
/* internal workqueue named AUFS_WKQ_NAME */
38
struct au_wkq {
39
	struct workqueue_struct	*q;
40
41
	/* accounting */
42
	atomic_t		busy;
43
	unsigned int		max_busy; // todo: STAT only
44
};
45
46
/*
47
 * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
48
 */
49
struct au_nowait_tasks {
50
#ifdef CONFIG_AUFS_HINOTIFY
51
	/*
52
	 * currently, the 'nowait' task which should be waited in the next
53
	 * operation is only hinotify.
54
	 */
55
	atomic_t		nw_len;
56
	wait_queue_head_t	nw_wq;
57
#endif
58
};
59
60
/* ---------------------------------------------------------------------- */
61
62
extern struct au_wkq *au_wkq;
63
typedef void (*au_wkq_func_t)(void *args);
64
65
/* wkq flags */
66
#define AuWkq_WAIT	1
67
#define AuWkq_DLGT	(1 << 1)
68
#define au_ftest_wkq(flags, name)	((flags) & AuWkq_##name)
69
#define au_fset_wkq(flags, name)	{ (flags) |= AuWkq_##name; }
70
#define au_fclr_wkq(flags, name)	{ (flags) &= ~AuWkq_##name; }
71
#ifndef CONFIG_AUFS_DLGT
72
#undef AuWkq_DLGT
73
#define AuWkq_DLGT	0
74
#endif
75
76
int au_wkq_run(au_wkq_func_t func, void *args, struct super_block *sb,
77
	       unsigned int flags);
78
int __init au_wkq_init(void);
79
void au_wkq_fin(void);
80
81
/* ---------------------------------------------------------------------- */
82
83
static inline int au_test_wkq(struct task_struct *tsk)
84
{
85
	return (!tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME));
86
}
87
88
static inline int au_wkq_wait(au_wkq_func_t func, void *args, int dlgt)
89
{
90
	unsigned int flags = AuWkq_WAIT;
91
	if (unlikely(dlgt))
92
		au_fset_wkq(flags, DLGT);
93
	return au_wkq_run(func, args, /*sb*/NULL, flags);
94
}
95
96
static inline int au_wkq_nowait(au_wkq_func_t func, void *args,
97
				struct super_block *sb, int dlgt)
98
{
99
	unsigned int flags = !AuWkq_WAIT;
100
	if (unlikely(dlgt))
101
		au_fset_wkq(flags, DLGT);
102
	return au_wkq_run(func, args, sb, flags);
103
}
104
105
#ifdef CONFIG_AUFS_HINOTIFY
106
//todo: memory barrier?
107
static inline void au_nwt_init(struct au_nowait_tasks *nwt)
108
{
109
	atomic_set(&nwt->nw_len, 0);
110
	smp_mb(); /* atomic_set */
111
	init_waitqueue_head(&nwt->nw_wq);
112
}
113
114
static inline int au_nwt_inc(struct au_nowait_tasks *nwt)
115
{
116
	return atomic_inc_return(&nwt->nw_len);
117
}
118
119
static inline int au_nwt_dec(struct au_nowait_tasks *nwt)
120
{
121
	int ret = atomic_dec_return(&nwt->nw_len);
122
	if (!ret)
123
		wake_up_all(&nwt->nw_wq);
124
	return ret;
125
}
126
127
static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
128
{
129
	wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
130
	return 0;
131
}
132
#else
133
static inline void au_nwt_init(struct au_nowait_tasks *nwt)
134
{
135
	/* nothing */
136
}
137
138
static inline int au_nwt_inc(struct au_nowait_tasks *nwt)
139
{
140
	return 0;
141
}
142
143
static inline int au_nwt_dec(struct au_nowait_tasks *nwt)
144
{
145
	return 0;
146
}
147
148
static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
149
{
150
	return 0;
151
}
152
#endif /* CONFIG_AUFS_HINOTIFY */
153
154
#endif /* __KERNEL__ */
155
#endif /* __AUFS_WKQ_H__ */
(-)linux-2.6.25.4-unionfs.orig/fs/aufs/xino.c (+1225 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005-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
 * external inode number translation table and bitmap
21
 *
22
 * $Id: xino.c,v 1.6 2008/05/19 01:51:23 sfjro Exp $
23
 */
24
25
//#include <linux/fsnotify.h>
26
//#include <linux/smp_lock.h>
27
#include <linux/uaccess.h>
28
#include "aufs.h"
29
30
/* ---------------------------------------------------------------------- */
31
32
static ssize_t xino_fread(au_readf_t func, struct file *file, void *buf,
33
			  size_t size, loff_t *pos)
34
{
35
	ssize_t err;
36
	mm_segment_t oldfs;
37
38
	LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
39
		  AuDLNPair(file->f_dentry), (unsigned long)size, *pos);
40
41
	oldfs = get_fs();
42
	set_fs(KERNEL_DS);
43
	do {
44
		// signal_pending
45
		err = func(file, (char __user *)buf, size, pos);
46
	} while (err == -EAGAIN || err == -EINTR);
47
	set_fs(oldfs);
48
49
	AuTraceErr(err);
50
	return err;
51
}
52
53
/* ---------------------------------------------------------------------- */
54
55
static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
56
			      size_t size, loff_t *pos)
57
{
58
	ssize_t err;
59
	mm_segment_t oldfs;
60
61
	lockdep_off();
62
	oldfs = get_fs();
63
	set_fs(KERNEL_DS);
64
	do {
65
		// signal_pending
66
		err = func(file, (const char __user *)buf, size, pos);
67
	} while (err == -EAGAIN || err == -EINTR);
68
	set_fs(oldfs);
69
	lockdep_on();
70
71
	if (err >= 0)
72
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
73
	/*ignore*/
74
75
	AuTraceErr(err);
76
	return err;
77
}
78
79
struct do_xino_fwrite_args {
80
	ssize_t *errp;
81
	au_writef_t func;
82
	struct file *file;
83
	void *buf;
84
	size_t size;
85
	loff_t *pos;
86
};
87
88
static void call_do_xino_fwrite(void *args)
89
{
90
	struct do_xino_fwrite_args *a = args;
91
	*a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
92
}
93
94
static ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf,
95
			   size_t size, loff_t *pos)
96
{
97
	ssize_t err;
98
99
	LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
100
		  AuDLNPair(file->f_dentry), (unsigned long)size, *pos);
101
102
	// signal block and no wkq?
103
	/*
104
	 * it breaks RLIMIT_FSIZE and normal user's limit,
105
	 * users should care about quota and real 'filesystem full.'
106
	 */
107
	if (!au_test_wkq(current)) {
108
		int wkq_err;
109
		struct do_xino_fwrite_args args = {
110
			.errp	= &err,
111
			.func	= func,
112
			.file	= file,
113
			.buf	= buf,
114
			.size	= size,
115
			.pos	= pos
116
		};
117
		wkq_err = au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
118
		if (unlikely(wkq_err))
119
			err = wkq_err;
120
	} else
121
		err = do_xino_fwrite(func, file, buf, size, pos);
122
123
	AuTraceErr(err);
124
	return err;
125
}
126
127
/* ---------------------------------------------------------------------- */
128
129
struct xino_do_trunc_args {
130
	struct vfsmount *mnt;
131
	struct au_branch *br;
132
};
133
134
static void xino_do_trunc(void *_args)
135
{
136
	struct xino_do_trunc_args *args = _args;
137
	struct super_block *sb;
138
	aufs_bindex_t bindex;
139
	int err;
140
	struct file *file;
141
142
	err = 0;
143
	sb = args->mnt->mnt_sb;
144
	si_noflush_write_lock(sb);
145
	bindex = au_br_index(sb, args->br->br_id);
146
	AuDebugOn(bindex < 0);
147
	err = au_xino_trunc(sb, bindex);
148
	if (unlikely(err))
149
		goto out;
150
151
	file = args->br->br_xino;
152
	au_update_fuse_h_inode(args->br->br_mnt, file->f_dentry); /*ignore*/
153
	if (file->f_dentry->d_inode->i_blocks >= args->br->br_xino_upper)
154
		args->br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
155
	//AuDbg("%Lu\n", (unsigned long long)args->br->br_xino_upper);
156
157
 out:
158
	si_write_unlock(sb);
159
	if (unlikely(err))
160
		AuWarn("err b%d, (%d)\n", bindex, err);
161
	au_nwt_dec(&au_sbi(sb)->si_nowait);
162
	atomic_dec_return(&args->br->br_xino_running);
163
	au_br_put(args->br);
164
	mntput(args->mnt);
165
	kfree(args);
166
}
167
168
static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
169
{
170
	struct xino_do_trunc_args *args;
171
	struct au_sbinfo *sbinfo;
172
	struct file *file = br->br_xino;
173
	int wkq_err;
174
175
	au_update_fuse_h_inode(br->br_mnt, file->f_dentry); /*ignore*/
176
	if (file->f_dentry->d_inode->i_blocks < br->br_xino_upper)
177
		return;
178
	if (atomic_inc_return(&br->br_xino_running) > 1)
179
		goto out;
180
181
	/* lock and kfree() will be called in trunc_xino() */
182
	args = kmalloc(sizeof(*args), GFP_TEMPORARY);
183
	if (args) {
184
		args->mnt = au_mntcache_get(sb);
185
		args->br = br;
186
		au_br_get(br);
187
		sbinfo = au_sbi(sb);
188
		au_nwt_inc(&sbinfo->si_nowait);
189
		wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*dlgt*/0);
190
		if (!wkq_err)
191
			return; /* success */
192
193
		AuErr("wkq %d\n", wkq_err);
194
		au_nwt_dec(&sbinfo->si_nowait);
195
		mntput(args->mnt);
196
		au_br_put(br);
197
		kfree(args);
198
	} else
199
		AuErr1("no memory\n");
200
 out:
201
	atomic_dec_return(&br->br_xino_running);
202
}
203
204
/* ---------------------------------------------------------------------- */
205
206
#define Au_LOFF_MAX	((loff_t)LLONG_MAX)
207
208
static int au_xino_do_write(au_writef_t write, struct file *file,
209
			    ino_t h_ino, struct au_xino_entry *xinoe)
210
{
211
	loff_t pos;
212
	ssize_t sz;
213
214
	AuTraceEnter();
215
216
	pos = h_ino;
217
	if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) {
218
		AuIOErr1("too large hi%lu\n", h_ino);
219
		return -EFBIG;
220
	}
221
	pos *= sizeof(*xinoe);
222
	sz = xino_fwrite(write, file, xinoe, sizeof(*xinoe), &pos);
223
	if (sz == sizeof(*xinoe))
224
		return 0; /* success */
225
226
	AuIOErr("write failed (%ld)\n", (long)sz);
227
	return -EIO;
228
}
229
230
/*
231
 * write @ino to the xinofile for the specified branch{@sb, @bindex}
232
 * at the position of @_ino.
233
 * when @ino is zero, it is written to the xinofile and means no entry.
234
 */
235
int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
236
		  struct au_xino_entry *xinoe)
237
{
238
	int err;
239
	struct file *file;
240
	struct au_branch *br;
241
	unsigned int mnt_flags;
242
243
	LKTRTrace("b%d, hi%lu, i%lu\n", bindex, h_ino, xinoe->ino);
244
	BUILD_BUG_ON(sizeof(long long) != sizeof(Au_LOFF_MAX)
245
		     || ((loff_t) - 1) > 0);
246
247
	mnt_flags = au_mntflags(sb);
248
	if (unlikely(!au_opt_test(mnt_flags, XINO)))
249
		return 0;
250
251
	br = au_sbr(sb, bindex);
252
	file = br->br_xino;
253
	AuDebugOn(!file);
254
255
	err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, h_ino, xinoe);
256
	if (!err) {
257
		if (unlikely(au_opt_test(mnt_flags, TRUNC_XINO)
258
			     && au_test_trunc_xino(br->br_mnt->mnt_sb)))
259
			xino_try_trunc(sb, br);
260
		return 0; /* success */
261
	}
262
263
	AuIOErr("write failed (%d)\n", err);
264
	return -EIO;
265
}
266
267
/* ---------------------------------------------------------------------- */
268
269
static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
270
//static const int page_bits = 4;
271
static ino_t xib_calc_ino(unsigned long pindex, int bit)
272
{
273
	ino_t ino;
274
	AuDebugOn(bit < 0 || page_bits <= bit);
275
	ino = AUFS_FIRST_INO + pindex * page_bits + bit;
276
	return ino;
277
}
278
279
static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
280
{
281
	AuDebugOn(ino < AUFS_FIRST_INO);
282
	ino -= AUFS_FIRST_INO;
283
	*pindex = ino / page_bits;
284
	*bit = ino % page_bits;
285
}
286
287
static int xib_pindex(struct super_block *sb, unsigned long pindex)
288
{
289
	int err;
290
	struct au_sbinfo *sbinfo;
291
	loff_t pos;
292
	ssize_t sz;
293
	struct file *xib;
294
	unsigned long *p;
295
296
	LKTRTrace("pindex %lu\n", pindex);
297
	sbinfo = au_sbi(sb);
298
	MtxMustLock(&sbinfo->si_xib_mtx);
299
	AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
300
		  || !au_opt_test(sbinfo->si_mntflags, XINO));
301
302
	if (pindex == sbinfo->si_xib_last_pindex)
303
		return 0;
304
305
	xib = sbinfo->si_xib;
306
	p = sbinfo->si_xib_buf;
307
	pos = sbinfo->si_xib_last_pindex;
308
	pos *= PAGE_SIZE;
309
	sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
310
	if (unlikely(sz != PAGE_SIZE))
311
		goto out;
312
313
	pos = pindex;
314
	pos *= PAGE_SIZE;
315
	if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
316
		sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
317
	else {
318
		memset(p, 0, PAGE_SIZE);
319
		sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
320
	}
321
	if (sz == PAGE_SIZE) {
322
		sbinfo->si_xib_last_pindex = pindex;
323
		return 0; /* success */
324
	}
325
326
 out:
327
	AuIOErr1("write failed (%ld)\n", (long)sz);
328
	err = sz;
329
	if (sz >= 0)
330
		err = -EIO;
331
	AuTraceErr(err);
332
	return err;
333
}
334
335
/* ---------------------------------------------------------------------- */
336
337
int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
338
		   ino_t ino)
339
{
340
	int err, bit;
341
	unsigned long pindex;
342
	struct au_sbinfo *sbinfo;
343
	struct au_xino_entry xinoe = {
344
		.ino	= 0
345
	};
346
347
	LKTRTrace("b%d, hi%lu, i%lu\n", bindex, h_ino, ino);
348
349
	sbinfo = au_sbi(sb);
350
	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
351
		return 0;
352
353
	err = 0;
354
	if (unlikely(ino)) {
355
		AuDebugOn(ino < AUFS_FIRST_INO);
356
		xib_calc_bit(ino, &pindex, &bit);
357
		AuDebugOn(page_bits <= bit);
358
		mutex_lock(&sbinfo->si_xib_mtx);
359
		err = xib_pindex(sb, pindex);
360
		if (!err) {
361
			clear_bit(bit, sbinfo->si_xib_buf);
362
			sbinfo->si_xib_next_bit = bit;
363
		}
364
		mutex_unlock(&sbinfo->si_xib_mtx);
365
	}
366
367
	if (!err)
368
		err = au_xino_write(sb, bindex, h_ino, &xinoe);
369
	return err;
370
}
371
372
ino_t au_xino_new_ino(struct super_block *sb)
373
{
374
	ino_t ino;
375
	struct au_sbinfo *sbinfo;
376
	int free_bit, err;
377
	unsigned long *p, pindex, ul, pend;
378
	struct file *file;
379
380
	//au_debug_on();
381
	AuTraceEnter();
382
383
	sbinfo = au_sbi(sb);
384
	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
385
		return iunique(sb, AUFS_FIRST_INO);
386
387
	mutex_lock(&sbinfo->si_xib_mtx);
388
	p = sbinfo->si_xib_buf;
389
	free_bit = sbinfo->si_xib_next_bit;
390
	//AuDbg("bit %d, pindex %d\n", free_bit, sbinfo->si_xib_last_pindex);
391
	//AuDbg("bit %d, %d\n", free_bit, test_bit(free_bit, p));
392
	if (free_bit < page_bits && !test_bit(free_bit, p))
393
		goto out; /* success */
394
	free_bit = find_first_zero_bit(p, page_bits);
395
	if (free_bit < page_bits)
396
		goto out; /* success */
397
398
	pindex = sbinfo->si_xib_last_pindex;
399
	for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
400
		err = xib_pindex(sb, ul);
401
		if (unlikely(err))
402
			goto out_err;
403
		free_bit = find_first_zero_bit(p, page_bits);
404
		if (free_bit < page_bits)
405
			goto out; /* success */
406
	}
407
408
	file = sbinfo->si_xib;
409
	pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
410
	for (ul = pindex + 1; ul <= pend; ul++) {
411
		err = xib_pindex(sb, ul);
412
		if (unlikely(err))
413
			goto out_err;
414
		free_bit = find_first_zero_bit(p, page_bits);
415
		if (free_bit < page_bits)
416
			goto out; /* success */
417
	}
418
	BUG();
419
420
 out:
421
	set_bit(free_bit, p);
422
	sbinfo->si_xib_next_bit++;
423
	pindex = sbinfo->si_xib_last_pindex;
424
	mutex_unlock(&sbinfo->si_xib_mtx);
425
	ino = xib_calc_ino(pindex, free_bit);
426
	//AuDbg("i%lu\n", ino);
427
	LKTRTrace("i%lu\n", ino);
428
	//au_debug_off();
429
	return ino;
430
 out_err:
431
	mutex_unlock(&sbinfo->si_xib_mtx);
432
	LKTRTrace("i0\n");
433
	//au_debug_off();
434
	return 0;
435
}
436
437
/*
438
 * read @ino from xinofile for the specified branch{@sb, @bindex}
439
 * at the position of @h_ino.
440
 * if @ino does not exist and @do_new is true, get new one.
441
 */
442
int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
443
		 struct au_xino_entry *xinoe)
444
{
445
	int err;
446
	struct file *file;
447
	loff_t pos;
448
	ssize_t sz;
449
	struct au_sbinfo *sbinfo;
450
451
	LKTRTrace("b%d, hi%lu\n", bindex, h_ino);
452
453
	err = 0;
454
	xinoe->ino = 0;
455
	sbinfo = au_sbi(sb);
456
	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
457
		return 0; /* no ino */
458
459
	pos = h_ino;
460
	if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) {
461
		AuIOErr1("too large hi%lu\n", h_ino);
462
		return -EFBIG;
463
	}
464
	pos *= sizeof(*xinoe);
465
466
	file = au_sbr(sb, bindex)->br_xino;
467
	AuDebugOn(!file);
468
	if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xinoe))
469
		return 0; /* no ino */
470
471
	sz = xino_fread(sbinfo->si_xread, file, xinoe, sizeof(*xinoe), &pos);
472
	if (sz == sizeof(*xinoe))
473
		return 0; /* success */
474
475
	err = sz;
476
	if (unlikely(sz >= 0)) {
477
		err = -EIO;
478
		AuIOErr("xino read error (%ld)\n", (long)sz);
479
	}
480
481
	AuTraceErr(err);
482
	return err;
483
}
484
485
/* ---------------------------------------------------------------------- */
486
487
struct file *au_xino_create(struct super_block *sb, char *fname, int silent,
488
			    struct dentry *parent)
489
{
490
	struct file *file;
491
	int err;
492
	struct dentry *h_parent;
493
	struct inode *h_dir;
494
	struct vfsub_args vargs;
495
	//const int hinotify = au_opt_test(au_mntflags(sb), UDBA_INOTIFY);
496
497
	LKTRTrace("%s\n", fname);
498
	//AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
499
500
	/* LSM may detect it */
501
	file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
502
			       S_IRUGO | S_IWUGO);
503
	//file = ERR_PTR(-1);
504
	if (IS_ERR(file)) {
505
		if (!silent)
506
			AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
507
		return file;
508
	}
509
510
	/* keep file count */
511
	h_parent = dget_parent(file->f_dentry);
512
	h_dir = h_parent->d_inode;
513
	vfsub_args_init(&vargs, NULL, 0, 0);
514
	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
515
	err = vfsub_unlink(h_dir, file->f_dentry, &vargs);
516
	mutex_unlock(&h_dir->i_mutex);
517
	dput(h_parent);
518
	if (unlikely(err)) {
519
		if (!silent)
520
			AuErr("unlink %s(%d)\n", fname, err);
521
		goto out;
522
	}
523
524
	if (sb != file->f_dentry->d_sb)
525
		return file; /* success */
526
527
	if (!silent)
528
		AuErr("%s must be outside\n", fname);
529
	err = -EINVAL;
530
531
 out:
532
	fput(file);
533
	file = ERR_PTR(err);
534
	return file;
535
}
536
537
/*
538
 * find another branch who is on the same filesystem of the specified
539
 * branch{@btgt}. search until @bend.
540
 */
541
static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
542
			aufs_bindex_t bend)
543
{
544
	aufs_bindex_t bindex;
545
	struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
546
547
	for (bindex = 0; bindex <= bend; bindex++)
548
		if (unlikely(btgt != bindex && tgt_sb == au_sbr_sb(sb, bindex)))
549
			return bindex;
550
	return -1;
551
}
552
553
/*
554
 * create a new xinofile at the same place/path as @base_file.
555
 */
556
static
557
struct file *au_xino_create2(struct super_block *sb, struct file *base_file,
558
			     struct file *copy_src)
559
{
560
	struct file *file;
561
	int err;
562
	struct dentry *base, *dentry, *parent;
563
	struct inode *dir, *inode;
564
	struct qstr *name;
565
	struct vfsub_args vargs;
566
	struct au_ndx ndx = {
567
		.nfsmnt	= NULL,
568
		.flags	= 0,
569
		.nd	= NULL,
570
		//.br	= NULL
571
	};
572
573
	base = base_file->f_dentry;
574
	LKTRTrace("%.*s\n", AuDLNPair(base));
575
	parent = base->d_parent; /* dir inode is locked */
576
	dir = parent->d_inode;
577
	IMustLock(dir);
578
579
	file = ERR_PTR(-EINVAL);
580
	if (unlikely(au_test_nfs(parent->d_sb)))
581
		goto out;
582
583
	/* do not superio, nor NFS. */
584
	name = &base->d_name;
585
	dentry = au_lkup_one(name->name, parent, name->len, &ndx);
586
	//if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
587
	if (IS_ERR(dentry)) {
588
		file = (void *)dentry;
589
		AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
590
		goto out;
591
	}
592
	err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, /*dlgt*/0);
593
	//if (LktrCond) {vfs_unlink(dir, dentry); err = -1;}
594
	if (unlikely(err)) {
595
		file = ERR_PTR(err);
596
		AuErr("%.*s create err %d\n", AuLNPair(name), err);
597
		goto out_dput;
598
	}
599
	file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
600
			   O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
601
	//if (LktrCond) {fput(file); file = ERR_PTR(-1);}
602
	if (IS_ERR(file)) {
603
		AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
604
		goto out_dput;
605
	}
606
	vfsub_args_init(&vargs, NULL, 0, 0);
607
	err = vfsub_unlink(dir, dentry, &vargs);
608
	//if (LktrCond) err = -1;
609
	if (unlikely(err)) {
610
		AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
611
		goto out_fput;
612
	}
613
614
	if (copy_src) {
615
		inode = copy_src->f_dentry->d_inode;
616
		err = au_copy_file(file, copy_src, i_size_read(inode), sb);
617
		if (unlikely(err)) {
618
			AuErr("%.*s copy err %d\n", AuLNPair(name), err);
619
			goto out_fput;
620
		}
621
	}
622
	goto out_dput; /* success */
623
624
 out_fput:
625
	fput(file);
626
	file = ERR_PTR(err);
627
 out_dput:
628
	dput(dentry);
629
 out:
630
	AuTraceErrPtr(file);
631
	return file;
632
}
633
634
/* ---------------------------------------------------------------------- */
635
636
/*
637
 * initialize the xinofile for the specified branch{@sb, @bindex}
638
 * at the place/path where @base_file indicates.
639
 * test whether another branch is on the same filesystem or not,
640
 * if @do_test is true.
641
 */
642
int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
643
	       struct file *base_file, int do_test)
644
{
645
	int err, do_create;
646
	struct au_branch *shared_br;
647
	aufs_bindex_t bshared, bend;
648
	struct inode *dir;
649
	struct au_xino_entry xinoe;
650
	struct dentry *parent;
651
	struct file *file;
652
653
	LKTRTrace("base_file %p, do_test %d\n", base_file, do_test);
654
	SiMustWriteLock(sb);
655
	AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
656
	AuDebugOn(br->br_xino);
657
658
	do_create = 1;
659
	bshared = -1;
660
	shared_br = NULL;
661
	bend = au_sbend(sb);
662
	if (do_test) {
663
		aufs_bindex_t bindex;
664
665
		struct super_block *tgt_sb = br->br_mnt->mnt_sb;
666
		for (bindex = 0; bindex <= bend; bindex++)
667
			if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) {
668
				bshared = bindex;
669
				break;
670
			}
671
	}
672
	if (unlikely(bshared >= 0)) {
673
		shared_br = au_sbr(sb, bshared);
674
		do_create = !shared_br->br_xino;
675
	}
676
677
	if (do_create) {
678
		parent = dget_parent(base_file->f_dentry);
679
		dir = parent->d_inode;
680
681
		mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
682
		file = au_xino_create2(sb, base_file, NULL);
683
		err = PTR_ERR(file);
684
		mutex_unlock(&dir->i_mutex);
685
		dput(parent);
686
		if (IS_ERR(file))
687
			goto out;
688
		br->br_xino = file;
689
	} else {
690
		br->br_xino = shared_br->br_xino;
691
		get_file(br->br_xino);
692
	}
693
694
	xinoe.ino = AUFS_ROOT_INO;
695
	//xinoe.h_gen = h_inode->i_generation;
696
	//WARN_ON(xinoe.h_gen == AuXino_INVALID_HGEN);
697
	err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino, h_ino,
698
			       &xinoe);
699
	//if (LktrCond) err = -1;
700
	if (!err)
701
		return 0; /* success */
702
703
	//fput(br->br_xino);
704
	//br->br_xino = NULL;
705
706
 out:
707
	AuTraceErr(err);
708
	return err;
709
}
710
711
/* too slow */
712
static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
713
{
714
	int err, bit;
715
	struct au_sbinfo *sbinfo;
716
	au_readf_t func;
717
	loff_t pos, pend;
718
	ssize_t sz;
719
	struct au_xino_entry *xinoe;
720
	unsigned long pindex;
721
722
	AuTraceEnter();
723
	SiMustWriteLock(sb);
724
725
	err = 0;
726
	sbinfo = au_sbi(sb);
727
	func = sbinfo->si_xread;
728
	pend = i_size_read(file->f_dentry->d_inode);
729
#ifdef CONFIG_AUFS_DEBUG
730
	if (unlikely(pend > (1 << 22)))
731
		AuWarn("testing a large xino file %Ld\n", (long long)pend);
732
#endif
733
	pos = 0;
734
	while (pos < pend) {
735
		sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
736
		err = sz;
737
		if (unlikely(sz <= 0))
738
			goto out;
739
740
		err = 0;
741
		for (xinoe = page; sz > 0; xinoe++, sz -= sizeof(xinoe)) {
742
			//AuDbg("i%lu\n", xinoe->ino);
743
			if (unlikely(xinoe->ino < AUFS_FIRST_INO))
744
				continue;
745
746
			xib_calc_bit(xinoe->ino, &pindex, &bit);
747
			AuDebugOn(page_bits <= bit);
748
			err = xib_pindex(sb, pindex);
749
			if (!err)
750
				set_bit(bit, sbinfo->si_xib_buf);
751
			else
752
				goto out;
753
			//AuDbg("i%lu, bit %d\n", xinoe->ino, bit);
754
		}
755
	}
756
757
 out:
758
	AuTraceErr(err);
759
	return err;
760
}
761
762
static int xib_restore(struct super_block *sb)
763
{
764
	int err;
765
	aufs_bindex_t bindex, bend;
766
	void *page;
767
768
	//au_debug_on();
769
	AuTraceEnter();
770
771
	err = -ENOMEM;
772
	page = (void *)__get_free_page(GFP_TEMPORARY);
773
	if (unlikely(!page))
774
		goto out;
775
776
	err = 0;
777
	bend = au_sbend(sb);
778
	for (bindex = 0; !err && bindex <= bend; bindex++)
779
		if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
780
			err = do_xib_restore
781
				(sb, au_sbr(sb, bindex)->br_xino, page);
782
		else
783
			LKTRTrace("b%d\n", bindex);
784
	free_page((unsigned long)page);
785
786
 out:
787
	AuTraceErr(err);
788
	//au_debug_off();
789
	return err;
790
}
791
792
int au_xib_trunc(struct super_block *sb)
793
{
794
	int err;
795
	struct au_sbinfo *sbinfo;
796
	unsigned long *p;
797
	//ino_t ino;
798
	loff_t pos;
799
	ssize_t sz;
800
	struct dentry *parent;
801
	struct inode *dir;
802
	struct file *file;
803
	unsigned int mnt_flags;
804
805
	AuTraceEnter();
806
	SiMustWriteLock(sb);
807
808
	mnt_flags = au_mntflags(sb);
809
	if (unlikely(!au_opt_test(mnt_flags, XINO)))
810
		return 0;
811
812
	//aufs_debug_on();
813
	sbinfo = au_sbi(sb);
814
	parent = dget_parent(sbinfo->si_xib->f_dentry);
815
	dir = parent->d_inode;
816
	mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
817
	file = au_xino_create2(sb, sbinfo->si_xib, NULL);
818
	mutex_unlock(&dir->i_mutex);
819
	dput(parent);
820
	err = PTR_ERR(file);
821
	if (IS_ERR(file))
822
		goto out;
823
	fput(sbinfo->si_xib);
824
	sbinfo->si_xib = file;
825
826
	p = sbinfo->si_xib_buf;
827
	memset(p, 0, PAGE_SIZE);
828
	pos = 0;
829
	sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
830
	if (unlikely(sz != PAGE_SIZE)) {
831
		err = sz;
832
		AuIOErr("err %d\n", err);
833
		if (sz >= 0)
834
			err = -EIO;
835
		goto out;
836
	}
837
838
	if (au_opt_test(mnt_flags, XINO)) {
839
		mutex_lock(&sbinfo->si_xib_mtx);
840
		err = xib_restore(sb);
841
		mutex_unlock(&sbinfo->si_xib_mtx);
842
	}
843
844
out:
845
	//aufs_debug_off();
846
	AuTraceErr(err);
847
	return err;
848
}
849
850
/* ---------------------------------------------------------------------- */
851
852
/*
853
 * xino mount option handlers
854
 */
855
static au_readf_t find_readf(struct file *h_file)
856
{
857
	const struct file_operations *fop = h_file->f_op;
858
859
	if (fop) {
860
		if (fop->read)
861
			return fop->read;
862
		if (fop->aio_read)
863
			return do_sync_read;
864
	}
865
	return ERR_PTR(-ENOSYS);
866
}
867
868
static au_writef_t find_writef(struct file *h_file)
869
{
870
	const struct file_operations *fop = h_file->f_op;
871
872
	if (fop) {
873
		if (fop->write)
874
			return fop->write;
875
		if (fop->aio_write)
876
			return do_sync_write;
877
	}
878
	return ERR_PTR(-ENOSYS);
879
}
880
881
/* xino bitmap */
882
static void xino_clear_xib(struct super_block *sb)
883
{
884
	struct au_sbinfo *sbinfo;
885
886
	AuTraceEnter();
887
	SiMustWriteLock(sb);
888
889
	sbinfo = au_sbi(sb);
890
	sbinfo->si_xread = NULL;
891
	sbinfo->si_xwrite = NULL;
892
	if (sbinfo->si_xib)
893
		fput(sbinfo->si_xib);
894
	sbinfo->si_xib = NULL;
895
	free_page((unsigned long)sbinfo->si_xib_buf);
896
	sbinfo->si_xib_buf = NULL;
897
}
898
899
static int au_xino_set_xib(struct super_block *sb, struct file *base)
900
{
901
	int err;
902
	struct au_sbinfo *sbinfo;
903
	struct file *file;
904
	loff_t pos;
905
906
	LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
907
	SiMustWriteLock(sb);
908
909
	sbinfo = au_sbi(sb);
910
	file = au_xino_create2(sb, base, sbinfo->si_xib);
911
	err = PTR_ERR(file);
912
	if (IS_ERR(file))
913
		goto out;
914
	if (sbinfo->si_xib)
915
		fput(sbinfo->si_xib);
916
	sbinfo->si_xib = file;
917
	sbinfo->si_xread = find_readf(file);
918
	AuDebugOn(IS_ERR(sbinfo->si_xread));
919
	sbinfo->si_xwrite = find_writef(file);
920
	AuDebugOn(IS_ERR(sbinfo->si_xwrite));
921
922
	err = -ENOMEM;
923
	if (!sbinfo->si_xib_buf)
924
		sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_KERNEL);
925
	if (unlikely(!sbinfo->si_xib_buf))
926
		goto out_unset;
927
928
	sbinfo->si_xib_last_pindex = 0;
929
	sbinfo->si_xib_next_bit = 0;
930
931
	/* no need to lock for i_size_read() */
932
	if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
933
		pos = 0;
934
		err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
935
				  PAGE_SIZE, &pos);
936
		if (unlikely(err != PAGE_SIZE))
937
			goto out_free;
938
	}
939
	err = 0;
940
	goto out; /* success */
941
942
 out_free:
943
	free_page((unsigned long)sbinfo->si_xib_buf);
944
	sbinfo->si_xib_buf = NULL;
945
	if (err >= 0)
946
		err = -EIO;
947
 out_unset:
948
	fput(sbinfo->si_xib);
949
	sbinfo->si_xib = NULL;
950
	sbinfo->si_xread = NULL;
951
	sbinfo->si_xwrite = NULL;
952
 out:
953
	AuTraceErr(err);
954
	return err;
955
}
956
957
/* xino for each branch */
958
static void xino_clear_br(struct super_block *sb)
959
{
960
	aufs_bindex_t bindex, bend;
961
	struct au_branch *br;
962
963
	AuTraceEnter();
964
	SiMustWriteLock(sb);
965
966
	bend = au_sbend(sb);
967
	for (bindex = 0; bindex <= bend; bindex++) {
968
		br = au_sbr(sb, bindex);
969
		if (unlikely(!br || !br->br_xino))
970
			continue;
971
972
		fput(br->br_xino);
973
		br->br_xino = NULL;
974
	}
975
}
976
977
static int au_xino_set_br(struct super_block *sb, struct file *base)
978
{
979
	int err;
980
	aufs_bindex_t bindex, bend, bshared;
981
	struct {
982
		struct file *old, *new;
983
	} *fpair, *p;
984
	struct au_branch *br;
985
	struct au_xino_entry xinoe;
986
	struct inode *inode;
987
	au_writef_t writef;
988
989
	//au_debug_on();
990
	LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
991
	SiMustWriteLock(sb);
992
993
	err = -ENOMEM;
994
	bend = au_sbend(sb);
995
	fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_TEMPORARY);
996
	if (unlikely(!fpair))
997
		goto out;
998
999
	inode = sb->s_root->d_inode;
1000
	xinoe.ino = AUFS_ROOT_INO;
1001
	writef = au_sbi(sb)->si_xwrite;
1002
	for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
1003
		br = au_sbr(sb, bindex);
1004
		bshared = is_sb_shared(sb, bindex, bindex - 1);
1005
		if (bshared >= 0) {
1006
			/* shared xino */
1007
			*p = fpair[bshared];
1008
			get_file(p->new);
1009
		}
1010
1011
		if (!p->new) {
1012
			/* new xino */
1013
			p->old = br->br_xino;
1014
			p->new = au_xino_create2(sb, base, br->br_xino);
1015
			err = PTR_ERR(p->new);
1016
			if (IS_ERR(p->new)) {
1017
				p->new = NULL;
1018
				goto out_pair;
1019
			}
1020
		}
1021
1022
		err = au_xino_do_write(writef, p->new,
1023
				       au_h_iptr(inode, bindex)->i_ino, &xinoe);
1024
		if (unlikely(err))
1025
			goto out_pair;
1026
	}
1027
1028
	for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
1029
		br = au_sbr(sb, bindex);
1030
		AuDebugOn(p->old != br->br_xino);
1031
		if (br->br_xino)
1032
			fput(br->br_xino);
1033
		get_file(p->new);
1034
		br->br_xino = p->new;
1035
	}
1036
1037
 out_pair:
1038
	for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
1039
		if (p->new)
1040
			fput(p->new);
1041
		else
1042
			break;
1043
	kfree(fpair);
1044
 out:
1045
	AuTraceErr(err);
1046
	//au_debug_off();
1047
	return err;
1048
}
1049
1050
void au_xino_clr(struct super_block *sb)
1051
{
1052
	AuTraceEnter();
1053
	SiMustWriteLock(sb);
1054
1055
	xino_clear_xib(sb);
1056
	xino_clear_br(sb);
1057
	au_opt_clr(au_sbi(sb)->si_mntflags, XINO);
1058
}
1059
1060
int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
1061
{
1062
	int err, skip;
1063
	struct dentry *parent, *cur_parent;
1064
	struct qstr *dname, *cur_name;
1065
	struct file *cur_xino;
1066
	struct inode *dir;
1067
	struct au_sbinfo *sbinfo;
1068
1069
	LKTRTrace("remount %d\n", remount);
1070
	SiMustWriteLock(sb);
1071
1072
	err = 0;
1073
	sbinfo = au_sbi(sb);
1074
	parent = dget_parent(xino->file->f_dentry);
1075
	if (remount) {
1076
		skip = 0;
1077
		dname = &xino->file->f_dentry->d_name;
1078
		cur_xino = sbinfo->si_xib;
1079
		if (cur_xino) {
1080
			cur_parent = dget_parent(cur_xino->f_dentry);
1081
			cur_name = &cur_xino->f_dentry->d_name;
1082
			skip = (cur_parent == parent
1083
				&& dname->len == cur_name->len
1084
				&& !memcmp(dname->name, cur_name->name,
1085
					   dname->len));
1086
			dput(cur_parent);
1087
		}
1088
		if (skip)
1089
			goto out;
1090
	}
1091
1092
	au_opt_set(sbinfo->si_mntflags, XINO);
1093
	dir = parent->d_inode;
1094
	mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
1095
	err = au_xino_set_xib(sb, xino->file);
1096
	if (!err)
1097
		err = au_xino_set_br(sb, xino->file);
1098
	mutex_unlock(&dir->i_mutex);
1099
	if (!err)
1100
		goto out; /* success */
1101
1102
	/* reset all */
1103
	AuIOErr("failed creating xino, forcing noxino (%d).\n", err);
1104
	err = -EIO;
1105
	au_xino_clr(sb);
1106
1107
 out:
1108
	dput(parent);
1109
	AuTraceErr(err);
1110
	return err;
1111
}
1112
1113
int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
1114
{
1115
	int err;
1116
	struct au_branch *br;
1117
	struct file *new_xino;
1118
	struct super_block *h_sb;
1119
	aufs_bindex_t bi, bend;
1120
	struct dentry *parent;
1121
	struct inode *dir;
1122
1123
	//au_debug_on();
1124
	LKTRTrace("b%d\n", bindex);
1125
	SiMustWriteLock(sb);
1126
1127
	err = -EINVAL;
1128
	bend = au_sbend(sb);
1129
	if (unlikely(bindex < 0 || bend < bindex))
1130
		goto out;
1131
	br = au_sbr(sb, bindex);
1132
	if (unlikely(!br->br_xino))
1133
		goto out;
1134
1135
	parent = dget_parent(br->br_xino->f_dentry);
1136
	dir = parent->d_inode;
1137
	//AuDbgFile(br->br_xino);
1138
	mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
1139
	new_xino = au_xino_create2(sb, br->br_xino, br->br_xino);
1140
	mutex_unlock(&dir->i_mutex);
1141
	//AuDbgFile(new_xino);
1142
	dput(parent);
1143
	err = PTR_ERR(new_xino);
1144
	if (IS_ERR(new_xino))
1145
		goto out;
1146
	err = 0;
1147
	fput(br->br_xino);
1148
	br->br_xino = new_xino;
1149
1150
	h_sb = br->br_mnt->mnt_sb;
1151
	for (bi = 0; bi <= bend; bi++) {
1152
		if (unlikely(bi == bindex))
1153
			continue;
1154
		br = au_sbr(sb, bi);
1155
		if (br->br_mnt->mnt_sb != h_sb)
1156
			continue;
1157
1158
		fput(br->br_xino);
1159
		br->br_xino = new_xino;
1160
		get_file(new_xino);
1161
	}
1162
1163
 out:
1164
	AuTraceErr(err);
1165
	//au_debug_off();
1166
	return err;
1167
}
1168
1169
/* ---------------------------------------------------------------------- */
1170
1171
/*
1172
 * create a xinofile at the default place/path.
1173
 */
1174
struct file *au_xino_def(struct super_block *sb)
1175
{
1176
	struct file *file;
1177
	aufs_bindex_t bend, bindex, bwr;
1178
	char *page, *p;
1179
	struct path path;
1180
1181
	AuTraceEnter();
1182
1183
	bend = au_sbend(sb);
1184
	bwr = -1;
1185
	for (bindex = 0; bindex <= bend; bindex++)
1186
		if (au_br_writable(au_sbr_perm(sb, bindex))
1187
		    && !au_test_nfs(au_h_dptr(sb->s_root, bindex)->d_sb)) {
1188
			bwr = bindex;
1189
			break;
1190
		}
1191
1192
	if (bwr >= 0) {
1193
		file = ERR_PTR(-ENOMEM);
1194
		page = __getname();
1195
		//if (LktrCond) {__putname(page); page = NULL;}
1196
		if (unlikely(!page))
1197
			goto out;
1198
		path.mnt = au_sbr_mnt(sb, bwr);
1199
		path.dentry = au_h_dptr(sb->s_root, bwr);
1200
		p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
1201
		//if (LktrCond) p = ERR_PTR(-1);
1202
		file = (void *)p;
1203
		if (p && !IS_ERR(p)) {
1204
			strcat(p, "/" AUFS_XINO_FNAME);
1205
			LKTRTrace("%s\n", p);
1206
			file = au_xino_create(sb, p, /*silent*/0, sb->s_root);
1207
			//if (LktrCond) {fput(file); file = ERR_PTR(-1);}
1208
		}
1209
		__putname(page);
1210
	} else {
1211
		file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
1212
				      /*parent*/NULL);
1213
		//if (LktrCond) {fput(file); file = ERR_PTR(-1);}
1214
		if (unlikely(au_test_nfs(file->f_dentry->d_sb))) {
1215
			AuErr("xino or noxino option is required "
1216
			      "since %s is NFS\n", AUFS_XINO_DEFPATH);
1217
			fput(file);
1218
			file = ERR_PTR(-EINVAL);
1219
		}
1220
	}
1221
1222
 out:
1223
	AuTraceErrPtr(file);
1224
	return file;
1225
}
(-)linux-2.6.25.4-unionfs.orig/fs/file_table.c (+1 lines)
Lines 308-313 Link Here
308
		file_free(file);
308
		file_free(file);
309
	}
309
	}
310
}
310
}
311
EXPORT_SYMBOL(put_filp);
311
312
312
void file_move(struct file *file, struct list_head *list)
313
void file_move(struct file *file, struct list_head *list)
313
{
314
{
(-)linux-2.6.25.4-unionfs.orig/fs/Kconfig (+2 lines)
Lines 614-619 Link Here
614
	  If you want to develop a userspace FS, or if you want to use
614
	  If you want to develop a userspace FS, or if you want to use
615
	  a filesystem based on FUSE, answer Y or M.
615
	  a filesystem based on FUSE, answer Y or M.
616
616
617
source "fs/aufs/Kconfig"
618
617
config GENERIC_ACL
619
config GENERIC_ACL
618
	bool
620
	bool
619
	select FS_POSIX_ACL
621
	select FS_POSIX_ACL
(-)linux-2.6.25.4-unionfs.orig/fs/Makefile (+1 lines)
Lines 107-112 Link Here
107
obj-$(CONFIG_AUTOFS4_FS)	+= autofs4/
107
obj-$(CONFIG_AUTOFS4_FS)	+= autofs4/
108
obj-$(CONFIG_ADFS_FS)		+= adfs/
108
obj-$(CONFIG_ADFS_FS)		+= adfs/
109
obj-$(CONFIG_FUSE_FS)		+= fuse/
109
obj-$(CONFIG_FUSE_FS)		+= fuse/
110
obj-$(CONFIG_AUFS)		+= aufs/
110
obj-$(CONFIG_UDF_FS)		+= udf/
111
obj-$(CONFIG_UDF_FS)		+= udf/
111
obj-$(CONFIG_SUN_OPENPROMFS)	+= openpromfs/
112
obj-$(CONFIG_SUN_OPENPROMFS)	+= openpromfs/
112
obj-$(CONFIG_JFS_FS)		+= jfs/
113
obj-$(CONFIG_JFS_FS)		+= jfs/
(-)linux-2.6.25.4-unionfs.orig/fs/namei.c (-1 / +3 lines)
Lines 1292-1298 Link Here
1292
	return err;
1292
	return err;
1293
}
1293
}
1294
1294
1295
static struct dentry *__lookup_hash(struct qstr *name,
1295
struct dentry *__lookup_hash(struct qstr *name,
1296
		struct dentry *base, struct nameidata *nd)
1296
		struct dentry *base, struct nameidata *nd)
1297
{
1297
{
1298
	struct dentry *dentry;
1298
	struct dentry *dentry;
Lines 2837-2839 Link Here
2837
EXPORT_SYMBOL(vfs_unlink);
2837
EXPORT_SYMBOL(vfs_unlink);
2838
EXPORT_SYMBOL(dentry_unhash);
2838
EXPORT_SYMBOL(dentry_unhash);
2839
EXPORT_SYMBOL(generic_readlink);
2839
EXPORT_SYMBOL(generic_readlink);
2840
EXPORT_SYMBOL(__lookup_hash);
2841
EXPORT_SYMBOL(deny_write_access);
(-)linux-2.6.25.4-unionfs.orig/fs/splice.c (-1 lines)
Lines 874-880 Link Here
874
{
874
{
875
	return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage);
875
	return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage);
876
}
876
}
877
878
EXPORT_SYMBOL(generic_splice_sendpage);
877
EXPORT_SYMBOL(generic_splice_sendpage);
879
878
880
/*
879
/*
(-)linux-2.6.25.4-unionfs.orig/fs/super.c (+1 lines)
Lines 267-272 Link Here
267
	__fsync_super(sb);
267
	__fsync_super(sb);
268
	return sync_blockdev(sb->s_bdev);
268
	return sync_blockdev(sb->s_bdev);
269
}
269
}
270
EXPORT_SYMBOL(fsync_super);
270
271
271
/**
272
/**
272
 *	generic_shutdown_super	-	common helper for ->kill_sb()
273
 *	generic_shutdown_super	-	common helper for ->kill_sb()
(-)linux-2.6.25.4-unionfs.orig/include/linux/aufs_type.h (+111 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2005, 2006, 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
/* $Id: aufs_type.h,v 1.105 2008/05/04 23:55:14 sfjro Exp $ */
20
21
#include <linux/ioctl.h>
22
23
#ifndef __AUFS_TYPE_H__
24
#define __AUFS_TYPE_H__
25
26
#define AUFS_VERSION	"20080505"
27
28
/* move this to linux-2.6.19/include/magic.h */
29
#define AUFS_SUPER_MAGIC	('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
30
31
/* ---------------------------------------------------------------------- */
32
33
#ifdef CONFIG_AUFS_BRANCH_MAX_127
34
/* some environments treat 'char' as 'unsigned char' by default */
35
typedef signed char aufs_bindex_t;
36
#define AUFS_BRANCH_MAX 127
37
#else
38
typedef short aufs_bindex_t;
39
#ifdef CONFIG_AUFS_BRANCH_MAX_511
40
#define AUFS_BRANCH_MAX 511
41
#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
42
#define AUFS_BRANCH_MAX 1023
43
#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
44
#define AUFS_BRANCH_MAX 32767
45
#else
46
#error unknown CONFIG_AUFS_BRANCH_MAX value
47
#endif
48
#endif
49
50
#define AUFS_NAME		"aufs"
51
#define AUFS_FSTYPE		AUFS_NAME
52
53
#define AUFS_ROOT_INO		2
54
#define AUFS_FIRST_INO		11
55
56
#define AUFS_WH_PFX		".wh."
57
#define AUFS_WH_PFX_LEN		((int)sizeof(AUFS_WH_PFX) - 1)
58
#define AUFS_XINO_FNAME		"." AUFS_NAME ".xino"
59
#define AUFS_XINO_DEFPATH	"/tmp/" AUFS_XINO_FNAME
60
#define AUFS_XINO_TRUNC_INIT	64 /* blocks */
61
#define AUFS_XINO_TRUNC_STEP	4  /* blocks */
62
#define AUFS_DIRWH_DEF		3
63
#define AUFS_RDCACHE_DEF	10 /* seconds */
64
#define AUFS_WKQ_NAME		AUFS_NAME "d"
65
#define AUFS_NWKQ_DEF		4
66
#define AUFS_MFS_SECOND_DEF	30 /* seconds */
67
#define AUFS_PLINK_WARN		100 /* number of plinks */
68
69
#ifdef CONFIG_AUFS_COMPAT
70
#define AUFS_DIROPQ_NAME	"__dir_opaque"
71
#else
72
#define AUFS_DIROPQ_NAME	AUFS_WH_PFX ".opq" /* whiteouted doubly */
73
#endif
74
#define AUFS_WH_DIROPQ		AUFS_WH_PFX AUFS_DIROPQ_NAME
75
76
/* will be whiteouted doubly */
77
#define AUFS_WH_BASENAME	AUFS_WH_PFX AUFS_NAME
78
#define AUFS_WH_PLINKDIR	AUFS_WH_PFX "plink"
79
80
/* ---------------------------------------------------------------------- */
81
82
/* ioctl */
83
enum {
84
	AuCtlErr,
85
	AuCtlErr_Last
86
};
87
enum {
88
	AuCtl_REFRESH, //AuCtl_REFRESHV,
89
	//AuCtl_FLUSH_PLINK,
90
	//AuCtl_CPUP,
91
	AuCtl_CPDOWN, AuCtl_MVDOWN,
92
	//AuCtl_DIROPQ
93
};
94
95
struct aufs_ctl_cp {
96
	int bsrc, bdst;
97
	int err;
98
};
99
100
#define AuCtlType		'A'
101
#define AUFS_CTL_REFRESH	_IO(AuCtlType, AuCtl_REFRESH)
102
//#define AUFS_CTL_REFRESHV	_IO(AuCtlType, AuCtl_REFRESHV)
103
//#define AUFS_CTL_FLUSH_PLINK	_IOR(AuCtlType, AuCtl_FLUSH_PLINK)
104
//#define AUFS_CTL_CPUP		_IOWR(AuCtlType, AuCtl_CPUP, struct aufs_ctl_cp)
105
#define AUFS_CTL_CPDOWN \
106
	_IOWR(AuCtlType, AuCtl_CPDOWN, struct aufs_ctl_cp)
107
#define AUFS_CTL_MVDOWN \
108
	_IOWR(AuCtlType, AuCtl_MVDOWN, struct aufs_ctl_cp)
109
//#define AUFS_CTL_DIROPQ		_IO(AuCtlType, AuCtl_DIROPQ)
110
111
#endif /* __AUFS_TYPE_H__ */
(-)linux-2.6.25.4-unionfs.orig/include/linux/namei.h (+1 lines)
Lines 71-76 Link Here
71
extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags);
71
extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags);
72
extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
72
extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
73
		int (*open)(struct inode *, struct file *));
73
		int (*open)(struct inode *, struct file *));
74
struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd);
74
extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
75
extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
75
extern void release_open_intent(struct nameidata *);
76
extern void release_open_intent(struct nameidata *);
76
77
(-)linux-2.6.25.4-unionfs.orig/include/linux/splice.h (-1 lines)
Lines 75-79 Link Here
75
extern long vfs_splice_to(struct file *in, loff_t *ppos,
75
extern long vfs_splice_to(struct file *in, loff_t *ppos,
76
			  struct pipe_inode_info *pipe, size_t len,
76
			  struct pipe_inode_info *pipe, size_t len,
77
			  unsigned int flags);
77
			  unsigned int flags);
78
79
#endif
78
#endif
(-)linux-2.6.25.4-unionfs.orig/security/security.c (+1 lines)
Lines 433-438 Link Here
433
		return 0;
433
		return 0;
434
	return security_ops->inode_permission(inode, mask, nd);
434
	return security_ops->inode_permission(inode, mask, nd);
435
}
435
}
436
EXPORT_SYMBOL(security_inode_permission);
436
437
437
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
438
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
438
{
439
{

Return to bug 15838