Here's my optimization patch (quick and dirty, looks bigger than it is, most of it is changing indenting of already existing code within if() statements I added) w/ postmark numbers. I'm a little confused as now unionfs on backing store is faster than plain backing store (albiet not many test iterations and my methodology might be suspect, any thoughts?)

so what do I do.

1) anywhere we check for a whiteout (lookup.c or inode.c), we don't check for it if the bindex we are searching in is bend/bopaque as, a whiteout shouldn't exist there.

for lookup.c ( unionfs_lookup_backend() ) that is the major loop and basically skip whiteout search if bindex = bend

for inode.c, since we are only looking in bstart for the whiteout, its if bstart = bend (or opaque if < bend and != -1)

there's also some whiteout code in rename.c that I didn't get to yet (though probably have to).

I also addressed whiteout code in unlink.c, unionfs_unlink_whiteout() always created a whiteout, even in a case where there was nothing to whiteout. In those cases (I believe, didn't change any branching just changed a create_whiteout() to "goto out").

similarly for rmdir, one shouldn't create a whiteout if one doesn't have to.

and this is what I mean by having to change rename as it also probably creates whiteouts when it doesn't have to.

as can be seen from the attached pdf, the speedup in postmark is remarkable, though makes perfect sense. Also attaching the raw 1 run numbers

my postmark script

set size 512 10240
set number 20000
set transactions 200000
set subdirectories 200
set read 4096
set write 4096
set buffering false
show
run
quit
plain ext3
----------
Time:
        1610 seconds total
        1576 seconds of transactions (126 per second)

Files:
        120077 created (74 per second)
                Creation alone: 20000 files (1250 per second)
                Mixed with transactions: 100077 files (63 per second)
        100097 read (63 per second)
        99286 appended (62 per second)
        120077 deleted (74 per second)
                Deletion alone: 20154 files (1119 per second)
                Mixed with transactions: 99923 files (63 per second)

Data:
        649.43 megabytes read (413.05 kilobytes per second)
        782.03 megabytes written (497.39 kilobytes per second)
17.60user 43.65system 26:50.03elapsed 3%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+1913minor)pagefaults 0swaps

unionfs - ext3 - unopt
----------------------
Time:
        1788 seconds total
        1752 seconds of transactions (114 per second)

Files:
        120077 created (67 per second)
                Creation alone: 20000 files (10000 per second)
                Mixed with transactions: 100077 files (57 per second)
        100097 read (57 per second)
        99286 appended (56 per second)
        120077 deleted (67 per second)
                Deletion alone: 20154 files (592 per second)
                Mixed with transactions: 99923 files (57 per second)

Data:
        649.43 megabytes read (371.93 kilobytes per second)
        782.03 megabytes written (447.88 kilobytes per second)
18.12user 34.49system 29:50.53elapsed 2%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+1914minor)pagefaults 0swaps

unionfs - ext3 - opt
--------------------
Time:
        1427 seconds total
        1412 seconds of transactions (141 per second)

Files:
        120077 created (84 per second)
                Creation alone: 20000 files (4000 per second)
                Mixed with transactions: 100077 files (70 per second)
        100097 read (70 per second)
        99286 appended (70 per second)
        120077 deleted (84 per second)
                Deletion alone: 20154 files (2015 per second)
                Mixed with transactions: 99923 files (70 per second)

Data:
        649.43 megabytes read (466.02 kilobytes per second)
        782.03 megabytes written (561.18 kilobytes per second)
17.30user 36.69system 23:47.19elapsed 3%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+1913minor)pagefaults 0swaps


plain nfs
---------
Time:
        2054 seconds total
        1980 seconds of transactions (101 per second)

Files:
        120077 created (58 per second)
                Creation alone: 20000 files (625 per second)
                Mixed with transactions: 100077 files (50 per second)
        100097 read (50 per second)
        99286 appended (50 per second)
        120077 deleted (58 per second)
                Deletion alone: 20154 files (479 per second)
                Mixed with transactions: 99923 files (50 per second)

Data:
        649.43 megabytes read (323.77 kilobytes per second)
        782.03 megabytes written (389.87 kilobytes per second)
18.93user 31.92system 34:14.26elapsed 2%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+1913minor)pagefaults 0swaps

