GIT: unionfs2-2.6.27.y: Unionfs: imported fixes from korg branch

Erez Zadok ezk at fsl.cs.sunysb.edu
Thu Aug 12 23:16:55 EDT 2010


commit 360e998d78ed79d3084f67341e203655a1c1dc10
Author: Erez_Zadok <ezk at cs.sunysb.edu>
Date:   Sat Aug 18 16:02:02 2007 -0400

    Unionfs: imported fixes from korg branch
    
    Export release_open_intent.
    SElinux: xattr fixes (CAP_FOWNER).
    unionfs_xattr_kfree inline function.
    alloc_lower_nd -> init_lower_nd.
    free_lower_nd -> release_lower_nd.
    unionfs_purge_extras -> unionfs_postcopyup_release.
    unionfs_inherit_mnt -> unionfs_postcopyup_setmnt.
    minor code/copyright cleanups.
    MS_SILENT remount fix.
    simplify unionfs_mntget/put.
    
    Signed-off-by: Erez Zadok <ezk at cs.sunysb.edu>

diff --git a/fs/namei.c b/fs/namei.c
index 832cd4b..86a3cab 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -393,6 +393,7 @@ void release_open_intent(struct nameidata *nd)
 	else
 		fput(nd->intent.open.file);
 }
+EXPORT_SYMBOL(release_open_intent);
 
 static inline struct dentry *
 do_revalidate(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index f13702d..86b1477 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -84,21 +84,27 @@ static int copyup_xattrs(struct dentry *old_lower_dentry,
 		/* Don't lock here since vfs_setxattr does it for us. */
 		err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
 				   size, 0);
+		/*
+		 * Selinux depends on "security.*" xattrs, so to maintain
+		 * the security of copied-up files, if Selinux is active,
+		 * then we must copy these xattrs as well.  So we need to
+		 * temporarily get FOWNER privileges.
+		 */
+		if (err == -EPERM && !capable(CAP_FOWNER)) {
+			cap_raise(current->cap_effective, CAP_FOWNER);
+			err = vfs_setxattr(new_lower_dentry, name_list,
+					   attr_value, size, 0);
+			cap_lower(current->cap_effective, CAP_FOWNER);
+		}
 		if (err < 0)
 			goto out;
 		name_list += strlen(name_list) + 1;
 	}
 out:
-	if (name_list_orig)
-		kfree(name_list_orig);
-	if (attr_value)
-		kfree(attr_value);
-	/*
-	 * Ignore if xattr isn't supported.  Also ignore EPERM because that
-	 * requires CAP_SYS_ADMIN for security.* xattrs, but copyup happens
-	 * as normal users.
-	 */
-	if (err == -ENOTSUPP || err == -EOPNOTSUPP || err == -EPERM)
+	unionfs_xattr_kfree(name_list_orig);
+	unionfs_xattr_kfree(attr_value);
+	/* Ignore if xattr isn't supported */
+	if (err == -ENOTSUPP || err == -EOPNOTSUPP)
 		err = 0;
 	return err;
 }
