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
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