unionfs - nfs - unopt
---------------------
Time:
        2614 seconds total
        2485 seconds of transactions (80 per second)

Files:
        120077 created (45 per second)
                Creation alone: 20000 files (512 per second)
                Mixed with transactions: 100077 files (40 per second)
        100097 read (40 per second)
        99286 appended (39 per second)
        120077 deleted (45 per second)
                Deletion alone: 20154 files (223 per second)
                Mixed with transactions: 99923 files (40 per second)

Data:
        649.43 megabytes read (254.41 kilobytes per second)
        782.03 megabytes written (306.35 kilobytes per second)
18.82user 50.45system 44:24.07elapsed 2%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (1major+1912minor)pagefaults 0swaps

unionfs - nfs - opt
-------------------
econds total
        1846 seconds of transactions (108 per second)

Files:
        120077 created (63 per second)
                Creation alone: 20000 files (740 per second)
                Mixed with transactions: 100077 files (54 per second)
        100097 read (54 per second)
        99286 appended (53 per second)
        120077 deleted (63 per second)
                Deletion alone: 20154 files (746 per second)
                Mixed with transactions: 99923 files (54 per second)

Data:
        649.43 megabytes read (350.01 kilobytes per second)
        782.03 megabytes written (421.47 kilobytes per second)
18.94user 38.63system 31:41.13elapsed 3%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+1912minor)pagefaults 0swaps

Attachment: postmark.pdf
Description: Adobe PDF document

