Magellan Linux

Annotation of /trunk/kernel26-magellan/patches-2.6.21-r4/0153-2.6.21-unionfs-2.0-u2.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 222 - (hide annotations) (download)
Tue Jun 12 08:03:28 2007 UTC (16 years, 11 months ago) by niro
File size: 247073 byte(s)
files for 2.6.21-magellan-r4

1 niro 222 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     +