[RFC 22/26] union-mount: white-out changes for copy-on-open

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When files on an upper layer of the union stack are removed we need to
white-out the removed filename.

Signed-off-by: Jan Blunck <[email protected]>
---
 fs/namei.c |   46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2253,6 +2253,13 @@ do_last:
 
 	/* Negative dentry, just create the file */
 	if (!path.dentry->d_inode || S_ISWHT(path.dentry->d_inode->i_mode)) {
+		if (path.dentry->d_parent != dir) {
+			dput_path(&path, nd);
+			path.dentry = __lookup_hash_kern(&nd->last, dir, nd);
+			path.mnt = nd->mnt;
+			goto do_last;
+		}
+
 		error = open_namei_create(nd, &path, flag, mode);
 		if (error)
 			goto exit;
@@ -2373,6 +2380,16 @@ int lookup_create(struct nameidata *nd, 
 {
 	int err = -EEXIST;
 
+	if (is_unionized(nd->dentry, nd->mnt)) {
+		err = union_relookup_topmost(nd, nd->flags & ~LOOKUP_PARENT);
+		if (err) {
+			/* FIXME: This really sucks */
+			mutex_lock_nested(&nd->dentry->d_inode->i_mutex,
+					  I_MUTEX_PARENT);
+			goto fail;
+		}
+	}
+
 	mutex_lock_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT);
 	/*
 	 * Yucky last component or no last component at all?
@@ -2391,6 +2408,16 @@ int lookup_create(struct nameidata *nd, 
 	if (err)
 		goto fail;
 
+	/* Special case - we found a whiteout */
+	if (path->dentry->d_inode && S_ISWHT(path->dentry->d_inode->i_mode)) {
+		if (path->dentry->d_parent != nd->dentry) {
+			dput_path(path, nd);
+			path->dentry = __lookup_hash_kern(&nd->last, nd->dentry,
+							  nd);
+			path->mnt = nd->mnt;
+		}
+	}
+
 	/*
 	 * Special case - lookup gave negative, but... we had foo/bar/
 	 * From the vfs_mknod() POV we just have a negative dentry -
@@ -2682,6 +2709,15 @@ static int do_whiteout(struct nameidata 
 	if (isdir && !directory_is_empty(path->dentry, path->mnt))
 		goto out;
 
+	mutex_unlock(&nd->dentry->d_inode->i_mutex);
+	err = union_relookup_topmost(nd, nd->flags & ~LOOKUP_PARENT);
+	if (err) {
+		mutex_lock_nested(&nd->dentry->d_inode->i_mutex,
+				  I_MUTEX_PARENT);
+		goto out;
+	}
+	mutex_lock_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+
 	/* safe the name for a later lookup */
 	err = -ENOMEM;
 	name.name = kmalloc(dentry->d_name.len, GFP_KERNEL);
@@ -3012,7 +3048,10 @@ static long do_rmdir(int dfd, const char
 	error = hash_lookup_union(&nd, &nd.last, &path);
 	if (error)
 		goto exit2;
-	error = vfs_rmdir(nd.dentry->d_inode, path.dentry);
+	if (is_unionized(nd.dentry, nd.mnt))
+		error = do_whiteout(&nd, &path, 1);
+	else
+		error = vfs_rmdir(nd.dentry->d_inode, path.dentry);
 	dput_path(&path, &nd);
 exit2:
 	mutex_unlock(&nd.dentry->d_inode->i_mutex);
@@ -3091,7 +3130,10 @@ static long do_unlinkat(int dfd, const c
 		inode = path.dentry->d_inode;
 		if (inode)
 			atomic_inc(&inode->i_count);
-		error = vfs_unlink(nd.dentry->d_inode, path.dentry);
+		if (is_unionized(nd.dentry, nd.mnt))
+			error = do_whiteout(&nd, &path, 0);
+		else
+			error = vfs_unlink(nd.dentry->d_inode, path.dentry);
 	exit2:
 		dput_path(&path, &nd);
 	}

-- 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux