Magellan Linux

Contents of /trunk/kernel26-magellan/patches-2.6.21-r3/0153-2.6.21-unionfs-2.0-u2.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 220 - (show annotations) (download)
Sun Jun 10 22:40:30 2007 UTC (16 years, 10 months ago) by niro
File size: 247073 byte(s)
files for 2.6.21-magellan-r3

1 diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
2 index 5717858..2ef035e 100644
3 --- a/Documentation/filesystems/00-INDEX
4 +++ b/Documentation/filesystems/00-INDEX
5 @@ -84,6 +84,8 @@ udf.txt
6 - info and mount options for the UDF filesystem.
7 ufs.txt
8 - info on the ufs filesystem.
9 +unionfs/
10 + - info on the unionfs filesystem
11 vfat.txt
12 - info on using the VFAT filesystem used in Windows NT and Windows 95
13 vfs.txt
14 diff --git a/Documentation/filesystems/unionfs/00-INDEX b/Documentation/filesystems/unionfs/00-INDEX
15 new file mode 100644
16 index 0000000..96fdf67
17 --- /dev/null
18 +++ b/Documentation/filesystems/unionfs/00-INDEX
19 @@ -0,0 +1,10 @@
20 +00-INDEX
21 + - this file.
22 +concepts.txt
23 + - A brief introduction of concepts.
24 +issues.txt
25 + - A summary of known issues with unionfs.
26 +rename.txt
27 + - Information regarding rename operations.
28 +usage.txt
29 + - Usage information and examples.
30 diff --git a/Documentation/filesystems/unionfs/concepts.txt b/Documentation/filesystems/unionfs/concepts.txt
31 new file mode 100644
32 index 0000000..83d45b9
33 --- /dev/null
34 +++ b/Documentation/filesystems/unionfs/concepts.txt
35 @@ -0,0 +1,75 @@
36 +Unionfs 2.0 CONCEPTS:
37 +=====================
38 +
39 +This file describes the concepts needed by a namespace unification file
40 +system.
41 +
42 +Branch Priority:
43 +================
44 +
45 +Each branch is assigned a unique priority - starting from 0 (highest
46 +priority). No two branches can have the same priority.
47 +
48 +
49 +Branch Mode:
50 +============
51 +
52 +Each branch is assigned a mode - read-write or read-only. This allows
53 +directories on media mounted read-write to be used in a read-only manner.
54 +
55 +
56 +Whiteouts:
57 +==========
58 +
59 +A whiteout removes a file name from the namespace. Whiteouts are needed when
60 +one attempts to remove a file on a read-only branch.
61 +
62 +Suppose we have a two-branch union, where branch 0 is read-write and branch
63 +1 is read-only. And a file 'foo' on branch 1:
64 +
65 +./b0/
66 +./b1/
67 +./b1/foo
68 +
69 +The unified view would simply be:
70 +
71 +./union/
72 +./union/foo
73 +
74 +Since 'foo' is stored on a read-only branch, it cannot be removed. A
75 +whiteout is used to remove the name 'foo' from the unified namespace. Again,
76 +since branch 1 is read-only, the whiteout cannot be created there. So, we
77 +try on a higher priority (lower numerically) branch and create the whiteout
78 +there.
79 +
80 +./b0/
81 +./b0/.wh.foo
82 +./b1/
83 +./b1/foo
84 +
85 +Later, when Unionfs traverses branches (due to lookup or readdir), it
86 +eliminate 'foo' from the namespace (as well as the whiteout itself.)
87 +
88 +
89 +Duplicate Elimination:
90 +======================
91 +
92 +It is possible for files on different branches to have the same name.
93 +Unionfs then has to select which instance of the file to show to the user.
94 +Given the fact that each branch has a priority associated with it, the
95 +simplest solution is to take the instance from the highest priority
96 +(numerically lowest value) and "hide" the others.
97 +
98 +
99 +Copyup:
100 +=======
101 +
102 +When a change is made to the contents of a file's data or meta-data, they
103 +have to be stored somewhere. The best way is to create a copy of the
104 +original file on a branch that is writable, and then redirect the write
105 +though to this copy. The copy must be made on a higher priority branch so
106 +that lookup and readdir return this newer "version" of the file rather than
107 +the original (see duplicate elimination).
108 +
109 +
110 +For more information, see <http://unionfs.filesystems.org/>.
111 diff --git a/Documentation/filesystems/unionfs/issues.txt b/Documentation/filesystems/unionfs/issues.txt
112 new file mode 100644
113 index 0000000..a434fee
114 --- /dev/null
115 +++ b/Documentation/filesystems/unionfs/issues.txt
116 @@ -0,0 +1,39 @@
117 +KNOWN Unionfs 2.0 ISSUES:
118 +=========================
119 +
120 +1. The NFS server returns -EACCES for read-only exports, instead of -EROFS.
121 + This means we can't reliably detect a read-only NFS export.
122 +
123 +2. Modifying a Unionfs branch directly, while the union is mounted, is
124 + currently unsupported. We have tested Unionfs under such conditions, and
125 + fixed any bugs we found (Unionfs comes with an extensive regression test
126 + suite). However, it may still be possible that changes made to lower
127 + branches directly could cause cache incoherency which, in the worst case,
128 + may case an oops. We are currently addressing this problem for Unionfs
129 + and also generically for all stackable file systems, by handing mmap and
130 + introducing small VFS/MM changes that would allow a file system to handle
131 + cache coherency correctly.
132 +
133 + Unionfs 2.0 has a temporary workaround for this. You can force Unionfs
134 + to increase the superblock generation number, and hence purge all cached
135 + Unionfs objects, which would then be re-gotten from the lower branches.
136 + This should ensure cache consistency. To increase the generation number,
137 + executed the command:
138 +
139 + mount -t unionfs -o remount,incgen none MOUNTPOINT
140 +
141 + Note that the older way of incrementing the generation number using an
142 + ioctl, is no longer supported in Unionfs 2.0. Ioctls in general are not
143 + encouraged. Plus, an ioctl is per-file concept, whereas the generation
144 + number is a per-file-system concept. Worse, such an ioctl requires an
145 + open file, which then has to be invalidated by the very nature of the
146 + generation number increase (read: the old generation increase ioctl was
147 + pretty racy).
148 +
149 +3. Unionfs should not use lookup_one_len() on the underlying f/s as it
150 + confuses NFS. Currently, unionfs_lookup() passes lookup intents to the
151 + lower file-system, this eliminates part of the problem. The remaining
152 + calls to lookup_one_len may need to be changed to pass an intent.
153 +
154 +
155 +For more information, see <http://unionfs.filesystems.org/>.
156 diff --git a/Documentation/filesystems/unionfs/rename.txt b/Documentation/filesystems/unionfs/rename.txt
157 new file mode 100644
158 index 0000000..e20bb82
159 --- /dev/null
160 +++ b/Documentation/filesystems/unionfs/rename.txt
161 @@ -0,0 +1,31 @@
162 +Rename is a complex beast. The following table shows which rename(2) operations
163 +should succeed and which should fail.
164 +
165 +o: success
166 +E: error (either unionfs or vfs)
167 +X: EXDEV
168 +
169 +none = file does not exist
170 +file = file is a file
171 +dir = file is a empty directory
172 +child= file is a non-empty directory
173 +wh = file is a directory containing only whiteouts; this makes it logically
174 + empty
175 +
176 + none file dir child wh
177 +file o o E E E
178 +dir o E o E o
179 +child X E X E X
180 +wh o E o E o
181 +
182 +
183 +Renaming directories:
184 +=====================
185 +
186 +Whenever a empty (either physically or logically) directory is being renamed,
187 +the following sequence of events should take place:
188 +
189 +1) Remove whiteouts from both source and destination directory
190 +2) Rename source to destination
191 +3) Make destination opaque to prevent anything under it from showing up
192 +
193 diff --git a/Documentation/filesystems/unionfs/usage.txt b/Documentation/filesystems/unionfs/usage.txt
194 new file mode 100644
195 index 0000000..13fbcea
196 --- /dev/null
197 +++ b/Documentation/filesystems/unionfs/usage.txt
198 @@ -0,0 +1,90 @@
199 +Unionfs is a stackable unification file system, which can appear to merge
200 +the contents of several directories (branches), while keeping their physical
201 +content separate. Unionfs is useful for unified source tree management,
202 +merged contents of split CD-ROM, merged separate software package
203 +directories, data grids, and more. Unionfs allows any mix of read-only and
204 +read-write branches, as well as insertion and deletion of branches anywhere
205 +in the fan-out. To maintain Unix semantics, Unionfs handles elimination of
206 +duplicates, partial-error conditions, and more.
207 +
208 +# mount -t unionfs -o branch-option[,union-options[,...]] none MOUNTPOINT
209 +
210 +The available branch-option for the mount command is:
211 +
212 + dirs=branch[=ro|=rw][:...]
213 +
214 +specifies a separated list of which directories compose the union.
215 +Directories that come earlier in the list have a higher precedence than
216 +those which come later. Additionally, read-only or read-write permissions of
217 +the branch can be specified by appending =ro or =rw (default) to each
218 +directory.
219 +
220 +Syntax:
221 +
222 + dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw]
223 +
224 +Example:
225 +
226 + dirs=/writable_branch=rw:/read-only_branch=ro
227 +
228 +
229 +DYNAMIC BRANCH MANAGEMENT AND REMOUNTS
230 +======================================
231 +
232 +You can remount a union and change its overall mode, or reconfigure the
233 +branches, as follows.
234 +
235 +To downgrade a union from read-write to read-only:
236 +
237 +# mount -t unionfs -o remount,ro none MOUNTPOINT
238 +
239 +To upgrade a union from read-only to read-write:
240 +
241 +# mount -t unionfs -o remount,rw none MOUNTPOINT
242 +
243 +To delete a branch /foo, regardless where it is in the current union:
244 +
245 +# mount -t unionfs -o del=/foo none MOUNTPOINT
246 +
247 +To insert (add) a branch /foo before /bar:
248 +
249 +# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT
250 +
251 +To insert (add) a branch /foo (with the "rw" mode flag) before /bar:
252 +
253 +# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT
254 +
255 +To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a
256 +new highest-priority branch), you can use the above syntax, or use a short
257 +hand version as follows:
258 +
259 +# mount -t unionfs -o remount,add=/foo none MOUNTPOINT
260 +
261 +To append a branch to the very end (new lowest-priority branch):
262 +
263 +# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT
264 +
265 +To append a branch to the very end (new lowest-priority branch), in
266 +read-only mode:
267 +
268 +# mount -t unionfs -o remount,add=:/foo:ro none MOUNTPOINT
269 +
270 +Finally, to change the mode of one existing branch, say /foo, from read-only
271 +to read-write, and change /bar from read-write to read-only:
272 +
273 +# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT
274 +
275 +
276 +CACHE CONSISTENCY
277 +=================
278 +
279 +If you modify any file on any of the lower branches directly, while there is
280 +a Unionfs 2.0 mounted above any of those branches, you should tell Unionfs
281 +to purge its caches and re-get the objects. To do that, you have to
282 +incremenet the generation number of the superblock using the following
283 +command:
284 +
285 +# mount -t unionfs -o remount,remount,incgen none MOUNTPOINT
286 +
287 +
288 +For more information, see <http://unionfs.filesystems.org/>.
289 diff --git a/MAINTAINERS b/MAINTAINERS
290 index 277877a..0b728ac 100644
291 --- a/MAINTAINERS
292 +++ b/MAINTAINERS
293 @@ -3364,6 +3364,13 @@ L: linux-kernel@vger.kernel.org
294 W: http://www.kernel.dk
295 S: Maintained
296
297 +UNIONFS
298 +P: Josef "Jeff" Sipek
299 +M: jsipek@cs.sunysb.edu
300 +L: unionfs@filesystems.org
301 +W: http://unionfs.filesystems.org
302 +S: Maintained
303 +
304 USB ACM DRIVER
305 P: Oliver Neukum
306 M: oliver@neukum.name
307 diff --git a/fs/Kconfig b/fs/Kconfig
308 index 3c4886b..a8cebe3 100644
309 --- a/fs/Kconfig
310 +++ b/fs/Kconfig
311 @@ -1034,6 +1034,41 @@ config CONFIGFS_FS
312
313 endmenu
314
315 +menu "Layered filesystems"
316 +
317 +config ECRYPT_FS
318 + tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
319 + depends on EXPERIMENTAL && KEYS && CRYPTO && NET
320 + help
321 + Encrypted filesystem that operates on the VFS layer. See
322 + <file:Documentation/ecryptfs.txt> to learn more about
323 + eCryptfs. Userspace components are required and can be
324 + obtained from <http://ecryptfs.sf.net>.
325 +
326 + To compile this file system support as a module, choose M here: the
327 + module will be called ecryptfs.
328 +
329 +config UNION_FS
330 + tristate "Union file system (EXPERIMENTAL)"
331 + depends on SLAB && EXPERIMENTAL
332 + help
333 + Unionfs is a stackable unification file system, which appears to
334 + merge the contents of several directories (branches), while keeping
335 + their physical content separate.
336 +
337 + See <http://unionfs.filesystems.org> for details
338 +
339 +config UNION_FS_XATTR
340 + bool "Unionfs extended attributes"
341 + depends on UNION_FS
342 + help
343 + Extended attributes are name:value pairs associated with inodes by
344 + the kernel or by users (see the attr(5) manual page).
345 +
346 + If unsure, say N.
347 +
348 +endmenu
349 +
350 menu "Miscellaneous filesystems"
351
352 config ADFS_FS
353 @@ -1086,18 +1121,6 @@ config AFFS_FS
354 To compile this file system support as a module, choose M here: the
355 module will be called affs. If unsure, say N.
356
357 -config ECRYPT_FS
358 - tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
359 - depends on EXPERIMENTAL && KEYS && CRYPTO && NET
360 - help
361 - Encrypted filesystem that operates on the VFS layer. See
362 - <file:Documentation/ecryptfs.txt> to learn more about
363 - eCryptfs. Userspace components are required and can be
364 - obtained from <http://ecryptfs.sf.net>.
365 -
366 - To compile this file system support as a module, choose M here: the
367 - module will be called ecryptfs.
368 -
369 config HFS_FS
370 tristate "Apple Macintosh file system support (EXPERIMENTAL)"
371 depends on BLOCK && EXPERIMENTAL
372 diff --git a/fs/Makefile b/fs/Makefile
373 index 9edf411..b490b1a 100644
374 --- a/fs/Makefile
375 +++ b/fs/Makefile
376 @@ -114,3 +114,4 @@ obj-$(CONFIG_HPPFS) += hppfs/
377 obj-$(CONFIG_DEBUG_FS) += debugfs/
378 obj-$(CONFIG_OCFS2_FS) += ocfs2/
379 obj-$(CONFIG_GFS2_FS) += gfs2/
380 +obj-$(CONFIG_UNION_FS) += unionfs/
381 diff --git a/fs/drop_caches.c b/fs/drop_caches.c
382 index 03ea769..6a7aa05 100644
383 --- a/fs/drop_caches.c
384 +++ b/fs/drop_caches.c
385 @@ -3,6 +3,7 @@
386 */
387
388 #include <linux/kernel.h>
389 +#include <linux/module.h>
390 #include <linux/mm.h>
391 #include <linux/fs.h>
392 #include <linux/writeback.h>
393 @@ -12,7 +13,7 @@
394 /* A global variable is a bit ugly, but it keeps the code simple */
395 int sysctl_drop_caches;
396
397 -static void drop_pagecache_sb(struct super_block *sb)
398 +void drop_pagecache_sb(struct super_block *sb)
399 {
400 struct inode *inode;
401
402 @@ -24,6 +25,7 @@ static void drop_pagecache_sb(struct super_block *sb)
403 }
404 spin_unlock(&inode_lock);
405 }
406 +EXPORT_SYMBOL(drop_pagecache_sb);
407
408 void drop_pagecache(void)
409 {
410 diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
411 index 1548be2..6655918 100644
412 --- a/fs/ecryptfs/inode.c
413 +++ b/fs/ecryptfs/inode.c
414 @@ -280,7 +280,9 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
415 int rc = 0;
416 struct dentry *lower_dir_dentry;
417 struct dentry *lower_dentry;
418 + struct dentry *dentry_save;
419 struct vfsmount *lower_mnt;
420 + struct vfsmount *mnt_save;
421 char *encoded_name;
422 unsigned int encoded_namelen;
423 struct ecryptfs_crypt_stat *crypt_stat = NULL;
424 @@ -308,9 +310,13 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
425 }
426 ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen "
427 "= [%d]\n", encoded_name, encoded_namelen);
428 - lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry,
429 - encoded_namelen - 1);
430 + dentry_save = nd->dentry;
431 + mnt_save = nd->mnt;
432 + lower_dentry = lookup_one_len_nd(encoded_name, lower_dir_dentry,
433 + (encoded_namelen - 1), nd);
434 kfree(encoded_name);
435 + nd->mnt = mnt_save;
436 + nd->dentry = dentry_save;
437 if (IS_ERR(lower_dentry)) {
438 ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n");
439 rc = PTR_ERR(lower_dentry);
440 diff --git a/fs/namei.c b/fs/namei.c
441 index ee60cc4..2995fba 100644
442 --- a/fs/namei.c
443 +++ b/fs/namei.c
444 @@ -1292,8 +1292,8 @@ static struct dentry *lookup_hash(struct nameidata *nd)
445 return __lookup_hash(&nd->last, nd->dentry, nd);
446 }
447
448 -/* SMP-safe */
449 -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
450 +struct dentry *lookup_one_len_nd(const char *name, struct dentry *base,
451 + int len, struct nameidata *nd)
452 {
453 unsigned long hash;
454 struct qstr this;
455 @@ -1313,7 +1313,7 @@ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
456 }
457 this.hash = end_name_hash(hash);
458
459 - return __lookup_hash(&this, base, NULL);
460 + return __lookup_hash(&this, base, nd);
461 access:
462 return ERR_PTR(-EACCES);
463 }
464 @@ -2758,7 +2758,7 @@ EXPORT_SYMBOL(follow_up);
465 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
466 EXPORT_SYMBOL(getname);
467 EXPORT_SYMBOL(lock_rename);
468 -EXPORT_SYMBOL(lookup_one_len);
469 +EXPORT_SYMBOL(lookup_one_len_nd);
470 EXPORT_SYMBOL(page_follow_link_light);
471 EXPORT_SYMBOL(page_put_link);
472 EXPORT_SYMBOL(page_readlink);
473 diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
474 new file mode 100644
475 index 0000000..e6b2e0c
476 --- /dev/null
477 +++ b/fs/unionfs/Makefile
478 @@ -0,0 +1,7 @@
479 +obj-$(CONFIG_UNION_FS) += unionfs.o
480 +
481 +unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
482 + branchman.o rdstate.o copyup.o dirhelper.o rename.o \
483 + unlink.o lookup.o commonfops.o dirfops.o sioq.o
484 +
485 +unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
486 diff --git a/fs/unionfs/branchman.c b/fs/unionfs/branchman.c
487 new file mode 100644
488 index 0000000..6912be9
489 --- /dev/null
490 +++ b/fs/unionfs/branchman.c
491 @@ -0,0 +1,60 @@
492 +/*
493 + * Copyright (c) 2003-2007 Erez Zadok
494 + * Copyright (c) 2003-2006 Charles P. Wright
495 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
496 + * Copyright (c) 2005-2006 Junjiro Okajima
497 + * Copyright (c) 2005 Arun M. Krishnakumar
498 + * Copyright (c) 2004-2006 David P. Quigley
499 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
500 + * Copyright (c) 2003 Puja Gupta
501 + * Copyright (c) 2003 Harikesavan Krishnan
502 + * Copyright (c) 2003-2007 Stony Brook University
503 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
504 + *
505 + * This program is free software; you can redistribute it and/or modify
506 + * it under the terms of the GNU General Public License version 2 as
507 + * published by the Free Software Foundation.
508 + */
509 +
510 +#include "union.h"
511 +
512 +/* return to userspace the branch indices containing the file in question
513 + *
514 + * We use fd_set and therefore we are limited to the number of the branches
515 + * to FD_SETSIZE, which is currently 1024 - plenty for most people
516 + */
517 +int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd,
518 + unsigned long arg)
519 +{
520 + int err = 0;
521 + fd_set branchlist;
522 +
523 + int bstart = 0, bend = 0, bindex = 0;
524 + struct dentry *dentry, *hidden_dentry;
525 +
526 + dentry = file->f_dentry;
527 + unionfs_lock_dentry(dentry);
528 + if ((err = unionfs_partial_lookup(dentry)))
529 + goto out;
530 + bstart = dbstart(dentry);
531 + bend = dbend(dentry);
532 +
533 + FD_ZERO(&branchlist);
534 +
535 + for (bindex = bstart; bindex <= bend; bindex++) {
536 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
537 + if (!hidden_dentry)
538 + continue;
539 + if (hidden_dentry->d_inode)
540 + FD_SET(bindex, &branchlist);
541 + }
542 +
543 + err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
544 + if (err)
545 + err = -EFAULT;
546 +
547 +out:
548 + unionfs_unlock_dentry(dentry);
549 + return err < 0 ? err : bend;
550 +}
551 +
552 diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
553 new file mode 100644
554 index 0000000..c9df99d
555 --- /dev/null
556 +++ b/fs/unionfs/commonfops.c
557 @@ -0,0 +1,687 @@
558 +/*
559 + * Copyright (c) 2003-2007 Erez Zadok
560 + * Copyright (c) 2003-2006 Charles P. Wright
561 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
562 + * Copyright (c) 2005-2006 Junjiro Okajima
563 + * Copyright (c) 2005 Arun M. Krishnakumar
564 + * Copyright (c) 2004-2006 David P. Quigley
565 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
566 + * Copyright (c) 2003 Puja Gupta
567 + * Copyright (c) 2003 Harikesavan Krishnan
568 + * Copyright (c) 2003-2007 Stony Brook University
569 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
570 + *
571 + * This program is free software; you can redistribute it and/or modify
572 + * it under the terms of the GNU General Public License version 2 as
573 + * published by the Free Software Foundation.
574 + */
575 +
576 +#include "union.h"
577 +
578 +/* 1) Copyup the file
579 + * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously
580 + * stolen from NFS's silly rename
581 + */
582 +static int copyup_deleted_file(struct file *file, struct dentry *dentry,
583 + int bstart, int bindex)
584 +{
585 + static unsigned int counter;
586 + const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2;
587 + const int countersize = sizeof(counter) * 2;
588 + const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
589 + char name[nlen + 1];
590 +
591 + int err;
592 + struct dentry *tmp_dentry = NULL;
593 + struct dentry *hidden_dentry;
594 + struct dentry *hidden_dir_dentry = NULL;
595 +
596 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bstart);
597 +
598 + sprintf(name, ".unionfs%*.*lx",
599 + i_inosize, i_inosize, hidden_dentry->d_inode->i_ino);
600 +
601 + /*
602 + * Loop, looking for an unused temp name to copyup to.
603 + *
604 + * It's somewhat silly that we look for a free temp tmp name in the
605 + * source branch (bstart) instead of the dest branch (bindex), where
606 + * the final name will be created. We _will_ catch it if somehow
607 + * the name exists in the dest branch, but it'd be nice to catch it
608 + * sooner than later.
609 + */
610 + tmp_dentry = NULL;
611 + do {
612 + char *suffix = name + nlen - countersize;
613 +
614 + dput(tmp_dentry);
615 + counter++;
616 + sprintf(suffix, "%*.*x", countersize, countersize, counter);
617 +
618 + printk(KERN_DEBUG "unionfs: trying to rename %s to %s\n",
619 + dentry->d_name.name, name);
620 +
621 + tmp_dentry = lookup_one_len(name, hidden_dentry->d_parent,
622 + UNIONFS_TMPNAM_LEN);
623 + if (IS_ERR(tmp_dentry)) {
624 + err = PTR_ERR(tmp_dentry);
625 + goto out;
626 + }
627 + /* don't dput here because of do-while condition eval order */
628 + } while (tmp_dentry->d_inode != NULL); /* need negative dentry */
629 + dput(tmp_dentry);
630 +
631 + err = copyup_named_file(dentry->d_parent->d_inode, file, name, bstart,
632 + bindex, file->f_dentry->d_inode->i_size);
633 + if (err)
634 + goto out;
635 +
636 + /* bring it to the same state as an unlinked file */
637 + hidden_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
638 + hidden_dir_dentry = lock_parent(hidden_dentry);
639 + err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
640 + unlock_dir(hidden_dir_dentry);
641 +
642 +out:
643 + return err;
644 +}
645 +
646 +/*
647 + * Find new index of matching branch with an open file, since branches could
648 + * have been added/deleted causing the one with open files to shift.
649 + *
650 + * @file: current file whose branches may have changed
651 + * @bindex: index of branch within current file (could be old branch)
652 + * @new_sb: the new superblock which may have new branch IDs
653 + * Returns index of newly found branch (0 or greater), -1 otherwise.
654 + */
655 +static int find_new_branch_index(struct file *file, int bindex,
656 + struct super_block *new_sb)
657 +{
658 + int old_branch_id = UNIONFS_F(file)->saved_branch_ids[bindex];
659 + int i;
660 +
661 + for (i = 0; i < sbmax(new_sb); i++)
662 + if (old_branch_id == branch_id(new_sb, i))
663 + return i;
664 + /*
665 + * XXX: maybe we should BUG_ON if not found new branch index?
666 + * (really that should never happen).
667 + */
668 + return -1;
669 +}
670 +
671 +/* put all references held by upper struct file and free lower file pointer
672 + * array
673 + */
674 +static void cleanup_file(struct file *file)
675 +{
676 + int bindex, bstart, bend;
677 + struct file **lf;
678 + struct super_block *sb = file->f_dentry->d_sb;
679 +
680 + lf = UNIONFS_F(file)->lower_files;
681 + bstart = fbstart(file);
682 + bend = fbend(file);
683 +
684 + for (bindex = bstart; bindex <= bend; bindex++) {
685 + if (unionfs_lower_file_idx(file, bindex)) {
686 + int i; /* holds (possibly) updated branch index */
687 + i = find_new_branch_index(file, bindex, sb);
688 + if (i < 0)
689 + printk(KERN_ERR "unionfs: no supberlock for file %p\n",
690 + file);
691 + else {
692 + unionfs_read_lock(sb);
693 + branchput(sb, i);
694 + unionfs_read_unlock(sb);
695 + /* XXX: is it correct to use sb->s_root here? */
696 + unionfs_mntput(sb->s_root, i);
697 + /* XXX: mntget b/c fput below will call mntput */
698 + unionfs_mntget(sb->s_root, bindex);
699 + }
700 + fput(unionfs_lower_file_idx(file, bindex));
701 + }
702 + }
703 +
704 + UNIONFS_F(file)->lower_files = NULL;
705 + kfree(lf);
706 + kfree(UNIONFS_F(file)->saved_branch_ids);
707 + /* set to NULL because caller needs to know if to kfree on error */
708 + UNIONFS_F(file)->saved_branch_ids = NULL;
709 +}
710 +
711 +/* open all lower files for a given file */
712 +static int open_all_files(struct file *file)
713 +{
714 + int bindex, bstart, bend, err = 0;
715 + struct file *hidden_file;
716 + struct dentry *hidden_dentry;
717 + struct dentry *dentry = file->f_dentry;
718 + struct super_block *sb = dentry->d_sb;
719 +
720 + bstart = dbstart(dentry);
721 + bend = dbend(dentry);
722 +
723 + for (bindex = bstart; bindex <= bend; bindex++) {
724 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
725 + if (!hidden_dentry)
726 + continue;
727 +
728 + dget(hidden_dentry);
729 + unionfs_mntget(dentry, bindex);
730 + unionfs_read_lock(sb);
731 + branchget(sb, bindex);
732 + unionfs_read_unlock(sb);
733 +
734 + hidden_file = dentry_open(hidden_dentry,
735 + unionfs_lower_mnt_idx(dentry, bindex),
736 + file->f_flags);
737 + if (IS_ERR(hidden_file)) {
738 + err = PTR_ERR(hidden_file);
739 + goto out;
740 + } else
741 + unionfs_set_lower_file_idx(file, bindex, hidden_file);
742 + }
743 +out:
744 + return err;
745 +}
746 +
747 +/* open the highest priority file for a given upper file */
748 +static int open_highest_file(struct file *file, int willwrite)
749 +{
750 + int bindex, bstart, bend, err = 0;
751 + struct file *hidden_file;
752 + struct dentry *hidden_dentry;
753 +
754 + struct dentry *dentry = file->f_dentry;
755 + struct inode *parent_inode = dentry->d_parent->d_inode;
756 + struct super_block *sb = dentry->d_sb;
757 + size_t inode_size = dentry->d_inode->i_size;
758 +
759 + bstart = dbstart(dentry);
760 + bend = dbend(dentry);
761 +
762 + hidden_dentry = unionfs_lower_dentry(dentry);
763 + if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) {
764 + for (bindex = bstart - 1; bindex >= 0; bindex--) {
765 + err = copyup_file(parent_inode, file, bstart, bindex,
766 + inode_size);
767 + if (!err)
768 + break;
769 + }
770 + atomic_set(&UNIONFS_F(file)->generation,
771 + atomic_read(&UNIONFS_I(dentry->d_inode)->generation));
772 + goto out;
773 + }
774 +
775 + dget(hidden_dentry);
776 + unionfs_mntget(dentry, bstart);
777 + unionfs_read_lock(sb);
778 + branchget(sb, bstart);
779 + unionfs_read_unlock(sb);
780 + hidden_file = dentry_open(hidden_dentry,
781 + unionfs_lower_mnt_idx(dentry, bstart), file->f_flags);
782 + if (IS_ERR(hidden_file)) {
783 + err = PTR_ERR(hidden_file);
784 + goto out;
785 + }
786 + unionfs_set_lower_file(file, hidden_file);
787 + /* Fix up the position. */
788 + hidden_file->f_pos = file->f_pos;
789 +
790 + memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
791 +out:
792 + return err;
793 +}
794 +
795 +static int do_delayed_copyup(struct file *file, struct dentry *dentry)
796 +{
797 + int bindex, bstart, bend, err = 0;
798 + struct inode *parent_inode = dentry->d_parent->d_inode;
799 + loff_t inode_size = file->f_dentry->d_inode->i_size;
800 +
801 + bstart = fbstart(file);
802 + bend = fbend(file);
803 +
804 + BUG_ON(!S_ISREG(file->f_dentry->d_inode->i_mode));
805 +
806 + for (bindex = bstart - 1; bindex >= 0; bindex--) {
807 + if (!d_deleted(file->f_dentry))
808 + err = copyup_file(parent_inode, file, bstart,
809 + bindex, inode_size);
810 + else
811 + err = copyup_deleted_file(file, dentry, bstart, bindex);
812 +
813 + if (!err)
814 + break;
815 + }
816 + if (!err && (bstart > fbstart(file))) {
817 + bend = fbend(file);
818 + for (bindex = bstart; bindex <= bend; bindex++) {
819 + if (unionfs_lower_file_idx(file, bindex)) {
820 + unionfs_read_lock(dentry->d_sb);
821 + branchput(dentry->d_sb, bindex);
822 + unionfs_read_unlock(dentry->d_sb);
823 + fput(unionfs_lower_file_idx(file, bindex));
824 + unionfs_set_lower_file_idx(file, bindex, NULL);
825 + }
826 + }
827 + fbend(file) = bend;
828 + }
829 + return err;
830 +}
831 +
832 +/*
833 + * Revalidate the struct file
834 + * @file: file to revalidate
835 + * @willwrite: 1 if caller may cause changes to the file; 0 otherwise.
836 + */
837 +int unionfs_file_revalidate(struct file *file, int willwrite)
838 +{
839 + struct super_block *sb;
840 + struct dentry *dentry;
841 + int sbgen, fgen, dgen;
842 + int bstart, bend;
843 + int size;
844 +
845 + int err = 0;
846 +
847 + dentry = file->f_dentry;
848 + unionfs_lock_dentry(dentry);
849 + sb = dentry->d_sb;
850 +
851 + /* first revalidate the dentry inside struct file */
852 + if (!__unionfs_d_revalidate_chain(dentry, NULL) && !d_deleted(dentry)) {
853 + err = -ESTALE;
854 + goto out_nofree;
855 + }
856 +
857 + sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
858 + dgen = atomic_read(&UNIONFS_D(dentry)->generation);
859 + fgen = atomic_read(&UNIONFS_F(file)->generation);
860 +
861 + BUG_ON(sbgen > dgen);
862 +
863 + /* There are two cases we are interested in. The first is if the
864 + * generation is lower than the super-block. The second is if someone
865 + * has copied up this file from underneath us, we also need to refresh
866 + * things.
867 + */
868 + if (!d_deleted(dentry) &&
869 + (sbgen > fgen || dbstart(dentry) != fbstart(file))) {
870 + /* First we throw out the existing files. */
871 + cleanup_file(file);
872 +
873 + /* Now we reopen the file(s) as in unionfs_open. */
874 + bstart = fbstart(file) = dbstart(dentry);
875 + bend = fbend(file) = dbend(dentry);
876 +
877 + size = sizeof(struct file *) * sbmax(sb);
878 + UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
879 + if (!UNIONFS_F(file)->lower_files) {
880 + err = -ENOMEM;
881 + goto out;
882 + }
883 + size = sizeof(int) * sbmax(sb);
884 + UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
885 + if (!UNIONFS_F(file)->saved_branch_ids) {
886 + err = -ENOMEM;
887 + goto out;
888 + }
889 +
890 + if (S_ISDIR(dentry->d_inode->i_mode)) {
891 + /* We need to open all the files. */
892 + err = open_all_files(file);
893 + if (err)
894 + goto out;
895 + } else {
896 + /* We only open the highest priority branch. */
897 + err = open_highest_file(file, willwrite);
898 + if (err)
899 + goto out;
900 + }
901 + atomic_set(&UNIONFS_F(file)->generation,
902 + atomic_read(&UNIONFS_I(dentry->d_inode)->
903 + generation));
904 + }
905 +
906 + /* Copyup on the first write to a file on a readonly branch. */
907 + if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
908 + !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
909 + is_robranch(dentry)) {
910 + printk(KERN_DEBUG "Doing delayed copyup of a read-write "
911 + "file on a read-only branch.\n");
912 + err = do_delayed_copyup(file, dentry);
913 + }
914 +
915 +out:
916 + if (err) {
917 + kfree(UNIONFS_F(file)->lower_files);
918 + kfree(UNIONFS_F(file)->saved_branch_ids);
919 + }
920 +out_nofree:
921 + unionfs_unlock_dentry(dentry);
922 + return err;
923 +}
924 +
925 +/* unionfs_open helper function: open a directory */
926 +static int __open_dir(struct inode *inode, struct file *file)
927 +{
928 + struct dentry *hidden_dentry;
929 + struct file *hidden_file;
930 + int bindex, bstart, bend;
931 +
932 + bstart = fbstart(file) = dbstart(file->f_dentry);
933 + bend = fbend(file) = dbend(file->f_dentry);
934 +
935 + for (bindex = bstart; bindex <= bend; bindex++) {
936 + hidden_dentry = unionfs_lower_dentry_idx(file->f_dentry, bindex);
937 + if (!hidden_dentry)
938 + continue;
939 +
940 + dget(hidden_dentry);
941 + unionfs_mntget(file->f_dentry, bindex);
942 + hidden_file = dentry_open(hidden_dentry,
943 + unionfs_lower_mnt_idx(file->f_dentry, bindex),
944 + file->f_flags);
945 + if (IS_ERR(hidden_file))
946 + return PTR_ERR(hidden_file);
947 +
948 + unionfs_set_lower_file_idx(file, bindex, hidden_file);
949 +
950 + /* The branchget goes after the open, because otherwise
951 + * we would miss the reference on release.
952 + */
953 + unionfs_read_lock(inode->i_sb);
954 + branchget(inode->i_sb, bindex);
955 + unionfs_read_unlock(inode->i_sb);
956 + }
957 +
958 + return 0;
959 +}
960 +
961 +/* unionfs_open helper function: open a file */
962 +static int __open_file(struct inode *inode, struct file *file)
963 +{
964 + struct dentry *hidden_dentry;
965 + struct file *hidden_file;
966 + int hidden_flags;
967 + int bindex, bstart, bend;
968 +
969 + hidden_dentry = unionfs_lower_dentry(file->f_dentry);
970 + hidden_flags = file->f_flags;
971 +
972 + bstart = fbstart(file) = dbstart(file->f_dentry);
973 + bend = fbend(file) = dbend(file->f_dentry);
974 +
975 + /* check for the permission for hidden file. If the error is COPYUP_ERR,
976 + * copyup the file.
977 + */
978 + if (hidden_dentry->d_inode && is_robranch(file->f_dentry)) {
979 + /* if the open will change the file, copy it up otherwise
980 + * defer it.
981 + */
982 + if (hidden_flags & O_TRUNC) {
983 + int size = 0;
984 + int err = -EROFS;
985 +
986 + /* copyup the file */
987 + for (bindex = bstart - 1; bindex >= 0; bindex--) {
988 + err = copyup_file(file->f_dentry->d_parent->d_inode,
989 + file, bstart, bindex, size);
990 + if (!err)
991 + break;
992 + }
993 + return err;
994 + } else
995 + hidden_flags &= ~(OPEN_WRITE_FLAGS);
996 + }
997 +
998 + dget(hidden_dentry);
999 +
1000 + /* dentry_open will decrement mnt refcnt if err.
1001 + * otherwise fput() will do an mntput() for us upon file close.
1002 + */
1003 + unionfs_mntget(file->f_dentry, bstart);
1004 + hidden_file = dentry_open(hidden_dentry,
1005 + unionfs_lower_mnt_idx(file->f_dentry, bstart),
1006 + hidden_flags);
1007 + if (IS_ERR(hidden_file))
1008 + return PTR_ERR(hidden_file);
1009 +
1010 + unionfs_set_lower_file(file, hidden_file);
1011 + unionfs_read_lock(inode->i_sb);
1012 + branchget(inode->i_sb, bstart);
1013 + unionfs_read_unlock(inode->i_sb);
1014 +
1015 + return 0;
1016 +}
1017 +
1018 +int unionfs_open(struct inode *inode, struct file *file)
1019 +{
1020 + int err = 0;
1021 + struct file *hidden_file = NULL;
1022 + struct dentry *dentry = NULL;
1023 + int bindex = 0, bstart = 0, bend = 0;
1024 + int size;
1025 +
1026 + unionfs_read_lock(inode->i_sb);
1027 + file->private_data = kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
1028 + if (!UNIONFS_F(file)) {
1029 + err = -ENOMEM;
1030 + goto out_nofree;
1031 + }
1032 + fbstart(file) = -1;
1033 + fbend(file) = -1;
1034 + atomic_set(&UNIONFS_F(file)->generation,
1035 + atomic_read(&UNIONFS_I(inode)->generation));
1036 +
1037 + size = sizeof(struct file *) * sbmax(inode->i_sb);
1038 + UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
1039 + if (!UNIONFS_F(file)->lower_files) {
1040 + err = -ENOMEM;
1041 + goto out;
1042 + }
1043 + size = sizeof(int) * sbmax(inode->i_sb);
1044 + UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
1045 + if (!UNIONFS_F(file)->saved_branch_ids) {
1046 + err = -ENOMEM;
1047 + goto out;
1048 + }
1049 +
1050 + dentry = file->f_dentry;
1051 + unionfs_lock_dentry(dentry);
1052 +
1053 + bstart = fbstart(file) = dbstart(dentry);
1054 + bend = fbend(file) = dbend(dentry);
1055 +
1056 + /* increment, so that we can flush appropriately */
1057 + atomic_inc(&UNIONFS_I(dentry->d_inode)->totalopens);
1058 +
1059 + /* open all directories and make the unionfs file struct point to
1060 + * these hidden file structs
1061 + */
1062 + if (S_ISDIR(inode->i_mode))
1063 + err = __open_dir(inode, file); /* open a dir */
1064 + else
1065 + err = __open_file(inode, file); /* open a file */
1066 +
1067 + /* freeing the allocated resources, and fput the opened files */
1068 + if (err) {
1069 + atomic_dec(&UNIONFS_I(dentry->d_inode)->totalopens);
1070 + for (bindex = bstart; bindex <= bend; bindex++) {
1071 + hidden_file = unionfs_lower_file_idx(file, bindex);
1072 + if (!hidden_file)
1073 + continue;
1074 +
1075 + unionfs_read_lock(file->f_dentry->d_sb);
1076 + branchput(file->f_dentry->d_sb, bindex);
1077 + unionfs_read_unlock(file->f_dentry->d_sb);
1078 + /* fput calls dput for hidden_dentry */
1079 + fput(hidden_file);
1080 + }
1081 + }
1082 +
1083 + unionfs_unlock_dentry(dentry);
1084 +
1085 +out:
1086 + if (err) {
1087 + kfree(UNIONFS_F(file)->lower_files);
1088 + kfree(UNIONFS_F(file)->saved_branch_ids);
1089 + kfree(UNIONFS_F(file));
1090 + }
1091 +out_nofree:
1092 + unionfs_read_unlock(inode->i_sb);
1093 + return err;
1094 +}
1095 +
1096 +/* release all lower object references & free the file info structure */
1097 +int unionfs_file_release(struct inode *inode, struct file *file)
1098 +{
1099 + struct file *hidden_file = NULL;
1100 + struct unionfs_file_info *fileinfo = UNIONFS_F(file);
1101 + struct unionfs_inode_info *inodeinfo = UNIONFS_I(inode);
1102 + int bindex, bstart, bend;
1103 + int fgen;
1104 +
1105 + unionfs_read_lock(inode->i_sb);
1106 + /* fput all the hidden files */
1107 + fgen = atomic_read(&fileinfo->generation);
1108 + bstart = fbstart(file);
1109 + bend = fbend(file);
1110 +
1111 + for (bindex = bstart; bindex <= bend; bindex++) {
1112 + hidden_file = unionfs_lower_file_idx(file, bindex);
1113 +
1114 + if (hidden_file) {
1115 + fput(hidden_file);
1116 + unionfs_read_lock(inode->i_sb);
1117 + branchput(inode->i_sb, bindex);
1118 + unionfs_read_unlock(inode->i_sb);
1119 + }
1120 + }
1121 + kfree(fileinfo->lower_files);
1122 + kfree(fileinfo->saved_branch_ids);
1123 +
1124 + if (fileinfo->rdstate) {
1125 + fileinfo->rdstate->access = jiffies;
1126 + printk(KERN_DEBUG "Saving rdstate with cookie %u [%d.%lld]\n",
1127 + fileinfo->rdstate->cookie,
1128 + fileinfo->rdstate->bindex,
1129 + (long long)fileinfo->rdstate->dirpos);
1130 + spin_lock(&inodeinfo->rdlock);
1131 + inodeinfo->rdcount++;
1132 + list_add_tail(&fileinfo->rdstate->cache,
1133 + &inodeinfo->readdircache);
1134 + mark_inode_dirty(inode);
1135 + spin_unlock(&inodeinfo->rdlock);
1136 + fileinfo->rdstate = NULL;
1137 + }
1138 + kfree(fileinfo);
1139 + unionfs_read_unlock(inode->i_sb);
1140 + return 0;
1141 +}
1142 +
1143 +/* pass the ioctl to the lower fs */
1144 +static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1145 +{
1146 + struct file *hidden_file;
1147 + int err;
1148 +
1149 + hidden_file = unionfs_lower_file(file);
1150 +
1151 + err = security_file_ioctl(hidden_file, cmd, arg);
1152 + if (err)
1153 + goto out;
1154 +
1155 + err = -ENOTTY;
1156 + if (!hidden_file || !hidden_file->f_op)
1157 + goto out;
1158 + if (hidden_file->f_op->unlocked_ioctl) {
1159 + err = hidden_file->f_op->unlocked_ioctl(hidden_file, cmd, arg);
1160 + } else if (hidden_file->f_op->ioctl) {
1161 + lock_kernel();
1162 + err = hidden_file->f_op->ioctl(hidden_file->f_dentry->d_inode,
1163 + hidden_file, cmd, arg);
1164 + unlock_kernel();
1165 + }
1166 +
1167 +out:
1168 + unionfs_read_unlock(file->f_dentry->d_sb);
1169 + return err;
1170 +}
1171 +
1172 +long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1173 +{
1174 + long err;
1175 +
1176 + unionfs_read_lock(file->f_dentry->d_sb);
1177 + if ((err = unionfs_file_revalidate(file, 1)))
1178 + goto out;
1179 +
1180 + /* check if asked for local commands */
1181 + switch (cmd) {
1182 + case UNIONFS_IOCTL_INCGEN:
1183 + /* Increment the superblock generation count */
1184 + printk("unionfs: incgen ioctl deprecated; use \"-o remount,incgen\"\n");
1185 + err = -ENOSYS;
1186 + break;
1187 +
1188 + case UNIONFS_IOCTL_QUERYFILE:
1189 + /* Return list of branches containing the given file */
1190 + err = unionfs_ioctl_queryfile(file, cmd, arg);
1191 + break;
1192 +
1193 + default:
1194 + /* pass the ioctl down */
1195 + err = do_ioctl(file, cmd, arg);
1196 + break;
1197 + }
1198 +
1199 +out:
1200 + return err;
1201 +}
1202 +
1203 +int unionfs_flush(struct file *file, fl_owner_t id)
1204 +{
1205 + int err = 0;
1206 + struct file *hidden_file = NULL;
1207 + struct dentry *dentry = file->f_dentry;
1208 + int bindex, bstart, bend;
1209 +
1210 + unionfs_read_lock(file->f_dentry->d_sb);
1211 +
1212 + if ((err = unionfs_file_revalidate(file, 1)))
1213 + goto out;
1214 +
1215 + if (!atomic_dec_and_test(&UNIONFS_I(dentry->d_inode)->totalopens))
1216 + goto out;
1217 +
1218 + unionfs_lock_dentry(dentry);
1219 +
1220 + bstart = fbstart(file);
1221 + bend = fbend(file);
1222 + for (bindex = bstart; bindex <= bend; bindex++) {
1223 + hidden_file = unionfs_lower_file_idx(file, bindex);
1224 +
1225 + if (hidden_file && hidden_file->f_op && hidden_file->f_op->flush) {
1226 + err = hidden_file->f_op->flush(hidden_file, id);
1227 + if (err)
1228 + goto out_lock;
1229 +
1230 + /* if there are no more references to the dentry, dput it */
1231 + if (d_deleted(dentry)) {
1232 + dput(unionfs_lower_dentry_idx(dentry, bindex));
1233 + unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
1234 + }
1235 + }
1236 +
1237 + }
1238 +
1239 +out_lock:
1240 + unionfs_unlock_dentry(dentry);
1241 +out:
1242 + unionfs_read_unlock(file->f_dentry->d_sb);
1243 + return err;
1244 +}
1245 diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
1246 new file mode 100644
1247 index 0000000..411553a
1248 --- /dev/null
1249 +++ b/fs/unionfs/copyup.c
1250 @@ -0,0 +1,776 @@
1251 +/*
1252 + * Copyright (c) 2003-2007 Erez Zadok
1253 + * Copyright (c) 2003-2006 Charles P. Wright
1254 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
1255 + * Copyright (c) 2005-2006 Junjiro Okajima
1256 + * Copyright (c) 2005 Arun M. Krishnakumar
1257 + * Copyright (c) 2004-2006 David P. Quigley
1258 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
1259 + * Copyright (c) 2003 Puja Gupta
1260 + * Copyright (c) 2003 Harikesavan Krishnan
1261 + * Copyright (c) 2003-2007 Stony Brook University
1262 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York*
1263 + *
1264 + * This program is free software; you can redistribute it and/or modify
1265 + * it under the terms of the GNU General Public License version 2 as
1266 + * published by the Free Software Foundation.
1267 + */
1268 +
1269 +#include "union.h"
1270 +
1271 +static int copyup_named_dentry(struct inode *dir, struct dentry *dentry,
1272 + int bstart, int new_bindex, const char *name,
1273 + int namelen, struct file **copyup_file,
1274 + loff_t len);
1275 +static struct dentry *create_parents_named(struct inode *dir,
1276 + struct dentry *dentry,
1277 + const char *name, int bindex);
1278 +
1279 +/* For detailed explanation of copyup see:
1280 + * Documentation/filesystems/unionfs/concepts.txt
1281 + */
1282 +
1283 +#ifdef CONFIG_UNION_FS_XATTR
1284 +/* copyup all extended attrs for a given dentry */
1285 +static int copyup_xattrs(struct dentry *old_hidden_dentry,
1286 + struct dentry *new_hidden_dentry)
1287 +{
1288 + int err = 0;
1289 + ssize_t list_size = -1;
1290 + char *name_list = NULL;
1291 + char *attr_value = NULL;
1292 + char *name_list_orig = NULL;
1293 +
1294 + list_size = vfs_listxattr(old_hidden_dentry, NULL, 0);
1295 +
1296 + if (list_size <= 0) {
1297 + err = list_size;
1298 + goto out;
1299 + }
1300 +
1301 + name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
1302 + if (!name_list || IS_ERR(name_list)) {
1303 + err = PTR_ERR(name_list);
1304 + goto out;
1305 + }
1306 + list_size = vfs_listxattr(old_hidden_dentry, name_list, list_size);
1307 + attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
1308 + if (!attr_value || IS_ERR(attr_value)) {
1309 + err = PTR_ERR(name_list);
1310 + goto out;
1311 + }
1312 + name_list_orig = name_list;
1313 + while (*name_list) {
1314 + ssize_t size;
1315 +
1316 + /* Lock here since vfs_getxattr doesn't lock for us */
1317 + mutex_lock(&old_hidden_dentry->d_inode->i_mutex);
1318 + size = vfs_getxattr(old_hidden_dentry, name_list,
1319 + attr_value, XATTR_SIZE_MAX);
1320 + mutex_unlock(&old_hidden_dentry->d_inode->i_mutex);
1321 + if (size < 0) {
1322 + err = size;
1323 + goto out;
1324 + }
1325 +
1326 + if (size > XATTR_SIZE_MAX) {
1327 + err = -E2BIG;
1328 + goto out;
1329 + }
1330 + /* Don't lock here since vfs_setxattr does it for us. */
1331 + err = vfs_setxattr(new_hidden_dentry, name_list, attr_value,
1332 + size, 0);
1333 +
1334 + if (err < 0)
1335 + goto out;
1336 + name_list += strlen(name_list) + 1;
1337 + }
1338 + out:
1339 + name_list = name_list_orig;
1340 +
1341 + if (name_list)
1342 + unionfs_xattr_free(name_list, list_size + 1);
1343 + if (attr_value)
1344 + unionfs_xattr_free(attr_value, XATTR_SIZE_MAX);
1345 + /* It is no big deal if this fails, we just roll with the punches. */
1346 + if (err == -ENOTSUPP || err == -EOPNOTSUPP)
1347 + err = 0;
1348 + return err;
1349 +}
1350 +#endif /* CONFIG_UNION_FS_XATTR */
1351 +
1352 +/* Determine the mode based on the copyup flags, and the existing dentry. */
1353 +static int copyup_permissions(struct super_block *sb,
1354 + struct dentry *old_hidden_dentry,
1355 + struct dentry *new_hidden_dentry)
1356 +{
1357 + struct inode *i = old_hidden_dentry->d_inode;
1358 + struct iattr newattrs;
1359 + int err;
1360 +
1361 + newattrs.ia_atime = i->i_atime;
1362 + newattrs.ia_mtime = i->i_mtime;
1363 + newattrs.ia_ctime = i->i_ctime;
1364 +
1365 + newattrs.ia_gid = i->i_gid;
1366 + newattrs.ia_uid = i->i_uid;
1367 +
1368 + newattrs.ia_mode = i->i_mode;
1369 +
1370 + newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
1371 + ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
1372 + ATTR_GID | ATTR_UID | ATTR_MODE;
1373 +
1374 + err = notify_change(new_hidden_dentry, &newattrs);
1375 +
1376 + return err;
1377 +}
1378 +
1379 +int copyup_dentry(struct inode *dir, struct dentry *dentry,
1380 + int bstart, int new_bindex,
1381 + struct file **copyup_file, loff_t len)
1382 +{
1383 + return copyup_named_dentry(dir, dentry, bstart, new_bindex,
1384 + dentry->d_name.name,
1385 + dentry->d_name.len, copyup_file, len);
1386 +}
1387 +
1388 +/* create the new device/file/directory - use copyup_permission to copyup
1389 + * times, and mode
1390 + *
1391 + * if the object being copied up is a regular file, the file is only created,
1392 + * the contents have to be copied up separately
1393 + */
1394 +static int __copyup_ndentry(struct dentry *old_hidden_dentry,
1395 + struct dentry *new_hidden_dentry,
1396 + struct dentry *new_hidden_parent_dentry,
1397 + char *symbuf)
1398 +{
1399 + int err = 0;
1400 + umode_t old_mode = old_hidden_dentry->d_inode->i_mode;
1401 + struct sioq_args args;
1402 +
1403 + if (S_ISDIR(old_mode)) {
1404 + args.mkdir.parent = new_hidden_parent_dentry->d_inode;
1405 + args.mkdir.dentry = new_hidden_dentry;
1406 + args.mkdir.mode = old_mode;
1407 +
1408 + run_sioq(__unionfs_mkdir, &args);
1409 + err = args.err;
1410 + } else if (S_ISLNK(old_mode)) {
1411 + args.symlink.parent = new_hidden_parent_dentry->d_inode;
1412 + args.symlink.dentry = new_hidden_dentry;
1413 + args.symlink.symbuf = symbuf;
1414 + args.symlink.mode = old_mode;
1415 +
1416 + run_sioq(__unionfs_symlink, &args);
1417 + err = args.err;
1418 + } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) ||
1419 + S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
1420 + args.mknod.parent = new_hidden_parent_dentry->d_inode;
1421 + args.mknod.dentry = new_hidden_dentry;
1422 + args.mknod.mode = old_mode;
1423 + args.mknod.dev = old_hidden_dentry->d_inode->i_rdev;
1424 +
1425 + run_sioq(__unionfs_mknod, &args);
1426 + err = args.err;
1427 + } else if (S_ISREG(old_mode)) {
1428 + args.create.parent = new_hidden_parent_dentry->d_inode;
1429 + args.create.dentry = new_hidden_dentry;
1430 + args.create.mode = old_mode;
1431 + args.create.nd = NULL;
1432 +
1433 + run_sioq(__unionfs_create, &args);
1434 + err = args.err;
1435 + } else {
1436 + printk(KERN_ERR "Unknown inode type %d\n",
1437 + old_mode);
1438 + BUG();
1439 + }
1440 +
1441 + return err;
1442 +}
1443 +
1444 +static int __copyup_reg_data(struct dentry *dentry,
1445 + struct dentry *new_hidden_dentry, int new_bindex,
1446 + struct dentry *old_hidden_dentry, int old_bindex,
1447 + struct file **copyup_file, loff_t len)
1448 +{
1449 + struct super_block *sb = dentry->d_sb;
1450 + struct file *input_file;
1451 + struct file *output_file;
1452 + mm_segment_t old_fs;
1453 + char *buf = NULL;
1454 + ssize_t read_bytes, write_bytes;
1455 + loff_t size;
1456 + int err = 0;
1457 +
1458 + /* open old file */
1459 + unionfs_mntget(dentry, old_bindex);
1460 + unionfs_read_lock(sb);
1461 + branchget(sb, old_bindex);
1462 + unionfs_read_unlock(sb);
1463 + input_file = dentry_open(old_hidden_dentry,
1464 + unionfs_lower_mnt_idx(dentry, old_bindex),
1465 + O_RDONLY | O_LARGEFILE);
1466 + if (IS_ERR(input_file)) {
1467 + dput(old_hidden_dentry);
1468 + err = PTR_ERR(input_file);
1469 + goto out;
1470 + }
1471 + if (!input_file->f_op || !input_file->f_op->read) {
1472 + err = -EINVAL;
1473 + goto out_close_in;
1474 + }
1475 +
1476 + /* open new file */
1477 + dget(new_hidden_dentry);
1478 + unionfs_mntget(dentry, new_bindex);
1479 + unionfs_read_lock(sb);
1480 + branchget(sb, new_bindex);
1481 + unionfs_read_unlock(sb);
1482 + output_file = dentry_open(new_hidden_dentry,
1483 + unionfs_lower_mnt_idx(dentry, new_bindex),
1484 + O_WRONLY | O_LARGEFILE);
1485 + if (IS_ERR(output_file)) {
1486 + err = PTR_ERR(output_file);
1487 + goto out_close_in2;
1488 + }
1489 + if (!output_file->f_op || !output_file->f_op->write) {
1490 + err = -EINVAL;
1491 + goto out_close_out;
1492 + }
1493 +
1494 + /* allocating a buffer */
1495 + buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1496 + if (!buf) {
1497 + err = -ENOMEM;
1498 + goto out_close_out;
1499 + }
1500 +
1501 + input_file->f_pos = 0;
1502 + output_file->f_pos = 0;
1503 +
1504 + old_fs = get_fs();
1505 + set_fs(KERNEL_DS);
1506 +
1507 + size = len;
1508 + err = 0;
1509 + do {
1510 + if (len >= PAGE_SIZE)
1511 + size = PAGE_SIZE;
1512 + else if ((len < PAGE_SIZE) && (len > 0))
1513 + size = len;
1514 +
1515 + len -= PAGE_SIZE;
1516 +
1517 + read_bytes =
1518 + input_file->f_op->read(input_file,
1519 + (char __user *)buf, size,
1520 + &input_file->f_pos);
1521 + if (read_bytes <= 0) {
1522 + err = read_bytes;
1523 + break;
1524 + }
1525 +
1526 + write_bytes =
1527 + output_file->f_op->write(output_file,
1528 + (char __user *)buf,
1529 + read_bytes,
1530 + &output_file->f_pos);
1531 + if ((write_bytes < 0) || (write_bytes < read_bytes)) {
1532 + err = write_bytes;
1533 + break;
1534 + }
1535 + } while ((read_bytes > 0) && (len > 0));
1536 +
1537 + set_fs(old_fs);
1538 +
1539 + kfree(buf);
1540 +
1541 + if (err)
1542 + goto out_close_out;
1543 + if (copyup_file) {
1544 + *copyup_file = output_file;
1545 + goto out_close_in;
1546 + }
1547 +
1548 +out_close_out:
1549 + fput(output_file);
1550 +
1551 +out_close_in2:
1552 + unionfs_read_lock(sb);
1553 + branchput(sb, new_bindex);
1554 + unionfs_read_unlock(sb);
1555 +
1556 +out_close_in:
1557 + fput(input_file);
1558 +
1559 +out:
1560 + unionfs_read_lock(sb);
1561 + branchput(sb, old_bindex);
1562 + unionfs_read_unlock(sb);
1563 +
1564 + return err;
1565 +}
1566 +
1567 +/* dput the lower references for old and new dentry & clear a lower dentry
1568 + * pointer
1569 + */
1570 +static void __clear(struct dentry *dentry, struct dentry *old_hidden_dentry,
1571 + int old_bstart, int old_bend,
1572 + struct dentry *new_hidden_dentry, int new_bindex)
1573 +{
1574 + /* get rid of the hidden dentry and all its traces */
1575 + unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL);
1576 + set_dbstart(dentry, old_bstart);
1577 + set_dbend(dentry, old_bend);
1578 +
1579 + dput(new_hidden_dentry);
1580 + dput(old_hidden_dentry);
1581 +}
1582 +
1583 +/* copy up a dentry to a file of specified name */
1584 +static int copyup_named_dentry(struct inode *dir, struct dentry *dentry,
1585 + int bstart, int new_bindex, const char *name,
1586 + int namelen, struct file **copyup_file,
1587 + loff_t len)
1588 +{
1589 + struct dentry *new_hidden_dentry;
1590 + struct dentry *old_hidden_dentry = NULL;
1591 + struct super_block *sb;
1592 + int err = 0;
1593 + int old_bindex;
1594 + int old_bstart;
1595 + int old_bend;
1596 + struct dentry *new_hidden_parent_dentry = NULL;
1597 + mm_segment_t oldfs;
1598 + char *symbuf = NULL;
1599 +
1600 + verify_locked(dentry);
1601 +
1602 + old_bindex = bstart;
1603 + old_bstart = dbstart(dentry);
1604 + old_bend = dbend(dentry);
1605 +
1606 + BUG_ON(new_bindex < 0);
1607 + BUG_ON(new_bindex >= old_bindex);
1608 +
1609 + sb = dir->i_sb;
1610 +
1611 + if ((err = is_robranch_super(sb, new_bindex)))
1612 + goto out;
1613 +
1614 + /* Create the directory structure above this dentry. */
1615 + new_hidden_dentry = create_parents_named(dir, dentry, name, new_bindex);
1616 + if (IS_ERR(new_hidden_dentry)) {
1617 + err = PTR_ERR(new_hidden_dentry);
1618 + goto out;
1619 + }
1620 +
1621 + old_hidden_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
1622 + /* we conditionally dput this old_hidden_dentry at end of function */
1623 + dget(old_hidden_dentry);
1624 +
1625 + /* For symlinks, we must read the link before we lock the directory. */
1626 + if (S_ISLNK(old_hidden_dentry->d_inode->i_mode)) {
1627 +
1628 + symbuf = kmalloc(PATH_MAX, GFP_KERNEL);
1629 + if (!symbuf) {
1630 + __clear(dentry, old_hidden_dentry,
1631 + old_bstart, old_bend,
1632 + new_hidden_dentry, new_bindex);
1633 + err = -ENOMEM;
1634 + goto out_free;
1635 + }
1636 +
1637 + oldfs = get_fs();
1638 + set_fs(KERNEL_DS);
1639 + err = old_hidden_dentry->d_inode->i_op->readlink(
1640 + old_hidden_dentry,
1641 + (char __user *)symbuf,
1642 + PATH_MAX);
1643 + set_fs(oldfs);
1644 + if (err) {
1645 + __clear(dentry, old_hidden_dentry,
1646 + old_bstart, old_bend,
1647 + new_hidden_dentry, new_bindex);
1648 + goto out_free;
1649 + }
1650 + symbuf[err] = '\0';
1651 + }
1652 +
1653 + /* Now we lock the parent, and create the object in the new branch. */
1654 + new_hidden_parent_dentry = lock_parent(new_hidden_dentry);
1655 +
1656 + /* create the new inode */
1657 + err = __copyup_ndentry(old_hidden_dentry, new_hidden_dentry,
1658 + new_hidden_parent_dentry, symbuf);
1659 +
1660 + if (err) {
1661 + __clear(dentry, old_hidden_dentry,
1662 + old_bstart, old_bend,
1663 + new_hidden_dentry, new_bindex);
1664 + goto out_unlock;
1665 + }
1666 +
1667 + /* We actually copyup the file here. */
1668 + if (S_ISREG(old_hidden_dentry->d_inode->i_mode))
1669 + err = __copyup_reg_data(dentry, new_hidden_dentry, new_bindex,
1670 + old_hidden_dentry, old_bindex, copyup_file, len);
1671 + if (err)
1672 + goto out_unlink;
1673 +
1674 + /* Set permissions. */
1675 + if ((err = copyup_permissions(sb, old_hidden_dentry, new_hidden_dentry)))
1676 + goto out_unlink;
1677 +
1678 +#ifdef CONFIG_UNION_FS_XATTR
1679 + /* Selinux uses extended attributes for permissions. */
1680 + if ((err = copyup_xattrs(old_hidden_dentry, new_hidden_dentry)))
1681 + goto out_unlink;
1682 +#endif
1683 +
1684 + /* do not allow files getting deleted to be reinterposed */
1685 + if (!d_deleted(dentry))
1686 + unionfs_reinterpose(dentry);
1687 +
1688 + goto out_unlock;
1689 + /****/
1690 +
1691 +out_unlink:
1692 + /* copyup failed, because we possibly ran out of space or
1693 + * quota, or something else happened so let's unlink; we don't
1694 + * really care about the return value of vfs_unlink
1695 + */
1696 + vfs_unlink(new_hidden_parent_dentry->d_inode, new_hidden_dentry);
1697 +
1698 + if (copyup_file) {
1699 + /* need to close the file */
1700 +
1701 + fput(*copyup_file);
1702 + unionfs_read_lock(sb);
1703 + branchput(sb, new_bindex);
1704 + unionfs_read_unlock(sb);
1705 + }
1706 +
1707 + /*
1708 + * TODO: should we reset the error to something like -EIO?
1709 + *
1710 + * If we don't reset, the user may get some non-sensical errors, but
1711 + * on the other hand, if we reset to EIO, we guarantee that the user
1712 + * will get a "confusing" error message.
1713 + */
1714 +
1715 +out_unlock:
1716 + unlock_dir(new_hidden_parent_dentry);
1717 +
1718 +out_free:
1719 + /*
1720 + * If old_hidden_dentry was a directory, we need to dput it. If it
1721 + * was a file, then it was already dput indirectly by other
1722 + * functions we call ablve which operate on regular files.
1723 + */
1724 + if (old_hidden_dentry && old_hidden_dentry->d_inode &&
1725 + S_ISDIR(old_hidden_dentry->d_inode->i_mode))
1726 + dput(old_hidden_dentry);
1727 + kfree(symbuf);
1728 +
1729 +out:
1730 + return err;
1731 +}
1732 +
1733 +/* This function creates a copy of a file represented by 'file' which currently
1734 + * resides in branch 'bstart' to branch 'new_bindex.' The copy will be named
1735 + * "name".
1736 + */
1737 +int copyup_named_file(struct inode *dir, struct file *file, char *name,
1738 + int bstart, int new_bindex, loff_t len)
1739 +{
1740 + int err = 0;
1741 + struct file *output_file = NULL;
1742 +
1743 + err = copyup_named_dentry(dir, file->f_dentry, bstart,
1744 + new_bindex, name, strlen(name), &output_file,
1745 + len);
1746 + if (!err) {
1747 + fbstart(file) = new_bindex;
1748 + unionfs_set_lower_file_idx(file, new_bindex, output_file);
1749 + }
1750 +
1751 + return err;
1752 +}
1753 +
1754 +/* This function creates a copy of a file represented by 'file' which currently
1755 + * resides in branch 'bstart' to branch 'new_bindex'.
1756 + */
1757 +int copyup_file(struct inode *dir, struct file *file, int bstart,
1758 + int new_bindex, loff_t len)
1759 +{
1760 + int err = 0;
1761 + struct file *output_file = NULL;
1762 +
1763 + err = copyup_dentry(dir, file->f_dentry, bstart, new_bindex,
1764 + &output_file, len);
1765 + if (!err) {
1766 + fbstart(file) = new_bindex;
1767 + unionfs_set_lower_file_idx(file, new_bindex, output_file);
1768 + }
1769 +
1770 + return err;
1771 +}
1772 +
1773 +/* This function replicates the directory structure upto given dentry
1774 + * in the bindex branch. Can create directory structure recursively to the right
1775 + * also.
1776 + */
1777 +struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
1778 + int bindex)
1779 +{
1780 + return create_parents_named(dir, dentry, dentry->d_name.name, bindex);
1781 +}
1782 +
1783 +static void __cleanup_dentry(struct dentry * dentry, int bindex,
1784 + int old_bstart, int old_bend)
1785 +{
1786 + int loop_start;
1787 + int loop_end;
1788 + int new_bstart = -1;
1789 + int new_bend = -1;
1790 + int i;
1791 +
1792 + loop_start = min(old_bstart, bindex);
1793 + loop_end = max(old_bend, bindex);
1794 +
1795 + /* This loop sets the bstart and bend for the new dentry by
1796 + * traversing from left to right. It also dputs all negative
1797 + * dentries except bindex
1798 + */
1799 + for (i = loop_start; i <= loop_end; i++) {
1800 + if (!unionfs_lower_dentry_idx(dentry, i))
1801 + continue;
1802 +
1803 + if (i == bindex) {
1804 + new_bend = i;
1805 + if (new_bstart < 0)
1806 + new_bstart = i;
1807 + continue;
1808 + }
1809 +
1810 + if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) {
1811 + dput(unionfs_lower_dentry_idx(dentry, i));
1812 + unionfs_set_lower_dentry_idx(dentry, i, NULL);
1813 +
1814 + unionfs_mntput(dentry, i);
1815 + unionfs_set_lower_mnt_idx(dentry, i, NULL);
1816 + } else {
1817 + if (new_bstart < 0)
1818 + new_bstart = i;
1819 + new_bend = i;
1820 + }
1821 + }
1822 +
1823 + if (new_bstart < 0)
1824 + new_bstart = bindex;
1825 + if (new_bend < 0)
1826 + new_bend = bindex;
1827 + set_dbstart(dentry, new_bstart);
1828 + set_dbend(dentry, new_bend);
1829 +
1830 +}
1831 +
1832 +/* set lower inode ptr and update bstart & bend if necessary */
1833 +static void __set_inode(struct dentry * upper, struct dentry * lower,
1834 + int bindex)
1835 +{
1836 + unionfs_set_lower_inode_idx(upper->d_inode, bindex,
1837 + igrab(lower->d_inode));
1838 + if (likely(ibstart(upper->d_inode) > bindex))
1839 + ibstart(upper->d_inode) = bindex;
1840 + if (likely(ibend(upper->d_inode) < bindex))
1841 + ibend(upper->d_inode) = bindex;
1842 +
1843 +}
1844 +
1845 +/* set lower dentry ptr and update bstart & bend if necessary */
1846 +static void __set_dentry(struct dentry * upper, struct dentry * lower,
1847 + int bindex)
1848 +{
1849 + unionfs_set_lower_dentry_idx(upper, bindex, lower);
1850 + if (likely(dbstart(upper) > bindex))
1851 + set_dbstart(upper, bindex);
1852 + if (likely(dbend(upper) < bindex))
1853 + set_dbend(upper, bindex);
1854 +}
1855 +
1856 +/* This function replicates the directory structure upto given dentry
1857 + * in the bindex branch.
1858 + */
1859 +static struct dentry *create_parents_named(struct inode *dir,
1860 + struct dentry *dentry,
1861 + const char *name, int bindex)
1862 +{
1863 + int err;
1864 + struct dentry *child_dentry;
1865 + struct dentry *parent_dentry;
1866 + struct dentry *hidden_parent_dentry = NULL;
1867 + struct dentry *hidden_dentry = NULL;
1868 + const char *childname;
1869 + unsigned int childnamelen;
1870 +
1871 + int old_kmalloc_size;
1872 + int kmalloc_size;
1873 + int num_dentry;
1874 + int count;
1875 +
1876 + int old_bstart;
1877 + int old_bend;
1878 + struct dentry **path = NULL;
1879 + struct dentry **tmp_path;
1880 + struct super_block *sb;
1881 +
1882 + verify_locked(dentry);
1883 +
1884 + /* There is no sense allocating any less than the minimum. */
1885 + kmalloc_size = malloc_sizes[0].cs_size;
1886 + num_dentry = kmalloc_size / sizeof(struct dentry *);
1887 +
1888 + if ((err = is_robranch_super(dir->i_sb, bindex))) {
1889 + hidden_dentry = ERR_PTR(err);
1890 + goto out;
1891 + }
1892 +
1893 + old_bstart = dbstart(dentry);
1894 + old_bend = dbend(dentry);
1895 +
1896 + hidden_dentry = ERR_PTR(-ENOMEM);
1897 + path = kzalloc(kmalloc_size, GFP_KERNEL);
1898 + if (!path)
1899 + goto out;
1900 +
1901 + /* assume the negative dentry of unionfs as the parent dentry */
1902 + parent_dentry = dentry;
1903 +
1904 + count = 0;
1905 + /* This loop finds the first parent that exists in the given branch.
1906 + * We start building the directory structure from there. At the end
1907 + * of the loop, the following should hold:
1908 + * - child_dentry is the first nonexistent child
1909 + * - parent_dentry is the first existent parent
1910 + * - path[0] is the = deepest child
1911 + * - path[count] is the first child to create
1912 + */
1913 + do {
1914 + child_dentry = parent_dentry;
1915 +
1916 + /* find the parent directory dentry in unionfs */
1917 + parent_dentry = child_dentry->d_parent;
1918 + unionfs_lock_dentry(parent_dentry);
1919 +
1920 + /* find out the hidden_parent_dentry in the given branch */
1921 + hidden_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
1922 +
1923 + /* store the child dentry */
1924 + path[count++] = child_dentry;
1925 +
1926 + /* grow path table */
1927 + if (count == num_dentry) {
1928 + old_kmalloc_size = kmalloc_size;
1929 + kmalloc_size *= 2;
1930 + num_dentry = kmalloc_size / sizeof(struct dentry *);
1931 +
1932 + tmp_path = kzalloc(kmalloc_size, GFP_KERNEL);
1933 + if (!tmp_path) {
1934 + hidden_dentry = ERR_PTR(-ENOMEM);
1935 + goto out;
1936 + }
1937 + memcpy(tmp_path, path, old_kmalloc_size);
1938 + kfree(path);
1939 + path = tmp_path;
1940 + tmp_path = NULL;
1941 + }
1942 +
1943 + } while (!hidden_parent_dentry);
1944 + count--;
1945 +
1946 + sb = dentry->d_sb;
1947 +
1948 + /* This is basically while(child_dentry != dentry). This loop is
1949 + * horrible to follow and should be replaced with cleaner code.
1950 + */
1951 + while (1) {
1952 + /* get hidden parent dir in the current branch */
1953 + hidden_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
1954 + unionfs_unlock_dentry(parent_dentry);
1955 +
1956 + /* init the values to lookup */
1957 + childname = child_dentry->d_name.name;
1958 + childnamelen = child_dentry->d_name.len;
1959 +
1960 + if (child_dentry != dentry) {
1961 + /* lookup child in the underlying file system */
1962 + hidden_dentry =
1963 + lookup_one_len(childname, hidden_parent_dentry,
1964 + childnamelen);
1965 + if (IS_ERR(hidden_dentry))
1966 + goto out;
1967 + } else {
1968 +
1969 + /* is the name a whiteout of the childname ?
1970 + * lookup the whiteout child in the underlying file system
1971 + */
1972 + hidden_dentry =
1973 + lookup_one_len(name, hidden_parent_dentry,
1974 + strlen(name));
1975 + if (IS_ERR(hidden_dentry))
1976 + goto out;
1977 +
1978 + /* Replace the current dentry (if any) with the new one. */
1979 + dput(unionfs_lower_dentry_idx(dentry, bindex));
1980 + unionfs_set_lower_dentry_idx(dentry, bindex, hidden_dentry);
1981 +
1982 + __cleanup_dentry(dentry, bindex, old_bstart, old_bend);
1983 + break;
1984 + }
1985 +
1986 + if (hidden_dentry->d_inode) {
1987 + /* since this already exists we dput to avoid
1988 + * multiple references on the same dentry
1989 + */
1990 + dput(hidden_dentry);
1991 + } else {
1992 + struct sioq_args args;
1993 +
1994 + /* its a negative dentry, create a new dir */
1995 + hidden_parent_dentry = lock_parent(hidden_dentry);
1996 +
1997 + args.mkdir.parent = hidden_parent_dentry->d_inode;
1998 + args.mkdir.dentry = hidden_dentry;
1999 + args.mkdir.mode = child_dentry->d_inode->i_mode;
2000 +
2001 + run_sioq(__unionfs_mkdir, &args);
2002 + err = args.err;
2003 +
2004 + if (!err)
2005 + err = copyup_permissions(dir->i_sb,
2006 + child_dentry, hidden_dentry);
2007 + unlock_dir(hidden_parent_dentry);
2008 + if (err) {
2009 + dput(hidden_dentry);
2010 + hidden_dentry = ERR_PTR(err);
2011 + goto out;
2012 + }
2013 +
2014 + }
2015 +
2016 + __set_inode(child_dentry, hidden_dentry, bindex);
2017 + __set_dentry(child_dentry, hidden_dentry, bindex);
2018 +
2019 + parent_dentry = child_dentry;
2020 + child_dentry = path[--count];
2021 + }
2022 +out:
2023 + kfree(path);
2024 + return hidden_dentry;
2025 +}
2026 +
2027 diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
2028 new file mode 100644
2029 index 0000000..9eb143d
2030 --- /dev/null
2031 +++ b/fs/unionfs/dentry.c
2032 @@ -0,0 +1,333 @@
2033 +/*
2034 + * Copyright (c) 2003-2007 Erez Zadok
2035 + * Copyright (c) 2003-2006 Charles P. Wright
2036 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
2037 + * Copyright (c) 2005-2006 Junjiro Okajima
2038 + * Copyright (c) 2005 Arun M. Krishnakumar
2039 + * Copyright (c) 2004-2006 David P. Quigley
2040 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
2041 + * Copyright (c) 2003 Puja Gupta
2042 + * Copyright (c) 2003 Harikesavan Krishnan
2043 + * Copyright (c) 2003-2007 Stony Brook University
2044 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
2045 + *
2046 + * This program is free software; you can redistribute it and/or modify
2047 + * it under the terms of the GNU General Public License version 2 as
2048 + * published by the Free Software Foundation.
2049 + */
2050 +
2051 +#include "union.h"
2052 +
2053 +
2054 +/*
2055 + * Revalidate a single dentry.
2056 + * Assume that dentry's info node is locked.
2057 + * Assume that parent(s) are all valid already, but
2058 + * the child may not yet be valid.
2059 + * Returns 1 if valid, 0 otherwise.
2060 + */
2061 +static int __unionfs_d_revalidate_one(struct dentry *dentry, struct nameidata *nd)
2062 +{
2063 + int valid = 1; /* default is valid (1); invalid is 0. */
2064 + struct dentry *hidden_dentry;
2065 + int bindex, bstart, bend;
2066 + int sbgen, dgen;
2067 + int positive = 0;
2068 + int locked = 0;
2069 + int interpose_flag;
2070 +
2071 + struct nameidata lowernd; /* TODO: be gentler to the stack */
2072 +
2073 + if (nd)
2074 + memcpy(&lowernd, nd, sizeof(struct nameidata));
2075 + else
2076 + memset(&lowernd, 0, sizeof(struct nameidata));
2077 +
2078 + verify_locked(dentry);
2079 +
2080 + /* if the dentry is unhashed, do NOT revalidate */
2081 + if (d_deleted(dentry)) {
2082 + printk(KERN_DEBUG "unhashed dentry being revalidated: %*s\n",
2083 + dentry->d_name.len, dentry->d_name.name);
2084 + goto out;
2085 + }
2086 +
2087 + BUG_ON(dbstart(dentry) == -1);
2088 + if (dentry->d_inode)
2089 + positive = 1;
2090 + dgen = atomic_read(&UNIONFS_D(dentry)->generation);
2091 + sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
2092 + /* If we are working on an unconnected dentry, then there is no
2093 + * revalidation to be done, because this file does not exist within the
2094 + * namespace, and Unionfs operates on the namespace, not data.
2095 + */
2096 + if (sbgen != dgen) {
2097 + struct dentry *result;
2098 + int pdgen;
2099 +
2100 + /* The root entry should always be valid */
2101 + BUG_ON(IS_ROOT(dentry));
2102 +
2103 + /* We can't work correctly if our parent isn't valid. */
2104 + pdgen = atomic_read(&UNIONFS_D(dentry->d_parent)->generation);
2105 + BUG_ON(pdgen != sbgen); /* should never happen here */
2106 +
2107 + /* Free the pointers for our inodes and this dentry. */
2108 + bstart = dbstart(dentry);
2109 + bend = dbend(dentry);
2110 + if (bstart >= 0) {
2111 + struct dentry *hidden_dentry;
2112 + for (bindex = bstart; bindex <= bend; bindex++) {
2113 + hidden_dentry =
2114 + unionfs_lower_dentry_idx(dentry, bindex);
2115 + dput(hidden_dentry);
2116 + }
2117 + }
2118 + set_dbstart(dentry, -1);
2119 + set_dbend(dentry, -1);
2120 +
2121 + interpose_flag = INTERPOSE_REVAL_NEG;
2122 + if (positive) {
2123 + interpose_flag = INTERPOSE_REVAL;
2124 + /*
2125 + * During BRM, the VFS could already hold a lock on
2126 + * a file being read, so don't lock it again
2127 + * (deadlock), but if you lock it in this function,
2128 + * then release it here too.
2129 + */
2130 + if (!mutex_is_locked(&dentry->d_inode->i_mutex)) {
2131 + mutex_lock(&dentry->d_inode->i_mutex);
2132 + locked = 1;
2133 + }
2134 +
2135 + bstart = ibstart(dentry->d_inode);
2136 + bend = ibend(dentry->d_inode);
2137 + if (bstart >= 0) {
2138 + struct inode *hidden_inode;
2139 + for (bindex = bstart; bindex <= bend; bindex++) {
2140 + hidden_inode =
2141 + unionfs_lower_inode_idx(dentry->d_inode,
2142 + bindex);
2143 + iput(hidden_inode);
2144 + }
2145 + }
2146 + kfree(UNIONFS_I(dentry->d_inode)->lower_inodes);
2147 + UNIONFS_I(dentry->d_inode)->lower_inodes = NULL;
2148 + ibstart(dentry->d_inode) = -1;
2149 + ibend(dentry->d_inode) = -1;
2150 + if (locked)
2151 + mutex_unlock(&dentry->d_inode->i_mutex);
2152 + }
2153 +
2154 + result = unionfs_lookup_backend(dentry, &lowernd, interpose_flag);
2155 + if (result) {
2156 + if (IS_ERR(result)) {
2157 + valid = 0;
2158 + goto out;
2159 + }
2160 + /* current unionfs_lookup_backend() doesn't return
2161 + * a valid dentry
2162 + */
2163 + dput(dentry);
2164 + dentry = result;
2165 + }
2166 +
2167 + if (positive && UNIONFS_I(dentry->d_inode)->stale) {
2168 + make_bad_inode(dentry->d_inode);
2169 + d_drop(dentry);
2170 + valid = 0;
2171 + goto out;
2172 + }
2173 + goto out;
2174 + }
2175 +
2176 + /* The revalidation must occur across all branches */
2177 + bstart = dbstart(dentry);
2178 + bend = dbend(dentry);
2179 + BUG_ON(bstart == -1);
2180 + for (bindex = bstart; bindex <= bend; bindex++) {
2181 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
2182 + if (!hidden_dentry || !hidden_dentry->d_op
2183 + || !hidden_dentry->d_op->d_revalidate)
2184 + continue;
2185 + if (!hidden_dentry->d_op->d_revalidate(hidden_dentry, &lowernd))
2186 + valid = 0;
2187 + }
2188 +
2189 + if (!dentry->d_inode)
2190 + valid = 0;
2191 +
2192 + if (valid) {
2193 + fsstack_copy_attr_all(dentry->d_inode,
2194 + unionfs_lower_inode(dentry->d_inode),
2195 + unionfs_get_nlinks);
2196 + fsstack_copy_inode_size(dentry->d_inode,
2197 + unionfs_lower_inode(dentry->d_inode));
2198 + }
2199 +
2200 +out:
2201 + return valid;
2202 +}
2203 +
2204 +/*
2205 + * Revalidate a parent chain of dentries, then the actual node.
2206 + * Assumes that dentry is locked, but will lock all parents if/when needed.
2207 + */
2208 +int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata *nd)
2209 +{
2210 + int valid = 0; /* default is invalid (0); valid is 1. */
2211 + struct dentry **chain = NULL; /* chain of dentries to reval */
2212 + int chain_len = 0;
2213 + struct dentry *dtmp;
2214 + int sbgen, dgen, i;
2215 + int saved_bstart, saved_bend, bindex;
2216 +
2217 + /* find length of chain needed to revalidate */
2218 + /* XXX: should I grab some global (dcache?) lock? */
2219 + chain_len = 0;
2220 + sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
2221 + dtmp = dentry->d_parent;
2222 + dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
2223 + while (sbgen != dgen) {
2224 + /* The root entry should always be valid */
2225 + BUG_ON(IS_ROOT(dtmp));
2226 + chain_len++;
2227 + dtmp = dtmp->d_parent;
2228 + dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
2229 + }
2230 + if (chain_len == 0) {
2231 + goto out_this; /* shortcut if parents are OK */
2232 + }
2233 +
2234 + /*
2235 + * Allocate array of dentries to reval. We could use linked lists,
2236 + * but the number of entries we need to alloc here is often small,
2237 + * and short lived, so locality will be better.
2238 + */
2239 + chain = kzalloc(chain_len * sizeof(struct dentry *), GFP_KERNEL);
2240 + if (!chain) {
2241 + printk("unionfs: no more memory in %s\n", __FUNCTION__);
2242 + goto out;
2243 + }
2244 +
2245 + /*
2246 + * lock all dentries in chain, in child to parent order.
2247 + * if failed, then sleep for a little, then retry.
2248 + */
2249 + dtmp = dentry->d_parent;
2250 + for (i=chain_len-1; i>=0; i--) {
2251 + chain[i] = dget(dtmp);
2252 + dtmp = dtmp->d_parent;
2253 + }
2254 +
2255 + /*
2256 + * call __unionfs_d_revalidate() on each dentry, but in parent to
2257 + * child order.
2258 + */
2259 + for (i=0; i<chain_len; i++) {
2260 + unionfs_lock_dentry(chain[i]);
2261 + saved_bstart = dbstart(chain[i]);
2262 + saved_bend = dbend(chain[i]);
2263 + sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
2264 + dgen = atomic_read(&UNIONFS_D(chain[i])->generation);
2265 +
2266 + valid = __unionfs_d_revalidate_one(chain[i], nd);
2267 + /* XXX: is this the correct mntput condition?! */
2268 + if (valid && chain_len > 0 &&
2269 + sbgen != dgen && chain[i]->d_inode &&
2270 + S_ISDIR(chain[i]->d_inode->i_mode)) {
2271 + for (bindex = saved_bstart; bindex <= saved_bend; bindex++)
2272 + unionfs_mntput(chain[i], bindex);
2273 + }
2274 + unionfs_unlock_dentry(chain[i]);
2275 +
2276 + if (!valid) {
2277 + goto out_free;
2278 + }
2279 + }
2280 +
2281 +
2282 + out_this:
2283 + /* finally, lock this dentry and revalidate it */
2284 + verify_locked(dentry);
2285 + dgen = atomic_read(&UNIONFS_D(dentry)->generation);
2286 + saved_bstart = dbstart(dentry);
2287 + saved_bend = dbend(dentry);
2288 + valid = __unionfs_d_revalidate_one(dentry, nd);
2289 +
2290 + if (valid && chain_len > 0 && sbgen != dgen) {
2291 + for (bindex = saved_bstart; bindex <= saved_bend; bindex++)
2292 + unionfs_mntput(dentry, bindex);
2293 + }
2294 +
2295 + out_free:
2296 + /* unlock/dput all dentries in chain and return status */
2297 + if (chain_len > 0) {
2298 + for (i=0; i<chain_len; i++) {
2299 + dput(chain[i]);
2300 + }
2301 + kfree(chain);
2302 + }
2303 + out:
2304 + return valid;
2305 +}
2306 +
2307 +static int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
2308 +{
2309 + int err;
2310 +
2311 + unionfs_lock_dentry(dentry);
2312 + err = __unionfs_d_revalidate_chain(dentry, nd);
2313 + unionfs_unlock_dentry(dentry);
2314 +
2315 + return err;
2316 +}
2317 +
2318 +/*
2319 + * At this point no one can reference this dentry, so we don't have to be
2320 + * careful about concurrent access.
2321 + */
2322 +static void unionfs_d_release(struct dentry *dentry)
2323 +{
2324 + int bindex, bstart, bend;
2325 +
2326 + /* this could be a negative dentry, so check first */
2327 + if (!UNIONFS_D(dentry)) {
2328 + printk(KERN_DEBUG "dentry without private data: %.*s",
2329 + dentry->d_name.len, dentry->d_name.name);
2330 + goto out;
2331 + } else if (dbstart(dentry) < 0) {
2332 + /* this is due to a failed lookup */
2333 + printk(KERN_DEBUG "dentry without hidden dentries : %.*s",
2334 + dentry->d_name.len, dentry->d_name.name);
2335 + goto out_free;
2336 + }
2337 +
2338 + /* Release all the hidden dentries */
2339 + bstart = dbstart(dentry);
2340 + bend = dbend(dentry);
2341 + for (bindex = bstart; bindex <= bend; bindex++) {
2342 + dput(unionfs_lower_dentry_idx(dentry, bindex));
2343 + unionfs_mntput(dentry, bindex);
2344 +
2345 + unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
2346 + unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
2347 + }
2348 + /* free private data (unionfs_dentry_info) here */
2349 + kfree(UNIONFS_D(dentry)->lower_paths);
2350 + UNIONFS_D(dentry)->lower_paths = NULL;
2351 +
2352 +out_free:
2353 + /* No need to unlock it, because it is disappeared. */
2354 + free_dentry_private_data(UNIONFS_D(dentry));
2355 + dentry->d_fsdata = NULL; /* just to be safe */
2356 +
2357 +out:
2358 + return;
2359 +}
2360 +
2361 +struct dentry_operations unionfs_dops = {
2362 + .d_revalidate = unionfs_d_revalidate,
2363 + .d_release = unionfs_d_release,
2364 +};
2365 +
2366 diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
2367 new file mode 100644
2368 index 0000000..6ff32a0
2369 --- /dev/null
2370 +++ b/fs/unionfs/dirfops.c
2371 @@ -0,0 +1,267 @@
2372 +/*
2373 + * Copyright (c) 2003-2007 Erez Zadok
2374 + * Copyright (c) 2003-2006 Charles P. Wright
2375 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
2376 + * Copyright (c) 2005-2006 Junjiro Okajima
2377 + * Copyright (c) 2005 Arun M. Krishnakumar
2378 + * Copyright (c) 2004-2006 David P. Quigley
2379 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
2380 + * Copyright (c) 2003 Puja Gupta
2381 + * Copyright (c) 2003 Harikesavan Krishnan
2382 + * Copyright (c) 2003-2007 Stony Brook University
2383 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
2384 + *
2385 + * This program is free software; you can redistribute it and/or modify
2386 + * it under the terms of the GNU General Public License version 2 as
2387 + * published by the Free Software Foundation.
2388 + */
2389 +
2390 +#include "union.h"
2391 +
2392 +/* Make sure our rdstate is playing by the rules. */
2393 +static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
2394 +{
2395 + BUG_ON(rdstate->offset >= DIREOF);
2396 + BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
2397 +}
2398 +
2399 +struct unionfs_getdents_callback {
2400 + struct unionfs_dir_state *rdstate;
2401 + void *dirent;
2402 + int entries_written;
2403 + int filldir_called;
2404 + int filldir_error;
2405 + filldir_t filldir;
2406 + struct super_block *sb;
2407 +};
2408 +
2409 +/* based on generic filldir in fs/readir.c */
2410 +static int unionfs_filldir(void *dirent, const char *name, int namelen,
2411 + loff_t offset, u64 ino, unsigned int d_type)
2412 +{
2413 + struct unionfs_getdents_callback *buf = dirent;
2414 + struct filldir_node *found = NULL;
2415 + int err = 0;
2416 + int is_wh_entry = 0;
2417 +
2418 + buf->filldir_called++;
2419 +
2420 + if ((namelen > UNIONFS_WHLEN) &&
2421 + !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
2422 + name += UNIONFS_WHLEN;
2423 + namelen -= UNIONFS_WHLEN;
2424 + is_wh_entry = 1;
2425 + }
2426 +
2427 + found = find_filldir_node(buf->rdstate, name, namelen);
2428 +
2429 + if (found)
2430 + goto out;
2431 +
2432 + /* if 'name' isn't a whiteout, filldir it. */
2433 + if (!is_wh_entry) {
2434 + off_t pos = rdstate2offset(buf->rdstate);
2435 + u64 unionfs_ino = ino;
2436 +
2437 + if (!err) {
2438 + err = buf->filldir(buf->dirent, name, namelen, pos,
2439 + unionfs_ino, d_type);
2440 + buf->rdstate->offset++;
2441 + verify_rdstate_offset(buf->rdstate);
2442 + }
2443 + }
2444 + /* If we did fill it, stuff it in our hash, otherwise return an error */
2445 + if (err) {
2446 + buf->filldir_error = err;
2447 + goto out;
2448 + }
2449 + buf->entries_written++;
2450 + if ((err = add_filldir_node(buf->rdstate, name, namelen,
2451 + buf->rdstate->bindex, is_wh_entry)))
2452 + buf->filldir_error = err;
2453 +
2454 +out:
2455 + return err;
2456 +}
2457 +
2458 +static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
2459 +{
2460 + int err = 0;
2461 + struct file *hidden_file = NULL;
2462 + struct inode *inode = NULL;
2463 + struct unionfs_getdents_callback buf;
2464 + struct unionfs_dir_state *uds;
2465 + int bend;
2466 + loff_t offset;
2467 +
2468 + unionfs_read_lock(file->f_dentry->d_sb);
2469 + if ((err = unionfs_file_revalidate(file, 0)))
2470 + goto out;
2471 +
2472 + inode = file->f_dentry->d_inode;
2473 +
2474 + uds = UNIONFS_F(file)->rdstate;
2475 + if (!uds) {
2476 + if (file->f_pos == DIREOF) {
2477 + goto out;
2478 + } else if (file->f_pos > 0) {
2479 + uds = find_rdstate(inode, file->f_pos);
2480 + if (!uds) {
2481 + err = -ESTALE;
2482 + goto out;
2483 + }
2484 + UNIONFS_F(file)->rdstate = uds;
2485 + } else {
2486 + init_rdstate(file);
2487 + uds = UNIONFS_F(file)->rdstate;
2488 + }
2489 + }
2490 + bend = fbend(file);
2491 +
2492 + while (uds->bindex <= bend) {
2493 + hidden_file = unionfs_lower_file_idx(file, uds->bindex);
2494 + if (!hidden_file) {
2495 + uds->bindex++;
2496 + uds->dirpos = 0;
2497 + continue;
2498 + }
2499 +
2500 + /* prepare callback buffer */
2501 + buf.filldir_called = 0;
2502 + buf.filldir_error = 0;
2503 + buf.entries_written = 0;
2504 + buf.dirent = dirent;
2505 + buf.filldir = filldir;
2506 + buf.rdstate = uds;
2507 + buf.sb = inode->i_sb;
2508 +
2509 + /* Read starting from where we last left off. */
2510 + offset = vfs_llseek(hidden_file, uds->dirpos, SEEK_SET);
2511 + if (offset < 0) {
2512 + err = offset;
2513 + goto out;
2514 + }
2515 + err = vfs_readdir(hidden_file, unionfs_filldir, &buf);
2516 +
2517 + /* Save the position for when we continue. */
2518 + offset = vfs_llseek(hidden_file, 0, SEEK_CUR);
2519 + if (offset < 0) {
2520 + err = offset;
2521 + goto out;
2522 + }
2523 + uds->dirpos = offset;
2524 +
2525 + /* Copy the atime. */
2526 + fsstack_copy_attr_atime(inode, hidden_file->f_dentry->d_inode);
2527 +
2528 + if (err < 0)
2529 + goto out;
2530 +
2531 + if (buf.filldir_error)
2532 + break;
2533 +
2534 + if (!buf.entries_written) {
2535 + uds->bindex++;
2536 + uds->dirpos = 0;
2537 + }
2538 + }
2539 +
2540 + if (!buf.filldir_error && uds->bindex >= bend) {
2541 + /* Save the number of hash entries for next time. */
2542 + UNIONFS_I(inode)->hashsize = uds->hashentries;
2543 + free_rdstate(uds);
2544 + UNIONFS_F(file)->rdstate = NULL;
2545 + file->f_pos = DIREOF;
2546 + } else
2547 + file->f_pos = rdstate2offset(uds);
2548 +
2549 +out:
2550 + unionfs_read_unlock(file->f_dentry->d_sb);
2551 + return err;
2552 +}
2553 +
2554 +/* This is not meant to be a generic repositioning function. If you do
2555 + * things that aren't supported, then we return EINVAL.
2556 + *
2557 + * What is allowed:
2558 + * (1) seeking to the same position that you are currently at
2559 + * This really has no effect, but returns where you are.
2560 + * (2) seeking to the beginning of the file
2561 + * This throws out all state, and lets you begin again.
2562 + */
2563 +static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
2564 +{
2565 + struct unionfs_dir_state *rdstate;
2566 + loff_t err;
2567 +
2568 + unionfs_read_lock(file->f_dentry->d_sb);
2569 + if ((err = unionfs_file_revalidate(file, 0)))
2570 + goto out;
2571 +
2572 + rdstate = UNIONFS_F(file)->rdstate;
2573 +
2574 + /* We let users seek to their current position, but not anywhere else. */
2575 + if (!offset) {
2576 + switch (origin) {
2577 + case SEEK_SET:
2578 + if (rdstate) {
2579 + free_rdstate(rdstate);
2580 + UNIONFS_F(file)->rdstate = NULL;
2581 + }
2582 + init_rdstate(file);
2583 + err = 0;
2584 + break;
2585 + case SEEK_CUR:
2586 + err = file->f_pos;
2587 + break;
2588 + case SEEK_END:
2589 + /* Unsupported, because we would break everything. */
2590 + err = -EINVAL;
2591 + break;
2592 + }
2593 + } else {
2594 + switch (origin) {
2595 + case SEEK_SET:
2596 + if (rdstate) {
2597 + if (offset == rdstate2offset(rdstate))
2598 + err = offset;
2599 + else if (file->f_pos == DIREOF)
2600 + err = DIREOF;
2601 + else
2602 + err = -EINVAL;
2603 + } else {
2604 + rdstate = find_rdstate(file->f_dentry->d_inode,
2605 + offset);
2606 + if (rdstate) {
2607 + UNIONFS_F(file)->rdstate = rdstate;
2608 + err = rdstate->offset;
2609 + } else
2610 + err = -EINVAL;
2611 + }
2612 + break;
2613 + case SEEK_CUR:
2614 + case SEEK_END:
2615 + /* Unsupported, because we would break everything. */
2616 + err = -EINVAL;
2617 + break;
2618 + }
2619 + }
2620 +
2621 +out:
2622 + unionfs_read_unlock(file->f_dentry->d_sb);
2623 + return err;
2624 +}
2625 +
2626 +/* Trimmed directory options, we shouldn't pass everything down since
2627 + * we don't want to operate on partial directories.
2628 + */
2629 +struct file_operations unionfs_dir_fops = {
2630 + .llseek = unionfs_dir_llseek,
2631 + .read = generic_read_dir,
2632 + .readdir = unionfs_readdir,
2633 + .unlocked_ioctl = unionfs_ioctl,
2634 + .open = unionfs_open,
2635 + .release = unionfs_file_release,
2636 + .flush = unionfs_flush,
2637 +};
2638 +
2639 diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
2640 new file mode 100644
2641 index 0000000..bd15eb4
2642 --- /dev/null
2643 +++ b/fs/unionfs/dirhelper.c
2644 @@ -0,0 +1,276 @@
2645 +/*
2646 + * Copyright (c) 2003-2007 Erez Zadok
2647 + * Copyright (c) 2003-2006 Charles P. Wright
2648 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
2649 + * Copyright (c) 2005-2006 Junjiro Okajima
2650 + * Copyright (c) 2005 Arun M. Krishnakumar
2651 + * Copyright (c) 2004-2006 David P. Quigley
2652 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
2653 + * Copyright (c) 2003 Puja Gupta
2654 + * Copyright (c) 2003 Harikesavan Krishnan
2655 + * Copyright (c) 2003-2007 Stony Brook University
2656 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
2657 + *
2658 + * This program is free software; you can redistribute it and/or modify
2659 + * it under the terms of the GNU General Public License version 2 as
2660 + * published by the Free Software Foundation.
2661 + */
2662 +
2663 +#include "union.h"
2664 +
2665 +/* Delete all of the whiteouts in a given directory for rmdir.
2666 + *
2667 + * hidden directory inode should be locked
2668 + */
2669 +int do_delete_whiteouts(struct dentry *dentry, int bindex,
2670 + struct unionfs_dir_state *namelist)
2671 +{
2672 + int err = 0;
2673 + struct dentry *hidden_dir_dentry = NULL;
2674 + struct dentry *hidden_dentry;
2675 + char *name = NULL, *p;
2676 + struct inode *hidden_dir;
2677 +
2678 + int i;
2679 + struct list_head *pos;
2680 + struct filldir_node *cursor;
2681 +
2682 + /* Find out hidden parent dentry */
2683 + hidden_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
2684 + BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode));
2685 + hidden_dir = hidden_dir_dentry->d_inode;
2686 + BUG_ON(!S_ISDIR(hidden_dir->i_mode));
2687 +
2688 + err = -ENOMEM;
2689 + name = __getname();
2690 + if (!name)
2691 + goto out;
2692 + strcpy(name, UNIONFS_WHPFX);
2693 + p = name + UNIONFS_WHLEN;
2694 +
2695 + err = 0;
2696 + for (i = 0; !err && i < namelist->size; i++) {
2697 + list_for_each(pos, &namelist->list[i]) {
2698 + cursor =
2699 + list_entry(pos, struct filldir_node, file_list);
2700 + /* Only operate on whiteouts in this branch. */
2701 + if (cursor->bindex != bindex)
2702 + continue;
2703 + if (!cursor->whiteout)
2704 + continue;
2705 +
2706 + strcpy(p, cursor->name);
2707 + hidden_dentry =
2708 + lookup_one_len(name, hidden_dir_dentry,
2709 + cursor->namelen + UNIONFS_WHLEN);
2710 + if (IS_ERR(hidden_dentry)) {
2711 + err = PTR_ERR(hidden_dentry);
2712 + break;
2713 + }
2714 + if (hidden_dentry->d_inode)
2715 + err = vfs_unlink(hidden_dir, hidden_dentry);
2716 + dput(hidden_dentry);
2717 + if (err)
2718 + break;
2719 + }
2720 + }
2721 +
2722 + __putname(name);
2723 +
2724 + /* After all of the removals, we should copy the attributes once. */
2725 + fsstack_copy_attr_times(dentry->d_inode, hidden_dir_dentry->d_inode);
2726 +
2727 +out:
2728 + return err;
2729 +}
2730 +
2731 +/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */
2732 +int delete_whiteouts(struct dentry *dentry, int bindex,
2733 + struct unionfs_dir_state *namelist)
2734 +{
2735 + int err;
2736 + struct super_block *sb;
2737 + struct dentry *hidden_dir_dentry;
2738 + struct inode *hidden_dir;
2739 +
2740 + struct sioq_args args;
2741 +
2742 + sb = dentry->d_sb;
2743 + unionfs_read_lock(sb);
2744 +
2745 + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
2746 + BUG_ON(bindex < dbstart(dentry));
2747 + BUG_ON(bindex > dbend(dentry));
2748 + err = is_robranch_super(sb, bindex);
2749 + if (err)
2750 + goto out;
2751 +
2752 + hidden_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
2753 + BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode));
2754 + hidden_dir = hidden_dir_dentry->d_inode;
2755 + BUG_ON(!S_ISDIR(hidden_dir->i_mode));
2756 +
2757 + mutex_lock(&hidden_dir->i_mutex);
2758 + if (!permission(hidden_dir, MAY_WRITE | MAY_EXEC, NULL))
2759 + err = do_delete_whiteouts(dentry, bindex, namelist);
2760 + else {
2761 + args.deletewh.namelist = namelist;
2762 + args.deletewh.dentry = dentry;
2763 + args.deletewh.bindex = bindex;
2764 + run_sioq(__delete_whiteouts, &args);
2765 + err = args.err;
2766 + }
2767 + mutex_unlock(&hidden_dir->i_mutex);
2768 +
2769 +out:
2770 + unionfs_read_unlock(sb);
2771 + return err;
2772 +}
2773 +
2774 +#define RD_NONE 0
2775 +#define RD_CHECK_EMPTY 1
2776 +/* The callback structure for check_empty. */
2777 +struct unionfs_rdutil_callback {
2778 + int err;
2779 + int filldir_called;
2780 + struct unionfs_dir_state *rdstate;
2781 + int mode;
2782 +};
2783 +
2784 +/* This filldir function makes sure only whiteouts exist within a directory. */
2785 +static int readdir_util_callback(void *dirent, const char *name, int namelen,
2786 + loff_t offset, u64 ino, unsigned int d_type)
2787 +{
2788 + int err = 0;
2789 + struct unionfs_rdutil_callback *buf = dirent;
2790 + int whiteout = 0;
2791 + struct filldir_node *found;
2792 +
2793 + buf->filldir_called = 1;
2794 +
2795 + if (name[0] == '.' && (namelen == 1 || (name[1] == '.' && namelen == 2)))
2796 + goto out;
2797 +
2798 + if (namelen > UNIONFS_WHLEN &&
2799 + !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
2800 + namelen -= UNIONFS_WHLEN;
2801 + name += UNIONFS_WHLEN;
2802 + whiteout = 1;
2803 + }
2804 +
2805 + found = find_filldir_node(buf->rdstate, name, namelen);
2806 + /* If it was found in the table there was a previous whiteout. */
2807 + if (found)
2808 + goto out;
2809 +
2810 + /* If it wasn't found and isn't a whiteout, the directory isn't empty. */
2811 + err = -ENOTEMPTY;
2812 + if ((buf->mode == RD_CHECK_EMPTY) && !whiteout)
2813 + goto out;
2814 +
2815 + err = add_filldir_node(buf->rdstate, name, namelen,
2816 + buf->rdstate->bindex, whiteout);
2817 +
2818 +out:
2819 + buf->err = err;
2820 + return err;
2821 +}
2822 +
2823 +/* Is a directory logically empty? */
2824 +int check_empty(struct dentry *dentry, struct unionfs_dir_state **namelist)
2825 +{
2826 + int err = 0;
2827 + struct dentry *hidden_dentry = NULL;
2828 + struct super_block *sb;
2829 + struct file *hidden_file;
2830 + struct unionfs_rdutil_callback *buf = NULL;
2831 + int bindex, bstart, bend, bopaque;
2832 +
2833 + sb = dentry->d_sb;
2834 +
2835 + unionfs_read_lock(sb);
2836 +
2837 + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
2838 +
2839 + if ((err = unionfs_partial_lookup(dentry)))
2840 + goto out;
2841 +
2842 + bstart = dbstart(dentry);
2843 + bend = dbend(dentry);
2844 + bopaque = dbopaque(dentry);
2845 + if (0 <= bopaque && bopaque < bend)
2846 + bend = bopaque;
2847 +
2848 + buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
2849 + if (!buf) {
2850 + err = -ENOMEM;
2851 + goto out;
2852 + }
2853 + buf->err = 0;
2854 + buf->mode = RD_CHECK_EMPTY;
2855 + buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
2856 + if (!buf->rdstate) {
2857 + err = -ENOMEM;
2858 + goto out;
2859 + }
2860 +
2861 + /* Process the hidden directories with rdutil_callback as a filldir. */
2862 + for (bindex = bstart; bindex <= bend; bindex++) {
2863 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
2864 + if (!hidden_dentry)
2865 + continue;
2866 + if (!hidden_dentry->d_inode)
2867 + continue;
2868 + if (!S_ISDIR(hidden_dentry->d_inode->i_mode))
2869 + continue;
2870 +
2871 + dget(hidden_dentry);
2872 + unionfs_mntget(dentry, bindex);
2873 + unionfs_read_lock(sb);
2874 + branchget(sb, bindex);
2875 + unionfs_read_unlock(sb);
2876 + hidden_file =
2877 + dentry_open(hidden_dentry, unionfs_lower_mnt_idx(dentry, bindex),
2878 + O_RDONLY);
2879 + if (IS_ERR(hidden_file)) {
2880 + err = PTR_ERR(hidden_file);
2881 + dput(hidden_dentry);
2882 + unionfs_read_lock(sb);
2883 + branchput(sb, bindex);
2884 + unionfs_read_unlock(sb);
2885 + goto out;
2886 + }
2887 +
2888 + do {
2889 + buf->filldir_called = 0;
2890 + buf->rdstate->bindex = bindex;
2891 + err = vfs_readdir(hidden_file,
2892 + readdir_util_callback, buf);
2893 + if (buf->err)
2894 + err = buf->err;
2895 + } while ((err >= 0) && buf->filldir_called);
2896 +
2897 + /* fput calls dput for hidden_dentry */
2898 + fput(hidden_file);
2899 + unionfs_read_lock(sb);
2900 + branchput(sb, bindex);
2901 + unionfs_read_unlock(sb);
2902 +
2903 + if (err < 0)
2904 + goto out;
2905 + }
2906 +
2907 +out:
2908 + if (buf) {
2909 + if (namelist && !err)
2910 + *namelist = buf->rdstate;
2911 + else if (buf->rdstate)
2912 + free_rdstate(buf->rdstate);
2913 + kfree(buf);
2914 + }
2915 +
2916 + unionfs_read_unlock(sb);
2917 +
2918 + return err;
2919 +}
2920 +
2921 diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
2922 new file mode 100644
2923 index 0000000..9e4a35f
2924 --- /dev/null
2925 +++ b/fs/unionfs/fanout.h
2926 @@ -0,0 +1,231 @@
2927 +/*
2928 + * Copyright (c) 2003-2007 Erez Zadok
2929 + * Copyright (c) 2003-2006 Charles P. Wright
2930 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
2931 + * Copyright (c) 2005 Arun M. Krishnakumar
2932 + * Copyright (c) 2004-2006 David P. Quigley
2933 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
2934 + * Copyright (c) 2003 Puja Gupta
2935 + * Copyright (c) 2003 Harikesavan Krishnan
2936 + * Copyright (c) 2003-2007 Stony Brook University
2937 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
2938 + *
2939 + * This program is free software; you can redistribute it and/or modify
2940 + * it under the terms of the GNU General Public License version 2 as
2941 + * published by the Free Software Foundation.
2942 + */
2943 +
2944 +#ifndef _FANOUT_H_
2945 +#define _FANOUT_H_
2946 +
2947 +/* Inode to private data */
2948 +static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
2949 +{
2950 + return container_of(inode, struct unionfs_inode_info, vfs_inode);
2951 +}
2952 +
2953 +#define ibstart(ino) (UNIONFS_I(ino)->bstart)
2954 +#define ibend(ino) (UNIONFS_I(ino)->bend)
2955 +
2956 +/* Superblock to private data */
2957 +#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info)
2958 +#define sbstart(sb) 0
2959 +#define sbend(sb) (UNIONFS_SB(sb)->bend)
2960 +#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
2961 +#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
2962 +
2963 +/* File to private Data */
2964 +#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
2965 +#define fbstart(file) (UNIONFS_F(file)->bstart)
2966 +#define fbend(file) (UNIONFS_F(file)->bend)
2967 +
2968 +/* macros to manipulate branch IDs in stored in our superblock */
2969 +static inline int branch_id(struct super_block *sb, int index)
2970 +{
2971 + return UNIONFS_SB(sb)->data[index].branch_id;
2972 +}
2973 +
2974 +static inline void set_branch_id(struct super_block *sb, int index, int val)
2975 +{
2976 + UNIONFS_SB(sb)->data[index].branch_id = val;
2977 +}
2978 +
2979 +static inline void new_branch_id(struct super_block *sb, int index)
2980 +{
2981 + set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
2982 +}
2983 +
2984 +/* File to lower file. */
2985 +static inline struct file *unionfs_lower_file(const struct file *f)
2986 +{
2987 + return UNIONFS_F(f)->lower_files[fbstart(f)];
2988 +}
2989 +
2990 +static inline struct file *unionfs_lower_file_idx(const struct file *f, int index)
2991 +{
2992 + return UNIONFS_F(f)->lower_files[index];
2993 +}
2994 +
2995 +static inline void unionfs_set_lower_file_idx(struct file *f, int index, struct file *val)
2996 +{
2997 + UNIONFS_F(f)->lower_files[index] = val;
2998 + /* save branch ID (may be redundant?) */
2999 + UNIONFS_F(f)->saved_branch_ids[index] =
3000 + branch_id((f)->f_dentry->d_sb, index);
3001 +}
3002 +
3003 +static inline void unionfs_set_lower_file(struct file *f, struct file *val)
3004 +{
3005 + unionfs_set_lower_file_idx((f), fbstart(f), (val));
3006 +}
3007 +
3008 +/* Inode to lower inode. */
3009 +static inline struct inode *unionfs_lower_inode(const struct inode *i)
3010 +{
3011 + return UNIONFS_I(i)->lower_inodes[ibstart(i)];
3012 +}
3013 +
3014 +static inline struct inode *unionfs_lower_inode_idx(const struct inode *i, int index)
3015 +{
3016 + return UNIONFS_I(i)->lower_inodes[index];
3017 +}
3018 +
3019 +static inline void unionfs_set_lower_inode_idx(struct inode *i, int index,
3020 + struct inode *val)
3021 +{
3022 + UNIONFS_I(i)->lower_inodes[index] = val;
3023 +}
3024 +
3025 +static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val)
3026 +{
3027 + UNIONFS_I(i)->lower_inodes[ibstart(i)] = val;
3028 +}
3029 +
3030 +/* Superblock to lower superblock. */
3031 +static inline struct super_block *unionfs_lower_super(const struct super_block *sb)
3032 +{
3033 + return UNIONFS_SB(sb)->data[sbstart(sb)].sb;
3034 +}
3035 +
3036 +static inline struct super_block *unionfs_lower_super_idx(const struct super_block *sb, int index)
3037 +{
3038 + return UNIONFS_SB(sb)->data[index].sb;
3039 +}
3040 +
3041 +static inline void unionfs_set_lower_super_idx(struct super_block *sb, int index,
3042 + struct super_block *val)
3043 +{
3044 + UNIONFS_SB(sb)->data[index].sb = val;
3045 +}
3046 +
3047 +static inline void unionfs_set_lower_super(struct super_block *sb, struct super_block *val)
3048 +{
3049 + UNIONFS_SB(sb)->data[sbstart(sb)].sb = val;
3050 +}
3051 +
3052 +/* Branch count macros. */
3053 +static inline int branch_count(const struct super_block *sb, int index)
3054 +{
3055 + return atomic_read(&UNIONFS_SB(sb)->data[index].open_files);
3056 +}
3057 +
3058 +static inline void set_branch_count(struct super_block *sb, int index, int val)
3059 +{
3060 + atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val);
3061 +}
3062 +
3063 +static inline void branchget(struct super_block *sb, int index)
3064 +{
3065 + atomic_inc(&UNIONFS_SB(sb)->data[index].open_files);
3066 +}
3067 +
3068 +static inline void branchput(struct super_block *sb, int index)
3069 +{
3070 + atomic_dec(&UNIONFS_SB(sb)->data[index].open_files);
3071 +}
3072 +
3073 +/* Dentry macros */
3074 +static inline struct unionfs_dentry_info *UNIONFS_D(const struct dentry *dent)
3075 +{
3076 + return dent->d_fsdata;
3077 +}
3078 +
3079 +static inline int dbstart(const struct dentry *dent)
3080 +{
3081 + return UNIONFS_D(dent)->bstart;
3082 +}
3083 +
3084 +static inline void set_dbstart(struct dentry *dent, int val)
3085 +{
3086 + UNIONFS_D(dent)->bstart = val;
3087 +}
3088 +
3089 +static inline int dbend(const struct dentry *dent)
3090 +{
3091 + return UNIONFS_D(dent)->bend;
3092 +}
3093 +
3094 +static inline void set_dbend(struct dentry *dent, int val)
3095 +{
3096 + UNIONFS_D(dent)->bend = val;
3097 +}
3098 +
3099 +static inline int dbopaque(const struct dentry *dent)
3100 +{
3101 + return UNIONFS_D(dent)->bopaque;
3102 +}
3103 +
3104 +static inline void set_dbopaque(struct dentry *dent, int val)
3105 +{
3106 + UNIONFS_D(dent)->bopaque = val;
3107 +}
3108 +
3109 +static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
3110 + struct dentry *val)
3111 +{
3112 + UNIONFS_D(dent)->lower_paths[index].dentry = val;
3113 +}
3114 +
3115 +static inline struct dentry *unionfs_lower_dentry_idx(const struct dentry *dent, int index)
3116 +{
3117 + return UNIONFS_D(dent)->lower_paths[index].dentry;
3118 +}
3119 +
3120 +static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent)
3121 +{
3122 + return unionfs_lower_dentry_idx(dent, dbstart(dent));
3123 +}
3124 +
3125 +static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index,
3126 + struct vfsmount *mnt)
3127 +{
3128 + UNIONFS_D(dent)->lower_paths[index].mnt = mnt;
3129 +}
3130 +
3131 +static inline struct vfsmount *unionfs_lower_mnt_idx(const struct dentry *dent, int index)
3132 +{
3133 + return UNIONFS_D(dent)->lower_paths[index].mnt;
3134 +}
3135 +
3136 +static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent)
3137 +{
3138 + return unionfs_lower_mnt_idx(dent,dbstart(dent));
3139 +}
3140 +
3141 +/* Macros for locking a dentry. */
3142 +static inline void unionfs_lock_dentry(struct dentry *d)
3143 +{
3144 + mutex_lock(&UNIONFS_D(d)->lock);
3145 +}
3146 +
3147 +static inline void unionfs_unlock_dentry(struct dentry *d)
3148 +{
3149 + mutex_unlock(&UNIONFS_D(d)->lock);
3150 +}
3151 +
3152 +static inline void verify_locked(struct dentry *d)
3153 +{
3154 + BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock));
3155 +}
3156 +
3157 +#endif /* _FANOUT_H */
3158 diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
3159 new file mode 100644
3160 index 0000000..84d6bab
3161 --- /dev/null
3162 +++ b/fs/unionfs/file.c
3163 @@ -0,0 +1,266 @@
3164 +/*
3165 + * Copyright (c) 2003-2007 Erez Zadok
3166 + * Copyright (c) 2003-2006 Charles P. Wright
3167 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
3168 + * Copyright (c) 2005-2006 Junjiro Okajima
3169 + * Copyright (c) 2005 Arun M. Krishnakumar
3170 + * Copyright (c) 2004-2006 David P. Quigley
3171 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
3172 + * Copyright (c) 2003 Puja Gupta
3173 + * Copyright (c) 2003 Harikesavan Krishnan
3174 + * Copyright (c) 2003-2007 Stony Brook University
3175 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
3176 + *
3177 + * This program is free software; you can redistribute it and/or modify
3178 + * it under the terms of the GNU General Public License version 2 as
3179 + * published by the Free Software Foundation.
3180 + */
3181 +
3182 +#include "union.h"
3183 +
3184 +/*******************
3185 + * File Operations *
3186 + *******************/
3187 +
3188 +static loff_t unionfs_llseek(struct file *file, loff_t offset, int origin)
3189 +{
3190 + loff_t err;
3191 + struct file *hidden_file = NULL;
3192 +
3193 + unionfs_read_lock(file->f_dentry->d_sb);
3194 + if ((err = unionfs_file_revalidate(file, 0)))
3195 + goto out;
3196 +
3197 + hidden_file = unionfs_lower_file(file);
3198 + /* always set hidden position to this one */
3199 + hidden_file->f_pos = file->f_pos;
3200 +
3201 + memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
3202 +
3203 + if (hidden_file->f_op && hidden_file->f_op->llseek)
3204 + err = hidden_file->f_op->llseek(hidden_file, offset, origin);
3205 + else
3206 + err = generic_file_llseek(hidden_file, offset, origin);
3207 +
3208 + if (err < 0)
3209 + goto out;
3210 + if (err != file->f_pos) {
3211 + file->f_pos = err;
3212 + file->f_version++;
3213 + }
3214 +out:
3215 + unionfs_read_unlock(file->f_dentry->d_sb);
3216 + return err;
3217 +}
3218 +
3219 +static ssize_t unionfs_read(struct file * file, char __user * buf,
3220 + size_t count, loff_t * ppos)
3221 +{
3222 + struct file *hidden_file;
3223 + loff_t pos = *ppos;
3224 + int err;
3225 +
3226 + unionfs_read_lock(file->f_dentry->d_sb);
3227 + if ((err = unionfs_file_revalidate(file, 0)))
3228 + goto out;
3229 +
3230 + err = -EINVAL;
3231 + hidden_file = unionfs_lower_file(file);
3232 + if (!hidden_file->f_op || !hidden_file->f_op->read)
3233 + goto out;
3234 +
3235 + err = hidden_file->f_op->read(hidden_file, buf, count, &pos);
3236 + *ppos = pos;
3237 +
3238 +out:
3239 + unionfs_read_unlock(file->f_dentry->d_sb);
3240 + return err;
3241 +}
3242 +
3243 +static ssize_t __unionfs_write(struct file * file, const char __user * buf,
3244 + size_t count, loff_t * ppos)
3245 +{
3246 + int err = -EINVAL;
3247 + struct file *hidden_file = NULL;
3248 + struct inode *inode;
3249 + struct inode *hidden_inode;
3250 + loff_t pos = *ppos;
3251 + int bstart, bend;
3252 +
3253 + inode = file->f_dentry->d_inode;
3254 +
3255 + bstart = fbstart(file);
3256 + bend = fbend(file);
3257 +
3258 + BUG_ON(bstart == -1);
3259 +
3260 + hidden_file = unionfs_lower_file(file);
3261 + hidden_inode = hidden_file->f_dentry->d_inode;
3262 +
3263 + if (!hidden_file->f_op || !hidden_file->f_op->write)
3264 + goto out;
3265 +
3266 + /* adjust for append -- seek to the end of the file */
3267 + if (file->f_flags & O_APPEND)
3268 + pos = inode->i_size;
3269 +
3270 + err = hidden_file->f_op->write(hidden_file, buf, count, &pos);
3271 +
3272 + /*
3273 + * copy ctime and mtime from lower layer attributes
3274 + * atime is unchanged for both layers
3275 + */
3276 + if (err >= 0)
3277 + fsstack_copy_attr_times(inode, hidden_inode);
3278 +
3279 + *ppos = pos;
3280 +
3281 + /* update this inode's size */
3282 + if (pos > inode->i_size)
3283 + inode->i_size = pos;
3284 +out:
3285 + return err;
3286 +}
3287 +
3288 +static ssize_t unionfs_write(struct file * file, const char __user * buf,
3289 + size_t count, loff_t * ppos)
3290 +{
3291 + int err = 0;
3292 +
3293 + unionfs_read_lock(file->f_dentry->d_sb);
3294 + if ((err = unionfs_file_revalidate(file, 1)))
3295 + goto out;
3296 +
3297 + err = __unionfs_write(file, buf, count, ppos);
3298 +
3299 +out:
3300 + unionfs_read_unlock(file->f_dentry->d_sb);
3301 + return err;
3302 +}
3303 +
3304 +static int unionfs_file_readdir(struct file *file, void *dirent,
3305 + filldir_t filldir)
3306 +{
3307 + return -ENOTDIR;
3308 +}
3309 +
3310 +static unsigned int unionfs_poll(struct file *file, poll_table * wait)
3311 +{
3312 + unsigned int mask = DEFAULT_POLLMASK;
3313 + struct file *hidden_file = NULL;
3314 +
3315 + unionfs_read_lock(file->f_dentry->d_sb);
3316 + if (unionfs_file_revalidate(file, 0)) {
3317 + /* We should pretend an error happend. */
3318 + mask = POLLERR | POLLIN | POLLOUT;
3319 + goto out;
3320 + }
3321 +
3322 + hidden_file = unionfs_lower_file(file);
3323 +
3324 + if (!hidden_file->f_op || !hidden_file->f_op->poll)
3325 + goto out;
3326 +
3327 + mask = hidden_file->f_op->poll(hidden_file, wait);
3328 +
3329 +out:
3330 + unionfs_read_unlock(file->f_dentry->d_sb);
3331 + return mask;
3332 +}
3333 +
3334 +static int __do_mmap(struct file *file, struct vm_area_struct *vma)
3335 +{
3336 + int err;
3337 + struct file *hidden_file;
3338 +
3339 + hidden_file = unionfs_lower_file(file);
3340 +
3341 + err = -ENODEV;
3342 + if (!hidden_file->f_op || !hidden_file->f_op->mmap)
3343 + goto out;
3344 +
3345 + vma->vm_file = hidden_file;
3346 + err = hidden_file->f_op->mmap(hidden_file, vma);
3347 + get_file(hidden_file); /* make sure it doesn't get freed on us */
3348 + fput(file); /* no need to keep extra ref on ours */
3349 +out:
3350 + return err;
3351 +}
3352 +
3353 +static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
3354 +{
3355 + int err = 0;
3356 + int willwrite;
3357 +
3358 + unionfs_read_lock(file->f_dentry->d_sb);
3359 + /* This might could be deferred to mmap's writepage. */
3360 + willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
3361 + if ((err = unionfs_file_revalidate(file, willwrite)))
3362 + goto out;
3363 +
3364 + err = __do_mmap(file, vma);
3365 +
3366 +out:
3367 + unionfs_read_unlock(file->f_dentry->d_sb);
3368 + return err;
3369 +}
3370 +
3371 +static int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync)
3372 +{
3373 + int err;
3374 + struct file *hidden_file = NULL;
3375 +
3376 + unionfs_read_lock(file->f_dentry->d_sb);
3377 + if ((err = unionfs_file_revalidate(file, 1)))
3378 + goto out;
3379 +
3380 + hidden_file = unionfs_lower_file(file);
3381 +
3382 + err = -EINVAL;
3383 + if (!hidden_file->f_op || !hidden_file->f_op->fsync)
3384 + goto out;
3385 +
3386 + mutex_lock(&hidden_file->f_dentry->d_inode->i_mutex);
3387 + err = hidden_file->f_op->fsync(hidden_file, hidden_file->f_dentry,
3388 + datasync);
3389 + mutex_unlock(&hidden_file->f_dentry->d_inode->i_mutex);
3390 +
3391 +out:
3392 + unionfs_read_unlock(file->f_dentry->d_sb);
3393 + return err;
3394 +}
3395 +
3396 +static int unionfs_fasync(int fd, struct file *file, int flag)
3397 +{
3398 + int err = 0;
3399 + struct file *hidden_file = NULL;
3400 +
3401 + unionfs_read_lock(file->f_dentry->d_sb);
3402 + if ((err = unionfs_file_revalidate(file, 1)))
3403 + goto out;
3404 +
3405 + hidden_file = unionfs_lower_file(file);
3406 +
3407 + if (hidden_file->f_op && hidden_file->f_op->fasync)
3408 + err = hidden_file->f_op->fasync(fd, hidden_file, flag);
3409 +
3410 +out:
3411 + unionfs_read_unlock(file->f_dentry->d_sb);
3412 + return err;
3413 +}
3414 +
3415 +struct file_operations unionfs_main_fops = {
3416 + .llseek = unionfs_llseek,
3417 + .read = unionfs_read,
3418 + .write = unionfs_write,
3419 + .readdir = unionfs_file_readdir,
3420 + .poll = unionfs_poll,
3421 + .unlocked_ioctl = unionfs_ioctl,
3422 + .mmap = unionfs_mmap,
3423 + .open = unionfs_open,
3424 + .flush = unionfs_flush,
3425 + .release = unionfs_file_release,
3426 + .fsync = unionfs_fsync,
3427 + .fasync = unionfs_fasync,
3428 +};
3429 +
3430 diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
3431 new file mode 100644
3432 index 0000000..97dad8c
3433 --- /dev/null
3434 +++ b/fs/unionfs/inode.c
3435 @@ -0,0 +1,1016 @@
3436 +/*
3437 + * Copyright (c) 2003-2007 Erez Zadok
3438 + * Copyright (c) 2003-2006 Charles P. Wright
3439 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
3440 + * Copyright (c) 2005-2006 Junjiro Okajima
3441 + * Copyright (c) 2005 Arun M. Krishnakumar
3442 + * Copyright (c) 2004-2006 David P. Quigley
3443 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
3444 + * Copyright (c) 2003 Puja Gupta
3445 + * Copyright (c) 2003 Harikesavan Krishnan
3446 + * Copyright (c) 2003-2007 Stony Brook University
3447 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
3448 + *
3449 + * This program is free software; you can redistribute it and/or modify
3450 + * it under the terms of the GNU General Public License version 2 as
3451 + * published by the Free Software Foundation.
3452 + */
3453 +
3454 +#include "union.h"
3455 +
3456 +static int unionfs_create(struct inode *parent, struct dentry *dentry,
3457 + int mode, struct nameidata *nd)
3458 +{
3459 + int err = 0;
3460 + struct dentry *hidden_dentry = NULL;
3461 + struct dentry *wh_dentry = NULL;
3462 + struct dentry *new_hidden_dentry;
3463 + struct dentry *hidden_parent_dentry = NULL;
3464 + int bindex = 0, bstart;
3465 + char *name = NULL;
3466 + int valid = 0;
3467 +
3468 + /*
3469 + * We have to read-lock the superblock rwsem, and we have to
3470 + * revalidate the parent dentry and this one. A branch-management
3471 + * operation could have taken place, mid-way through a VFS operation
3472 + * that eventually reaches here. So we have to ensure consistency,
3473 + * just as we do with the file operations.
3474 + *
3475 + * XXX: we may need to do this for all other inode ops that take a
3476 + * dentry.
3477 + */
3478 + unionfs_read_lock(dentry->d_sb);
3479 + unionfs_lock_dentry(dentry);
3480 +
3481 + unionfs_lock_dentry(dentry->d_parent);
3482 + valid = __unionfs_d_revalidate_chain(dentry->d_parent, nd);
3483 + unionfs_unlock_dentry(dentry->d_parent);
3484 + if (!valid) {
3485 + err = -ENOENT; /* same as what real_lookup does */
3486 + goto out;
3487 + }
3488 + valid = __unionfs_d_revalidate_chain(dentry, nd);
3489 + /*
3490 + * It's only a bug if this dentry was not negative and couldn't be
3491 + * revalidated (shouldn't happen).
3492 + */
3493 + BUG_ON(!valid && dentry->d_inode);
3494 +
3495 + /* We start out in the leftmost branch. */
3496 + bstart = dbstart(dentry);
3497 + hidden_dentry = unionfs_lower_dentry(dentry);
3498 +
3499 + /* check if whiteout exists in this branch, i.e. lookup .wh.foo first */
3500 + name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
3501 + if (IS_ERR(name)) {
3502 + err = PTR_ERR(name);
3503 + goto out;
3504 + }
3505 +
3506 + wh_dentry = lookup_one_len(name, hidden_dentry->d_parent,
3507 + dentry->d_name.len + UNIONFS_WHLEN);
3508 + if (IS_ERR(wh_dentry)) {
3509 + err = PTR_ERR(wh_dentry);
3510 + wh_dentry = NULL;
3511 + goto out;
3512 + }
3513 +
3514 + if (wh_dentry->d_inode) {
3515 + /* .wh.foo has been found. */
3516 + /* First truncate it and then rename it to foo (hence having
3517 + * the same overall effect as a normal create.
3518 + */
3519 + struct dentry *hidden_dir_dentry;
3520 + struct iattr newattrs;
3521 +
3522 + mutex_lock(&wh_dentry->d_inode->i_mutex);
3523 + newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME
3524 + | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE
3525 + | ATTR_KILL_SUID | ATTR_KILL_SGID;
3526 +
3527 + newattrs.ia_mode = mode & ~current->fs->umask;
3528 + newattrs.ia_uid = current->fsuid;
3529 + newattrs.ia_gid = current->fsgid;
3530 +
3531 + if (wh_dentry->d_inode->i_size != 0) {
3532 + newattrs.ia_valid |= ATTR_SIZE;
3533 + newattrs.ia_size = 0;
3534 + }
3535 +
3536 + err = notify_change(wh_dentry, &newattrs);
3537 +
3538 + mutex_unlock(&wh_dentry->d_inode->i_mutex);
3539 +
3540 + if (err)
3541 + printk(KERN_WARNING "unionfs: %s:%d: notify_change "
3542 + "failed: %d, ignoring..\n",
3543 + __FILE__, __LINE__, err);
3544 +
3545 + new_hidden_dentry = unionfs_lower_dentry(dentry);
3546 + dget(new_hidden_dentry);
3547 +
3548 + hidden_dir_dentry = dget_parent(wh_dentry);
3549 + lock_rename(hidden_dir_dentry, hidden_dir_dentry);
3550 +
3551 + if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
3552 + err = vfs_rename(hidden_dir_dentry->d_inode,
3553 + wh_dentry,
3554 + hidden_dir_dentry->d_inode,
3555 + new_hidden_dentry);
3556 + }
3557 + if (!err) {
3558 + fsstack_copy_attr_times(parent,
3559 + new_hidden_dentry->d_parent->d_inode);
3560 + fsstack_copy_inode_size(parent,
3561 + new_hidden_dentry->d_parent->d_inode);
3562 + parent->i_nlink = unionfs_get_nlinks(parent);
3563 + }
3564 +
3565 + unlock_rename(hidden_dir_dentry, hidden_dir_dentry);
3566 + dput(hidden_dir_dentry);
3567 +
3568 + dput(new_hidden_dentry);
3569 +
3570 + if (err) {
3571 + /* exit if the error returned was NOT -EROFS */
3572 + if (!IS_COPYUP_ERR(err))
3573 + goto out;
3574 + /* We were not able to create the file in this
3575 + * branch, so, we try to create it in one branch to
3576 + * left
3577 + */
3578 + bstart--;
3579 + } else {
3580 + /* reset the unionfs dentry to point to the .wh.foo
3581 + * entry.
3582 + */
3583 +
3584 + /* Discard any old reference. */
3585 + dput(unionfs_lower_dentry(dentry));
3586 +
3587 + /* Trade one reference to another. */
3588 + unionfs_set_lower_dentry_idx(dentry, bstart, wh_dentry);
3589 + wh_dentry = NULL;
3590 +
3591 + err = unionfs_interpose(dentry, parent->i_sb, 0);
3592 + goto out;
3593 + }
3594 + }
3595 +
3596 + for (bindex = bstart; bindex >= 0; bindex--) {
3597 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
3598 + if (!hidden_dentry) {
3599 + /* if hidden_dentry is NULL, create the entire
3600 + * dentry directory structure in branch 'bindex'.
3601 + * hidden_dentry will NOT be null when bindex == bstart
3602 + * because lookup passed as a negative unionfs dentry
3603 + * pointing to a lone negative underlying dentry */
3604 + hidden_dentry = create_parents(parent, dentry, bindex);
3605 + if (!hidden_dentry || IS_ERR(hidden_dentry)) {
3606 + if (IS_ERR(hidden_dentry))
3607 + err = PTR_ERR(hidden_dentry);
3608 + continue;
3609 + }
3610 + }
3611 +
3612 + hidden_parent_dentry = lock_parent(hidden_dentry);
3613 + if (IS_ERR(hidden_parent_dentry)) {
3614 + err = PTR_ERR(hidden_parent_dentry);
3615 + goto out;
3616 + }
3617 + /* We shouldn't create things in a read-only branch. */
3618 + if (!(err = is_robranch_super(dentry->d_sb, bindex)))
3619 + err = vfs_create(hidden_parent_dentry->d_inode,
3620 + hidden_dentry, mode, nd);
3621 +
3622 + if (err || !hidden_dentry->d_inode) {
3623 + unlock_dir(hidden_parent_dentry);
3624 +
3625 + /* break out of for loop if the error wasn't -EROFS */
3626 + if (!IS_COPYUP_ERR(err))
3627 + break;
3628 + } else {
3629 + err = unionfs_interpose(dentry, parent->i_sb, 0);
3630 + if (!err) {
3631 + fsstack_copy_attr_times(parent,
3632 + hidden_parent_dentry->d_inode);
3633 + fsstack_copy_inode_size(parent,
3634 + hidden_parent_dentry->d_inode);
3635 + /* update number of links on parent directory */
3636 + parent->i_nlink = unionfs_get_nlinks(parent);
3637 + }
3638 + unlock_dir(hidden_parent_dentry);
3639 + break;
3640 + }
3641 + }
3642 +
3643 +out:
3644 + dput(wh_dentry);
3645 + kfree(name);
3646 +
3647 + unionfs_unlock_dentry(dentry);
3648 + unionfs_read_unlock(dentry->d_sb);
3649 + return err;
3650 +}
3651 +
3652 +static struct dentry *unionfs_lookup(struct inode *parent,
3653 + struct dentry *dentry,
3654 + struct nameidata *nd)
3655 +{
3656 + struct path path_save;
3657 + struct dentry *ret;
3658 +
3659 + /* save the dentry & vfsmnt from namei */
3660 + if (nd) {
3661 + path_save.dentry = nd->dentry;
3662 + path_save.mnt = nd->mnt;
3663 + }
3664 +
3665 + /* The locking is done by unionfs_lookup_backend. */
3666 + ret = unionfs_lookup_backend(dentry, nd, INTERPOSE_LOOKUP);
3667 +
3668 + /* restore the dentry & vfsmnt in namei */
3669 + if (nd) {
3670 + nd->dentry = path_save.dentry;
3671 + nd->mnt = path_save.mnt;
3672 + }
3673 +
3674 + return ret;
3675 +}
3676 +
3677 +static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
3678 + struct dentry *new_dentry)
3679 +{
3680 + int err = 0;
3681 + struct dentry *hidden_old_dentry = NULL;
3682 + struct dentry *hidden_new_dentry = NULL;
3683 + struct dentry *hidden_dir_dentry = NULL;
3684 + struct dentry *whiteout_dentry;
3685 + char *name = NULL;
3686 +
3687 + BUG_ON(!is_valid_dentry(new_dentry));
3688 + BUG_ON(!is_valid_dentry(old_dentry));
3689 +
3690 + double_lock_dentry(new_dentry, old_dentry);
3691 +
3692 + hidden_new_dentry = unionfs_lower_dentry(new_dentry);
3693 +
3694 + /* check if whiteout exists in the branch of new dentry, i.e. lookup
3695 + * .wh.foo first. If present, delete it
3696 + */
3697 + name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len);
3698 + if (IS_ERR(name)) {
3699 + err = PTR_ERR(name);
3700 + goto out;
3701 + }
3702 +
3703 + whiteout_dentry = lookup_one_len(name, hidden_new_dentry->d_parent,
3704 + new_dentry->d_name.len + UNIONFS_WHLEN);
3705 + if (IS_ERR(whiteout_dentry)) {
3706 + err = PTR_ERR(whiteout_dentry);
3707 + goto out;
3708 + }
3709 +
3710 + if (!whiteout_dentry->d_inode) {
3711 + dput(whiteout_dentry);
3712 + whiteout_dentry = NULL;
3713 + } else {
3714 + /* found a .wh.foo entry, unlink it and then call vfs_link() */
3715 + hidden_dir_dentry = lock_parent(whiteout_dentry);
3716 + err = is_robranch_super(new_dentry->d_sb, dbstart(new_dentry));
3717 + if (!err)
3718 + err = vfs_unlink(hidden_dir_dentry->d_inode,
3719 + whiteout_dentry);
3720 +
3721 + fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
3722 + dir->i_nlink = unionfs_get_nlinks(dir);
3723 + unlock_dir(hidden_dir_dentry);
3724 + hidden_dir_dentry = NULL;
3725 + dput(whiteout_dentry);
3726 + if (err)
3727 + goto out;
3728 + }
3729 +
3730 + if (dbstart(old_dentry) != dbstart(new_dentry)) {
3731 + hidden_new_dentry =
3732 + create_parents(dir, new_dentry, dbstart(old_dentry));
3733 + err = PTR_ERR(hidden_new_dentry);
3734 + if (IS_COPYUP_ERR(err))
3735 + goto docopyup;
3736 + if (!hidden_new_dentry || IS_ERR(hidden_new_dentry))
3737 + goto out;
3738 + }
3739 + hidden_new_dentry = unionfs_lower_dentry(new_dentry);
3740 + hidden_old_dentry = unionfs_lower_dentry(old_dentry);
3741 +
3742 + BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
3743 + hidden_dir_dentry = lock_parent(hidden_new_dentry);
3744 + if (!(err = is_robranch(old_dentry)))
3745 + err = vfs_link(hidden_old_dentry, hidden_dir_dentry->d_inode,
3746 + hidden_new_dentry);
3747 + unlock_dir(hidden_dir_dentry);
3748 +
3749 +docopyup:
3750 + if (IS_COPYUP_ERR(err)) {
3751 + int old_bstart = dbstart(old_dentry);
3752 + int bindex;
3753 +
3754 + for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
3755 + err =
3756 + copyup_dentry(old_dentry->d_parent->
3757 + d_inode, old_dentry,
3758 + old_bstart, bindex, NULL,
3759 + old_dentry->d_inode->i_size);
3760 + if (!err) {
3761 + hidden_new_dentry =
3762 + create_parents(dir, new_dentry, bindex);
3763 + hidden_old_dentry = unionfs_lower_dentry(old_dentry);
3764 + hidden_dir_dentry =
3765 + lock_parent(hidden_new_dentry);
3766 + /* do vfs_link */
3767 + err = vfs_link(hidden_old_dentry,
3768 + hidden_dir_dentry->d_inode,
3769 + hidden_new_dentry);
3770 + unlock_dir(hidden_dir_dentry);
3771 + goto check_link;
3772 + }
3773 + }
3774 + goto out;
3775 + }
3776 +
3777 +check_link:
3778 + if (err || !hidden_new_dentry->d_inode)
3779 + goto out;
3780 +
3781 + /* Its a hard link, so use the same inode */
3782 + new_dentry->d_inode = igrab(old_dentry->d_inode);
3783 + d_instantiate(new_dentry, new_dentry->d_inode);
3784 + fsstack_copy_attr_all(dir, hidden_new_dentry->d_parent->d_inode,
3785 + unionfs_get_nlinks);
3786 + fsstack_copy_inode_size(dir, hidden_new_dentry->d_parent->d_inode);
3787 +
3788 + /* propagate number of hard-links */
3789 + old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
3790 +
3791 +out:
3792 + if (!new_dentry->d_inode)
3793 + d_drop(new_dentry);
3794 +
3795 + kfree(name);
3796 +
3797 + unionfs_unlock_dentry(new_dentry);
3798 + unionfs_unlock_dentry(old_dentry);
3799 +
3800 + return err;
3801 +}
3802 +
3803 +static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
3804 + const char *symname)
3805 +{
3806 + int err = 0;
3807 + struct dentry *hidden_dentry = NULL;
3808 + struct dentry *whiteout_dentry = NULL;
3809 + struct dentry *hidden_dir_dentry = NULL;
3810 + umode_t mode;
3811 + int bindex = 0, bstart;
3812 + char *name = NULL;
3813 +
3814 + BUG_ON(!is_valid_dentry(dentry));
3815 +
3816 + unionfs_lock_dentry(dentry);
3817 +
3818 + /* We start out in the leftmost branch. */
3819 + bstart = dbstart(dentry);
3820 +
3821 + hidden_dentry = unionfs_lower_dentry(dentry);
3822 +
3823 + /* check if whiteout exists in this branch, i.e. lookup .wh.foo
3824 + * first. If present, delete it
3825 + */
3826 + name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
3827 + if (IS_ERR(name)) {
3828 + err = PTR_ERR(name);
3829 + goto out;
3830 + }
3831 +
3832 + whiteout_dentry =
3833 + lookup_one_len(name, hidden_dentry->d_parent,
3834 + dentry->d_name.len + UNIONFS_WHLEN);
3835 + if (IS_ERR(whiteout_dentry)) {
3836 + err = PTR_ERR(whiteout_dentry);
3837 + goto out;
3838 + }
3839 +
3840 + if (!whiteout_dentry->d_inode) {
3841 + dput(whiteout_dentry);
3842 + whiteout_dentry = NULL;
3843 + } else {
3844 + /* found a .wh.foo entry, unlink it and then call vfs_symlink() */
3845 + hidden_dir_dentry = lock_parent(whiteout_dentry);
3846 +
3847 + if (!(err = is_robranch_super(dentry->d_sb, bstart)))
3848 + err = vfs_unlink(hidden_dir_dentry->d_inode,
3849 + whiteout_dentry);
3850 + dput(whiteout_dentry);
3851 +
3852 + fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
3853 + /* propagate number of hard-links */
3854 + dir->i_nlink = unionfs_get_nlinks(dir);
3855 +
3856 + unlock_dir(hidden_dir_dentry);
3857 +
3858 + if (err) {
3859 + /* exit if the error returned was NOT -EROFS */
3860 + if (!IS_COPYUP_ERR(err))
3861 + goto out;
3862 + /* should now try to create symlink in the another branch */
3863 + bstart--;
3864 + }
3865 + }
3866 +
3867 + /* deleted whiteout if it was present, now do a normal vfs_symlink()
3868 + * with possible recursive directory creation
3869 + */
3870 + for (bindex = bstart; bindex >= 0; bindex--) {
3871 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
3872 + if (!hidden_dentry) {
3873 + /* if hidden_dentry is NULL, create the entire
3874 + * dentry directory structure in branch 'bindex'.
3875 + * hidden_dentry will NOT be null when bindex ==
3876 + * bstart because lookup passed as a negative
3877 + * unionfs dentry pointing to a lone negative
3878 + * underlying dentry
3879 + */
3880 + hidden_dentry = create_parents(dir, dentry, bindex);
3881 + if (!hidden_dentry || IS_ERR(hidden_dentry)) {
3882 + if (IS_ERR(hidden_dentry))
3883 + err = PTR_ERR(hidden_dentry);
3884 +
3885 + printk(KERN_DEBUG "hidden dentry NULL (or error)"
3886 + "for bindex = %d\n", bindex);
3887 + continue;
3888 + }
3889 + }
3890 +
3891 + hidden_dir_dentry = lock_parent(hidden_dentry);
3892 +
3893 + if (!(err = is_robranch_super(dentry->d_sb, bindex))) {
3894 + mode = S_IALLUGO;
3895 + err =
3896 + vfs_symlink(hidden_dir_dentry->d_inode,
3897 + hidden_dentry, symname, mode);
3898 + }
3899 + unlock_dir(hidden_dir_dentry);
3900 +
3901 + if (err || !hidden_dentry->d_inode) {
3902 + /* break out of for loop if error returned was NOT -EROFS */
3903 + if (!IS_COPYUP_ERR(err))
3904 + break;
3905 + } else {
3906 + err = unionfs_interpose(dentry, dir->i_sb, 0);
3907 + if (!err) {
3908 + fsstack_copy_attr_times(dir,
3909 + hidden_dir_dentry->d_inode);
3910 + fsstack_copy_inode_size(dir,
3911 + hidden_dir_dentry->d_inode);
3912 + /* update number of links on parent directory */
3913 + dir->i_nlink = unionfs_get_nlinks(dir);
3914 + }
3915 + break;
3916 + }
3917 + }
3918 +
3919 +out:
3920 + if (!dentry->d_inode)
3921 + d_drop(dentry);
3922 +
3923 + kfree(name);
3924 + unionfs_unlock_dentry(dentry);
3925 + return err;
3926 +}
3927 +
3928 +static int unionfs_mkdir(struct inode *parent, struct dentry *dentry, int mode)
3929 +{
3930 + int err = 0;
3931 + struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
3932 + struct dentry *hidden_parent_dentry = NULL;
3933 + int bindex = 0, bstart;
3934 + char *name = NULL;
3935 + int whiteout_unlinked = 0;
3936 + struct sioq_args args;
3937 +
3938 + BUG_ON(!is_valid_dentry(dentry));
3939 +
3940 + unionfs_lock_dentry(dentry);
3941 + bstart = dbstart(dentry);
3942 +
3943 + hidden_dentry = unionfs_lower_dentry(dentry);
3944 +
3945 + /* check if whiteout exists in this branch, i.e. lookup .wh.foo first */
3946 + name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
3947 + if (IS_ERR(name)) {
3948 + err = PTR_ERR(name);
3949 + goto out;
3950 + }
3951 +
3952 + whiteout_dentry = lookup_one_len(name, hidden_dentry->d_parent,
3953 + dentry->d_name.len + UNIONFS_WHLEN);
3954 + if (IS_ERR(whiteout_dentry)) {
3955 + err = PTR_ERR(whiteout_dentry);
3956 + goto out;
3957 + }
3958 +
3959 + if (!whiteout_dentry->d_inode) {
3960 + dput(whiteout_dentry);
3961 + whiteout_dentry = NULL;
3962 + } else {
3963 + hidden_parent_dentry = lock_parent(whiteout_dentry);
3964 +
3965 + /* found a.wh.foo entry, remove it then do vfs_mkdir */
3966 + if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
3967 + args.unlink.parent = hidden_parent_dentry->d_inode;
3968 + args.unlink.dentry = whiteout_dentry;
3969 + run_sioq(__unionfs_unlink, &args);
3970 + err = args.err;
3971 + }
3972 + dput(whiteout_dentry);
3973 +
3974 + unlock_dir(hidden_parent_dentry);
3975 +
3976 + if (err) {
3977 + /* exit if the error returned was NOT -EROFS */
3978 + if (!IS_COPYUP_ERR(err))
3979 + goto out;
3980 + bstart--;
3981 + } else
3982 + whiteout_unlinked = 1;
3983 + }
3984 +
3985 + for (bindex = bstart; bindex >= 0; bindex--) {
3986 + int i;
3987 + int bend = dbend(dentry);
3988 +
3989 + if (is_robranch_super(dentry->d_sb, bindex))
3990 + continue;
3991 +
3992 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
3993 + if (!hidden_dentry) {
3994 + hidden_dentry = create_parents(parent, dentry, bindex);
3995 + if (!hidden_dentry || IS_ERR(hidden_dentry)) {
3996 + printk(KERN_DEBUG "hidden dentry NULL for "
3997 + "bindex = %d\n", bindex);
3998 + continue;
3999 + }
4000 + }
4001 +
4002 + hidden_parent_dentry = lock_parent(hidden_dentry);
4003 +
4004 + if (IS_ERR(hidden_parent_dentry)) {
4005 + err = PTR_ERR(hidden_parent_dentry);
4006 + goto out;
4007 + }
4008 +
4009 + err = vfs_mkdir(hidden_parent_dentry->d_inode, hidden_dentry, mode);
4010 +
4011 + unlock_dir(hidden_parent_dentry);
4012 +
4013 + /* did the mkdir suceed? */
4014 + if (err)
4015 + break;
4016 +
4017 + for (i = bindex + 1; i < bend; i++) {
4018 + if (unionfs_lower_dentry_idx(dentry, i)) {
4019 + dput(unionfs_lower_dentry_idx(dentry, i));
4020 + unionfs_set_lower_dentry_idx(dentry, i, NULL);
4021 + }
4022 + }
4023 + set_dbend(dentry, bindex);
4024 +
4025 + err = unionfs_interpose(dentry, parent->i_sb, 0);
4026 + if (!err) {
4027 + fsstack_copy_attr_times(parent,
4028 + hidden_parent_dentry->d_inode);
4029 + fsstack_copy_inode_size(parent,
4030 + hidden_parent_dentry->d_inode);
4031 +
4032 + /* update number of links on parent directory */
4033 + parent->i_nlink = unionfs_get_nlinks(parent);
4034 + }
4035 +
4036 + err = make_dir_opaque(dentry, dbstart(dentry));
4037 + if (err) {
4038 + printk(KERN_ERR "mkdir: error creating "
4039 + ".wh.__dir_opaque: %d\n", err);
4040 + goto out;
4041 + }
4042 +
4043 + /* we are done! */
4044 + break;
4045 + }
4046 +
4047 +out:
4048 + if (!dentry->d_inode)
4049 + d_drop(dentry);
4050 +
4051 + kfree(name);
4052 +
4053 + unionfs_unlock_dentry(dentry);
4054 + return err;
4055 +}
4056 +
4057 +static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
4058 + dev_t dev)
4059 +{
4060 + int err = 0;
4061 + struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
4062 + struct dentry *hidden_parent_dentry = NULL;
4063 + int bindex = 0, bstart;
4064 + char *name = NULL;
4065 + int whiteout_unlinked = 0;
4066 +
4067 + BUG_ON(!is_valid_dentry(dentry));
4068 +
4069 + unionfs_lock_dentry(dentry);
4070 + bstart = dbstart(dentry);
4071 +
4072 + hidden_dentry = unionfs_lower_dentry(dentry);
4073 +
4074 + /* check if whiteout exists in this branch, i.e. lookup .wh.foo first */
4075 + name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
4076 + if (IS_ERR(name)) {
4077 + err = PTR_ERR(name);
4078 + goto out;
4079 + }
4080 +
4081 + whiteout_dentry = lookup_one_len(name, hidden_dentry->d_parent,
4082 + dentry->d_name.len + UNIONFS_WHLEN);
4083 + if (IS_ERR(whiteout_dentry)) {
4084 + err = PTR_ERR(whiteout_dentry);
4085 + goto out;
4086 + }
4087 +
4088 + if (!whiteout_dentry->d_inode) {
4089 + dput(whiteout_dentry);
4090 + whiteout_dentry = NULL;
4091 + } else {
4092 + /* found .wh.foo, unlink it */
4093 + hidden_parent_dentry = lock_parent(whiteout_dentry);
4094 +
4095 + /* found a.wh.foo entry, remove it then do vfs_mkdir */
4096 + if (!(err = is_robranch_super(dentry->d_sb, bstart)))
4097 + err = vfs_unlink(hidden_parent_dentry->d_inode,
4098 + whiteout_dentry);
4099 + dput(whiteout_dentry);
4100 +
4101 + unlock_dir(hidden_parent_dentry);
4102 +
4103 + if (err) {
4104 + if (!IS_COPYUP_ERR(err))
4105 + goto out;
4106 +
4107 + bstart--;
4108 + } else
4109 + whiteout_unlinked = 1;
4110 + }
4111 +
4112 + for (bindex = bstart; bindex >= 0; bindex--) {
4113 + if (is_robranch_super(dentry->d_sb, bindex))
4114 + continue;
4115 +
4116 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4117 + if (!hidden_dentry) {
4118 + hidden_dentry = create_parents(dir, dentry, bindex);
4119 + if (IS_ERR(hidden_dentry)) {
4120 + printk(KERN_DEBUG
4121 + "failed to create parents on %d, err = %ld\n",
4122 + bindex, PTR_ERR(hidden_dentry));
4123 + continue;
4124 + }
4125 + }
4126 +
4127 + hidden_parent_dentry = lock_parent(hidden_dentry);
4128 + if (IS_ERR(hidden_parent_dentry)) {
4129 + err = PTR_ERR(hidden_parent_dentry);
4130 + goto out;
4131 + }
4132 +
4133 + err = vfs_mknod(hidden_parent_dentry->d_inode,
4134 + hidden_dentry, mode, dev);
4135 +
4136 + if (err) {
4137 + unlock_dir(hidden_parent_dentry);
4138 + break;
4139 + }
4140 +
4141 + err = unionfs_interpose(dentry, dir->i_sb, 0);
4142 + if (!err) {
4143 + fsstack_copy_attr_times(dir,
4144 + hidden_parent_dentry->d_inode);
4145 + fsstack_copy_inode_size(dir,
4146 + hidden_parent_dentry->d_inode);
4147 + /* update number of links on parent directory */
4148 + dir->i_nlink = unionfs_get_nlinks(dir);
4149 + }
4150 + unlock_dir(hidden_parent_dentry);
4151 +
4152 + break;
4153 + }
4154 +
4155 +out:
4156 + if (!dentry->d_inode)
4157 + d_drop(dentry);
4158 +
4159 + kfree(name);
4160 +
4161 + unionfs_unlock_dentry(dentry);
4162 + return err;
4163 +}
4164 +
4165 +static int unionfs_readlink(struct dentry *dentry, char __user * buf,
4166 + int bufsiz)
4167 +{
4168 + int err;
4169 + struct dentry *hidden_dentry;
4170 +
4171 + BUG_ON(!is_valid_dentry(dentry));
4172 +
4173 + unionfs_lock_dentry(dentry);
4174 + hidden_dentry = unionfs_lower_dentry(dentry);
4175 +
4176 + if (!hidden_dentry->d_inode->i_op ||
4177 + !hidden_dentry->d_inode->i_op->readlink) {
4178 + err = -EINVAL;
4179 + goto out;
4180 + }
4181 +
4182 + err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry, buf, bufsiz);
4183 + if (err > 0)
4184 + fsstack_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode);
4185 +
4186 +out:
4187 + unionfs_unlock_dentry(dentry);
4188 + return err;
4189 +}
4190 +
4191 +/* We don't lock the dentry here, because readlink does the heavy lifting. */
4192 +static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
4193 +{
4194 + char *buf;
4195 + int len = PAGE_SIZE, err;
4196 + mm_segment_t old_fs;
4197 +
4198 + BUG_ON(!is_valid_dentry(dentry));
4199 +
4200 + /* This is freed by the put_link method assuming a successful call. */
4201 + buf = kmalloc(len, GFP_KERNEL);
4202 + if (!buf) {
4203 + err = -ENOMEM;
4204 + goto out;
4205 + }
4206 +
4207 + /* read the symlink, and then we will follow it */
4208 + old_fs = get_fs();
4209 + set_fs(KERNEL_DS);
4210 + err = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
4211 + set_fs(old_fs);
4212 + if (err < 0) {
4213 + kfree(buf);
4214 + buf = NULL;
4215 + goto out;
4216 + }
4217 + buf[err] = 0;
4218 + nd_set_link(nd, buf);
4219 + err = 0;
4220 +
4221 +out:
4222 + return ERR_PTR(err);
4223 +}
4224 +
4225 +static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd,
4226 + void *cookie)
4227 +{
4228 + kfree(nd_get_link(nd));
4229 +}
4230 +
4231 +/* Basically copied from the kernel vfs permission(), but we've changed
4232 + * the following:
4233 + * (1) the IS_RDONLY check is skipped, and
4234 + * (2) if you set the mount option `mode=nfsro', we assume that -EACCES
4235 + * means that the export is read-only and we should check standard Unix
4236 + * permissions. This means that NFS ACL checks (or other advanced
4237 + * permission features) are bypassed. Note however, that we do call
4238 + * security_inode_permission, and therefore security inside SELinux, etc.
4239 + * are performed.
4240 + */
4241 +static int inode_permission(struct inode *inode, int mask, struct nameidata *nd,
4242 + int bindex)
4243 +{
4244 + int retval, submask;
4245 +
4246 + if (mask & MAY_WRITE) {
4247 + /* The first branch is allowed to be really readonly. */
4248 + if (bindex == 0) {
4249 + umode_t mode = inode->i_mode;
4250 + if (IS_RDONLY(inode) &&
4251 + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
4252 + return -EROFS;
4253 + }
4254 + /*
4255 + * Nobody gets write access to an immutable file.
4256 + */
4257 + if (IS_IMMUTABLE(inode))
4258 + return -EACCES;
4259 + }
4260 +
4261 + /* Ordinary permission routines do not understand MAY_APPEND. */
4262 + submask = mask & ~MAY_APPEND;
4263 + if (inode->i_op && inode->i_op->permission) {
4264 + retval = inode->i_op->permission(inode, submask, nd);
4265 + if ((retval == -EACCES) && (submask & MAY_WRITE) &&
4266 + (!strcmp("nfs", (inode)->i_sb->s_type->name)) &&
4267 + (nd) && (nd->mnt) && (nd->mnt->mnt_sb)) {
4268 + int perms;
4269 + unionfs_read_lock(nd->mnt->mnt_sb);
4270 + perms = branchperms(nd->mnt->mnt_sb, bindex);
4271 + unionfs_read_unlock(nd->mnt->mnt_sb);
4272 + if (perms & MAY_NFSRO)
4273 + retval = generic_permission(inode, submask, NULL);
4274 + }
4275 + } else
4276 + retval = generic_permission(inode, submask, NULL);
4277 +
4278 + if (retval && retval != -EROFS) /* ignore EROFS */
4279 + return retval;
4280 +
4281 + retval = security_inode_permission(inode, mask, nd);
4282 + return ((retval == -EROFS) ? 0 : retval); /* ignore EROFS */
4283 +}
4284 +
4285 +static int unionfs_permission(struct inode *inode, int mask,
4286 + struct nameidata *nd)
4287 +{
4288 + struct inode *hidden_inode = NULL;
4289 + int err = 0;
4290 + int bindex, bstart, bend;
4291 + const int is_file = !S_ISDIR(inode->i_mode);
4292 + const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
4293 +
4294 + unionfs_read_lock(inode->i_sb);
4295 +
4296 + bstart = ibstart(inode);
4297 + bend = ibend(inode);
4298 + if (bstart < 0 || bend < 0) {
4299 + /*
4300 + * With branch-management, we can get a stale inode here.
4301 + * If so, we return ESTALE back to link_path_walk, which
4302 + * would discard the dcache entry and re-lookup the
4303 + * dentry+inode. This should be equivalent to issuing
4304 + * __unionfs_d_revalidate_chain on nd.dentry here.
4305 + */
4306 + err = -ESTALE; /* force revalidate */
4307 + goto out;
4308 + }
4309 +
4310 + for (bindex = bstart; bindex <= bend; bindex++) {
4311 + hidden_inode = unionfs_lower_inode_idx(inode, bindex);
4312 + if (!hidden_inode)
4313 + continue;
4314 +
4315 + /* check the condition for D-F-D underlying files/directories,
4316 + * we dont have to check for files, if we are checking for
4317 + * directories.
4318 + */
4319 + if (!is_file && !S_ISDIR(hidden_inode->i_mode))
4320 + continue;
4321 +
4322 + /* We use our own special version of permission, such that
4323 + * only the first branch returns -EROFS.
4324 + */
4325 + err = inode_permission(hidden_inode, mask, nd, bindex);
4326 +
4327 + /* The permissions are an intersection of the overall directory
4328 + * permissions, so we fail if one fails.
4329 + */
4330 + if (err)
4331 + goto out;
4332 +
4333 + /* only the leftmost file matters. */
4334 + if (is_file || write_mask) {
4335 + if (is_file && write_mask) {
4336 + err = get_write_access(hidden_inode);
4337 + if (!err)
4338 + put_write_access(hidden_inode);
4339 + }
4340 + break;
4341 + }
4342 + }
4343 +
4344 +out:
4345 + unionfs_read_unlock(inode->i_sb);
4346 + return err;
4347 +}
4348 +
4349 +static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
4350 +{
4351 + int err = 0;
4352 + struct dentry *hidden_dentry;
4353 + struct inode *inode = NULL;
4354 + struct inode *hidden_inode = NULL;
4355 + int bstart, bend, bindex;
4356 + int i;
4357 + int copyup = 0;
4358 +
4359 + BUG_ON(!is_valid_dentry(dentry));
4360 +
4361 + unionfs_lock_dentry(dentry);
4362 + bstart = dbstart(dentry);
4363 + bend = dbend(dentry);
4364 + inode = dentry->d_inode;
4365 +
4366 + for (bindex = bstart; (bindex <= bend) || (bindex == bstart); bindex++) {
4367 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4368 + if (!hidden_dentry)
4369 + continue;
4370 + BUG_ON(hidden_dentry->d_inode == NULL);
4371 +
4372 + /* If the file is on a read only branch */
4373 + if (is_robranch_super(dentry->d_sb, bindex)
4374 + || IS_RDONLY(hidden_dentry->d_inode)) {
4375 + if (copyup || (bindex != bstart))
4376 + continue;
4377 + /* Only if its the leftmost file, copyup the file */
4378 + for (i = bstart - 1; i >= 0; i--) {
4379 + loff_t size = dentry->d_inode->i_size;
4380 + if (ia->ia_valid & ATTR_SIZE)
4381 + size = ia->ia_size;
4382 + err = copyup_dentry(dentry->d_parent->d_inode,
4383 + dentry, bstart, i, NULL,
4384 + size);
4385 +
4386 + if (!err) {
4387 + copyup = 1;
4388 + hidden_dentry = unionfs_lower_dentry(dentry);
4389 + break;
4390 + }
4391 + /* if error is in the leftmost branch, pass it up */
4392 + if (i == 0)
4393 + goto out;
4394 + }
4395 +
4396 + }
4397 + err = notify_change(hidden_dentry, ia);
4398 + if (err)
4399 + goto out;
4400 + break;
4401 + }
4402 +
4403 + /* get the size from the first hidden inode */
4404 + hidden_inode = unionfs_lower_inode(dentry->d_inode);
4405 + fsstack_copy_attr_all(inode, hidden_inode, unionfs_get_nlinks);
4406 + fsstack_copy_inode_size(inode, hidden_inode);
4407 +
4408 +out:
4409 + unionfs_unlock_dentry(dentry);
4410 + return err;
4411 +}
4412 +
4413 +struct inode_operations unionfs_symlink_iops = {
4414 + .readlink = unionfs_readlink,
4415 + .permission = unionfs_permission,
4416 + .follow_link = unionfs_follow_link,
4417 + .setattr = unionfs_setattr,
4418 + .put_link = unionfs_put_link,
4419 +};
4420 +
4421 +struct inode_operations unionfs_dir_iops = {
4422 + .create = unionfs_create,
4423 + .lookup = unionfs_lookup,
4424 + .link = unionfs_link,
4425 + .unlink = unionfs_unlink,
4426 + .symlink = unionfs_symlink,
4427 + .mkdir = unionfs_mkdir,
4428 + .rmdir = unionfs_rmdir,
4429 + .mknod = unionfs_mknod,
4430 + .rename = unionfs_rename,
4431 + .permission = unionfs_permission,
4432 + .setattr = unionfs_setattr,
4433 +#ifdef CONFIG_UNION_FS_XATTR
4434 + .setxattr = unionfs_setxattr,
4435 + .getxattr = unionfs_getxattr,
4436 + .removexattr = unionfs_removexattr,
4437 + .listxattr = unionfs_listxattr,
4438 +#endif
4439 +};
4440 +
4441 +struct inode_operations unionfs_main_iops = {
4442 + .permission = unionfs_permission,
4443 + .setattr = unionfs_setattr,
4444 +#ifdef CONFIG_UNION_FS_XATTR
4445 + .setxattr = unionfs_setxattr,
4446 + .getxattr = unionfs_getxattr,
4447 + .removexattr = unionfs_removexattr,
4448 + .listxattr = unionfs_listxattr,
4449 +#endif
4450 +};
4451 +
4452 diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
4453 new file mode 100644
4454 index 0000000..0fc5993
4455 --- /dev/null
4456 +++ b/fs/unionfs/lookup.c
4457 @@ -0,0 +1,523 @@
4458 +/*
4459 + * Copyright (c) 2003-2007 Erez Zadok
4460 + * Copyright (c) 2003-2006 Charles P. Wright
4461 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
4462 + * Copyright (c) 2005-2006 Junjiro Okajima
4463 + * Copyright (c) 2005 Arun M. Krishnakumar
4464 + * Copyright (c) 2004-2006 David P. Quigley
4465 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
4466 + * Copyright (c) 2003 Puja Gupta
4467 + * Copyright (c) 2003 Harikesavan Krishnan
4468 + * Copyright (c) 2003-2007 Stony Brook University
4469 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
4470 + *
4471 + * This program is free software; you can redistribute it and/or modify
4472 + * it under the terms of the GNU General Public License version 2 as
4473 + * published by the Free Software Foundation.
4474 + */
4475 +
4476 +#include "union.h"
4477 +
4478 +/* is the filename valid == !(whiteout for a file or opaque dir marker) */
4479 +static int is_validname(const char *name)
4480 +{
4481 + if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN))
4482 + return 0;
4483 + if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME,
4484 + sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1))
4485 + return 0;
4486 + return 1;
4487 +}
4488 +
4489 +/* The rest of these are utility functions for lookup. */
4490 +static noinline int is_opaque_dir(struct dentry *dentry, int bindex)
4491 +{
4492 + int err = 0;
4493 + struct dentry *hidden_dentry;
4494 + struct dentry *wh_hidden_dentry;
4495 + struct inode *hidden_inode;
4496 + struct sioq_args args;
4497 +
4498 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4499 + hidden_inode = hidden_dentry->d_inode;
4500 +
4501 + BUG_ON(!S_ISDIR(hidden_inode->i_mode));
4502 +
4503 + mutex_lock(&hidden_inode->i_mutex);
4504 +
4505 + if (!permission(hidden_inode, MAY_EXEC, NULL))
4506 + wh_hidden_dentry = lookup_one_len(UNIONFS_DIR_OPAQUE, hidden_dentry,
4507 + sizeof(UNIONFS_DIR_OPAQUE) - 1);
4508 + else {
4509 + args.is_opaque.dentry = hidden_dentry;
4510 + run_sioq(__is_opaque_dir, &args);
4511 + wh_hidden_dentry = args.ret;
4512 + }
4513 +
4514 + mutex_unlock(&hidden_inode->i_mutex);
4515 +
4516 + if (IS_ERR(wh_hidden_dentry)) {
4517 + err = PTR_ERR(wh_hidden_dentry);
4518 + goto out;
4519 + }
4520 +
4521 + /* This is an opaque dir iff wh_hidden_dentry is positive */
4522 + err = !!wh_hidden_dentry->d_inode;
4523 +
4524 + dput(wh_hidden_dentry);
4525 +out:
4526 + return err;
4527 +}
4528 +
4529 +struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *nd,
4530 + int lookupmode)
4531 +{
4532 + int err = 0;
4533 + struct dentry *hidden_dentry = NULL;
4534 + struct dentry *wh_hidden_dentry = NULL;
4535 + struct dentry *hidden_dir_dentry = NULL;
4536 + struct dentry *parent_dentry = NULL;
4537 + int bindex, bstart, bend, bopaque;
4538 + int dentry_count = 0; /* Number of positive dentries. */
4539 + int first_dentry_offset = -1; /* -1 is uninitialized */
4540 + struct dentry *first_dentry = NULL;
4541 + struct dentry *first_hidden_dentry = NULL;
4542 + struct vfsmount *first_hidden_mnt = NULL;
4543 + int locked_parent = 0;
4544 + int locked_child = 0;
4545 + int allocated_new_info = 0;
4546 +
4547 + int opaque;
4548 + char *whname = NULL;
4549 + const char *name;
4550 + int namelen;
4551 +
4552 + /* We should already have a lock on this dentry in the case of a
4553 + * partial lookup, or a revalidation. Otherwise it is returned from
4554 + * new_dentry_private_data already locked.
4555 + */
4556 + if (lookupmode == INTERPOSE_PARTIAL || lookupmode == INTERPOSE_REVAL ||
4557 + lookupmode == INTERPOSE_REVAL_NEG)
4558 + verify_locked(dentry);
4559 + else {
4560 + BUG_ON(UNIONFS_D(dentry) != NULL);
4561 + locked_child = 1;
4562 + }
4563 + if (lookupmode != INTERPOSE_PARTIAL) {
4564 + if ((err = new_dentry_private_data(dentry)))
4565 + goto out;
4566 + allocated_new_info = 1;
4567 + }
4568 + /* must initialize dentry operations */
4569 + dentry->d_op = &unionfs_dops;
4570 +
4571 + parent_dentry = dget_parent(dentry);
4572 + /* We never partial lookup the root directory. */
4573 + if (parent_dentry != dentry) {
4574 + unionfs_lock_dentry(parent_dentry);
4575 + locked_parent = 1;
4576 + } else {
4577 + dput(parent_dentry);
4578 + parent_dentry = NULL;
4579 + goto out;
4580 + }
4581 +
4582 + name = dentry->d_name.name;
4583 + namelen = dentry->d_name.len;
4584 +
4585 + /* No dentries should get created for possible whiteout names. */
4586 + if (!is_validname(name)) {
4587 + err = -EPERM;
4588 + goto out_free;
4589 + }
4590 +
4591 + /* Now start the actual lookup procedure. */
4592 + bstart = dbstart(parent_dentry);
4593 + bend = dbend(parent_dentry);
4594 + bopaque = dbopaque(parent_dentry);
4595 + BUG_ON(bstart < 0);
4596 +
4597 + /* It would be ideal if we could convert partial lookups to only have
4598 + * to do this work when they really need to. It could probably improve
4599 + * performance quite a bit, and maybe simplify the rest of the code.
4600 + */
4601 + if (lookupmode == INTERPOSE_PARTIAL) {
4602 + bstart++;
4603 + if ((bopaque != -1) && (bopaque < bend))
4604 + bend = bopaque;
4605 + }
4606 +
4607 + for (bindex = bstart; bindex <= bend; bindex++) {
4608 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4609 + if (lookupmode == INTERPOSE_PARTIAL && hidden_dentry)
4610 + continue;
4611 + BUG_ON(hidden_dentry != NULL);
4612 +
4613 + hidden_dir_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
4614 +
4615 + /* if the parent hidden dentry does not exist skip this */
4616 + if (!(hidden_dir_dentry && hidden_dir_dentry->d_inode))
4617 + continue;
4618 +
4619 + /* also skip it if the parent isn't a directory. */
4620 + if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode))
4621 + continue;
4622 +
4623 + /* Reuse the whiteout name because its value doesn't change. */
4624 + if (!whname) {
4625 + whname = alloc_whname(name, namelen);
4626 + if (IS_ERR(whname)) {
4627 + err = PTR_ERR(whname);
4628 + goto out_free;
4629 + }
4630 + }
4631 +
4632 + /* check if whiteout exists in this branch: lookup .wh.foo */
4633 + wh_hidden_dentry = lookup_one_len(whname, hidden_dir_dentry,
4634 + namelen + UNIONFS_WHLEN);
4635 + if (IS_ERR(wh_hidden_dentry)) {
4636 + dput(first_hidden_dentry);
4637 + unionfs_mntput(first_dentry, first_dentry_offset);
4638 + err = PTR_ERR(wh_hidden_dentry);
4639 + goto out_free;
4640 + }
4641 +
4642 + if (wh_hidden_dentry->d_inode) {
4643 + /* We found a whiteout so lets give up. */
4644 + if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) {
4645 + set_dbend(dentry, bindex);
4646 + set_dbopaque(dentry, bindex);
4647 + dput(wh_hidden_dentry);
4648 + break;
4649 + }
4650 + err = -EIO;
4651 + printk(KERN_NOTICE "EIO: Invalid whiteout entry type"
4652 + " %d.\n", wh_hidden_dentry->d_inode->i_mode);
4653 + dput(wh_hidden_dentry);
4654 + dput(first_hidden_dentry);
4655 + unionfs_mntput(first_dentry, first_dentry_offset);
4656 + goto out_free;
4657 + }
4658 +
4659 + dput(wh_hidden_dentry);
4660 + wh_hidden_dentry = NULL;
4661 +
4662 + /* Now do regular lookup; lookup foo */
4663 + nd->dentry = unionfs_lower_dentry_idx(dentry, bindex);
4664 + /* FIXME: fix following line for mount point crossing */
4665 + nd->mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
4666 +
4667 + hidden_dentry = lookup_one_len_nd(name, hidden_dir_dentry,
4668 + namelen, nd);
4669 + if (IS_ERR(hidden_dentry)) {
4670 + dput(first_hidden_dentry);
4671 + unionfs_mntput(first_dentry, first_dentry_offset);
4672 + err = PTR_ERR(hidden_dentry);
4673 + goto out_free;
4674 + }
4675 +
4676 + /* Store the first negative dentry specially, because if they
4677 + * are all negative we need this for future creates.
4678 + */
4679 + if (!hidden_dentry->d_inode) {
4680 + if (!first_hidden_dentry && (dbstart(dentry) == -1)) {
4681 + first_hidden_dentry = hidden_dentry;
4682 + /* FIXME: following line needs to be changed
4683 + * to allow mountpoint crossing
4684 + */
4685 + first_dentry = parent_dentry;
4686 + first_hidden_mnt = unionfs_mntget(parent_dentry, bindex);
4687 + first_dentry_offset = bindex;
4688 + } else
4689 + dput(hidden_dentry);
4690 +
4691 + continue;
4692 + }
4693 +
4694 + /* number of positive dentries */
4695 + dentry_count++;
4696 +
4697 + /* store underlying dentry */
4698 + if (dbstart(dentry) == -1)
4699 + set_dbstart(dentry, bindex);
4700 + unionfs_set_lower_dentry_idx(dentry, bindex, hidden_dentry);
4701 + /* FIXME: the following line needs to get fixed to allow
4702 + * mountpoint crossing
4703 + */
4704 + unionfs_set_lower_mnt_idx(dentry, bindex,
4705 + unionfs_mntget(parent_dentry, bindex));
4706 + set_dbend(dentry, bindex);
4707 +
4708 + /* update parent directory's atime with the bindex */
4709 + fsstack_copy_attr_atime(parent_dentry->d_inode,
4710 + hidden_dir_dentry->d_inode);
4711 +
4712 + /* We terminate file lookups here. */
4713 + if (!S_ISDIR(hidden_dentry->d_inode->i_mode)) {
4714 + if (lookupmode == INTERPOSE_PARTIAL)
4715 + continue;
4716 + if (dentry_count == 1)
4717 + goto out_positive;
4718 + /* This can only happen with mixed D-*-F-* */
4719 + BUG_ON(!S_ISDIR(unionfs_lower_dentry(dentry)->d_inode->i_mode));
4720 + continue;
4721 + }
4722 +
4723 + opaque = is_opaque_dir(dentry, bindex);
4724 + if (opaque < 0) {
4725 + dput(first_hidden_dentry);
4726 + unionfs_mntput(first_dentry, first_dentry_offset);
4727 + err = opaque;
4728 + goto out_free;
4729 + } else if (opaque) {
4730 + set_dbend(dentry, bindex);
4731 + set_dbopaque(dentry, bindex);
4732 + break;
4733 + }
4734 + }
4735 +
4736 + if (dentry_count)
4737 + goto out_positive;
4738 + else
4739 + goto out_negative;
4740 +
4741 +out_negative:
4742 + if (lookupmode == INTERPOSE_PARTIAL)
4743 + goto out;
4744 +
4745 + /* If we've only got negative dentries, then use the leftmost one. */
4746 + if (lookupmode == INTERPOSE_REVAL) {
4747 + if (dentry->d_inode)
4748 + UNIONFS_I(dentry->d_inode)->stale = 1;
4749 +
4750 + goto out;
4751 + }
4752 + /* This should only happen if we found a whiteout. */
4753 + if (first_dentry_offset == -1) {
4754 + nd->dentry = dentry;
4755 + /* FIXME: fix following line for mount point crossing */
4756 + nd->mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
4757 +
4758 + first_hidden_dentry = lookup_one_len_nd(name, hidden_dir_dentry,
4759 + namelen, nd);
4760 + first_dentry_offset = bindex;
4761 + if (IS_ERR(first_hidden_dentry)) {
4762 + err = PTR_ERR(first_hidden_dentry);
4763 + goto out;
4764 + }
4765 +
4766 + /* FIXME: the following line needs to be changed to allow
4767 + * mountpoint crossing
4768 + */
4769 + first_dentry = dentry;
4770 + first_hidden_mnt = unionfs_mntget(dentry, bindex);
4771 + }
4772 + unionfs_set_lower_dentry_idx(dentry, first_dentry_offset, first_hidden_dentry);
4773 + unionfs_set_lower_mnt_idx(dentry, first_dentry_offset, first_hidden_mnt);
4774 + set_dbstart(dentry, first_dentry_offset);
4775 + set_dbend(dentry, first_dentry_offset);
4776 +
4777 + if (lookupmode == INTERPOSE_REVAL_NEG)
4778 + BUG_ON(dentry->d_inode != NULL);
4779 + else
4780 + d_add(dentry, NULL);
4781 + goto out;
4782 +
4783 +/* This part of the code is for positive dentries. */
4784 +out_positive:
4785 + BUG_ON(dentry_count <= 0);
4786 +
4787 + /* If we're holding onto the first negative dentry & corresponding
4788 + * vfsmount - throw it out.
4789 + */
4790 + dput(first_hidden_dentry);
4791 + unionfs_mntput(first_dentry, first_dentry_offset);
4792 +
4793 + /* Partial lookups need to reinterpose, or throw away older negs. */
4794 + if (lookupmode == INTERPOSE_PARTIAL) {
4795 + if (dentry->d_inode) {
4796 + unionfs_reinterpose(dentry);
4797 + goto out;
4798 + }
4799 +
4800 + /* This somehow turned positive, so it is as if we had a
4801 + * negative revalidation.
4802 + */
4803 + lookupmode = INTERPOSE_REVAL_NEG;
4804 +
4805 + update_bstart(dentry);
4806 + bstart = dbstart(dentry);
4807 + bend = dbend(dentry);
4808 + }
4809 +
4810 + err = unionfs_interpose(dentry, dentry->d_sb, lookupmode);
4811 + if (err)
4812 + goto out_drop;
4813 +
4814 + goto out;
4815 +
4816 +out_drop:
4817 + d_drop(dentry);
4818 +
4819 +out_free:
4820 + /* should dput all the underlying dentries on error condition */
4821 + bstart = dbstart(dentry);
4822 + if (bstart >= 0) {
4823 + bend = dbend(dentry);
4824 + for (bindex = bstart; bindex <= bend; bindex++) {
4825 + dput(unionfs_lower_dentry_idx(dentry, bindex));
4826 + unionfs_mntput(dentry, bindex);
4827 + }
4828 + }
4829 + kfree(UNIONFS_D(dentry)->lower_paths);
4830 + UNIONFS_D(dentry)->lower_paths = NULL;
4831 + set_dbstart(dentry, -1);
4832 + set_dbend(dentry, -1);
4833 +
4834 +out:
4835 + if (!err && UNIONFS_D(dentry)) {
4836 + BUG_ON(dbend(dentry) > UNIONFS_D(dentry)->bcount);
4837 + BUG_ON(dbend(dentry) > sbmax(dentry->d_sb));
4838 + BUG_ON(dbstart(dentry) < 0);
4839 + }
4840 + kfree(whname);
4841 + if (locked_parent)
4842 + unionfs_unlock_dentry(parent_dentry);
4843 + dput(parent_dentry);
4844 + if (locked_child || (err && allocated_new_info))
4845 + unionfs_unlock_dentry(dentry);
4846 + return ERR_PTR(err);
4847 +}
4848 +
4849 +/* This is a utility function that fills in a unionfs dentry.*/
4850 +int unionfs_partial_lookup(struct dentry *dentry)
4851 +{
4852 + struct dentry *tmp;
4853 + struct nameidata nd = { .flags = 0 };
4854 +
4855 + tmp = unionfs_lookup_backend(dentry, &nd, INTERPOSE_PARTIAL);
4856 + if (!tmp)
4857 + return 0;
4858 + if (IS_ERR(tmp))
4859 + return PTR_ERR(tmp);
4860 + /* need to change the interface */
4861 + BUG_ON(tmp != dentry);
4862 + return -ENOSYS;
4863 +}
4864 +
4865 +/* The dentry cache is just so we have properly sized dentries. */
4866 +static struct kmem_cache *unionfs_dentry_cachep;
4867 +int unionfs_init_dentry_cache(void)
4868 +{
4869 + unionfs_dentry_cachep = kmem_cache_create("unionfs_dentry",
4870 + sizeof(struct unionfs_dentry_info), 0,
4871 + SLAB_RECLAIM_ACCOUNT, NULL, NULL);
4872 +
4873 + return (unionfs_dentry_cachep ? 0 : -ENOMEM);
4874 +}
4875 +
4876 +void unionfs_destroy_dentry_cache(void)
4877 +{
4878 + if (unionfs_dentry_cachep)
4879 + kmem_cache_destroy(unionfs_dentry_cachep);
4880 +}
4881 +
4882 +void free_dentry_private_data(struct unionfs_dentry_info *udi)
4883 +{
4884 + if (!udi)
4885 + return;
4886 + kmem_cache_free(unionfs_dentry_cachep, udi);
4887 +}
4888 +
4889 +/* allocate new dentry private data, free old one if necessary */
4890 +int new_dentry_private_data(struct dentry *dentry)
4891 +{
4892 + int newsize;
4893 + int oldsize = 0;
4894 + struct unionfs_dentry_info *info = UNIONFS_D(dentry);
4895 + int unlock_on_err = 0;
4896 +
4897 + spin_lock(&dentry->d_lock);
4898 + if (!info) {
4899 + dentry->d_fsdata = kmem_cache_alloc(unionfs_dentry_cachep,
4900 + GFP_ATOMIC);
4901 + info = UNIONFS_D(dentry);
4902 +
4903 + if (!info)
4904 + goto out;
4905 +
4906 + mutex_init(&info->lock);
4907 + mutex_lock(&info->lock);
4908 + unlock_on_err = 1;
4909 +
4910 + info->lower_paths = NULL;
4911 + } else
4912 + oldsize = sizeof(struct path) * info->bcount;
4913 +
4914 + info->bstart = -1;
4915 + info->bend = -1;
4916 + info->bopaque = -1;
4917 + info->bcount = sbmax(dentry->d_sb);
4918 + atomic_set(&info->generation,
4919 + atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
4920 + newsize = sizeof(struct path) * sbmax(dentry->d_sb);
4921 +
4922 + /* Don't reallocate when we already have enough space. */
4923 + /* It would be ideal if we could actually use the slab macros to
4924 + * determine what our object sizes is, but those are not exported.
4925 + */
4926 + if (oldsize) {
4927 + int minsize = malloc_sizes[0].cs_size;
4928 +
4929 + if (!newsize || ((oldsize < newsize) && (newsize > minsize))) {
4930 + kfree(info->lower_paths);
4931 + info->lower_paths = NULL;
4932 + }
4933 + }
4934 +
4935 + if (!info->lower_paths && newsize) {
4936 + info->lower_paths = kmalloc(newsize, GFP_ATOMIC);
4937 + if (!info->lower_paths)
4938 + goto out_free;
4939 + }
4940 +
4941 + memset(info->lower_paths, 0, (oldsize > newsize ? oldsize : newsize));
4942 +
4943 + spin_unlock(&dentry->d_lock);
4944 + return 0;
4945 +
4946 +out_free:
4947 + kfree(info->lower_paths);
4948 + if (unlock_on_err)
4949 + mutex_unlock(&info->lock);
4950 +
4951 +out:
4952 + free_dentry_private_data(info);
4953 + dentry->d_fsdata = NULL;
4954 + spin_unlock(&dentry->d_lock);
4955 + return -ENOMEM;
4956 +}
4957 +
4958 +/* scan through the lower dentry objects, and set bstart to reflect the
4959 + * starting branch
4960 + */
4961 +void update_bstart(struct dentry *dentry)
4962 +{
4963 + int bindex;
4964 + int bstart = dbstart(dentry);
4965 + int bend = dbend(dentry);
4966 + struct dentry *hidden_dentry;
4967 +
4968 + for (bindex = bstart; bindex <= bend; bindex++) {
4969 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4970 + if (!hidden_dentry)
4971 + continue;
4972 + if (hidden_dentry->d_inode) {
4973 + set_dbstart(dentry, bindex);
4974 + break;
4975 + }
4976 + dput(hidden_dentry);
4977 + unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
4978 + }
4979 +}
4980 +
4981 diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
4982 new file mode 100644
4983 index 0000000..4fffafa
4984 --- /dev/null
4985 +++ b/fs/unionfs/main.c
4986 @@ -0,0 +1,703 @@
4987 +/*
4988 + * Copyright (c) 2003-2007 Erez Zadok
4989 + * Copyright (c) 2003-2006 Charles P. Wright
4990 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
4991 + * Copyright (c) 2005-2006 Junjiro Okajima
4992 + * Copyright (c) 2005 Arun M. Krishnakumar
4993 + * Copyright (c) 2004-2006 David P. Quigley
4994 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
4995 + * Copyright (c) 2003 Puja Gupta
4996 + * Copyright (c) 2003 Harikesavan Krishnan
4997 + * Copyright (c) 2003-2007 Stony Brook University
4998 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
4999 + *
5000 + * This program is free software; you can redistribute it and/or modify
5001 + * it under the terms of the GNU General Public License version 2 as
5002 + * published by the Free Software Foundation.
5003 + */
5004 +
5005 +#include "union.h"
5006 +#include <linux/module.h>
5007 +#include <linux/moduleparam.h>
5008 +
5009 +/* sb we pass is unionfs's super_block */
5010 +int unionfs_interpose(struct dentry *dentry, struct super_block *sb, int flag)
5011 +{
5012 + struct inode *hidden_inode;
5013 + struct dentry *hidden_dentry;
5014 + int err = 0;
5015 + struct inode *inode;
5016 + int is_negative_dentry = 1;
5017 + int bindex, bstart, bend;
5018 +
5019 + verify_locked(dentry);
5020 +
5021 + bstart = dbstart(dentry);
5022 + bend = dbend(dentry);
5023 +
5024 + /* Make sure that we didn't get a negative dentry. */
5025 + for (bindex = bstart; bindex <= bend; bindex++) {
5026 + if (unionfs_lower_dentry_idx(dentry, bindex) &&
5027 + unionfs_lower_dentry_idx(dentry, bindex)->d_inode) {
5028 + is_negative_dentry = 0;
5029 + break;
5030 + }
5031 + }
5032 + BUG_ON(is_negative_dentry);
5033 +
5034 + /* We allocate our new inode below, by calling iget.
5035 + * iget will call our read_inode which will initialize some
5036 + * of the new inode's fields
5037 + */
5038 +
5039 + /* On revalidate we've already got our own inode and just need
5040 + * to fix it up.
5041 + */
5042 + if (flag == INTERPOSE_REVAL) {
5043 + inode = dentry->d_inode;
5044 + UNIONFS_I(inode)->bstart = -1;
5045 + UNIONFS_I(inode)->bend = -1;
5046 + atomic_set(&UNIONFS_I(inode)->generation,
5047 + atomic_read(&UNIONFS_SB(sb)->generation));
5048 +
5049 + UNIONFS_I(inode)->lower_inodes =
5050 + kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL);
5051 + if (!UNIONFS_I(inode)->lower_inodes) {
5052 + err = -ENOMEM;
5053 + goto out;
5054 + }
5055 + } else {
5056 + /* get unique inode number for unionfs */
5057 + inode = iget(sb, iunique(sb, UNIONFS_ROOT_INO));
5058 + if (!inode) {
5059 + err = -EACCES;
5060 + goto out;
5061 + }
5062 +
5063 + if (atomic_read(&inode->i_count) > 1)
5064 + goto skip;
5065 + }
5066 +
5067 + for (bindex = bstart; bindex <= bend; bindex++) {
5068 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
5069 + if (!hidden_dentry) {
5070 + unionfs_set_lower_inode_idx(inode, bindex, NULL);
5071 + continue;
5072 + }
5073 +
5074 + /* Initialize the hidden inode to the new hidden inode. */
5075 + if (!hidden_dentry->d_inode)
5076 + continue;
5077 +
5078 + unionfs_set_lower_inode_idx(inode, bindex,
5079 + igrab(hidden_dentry->d_inode));
5080 + }
5081 +
5082 + ibstart(inode) = dbstart(dentry);
5083 + ibend(inode) = dbend(dentry);
5084 +
5085 + /* Use attributes from the first branch. */
5086 + hidden_inode = unionfs_lower_inode(inode);
5087 +
5088 + /* Use different set of inode ops for symlinks & directories */
5089 + if (S_ISLNK(hidden_inode->i_mode))
5090 + inode->i_op = &unionfs_symlink_iops;
5091 + else if (S_ISDIR(hidden_inode->i_mode))
5092 + inode->i_op = &unionfs_dir_iops;
5093 +
5094 + /* Use different set of file ops for directories */
5095 + if (S_ISDIR(hidden_inode->i_mode))
5096 + inode->i_fop = &unionfs_dir_fops;
5097 +
5098 + /* properly initialize special inodes */
5099 + if (S_ISBLK(hidden_inode->i_mode) || S_ISCHR(hidden_inode->i_mode) ||
5100 + S_ISFIFO(hidden_inode->i_mode) || S_ISSOCK(hidden_inode->i_mode))
5101 + init_special_inode(inode, hidden_inode->i_mode,
5102 + hidden_inode->i_rdev);
5103 + /* Fix our inode's address operations to that of the lower inode
5104 + * (Unionfs is FiST-Lite)
5105 + */
5106 + if (inode->i_mapping->a_ops != hidden_inode->i_mapping->a_ops)
5107 + inode->i_mapping->a_ops = hidden_inode->i_mapping->a_ops;
5108 +
5109 + /* all well, copy inode attributes */
5110 + fsstack_copy_attr_all(inode, hidden_inode, unionfs_get_nlinks);
5111 + fsstack_copy_inode_size(inode, hidden_inode);
5112 +
5113 +skip:
5114 + /* only (our) lookup wants to do a d_add */
5115 + switch (flag) {
5116 + case INTERPOSE_DEFAULT:
5117 + case INTERPOSE_REVAL_NEG:
5118 + d_instantiate(dentry, inode);
5119 + break;
5120 + case INTERPOSE_LOOKUP:
5121 + err = PTR_ERR(d_splice_alias(inode, dentry));
5122 + break;
5123 + case INTERPOSE_REVAL:
5124 + /* Do nothing. */
5125 + break;
5126 + default:
5127 + printk(KERN_ERR "Invalid interpose flag passed!");
5128 + BUG();
5129 + }
5130 +
5131 +out:
5132 + return err;
5133 +}
5134 +
5135 +void unionfs_reinterpose(struct dentry *dentry)
5136 +{
5137 + struct dentry *hidden_dentry;
5138 + struct inode *inode;
5139 + int bindex, bstart, bend;
5140 +
5141 + verify_locked(dentry);
5142 +
5143 + /* This is pre-allocated inode */
5144 + inode = dentry->d_inode;
5145 +
5146 + bstart = dbstart(dentry);
5147 + bend = dbend(dentry);
5148 + for (bindex = bstart; bindex <= bend; bindex++) {
5149 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
5150 + if (!hidden_dentry)
5151 + continue;
5152 +
5153 + if (!hidden_dentry->d_inode)
5154 + continue;
5155 + if (unionfs_lower_inode_idx(inode, bindex))
5156 + continue;
5157 + unionfs_set_lower_inode_idx(inode, bindex,
5158 + igrab(hidden_dentry->d_inode));
5159 + }
5160 + ibstart(inode) = dbstart(dentry);
5161 + ibend(inode) = dbend(dentry);
5162 +}
5163 +
5164 +/* make sure the branch we just looked up (nd) makes sense:
5165 + *
5166 + * 1) we're not trying to stack unionfs on top of unionfs
5167 + * 2) it exists
5168 + * 3) is a directory
5169 + */
5170 +int check_branch(struct nameidata *nd)
5171 +{
5172 + if (!strcmp(nd->dentry->d_sb->s_type->name, "unionfs"))
5173 + return -EINVAL;
5174 + if (!nd->dentry->d_inode)
5175 + return -ENOENT;
5176 + if (!S_ISDIR(nd->dentry->d_inode->i_mode))
5177 + return -ENOTDIR;
5178 + return 0;
5179 +}
5180 +
5181 +/* checks if two hidden_dentries have overlapping branches */
5182 +static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2)
5183 +{
5184 + struct dentry *dent = NULL;
5185 +
5186 + dent = dent1;
5187 + while ((dent != dent2) && (dent->d_parent != dent))
5188 + dent = dent->d_parent;
5189 +
5190 + if (dent == dent2)
5191 + return 1;
5192 +
5193 + dent = dent2;
5194 + while ((dent != dent1) && (dent->d_parent != dent))
5195 + dent = dent->d_parent;
5196 +
5197 + return (dent == dent1);
5198 +}
5199 +
5200 +/*
5201 + * Parse branch mode helper function
5202 + */
5203 +int __parse_branch_mode(const char *name)
5204 +{
5205 + if (!name)
5206 + return 0;
5207 + if (!strcmp(name, "ro"))
5208 + return MAY_READ;
5209 + if (!strcmp(name, "rw"))
5210 + return (MAY_READ | MAY_WRITE);
5211 + return 0;
5212 +}
5213 +
5214 +/*
5215 + * Parse "ro" or "rw" options, but default to "rw" of no mode options
5216 + * was specified.
5217 + */
5218 +int parse_branch_mode(const char *name)
5219 +{
5220 + int perms = __parse_branch_mode(name);
5221 + if (perms == 0)
5222 + perms = MAY_READ | MAY_WRITE;
5223 + return perms;
5224 +}
5225 +
5226 +/* parse the dirs= mount argument */
5227 +static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
5228 + *hidden_root_info, char *options)
5229 +{
5230 + struct nameidata nd;
5231 + char *name;
5232 + int err = 0;
5233 + int branches = 1;
5234 + int bindex = 0;
5235 + int i = 0;
5236 + int j = 0;
5237 +
5238 + struct dentry *dent1;
5239 + struct dentry *dent2;
5240 +
5241 + if (options[0] == '\0') {
5242 + printk(KERN_WARNING "unionfs: no branches specified\n");
5243 + err = -EINVAL;
5244 + goto out;
5245 + }
5246 +
5247 + /* Each colon means we have a separator, this is really just a rough
5248 + * guess, since strsep will handle empty fields for us.
5249 + */
5250 + for (i = 0; options[i]; i++)
5251 + if (options[i] == ':')
5252 + branches++;
5253 +
5254 + /* allocate space for underlying pointers to hidden dentry */
5255 + UNIONFS_SB(sb)->data = kcalloc(branches,
5256 + sizeof(struct unionfs_data), GFP_KERNEL);
5257 + if (!UNIONFS_SB(sb)->data) {
5258 + err = -ENOMEM;
5259 + goto out;
5260 + }
5261 +
5262 + hidden_root_info->lower_paths = kcalloc(branches,
5263 + sizeof(struct path), GFP_KERNEL);
5264 + if (!hidden_root_info->lower_paths) {
5265 + err = -ENOMEM;
5266 + goto out;
5267 + }
5268 +
5269 + /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
5270 + branches = 0;
5271 + while ((name = strsep(&options, ":")) != NULL) {
5272 + int perms;
5273 + char *mode = strchr(name, '=');
5274 +
5275 + if (!name || !*name)
5276 + continue;
5277 +
5278 + branches++;
5279 +
5280 + /* strip off '=' if any */
5281 + if (mode)
5282 + *mode++ = '\0';
5283 +
5284 + perms = parse_branch_mode(mode);
5285 + if (!bindex && !(perms & MAY_WRITE)) {
5286 + err = -EINVAL;
5287 + goto out;
5288 + }
5289 +
5290 + err = path_lookup(name, LOOKUP_FOLLOW, &nd);
5291 + if (err) {
5292 + printk(KERN_WARNING "unionfs: error accessing "
5293 + "hidden directory '%s' (error %d)\n", name, err);
5294 + goto out;
5295 + }
5296 +
5297 + if ((err = check_branch(&nd))) {
5298 + printk(KERN_WARNING "unionfs: hidden directory "
5299 + "'%s' is not a valid branch\n", name);
5300 + path_release(&nd);
5301 + goto out;
5302 + }
5303 +
5304 + hidden_root_info->lower_paths[bindex].dentry = nd.dentry;
5305 + hidden_root_info->lower_paths[bindex].mnt = nd.mnt;
5306 +
5307 + unionfs_write_lock(sb);
5308 + set_branchperms(sb, bindex, perms);
5309 + set_branch_count(sb, bindex, 0);
5310 + new_branch_id(sb, bindex);
5311 + unionfs_write_unlock(sb);
5312 +
5313 + if (hidden_root_info->bstart < 0)
5314 + hidden_root_info->bstart = bindex;
5315 + hidden_root_info->bend = bindex;
5316 + bindex++;
5317 + }
5318 +
5319 + if (branches == 0) {
5320 + printk(KERN_WARNING "unionfs: no branches specified\n");
5321 + err = -EINVAL;
5322 + goto out;
5323 + }
5324 +
5325 + BUG_ON(branches != (hidden_root_info->bend + 1));
5326 +
5327 + /* ensure that no overlaps exist in the branches */
5328 + for (i = 0; i < branches; i++) {
5329 + for (j = i + 1; j < branches; j++) {
5330 + dent1 = hidden_root_info->lower_paths[i].dentry;
5331 + dent2 = hidden_root_info->lower_paths[j].dentry;
5332 +
5333 + if (is_branch_overlap(dent1, dent2)) {
5334 + printk(KERN_WARNING "unionfs: branches %d and "
5335 + "%d overlap\n", i, j);
5336 + err = -EINVAL;
5337 + goto out;
5338 + }
5339 + }
5340 + }
5341 +
5342 +out:
5343 + if (err) {
5344 + for (i = 0; i < branches; i++)
5345 + if (hidden_root_info->lower_paths[i].dentry) {
5346 + dput(hidden_root_info->lower_paths[i].dentry);
5347 + /* initializing: can't use unionfs_mntput here */
5348 + mntput(hidden_root_info->lower_paths[i].mnt);
5349 + }
5350 +
5351 + kfree(hidden_root_info->lower_paths);
5352 + kfree(UNIONFS_SB(sb)->data);
5353 +
5354 + /* MUST clear the pointers to prevent potential double free if
5355 + * the caller dies later on
5356 + */
5357 + hidden_root_info->lower_paths = NULL;
5358 + UNIONFS_SB(sb)->data = NULL;
5359 + }
5360 + return err;
5361 +}
5362 +
5363 +/*
5364 + * Parse mount options. See the manual page for usage instructions.
5365 + *
5366 + * Returns the dentry object of the lower-level (hidden) directory;
5367 + * We want to mount our stackable file system on top of that hidden directory.
5368 + */
5369 +static struct unionfs_dentry_info *unionfs_parse_options(struct super_block *sb,
5370 + char *options)
5371 +{
5372 + struct unionfs_dentry_info *hidden_root_info;
5373 + char *optname;
5374 + int err = 0;
5375 + int bindex;
5376 + int dirsfound = 0;
5377 +
5378 + /* allocate private data area */
5379 + err = -ENOMEM;
5380 + hidden_root_info =
5381 + kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
5382 + if (!hidden_root_info)
5383 + goto out_error;
5384 + hidden_root_info->bstart = -1;
5385 + hidden_root_info->bend = -1;
5386 + hidden_root_info->bopaque = -1;
5387 +
5388 + while ((optname = strsep(&options, ",")) != NULL) {
5389 + char *optarg;
5390 + char *endptr;
5391 + int intval;
5392 +
5393 + if (!optname || !*optname)
5394 + continue;
5395 +
5396 + optarg = strchr(optname, '=');
5397 + if (optarg)
5398 + *optarg++ = '\0';
5399 +
5400 + /* All of our options take an argument now. Insert ones that
5401 + * don't, above this check.
5402 + */
5403 + if (!optarg) {
5404 + printk("unionfs: %s requires an argument.\n", optname);
5405 + err = -EINVAL;
5406 + goto out_error;
5407 + }
5408 +
5409 + if (!strcmp("dirs", optname)) {
5410 + if (++dirsfound > 1) {
5411 + printk(KERN_WARNING
5412 + "unionfs: multiple dirs specified\n");
5413 + err = -EINVAL;
5414 + goto out_error;
5415 + }
5416 + err = parse_dirs_option(sb, hidden_root_info, optarg);
5417 + if (err)
5418 + goto out_error;
5419 + continue;
5420 + }
5421 +
5422 + /* All of these options require an integer argument. */
5423 + intval = simple_strtoul(optarg, &endptr, 0);
5424 + if (*endptr) {
5425 + printk(KERN_WARNING
5426 + "unionfs: invalid %s option '%s'\n",
5427 + optname, optarg);
5428 + err = -EINVAL;
5429 + goto out_error;
5430 + }
5431 +
5432 + err = -EINVAL;
5433 + printk(KERN_WARNING
5434 + "unionfs: unrecognized option '%s'\n", optname);
5435 + goto out_error;
5436 + }
5437 + if (dirsfound != 1) {
5438 + printk(KERN_WARNING "unionfs: dirs option required\n");
5439 + err = -EINVAL;
5440 + goto out_error;
5441 + }
5442 + goto out;
5443 +
5444 +out_error:
5445 + if (hidden_root_info && hidden_root_info->lower_paths) {
5446 + for (bindex = hidden_root_info->bstart;
5447 + bindex >= 0 && bindex <= hidden_root_info->bend;
5448 + bindex++) {
5449 + struct dentry *d;
5450 + struct vfsmount *m;
5451 +
5452 + d = hidden_root_info->lower_paths[bindex].dentry;
5453 + m = hidden_root_info->lower_paths[bindex].mnt;
5454 +
5455 + dput(d);
5456 + /* initializing: can't use unionfs_mntput here */
5457 + mntput(m);
5458 + }
5459 + }
5460 +
5461 + kfree(hidden_root_info->lower_paths);
5462 + kfree(hidden_root_info);
5463 +
5464 + kfree(UNIONFS_SB(sb)->data);
5465 + UNIONFS_SB(sb)->data = NULL;
5466 +
5467 + hidden_root_info = ERR_PTR(err);
5468 +out:
5469 + return hidden_root_info;
5470 +}
5471 +
5472 +/* our custom d_alloc_root workalike
5473 + *
5474 + * we can't use d_alloc_root if we want to use our own interpose function
5475 + * unchanged, so we simply call our own "fake" d_alloc_root
5476 + */
5477 +static struct dentry *unionfs_d_alloc_root(struct super_block *sb)
5478 +{
5479 + struct dentry *ret = NULL;
5480 +
5481 + if (sb) {
5482 + static const struct qstr name = {.name = "/",.len = 1 };
5483 +
5484 + ret = d_alloc(NULL, &name);
5485 + if (ret) {
5486 + ret->d_op = &unionfs_dops;
5487 + ret->d_sb = sb;
5488 + ret->d_parent = ret;
5489 + }
5490 + }
5491 + return ret;
5492 +}
5493 +
5494 +static int unionfs_read_super(struct super_block *sb, void *raw_data,
5495 + int silent)
5496 +{
5497 + int err = 0;
5498 +
5499 + struct unionfs_dentry_info *hidden_root_info = NULL;
5500 + int bindex, bstart, bend;
5501 +
5502 + if (!raw_data) {
5503 + printk(KERN_WARNING
5504 + "unionfs_read_super: missing data argument\n");
5505 + err = -EINVAL;
5506 + goto out;
5507 + }
5508 +
5509 + /* Allocate superblock private data */
5510 + sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL);
5511 + if (!UNIONFS_SB(sb)) {
5512 + printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
5513 + err = -ENOMEM;
5514 + goto out;
5515 + }
5516 +
5517 + UNIONFS_SB(sb)->bend = -1;
5518 + atomic_set(&UNIONFS_SB(sb)->generation, 1);
5519 + init_rwsem(&UNIONFS_SB(sb)->rwsem);
5520 + UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
5521 +
5522 + hidden_root_info = unionfs_parse_options(sb, raw_data);
5523 + if (IS_ERR(hidden_root_info)) {
5524 + printk(KERN_WARNING
5525 + "unionfs_read_super: error while parsing options "
5526 + "(err = %ld)\n", PTR_ERR(hidden_root_info));
5527 + err = PTR_ERR(hidden_root_info);
5528 + hidden_root_info = NULL;
5529 + goto out_free;
5530 + }
5531 + if (hidden_root_info->bstart == -1) {
5532 + err = -ENOENT;
5533 + goto out_free;
5534 + }
5535 +
5536 + /* set the hidden superblock field of upper superblock */
5537 + bstart = hidden_root_info->bstart;
5538 + BUG_ON(bstart != 0);
5539 + sbend(sb) = bend = hidden_root_info->bend;
5540 + for (bindex = bstart; bindex <= bend; bindex++) {
5541 + struct dentry *d;
5542 +
5543 + d = hidden_root_info->lower_paths[bindex].dentry;
5544 +
5545 + unionfs_write_lock(sb);
5546 + unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
5547 + unionfs_write_unlock(sb);
5548 + }
5549 +
5550 + /* Unionfs: Max Bytes is the maximum bytes from highest priority branch */
5551 + unionfs_read_lock(sb);
5552 + sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
5553 + unionfs_read_unlock(sb);
5554 +
5555 + sb->s_op = &unionfs_sops;
5556 +
5557 + /* See comment next to the definition of unionfs_d_alloc_root */
5558 + sb->s_root = unionfs_d_alloc_root(sb);
5559 + if (!sb->s_root) {
5560 + err = -ENOMEM;
5561 + goto out_dput;
5562 + }
5563 +
5564 + /* link the upper and lower dentries */
5565 + sb->s_root->d_fsdata = NULL;
5566 + if ((err = new_dentry_private_data(sb->s_root)))
5567 + goto out_freedpd;
5568 +
5569 + /* Set the hidden dentries for s_root */
5570 + for (bindex = bstart; bindex <= bend; bindex++) {
5571 + struct dentry *d;
5572 + struct vfsmount *m;
5573 +
5574 + d = hidden_root_info->lower_paths[bindex].dentry;
5575 + m = hidden_root_info->lower_paths[bindex].mnt;
5576 +
5577 + unionfs_set_lower_dentry_idx(sb->s_root, bindex, d);
5578 + unionfs_set_lower_mnt_idx(sb->s_root, bindex, m);
5579 + }
5580 + set_dbstart(sb->s_root, bstart);
5581 + set_dbend(sb->s_root, bend);
5582 +
5583 + /* Set the generation number to one, since this is for the mount. */
5584 + atomic_set(&UNIONFS_D(sb->s_root)->generation, 1);
5585 +
5586 + /* call interpose to create the upper level inode */
5587 + err = unionfs_interpose(sb->s_root, sb, 0);
5588 + unionfs_unlock_dentry(sb->s_root);
5589 + if (!err)
5590 + goto out;
5591 + /* else fall through */
5592 +
5593 +out_freedpd:
5594 + if (UNIONFS_D(sb->s_root)) {
5595 + kfree(UNIONFS_D(sb->s_root)->lower_paths);
5596 + free_dentry_private_data(UNIONFS_D(sb->s_root));
5597 + }
5598 + dput(sb->s_root);
5599 +
5600 +out_dput:
5601 + if (hidden_root_info && !IS_ERR(hidden_root_info)) {
5602 + for (bindex = hidden_root_info->bstart;
5603 + bindex <= hidden_root_info->bend; bindex++) {
5604 + struct dentry *d;
5605 + struct vfsmount *m;
5606 +
5607 + d = hidden_root_info->lower_paths[bindex].dentry;
5608 + m = hidden_root_info->lower_paths[bindex].mnt;
5609 +
5610 + dput(d);
5611 + /* initializing: can't use unionfs_mntput here */
5612 + mntput(m);
5613 + }
5614 + kfree(hidden_root_info->lower_paths);
5615 + kfree(hidden_root_info);
5616 + hidden_root_info = NULL;
5617 + }
5618 +
5619 +out_free:
5620 + kfree(UNIONFS_SB(sb)->data);
5621 + kfree(UNIONFS_SB(sb));
5622 + sb->s_fs_info = NULL;
5623 +
5624 +out:
5625 + if (hidden_root_info && !IS_ERR(hidden_root_info)) {
5626 + kfree(hidden_root_info->lower_paths);
5627 + kfree(hidden_root_info);
5628 + }
5629 + return err;
5630 +}
5631 +
5632 +static int unionfs_get_sb(struct file_system_type *fs_type,
5633 + int flags, const char *dev_name,
5634 + void *raw_data, struct vfsmount *mnt)
5635 +{
5636 + return get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt);
5637 +}
5638 +
5639 +static struct file_system_type unionfs_fs_type = {
5640 + .owner = THIS_MODULE,
5641 + .name = "unionfs",
5642 + .get_sb = unionfs_get_sb,
5643 + .kill_sb = generic_shutdown_super,
5644 + .fs_flags = FS_REVAL_DOT,
5645 +};
5646 +
5647 +static int __init init_unionfs_fs(void)
5648 +{
5649 + int err;
5650 + printk("Registering unionfs " UNIONFS_VERSION "\n");
5651 +
5652 + if ((err = unionfs_init_filldir_cache()))
5653 + goto out;
5654 + if ((err = unionfs_init_inode_cache()))
5655 + goto out;
5656 + if ((err = unionfs_init_dentry_cache()))
5657 + goto out;
5658 + if ((err = init_sioq()))
5659 + goto out;
5660 + err = register_filesystem(&unionfs_fs_type);
5661 +out:
5662 + if (err) {
5663 + stop_sioq();
5664 + unionfs_destroy_filldir_cache();
5665 + unionfs_destroy_inode_cache();
5666 + unionfs_destroy_dentry_cache();
5667 + }
5668 + return err;
5669 +}
5670 +
5671 +static void __exit exit_unionfs_fs(void)
5672 +{
5673 + stop_sioq();
5674 + unionfs_destroy_filldir_cache();
5675 + unionfs_destroy_inode_cache();
5676 + unionfs_destroy_dentry_cache();
5677 + unregister_filesystem(&unionfs_fs_type);
5678 + printk("Completed unionfs module unload.\n");
5679 +}
5680 +
5681 +MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
5682 + " (http://www.fsl.cs.sunysb.edu)");
5683 +MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION
5684 + " (http://unionfs.filesystems.org)");
5685 +MODULE_LICENSE("GPL");
5686 +
5687 +module_init(init_unionfs_fs);
5688 +module_exit(exit_unionfs_fs);
5689 +
5690 diff --git a/fs/unionfs/rdstate.c b/fs/unionfs/rdstate.c
5691 new file mode 100644
5692 index 0000000..b67a86a
5693 --- /dev/null
5694 +++ b/fs/unionfs/rdstate.c
5695 @@ -0,0 +1,275 @@
5696 +/*
5697 + * Copyright (c) 2003-2007 Erez Zadok
5698 + * Copyright (c) 2003-2006 Charles P. Wright
5699 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
5700 + * Copyright (c) 2005-2006 Junjiro Okajima
5701 + * Copyright (c) 2005 Arun M. Krishnakumar
5702 + * Copyright (c) 2004-2006 David P. Quigley
5703 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
5704 + * Copyright (c) 2003 Puja Gupta
5705 + * Copyright (c) 2003 Harikesavan Krishnan
5706 + * Copyright (c) 2003-2007 Stony Brook University
5707 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
5708 + *
5709 + * This program is free software; you can redistribute it and/or modify
5710 + * it under the terms of the GNU General Public License version 2 as
5711 + * published by the Free Software Foundation.
5712 + */
5713 +
5714 +#include "union.h"
5715 +
5716 +/* This file contains the routines for maintaining readdir state. */
5717 +
5718 +/* There are two structures here, rdstate which is a hash table
5719 + * of the second structure which is a filldir_node.
5720 + */
5721 +
5722 +/* This is a struct kmem_cache for filldir nodes, because we allocate a lot
5723 + * of them and they shouldn't waste memory. If the node has a small name
5724 + * (as defined by the dentry structure), then we use an inline name to
5725 + * preserve kmalloc space.
5726 + */
5727 +static struct kmem_cache *unionfs_filldir_cachep;
5728 +
5729 +int unionfs_init_filldir_cache(void)
5730 +{
5731 + unionfs_filldir_cachep =
5732 + kmem_cache_create("unionfs_filldir", sizeof(struct filldir_node), 0,
5733 + SLAB_RECLAIM_ACCOUNT, NULL, NULL);
5734 +
5735 + return (unionfs_filldir_cachep ? 0 : -ENOMEM);
5736 +}
5737 +
5738 +void unionfs_destroy_filldir_cache(void)
5739 +{
5740 + if (unionfs_filldir_cachep)
5741 + kmem_cache_destroy(unionfs_filldir_cachep);
5742 +}
5743 +
5744 +/* This is a tuning parameter that tells us roughly how big to make the
5745 + * hash table in directory entries per page. This isn't perfect, but
5746 + * at least we get a hash table size that shouldn't be too overloaded.
5747 + * The following averages are based on my home directory.
5748 + * 14.44693 Overall
5749 + * 12.29 Single Page Directories
5750 + * 117.93 Multi-page directories
5751 + */
5752 +#define DENTPAGE 4096
5753 +#define DENTPERONEPAGE 12
5754 +#define DENTPERPAGE 118
5755 +#define MINHASHSIZE 1
5756 +static int guesstimate_hash_size(struct inode *inode)
5757 +{
5758 + struct inode *hidden_inode;
5759 + int bindex;
5760 + int hashsize = MINHASHSIZE;
5761 +
5762 + if (UNIONFS_I(inode)->hashsize > 0)
5763 + return UNIONFS_I(inode)->hashsize;
5764 +
5765 + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
5766 + if (!(hidden_inode = unionfs_lower_inode_idx(inode, bindex)))
5767 + continue;
5768 +
5769 + if (hidden_inode->i_size == DENTPAGE)
5770 + hashsize += DENTPERONEPAGE;
5771 + else
5772 + hashsize += (hidden_inode->i_size / DENTPAGE) * DENTPERPAGE;
5773 + }
5774 +
5775 + return hashsize;
5776 +}
5777 +
5778 +int init_rdstate(struct file *file)
5779 +{
5780 + BUG_ON(sizeof(loff_t) != (sizeof(unsigned int) + sizeof(unsigned int)));
5781 + BUG_ON(UNIONFS_F(file)->rdstate != NULL);
5782 +
5783 + UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_dentry->d_inode,
5784 + fbstart(file));
5785 +
5786 + return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
5787 +}
5788 +
5789 +struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos)
5790 +{
5791 + struct unionfs_dir_state *rdstate = NULL;
5792 + struct list_head *pos;
5793 +
5794 + spin_lock(&UNIONFS_I(inode)->rdlock);
5795 + list_for_each(pos, &UNIONFS_I(inode)->readdircache) {
5796 + struct unionfs_dir_state *r =
5797 + list_entry(pos, struct unionfs_dir_state, cache);
5798 + if (fpos == rdstate2offset(r)) {
5799 + UNIONFS_I(inode)->rdcount--;
5800 + list_del(&r->cache);
5801 + rdstate = r;
5802 + break;
5803 + }
5804 + }
5805 + spin_unlock(&UNIONFS_I(inode)->rdlock);
5806 + return rdstate;
5807 +}
5808 +
5809 +struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex)
5810 +{
5811 + int i = 0;
5812 + int hashsize;
5813 + unsigned long mallocsize = sizeof(struct unionfs_dir_state);
5814 + struct unionfs_dir_state *rdstate;
5815 +
5816 + hashsize = guesstimate_hash_size(inode);
5817 + mallocsize += hashsize * sizeof(struct list_head);
5818 + mallocsize = __roundup_pow_of_two(mallocsize);
5819 +
5820 + /* This should give us about 500 entries anyway. */
5821 + if (mallocsize > PAGE_SIZE)
5822 + mallocsize = PAGE_SIZE;
5823 +
5824 + hashsize = (mallocsize -
5825 + sizeof(struct unionfs_dir_state)) / sizeof(struct list_head);
5826 +
5827 + rdstate = kmalloc(mallocsize, GFP_KERNEL);
5828 + if (!rdstate)
5829 + return NULL;
5830 +
5831 + spin_lock(&UNIONFS_I(inode)->rdlock);
5832 + if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1))
5833 + UNIONFS_I(inode)->cookie = 1;
5834 + else
5835 + UNIONFS_I(inode)->cookie++;
5836 +
5837 + rdstate->cookie = UNIONFS_I(inode)->cookie;
5838 + spin_unlock(&UNIONFS_I(inode)->rdlock);
5839 + rdstate->offset = 1;
5840 + rdstate->access = jiffies;
5841 + rdstate->bindex = bindex;
5842 + rdstate->dirpos = 0;
5843 + rdstate->hashentries = 0;
5844 + rdstate->size = hashsize;
5845 + for (i = 0; i < rdstate->size; i++)
5846 + INIT_LIST_HEAD(&rdstate->list[i]);
5847 +
5848 + return rdstate;
5849 +}
5850 +
5851 +static void free_filldir_node(struct filldir_node *node)
5852 +{
5853 + if (node->namelen >= DNAME_INLINE_LEN_MIN)
5854 + kfree(node->name);
5855 + kmem_cache_free(unionfs_filldir_cachep, node);
5856 +}
5857 +
5858 +void free_rdstate(struct unionfs_dir_state *state)
5859 +{
5860 + struct filldir_node *tmp;
5861 + int i;
5862 +
5863 + for (i = 0; i < state->size; i++) {
5864 + struct list_head *head = &(state->list[i]);
5865 + struct list_head *pos, *n;
5866 +
5867 + /* traverse the list and deallocate space */
5868 + list_for_each_safe(pos, n, head) {
5869 + tmp = list_entry(pos, struct filldir_node, file_list);
5870 + list_del(&tmp->file_list);
5871 + free_filldir_node(tmp);
5872 + }
5873 + }
5874 +
5875 + kfree(state);
5876 +}
5877 +
5878 +struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
5879 + const char *name, int namelen)
5880 +{
5881 + int index;
5882 + unsigned int hash;
5883 + struct list_head *head;
5884 + struct list_head *pos;
5885 + struct filldir_node *cursor = NULL;
5886 + int found = 0;
5887 +
5888 + BUG_ON(namelen <= 0);
5889 +
5890 + hash = full_name_hash(name, namelen);
5891 + index = hash % rdstate->size;
5892 +
5893 + head = &(rdstate->list[index]);
5894 + list_for_each(pos, head) {
5895 + cursor = list_entry(pos, struct filldir_node, file_list);
5896 +
5897 + if (cursor->namelen == namelen && cursor->hash == hash &&
5898 + !strncmp(cursor->name, name, namelen)) {
5899 + /* a duplicate exists, and hence no need to create
5900 + * entry to the list
5901 + */
5902 + found = 1;
5903 +
5904 + /* if the duplicate is in this branch, then the file
5905 + * system is corrupted.
5906 + */
5907 + if (cursor->bindex == rdstate->bindex) {
5908 + printk(KERN_DEBUG "Possible I/O error "
5909 + "unionfs_filldir: a file is duplicated "
5910 + "in the same branch %d: %s\n",
5911 + rdstate->bindex, cursor->name);
5912 + }
5913 + break;
5914 + }
5915 + }
5916 +
5917 + if (!found)
5918 + cursor = NULL;
5919 +
5920 + return cursor;
5921 +}
5922 +
5923 +int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
5924 + int namelen, int bindex, int whiteout)
5925 +{
5926 + struct filldir_node *new;
5927 + unsigned int hash;
5928 + int index;
5929 + int err = 0;
5930 + struct list_head *head;
5931 +
5932 + BUG_ON(namelen <= 0);
5933 +
5934 + hash = full_name_hash(name, namelen);
5935 + index = hash % rdstate->size;
5936 + head = &(rdstate->list[index]);
5937 +
5938 + new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL);
5939 + if (!new) {
5940 + err = -ENOMEM;
5941 + goto out;
5942 + }
5943 +
5944 + INIT_LIST_HEAD(&new->file_list);
5945 + new->namelen = namelen;
5946 + new->hash = hash;
5947 + new->bindex = bindex;
5948 + new->whiteout = whiteout;
5949 +
5950 + if (namelen < DNAME_INLINE_LEN_MIN)
5951 + new->name = new->iname;
5952 + else {
5953 + new->name = kmalloc(namelen + 1, GFP_KERNEL);
5954 + if (!new->name) {
5955 + kmem_cache_free(unionfs_filldir_cachep, new);
5956 + new = NULL;
5957 + goto out;
5958 + }
5959 + }
5960 +
5961 + memcpy(new->name, name, namelen);
5962 + new->name[namelen] = '\0';
5963 +
5964 + rdstate->hashentries++;
5965 +
5966 + list_add(&(new->file_list), head);
5967 +out:
5968 + return err;
5969 +}
5970 +
5971 diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
5972 new file mode 100644
5973 index 0000000..0044492
5974 --- /dev/null
5975 +++ b/fs/unionfs/rename.c
5976 @@ -0,0 +1,448 @@
5977 +/*
5978 + * Copyright (c) 2003-2007 Erez Zadok
5979 + * Copyright (c) 2003-2006 Charles P. Wright
5980 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
5981 + * Copyright (c) 2005-2006 Junjiro Okajima
5982 + * Copyright (c) 2005 Arun M. Krishnakumar
5983 + * Copyright (c) 2004-2006 David P. Quigley
5984 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
5985 + * Copyright (c) 2003 Puja Gupta
5986 + * Copyright (c) 2003 Harikesavan Krishnan
5987 + * Copyright (c) 2003-2007 Stony Brook University
5988 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
5989 + *
5990 + * This program is free software; you can redistribute it and/or modify
5991 + * it under the terms of the GNU General Public License version 2 as
5992 + * published by the Free Software Foundation.
5993 + */
5994 +
5995 +#include "union.h"
5996 +
5997 +static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
5998 + struct inode *new_dir, struct dentry *new_dentry,
5999 + int bindex, struct dentry **wh_old)
6000 +{
6001 + int err = 0;
6002 + struct dentry *hidden_old_dentry;
6003 + struct dentry *hidden_new_dentry;
6004 + struct dentry *hidden_old_dir_dentry;
6005 + struct dentry *hidden_new_dir_dentry;
6006 + struct dentry *hidden_wh_dentry;
6007 + struct dentry *hidden_wh_dir_dentry;
6008 + char *wh_name = NULL;
6009 +
6010 + hidden_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
6011 + hidden_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
6012 +
6013 + if (!hidden_new_dentry) {
6014 + hidden_new_dentry =
6015 + create_parents(new_dentry->d_parent->d_inode, new_dentry, bindex);
6016 + if (IS_ERR(hidden_new_dentry)) {
6017 + printk(KERN_DEBUG "error creating directory tree for"
6018 + " rename, bindex = %d, err = %ld\n",
6019 + bindex, PTR_ERR(hidden_new_dentry));
6020 + err = PTR_ERR(hidden_new_dentry);
6021 + goto out;
6022 + }
6023 + }
6024 +
6025 + wh_name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len);
6026 + if (IS_ERR(wh_name)) {
6027 + err = PTR_ERR(wh_name);
6028 + goto out;
6029 + }
6030 +
6031 + hidden_wh_dentry = lookup_one_len(wh_name, hidden_new_dentry->d_parent,
6032 + new_dentry->d_name.len + UNIONFS_WHLEN);
6033 + if (IS_ERR(hidden_wh_dentry)) {
6034 + err = PTR_ERR(hidden_wh_dentry);
6035 + goto out;
6036 + }
6037 +
6038 + if (hidden_wh_dentry->d_inode) {
6039 + /* get rid of the whiteout that is existing */
6040 + if (hidden_new_dentry->d_inode) {
6041 + printk(KERN_WARNING "Both a whiteout and a dentry"
6042 + " exist when doing a rename!\n");
6043 + err = -EIO;
6044 +
6045 + dput(hidden_wh_dentry);
6046 + goto out;
6047 + }
6048 +
6049 + hidden_wh_dir_dentry = lock_parent(hidden_wh_dentry);
6050 + if (!(err = is_robranch_super(old_dentry->d_sb, bindex)))
6051 + err = vfs_unlink(hidden_wh_dir_dentry->d_inode,
6052 + hidden_wh_dentry);
6053 +
6054 + dput(hidden_wh_dentry);
6055 + unlock_dir(hidden_wh_dir_dentry);
6056 + if (err)
6057 + goto out;
6058 + } else
6059 + dput(hidden_wh_dentry);
6060 +
6061 + dget(hidden_old_dentry);
6062 + hidden_old_dir_dentry = dget_parent(hidden_old_dentry);
6063 + hidden_new_dir_dentry = dget_parent(hidden_new_dentry);
6064 +
6065 + lock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);
6066 +
6067 + err = is_robranch_super(old_dentry->d_sb, bindex);
6068 + if (err)
6069 + goto out_unlock;
6070 +
6071 + /* ready to whiteout for old_dentry. caller will create the actual
6072 + * whiteout, and must dput(*wh_old)
6073 + */
6074 + if (wh_old) {
6075 + char *whname;
6076 + whname = alloc_whname(old_dentry->d_name.name,
6077 + old_dentry->d_name.len);
6078 + err = PTR_ERR(whname);
6079 + if (IS_ERR(whname))
6080 + goto out_unlock;
6081 + *wh_old = lookup_one_len(whname, hidden_old_dir_dentry,
6082 + old_dentry->d_name.len + UNIONFS_WHLEN);
6083 + kfree(whname);
6084 + err = PTR_ERR(*wh_old);
6085 + if (IS_ERR(*wh_old)) {
6086 + *wh_old = NULL;
6087 + goto out_unlock;
6088 + }
6089 + }
6090 +
6091 + err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry,
6092 + hidden_new_dir_dentry->d_inode, hidden_new_dentry);
6093 +
6094 +out_unlock:
6095 + unlock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);
6096 +
6097 + dput(hidden_old_dir_dentry);
6098 + dput(hidden_new_dir_dentry);
6099 + dput(hidden_old_dentry);
6100 +
6101 +out:
6102 + if (!err) {
6103 + /* Fixup the newdentry. */
6104 + if (bindex < dbstart(new_dentry))
6105 + set_dbstart(new_dentry, bindex);
6106 + else if (bindex > dbend(new_dentry))
6107 + set_dbend(new_dentry, bindex);
6108 + }
6109 +
6110 + kfree(wh_name);
6111 +
6112 + return err;
6113 +}
6114 +
6115 +static int do_unionfs_rename(struct inode *old_dir,
6116 + struct dentry *old_dentry,
6117 + struct inode *new_dir,
6118 + struct dentry *new_dentry)
6119 +{
6120 + int err = 0;
6121 + int bindex, bwh_old;
6122 + int old_bstart, old_bend;
6123 + int new_bstart, new_bend;
6124 + int do_copyup = -1;
6125 + struct dentry *parent_dentry;
6126 + int local_err = 0;
6127 + int eio = 0;
6128 + int revert = 0;
6129 + struct dentry *wh_old = NULL;
6130 +
6131 + old_bstart = dbstart(old_dentry);
6132 + bwh_old = old_bstart;
6133 + old_bend = dbend(old_dentry);
6134 + parent_dentry = old_dentry->d_parent;
6135 +
6136 + new_bstart = dbstart(new_dentry);
6137 + new_bend = dbend(new_dentry);
6138 +
6139 + /* Rename source to destination. */
6140 + err = do_rename(old_dir, old_dentry, new_dir, new_dentry, old_bstart,
6141 + &wh_old);
6142 + if (err) {
6143 + if (!IS_COPYUP_ERR(err))
6144 + goto out;
6145 + do_copyup = old_bstart - 1;
6146 + } else
6147 + revert = 1;
6148 +
6149 + /* Unlink all instances of destination that exist to the left of
6150 + * bstart of source. On error, revert back, goto out.
6151 + */
6152 + for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
6153 + struct dentry *unlink_dentry;
6154 + struct dentry *unlink_dir_dentry;
6155 +
6156 + unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
6157 + if (!unlink_dentry)
6158 + continue;
6159 +
6160 + unlink_dir_dentry = lock_parent(unlink_dentry);
6161 + if (!(err = is_robranch_super(old_dir->i_sb, bindex)))
6162 + err = vfs_unlink(unlink_dir_dentry->d_inode,
6163 + unlink_dentry);
6164 +
6165 + fsstack_copy_attr_times(new_dentry->d_parent->d_inode,
6166 + unlink_dir_dentry->d_inode);
6167 + /* propagate number of hard-links */
6168 + new_dentry->d_parent->d_inode->i_nlink =
6169 + unionfs_get_nlinks(new_dentry->d_parent->d_inode);
6170 +
6171 + unlock_dir(unlink_dir_dentry);
6172 + if (!err) {
6173 + if (bindex != new_bstart) {
6174 + dput(unlink_dentry);
6175 + unionfs_set_lower_dentry_idx(new_dentry, bindex, NULL);
6176 + }
6177 + } else if (IS_COPYUP_ERR(err)) {
6178 + do_copyup = bindex - 1;
6179 + } else if (revert) {
6180 + dput(wh_old);
6181 + goto revert;
6182 + }
6183 + }
6184 +
6185 + if (do_copyup != -1) {
6186 + for (bindex = do_copyup; bindex >= 0; bindex--) {
6187 + /* copyup the file into some left directory, so that
6188 + * you can rename it
6189 + */
6190 + err = copyup_dentry(old_dentry->d_parent->d_inode,
6191 + old_dentry, old_bstart, bindex, NULL,
6192 + old_dentry->d_inode->i_size);
6193 + if (!err) {
6194 + dput(wh_old);
6195 + bwh_old = bindex;
6196 + err = do_rename(old_dir, old_dentry, new_dir,
6197 + new_dentry, bindex, &wh_old);
6198 + break;
6199 + }
6200 + }
6201 + }
6202 +
6203 + /* make it opaque */
6204 + if (S_ISDIR(old_dentry->d_inode->i_mode)) {
6205 + err = make_dir_opaque(old_dentry, dbstart(old_dentry));
6206 + if (err)
6207 + goto revert;
6208 + }
6209 +
6210 + /* Create whiteout for source, only if:
6211 + * (1) There is more than one underlying instance of source.
6212 + * (2) We did a copy_up
6213 + */
6214 + if ((old_bstart != old_bend) || (do_copyup != -1)) {
6215 + struct dentry *hidden_parent;
6216 + BUG_ON(!wh_old || wh_old->d_inode || bwh_old < 0);
6217 + hidden_parent = lock_parent(wh_old);
6218 + local_err = vfs_create(hidden_parent->d_inode, wh_old, S_IRUGO,
6219 + NULL);
6220 + unlock_dir(hidden_parent);
6221 + if (!local_err)
6222 + set_dbopaque(old_dentry, bwh_old);
6223 + else {
6224 + /* We can't fix anything now, so we cop-out and use -EIO. */
6225 + printk(KERN_ERR "We can't create a whiteout for the "
6226 + "source in rename!\n");
6227 + err = -EIO;
6228 + }
6229 + }
6230 +
6231 +out:
6232 + dput(wh_old);
6233 + return err;
6234 +
6235 +revert:
6236 + /* Do revert here. */
6237 + local_err = unionfs_refresh_hidden_dentry(new_dentry, old_bstart);
6238 + if (local_err) {
6239 + printk(KERN_WARNING "Revert failed in rename: the new refresh "
6240 + "failed.\n");
6241 + eio = -EIO;
6242 + }
6243 +
6244 + local_err = unionfs_refresh_hidden_dentry(old_dentry, old_bstart);
6245 + if (local_err) {
6246 + printk(KERN_WARNING "Revert failed in rename: the old refresh "
6247 + "failed.\n");
6248 + eio = -EIO;
6249 + goto revert_out;
6250 + }
6251 +
6252 + if (!unionfs_lower_dentry_idx(new_dentry, bindex) ||
6253 + !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) {
6254 + printk(KERN_WARNING "Revert failed in rename: the object "
6255 + "disappeared from under us!\n");
6256 + eio = -EIO;
6257 + goto revert_out;
6258 + }
6259 +
6260 + if (unionfs_lower_dentry_idx(old_dentry, bindex) &&
6261 + unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) {
6262 + printk(KERN_WARNING "Revert failed in rename: the object was "
6263 + "created underneath us!\n");
6264 + eio = -EIO;
6265 + goto revert_out;
6266 + }
6267 +
6268 + local_err = do_rename(new_dir, new_dentry, old_dir, old_dentry, old_bstart,
6269 + NULL);
6270 +
6271 + /* If we can't fix it, then we cop-out with -EIO. */
6272 + if (local_err) {
6273 + printk(KERN_WARNING "Revert failed in rename!\n");
6274 + eio = -EIO;
6275 + }
6276 +
6277 + local_err = unionfs_refresh_hidden_dentry(new_dentry, bindex);
6278 + if (local_err)
6279 + eio = -EIO;
6280 + local_err = unionfs_refresh_hidden_dentry(old_dentry, bindex);
6281 + if (local_err)
6282 + eio = -EIO;
6283 +
6284 +revert_out:
6285 + if (eio)
6286 + err = eio;
6287 + return err;
6288 +}
6289 +
6290 +static struct dentry *lookup_whiteout(struct dentry *dentry)
6291 +{
6292 + char *whname;
6293 + int bindex = -1, bstart = -1, bend = -1;
6294 + struct dentry *parent, *hidden_parent, *wh_dentry;
6295 +
6296 + whname = alloc_whname(dentry->d_name.name, dentry->d_name.len);
6297 + if (IS_ERR(whname))
6298 + return (void *)whname;
6299 +
6300 + parent = dget_parent(dentry);
6301 + unionfs_lock_dentry(parent);
6302 + bstart = dbstart(parent);
6303 + bend = dbend(parent);
6304 + wh_dentry = ERR_PTR(-ENOENT);
6305 + for (bindex = bstart; bindex <= bend; bindex++) {
6306 + hidden_parent = unionfs_lower_dentry_idx(parent, bindex);
6307 + if (!hidden_parent)
6308 + continue;
6309 + wh_dentry = lookup_one_len(whname, hidden_parent,
6310 + dentry->d_name.len + UNIONFS_WHLEN);
6311 + if (IS_ERR(wh_dentry))
6312 + continue;
6313 + if (wh_dentry->d_inode)
6314 + break;
6315 + dput(wh_dentry);
6316 + wh_dentry = ERR_PTR(-ENOENT);
6317 + }
6318 + unionfs_unlock_dentry(parent);
6319 + dput(parent);
6320 + kfree(whname);
6321 + return wh_dentry;
6322 +}
6323 +
6324 +/* We can't copyup a directory, because it may involve huge
6325 + * numbers of children, etc. Doing that in the kernel would
6326 + * be bad, so instead we let the userspace recurse and ask us
6327 + * to copy up each file separately
6328 + */
6329 +static int may_rename_dir(struct dentry *dentry)
6330 +{
6331 + int err, bstart;
6332 +
6333 + err = check_empty(dentry, NULL);
6334 + if (err == -ENOTEMPTY) {
6335 + if (is_robranch(dentry))
6336 + return -EXDEV;
6337 + } else if (err)
6338 + return err;
6339 +
6340 + bstart = dbstart(dentry);
6341 + if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
6342 + return 0;
6343 +
6344 + set_dbstart(dentry, bstart + 1);
6345 + err = check_empty(dentry, NULL);
6346 + set_dbstart(dentry, bstart);
6347 + if (err == -ENOTEMPTY)
6348 + err = -EXDEV;
6349 + return err;
6350 +}
6351 +
6352 +int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
6353 + struct inode *new_dir, struct dentry *new_dentry)
6354 +{
6355 + int err = 0;
6356 + struct dentry *wh_dentry;
6357 +
6358 + BUG_ON(!is_valid_dentry(old_dentry));
6359 + BUG_ON(!is_valid_dentry(new_dentry));
6360 +
6361 + double_lock_dentry(old_dentry, new_dentry);
6362 +
6363 + if (!S_ISDIR(old_dentry->d_inode->i_mode))
6364 + err = unionfs_partial_lookup(old_dentry);
6365 + else
6366 + err = may_rename_dir(old_dentry);
6367 +
6368 + if (err)
6369 + goto out;
6370 +
6371 + err = unionfs_partial_lookup(new_dentry);
6372 + if (err)
6373 + goto out;
6374 +
6375 + /*
6376 + * if new_dentry is already hidden because of whiteout,
6377 + * simply override it even if the whiteouted dir is not empty.
6378 + */
6379 + wh_dentry = lookup_whiteout(new_dentry);
6380 + if (!IS_ERR(wh_dentry))
6381 + dput(wh_dentry);
6382 + else if (new_dentry->d_inode) {
6383 + if (S_ISDIR(old_dentry->d_inode->i_mode) !=
6384 + S_ISDIR(new_dentry->d_inode->i_mode)) {
6385 + err = S_ISDIR(old_dentry->d_inode->i_mode) ?
6386 + -ENOTDIR : -EISDIR;
6387 + goto out;
6388 + }
6389 +
6390 + if (S_ISDIR(new_dentry->d_inode->i_mode)) {
6391 + struct unionfs_dir_state *namelist;
6392 + /* check if this unionfs directory is empty or not */
6393 + err = check_empty(new_dentry, &namelist);
6394 + if (err)
6395 + goto out;
6396 +
6397 + if (!is_robranch(new_dentry))
6398 + err = delete_whiteouts(new_dentry,
6399 + dbstart(new_dentry),
6400 + namelist);
6401 +
6402 + free_rdstate(namelist);
6403 +
6404 + if (err)
6405 + goto out;
6406 + }
6407 + }
6408 + err = do_unionfs_rename(old_dir, old_dentry, new_dir, new_dentry);
6409 +
6410 +out:
6411 + if (err)
6412 + /* clear the new_dentry stuff created */
6413 + d_drop(new_dentry);
6414 + else
6415 + /* force re-lookup since the dir on ro branch is not renamed,
6416 + and hidden dentries still indicate the un-renamed ones. */
6417 + if (S_ISDIR(old_dentry->d_inode->i_mode))
6418 + atomic_dec(&UNIONFS_D(old_dentry)->generation);
6419 +
6420 + unionfs_unlock_dentry(new_dentry);
6421 + unionfs_unlock_dentry(old_dentry);
6422 + return err;
6423 +}
6424 +
6425 diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
6426 new file mode 100644
6427 index 0000000..c0d89a3
6428 --- /dev/null
6429 +++ b/fs/unionfs/sioq.c
6430 @@ -0,0 +1,123 @@
6431 +/*
6432 + * Copyright (c) 2003-2007 Erez Zadok
6433 + * Copyright (c) 2003-2006 Charles P. Wright
6434 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
6435 + * Copyright (c) 2005-2006 Junjiro Okajima
6436 + * Copyright (c) 2005 Arun M. Krishnakumar
6437 + * Copyright (c) 2004-2006 David P. Quigley
6438 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
6439 + * Copyright (c) 2003 Puja Gupta
6440 + * Copyright (c) 2003 Harikesavan Krishnan
6441 + * Copyright (c) 2003-2007 Stony Brook University
6442 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
6443 + *
6444 + * This program is free software; you can redistribute it and/or modify
6445 + * it under the terms of the GNU General Public License version 2 as
6446 + * published by the Free Software Foundation.
6447 + */
6448 +
6449 +#include "union.h"
6450 +
6451 +/* Super-user IO work Queue - sometimes we need to perform actions which
6452 + * would fail due to the unix permissions on the parent directory (e.g.,
6453 + * rmdir a directory which appears empty, but in reality contains
6454 + * whiteouts).
6455 + */
6456 +
6457 +static struct workqueue_struct *superio_workqueue;
6458 +
6459 +int __init init_sioq(void)
6460 +{
6461 + int err;
6462 +
6463 + superio_workqueue = create_workqueue("unionfs_siod");
6464 + if (!IS_ERR(superio_workqueue))
6465 + return 0;
6466 +
6467 + err = PTR_ERR(superio_workqueue);
6468 + printk(KERN_ERR "create_workqueue failed %d\n", err);
6469 + superio_workqueue = NULL;
6470 + return err;
6471 +}
6472 +
6473 +void stop_sioq(void)
6474 +{
6475 + if (superio_workqueue)
6476 + destroy_workqueue(superio_workqueue);
6477 +}
6478 +
6479 +void run_sioq(work_func_t func, struct sioq_args *args)
6480 +{
6481 + INIT_WORK(&args->work, func);
6482 +
6483 + init_completion(&args->comp);
6484 + while (!queue_work(superio_workqueue, &args->work)) {
6485 + /* TODO: do accounting if needed */
6486 + schedule();
6487 + }
6488 + wait_for_completion(&args->comp);
6489 +}
6490 +
6491 +void __unionfs_create(struct work_struct *work)
6492 +{
6493 + struct sioq_args *args = container_of(work, struct sioq_args, work);
6494 + struct create_args *c = &args->create;
6495 +
6496 + args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd);
6497 + complete(&args->comp);
6498 +}
6499 +
6500 +void __unionfs_mkdir(struct work_struct *work)
6501 +{
6502 + struct sioq_args *args = container_of(work, struct sioq_args, work);
6503 + struct mkdir_args *m = &args->mkdir;
6504 +
6505 + args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
6506 + complete(&args->comp);
6507 +}
6508 +
6509 +void __unionfs_mknod(struct work_struct *work)
6510 +{
6511 + struct sioq_args *args = container_of(work, struct sioq_args, work);
6512 + struct mknod_args *m = &args->mknod;
6513 +
6514 + args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
6515 + complete(&args->comp);
6516 +}
6517 +
6518 +void __unionfs_symlink(struct work_struct *work)
6519 +{
6520 + struct sioq_args *args = container_of(work, struct sioq_args, work);
6521 + struct symlink_args *s = &args->symlink;
6522 +
6523 + args->err = vfs_symlink(s->parent, s->dentry, s->symbuf, s->mode);
6524 + complete(&args->comp);
6525 +}
6526 +
6527 +void __unionfs_unlink(struct work_struct *work)
6528 +{
6529 + struct sioq_args *args = container_of(work, struct sioq_args, work);
6530 + struct unlink_args *u = &args->unlink;
6531 +
6532 + args->err = vfs_unlink(u->parent, u->dentry);
6533 + complete(&args->comp);
6534 +}
6535 +
6536 +void __delete_whiteouts(struct work_struct *work)
6537 +{
6538 + struct sioq_args *args = container_of(work, struct sioq_args, work);
6539 + struct deletewh_args *d = &args->deletewh;
6540 +
6541 + args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist);
6542 + complete(&args->comp);
6543 +}
6544 +
6545 +void __is_opaque_dir(struct work_struct *work)
6546 +{
6547 + struct sioq_args *args = container_of(work, struct sioq_args, work);
6548 +
6549 + args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry,
6550 + sizeof(UNIONFS_DIR_OPAQUE) - 1);
6551 + complete(&args->comp);
6552 +}
6553 +
6554 diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
6555 new file mode 100644
6556 index 0000000..20e3b0c
6557 --- /dev/null
6558 +++ b/fs/unionfs/sioq.h
6559 @@ -0,0 +1,78 @@
6560 +#ifndef _SIOQ_H
6561 +#define _SIOQ_H
6562 +
6563 +struct deletewh_args {
6564 + struct unionfs_dir_state *namelist;
6565 + struct dentry *dentry;
6566 + int bindex;
6567 +};
6568 +
6569 +struct is_opaque_args {
6570 + struct dentry *dentry;
6571 +};
6572 +
6573 +struct create_args {
6574 + struct inode *parent;
6575 + struct dentry *dentry;
6576 + umode_t mode;
6577 + struct nameidata *nd;
6578 +};
6579 +
6580 +struct mkdir_args {
6581 + struct inode *parent;
6582 + struct dentry *dentry;
6583 + umode_t mode;
6584 +};
6585 +
6586 +struct mknod_args {
6587 + struct inode *parent;
6588 + struct dentry *dentry;
6589 + umode_t mode;
6590 + dev_t dev;
6591 +};
6592 +
6593 +struct symlink_args {
6594 + struct inode *parent;
6595 + struct dentry *dentry;
6596 + char *symbuf;
6597 + umode_t mode;
6598 +};
6599 +
6600 +struct unlink_args {
6601 + struct inode *parent;
6602 + struct dentry *dentry;
6603 +};
6604 +
6605 +
6606 +struct sioq_args {
6607 + struct completion comp;
6608 + struct work_struct work;
6609 + int err;
6610 + void *ret;
6611 +
6612 + union {
6613 + struct deletewh_args deletewh;
6614 + struct is_opaque_args is_opaque;
6615 + struct create_args create;
6616 + struct mkdir_args mkdir;
6617 + struct mknod_args mknod;
6618 + struct symlink_args symlink;
6619 + struct unlink_args unlink;
6620 + };
6621 +};
6622 +
6623 +extern int __init init_sioq(void);
6624 +extern __exit void stop_sioq(void);
6625 +extern void run_sioq(work_func_t func, struct sioq_args *args);
6626 +
6627 +/* Extern definitions for our privlege escalation helpers */
6628 +extern void __unionfs_create(struct work_struct *work);
6629 +extern void __unionfs_mkdir(struct work_struct *work);
6630 +extern void __unionfs_mknod(struct work_struct *work);
6631 +extern void __unionfs_symlink(struct work_struct *work);
6632 +extern void __unionfs_unlink(struct work_struct *work);
6633 +extern void __delete_whiteouts(struct work_struct *work);
6634 +extern void __is_opaque_dir(struct work_struct *work);
6635 +
6636 +#endif /* _SIOQ_H */
6637 +
6638 diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c
6639 new file mode 100644
6640 index 0000000..d274752
6641 --- /dev/null
6642 +++ b/fs/unionfs/subr.c
6643 @@ -0,0 +1,233 @@
6644 +/*
6645 + * Copyright (c) 2003-2007 Erez Zadok
6646 + * Copyright (c) 2003-2006 Charles P. Wright
6647 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
6648 + * Copyright (c) 2005-2006 Junjiro Okajima
6649 + * Copyright (c) 2005 Arun M. Krishnakumar
6650 + * Copyright (c) 2004-2006 David P. Quigley
6651 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
6652 + * Copyright (c) 2003 Puja Gupta
6653 + * Copyright (c) 2003 Harikesavan Krishnan
6654 + * Copyright (c) 2003-2007 Stony Brook University
6655 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
6656 + *
6657 + * This program is free software; you can redistribute it and/or modify
6658 + * it under the terms of the GNU General Public License version 2 as
6659 + * published by the Free Software Foundation.
6660 + */
6661 +
6662 +#include "union.h"
6663 +
6664 +/* Pass an unionfs dentry and an index. It will try to create a whiteout
6665 + * for the filename in dentry, and will try in branch 'index'. On error,
6666 + * it will proceed to a branch to the left.
6667 + */
6668 +int create_whiteout(struct dentry *dentry, int start)
6669 +{
6670 + int bstart, bend, bindex;
6671 + struct dentry *hidden_dir_dentry;
6672 + struct dentry *hidden_dentry;
6673 + struct dentry *hidden_wh_dentry;
6674 + char *name = NULL;
6675 + int err = -EINVAL;
6676 +
6677 + verify_locked(dentry);
6678 +
6679 + bstart = dbstart(dentry);
6680 + bend = dbend(dentry);
6681 +
6682 + /* create dentry's whiteout equivalent */
6683 + name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
6684 + if (IS_ERR(name)) {
6685 + err = PTR_ERR(name);
6686 + goto out;
6687 + }
6688 +
6689 + for (bindex = start; bindex >= 0; bindex--) {
6690 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
6691 +
6692 + if (!hidden_dentry) {
6693 + /* if hidden dentry is not present, create the entire
6694 + * hidden dentry directory structure and go ahead.
6695 + * Since we want to just create whiteout, we only want
6696 + * the parent dentry, and hence get rid of this dentry.
6697 + */
6698 + hidden_dentry = create_parents(dentry->d_inode,
6699 + dentry, bindex);
6700 + if (!hidden_dentry || IS_ERR(hidden_dentry)) {
6701 + printk(KERN_DEBUG "create_parents failed for "
6702 + "bindex = %d\n", bindex);
6703 + continue;
6704 + }
6705 + }
6706 +
6707 + hidden_wh_dentry = lookup_one_len(name, hidden_dentry->d_parent,
6708 + dentry->d_name.len + UNIONFS_WHLEN);
6709 + if (IS_ERR(hidden_wh_dentry))
6710 + continue;
6711 +
6712 + /* The whiteout already exists. This used to be impossible, but
6713 + * now is possible because of opaqueness.
6714 + */
6715 + if (hidden_wh_dentry->d_inode) {
6716 + dput(hidden_wh_dentry);
6717 + err = 0;
6718 + goto out;
6719 + }
6720 +
6721 + hidden_dir_dentry = lock_parent(hidden_wh_dentry);
6722 + if (!(err = is_robranch_super(dentry->d_sb, bindex))) {
6723 + err = vfs_create(hidden_dir_dentry->d_inode,
6724 + hidden_wh_dentry,
6725 + ~current->fs->umask & S_IRWXUGO, NULL);
6726 +
6727 + }
6728 + unlock_dir(hidden_dir_dentry);
6729 + dput(hidden_wh_dentry);
6730 +
6731 + if (!err || !IS_COPYUP_ERR(err))
6732 + break;
6733 + }
6734 +
6735 + /* set dbopaque so that lookup will not proceed after this branch */
6736 + if (!err)
6737 + set_dbopaque(dentry, bindex);
6738 +
6739 +out:
6740 + kfree(name);
6741 + return err;
6742 +}
6743 +
6744 +/* This is a helper function for rename, which ends up with hosed over dentries
6745 + * when it needs to revert.
6746 + */
6747 +int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex)
6748 +{
6749 + struct dentry *hidden_dentry;
6750 + struct dentry *hidden_parent;
6751 + int err = 0;
6752 +
6753 + verify_locked(dentry);
6754 +
6755 + unionfs_lock_dentry(dentry->d_parent);
6756 + hidden_parent = unionfs_lower_dentry_idx(dentry->d_parent, bindex);
6757 + unionfs_unlock_dentry(dentry->d_parent);
6758 +
6759 + BUG_ON(!S_ISDIR(hidden_parent->d_inode->i_mode));
6760 +
6761 + hidden_dentry = lookup_one_len(dentry->d_name.name, hidden_parent,
6762 + dentry->d_name.len);
6763 + if (IS_ERR(hidden_dentry)) {
6764 + err = PTR_ERR(hidden_dentry);
6765 + goto out;
6766 + }
6767 +
6768 + dput(unionfs_lower_dentry_idx(dentry, bindex));
6769 + iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
6770 + unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL);
6771 +
6772 + if (!hidden_dentry->d_inode) {
6773 + dput(hidden_dentry);
6774 + unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
6775 + } else {
6776 + unionfs_set_lower_dentry_idx(dentry, bindex, hidden_dentry);
6777 + unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
6778 + igrab(hidden_dentry->d_inode));
6779 + }
6780 +
6781 +out:
6782 + return err;
6783 +}
6784 +
6785 +int make_dir_opaque(struct dentry *dentry, int bindex)
6786 +{
6787 + int err = 0;
6788 + struct dentry *hidden_dentry, *diropq;
6789 + struct inode *hidden_dir;
6790 +
6791 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
6792 + hidden_dir = hidden_dentry->d_inode;
6793 + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) ||
6794 + !S_ISDIR(hidden_dir->i_mode));
6795 +
6796 + mutex_lock(&hidden_dir->i_mutex);
6797 + diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, hidden_dentry,
6798 + sizeof(UNIONFS_DIR_OPAQUE) - 1);
6799 + if (IS_ERR(diropq)) {
6800 + err = PTR_ERR(diropq);
6801 + goto out;
6802 + }
6803 +
6804 + if (!diropq->d_inode)
6805 + err = vfs_create(hidden_dir, diropq, S_IRUGO, NULL);
6806 + if (!err)
6807 + set_dbopaque(dentry, bindex);
6808 +
6809 + dput(diropq);
6810 +
6811 +out:
6812 + mutex_unlock(&hidden_dir->i_mutex);
6813 + return err;
6814 +}
6815 +
6816 +/* returns the sum of the n_link values of all the underlying inodes of the
6817 + * passed inode
6818 + */
6819 +int unionfs_get_nlinks(struct inode *inode)
6820 +{
6821 + int sum_nlinks = 0;
6822 + int dirs = 0;
6823 + int bindex;
6824 + struct inode *hidden_inode;
6825 +
6826 + /* don't bother to do all the work since we're unlinked */
6827 + if (inode->i_nlink == 0)
6828 + return 0;
6829 +
6830 + if (!S_ISDIR(inode->i_mode))
6831 + return unionfs_lower_inode(inode)->i_nlink;
6832 +
6833 + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
6834 + hidden_inode = unionfs_lower_inode_idx(inode, bindex);
6835 +
6836 + /* ignore files */
6837 + if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode))
6838 + continue;
6839 +
6840 + BUG_ON(hidden_inode->i_nlink < 0);
6841 +
6842 + /* A deleted directory. */
6843 + if (hidden_inode->i_nlink == 0)
6844 + continue;
6845 + dirs++;
6846 +
6847 + /*
6848 + * A broken directory...
6849 + *
6850 + * Some filesystems don't properly set the number of links
6851 + * on empty directories
6852 + */
6853 + if (hidden_inode->i_nlink == 1)
6854 + sum_nlinks += 2;
6855 + else
6856 + sum_nlinks += (hidden_inode->i_nlink - 2);
6857 + }
6858 +
6859 + return (!dirs ? 0 : sum_nlinks + 2);
6860 +}
6861 +
6862 +/* construct whiteout filename */
6863 +char *alloc_whname(const char *name, int len)
6864 +{
6865 + char *buf;
6866 +
6867 + buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL);
6868 + if (!buf)
6869 + return ERR_PTR(-ENOMEM);
6870 +
6871 + strcpy(buf, UNIONFS_WHPFX);
6872 + strlcat(buf, name, len + UNIONFS_WHLEN + 1);
6873 +
6874 + return buf;
6875 +}
6876 +
6877 diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
6878 new file mode 100644
6879 index 0000000..02c0cc8
6880 --- /dev/null
6881 +++ b/fs/unionfs/super.c
6882 @@ -0,0 +1,965 @@
6883 +/*
6884 + * Copyright (c) 2003-2007 Erez Zadok
6885 + * Copyright (c) 2003-2006 Charles P. Wright
6886 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
6887 + * Copyright (c) 2005-2006 Junjiro Okajima
6888 + * Copyright (c) 2005 Arun M. Krishnakumar
6889 + * Copyright (c) 2004-2006 David P. Quigley
6890 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
6891 + * Copyright (c) 2003 Puja Gupta
6892 + * Copyright (c) 2003 Harikesavan Krishnan
6893 + * Copyright (c) 2003-2007 Stony Brook University
6894 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
6895 + *
6896 + * This program is free software; you can redistribute it and/or modify
6897 + * it under the terms of the GNU General Public License version 2 as
6898 + * published by the Free Software Foundation.
6899 + */
6900 +
6901 +#include "union.h"
6902 +
6903 +/* The inode cache is used with alloc_inode for both our inode info and the
6904 + * vfs inode.
6905 + */
6906 +static struct kmem_cache *unionfs_inode_cachep;
6907 +
6908 +static void unionfs_read_inode(struct inode *inode)
6909 +{
6910 + static struct address_space_operations unionfs_empty_aops;
6911 + int size;
6912 + struct unionfs_inode_info *info = UNIONFS_I(inode);
6913 +
6914 + if (!info) {
6915 + printk(KERN_ERR "No kernel memory when allocating inode "
6916 + "private data!\n");
6917 + BUG();
6918 + }
6919 +
6920 + memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode));
6921 + info->bstart = -1;
6922 + info->bend = -1;
6923 + atomic_set(&info->generation,
6924 + atomic_read(&UNIONFS_SB(inode->i_sb)->generation));
6925 + spin_lock_init(&info->rdlock);
6926 + info->rdcount = 1;
6927 + info->hashsize = -1;
6928 + INIT_LIST_HEAD(&info->readdircache);
6929 +
6930 + size = sbmax(inode->i_sb) * sizeof(struct inode *);
6931 + info->lower_inodes = kzalloc(size, GFP_KERNEL);
6932 + if (!info->lower_inodes) {
6933 + printk(KERN_ERR "No kernel memory when allocating lower-"
6934 + "pointer array!\n");
6935 + BUG();
6936 + }
6937 +
6938 + inode->i_version++;
6939 + inode->i_op = &unionfs_main_iops;
6940 + inode->i_fop = &unionfs_main_fops;
6941 +
6942 + /* I don't think ->a_ops is ever allowed to be NULL */
6943 + inode->i_mapping->a_ops = &unionfs_empty_aops;
6944 +}
6945 +
6946 +static void unionfs_put_inode(struct inode *inode)
6947 +{
6948 + /*
6949 + * This is really funky stuff:
6950 + * Basically, if i_count == 1, iput will then decrement it and this
6951 + * inode will be destroyed. It is currently holding a reference to the
6952 + * hidden inode. Therefore, it needs to release that reference by
6953 + * calling iput on the hidden inode. iput() _will_ do it for us (by
6954 + * calling our clear_inode), but _only_ if i_nlink == 0. The problem
6955 + * is, NFS keeps i_nlink == 1 for silly_rename'd files. So we must for
6956 + * our i_nlink to 0 here to trick iput() into calling our clear_inode.
6957 + */
6958 +
6959 + if (atomic_read(&inode->i_count) == 1)
6960 + inode->i_nlink = 0;
6961 +}
6962 +
6963 +/*
6964 + * we now define delete_inode, because there are two VFS paths that may
6965 + * destroy an inode: one of them calls clear inode before doing everything
6966 + * else that's needed, and the other is fine. This way we truncate the inode
6967 + * size (and its pages) and then clear our own inode, which will do an iput
6968 + * on our and the lower inode.
6969 + */
6970 +static void unionfs_delete_inode(struct inode *inode)
6971 +{
6972 + inode->i_size = 0; /* every f/s seems to do that */
6973 +
6974 + clear_inode(inode);
6975 +}
6976 +
6977 +/* final actions when unmounting a file system */
6978 +static void unionfs_put_super(struct super_block *sb)
6979 +{
6980 + int bindex, bstart, bend;
6981 + struct unionfs_sb_info *spd;
6982 + int leaks = 0;
6983 +
6984 + spd = UNIONFS_SB(sb);
6985 + if (!spd)
6986 + return;
6987 +
6988 + bstart = sbstart(sb);
6989 + bend = sbend(sb);
6990 +
6991 + /* Make sure we have no leaks of branchget/branchput. */
6992 + for (bindex = bstart; bindex <= bend; bindex++)
6993 + if (branch_count(sb, bindex) != 0) {
6994 + printk("unionfs: branch %d has %d references left!\n",
6995 + bindex, branch_count(sb,bindex));
6996 + leaks = 1;
6997 + }
6998 + BUG_ON(leaks != 0);
6999 +
7000 + kfree(spd->data);
7001 + kfree(spd);
7002 + sb->s_fs_info = NULL;
7003 +}
7004 +
7005 +/* Since people use this to answer the "How big of a file can I write?"
7006 + * question, we report the size of the highest priority branch as the size of
7007 + * the union.
7008 + */
7009 +static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf)
7010 +{
7011 + int err = 0;
7012 + struct super_block *sb, *hidden_sb;
7013 +
7014 + BUG_ON(!is_valid_dentry(dentry));
7015 +
7016 + sb = dentry->d_sb;
7017 +
7018 + unionfs_read_lock(sb);
7019 + hidden_sb = unionfs_lower_super_idx(sb, sbstart(sb));
7020 + unionfs_read_unlock(sb);
7021 + err = vfs_statfs(hidden_sb->s_root, buf);
7022 +
7023 + buf->f_type = UNIONFS_SUPER_MAGIC;
7024 + buf->f_namelen -= UNIONFS_WHLEN;
7025 +
7026 + memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t));
7027 + memset(&buf->f_spare, 0, sizeof(buf->f_spare));
7028 +
7029 + return err;
7030 +}
7031 +
7032 +/* handle mode changing during remount */
7033 +static noinline int do_remount_mode_option(char *optarg, int cur_branches,
7034 + struct unionfs_data *new_data,
7035 + struct path *new_lower_paths)
7036 +{
7037 + int err = -EINVAL;
7038 + int perms, idx;
7039 + char *modename = strchr(optarg, '=');
7040 + struct nameidata nd;
7041 +
7042 + /* by now, optarg contains the branch name */
7043 + if (!*optarg) {
7044 + printk("unionfs: no branch specified for mode change.\n");
7045 + goto out;
7046 + }
7047 + if (!modename) {
7048 + printk("unionfs: branch \"%s\" requires a mode.\n", optarg);
7049 + goto out;
7050 + }
7051 + *modename++ = '\0';
7052 + perms = __parse_branch_mode(modename);
7053 + if (perms == 0) {
7054 + printk("unionfs: invalid mode \"%s\" for \"%s\".\n",
7055 + modename, optarg);
7056 + goto out;
7057 + }
7058 +
7059 + /*
7060 + * Find matching branch index. For now, this assumes that nothing
7061 + * has been mounted on top of this Unionfs stack. Once we have /odf
7062 + * and cache-coherency resolved, we'll address the branch-path
7063 + * uniqueness.
7064 + */
7065 + err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
7066 + if (err) {
7067 + printk(KERN_WARNING "unionfs: error accessing "
7068 + "hidden directory \"%s\" (error %d)\n",
7069 + optarg, err);
7070 + goto out;
7071 + }
7072 + for (idx=0; idx<cur_branches; idx++)
7073 + if (nd.mnt == new_lower_paths[idx].mnt &&
7074 + nd.dentry == new_lower_paths[idx].dentry)
7075 + break;
7076 + path_release(&nd); /* no longer needed */
7077 + if (idx == cur_branches) {
7078 + err = -ENOENT; /* err may have been reset above */
7079 + printk(KERN_WARNING "unionfs: branch \"%s\" "
7080 + "not found\n", optarg);
7081 + goto out;
7082 + }
7083 + /* check/change mode for existing branch */
7084 + /* we don't warn if perms==branchperms */
7085 + new_data[idx].branchperms = perms;
7086 + err = 0;
7087 +out:
7088 + return err;
7089 +}
7090 +
7091 +/* handle branch deletion during remount */
7092 +static noinline int do_remount_del_option(char *optarg, int cur_branches,
7093 + struct unionfs_data *new_data,
7094 + struct path *new_lower_paths)
7095 +{
7096 + int err = -EINVAL;
7097 + int idx;
7098 + struct nameidata nd;
7099 + /* optarg contains the branch name to delete */
7100 +
7101 + /*
7102 + * Find matching branch index. For now, this assumes that nothing
7103 + * has been mounted on top of this Unionfs stack. Once we have /odf
7104 + * and cache-coherency resolved, we'll address the branch-path
7105 + * uniqueness.
7106 + */
7107 + err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
7108 + if (err) {
7109 + printk(KERN_WARNING "unionfs: error accessing "
7110 + "hidden directory \"%s\" (error %d)\n",
7111 + optarg, err);
7112 + goto out;
7113 + }
7114 + for (idx=0; idx < cur_branches; idx++)
7115 + if (nd.mnt == new_lower_paths[idx].mnt &&
7116 + nd.dentry == new_lower_paths[idx].dentry)
7117 + break;
7118 + path_release(&nd); /* no longer needed */
7119 + if (idx == cur_branches) {
7120 + printk(KERN_WARNING "unionfs: branch \"%s\" "
7121 + "not found\n", optarg);
7122 + err = -ENOENT;
7123 + goto out;
7124 + }
7125 + /* check if there are any open files on the branch to be deleted */
7126 + if (atomic_read(&new_data[idx].open_files) > 0) {
7127 + err = -EBUSY;
7128 + goto out;
7129 + }
7130 +
7131 + /*
7132 + * Now we have to delete the branch. First, release any handles it
7133 + * has. Then, move the remaining array indexes past "idx" in
7134 + * new_data and new_lower_paths one to the left. Finally, adjust
7135 + * cur_branches.
7136 + */
7137 + pathput(&new_lower_paths[idx]);
7138 +
7139 + if (idx < cur_branches - 1) {
7140 + /* if idx==cur_branches-1, we delete last branch: easy */
7141 + memmove(&new_data[idx], &new_data[idx+1],
7142 + (cur_branches - 1 - idx) * sizeof(struct unionfs_data));
7143 + memmove(&new_lower_paths[idx], &new_lower_paths[idx+1],
7144 + (cur_branches - 1 - idx) * sizeof(struct path));
7145 + }
7146 +
7147 + err = 0;
7148 +out:
7149 + return err;
7150 +}
7151 +
7152 +/* handle branch insertion during remount */
7153 +static noinline int do_remount_add_option(char *optarg, int cur_branches,
7154 + struct unionfs_data *new_data,
7155 + struct path *new_lower_paths,
7156 + int *high_branch_id)
7157 +{
7158 + int err = -EINVAL;
7159 + int perms;
7160 + int idx = 0; /* default: insert at beginning */
7161 + char *new_branch , *modename = NULL;
7162 + struct nameidata nd;
7163 +
7164 + /*
7165 + * optarg can be of several forms:
7166 + *
7167 + * /bar:/foo insert /foo before /bar
7168 + * /bar:/foo=ro insert /foo in ro mode before /bar
7169 + * /foo insert /foo in the beginning (prepend)
7170 + * :/foo insert /foo at the end (append)
7171 + */
7172 + if (*optarg == ':') { /* append? */
7173 + new_branch = optarg + 1; /* skip ':' */
7174 + idx = cur_branches;
7175 + goto found_insertion_point;
7176 + }
7177 + new_branch = strchr(optarg, ':');
7178 + if (!new_branch) { /* prepend? */
7179 + new_branch = optarg;
7180 + goto found_insertion_point;
7181 + }
7182 + *new_branch++ = '\0'; /* holds path+mode of new branch */
7183 +
7184 + /*
7185 + * Find matching branch index. For now, this assumes that nothing
7186 + * has been mounted on top of this Unionfs stack. Once we have /odf
7187 + * and cache-coherency resolved, we'll address the branch-path
7188 + * uniqueness.
7189 + */
7190 + err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
7191 + if (err) {
7192 + printk(KERN_WARNING "unionfs: error accessing "
7193 + "hidden directory \"%s\" (error %d)\n",
7194 + optarg, err);
7195 + goto out;
7196 + }
7197 + for (idx=0; idx < cur_branches; idx++)
7198 + if (nd.mnt == new_lower_paths[idx].mnt &&
7199 + nd.dentry == new_lower_paths[idx].dentry)
7200 + break;
7201 + path_release(&nd); /* no longer needed */
7202 + if (idx == cur_branches) {
7203 + printk(KERN_WARNING "unionfs: branch \"%s\" "
7204 + "not found\n", optarg);
7205 + err = -ENOENT;
7206 + goto out;
7207 + }
7208 +
7209 + /*
7210 + * At this point idx will hold the index where the new branch should
7211 + * be inserted before.
7212 + */
7213 +found_insertion_point:
7214 + /* find the mode for the new branch */
7215 + if (new_branch)
7216 + modename = strchr(new_branch, '=');
7217 + if (modename)
7218 + *modename++ = '\0';
7219 + perms = parse_branch_mode(modename);
7220 +
7221 + if (!new_branch || !*new_branch) {
7222 + printk(KERN_WARNING "unionfs: null new branch\n");
7223 + err = -EINVAL;
7224 + goto out;
7225 + }
7226 + err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd);
7227 + if (err) {
7228 + printk(KERN_WARNING "unionfs: error accessing "
7229 + "hidden directory \"%s\" (error %d)\n",
7230 + new_branch, err);
7231 + goto out;
7232 + }
7233 + /* it's probably safe to check_mode the new branch to insert */
7234 + if ((err = check_branch(&nd))) {
7235 + printk(KERN_WARNING "unionfs: hidden directory "
7236 + "\"%s\" is not a valid branch\n", optarg);
7237 + path_release(&nd);
7238 + goto out;
7239 + }
7240 +
7241 + /*
7242 + * Now we have to insert the new branch. But first, move the bits
7243 + * to make space for the new branch, if needed. Finally, adjust
7244 + * cur_branches.
7245 + * We don't release nd here; it's kept until umount/remount.
7246 + */
7247 + if (idx < cur_branches) {
7248 + /* if idx==cur_branches, we append: easy */
7249 + memmove(&new_data[idx+1], &new_data[idx],
7250 + (cur_branches - idx) * sizeof(struct unionfs_data));
7251 + memmove(&new_lower_paths[idx+1], &new_lower_paths[idx],
7252 + (cur_branches - idx) * sizeof(struct path));
7253 + }
7254 + new_lower_paths[idx].dentry = nd.dentry;
7255 + new_lower_paths[idx].mnt = nd.mnt;
7256 +
7257 + new_data[idx].sb = nd.dentry->d_sb;
7258 + atomic_set(&new_data[idx].open_files, 0);
7259 + new_data[idx].branchperms = perms;
7260 + new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */
7261 +
7262 + err = 0;
7263 +out:
7264 + return err;
7265 +}
7266 +
7267 +
7268 +/*
7269 + * Support branch management options on remount.
7270 + *
7271 + * See Documentation/filesystems/unionfs/ for details.
7272 + *
7273 + * @flags: numeric mount options
7274 + * @options: mount options string
7275 + *
7276 + * This function can rearrange a mounted union dynamically, adding and
7277 + * removing branches, including changing branch modes. Clearly this has to
7278 + * be done safely and atomically. Luckily, the VFS already calls this
7279 + * function with lock_super(sb) and lock_kernel() held, preventing
7280 + * concurrent mixing of new mounts, remounts, and unmounts. Moreover,
7281 + * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb)
7282 + * to purge dentries/inodes from our superblock, and also called
7283 + * fsync_super(sb) to purge any dirty pages. So we're good.
7284 + *
7285 + * XXX: however, our remount code may also need to invalidate mapped pages
7286 + * so as to force them to be re-gotten from the (newly reconfigured) lower
7287 + * branches. This has to wait for proper mmap and cache coherency support
7288 + * in the VFS.
7289 + *
7290 + */
7291 +static int unionfs_remount_fs(struct super_block *sb, int *flags,
7292 + char *options)
7293 +{
7294 + int err = 0;
7295 + int i;
7296 + char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */
7297 + char *optname;
7298 + int cur_branches; /* no. of current branches */
7299 + int new_branches; /* no. of branches actually left in the end */
7300 + int add_branches; /* est. no. of branches to add */
7301 + int del_branches; /* est. no. of branches to del */
7302 + int max_branches; /* max possible no. of branches */
7303 + struct unionfs_data *new_data = NULL, *tmp_data = NULL;
7304 + struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL;
7305 + int new_high_branch_id; /* new high branch ID */
7306 +
7307 + unionfs_write_lock(sb);
7308 +
7309 + /*
7310 + * The VFS will take care of "ro" and "rw" flags, and we can safely
7311 + * ignore MS_SILENT, but anything else left over is an error. So we
7312 + * need to check if any other flags may have been passed (none are
7313 + * allowed/supported as of now).
7314 + */
7315 + if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
7316 + printk(KERN_WARNING
7317 + "unionfs: remount flags 0x%x unsupported\n", *flags);
7318 + err = -EINVAL;
7319 + goto out_error;
7320 + }
7321 +
7322 + /*
7323 + * If 'options' is NULL, it's probably because the user just changed
7324 + * the union to a "ro" or "rw" and the VFS took care of it. So
7325 + * nothing to do and we're done.
7326 + */
7327 + if (!options || options[0] == '\0')
7328 + goto out_error;
7329 +
7330 + /*
7331 + * Find out how many branches we will have in the end, counting
7332 + * "add" and "del" commands. Copy the "options" string because
7333 + * strsep modifies the string and we need it later.
7334 + */
7335 + optionstmp = tmp_to_free = kstrdup(options, GFP_KERNEL);
7336 + if (!optionstmp) {
7337 + err = -ENOMEM;
7338 + goto out_free;
7339 + }
7340 + new_branches = cur_branches = sbmax(sb); /* current no. branches */
7341 + add_branches = del_branches = 0;
7342 + new_high_branch_id = sbhbid(sb); /* save current high_branch_id */
7343 + while ((optname = strsep(&optionstmp, ",")) != NULL) {
7344 + char *optarg;
7345 +
7346 + if (!optname || !*optname)
7347 + continue;
7348 +
7349 + optarg = strchr(optname, '=');
7350 + if (optarg)
7351 + *optarg++ = '\0';
7352 +
7353 + if (!strcmp("add", optname))
7354 + add_branches++;
7355 + else if (!strcmp("del", optname))
7356 + del_branches++;
7357 + }
7358 + kfree(tmp_to_free);
7359 + /* after all changes, will we have at least one branch left? */
7360 + if ((new_branches + add_branches - del_branches) < 1) {
7361 + printk(KERN_WARNING
7362 + "unionfs: no branches left after remount\n");
7363 + err = -EINVAL;
7364 + goto out_free;
7365 + }
7366 +
7367 + /*
7368 + * Since we haven't actually parsed all the add/del options, nor
7369 + * have we checked them for errors, we don't know for sure how many
7370 + * branches we will have after all changes have taken place. In
7371 + * fact, the total number of branches left could be less than what
7372 + * we have now. So we need to allocate space for a temporary
7373 + * placeholder that is at least as large as the maximum number of
7374 + * branches we *could* have, which is the current number plus all
7375 + * the additions. Once we're done with these temp placeholders, we
7376 + * may have to re-allocate the final size, copy over from the temp,
7377 + * and then free the temps (done near the end of this function).
7378 + */
7379 + max_branches = cur_branches + add_branches;
7380 + /* allocate space for new pointers to hidden dentry */
7381 + tmp_data = kcalloc(max_branches,
7382 + sizeof(struct unionfs_data), GFP_KERNEL);
7383 + if (!tmp_data) {
7384 + err = -ENOMEM;
7385 + goto out_free;
7386 + }
7387 + /* allocate space for new pointers to lower paths */
7388 + tmp_lower_paths = kcalloc(max_branches,
7389 + sizeof(struct path), GFP_KERNEL);
7390 + if (!tmp_lower_paths) {
7391 + err = -ENOMEM;
7392 + goto out_free;
7393 + }
7394 + /* copy current info into new placeholders, incrementing refcnts */
7395 + memcpy(tmp_data, UNIONFS_SB(sb)->data,
7396 + cur_branches * sizeof(struct unionfs_data));
7397 + memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths,
7398 + cur_branches * sizeof(struct path));
7399 + for (i=0; i<cur_branches; i++)
7400 + pathget(&tmp_lower_paths[i]); /* drop refs at end of fxn */
7401 +
7402 + /*******************************************************************
7403 + * For each branch command, do path_lookup on the requested branch,
7404 + * and apply the change to a temp branch list. To handle errors, we
7405 + * already dup'ed the old arrays (above), and increased the refcnts
7406 + * on various f/s objects. So now we can do all the path_lookups
7407 + * and branch-management commands on the new arrays. If it fail mid
7408 + * way, we free the tmp arrays and *put all objects. If we succeed,
7409 + * then we free old arrays and *put its objects, and then replace
7410 + * the arrays with the new tmp list (we may have to re-allocate the
7411 + * memory because the temp lists could have been larger than what we
7412 + * actually needed).
7413 + *******************************************************************/
7414 +
7415 + while ((optname = strsep(&options, ",")) != NULL) {
7416 + char *optarg;
7417 +
7418 + if (!optname || !*optname)
7419 + continue;
7420 + /*
7421 + * At this stage optname holds a comma-delimited option, but
7422 + * without the commas. Next, we need to break the string on
7423 + * the '=' symbol to separate CMD=ARG, where ARG itself can
7424 + * be KEY=VAL. For example, in mode=/foo=rw, CMD is "mode",
7425 + * KEY is "/foo", and VAL is "rw".
7426 + */
7427 + optarg = strchr(optname, '=');
7428 + if (optarg)
7429 + *optarg++ = '\0';
7430 + /* incgen remount option (instead of old ioctl) */
7431 + if (!strcmp("incgen", optname)) {
7432 + err = 0;
7433 + goto out_no_change;
7434 + }
7435 +
7436 + /*
7437 + * All of our options take an argument now. (Insert ones
7438 + * that don't above this check.) So at this stage optname
7439 + * contains the CMD part and optarg contains the ARG part.
7440 + */
7441 + if (!optarg || !*optarg) {
7442 + printk("unionfs: all remount options require "
7443 + "an argument (%s).\n", optname);
7444 + err = -EINVAL;
7445 + goto out_release;
7446 + }
7447 +
7448 + if (!strcmp("add", optname)) {
7449 + err = do_remount_add_option(optarg, new_branches,
7450 + tmp_data,
7451 + tmp_lower_paths,
7452 + &new_high_branch_id);
7453 + if (err)
7454 + goto out_release;
7455 + new_branches++;
7456 + if (new_branches > UNIONFS_MAX_BRANCHES) {
7457 + printk("unionfs: command exceeds %d branches\n",
7458 + UNIONFS_MAX_BRANCHES);
7459 + err = -E2BIG;
7460 + goto out_release;
7461 + }
7462 + continue;
7463 + }
7464 + if (!strcmp("del", optname)) {
7465 + err = do_remount_del_option(optarg, new_branches,
7466 + tmp_data,
7467 + tmp_lower_paths);
7468 + if (err)
7469 + goto out_release;
7470 + new_branches--;
7471 + continue;
7472 + }
7473 + if (!strcmp("mode", optname)) {
7474 + err = do_remount_mode_option(optarg, new_branches,
7475 + tmp_data,
7476 + tmp_lower_paths);
7477 + if (err)
7478 + goto out_release;
7479 + continue;
7480 + }
7481 +
7482 + /*
7483 + * When you use "mount -o remount,ro", mount(8) will
7484 + * reportedly pass the original dirs= string from
7485 + * /proc/mounts. So for now, we have to ignore dirs= and
7486 + * not consider it an error, unless we want to allow users
7487 + * to pass dirs= in remount. Note that to allow the VFS to
7488 + * actually process the ro/rw remount options, we have to
7489 + * return 0 from this function.
7490 + */
7491 + if (!strcmp("dirs", optname)) {
7492 + printk(KERN_WARNING
7493 + "unionfs: remount ignoring option \"%s\".\n",
7494 + optname);
7495 + continue;
7496 + }
7497 +
7498 + err = -EINVAL;
7499 + printk(KERN_WARNING
7500 + "unionfs: unrecognized option \"%s\"\n", optname);
7501 + goto out_release;
7502 + }
7503 +
7504 +out_no_change:
7505 +
7506 + /******************************************************************
7507 + * WE'RE ALMOST DONE: see if we need to allocate a small-sized new
7508 + * vector, copy the vectors to their correct place, release the
7509 + * refcnt of the older ones, and return.
7510 + * Also handle invalidating any pgaes that will have to be re-read.
7511 + *******************************************************************/
7512 +
7513 + /*
7514 + * Allocate space for actual pointers, if needed. By the time we
7515 + * finish this block of code, new_branches and new_lower_paths will
7516 + * have the correct size. None of this code below would be needed
7517 + * if the kernel had a realloc() function, at least one capable of
7518 + * shrinking/truncating an allocation's size (hint, hint).
7519 + */
7520 + if (new_branches < max_branches) {
7521 +
7522 + /* allocate space for new pointers to hidden dentry */
7523 + new_data = kcalloc(new_branches,
7524 + sizeof(struct unionfs_data), GFP_KERNEL);
7525 + if (!new_data) {
7526 + err = -ENOMEM;
7527 + goto out_release;
7528 + }
7529 + /* allocate space for new pointers to lower paths */
7530 + new_lower_paths = kcalloc(new_branches,
7531 + sizeof(struct path), GFP_KERNEL);
7532 + if (!new_lower_paths) {
7533 + err = -ENOMEM;
7534 + goto out_release;
7535 + }
7536 + /*
7537 + * copy current info into new placeholders, incrementing
7538 + * refcounts.
7539 + */
7540 + memcpy(new_data, tmp_data,
7541 + new_branches * sizeof(struct unionfs_data));
7542 + memcpy(new_lower_paths, tmp_lower_paths,
7543 + new_branches * sizeof(struct path));
7544 + /*
7545 + * Since we already hold various refcnts on the objects, we
7546 + * don't need to redo it here. Just free the older memory
7547 + * and re-point the pointers.
7548 + */
7549 + kfree(tmp_data);
7550 + kfree(tmp_lower_paths);
7551 + /* no need to nullify pointers here */
7552 + } else {
7553 + /* number of branches didn't change, no need to re-alloc */
7554 + new_data = tmp_data;
7555 + new_lower_paths = tmp_lower_paths;
7556 + }
7557 +
7558 + /*
7559 + * OK, just before we actually put the new set of branches in place,
7560 + * we need to ensure that our own f/s has no dirty objects left.
7561 + * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and
7562 + * fsync_super(sb), taking care of dentries, inodes, and dirty
7563 + * pages. So all that's left is for us to invalidate any leftover
7564 + * (non-dirty) pages to ensure that they will be re-read from the
7565 + * new lower branches (and to support mmap).
7566 + */
7567 +
7568 + /*
7569 + * No we call drop_pagecache_sb() to invalidate all pages in this
7570 + * super. This function calls invalidate_inode_pages(mapping),
7571 + * which calls invalidate_mapping_pages(): the latter, however, will
7572 + * not invalidate pages which are dirty, locked, under writeback, or
7573 + * mapped into pagetables. We shouldn't have to worry about dirty
7574 + * or under-writeback pages, because do_remount_sb() called
7575 + * fsync_super() which would not have returned until all dirty pages
7576 + * were flushed.
7577 + *
7578 + * But do w have to worry about locked pages? Is there any chance
7579 + * that in here we'll get locked pages?
7580 + *
7581 + * XXX: what about pages mapped into pagetables? Are these pages
7582 + * which user processes may have mmap(2)'ed? If so, then we need to
7583 + * invalidate those too, no? Maybe we'll have to write our own
7584 + * version of invalidate_mapping_pages() which also handled mapped
7585 + * pages.
7586 + *
7587 + * XXX: Alternatively, maybe we should call truncate_inode_pages(),
7588 + * which use two passes over the pages list, and will truncate all
7589 + * pages.
7590 + */
7591 + drop_pagecache_sb(sb);
7592 +
7593 + /* copy new vectors into their correct place */
7594 + tmp_data = UNIONFS_SB(sb)->data;
7595 + UNIONFS_SB(sb)->data = new_data;
7596 + new_data = NULL; /* so don't free good pointers below */
7597 + tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths;
7598 + UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths;
7599 + new_lower_paths = NULL; /* so don't free good pointers below */
7600 +
7601 + /* update our unionfs_sb_info and root dentry index of last branch */
7602 + i = sbmax(sb); /* save no. of branches to release at end */
7603 + sbend(sb) = new_branches - 1;
7604 + set_dbend(sb->s_root, new_branches - 1);
7605 + UNIONFS_D(sb->s_root)->bcount = new_branches;
7606 + new_branches = i; /* no. of branches to release below */
7607 +
7608 + /* maxbytes may have changed */
7609 + sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
7610 + /* update high branch ID */
7611 + sbhbid(sb) = new_high_branch_id;
7612 +
7613 + /* update our sb->generation for revalidating objects */
7614 + i = atomic_inc_return(&UNIONFS_SB(sb)->generation);
7615 + atomic_set(&UNIONFS_D(sb->s_root)->generation, i);
7616 + atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i);
7617 + if (!(*flags & MS_SILENT))
7618 + printk("unionfs: new generation number %d\n", i);
7619 + err = 0; /* reset to success */
7620 +
7621 + /*
7622 + * The code above falls through to the next label, and releases the
7623 + * refcnts of the older ones (stored in tmp_*): if we fell through
7624 + * here, it means success. However, if we jump directly to this
7625 + * label from any error above, then an error occurred after we
7626 + * grabbed various refcnts, and so we have to release the
7627 + * temporarily constructed structures.
7628 + */
7629 +out_release:
7630 + /* no need to cleanup/release anything in tmp_data */
7631 + if (tmp_lower_paths)
7632 + for (i=0; i<new_branches; i++)
7633 + pathput(&tmp_lower_paths[i]);
7634 +out_free:
7635 + kfree(tmp_lower_paths);
7636 + kfree(tmp_data);
7637 + kfree(new_lower_paths);
7638 + kfree(new_data);
7639 +out_error:
7640 + unionfs_write_unlock(sb);
7641 + return err;
7642 +}
7643 +
7644 +/*
7645 + * Called by iput() when the inode reference count reached zero
7646 + * and the inode is not hashed anywhere. Used to clear anything
7647 + * that needs to be, before the inode is completely destroyed and put
7648 + * on the inode free list.
7649 + */
7650 +static void unionfs_clear_inode(struct inode *inode)
7651 +{
7652 + int bindex, bstart, bend;
7653 + struct inode *hidden_inode;
7654 + struct list_head *pos, *n;
7655 + struct unionfs_dir_state *rdstate;
7656 +
7657 + list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
7658 + rdstate = list_entry(pos, struct unionfs_dir_state, cache);
7659 + list_del(&rdstate->cache);
7660 + free_rdstate(rdstate);
7661 + }
7662 +
7663 + /* Decrement a reference to a hidden_inode, which was incremented
7664 + * by our read_inode when it was created initially.
7665 + */
7666 + bstart = ibstart(inode);
7667 + bend = ibend(inode);
7668 + if (bstart >= 0) {
7669 + for (bindex = bstart; bindex <= bend; bindex++) {
7670 + hidden_inode = unionfs_lower_inode_idx(inode, bindex);
7671 + if (!hidden_inode)
7672 + continue;
7673 + iput(hidden_inode);
7674 + }
7675 + }
7676 +
7677 + kfree(UNIONFS_I(inode)->lower_inodes);
7678 + UNIONFS_I(inode)->lower_inodes = NULL;
7679 +}
7680 +
7681 +static struct inode *unionfs_alloc_inode(struct super_block *sb)
7682 +{
7683 + struct unionfs_inode_info *i;
7684 +
7685 + i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL);
7686 + if (!i)
7687 + return NULL;
7688 +
7689 + /* memset everything up to the inode to 0 */
7690 + memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode));
7691 +
7692 + i->vfs_inode.i_version = 1;
7693 + return &i->vfs_inode;
7694 +}
7695 +
7696 +static void unionfs_destroy_inode(struct inode *inode)
7697 +{
7698 + kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode));
7699 +}
7700 +
7701 +/* unionfs inode cache constructor */
7702 +static void init_once(void *v, struct kmem_cache * cachep, unsigned long flags)
7703 +{
7704 + struct unionfs_inode_info *i = v;
7705 +
7706 + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
7707 + SLAB_CTOR_CONSTRUCTOR)
7708 + inode_init_once(&i->vfs_inode);
7709 +}
7710 +
7711 +int unionfs_init_inode_cache(void)
7712 +{
7713 + int err = 0;
7714 +
7715 + unionfs_inode_cachep =
7716 + kmem_cache_create("unionfs_inode_cache",
7717 + sizeof(struct unionfs_inode_info), 0,
7718 + SLAB_RECLAIM_ACCOUNT, init_once, NULL);
7719 + if (!unionfs_inode_cachep)
7720 + err = -ENOMEM;
7721 + return err;
7722 +}
7723 +
7724 +void unionfs_destroy_inode_cache(void)
7725 +{
7726 + if (unionfs_inode_cachep)
7727 + kmem_cache_destroy(unionfs_inode_cachep);
7728 +}
7729 +
7730 +/* Called when we have a dirty inode, right here we only throw out
7731 + * parts of our readdir list that are too old.
7732 + */
7733 +static int unionfs_write_inode(struct inode *inode, int sync)
7734 +{
7735 + struct list_head *pos, *n;
7736 + struct unionfs_dir_state *rdstate;
7737 +
7738 + spin_lock(&UNIONFS_I(inode)->rdlock);
7739 + list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
7740 + rdstate = list_entry(pos, struct unionfs_dir_state, cache);
7741 + /* We keep this list in LRU order. */
7742 + if ((rdstate->access + RDCACHE_JIFFIES) > jiffies)
7743 + break;
7744 + UNIONFS_I(inode)->rdcount--;
7745 + list_del(&rdstate->cache);
7746 + free_rdstate(rdstate);
7747 + }
7748 + spin_unlock(&UNIONFS_I(inode)->rdlock);
7749 +
7750 + return 0;
7751 +}
7752 +
7753 +/*
7754 + * Used only in nfs, to kill any pending RPC tasks, so that subsequent
7755 + * code can actually succeed and won't leave tasks that need handling.
7756 + */
7757 +static void unionfs_umount_begin(struct vfsmount *mnt, int flags)
7758 +{
7759 + struct super_block *sb, *hidden_sb;
7760 + struct vfsmount *hidden_mnt;
7761 + int bindex, bstart, bend;
7762 +
7763 + if (!(flags & MNT_FORCE))
7764 + /* we are not being MNT_FORCEd, therefore we should emulate
7765 + * old behaviour
7766 + */
7767 + return;
7768 +
7769 + sb = mnt->mnt_sb;
7770 +
7771 + bstart = sbstart(sb);
7772 + bend = sbend(sb);
7773 + for (bindex = bstart; bindex <= bend; bindex++) {
7774 + hidden_mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
7775 + unionfs_read_lock(sb);
7776 + hidden_sb = unionfs_lower_super_idx(sb, bindex);
7777 + unionfs_read_unlock(sb);
7778 +
7779 + if (hidden_mnt && hidden_sb && hidden_sb->s_op &&
7780 + hidden_sb->s_op->umount_begin)
7781 + hidden_sb->s_op->umount_begin(hidden_mnt, flags);
7782 + }
7783 +}
7784 +
7785 +static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt)
7786 +{
7787 + struct super_block *sb = mnt->mnt_sb;
7788 + int ret = 0;
7789 + char *tmp_page;
7790 + char *path;
7791 + int bindex, bstart, bend;
7792 + int perms;
7793 +
7794 + unionfs_lock_dentry(sb->s_root);
7795 +
7796 + tmp_page = (char*) __get_free_page(GFP_KERNEL);
7797 + if (!tmp_page) {
7798 + ret = -ENOMEM;
7799 + goto out;
7800 + }
7801 +
7802 + bstart = sbstart(sb);
7803 + bend = sbend(sb);
7804 +
7805 + seq_printf(m, ",dirs=");
7806 + for (bindex = bstart; bindex <= bend; bindex++) {
7807 + path = d_path(unionfs_lower_dentry_idx(sb->s_root, bindex),
7808 + unionfs_lower_mnt_idx(sb->s_root, bindex), tmp_page,
7809 + PAGE_SIZE);
7810 + if (IS_ERR(path)) {
7811 + ret = PTR_ERR(path);
7812 + goto out;
7813 + }
7814 +
7815 + unionfs_read_lock(sb);
7816 + perms = branchperms(sb, bindex);
7817 + unionfs_read_unlock(sb);
7818 +
7819 + seq_printf(m, "%s=%s", path,
7820 + perms & MAY_WRITE ? "rw" : "ro");
7821 + if (bindex != bend)
7822 + seq_printf(m, ":");
7823 + }
7824 +
7825 +out:
7826 + free_page((unsigned long) tmp_page);
7827 +
7828 + unionfs_unlock_dentry(sb->s_root);
7829 +
7830 + return ret;
7831 +}
7832 +
7833 +struct super_operations unionfs_sops = {
7834 + .read_inode = unionfs_read_inode,
7835 + .put_inode = unionfs_put_inode,
7836 + .delete_inode = unionfs_delete_inode,
7837 + .put_super = unionfs_put_super,
7838 + .statfs = unionfs_statfs,
7839 + .remount_fs = unionfs_remount_fs,
7840 + .clear_inode = unionfs_clear_inode,
7841 + .umount_begin = unionfs_umount_begin,
7842 + .show_options = unionfs_show_options,
7843 + .write_inode = unionfs_write_inode,
7844 + .alloc_inode = unionfs_alloc_inode,
7845 + .destroy_inode = unionfs_destroy_inode,
7846 +};
7847 +
7848 diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
7849 new file mode 100644
7850 index 0000000..b6fa0a2
7851 --- /dev/null
7852 +++ b/fs/unionfs/union.h
7853 @@ -0,0 +1,489 @@
7854 +/*
7855 + * Copyright (c) 2003-2007 Erez Zadok
7856 + * Copyright (c) 2003-2006 Charles P. Wright
7857 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
7858 + * Copyright (c) 2005 Arun M. Krishnakumar
7859 + * Copyright (c) 2004-2006 David P. Quigley
7860 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
7861 + * Copyright (c) 2003 Puja Gupta
7862 + * Copyright (c) 2003 Harikesavan Krishnan
7863 + * Copyright (c) 2003-2007 Stony Brook University
7864 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
7865 + *
7866 + * This program is free software; you can redistribute it and/or modify
7867 + * it under the terms of the GNU General Public License version 2 as
7868 + * published by the Free Software Foundation.
7869 + */
7870 +
7871 +#ifndef _UNION_H_
7872 +#define _UNION_H_
7873 +
7874 +#include <linux/dcache.h>
7875 +#include <linux/file.h>
7876 +#include <linux/list.h>
7877 +#include <linux/fs.h>
7878 +#include <linux/mm.h>
7879 +#include <linux/module.h>
7880 +#include <linux/mount.h>
7881 +#include <linux/namei.h>
7882 +#include <linux/page-flags.h>
7883 +#include <linux/pagemap.h>
7884 +#include <linux/poll.h>
7885 +#include <linux/security.h>
7886 +#include <linux/seq_file.h>
7887 +#include <linux/slab.h>
7888 +#include <linux/spinlock.h>
7889 +#include <linux/smp_lock.h>
7890 +#include <linux/statfs.h>
7891 +#include <linux/string.h>
7892 +#include <linux/vmalloc.h>
7893 +#include <linux/writeback.h>
7894 +#include <linux/xattr.h>
7895 +#include <linux/fs_stack.h>
7896 +#include <linux/magic.h>
7897 +#include <linux/log2.h>
7898 +
7899 +#include <asm/mman.h>
7900 +#include <asm/system.h>
7901 +
7902 +#include <linux/union_fs.h>
7903 +
7904 +/* the file system name */
7905 +#define UNIONFS_NAME "unionfs"
7906 +
7907 +/* unionfs root inode number */
7908 +#define UNIONFS_ROOT_INO 1
7909 +
7910 +/* number of characters while generating unique temporary file names */
7911 +#define UNIONFS_TMPNAM_LEN 12
7912 +
7913 +/* number of times we try to get a unique temporary file name */
7914 +#define GET_TMPNAM_MAX_RETRY 5
7915 +
7916 +/* maximum number of branches we support, to avoid memory blowup */
7917 +#define UNIONFS_MAX_BRANCHES 128
7918 +
7919 +/* Operations vectors defined in specific files. */
7920 +extern struct file_operations unionfs_main_fops;
7921 +extern struct file_operations unionfs_dir_fops;
7922 +extern struct inode_operations unionfs_main_iops;
7923 +extern struct inode_operations unionfs_dir_iops;
7924 +extern struct inode_operations unionfs_symlink_iops;
7925 +extern struct super_operations unionfs_sops;
7926 +extern struct dentry_operations unionfs_dops;
7927 +
7928 +/* How long should an entry be allowed to persist */
7929 +#define RDCACHE_JIFFIES (5*HZ)
7930 +
7931 +/* file private data. */
7932 +struct unionfs_file_info {
7933 + int bstart;
7934 + int bend;
7935 + atomic_t generation;
7936 +
7937 + struct unionfs_dir_state *rdstate;
7938 + struct file **lower_files;
7939 + int *saved_branch_ids; /* IDs of branches when file was opened */
7940 +};
7941 +
7942 +/* unionfs inode data in memory */
7943 +struct unionfs_inode_info {
7944 + int bstart;
7945 + int bend;
7946 + atomic_t generation;
7947 + int stale;
7948 + /* Stuff for readdir over NFS. */
7949 + spinlock_t rdlock;
7950 + struct list_head readdircache;
7951 + int rdcount;
7952 + int hashsize;
7953 + int cookie;
7954 +
7955 + /* The hidden inodes */
7956 + struct inode **lower_inodes;
7957 + /* to keep track of reads/writes for unlinks before closes */
7958 + atomic_t totalopens;
7959 +
7960 + struct inode vfs_inode;
7961 +};
7962 +
7963 +/* unionfs dentry data in memory */
7964 +struct unionfs_dentry_info {
7965 + /* The semaphore is used to lock the dentry as soon as we get into a
7966 + * unionfs function from the VFS. Our lock ordering is that children
7967 + * go before their parents.
7968 + */
7969 + struct mutex lock;
7970 + int bstart;
7971 + int bend;
7972 + int bopaque;
7973 + int bcount;
7974 + atomic_t generation;
7975 + struct path *lower_paths;
7976 +};
7977 +
7978 +/* These are the pointers to our various objects. */
7979 +struct unionfs_data {
7980 + struct super_block *sb;
7981 + atomic_t open_files; /* number of open files on branch */
7982 + int branchperms;
7983 + int branch_id; /* unique branch ID at re/mount time */
7984 +};
7985 +
7986 +/* unionfs super-block data in memory */
7987 +struct unionfs_sb_info {
7988 + int bend;
7989 +
7990 + atomic_t generation;
7991 + struct rw_semaphore rwsem; /* protects access to data+id fields */
7992 + int high_branch_id; /* last unique branch ID given */
7993 + struct unionfs_data *data;
7994 +};
7995 +
7996 +/*
7997 + * structure for making the linked list of entries by readdir on left branch
7998 + * to compare with entries on right branch
7999 + */
8000 +struct filldir_node {
8001 + struct list_head file_list; /* list for directory entries */
8002 + char *name; /* name entry */
8003 + int hash; /* name hash */
8004 + int namelen; /* name len since name is not 0 terminated */
8005 +
8006 + /* we can check for duplicate whiteouts and files in the same branch
8007 + * in order to return -EIO.
8008 + */
8009 + int bindex;
8010 +
8011 + /* is this a whiteout entry? */
8012 + int whiteout;
8013 +
8014 + /* Inline name, so we don't need to separately kmalloc small ones */
8015 + char iname[DNAME_INLINE_LEN_MIN];
8016 +};
8017 +
8018 +/* Directory hash table. */
8019 +struct unionfs_dir_state {
8020 + unsigned int cookie; /* The cookie, which is based off of rdversion */
8021 + unsigned int offset; /* The entry we have returned. */
8022 + int bindex;
8023 + loff_t dirpos; /* The offset within the lower level directory. */
8024 + int size; /* How big is the hash table? */
8025 + int hashentries; /* How many entries have been inserted? */
8026 + unsigned long access;
8027 +
8028 + /* This cache list is used when the inode keeps us around. */
8029 + struct list_head cache;
8030 + struct list_head list[0];
8031 +};
8032 +
8033 +/* include miscellaneous macros */
8034 +#include "fanout.h"
8035 +#include "sioq.h"
8036 +
8037 +/* Cache creation/deletion routines. */
8038 +void unionfs_destroy_filldir_cache(void);
8039 +int unionfs_init_filldir_cache(void);
8040 +int unionfs_init_inode_cache(void);
8041 +void unionfs_destroy_inode_cache(void);
8042 +int unionfs_init_dentry_cache(void);
8043 +void unionfs_destroy_dentry_cache(void);
8044 +
8045 +/* Initialize and free readdir-specific state. */
8046 +int init_rdstate(struct file *file);
8047 +struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex);
8048 +struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos);
8049 +void free_rdstate(struct unionfs_dir_state *state);
8050 +int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
8051 + int namelen, int bindex, int whiteout);
8052 +struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
8053 + const char *name, int namelen);
8054 +
8055 +struct dentry **alloc_new_dentries(int objs);
8056 +struct unionfs_data *alloc_new_data(int objs);
8057 +
8058 +/* We can only use 32-bits of offset for rdstate --- blech! */
8059 +#define DIREOF (0xfffff)
8060 +#define RDOFFBITS 20 /* This is the number of bits in DIREOF. */
8061 +#define MAXRDCOOKIE (0xfff)
8062 +/* Turn an rdstate into an offset. */
8063 +static inline off_t rdstate2offset(struct unionfs_dir_state *buf)
8064 +{
8065 + off_t tmp;
8066 + tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS)
8067 + | (buf->offset & DIREOF);
8068 + return tmp;
8069 +}
8070 +
8071 +#define unionfs_read_lock(sb) down_read(&UNIONFS_SB(sb)->rwsem)
8072 +#define unionfs_read_unlock(sb) up_read(&UNIONFS_SB(sb)->rwsem)
8073 +#define unionfs_write_lock(sb) down_write(&UNIONFS_SB(sb)->rwsem)
8074 +#define unionfs_write_unlock(sb) up_write(&UNIONFS_SB(sb)->rwsem)
8075 +
8076 +static inline void double_lock_dentry(struct dentry *d1, struct dentry *d2)
8077 +{
8078 + if (d2 < d1) {
8079 + struct dentry *tmp = d1;
8080 + d1 = d2;
8081 + d2 = tmp;
8082 + }
8083 + unionfs_lock_dentry(d1);
8084 + unionfs_lock_dentry(d2);
8085 +}
8086 +
8087 +extern int new_dentry_private_data(struct dentry *dentry);
8088 +void free_dentry_private_data(struct unionfs_dentry_info *udi);
8089 +void update_bstart(struct dentry *dentry);
8090 +
8091 +/*
8092 + * EXTERNALS:
8093 + */
8094 +
8095 +/* replicates the directory structure upto given dentry in given branch */
8096 +extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
8097 + int bindex);
8098 +
8099 +/* partial lookup */
8100 +extern int unionfs_partial_lookup(struct dentry *dentry);
8101 +
8102 +/* Pass an unionfs dentry and an index and it will try to create a whiteout
8103 + * in branch 'index'.
8104 + *
8105 + * On error, it will proceed to a branch to the left
8106 + */
8107 +extern int create_whiteout(struct dentry *dentry, int start);
8108 +/* copies a file from dbstart to newbindex branch */
8109 +extern int copyup_file(struct inode *dir, struct file *file, int bstart,
8110 + int newbindex, loff_t size);
8111 +extern int copyup_named_file(struct inode *dir, struct file *file,
8112 + char *name, int bstart, int new_bindex,
8113 + loff_t len);
8114 +/* copies a dentry from dbstart to newbindex branch */
8115 +extern int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart,
8116 + int new_bindex, struct file **copyup_file, loff_t len);
8117 +
8118 +extern int remove_whiteouts(struct dentry *dentry, struct dentry *hidden_dentry,
8119 + int bindex);
8120 +
8121 +extern int do_delete_whiteouts(struct dentry *dentry, int bindex,
8122 + struct unionfs_dir_state *namelist);
8123 +
8124 +extern int unionfs_get_nlinks(struct inode *inode);
8125 +
8126 +/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
8127 +extern int check_empty(struct dentry *dentry,
8128 + struct unionfs_dir_state **namelist);
8129 +/* Delete whiteouts from this directory in branch bindex. */
8130 +extern int delete_whiteouts(struct dentry *dentry, int bindex,
8131 + struct unionfs_dir_state *namelist);
8132 +
8133 +/* Re-lookup a hidden dentry. */
8134 +extern int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex);
8135 +
8136 +extern void unionfs_reinterpose(struct dentry *this_dentry);
8137 +extern struct super_block *unionfs_duplicate_super(struct super_block *sb);
8138 +
8139 +/* Locking functions. */
8140 +extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl);
8141 +extern int unionfs_getlk(struct file *file, struct file_lock *fl);
8142 +
8143 +/* Common file operations. */
8144 +extern int unionfs_file_revalidate(struct file *file, int willwrite);
8145 +extern int unionfs_open(struct inode *inode, struct file *file);
8146 +extern int unionfs_file_release(struct inode *inode, struct file *file);
8147 +extern int unionfs_flush(struct file *file, fl_owner_t id);
8148 +extern long unionfs_ioctl(struct file *file, unsigned int cmd,
8149 + unsigned long arg);
8150 +
8151 +/* Inode operations */
8152 +extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
8153 + struct inode *new_dir, struct dentry *new_dentry);
8154 +int unionfs_unlink(struct inode *dir, struct dentry *dentry);
8155 +int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
8156 +
8157 +int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata *nd);
8158 +
8159 +/* The values for unionfs_interpose's flag. */
8160 +#define INTERPOSE_DEFAULT 0
8161 +#define INTERPOSE_LOOKUP 1
8162 +#define INTERPOSE_REVAL 2
8163 +#define INTERPOSE_REVAL_NEG 3
8164 +#define INTERPOSE_PARTIAL 4
8165 +
8166 +extern int unionfs_interpose(struct dentry *this_dentry, struct super_block *sb,
8167 + int flag);
8168 +
8169 +/* Branch management ioctls. */
8170 +int unionfs_ioctl_incgen(struct file *file, unsigned int cmd,
8171 + unsigned long arg);
8172 +int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd,
8173 + unsigned long arg);
8174 +
8175 +#ifdef CONFIG_UNION_FS_XATTR
8176 +/* Extended attribute functions. */
8177 +extern void *unionfs_xattr_alloc(size_t size, size_t limit);
8178 +extern void unionfs_xattr_free(void *ptr, size_t size);
8179 +
8180 +extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
8181 + void *value, size_t size);
8182 +extern int unionfs_removexattr(struct dentry *dentry, const char *name);
8183 +extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
8184 + size_t size);
8185 +extern int unionfs_setxattr(struct dentry *dentry, const char *name,
8186 + const void *value, size_t size, int flags);
8187 +#endif /* CONFIG_UNION_FS_XATTR */
8188 +
8189 +/* The root directory is unhashed, but isn't deleted. */
8190 +static inline int d_deleted(struct dentry *d)
8191 +{
8192 + return d_unhashed(d) && (d != d->d_sb->s_root);
8193 +}
8194 +
8195 +struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *nd, int lookupmode);
8196 +
8197 +/* unionfs_permission, check if we should bypass error to facilitate copyup */
8198 +#define IS_COPYUP_ERR(err) ((err) == -EROFS)
8199 +
8200 +/* unionfs_open, check if we need to copyup the file */
8201 +#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND)
8202 +#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS)
8203 +
8204 +static inline int branchperms(const struct super_block *sb, int index)
8205 +{
8206 + BUG_ON(index < 0);
8207 +
8208 + return UNIONFS_SB(sb)->data[index].branchperms;
8209 +}
8210 +
8211 +static inline int set_branchperms(struct super_block *sb, int index, int perms)
8212 +{
8213 + BUG_ON(index < 0);
8214 +
8215 + UNIONFS_SB(sb)->data[index].branchperms = perms;
8216 +
8217 + return perms;
8218 +}
8219 +
8220 +/* Is this file on a read-only branch? */
8221 +static inline int is_robranch_super(const struct super_block *sb, int index)
8222 +{
8223 + int ret;
8224 + unionfs_read_lock(sb);
8225 + ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
8226 + unionfs_read_unlock(sb);
8227 + return ret;
8228 +}
8229 +
8230 +/* Is this file on a read-only branch? */
8231 +static inline int is_robranch_idx(const struct dentry *dentry, int index)
8232 +{
8233 + int err = 0;
8234 +
8235 + BUG_ON(index < 0);
8236 +
8237 + unionfs_read_lock(dentry->d_sb);
8238 + if ((!(branchperms(dentry->d_sb, index) & MAY_WRITE)) ||
8239 + IS_RDONLY(unionfs_lower_dentry_idx(dentry, index)->d_inode))
8240 + err = -EROFS;
8241 + unionfs_read_unlock(dentry->d_sb);
8242 + return err;
8243 +}
8244 +
8245 +static inline int is_robranch(const struct dentry *dentry)
8246 +{
8247 + int index;
8248 +
8249 + index = UNIONFS_D(dentry)->bstart;
8250 + BUG_ON(index < 0);
8251 +
8252 + return is_robranch_idx(dentry, index);
8253 +}
8254 +
8255 +/*
8256 + * Check if dentry is valid or not, as per our generation numbers.
8257 + * @dentry: dentry to check.
8258 + * Returns 1 (valid) or 0 (invalid/stale).
8259 + */
8260 +static inline int is_valid_dentry(struct dentry *dentry)
8261 +{
8262 + BUG_ON(!UNIONFS_D(dentry));
8263 + BUG_ON(!UNIONFS_SB(dentry->d_sb));
8264 + return (atomic_read(&UNIONFS_D(dentry)->generation) ==
8265 + atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
8266 +}
8267 +
8268 +/* What do we use for whiteouts. */
8269 +#define UNIONFS_WHPFX ".wh."
8270 +#define UNIONFS_WHLEN 4
8271 +/* If a directory contains this file, then it is opaque. We start with the
8272 + * .wh. flag so that it is blocked by lookup.
8273 + */
8274 +#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
8275 +#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME
8276 +
8277 +#ifndef DEFAULT_POLLMASK
8278 +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
8279 +#endif
8280 +
8281 +/*
8282 + * EXTERNALS:
8283 + */
8284 +extern char *alloc_whname(const char *name, int len);
8285 +extern int check_branch(struct nameidata *nd);
8286 +extern int __parse_branch_mode(const char *name);
8287 +extern int parse_branch_mode(const char *name);
8288 +
8289 +/* These two functions are here because it is kind of daft to copy and paste the
8290 + * contents of the two functions to 32+ places in unionfs
8291 + */
8292 +static inline struct dentry *lock_parent(struct dentry *dentry)
8293 +{
8294 + struct dentry *dir = dget(dentry->d_parent);
8295 +
8296 + mutex_lock(&dir->d_inode->i_mutex);
8297 + return dir;
8298 +}
8299 +
8300 +static inline void unlock_dir(struct dentry *dir)
8301 +{
8302 + mutex_unlock(&dir->d_inode->i_mutex);
8303 + dput(dir);
8304 +}
8305 +
8306 +extern int make_dir_opaque(struct dentry *dir, int bindex);
8307 +
8308 +static inline struct vfsmount *unionfs_mntget(struct dentry *dentry, int bindex)
8309 +{
8310 + struct vfsmount *mnt;
8311 + if (!dentry) {
8312 + if (bindex < 0)
8313 + return NULL;
8314 + BUG_ON(bindex < 0);
8315 + }
8316 + mnt = unionfs_lower_mnt_idx(dentry, bindex);
8317 + if (!mnt) {
8318 + if (bindex < 0)
8319 + return NULL;
8320 + BUG_ON(mnt && bindex < 0);
8321 + }
8322 + mnt = mntget(mnt);
8323 + return mnt;
8324 +}
8325 +
8326 +static inline void unionfs_mntput(struct dentry *dentry, int bindex)
8327 +{
8328 + struct vfsmount *mnt;
8329 + if (!dentry) {
8330 + if (bindex < 0)
8331 + return;
8332 + BUG_ON(dentry && bindex < 0);
8333 + }
8334 + mnt = unionfs_lower_mnt_idx(dentry, bindex);
8335 + if (!mnt) {
8336 + if (bindex < 0)
8337 + return;
8338 + BUG_ON(mnt && bindex < 0);
8339 + }
8340 + mntput(mnt);
8341 +}
8342 +#endif /* not _UNION_H_ */
8343 diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
8344 new file mode 100644
8345 index 0000000..dd1dd9c
8346 --- /dev/null
8347 +++ b/fs/unionfs/unlink.c
8348 @@ -0,0 +1,166 @@
8349 +/*
8350 + * Copyright (c) 2003-2007 Erez Zadok
8351 + * Copyright (c) 2003-2006 Charles P. Wright
8352 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
8353 + * Copyright (c) 2005-2006 Junjiro Okajima
8354 + * Copyright (c) 2005 Arun M. Krishnakumar
8355 + * Copyright (c) 2004-2006 David P. Quigley
8356 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
8357 + * Copyright (c) 2003 Puja Gupta
8358 + * Copyright (c) 2003 Harikesavan Krishnan
8359 + * Copyright (c) 2003-2007 Stony Brook University
8360 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York
8361 + *
8362 + * This program is free software; you can redistribute it and/or modify
8363 + * it under the terms of the GNU General Public License version 2 as
8364 + * published by the Free Software Foundation.
8365 + */
8366 +
8367 +#include "union.h"
8368 +
8369 +/* unlink a file by creating a whiteout */
8370 +static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
8371 +{
8372 + struct dentry *hidden_dentry;
8373 + struct dentry *hidden_dir_dentry;
8374 + int bindex;
8375 + int err = 0;
8376 +
8377 + if ((err = unionfs_partial_lookup(dentry)))
8378 + goto out;
8379 +
8380 + bindex = dbstart(dentry);
8381 +
8382 + hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
8383 + if (!hidden_dentry)
8384 + goto out;
8385 +
8386 + hidden_dir_dentry = lock_parent(hidden_dentry);
8387 +
8388 + /* avoid destroying the hidden inode if the file is in use */
8389 + dget(hidden_dentry);
8390 + if (!(err = is_robranch_super(dentry->d_sb, bindex)))
8391 + err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
8392 + dput(hidden_dentry);
8393 + fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
8394 + unlock_dir(hidden_dir_dentry);
8395 +
8396 + if (err && !IS_COPYUP_ERR(err))
8397 + goto out;
8398 +
8399 + if (err) {
8400 + if (dbstart(dentry) == 0)
8401 + goto out;
8402 +
8403 + err = create_whiteout(dentry, dbstart(dentry) - 1);
8404 + } else if (dbopaque(dentry) != -1)
8405 + /* There is a hidden lower-priority file with the same name. */
8406 + err = create_whiteout(dentry, dbopaque(dentry));
8407 + else
8408 + err = create_whiteout(dentry, dbstart(dentry));
8409 +
8410 +out:
8411 + if (!err)
8412 + dentry->d_inode->i_nlink--;
8413 +
8414 + /* We don't want to leave negative leftover dentries for revalidate. */
8415 + if (!err && (dbopaque(dentry) != -1))
8416 + update_bstart(dentry);
8417 +
8418 + return err;
8419 +}
8420 +
8421 +int unionfs_unlink(struct inode *dir, struct dentry *dentry)
8422 +{
8423 + int err = 0;
8424 +
8425 + BUG_ON(!is_valid_dentry(dentry));
8426 +
8427 + unionfs_lock_dentry(dentry);
8428 +
8429 + err = unionfs_unlink_whiteout(dir, dentry);
8430 + /* call d_drop so the system "forgets" about us */
8431 + if (!err)
8432 + d_drop(dentry);
8433 +
8434 + unionfs_unlock_dentry(dentry);
8435 + return err;
8436 +}
8437 +
8438 +static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
8439 + struct unionfs_dir_state *namelist)
8440 +{
8441 + int err;
8442 + struct dentry *hidden_dentry;
8443 + struct dentry *hidden_dir_dentry = NULL;
8444 +
8445 + /* Here we need to remove whiteout entries. */
8446 + err = delete_whiteouts(dentry, dbstart(dentry), namelist);
8447 + if (err)
8448 + goto out;
8449 +
8450 + hidden_dentry = unionfs_lower_dentry(dentry);
8451 +
8452 + hidden_dir_dentry = lock_parent(hidden_dentry);
8453 +
8454 + /* avoid destroying the hidden inode if the file is in use */
8455 + dget(hidden_dentry);
8456 + if (!(err = is_robranch(dentry)))
8457 + err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry);
8458 + dput(hidden_dentry);
8459 +
8460 + fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
8461 + /* propagate number of hard-links */
8462 + dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
8463 +
8464 +out:
8465 + if (hidden_dir_dentry)
8466 + unlock_dir(hidden_dir_dentry);
8467 + return err;
8468 +}
8469 +
8470 +int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
8471 +{
8472 + int err = 0;
8473 + struct unionfs_dir_state *namelist = NULL;
8474 +
8475 + BUG_ON(!is_valid_dentry(dentry));
8476 +
8477 + unionfs_lock_dentry(dentry);
8478 +
8479 + /* check if this unionfs directory is empty or not */
8480 + err = check_empty(dentry, &namelist);
8481 + if (err)
8482 + goto out;
8483 +
8484 + err = unionfs_rmdir_first(dir, dentry, namelist);
8485 + /* create whiteout */
8486 + if (!err)
8487 + err = create_whiteout(dentry, dbstart(dentry));
8488 + else {
8489 + int new_err;
8490 +
8491 + if (dbstart(dentry) == 0)
8492 + goto out;
8493 +
8494 + /* exit if the error returned was NOT -EROFS */
8495 + if (!IS_COPYUP_ERR(err))
8496 + goto out;
8497 +
8498 + new_err = create_whiteout(dentry, dbstart(dentry) - 1);
8499 + if (new_err != -EEXIST)
8500 + err = new_err;
8501 + }
8502 +
8503 +out:
8504 + /* call d_drop so the system "forgets" about us */
8505 + if (!err)
8506 + d_drop(dentry);
8507 +
8508 + if (namelist)
8509 + free_rdstate(namelist);
8510 +
8511 + unionfs_unlock_dentry(dentry);
8512 + return err;
8513 +}
8514 +
8515 diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
8516 new file mode 100644
8517 index 0000000..6e1f4bd
8518 --- /dev/null
8519 +++ b/fs/unionfs/xattr.c
8520 @@ -0,0 +1,131 @@
8521 +/*
8522 + * Copyright (c) 2003-2007 Erez Zadok
8523 + * Copyright (c) 2003-2006 Charles P. Wright
8524 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
8525 + * Copyright (c) 2005-2006 Junjiro Okajima
8526 + * Copyright (c) 2005 Arun M. Krishnakumar
8527 + * Copyright (c) 2004-2006 David P. Quigley
8528 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
8529 + * Copyright (c) 2003 Puja Gupta
8530 + * Copyright (c) 2003 Harikesavan Krishnan
8531 + * Copyright (c) 2003-2007 Stony Brook University
8532 + * Copyright (c) 2003-2007 The Research Foundation of State University of New York*
8533 + *
8534 + * This program is free software; you can redistribute it and/or modify
8535 + * it under the terms of the GNU General Public License version 2 as
8536 + * published by the Free Software Foundation.
8537 + */
8538 +
8539 +#include "union.h"
8540 +
8541 +/* This is lifted from fs/xattr.c */
8542 +void *unionfs_xattr_alloc(size_t size, size_t limit)
8543 +{
8544 + void *ptr;
8545 +
8546 + if (size > limit)
8547 + return ERR_PTR(-E2BIG);
8548 +
8549 + if (!size) /* size request, no buffer is needed */
8550 + return NULL;
8551 + else if (size <= PAGE_SIZE)
8552 + ptr = kmalloc(size, GFP_KERNEL);
8553 + else
8554 + ptr = vmalloc(size);
8555 + if (!ptr)
8556 + return ERR_PTR(-ENOMEM);
8557 + return ptr;
8558 +}
8559 +
8560 +void unionfs_xattr_free(void *ptr, size_t size)
8561 +{
8562 + if (!size) /* size request, no buffer was needed */
8563 + return;
8564 + else if (size <= PAGE_SIZE)
8565 + kfree(ptr);
8566 + else
8567 + vfree(ptr);
8568 +}
8569 +
8570 +/* BKL held by caller.
8571 + * dentry->d_inode->i_mutex locked
8572 + */
8573 +ssize_t unionfs_getxattr(struct dentry * dentry, const char *name, void *value,
8574 + size_t size)
8575 +{
8576 + struct dentry *hidden_dentry = NULL;
8577 + int err = -EOPNOTSUPP;
8578 +
8579 + BUG_ON(!is_valid_dentry(dentry));
8580 +
8581 + unionfs_lock_dentry(dentry);
8582 +
8583 + hidden_dentry = unionfs_lower_dentry(dentry);
8584 +
8585 + err = vfs_getxattr(hidden_dentry, (char*) name, value, size);
8586 +
8587 + unionfs_unlock_dentry(dentry);
8588 + return err;
8589 +}
8590 +
8591 +/* BKL held by caller.
8592 + * dentry->d_inode->i_mutex locked
8593 + */
8594 +int unionfs_setxattr(struct dentry *dentry, const char *name, const void *value,
8595 + size_t size, int flags)
8596 +{
8597 + struct dentry *hidden_dentry = NULL;
8598 + int err = -EOPNOTSUPP;
8599 +
8600 + BUG_ON(!is_valid_dentry(dentry));
8601 +
8602 + unionfs_lock_dentry(dentry);
8603 + hidden_dentry = unionfs_lower_dentry(dentry);
8604 +
8605 + err = vfs_setxattr(hidden_dentry, (char*) name, (void*) value, size, flags);
8606 +
8607 + unionfs_unlock_dentry(dentry);
8608 + return err;
8609 +}
8610 +
8611 +/* BKL held by caller.
8612 + * dentry->d_inode->i_mutex locked
8613 + */
8614 +int unionfs_removexattr(struct dentry *dentry, const char *name)
8615 +{
8616 + struct dentry *hidden_dentry = NULL;
8617 + int err = -EOPNOTSUPP;
8618 +
8619 + BUG_ON(!is_valid_dentry(dentry));
8620 +
8621 + unionfs_lock_dentry(dentry);
8622 + hidden_dentry = unionfs_lower_dentry(dentry);
8623 +
8624 + err = vfs_removexattr(hidden_dentry, (char*) name);
8625 +
8626 + unionfs_unlock_dentry(dentry);
8627 + return err;
8628 +}
8629 +
8630 +/* BKL held by caller.
8631 + * dentry->d_inode->i_mutex locked
8632 + */
8633 +ssize_t unionfs_listxattr(struct dentry * dentry, char *list, size_t size)
8634 +{
8635 + struct dentry *hidden_dentry = NULL;
8636 + int err = -EOPNOTSUPP;
8637 + char *encoded_list = NULL;
8638 +
8639 + BUG_ON(!is_valid_dentry(dentry));
8640 +
8641 + unionfs_lock_dentry(dentry);
8642 +
8643 + hidden_dentry = unionfs_lower_dentry(dentry);
8644 +
8645 + encoded_list = list;
8646 + err = vfs_listxattr(hidden_dentry, encoded_list, size);
8647 +
8648 + unionfs_unlock_dentry(dentry);
8649 + return err;
8650 +}
8651 +
8652 diff --git a/include/linux/magic.h b/include/linux/magic.h
8653 index a9c6567..a6751f6 100644
8654 --- a/include/linux/magic.h
8655 +++ b/include/linux/magic.h
8656 @@ -35,6 +35,8 @@
8657 #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
8658 #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
8659
8660 +#define UNIONFS_SUPER_MAGIC 0xf15f083d
8661 +
8662 #define SMB_SUPER_MAGIC 0x517B
8663 #define USBDEVICE_SUPER_MAGIC 0x9fa2
8664
8665 diff --git a/include/linux/mm.h b/include/linux/mm.h
8666 index 60e0e4a..c680669 100644
8667 --- a/include/linux/mm.h
8668 +++ b/include/linux/mm.h
8669 @@ -1157,6 +1157,7 @@ int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *,
8670 void __user *, size_t *, loff_t *);
8671 unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
8672 unsigned long lru_pages);
8673 +extern void drop_pagecache_sb(struct super_block *);
8674 void drop_pagecache(void);
8675 void drop_slab(void);
8676
8677 diff --git a/include/linux/namei.h b/include/linux/namei.h
8678 index d39a5a6..92b422b 100644
8679 --- a/include/linux/namei.h
8680 +++ b/include/linux/namei.h
8681 @@ -3,6 +3,7 @@
8682
8683 #include <linux/dcache.h>
8684 #include <linux/linkage.h>
8685 +#include <linux/mount.h>
8686
8687 struct vfsmount;
8688
8689 @@ -81,7 +82,15 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
8690 extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
8691 extern void release_open_intent(struct nameidata *);
8692
8693 -extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
8694 +extern struct dentry *lookup_one_len_nd(const char *,
8695 + struct dentry *, int, struct nameidata *);
8696 +
8697 +/* SMP-safe */
8698 +static inline struct dentry *lookup_one_len(const char *name,
8699 + struct dentry *dir, int len)
8700 +{
8701 + return lookup_one_len_nd(name, dir, len, NULL);
8702 +}
8703
8704 extern int follow_down(struct vfsmount **, struct dentry **);
8705 extern int follow_up(struct vfsmount **, struct dentry **);
8706 @@ -99,4 +108,16 @@ static inline char *nd_get_link(struct nameidata *nd)
8707 return nd->saved_names[nd->depth];
8708 }
8709
8710 +static inline void pathget(struct path *path)
8711 +{
8712 + mntget(path->mnt);
8713 + dget(path->dentry);
8714 +}
8715 +
8716 +static inline void pathput(struct path *path)
8717 +{
8718 + dput(path->dentry);
8719 + mntput(path->mnt);
8720 +}
8721 +
8722 #endif /* _LINUX_NAMEI_H */
8723 diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
8724 new file mode 100644
8725 index 0000000..b724031
8726 --- /dev/null
8727 +++ b/include/linux/union_fs.h
8728 @@ -0,0 +1,18 @@
8729 +#ifndef _LINUX_UNION_FS_H
8730 +#define _LINUX_UNION_FS_H
8731 +
8732 +#define UNIONFS_VERSION "2.0"
8733 +/*
8734 + * DEFINITIONS FOR USER AND KERNEL CODE:
8735 + */
8736 +# define UNIONFS_IOCTL_INCGEN _IOR(0x15, 11, int)
8737 +# define UNIONFS_IOCTL_QUERYFILE _IOR(0x15, 15, int)
8738 +
8739 +/* We don't support normal remount, but unionctl uses it. */
8740 +# define UNIONFS_REMOUNT_MAGIC 0x4a5a4380
8741 +
8742 +/* should be at least LAST_USED_UNIONFS_PERMISSION<<1 */
8743 +#define MAY_NFSRO 16
8744 +
8745 +#endif /* _LINUX_UNIONFS_H */
8746 +