Unionfs: ensure consistent lower inodes types
authorRachita Kothiyal <rachita@dewey.fsl.cs.sunysb.edu>
Mon, 31 Mar 2008 19:46:51 +0000 (15:46 -0400)
committerRachita Kothiyal <rachita@dewey.fsl.cs.sunysb.edu>
Mon, 31 Mar 2008 19:46:51 +0000 (15:46 -0400)
When looking up a lower object in multiple branches, especially for
directories, ignore any existing entries whose type is different than the
type of the first found object (otherwise we'll be trying to, say, call
readdir on a non-dir inode).

Signed-off-by: Himanshu Kanda <hkanda@fsl.cs.sunysb.edu>
Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/lookup.c

index b5a390f8c5b22f728931fbf1742e04f28c1eb015..17e4f71603449f427d2d059fbdc4b8d1d5043767 100644 (file)
@@ -187,6 +187,20 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry,
                        continue;
                }
 
+               /*
+                * If we already found at least one positive dentry
+                * (dentry_count is non-zero), then we skip all remaining
+                * positive dentries if their type is a non-dir.  This is
+                * because only directories are allowed to stack on multiple
+                * branches, but we have to skip non-dirs (to avoid, say,
+                * calling readdir on a regular file).
+                */
+               if ((lookupmode != INTERPOSE_PARTIAL) &&
+                   !S_ISDIR(lower_dentry->d_inode->i_mode) && dentry_count) {
+                       dput(lower_dentry);
+                       continue;
+               }
+
                /* number of positive dentries */
                dentry_count++;
 
@@ -213,10 +227,6 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry,
                                continue;
                        if (dentry_count == 1)
                                goto out_positive;
-                       /* This can only happen with mixed D-*-F-* */
-                       BUG_ON(!S_ISDIR(unionfs_lower_dentry(dentry)->
-                                       d_inode->i_mode));
-                       continue;
                }
        }