@@ -189,19 +195,18 @@ static int __copyup_ndentry(struct dentry *old_lower_dentry,
 		run_sioq(__unionfs_mknod, &args);
 		err = args.err;
 	} else if (S_ISREG(old_mode)) {
-		struct nameidata *nd = alloc_lower_nd(LOOKUP_CREATE);
-		if (!nd) {
-			err = -ENOMEM;
+		struct nameidata nd;
+		err = init_lower_nd(&nd, LOOKUP_CREATE);
+		if (err < 0)
 			goto out;
-		}
-		args.create.nd = nd;
+		args.create.nd = &nd;
 		args.create.parent = new_lower_parent_dentry->d_inode;
 		args.create.dentry = new_lower_dentry;
 		args.create.mode = old_mode;
 
 		run_sioq(__unionfs_create, &args);
 		err = args.err;
-		free_lower_nd(nd, err);
+		release_lower_nd(&nd, err);
 	} else {
 		printk(KERN_ERR "unionfs: unknown inode type %d\n",
 		       old_mode);
@@ -510,7 +515,7 @@ out_free:
 	if (err)
 		goto out;
 	if (!S_ISDIR(dentry->d_inode->i_mode)) {
-		unionfs_purge_extras(dentry);
+		unionfs_postcopyup_release(dentry);
 		if (!unionfs_lower_inode(dentry->d_inode)) {
 			/*
 			 * If we got here, then we copied up to an
@@ -523,7 +528,7 @@ out_free:
 						    inode);
 		}
 	}
-	unionfs_inherit_mnt(dentry);
+	unionfs_postcopyup_setmnt(dentry);
 	/* sync inode times from copied-up inode to our inode */
 	unionfs_copy_attr_times(dentry->d_inode);
 	unionfs_check_inode(dir);
@@ -837,8 +842,11 @@ out:
 	return lower_dentry;
 }
 
-/* set lower mnt of dentry+parents to the first parent node that has an mnt */
-void unionfs_inherit_mnt(struct dentry *dentry)
+/*
+ * Post-copyup helper to ensure we have valid mnts: set lower mnt of
+ * dentry+parents to the first parent node that has an mnt.
+ */
+void unionfs_postcopyup_setmnt(struct dentry *dentry)
 {
 	struct dentry *parent, *hasone;
 	int bindex = dbstart(dentry);
@@ -847,9 +855,8 @@ void unionfs_inherit_mnt(struct dentry *dentry)
 		return;
 	hasone = dentry->d_parent;
 	/* this loop should stop at root dentry */
-	while (!unionfs_lower_mnt_idx(hasone, bindex)) {
+	while (!unionfs_lower_mnt_idx(hasone, bindex))
 		hasone = hasone->d_parent;
-	}
 	parent = dentry;
 	while (!unionfs_lower_mnt_idx(parent, bindex)) {
 		unionfs_set_lower_mnt_idx(parent, bindex,
@@ -859,11 +866,10 @@ void unionfs_inherit_mnt(struct dentry *dentry)
 }
 
 /*
- * Regular files should have only one lower object(s).  On copyup, we may
- * have leftover objects from previous branches.  So purge all such extra
- * objects and keep only the most recent, leftmost, copied-up one.
+ * Post-copyup helper to release all non-directory source objects of a
+ * copied-up file.  Regular files should have only one lower object.
  */
-void unionfs_purge_extras(struct dentry *dentry)
+void unionfs_postcopyup_release(struct dentry *dentry)
 {
 	int bindex;
 
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 9e0801a..9adf272 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -223,7 +223,7 @@ out:
 	kfree(name);
 
 	if (!err)
-		unionfs_inherit_mnt(dentry);
+		unionfs_postcopyup_setmnt(dentry);
 	unionfs_unlock_dentry(dentry);
 	unionfs_read_unlock(dentry->d_sb);
 
@@ -412,7 +412,7 @@ out:
 
 	kfree(name);
 	if (!err)
-		unionfs_inherit_mnt(new_dentry);
+		unionfs_postcopyup_setmnt(new_dentry);
 
 	unionfs_unlock_dentry(new_dentry);
 	unionfs_unlock_dentry(old_dentry);
@@ -577,7 +577,7 @@ out:
 
 	kfree(name);
 	if (!err)
-		unionfs_inherit_mnt(dentry);
+		unionfs_postcopyup_setmnt(dentry);
 	unionfs_unlock_dentry(dentry);
 
 	unionfs_check_inode(dir);
@@ -856,7 +856,7 @@ out:
 	kfree(name);
 
 	if (!err)
-		unionfs_inherit_mnt(dentry);
+		unionfs_postcopyup_setmnt(dentry);
 	unionfs_unlock_dentry(dentry);
 
 	unionfs_check_inode(dir);
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index d8f2793..d36f097 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -568,16 +568,15 @@ void update_bstart(struct dentry *dentry)
 
 
 /*
- * Allocate and fill in a nameidata structure (the intent part) we can pass
- * to a lower file system.  Returns NULL on error (only -ENOMEM possible),
- * or a valid allocated nameidata structure.  Inside that structure, this
- * function may also return an allocated struct file (for open intents).
- * The caller, when done with this nd, must kfree both the intent file and
- * the entire nd.
+ * Initialize a nameidata structure (the intent part) we can pass to a lower
+ * file system.  Returns 0 on success or -error (only -ENOMEM possible).
+ * Inside that nd structure, this function may also return an allocated
+ * struct file (for open intents).  The caller, when done with this nd, must
+ * kfree the intent file (using release_lower_nd).
  */
-struct nameidata *alloc_lower_nd(unsigned int flags)
+int init_lower_nd(struct nameidata *nd, unsigned int flags)
 {
-	struct nameidata *nd;
+	int err = 0;
 #ifdef ALLOC_LOWER_ND_FILE
 	/*
 	 * XXX: one day we may need to have the lower return an open file
@@ -587,10 +586,6 @@ struct nameidata *alloc_lower_nd(unsigned int flags)
 	struct file *file;
 #endif /* ALLOC_LOWER_ND_FILE */
 
-	nd = kzalloc(sizeof(struct nameidata), GFP_KERNEL);
-	if (!nd)
-		goto out;
-
 	switch (flags) {
 	case LOOKUP_CREATE:
 		nd->flags = LOOKUP_CREATE;
@@ -598,9 +593,8 @@ struct nameidata *alloc_lower_nd(unsigned int flags)
 #ifdef ALLOC_LOWER_ND_FILE
 		file = kzalloc(sizeof(struct file), GFP_KERNEL);
 		if (!file) {
-			kfree(nd);
-			nd = NULL;
-			goto out;
+			err = -ENOMEM;
+			break; /* exit switch statement and thus return */
 		}
 		nd->intent.open.file = file;
 #endif /* ALLOC_LOWER_ND_FILE */
@@ -613,17 +607,15 @@ struct nameidata *alloc_lower_nd(unsigned int flags)
 		BUG();
 		break;
 	}
-out:
-	return nd;
+
+	return err;
 }
 
-void free_lower_nd(struct nameidata *nd, int err)
+void release_lower_nd(struct nameidata *nd, int err)
 {
-	if (nd->intent.open.file) {
-		if (!err)
-			fput(nd->intent.open.file); /* XXX: open file not needed? */
-		kfree(nd->intent.open.file);
-	}
-	kfree(nd);
+	if (nd->intent.open.file)
+		return;
+	if (!err)
+		release_open_intent(nd);
+	kfree(nd->intent.open.file);
 }
-
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index c96133b..58c2897 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -143,14 +143,15 @@ skip:
 		spliced = d_splice_alias(inode, dentry);
 		if (IS_ERR(spliced))
 			err = PTR_ERR(spliced);
-
-		/*
-		 * d_splice can return a dentry if it was disconnected and
-		 * had to be moved.  We must ensure that the private data of
-		 * the new dentry is correct and that the inode info was
-		 * filled properly.  Finally we must return this new dentry.
-		 */
 		else if (spliced && spliced != dentry) {
+			/*
+			 * d_splice can return a dentry if it was
+			 * disconnected and had to be moved.  We must ensure
+			 * that the private data of the new dentry is
+			 * correct and that the inode info was filled
+			 * properly.  Finally we must return this new
+			 * dentry.
+			 */
 			spliced->d_op = &unionfs_dops;
 			spliced->d_fsdata = dentry->d_fsdata;
 			dentry->d_fsdata = NULL;
diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index d6b0215..fcf5d7b 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -256,7 +256,7 @@ static int do_unionfs_rename(struct inode *old_dir,
 	 */
 	if ((old_bstart != old_bend) || (do_copyup != -1)) {
 		struct dentry *lower_parent;
-		struct nameidata *nd;
+		struct nameidata nd;
 		if (!wh_old || wh_old->d_inode || bwh_old < 0) {
 			printk(KERN_ERR "unionfs: rename error "
 			       "(wh_old=%p/%p bwh_old=%d)\n", wh_old,
@@ -264,14 +264,12 @@ static int do_unionfs_rename(struct inode *old_dir,
 			err = -EIO;
 			goto out;
 		}
-		nd = alloc_lower_nd(LOOKUP_CREATE);
-		if (!nd) {
-			err = -ENOMEM;
+		err = init_lower_nd(&nd, LOOKUP_CREATE);
+		if (err < 0)
 			goto out;
-		}
 		lower_parent = lock_parent(wh_old);
 		local_err = vfs_create(lower_parent->d_inode, wh_old, S_IRUGO,
-				       nd);
+				       &nd);
 		unlock_dir(lower_parent);
 		if (!local_err)
 			set_dbopaque(old_dentry, bwh_old);
@@ -284,7 +282,7 @@ static int do_unionfs_rename(struct inode *old_dir,
 			       "the source in rename!\n");
 			err = -EIO;
 		}
-		free_lower_nd(nd, local_err);
+		release_lower_nd(&nd, local_err);
 	}
 
 out:
@@ -486,11 +484,11 @@ out:
 		if (S_ISDIR(old_dentry->d_inode->i_mode))
 			atomic_dec(&UNIONFS_D(old_dentry)->generation);
 		else
-			unionfs_purge_extras(old_dentry);
+			unionfs_postcopyup_release(old_dentry);
 		if (new_dentry->d_inode &&
 		    !S_ISDIR(new_dentry->d_inode->i_mode)) {
-			unionfs_purge_extras(new_dentry);
-			unionfs_inherit_mnt(new_dentry);
+			unionfs_postcopyup_release(new_dentry);
+			unionfs_postcopyup_setmnt(new_dentry);
 			if (!unionfs_lower_inode(new_dentry->d_inode)) {
 				/*
 				 * If we get here, it means that no copyup
diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
index 478041d..ce17a8d 100644
--- a/fs/unionfs/sioq.c
+++ b/fs/unionfs/sioq.c
@@ -3,11 +3,7 @@
  * Copyright (c) 2003-2006 Charles P. Wright
  * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
  * Copyright (c) 2005-2006 Junjiro Okajima
- * Copyright (c) 2005      Arun M. Krishnakumar
  * Copyright (c) 2004-2006 David P. Quigley
- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
- * Copyright (c) 2003      Puja Gupta
- * Copyright (c) 2003      Harikesavan Krishnan
  * Copyright (c) 2003-2007 Stony Brook University
  * Copyright (c) 2003-2007 The Research Foundation of SUNY
  *
diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
index e180756..3521ed2 100644
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -3,11 +3,7 @@
  * Copyright (c) 2003-2006 Charles P. Wright
  * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
  * Copyright (c) 2005-2006 Junjiro Okajima
- * Copyright (c) 2005      Arun M. Krishnakumar
  * Copyright (c) 2004-2006 David P. Quigley
- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
- * Copyright (c) 2003      Puja Gupta
- * Copyright (c) 2003      Harikesavan Krishnan
  * Copyright (c) 2003-2007 Stony Brook University
  * Copyright (c) 2003-2007 The Research Foundation of SUNY
  *
diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c
index 3b76737..b7e7904 100644
--- a/fs/unionfs/subr.c
+++ b/fs/unionfs/subr.c
@@ -29,7 +29,7 @@ int create_whiteout(struct dentry *dentry, int start)
 	struct dentry *lower_dir_dentry;
 	struct dentry *lower_dentry;
 	struct dentry *lower_wh_dentry;
-	struct nameidata *nd;
+	struct nameidata nd;
 	char *name = NULL;
 	int err = -EINVAL;
 
@@ -83,20 +83,18 @@ int create_whiteout(struct dentry *dentry, int start)
 			goto out;
 		}
 
-		nd = alloc_lower_nd(LOOKUP_CREATE);
-		if (!nd) {
-			err = -ENOMEM;
+		err = init_lower_nd(&nd, LOOKUP_CREATE);
+		if (err < 0)
 			goto out;
-		}
 		lower_dir_dentry = lock_parent(lower_wh_dentry);
 		if (!(err = is_robranch_super(dentry->d_sb, bindex)))
 			err = vfs_create(lower_dir_dentry->d_inode,
 					 lower_wh_dentry,
 					 ~current->fs->umask & S_IRWXUGO,
-					 nd);
+					 &nd);
 		unlock_dir(lower_dir_dentry);
 		dput(lower_wh_dentry);
-		free_lower_nd(nd, err);
+		release_lower_nd(&nd, err);
 
 		if (!err || !IS_COPYUP_ERR(err))
 			break;
@@ -158,7 +156,7 @@ int make_dir_opaque(struct dentry *dentry, int bindex)
 	int err = 0;
 	struct dentry *lower_dentry, *diropq;
 	struct inode *lower_dir;
-	struct nameidata *nd;
+	struct nameidata nd;
 
 	lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
 	lower_dir = lower_dentry->d_inode;
@@ -173,16 +171,14 @@ int make_dir_opaque(struct dentry *dentry, int bindex)
 		goto out;
 	}
 
-	nd = alloc_lower_nd(LOOKUP_CREATE);
-	if (!nd) {
-		err = -ENOMEM;
+	err = init_lower_nd(&nd, LOOKUP_CREATE);
+	if (err < 0)
 		goto out;
-	}
 	if (!diropq->d_inode)
-		err = vfs_create(lower_dir, diropq, S_IRUGO, nd);
+		err = vfs_create(lower_dir, diropq, S_IRUGO, &nd);
 	if (!err)
 		set_dbopaque(dentry, bindex);
-	free_lower_nd(nd, err);
+	release_lower_nd(&nd, err);
 
 	dput(diropq);
 
diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
index 21a554a..3d9b7c7 100644
--- a/fs/unionfs/super.c
+++ b/fs/unionfs/super.c
@@ -448,11 +448,12 @@ static int unionfs_remount_fs(struct super_block *sb, int *flags,
 	unionfs_write_lock(sb);
 
 	/*
-	 * The VFS will take care of "ro" and "rw" flags, so anything else
-	 * is an error.  So we need to check if any other flags may have
-	 * been passed (none are allowed/supported as of now).
+	 * The VFS will take care of "ro" and "rw" flags, and we can safely
+	 * ignore MS_SILENT, but anything else left over is an error.  So we
+	 * need to check if any other flags may have been passed (none are
+	 * allowed/supported as of now).
 	 */
-	if ((*flags & ~MS_RDONLY) != 0) {
+	if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
 		printk(KERN_WARNING
 		       "unionfs: remount flags 0x%x unsupported\n", *flags);
 		err = -EINVAL;
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index eb881b0..1b11eab 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -251,8 +251,8 @@ static inline void unionfs_double_lock_dentry(struct dentry *d1,
 extern int new_dentry_private_data(struct dentry *dentry);
 extern void free_dentry_private_data(struct dentry *dentry);
 extern void update_bstart(struct dentry *dentry);
-extern struct nameidata *alloc_lower_nd(unsigned int flags);
-extern void free_lower_nd(struct nameidata *nd, int err);
+extern int init_lower_nd(struct nameidata *nd, unsigned int flags);
+extern void release_lower_nd(struct nameidata *nd, int err);
 
 /*
  * EXTERNALS:
@@ -283,9 +283,9 @@ extern int copyup_named_file(struct inode *dir, struct file *file,
 extern int copyup_dentry(struct inode *dir, struct dentry *dentry,
 			 int bstart, int new_bindex, const char *name,
 			 int namelen, struct file **copyup_file, loff_t len);
-/* helper functions for post-copyup cleanup */
-extern void unionfs_inherit_mnt(struct dentry *dentry);
-extern void unionfs_purge_extras(struct dentry *dentry);
+/* helper functions for post-copyup actions */
+extern void unionfs_postcopyup_setmnt(struct dentry *dentry);
+extern void unionfs_postcopyup_release(struct dentry *dentry);
 
 extern int remove_whiteouts(struct dentry *dentry,
 			    struct dentry *lower_dentry, int bindex);
@@ -344,7 +344,7 @@ extern struct dentry *unionfs_interpose(struct dentry *this_dentry,
 #ifdef CONFIG_UNION_FS_XATTR
 /* Extended attribute functions. */
 extern void *unionfs_xattr_alloc(size_t size, size_t limit);
-
+static inline void unionfs_xattr_kfree(const void *p) {kfree((p));}
 extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
 				void *value, size_t size);
 extern int unionfs_removexattr(struct dentry *dentry, const char *name);
@@ -460,32 +460,18 @@ static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
 {
 	struct vfsmount *mnt;
 
-	if (!dentry) {
-		if (bindex < 0)
-			return NULL;
-		if (!dentry && bindex >= 0) {
-#ifdef UNIONFS_DEBUG
-			printk(KERN_DEBUG
-			       "unionfs_mntget: dentry=%p bindex=%d\n",
-			       dentry, bindex);
-#endif /* UNIONFS_DEBUG */
-			return NULL;
-		}
-	}
+	BUG_ON(!dentry);
+	BUG_ON(bindex < 0);
+
 	mnt = unionfs_lower_mnt_idx(dentry, bindex);
-	if (!mnt) {
-		if (bindex < 0)
-			return NULL;
-		if (!mnt && bindex >= 0) {
+	if (mnt)
+		mnt = mntget(mnt);
 #ifdef UNIONFS_DEBUG
-			printk(KERN_DEBUG
-			       "unionfs_mntget: mnt=%p bindex=%d\n",
-			       mnt, bindex);
+	else
+		printk(KERN_DEBUG "unionfs_mntget: mnt=%p bindex=%d\n",
+		       mnt, bindex);
 #endif /* UNIONFS_DEBUG */
-			return NULL;
-		}
-	}
-	mnt = mntget(mnt);
+
 	return mnt;
 }
 
@@ -493,40 +479,28 @@ static inline void unionfs_mntput(struct dentry *dentry, int bindex)
 {
 	struct vfsmount *mnt;
 
-	if (!dentry) {
-		if (bindex < 0)
-			return;
-		if (!dentry && bindex >= 0) {
-#ifdef UNIONFS_DEBUG
-			printk(KERN_DEBUG
-			       "unionfs_mntput: dentry=%p bindex=%d\n",
-			       dentry, bindex);
-#endif /* UNIONFS_DEBUG */
-			return;
-		}
-	}
+	if (!dentry && bindex < 0)
+		return;
+	BUG_ON(!dentry);
+	BUG_ON(bindex < 0);
+
 	mnt = unionfs_lower_mnt_idx(dentry, bindex);
 	if (!mnt) {
-		if (bindex < 0)
-			return;
-		if (!mnt && bindex >= 0) {
 #ifdef UNIONFS_DEBUG
-			/*
-			 * Directories can have NULL lower objects in
-			 * between start/end, but NOT if at the start/end
-			 * range.  We cannot verify that this dentry is a
-			 * type=DIR, because it may already be a negative
-			 * dentry.  But if dbstart is greater than dbend, we
-			 * know that this couldn't have been a regular file:
-			 * it had to have been a directory.
-			 */
-			if (!(bindex > dbstart(dentry) && bindex < dbend(dentry)))
-				printk(KERN_WARNING
-				       "unionfs_mntput: mnt=%p bindex=%d\n",
-				       mnt, bindex);
+		/*
+		 * Directories can have NULL lower objects in between
+		 * start/end, but NOT if at the start/end range.  We cannot
+		 * verify that this dentry is a type=DIR, because it may
+		 * already be a negative dentry.  But if dbstart is greater
+		 * than dbend, we know that this couldn't have been a
+		 * regular file: it had to have been a directory.
+		 */
+		if (!(bindex > dbstart(dentry) && bindex < dbend(dentry)))
+			printk(KERN_WARNING
+			       "unionfs_mntput: mnt=%p bindex=%d\n",
+			       mnt, bindex);
 #endif /* UNIONFS_DEBUG */
-			return;
-		}
+		return;
 	}
 	mntput(mnt);
 }
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index 47bebab..4ea350a 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -89,7 +89,7 @@ int unionfs_unlink(struct inode *dir, struct dentry *dentry)
 	/* call d_drop so the system "forgets" about us */
 	if (!err) {
 		if (!S_ISDIR(dentry->d_inode->i_mode))
-			unionfs_purge_extras(dentry);
+			unionfs_postcopyup_release(dentry);
 		d_drop(dentry);
 		/*
 		 * if unlink/whiteout succeeded, parent dir mtime has


More information about the unionfs-cvs mailing list