head	1.1;
access;
symbols
	LKML-branch:1.1.0.2;
locks; strict;
comment	@# @;


1.1
date	2006.10.24.06.14.17;	author jsipek;	state dead;
branches
	1.1.2.1;
next	;

1.1.2.1
date	2006.10.24.06.14.17;	author jsipek;	state Exp;
branches;
next	1.1.2.2;

1.1.2.2
date	2006.11.07.06.13.33;	author jsipek;	state Exp;
branches;
next	1.1.2.3;

1.1.2.3
date	2006.12.01.02.28.38;	author jsipek;	state Exp;
branches;
next	1.1.2.4;

1.1.2.4
date	2006.12.01.02.36.12;	author jsipek;	state Exp;
branches;
next	1.1.2.5;

1.1.2.5
date	2006.12.03.21.49.41;	author jsipek;	state Exp;
branches;
next	1.1.2.6;

1.1.2.6
date	2006.12.11.14.23.59;	author jsipek;	state Exp;
branches;
next	1.1.2.7;

1.1.2.7
date	2007.01.21.23.59.13;	author jsipek;	state Exp;
branches;
next	;


desc
@@


1.1
log
@file unlink was initially added on branch LKML-branch.
@
text
@@


1.1.2.1
log
@Move unionfs specific bits into a subdir
@
text
@a0 192
Unionfs: Unlink

From: Josef "Jeff" Sipek <jsipek@@cs.sunysb.edu>

This patch provides unlink functionality for Unionfs.

Signed-off-by: Josef "Jeff" Sipek <jsipek@@cs.sunysb.edu>
Signed-off-by: David Quigley <dquigley@@fsl.cs.sunysb.edu>
Signed-off-by: Erez Zadok <ezk@@cs.sunysb.edu>

diff -r bd3a2c05a931 fs/unionfs/unlink.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fs/unionfs/unlink.c	Sat Sep 23 02:53:18 2006 -0400
@@@@ -0,0 +1,178 @@@@
+/*
+ * Copyright (c) 2003-2006 Erez Zadok
+ * Copyright (c) 2003-2006 Charles P. Wright
+ * Copyright (c) 2005-2006 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-2006 Stony Brook University
+ * Copyright (c) 2003-2006 The Research Foundation of State University of New York
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "union.h"
+
+static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
+{
+	struct dentry *hidden_dentry;
+	struct dentry *hidden_dir_dentry;
+	int bindex;
+	int err = 0;
+
+	if ((err = unionfs_partial_lookup(dentry)))
+		goto out;
+
+	bindex = dbstart(dentry);
+
+	hidden_dentry = dtohd_index(dentry, bindex);
+	if (!hidden_dentry)
+		goto out;
+
+	hidden_dir_dentry = lock_parent(hidden_dentry);
+
+	/* avoid destroying the hidden inode if the file is in use */
+	dget(hidden_dentry);
+	if (!(err = is_robranch_super(dentry->d_sb, bindex)))
+		err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
+	dput(hidden_dentry);
+	fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+	unlock_dir(hidden_dir_dentry);
+
+	if (err && !IS_COPYUP_ERR(err))
+		goto out;
+
+	if (err) {
+		if (dbstart(dentry) == 0)
+			goto out;
+
+		err = create_whiteout(dentry, dbstart(dentry) - 1);
+	} else if (dbopaque(dentry) != -1) {
+		/* There is a hidden lower-priority file with the same name. */
+		err = create_whiteout(dentry, dbopaque(dentry));
+	} else {
+		err = create_whiteout(dentry, dbstart(dentry));
+	}
+
+out:
+	if (!err)
+		dentry->d_inode->i_nlink--;
+
+	/* We don't want to leave negative leftover dentries for revalidate. */
+	if (!err && (dbopaque(dentry) != -1))
+		update_bstart(dentry);
+
+	return err;
+}
+
+int unionfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int err = 0;
+
+	lock_dentry(dentry);
+
+	err = unionfs_unlink_whiteout(dir, dentry);
+	/* call d_drop so the system "forgets" about us */
+	if (!err)
+		d_drop(dentry);
+
+	unlock_dentry(dentry);
+	return err;
+}
+
+static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
+			       struct unionfs_dir_state *namelist)
+{
+	int err;
+	struct dentry *hidden_dentry;
+	struct dentry *hidden_dir_dentry = NULL;
+
+	/* Here we need to remove whiteout entries. */
+	err = delete_whiteouts(dentry, dbstart(dentry), namelist);
+	if (err) {
+		goto out;
+	}
+
+	hidden_dentry = dtohd(dentry);
+
+	hidden_dir_dentry = lock_parent(hidden_dentry);
+
+	/* avoid destroying the hidden inode if the file is in use */
+	dget(hidden_dentry);
+	if (!(err = is_robranch(dentry))) {
+		err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry);
+	}
+	dput(hidden_dentry);
+
+	fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+	/* propagate number of hard-links */
+	dentry->d_inode->i_nlink = get_nlinks(dentry->d_inode);
+
+out:
+	if (hidden_dir_dentry) {
+		unlock_dir(hidden_dir_dentry);
+	}
+	return err;
+}
+
+int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int err = 0;
+	struct unionfs_dir_state *namelist = NULL;
+
+	lock_dentry(dentry);
+
+	/* check if this unionfs directory is empty or not */
+	err = check_empty(dentry, &namelist);
+	if (err) {
+#if 0
+		/* vfs_rmdir(our caller) unhashed the dentry.  This will recover
+		 * the Unionfs inode number for the directory itself, but the
+		 * children are already lost.  It seems that tmpfs manages its
+		 * way around this by upping the refcount on everything.
+		 *
+		 * Even if we do this, we still lose the inode numbers of the
+		 * children.  The best way to fix this is to fix the VFS (or
+		 * use persistent inode maps). */
+		if (d_unhashed(dentry))
+			d_rehash(dentry);
+#endif
+		goto out;
+	}
+
+	err = unionfs_rmdir_first(dir, dentry, namelist);
+	/* create whiteout */
+	if (!err) {
+		err = create_whiteout(dentry, dbstart(dentry));
+	} else {
+		int new_err;
+
+		if (dbstart(dentry) == 0)
+			goto out;
+
+		/* exit if the error returned was NOT -EROFS */
+		if (!IS_COPYUP_ERR(err))
+			goto out;
+
+		new_err = create_whiteout(dentry, dbstart(dentry) - 1);
+		if (new_err != -EEXIST)
+			err = new_err;
+	}
+
+out:
+	/* call d_drop so the system "forgets" about us */
+	if (!err)
+		d_drop(dentry);
+
+	if (namelist)
+		free_rdstate(namelist);
+
+	unlock_dentry(dentry);
+	return err;
+}
+
@