diff -rNup unionfs-1.5pre-cvs200701042308/inode.c 
unionfs-1.5pre-cvs200701042308.opt/inode.c
--- unionfs-1.5pre-cvs200701042308/inode.c      2007-01-04 23:09:48.000000000 
-0500
+++ unionfs-1.5pre-cvs200701042308.opt/inode.c  2007-01-12 02:25:01.000000000 
-0500
@@ -38,7 +38,7 @@ static int unionfs_create(struct inode *
        struct dentry *whiteout_dentry = NULL;
        struct dentry *new_hidden_dentry;
        struct dentry *hidden_parent_dentry = NULL;
-       int bindex = 0, bstart;
+       int bindex = 0, bstart, bend, bopaque;
        char *name = NULL;
 
        print_entry_location();
@@ -47,105 +47,112 @@ static int unionfs_create(struct inode *
 
        /* We start out in the leftmost branch. */
        bstart = dbstart(dentry);
+       bend = dbend(dentry);
+       bopaque = dbopaque(dentry);
        hidden_dentry = dtohd(dentry);
 
-       /* check if whiteout exists in this branch, i.e. lookup .wh.foo first */
-       name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-       if (IS_ERR(name)) {
-               err = PTR_ERR(name);
-               goto out;
-       }
+       if ((bopaque != -1) && (bopaque < bend))
+               bend = bopaque;
 
-       whiteout_dentry =
-           LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
-                          dentry->d_name.len + WHLEN);
-       if (IS_ERR(whiteout_dentry)) {
-               err = PTR_ERR(whiteout_dentry);
-               whiteout_dentry = NULL;
-               goto out;
-       }
+       if (bstart != bend) {
+               /* check if whiteout exists in this branch, i.e. lookup .wh.foo 
first */
+               name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+               if (IS_ERR(name)) {
+                       err = PTR_ERR(name);
+                       goto out;
+               }
 
-       if (whiteout_dentry->d_inode) {
-               /* .wh.foo has been found. */
-               /* First truncate it and then rename it to foo (hence having
-                * the same overall effect as a normal create.
-                *
-                * XXX: This is not strictly correct.  If we have unlinked the
-                * file and it still has a reference count, then we should
-                * actually unlink the whiteout so that user's data isn't
-                * hosed over.
-                */
-               struct dentry *hidden_dir_dentry;
-               struct iattr newattrs;
+               whiteout_dentry =
+                   LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
+                                  dentry->d_name.len + WHLEN);
+               if (IS_ERR(whiteout_dentry)) {
+                       err = PTR_ERR(whiteout_dentry);
+                       whiteout_dentry = NULL;
+                       goto out;
+               }
 
-               mutex_lock(&whiteout_dentry->d_inode->i_mutex);
-               newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME
-                   | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE
-                   | ATTR_KILL_SUID | ATTR_KILL_SGID;
+               if (whiteout_dentry->d_inode) {
+                       /* .wh.foo has been found. */
+                       /* First truncate it and then rename it to foo (hence 
having
+                        * the same overall effect as a normal create.
+                        *
+                        * XXX: This is not strictly correct.  If we have 
unlinked the
+                        * file and it still has a reference count, then we 
should
+                        * actually unlink the whiteout so that user's data 
isn't
+                        * hosed over.
+                        */
+                       struct dentry *hidden_dir_dentry;
+                       struct iattr newattrs;
 
-               newattrs.ia_mode = mode & ~current->fs->umask;
-               newattrs.ia_uid = current->fsuid;
-               newattrs.ia_gid = current->fsgid;
+                       mutex_lock(&whiteout_dentry->d_inode->i_mutex);
+                       newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME
+                           | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE
+                           | ATTR_KILL_SUID | ATTR_KILL_SGID;
 
-               if (whiteout_dentry->d_inode->i_size != 0) {
-                       newattrs.ia_valid |= ATTR_SIZE;
-                       newattrs.ia_size = 0;
-               }
+                       newattrs.ia_mode = mode & ~current->fs->umask;
+                       newattrs.ia_uid = current->fsuid;
+                       newattrs.ia_gid = current->fsgid;
 
-               err = notify_change(whiteout_dentry, &newattrs);
+                       if (whiteout_dentry->d_inode->i_size != 0) {
+                               newattrs.ia_valid |= ATTR_SIZE;
+                               newattrs.ia_size = 0;
+                       }
 
-               mutex_unlock(&whiteout_dentry->d_inode->i_mutex);
+                       err = notify_change(whiteout_dentry, &newattrs);
 
-               if (err)
-                       printk(KERN_WARNING
-                              "unionfs: %s:%d: notify_change failed: %d, 
ignoring..\n",
-                              __FILE__, __LINE__, err);
+                       mutex_unlock(&whiteout_dentry->d_inode->i_mutex);
 
-               new_hidden_dentry = dtohd(dentry);
-               DGET(new_hidden_dentry);
+                       if (err)
+                               printk(KERN_WARNING
+                                      "unionfs: %s:%d: notify_change failed: 
%d, ignoring..\n",
+                                      __FILE__, __LINE__, err);
 
-               hidden_dir_dentry = GET_PARENT(whiteout_dentry);
-               lock_rename(hidden_dir_dentry, hidden_dir_dentry);
+                       new_hidden_dentry = dtohd(dentry);
+                       DGET(new_hidden_dentry);
 
-               if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
-                       err =
-                           vfs_rename(hidden_dir_dentry->d_inode,
-                                      whiteout_dentry,
-                                      hidden_dir_dentry->d_inode,
-                                      new_hidden_dentry);
-               }
-               if (!err) {
-                       fist_copy_attr_timesizes(parent,
-                                                new_hidden_dentry->d_parent->
-                                                d_inode);
-                       parent->i_nlink = get_nlinks(parent);
-               }
+                       hidden_dir_dentry = GET_PARENT(whiteout_dentry);
+                       lock_rename(hidden_dir_dentry, hidden_dir_dentry);
 
-               unlock_rename(hidden_dir_dentry, hidden_dir_dentry);
-               DPUT(hidden_dir_dentry);
-
-               DPUT(new_hidden_dentry);
+                       if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
+                               err =
+                                   vfs_rename(hidden_dir_dentry->d_inode,
+                                              whiteout_dentry,
+                                              hidden_dir_dentry->d_inode,
+                                              new_hidden_dentry);
+                       }
+                       if (!err) {
+                               fist_copy_attr_timesizes(parent,
+                                                        
new_hidden_dentry->d_parent->
+                                                        d_inode);
+                               parent->i_nlink = get_nlinks(parent);
+                       }
 
-               if (err) {
-                       /* exit if the error returned was NOT -EROFS */
-                       if (!IS_COPYUP_ERR(err))
-                               goto out;
-                       /* We were not able to create the file in this branch,
-                        * so, we try to create it in one branch to left
-                        */
-                       bstart--;
-               } else {
-                       /* reset the unionfs dentry to point to the .wh.foo 
entry. */
+                       unlock_rename(hidden_dir_dentry, hidden_dir_dentry);
+                       DPUT(hidden_dir_dentry);
 
-                       /* Discard any old reference. */
-                       DPUT(dtohd(dentry));
+                       DPUT(new_hidden_dentry);
 
-                       /* Trade one reference to another. */
-                       set_dtohd_index(dentry, bstart, whiteout_dentry);
-                       whiteout_dentry = NULL;
+                       if (err) {
+                               /* exit if the error returned was NOT -EROFS */
+                               if (!IS_COPYUP_ERR(err))
+                                       goto out;
+                               /* We were not able to create the file in this 
branch,
+                                * so, we try to create it in one branch to left
+                                */
+                               bstart--;
+                       } else {
+                               /* reset the unionfs dentry to point to the 
.wh.foo entry. */
+
+                               /* Discard any old reference. */
+                               DPUT(dtohd(dentry));
+
+                               /* Trade one reference to another. */
+                               set_dtohd_index(dentry, bstart, 
whiteout_dentry);
+                               whiteout_dentry = NULL;
 
-                       err = unionfs_interpose(dentry, parent->i_sb, 0);
-                       goto out;
+                               err = unionfs_interpose(dentry, parent->i_sb, 
0);
+                               goto out;
+                       }
                }
        }
 