1.1.2.2
log
@Git generates slightly different diffs - same information, just little
different
@
text
@d11 3
a13 5
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
new file mode 100644
index 0000000..9c2fa02
--- /dev/null
+++ b/fs/unionfs/unlink.c
@


1.1.2.3
log
@Sync
@
text
@d14 3
a16 5

diff -r a3e6daf9d54c fs/unionfs/unlink.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fs/unionfs/unlink.c	Thu Nov 30 21:19:32 2006 -0500
@@@@ -0,0 +1,177 @@@@
d60 1
a60 1
+	fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
d71 1
a71 1
+	} else if (dbopaque(dentry) != -1)
d74 1
a74 1
+	else
d76 1
d128 1
a128 1
+	fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
d130 1
a130 1
+	dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
@


1.1.2.4
log
@Remove git crud & nicer makefile
@
text
@d11 4
@


1.1.2.5
log
@Collapsed macro patch into unionfs proper
@
text
@d11 1
a11 1
diff -r 566f659958c2 fs/unionfs/unlink.c
d13 2
a14 2
+++ b/fs/unionfs/unlink.c	Sun Dec 03 16:41:18 2006 -0500
@@@@ -0,0 +1,162 @@@@
a34 1
+/* unlink a file by creating a whiteout */
d47 1
a47 1
+	hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
d110 1
a110 1
+	if (err)
d112 1
d114 1
a114 1
+	hidden_dentry = unionfs_lower_dentry(dentry);
d120 1
a120 1
+	if (!(err = is_robranch(dentry)))
d122 1
d130 1
a130 1
+	if (hidden_dir_dentry)
d132 1
d145 13
a157 1
+	if (err)
d159 1
d163 1
a163 1
+	if (!err)
d165 1
a165 1
+	else {
@


1.1.2.6
log
@Folded unionfs-lkml-comments-jan
@
text
@d11 1
a11 1
diff -r dc63340e8948 fs/unionfs/unlink.c
d13 1
a13 1
+++ b/fs/unionfs/unlink.c	Mon Dec 11 09:10:01 2006 -0500
@


1.1.2.7
log
@A. Bunk's patch, more akpm comments, new copyright
@
text
@d11 3
a13 5
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
new file mode 100644
index 0000000..9e690d2
--- /dev/null
+++ b/fs/unionfs/unlink.c
d16 1
a16 1
+ * Copyright (c) 2003-2007 Erez Zadok
d18 1
a18 1
+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
d25 2
a26 2
+ * Copyright (c) 2003-2007 Stony Brook University
+ * Copyright (c) 2003-2007 The Research Foundation of State University of New York
@