@@ -224,49 +231,58 @@ static int unionfs_link(struct dentry *o
        struct dentry *hidden_dir_dentry = NULL;
        struct dentry *whiteout_dentry;
        char *name = NULL;
+       int bstart, bend, bopaque;
 
        print_entry_location();
        double_lock_dentry(new_dentry, old_dentry);
 
        hidden_new_dentry = dtohd(new_dentry);
+       bstart = dbstart(new_dentry->d_parent);
+       bend = dbend(new_dentry->d_parent);
+       bopaque = dbopaque(new_dentry->d_parent);
+
+       if ((bopaque != -1) && (bopaque < bend))
+               bend = bopaque;
+
+       if (bstart != bend) {
+               /* check if whiteout exists in the branch of new dentry, i.e. 
lookup
+                * .wh.foo first. If present, delete it */
+               name = alloc_whname(new_dentry->d_name.name, 
new_dentry->d_name.len);
+               if (IS_ERR(name)) {
+                       err = PTR_ERR(name);
+                       goto out;
+               }
 
-       /* check if whiteout exists in the branch of new dentry, i.e. lookup
-        * .wh.foo first. If present, delete it */
-       name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len);
-       if (IS_ERR(name)) {
-               err = PTR_ERR(name);
-               goto out;
-       }
-
-       whiteout_dentry =
-           LOOKUP_ONE_LEN(name, hidden_new_dentry->d_parent,
-                          new_dentry->d_name.len + WHLEN);
-       if (IS_ERR(whiteout_dentry)) {
-               err = PTR_ERR(whiteout_dentry);
-               goto out;
-       }
+               whiteout_dentry =
+                   LOOKUP_ONE_LEN(name, hidden_new_dentry->d_parent,
+                                  new_dentry->d_name.len + WHLEN);
+               if (IS_ERR(whiteout_dentry)) {
+                       err = PTR_ERR(whiteout_dentry);
+                       goto out;
+               }
 
-       if (!whiteout_dentry->d_inode) {
-               DPUT(whiteout_dentry);
-               whiteout_dentry = NULL;
-       } else {
-               /* found a .wh.foo entry, unlink it and then call vfs_link() */
-               hidden_dir_dentry = lock_parent(whiteout_dentry);
-               if (!
-                   (err =
-                    is_robranch_super(new_dentry->d_sb,
-                                      dbstart(new_dentry)))) {
-                       err =
-                           vfs_unlink(hidden_dir_dentry->d_inode,
-                                      whiteout_dentry);
+               if (!whiteout_dentry->d_inode) {
+                       DPUT(whiteout_dentry);
+                       whiteout_dentry = NULL;
+               } else {
+                       /* found a .wh.foo entry, unlink it and then call 
vfs_link() */
+                       hidden_dir_dentry = lock_parent(whiteout_dentry);
+                       if (!
+                           (err =
+                            is_robranch_super(new_dentry->d_sb,
+                                              dbstart(new_dentry)))) {
+                               err =
+                                   vfs_unlink(hidden_dir_dentry->d_inode,
+                                              whiteout_dentry);
+                       }
+                       fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+                       dir->i_nlink = get_nlinks(dir);
+                       unlock_dir(hidden_dir_dentry);
+                       hidden_dir_dentry = NULL;
+                       DPUT(whiteout_dentry);
+                       if (err)
+                               goto out;
                }
-               fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);
-               dir->i_nlink = get_nlinks(dir);
-               unlock_dir(hidden_dir_dentry);
-               hidden_dir_dentry = NULL;
-               DPUT(whiteout_dentry);
-               if (err)
-                       goto out;
        }
 
        if (dbstart(old_dentry) != dbstart(new_dentry)) {
@@ -349,7 +365,7 @@ static int unionfs_symlink(struct inode 
        struct dentry *whiteout_dentry = NULL;
        struct dentry *hidden_dir_dentry = NULL;
        umode_t mode;
-       int bindex = 0, bstart;
+       int bindex = 0, bstart, bend, bopaque;
        char *name = NULL;
 
        print_entry_location();
@@ -358,53 +374,60 @@ static int unionfs_symlink(struct inode 
 
        /* We start out in the leftmost branch. */
        bstart = dbstart(dentry);
+       bend = dbend(dentry);
+       bopaque = dbopaque(dentry);
+
+       if ((bopaque != -1) && (bopaque < bend))
+               bend = bopaque;
 
        hidden_dentry = dtohd(dentry);
 
-       /* check if whiteout exists in this branch, i.e. lookup .wh.foo first. 
If present, delete it */
-       name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-       if (IS_ERR(name)) {
-               err = PTR_ERR(name);
-               goto out;
-       }
+       if (bstart != bend) {
+               /* check if whiteout exists in this branch, i.e. lookup .wh.foo 
first. If present, delete it */
+               name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+               if (IS_ERR(name)) {
+                       err = PTR_ERR(name);
+                       goto out;
+               }
 
-       whiteout_dentry =
-           LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
-                          dentry->d_name.len + WHLEN);
-       if (IS_ERR(whiteout_dentry)) {
-               err = PTR_ERR(whiteout_dentry);
-               goto out;
-       }
+               whiteout_dentry =
+                   LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
+                                  dentry->d_name.len + WHLEN);
+               if (IS_ERR(whiteout_dentry)) {
+                       err = PTR_ERR(whiteout_dentry);
+                       goto out;
+               }
 
-       if (!whiteout_dentry->d_inode) {
-               DPUT(whiteout_dentry);
-               whiteout_dentry = NULL;
-       } else {
-               /* found a .wh.foo entry, unlink it and then call vfs_symlink() 
*/
-               hidden_dir_dentry = lock_parent(whiteout_dentry);
+               if (!whiteout_dentry->d_inode) {
+                       DPUT(whiteout_dentry);
+                       whiteout_dentry = NULL;
+               } else {
+                       /* found a .wh.foo entry, unlink it and then call 
vfs_symlink() */
+                       hidden_dir_dentry = lock_parent(whiteout_dentry);
 
-               print_dentry("HDD", hidden_dir_dentry);
-               print_dentry("WD", whiteout_dentry);
+                       print_dentry("HDD", hidden_dir_dentry);
+                       print_dentry("WD", whiteout_dentry);
 
-               if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
-                       err =
-                           vfs_unlink(hidden_dir_dentry->d_inode,
-                                      whiteout_dentry);
-               }
-               DPUT(whiteout_dentry);
+                       if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
+                               err =
+                                   vfs_unlink(hidden_dir_dentry->d_inode,
+                                              whiteout_dentry);
+                       }
+                       DPUT(whiteout_dentry);
 
-               fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);
-               /* propagate number of hard-links */
-               dir->i_nlink = get_nlinks(dir);
+                       fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+                       /* propagate number of hard-links */
+                       dir->i_nlink = get_nlinks(dir);
 
-               unlock_dir(hidden_dir_dentry);
+                       unlock_dir(hidden_dir_dentry);
 
-               if (err) {
-                       /* exit if the error returned was NOT -EROFS */
-                       if (!IS_COPYUP_ERR(err))
-                               goto out;
-                       /* should now try to create symlink in the another 
branch */
-                       bstart--;
+                       if (err) {
+                               /* exit if the error returned was NOT -EROFS */
+                               if (!IS_COPYUP_ERR(err))
+                                       goto out;
+                               /* should now try to create symlink in the 
another branch */
+                               bstart--;
+                       }
                }
        }
 
@@ -472,7 +495,7 @@ static int unionfs_mkdir(struct inode *p
        int err = 0;
        struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
        struct dentry *hidden_parent_dentry = NULL;
-       int bindex = 0, bstart;
+       int bindex = 0, bstart, bend, bopaque;
        char *name = NULL;
        int whiteout_unlinked = 0;
        struct sioq_args args;
@@ -481,48 +504,55 @@ static int unionfs_mkdir(struct inode *p
        lock_dentry(dentry);
        print_dentry("IN unionfs_mkdir", dentry);
        bstart = dbstart(dentry);
+       bend = dbend(dentry);
+       bopaque = dbopaque(dentry);
+
+       if ((bopaque != -1) && (bopaque < bend))
+               bend = bopaque;
 
        hidden_dentry = dtohd(dentry);
 
-       // check if whiteout exists in this branch, i.e. lookup .wh.foo first
-       name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-       if (IS_ERR(name)) {
-               err = PTR_ERR(name);
-               goto out;
-       }
+       if (bstart != bend) {
+               // check if whiteout exists in this branch, i.e. lookup .wh.foo 
first
+               name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+               if (IS_ERR(name)) {
+                       err = PTR_ERR(name);
+                       goto out;
+               }
 
-       whiteout_dentry =
-           LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
-                          dentry->d_name.len + WHLEN);
-       if (IS_ERR(whiteout_dentry)) {
-               err = PTR_ERR(whiteout_dentry);
-               goto out;
-       }
+               whiteout_dentry =
+                   LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
+                                  dentry->d_name.len + WHLEN);
+               if (IS_ERR(whiteout_dentry)) {
+                       err = PTR_ERR(whiteout_dentry);
+                       goto out;
+               }
 
-       if (!whiteout_dentry->d_inode) {
-               DPUT(whiteout_dentry);
-               whiteout_dentry = NULL;
-       } else {
-               hidden_parent_dentry = lock_parent(whiteout_dentry);
+               if (!whiteout_dentry->d_inode) {
+                       DPUT(whiteout_dentry);
+                       whiteout_dentry = NULL;
+               } else {
+                       hidden_parent_dentry = lock_parent(whiteout_dentry);
 
-               //found a.wh.foo entry, remove it then do vfs_mkdir
-               if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
-                       args.unlink.parent = hidden_parent_dentry->d_inode;
-                       args.unlink.dentry = whiteout_dentry;
-                       run_sioq(__unionfs_unlink, &args);
-                       err = args.err;
-               }
-               DPUT(whiteout_dentry);
+                       //found a.wh.foo entry, remove it then do vfs_mkdir
+                       if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
+                               args.unlink.parent = 
hidden_parent_dentry->d_inode;
+                               args.unlink.dentry = whiteout_dentry;
+                               run_sioq(__unionfs_unlink, &args);
+                               err = args.err;
+                       }
+                       DPUT(whiteout_dentry);
 
-               unlock_dir(hidden_parent_dentry);
+                       unlock_dir(hidden_parent_dentry);
 
-               if (err) {
-                       /* exit if the error returned was NOT -EROFS */
-                       if (!IS_COPYUP_ERR(err))
-                               goto out;
-                       bstart--;
-               } else {
-                       whiteout_unlinked = 1;
+                       if (err) {
+                               /* exit if the error returned was NOT -EROFS */
+                               if (!IS_COPYUP_ERR(err))
+                                       goto out;
+                               bstart--;
+                       } else {
+                               whiteout_unlinked = 1;
+                       }
                }
        }
 
@@ -606,7 +636,7 @@ static int unionfs_mknod(struct inode *d
        int err = 0;
        struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
        struct dentry *hidden_parent_dentry = NULL;
-       int bindex = 0, bstart;
+       int bindex = 0, bstart, bend, bopaque;
        char *name = NULL;
        int whiteout_unlinked = 0;
 
@@ -614,46 +644,53 @@ static int unionfs_mknod(struct inode *d
        lock_dentry(dentry);
        print_dentry("IN unionfs_mknod", dentry);
        bstart = dbstart(dentry);
+       bend = dbend(dentry);
+       bopaque = dbopaque(dentry);
+
+       if ((bopaque != -1) && (bopaque < bend))
+               bend = bopaque;
 
        hidden_dentry = dtohd(dentry);
 
-       // check if whiteout exists in this branch, i.e. lookup .wh.foo first
-       name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-       if (IS_ERR(name)) {
-               err = PTR_ERR(name);
-               goto out;
-       }
+       if (bstart != bend) {
+               // check if whiteout exists in this branch, i.e. lookup .wh.foo 
first
+               name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+               if (IS_ERR(name)) {
+                       err = PTR_ERR(name);
+                       goto out;
+               }
 
-       whiteout_dentry =
-           LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
-                          dentry->d_name.len + WHLEN);
-       if (IS_ERR(whiteout_dentry)) {
-               err = PTR_ERR(whiteout_dentry);
-               goto out;
-       }
+               whiteout_dentry =
+                   LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
+                                  dentry->d_name.len + WHLEN);
+               if (IS_ERR(whiteout_dentry)) {
+                       err = PTR_ERR(whiteout_dentry);
+                       goto out;
+               }
 
-       if (!whiteout_dentry->d_inode) {
-               DPUT(whiteout_dentry);
-               whiteout_dentry = NULL;
-       } else {
-               /* found .wh.foo, unlink it */
-               hidden_parent_dentry = lock_parent(whiteout_dentry);
+               if (!whiteout_dentry->d_inode) {
+                       DPUT(whiteout_dentry);
+                       whiteout_dentry = NULL;
+               } else {
+                       /* found .wh.foo, unlink it */
+                       hidden_parent_dentry = lock_parent(whiteout_dentry);
 
-               //found a.wh.foo entry, remove it then do vfs_mkdir
-               if (!(err = is_robranch_super(dentry->d_sb, bstart)))
-                       err = vfs_unlink(hidden_parent_dentry->d_inode,
-                                        whiteout_dentry);
-               DPUT(whiteout_dentry);
+                       //found a.wh.foo entry, remove it then do vfs_mkdir
+                       if (!(err = is_robranch_super(dentry->d_sb, bstart)))
+                               err = vfs_unlink(hidden_parent_dentry->d_inode,
+                                                whiteout_dentry);
+                       DPUT(whiteout_dentry);
 
-               unlock_dir(hidden_parent_dentry);
+                       unlock_dir(hidden_parent_dentry);
 
-               if (err) {
-                       if (!IS_COPYUP_ERR(err))
-                               goto out;
+                       if (err) {
+                               if (!IS_COPYUP_ERR(err))
+                                       goto out;
 
-                       bstart--;
-               } else {
-                       whiteout_unlinked = 1;
+                               bstart--;
+                       } else {
+                               whiteout_unlinked = 1;
+                       }
                }
        }
 
Binary files unionfs-1.5pre-cvs200701042308/.inode.c.swp and 
unionfs-1.5pre-cvs200701042308.opt/.inode.c.swp differ
diff -rNup unionfs-1.5pre-cvs200701042308/lookup.c 
unionfs-1.5pre-cvs200701042308.opt/lookup.c
--- unionfs-1.5pre-cvs200701042308/lookup.c     2007-01-04 23:09:48.000000000 
-0500
+++ unionfs-1.5pre-cvs200701042308.opt/lookup.c 2007-01-12 02:03:46.000000000 
-0500
@@ -101,6 +101,7 @@ struct dentry *unionfs_lookup_backend(st
        }
 
        dprint(PRINT_DEBUG, "bstart = %d, bend = %d\n", bstart, bend);
+
        for (bindex = bstart; bindex <= bend; bindex++) {
                hidden_dentry = dtohd_index(dentry, bindex);
                if (lookupmode == INTERPOSE_PARTIAL && hidden_dentry)
@@ -117,44 +118,47 @@ struct dentry *unionfs_lookup_backend(st
                if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode))
                        continue;
 
-               /* Reuse the whiteout name because its value doesn't change. */
-               if (!whname) {
-                       whname = alloc_whname(name, namelen);
-                       if (IS_ERR(whname)) {
-                               err = PTR_ERR(whname);
-                               goto out_free;
+               if (bindex != bend) {
+
+                       /* Reuse the whiteout name because its value doesn't 
change. */
+                       if (!whname) {
+                               whname = alloc_whname(name, namelen);
+                               if (IS_ERR(whname)) {
+                                       err = PTR_ERR(whname);
+                                       goto out_free;
+                               }
                        }
-               }
 
-               /* check if whiteout exists in this branch: lookup .wh.foo */
-               wh_hidden_dentry = LOOKUP_ONE_LEN(whname, hidden_dir_dentry,
-                                                 namelen + WHLEN);
-               if (IS_ERR(wh_hidden_dentry)) {
-                       DPUT(first_hidden_dentry);
-                       err = PTR_ERR(wh_hidden_dentry);
-                       goto out_free;
-               }
+                       /* check if whiteout exists in this branch: lookup 
.wh.foo */
+                       wh_hidden_dentry = LOOKUP_ONE_LEN(whname, 
hidden_dir_dentry,
+                                                         namelen + WHLEN);
+                       if (IS_ERR(wh_hidden_dentry)) {
+                               DPUT(first_hidden_dentry);
+                               err = PTR_ERR(wh_hidden_dentry);
+                               goto out_free;
+                       }
 
-               if (wh_hidden_dentry->d_inode) {
-                       /* We found a whiteout so lets give up. */
-                       dprint(PRINT_DEBUG, "whiteout found in %d\n", bindex);
-                       if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) {
-                               set_dbend(dentry, bindex);
-                               set_dbopaque(dentry, bindex);
+                       if (wh_hidden_dentry->d_inode) {
+                               /* We found a whiteout so lets give up. */
+                               dprint(PRINT_DEBUG, "whiteout found in %d\n", 
bindex);
+                               if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) 
{
+                                       set_dbend(dentry, bindex);
+                                       set_dbopaque(dentry, bindex);
+                                       DPUT(wh_hidden_dentry);
+                                       break;
+                               }
+                               err = -EIO;
+                               printk(KERN_NOTICE "EIO: Invalid whiteout entry 
type"
+                              " %d.\n", wh_hidden_dentry->d_inode->i_mode);
                                DPUT(wh_hidden_dentry);
-                               break;
+                               DPUT(first_hidden_dentry);
+                               goto out_free;
                        }
-                       err = -EIO;
-                       printk(KERN_NOTICE "EIO: Invalid whiteout entry type"
-                              " %d.\n", wh_hidden_dentry->d_inode->i_mode);
+
                        DPUT(wh_hidden_dentry);
-                       DPUT(first_hidden_dentry);
-                       goto out_free;
+                       wh_hidden_dentry = NULL;
                }
 
-               DPUT(wh_hidden_dentry);
-               wh_hidden_dentry = NULL;
-
                /* Now do regular lookup; lookup foo */
                hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry,
                                               namelen);
diff -rNup unionfs-1.5pre-cvs200701042308/unlink.c 
unionfs-1.5pre-cvs200701042308.opt/unlink.c
--- unionfs-1.5pre-cvs200701042308/unlink.c     2007-01-04 23:09:48.000000000 
-0500
+++ unionfs-1.5pre-cvs200701042308.opt/unlink.c 2007-01-12 03:30:34.000000000 
-0500
@@ -127,7 +127,7 @@ static int unionfs_unlink_whiteout(struc
                goto out;
 
        if (err) {
-               if (dbstart(dentry) == 0)
+               if ((dbstart(dentry) == 0) || (dbstart(dentry) == 
dbopaque(dentry)))
                        goto out;
 
                err = create_whiteout(dentry, dbstart(dentry) - 1);
@@ -329,6 +329,8 @@ int unionfs_rmdir(struct inode *dir, str
                err = unionfs_rmdir_first(dir, dentry, namelist);
                /* create whiteout */
                if (!err) {
+                       if ((dbstart(dentry) == 0) || (dbstart(dentry) == 
dbopaque(dentry)))
+                               goto out;
                        err = create_whiteout(dentry, dbstart(dentry));
                } else {
                        int new_err;
_______________________________________________
unionfs mailing list
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs

Reply via email to