linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Valerie Aurora <vaurora@redhat.com>
To: Jan Blunck <jblunck@suse.de>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Christoph Hellwig <hch@infradead.org>,
	Andy Whitcroft <apw@canonical.com>,
	Scott James Remnant <scott@canonica
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	Jan Blunck <jblunck@suse.de>
Subject: [PATCH 21/41] union-mount: Drive the union cache via dcache
Date: Wed, 21 Oct 2009 12:19:19 -0700	[thread overview]
Message-ID: <1256152779-10054-22-git-send-email-vaurora@redhat.com> (raw)
In-Reply-To: <1256152779-10054-21-git-send-email-vaurora@redhat.com>

From: Jan Blunck <jblunck@suse.de>

If a dentry is removed from dentry cache because its usage count drops to
zero, the references to the underlying layer of the unions the dentry is in
are droped too. Therefore the union cache is driven by the dentry cache.

Signed-off-by: Jan Blunck <jblunck@suse.de>
Signed-off-by: Valerie Aurora <vaurora@redhat.com>
---
 fs/dcache.c            |   10 ++++++-
 fs/union.c             |   74 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/dcache.h |    8 +++++
 include/linux/union.h  |    6 ++++
 4 files changed, 97 insertions(+), 1 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 56bd05f..d80a3bb 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <linux/union.h>
 #include <linux/fsnotify.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -188,11 +189,14 @@ static struct dentry *__d_kill(struct dentry *dentry, struct list_head *list,
 		list_add(&dentry->d_lru, list);
 		spin_unlock(&dentry->d_lock);
 		spin_unlock(&dcache_lock);
+		__shrink_d_unions(dentry, list);
 		return NULL;
 	}
 
-	/*drops the locks, at that point nobody can reach this dentry */
+	/* drops the locks, at that point nobody can reach this dentry */
 	dentry_iput(dentry);
+	/* If the dentry was in an union delete them */
+	__shrink_d_unions(dentry, list);
 	if (IS_ROOT(dentry))
 		parent = NULL;
 	else
@@ -784,6 +788,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 					iput(inode);
 			}
 
+			shrink_d_unions(dentry);
 			d_free(dentry);
 
 			/* finished when we fall off the top of the tree,
@@ -1614,7 +1619,9 @@ void d_delete(struct dentry * dentry)
 	spin_lock(&dentry->d_lock);
 	isdir = S_ISDIR(dentry->d_inode->i_mode);
 	if (atomic_read(&dentry->d_count) == 1) {
+		__d_drop_unions(dentry);
 		dentry_iput(dentry);
+		shrink_d_unions(dentry);
 		fsnotify_nameremove(dentry, isdir);
 		return;
 	}
@@ -1625,6 +1632,7 @@ void d_delete(struct dentry * dentry)
 	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 
+	shrink_d_unions(dentry);
 	fsnotify_nameremove(dentry, isdir);
 }
 
diff --git a/fs/union.c b/fs/union.c
index d1950c2..6b99393 100644
--- a/fs/union.c
+++ b/fs/union.c
@@ -14,6 +14,7 @@
 
 #include <linux/bootmem.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/hash.h>
 #include <linux/fs.h>
@@ -255,6 +256,8 @@ int append_to_union(struct vfsmount *mnt, struct dentry *dentry,
 		union_put(this);
 		return 0;
 	}
+	list_add(&this->u_unions, &dentry->d_unions);
+	dest_dentry->d_unionized++;
 	__union_hash(this);
 	spin_unlock(&union_lock);
 	return 0;
@@ -330,3 +333,74 @@ int follow_union_mount(struct vfsmount **mnt, struct dentry **dentry)
 
 	return res;
 }
+
+/*
+ * This must be called when unhashing a dentry. This is called with dcache_lock
+ * and unhashes all unions this dentry is in.
+ */
+void __d_drop_unions(struct dentry *dentry)
+{
+	struct union_mount *this, *next;
+
+	spin_lock(&union_lock);
+	list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions)
+		__union_unhash(this);
+	spin_unlock(&union_lock);
+}
+EXPORT_SYMBOL_GPL(__d_drop_unions);
+
+/*
+ * This must be called after __d_drop_unions() without holding any locks.
+ * Note: The dentry might still be reachable via a lookup but at that time it
+ * already a negative dentry. Otherwise it would be unhashed. The union_mount
+ * structure itself is still reachable through mnt->mnt_unions (which we
+ * protect against with union_lock).
+ */
+void shrink_d_unions(struct dentry *dentry)
+{
+	struct union_mount *this, *next;
+
+repeat:
+	spin_lock(&union_lock);
+	list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) {
+		BUG_ON(!hlist_unhashed(&this->u_hash));
+		BUG_ON(!hlist_unhashed(&this->u_rhash));
+		list_del(&this->u_unions);
+		this->u_next.dentry->d_unionized--;
+		spin_unlock(&union_lock);
+		union_put(this);
+		goto repeat;
+	}
+	spin_unlock(&union_lock);
+}
+
+extern void __dput(struct dentry *, struct list_head *, int);
+
+/*
+ * This is the special variant for use in dput() only.
+ */
+void __shrink_d_unions(struct dentry *dentry, struct list_head *list)
+{
+	struct union_mount *this, *next;
+
+	BUG_ON(!d_unhashed(dentry));
+
+repeat:
+	spin_lock(&union_lock);
+	list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) {
+		struct dentry *n_dentry = this->u_next.dentry;
+		struct vfsmount *n_mnt = this->u_next.mnt;
+
+		BUG_ON(!hlist_unhashed(&this->u_hash));
+		BUG_ON(!hlist_unhashed(&this->u_rhash));
+		list_del(&this->u_unions);
+		this->u_next.dentry->d_unionized--;
+		spin_unlock(&union_lock);
+		if (__union_put(this)) {
+			__dput(n_dentry, list, 0);
+			mntput(n_mnt);
+		}
+		goto repeat;
+	}
+	spin_unlock(&union_lock);
+}
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 4d48c20..730c432 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -215,12 +215,20 @@ extern seqlock_t rename_lock;
  * __d_drop requires dentry->d_lock.
  */
 
+#ifdef CONFIG_UNION_MOUNT
+extern void __d_drop_unions(struct dentry *);
+#endif
+
 static inline void __d_drop(struct dentry *dentry)
 {
 	if (!(dentry->d_flags & DCACHE_UNHASHED)) {
 		dentry->d_flags |= DCACHE_UNHASHED;
 		hlist_del_rcu(&dentry->d_hash);
 	}
+#ifdef CONFIG_UNION_MOUNT
+	/* remove dentry from the union hashtable */
+	__d_drop_unions(dentry);
+#endif
 }
 
 static inline void d_drop(struct dentry *dentry)
diff --git a/include/linux/union.h b/include/linux/union.h
index 0c85312..b035a82 100644
--- a/include/linux/union.h
+++ b/include/linux/union.h
@@ -46,6 +46,9 @@ extern int append_to_union(struct vfsmount *, struct dentry *,
 			   struct vfsmount *, struct dentry *);
 extern int follow_union_down(struct vfsmount **, struct dentry **);
 extern int follow_union_mount(struct vfsmount **, struct dentry **);
+extern void __d_drop_unions(struct dentry *);
+extern void shrink_d_unions(struct dentry *);
+extern void __shrink_d_unions(struct dentry *, struct list_head *);
 
 #else /* CONFIG_UNION_MOUNT */
 
@@ -55,6 +58,9 @@ extern int follow_union_mount(struct vfsmount **, struct dentry **);
 #define append_to_union(x1, y1, x2, y2)	({ BUG(); (0); })
 #define follow_union_down(x, y)		({ (0); })
 #define follow_union_mount(x, y)	({ (0); })
+#define __d_drop_unions(x)		do { } while (0)
+#define shrink_d_unions(x)		do { } while (0)
+#define __shrink_d_unions(x,y)		do { } while (0)
 
 #endif	/* CONFIG_UNION_MOUNT */
 #endif	/* __KERNEL__ */
-- 
1.6.3.3

  reply	other threads:[~2009-10-21 19:19 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-21 19:18 [RFC PATCH 00/40] Writable overlays (union mounts) Valerie Aurora
2009-10-21 19:18 ` [PATCH 01/41] VFS: BUG() if somebody tries to rehash an already hashed dentry Valerie Aurora
2009-10-21 19:19   ` [PATCH 02/41] VFS: propagate mnt_flags into do_loopback Valerie Aurora
2009-10-21 19:19     ` [PATCH 03/41] VFS: Make lookup_hash() return a struct path Valerie Aurora
2009-10-21 19:19       ` [PATCH 04/41] VFS: Remove unnecessary micro-optimization in cached_lookup() Valerie Aurora
2009-10-21 19:19         ` [PATCH 05/41] VFS: Make real_lookup() return a struct path Valerie Aurora
2009-10-21 19:19           ` [PATCH 06/41] VFS: Introduce dput() variant that maintains a kill-list Valerie Aurora
2009-10-21 19:19             ` [PATCH 07/41] VFS: Add read-only users count to superblock Valerie Aurora
2009-10-21 19:19               ` [PATCH 08/41] Don't replace nameidata path when following links Valerie Aurora
2009-10-21 19:19                 ` [PATCH 09/41] whiteout: Don't return information about whiteouts to userspace Valerie Aurora
2009-10-21 19:19                   ` [PATCH 10/41] whiteout: Add vfs_whiteout() and whiteout inode operation Valerie Aurora
2009-10-21 19:19                     ` [PATCH 11/41] whiteout: Set S_OPAQUE inode flag when creating directories Valerie Aurora
2009-10-21 19:19                       ` [PATCH 12/41] union-mount: Allow removal of a directory Valerie Aurora
2009-10-21 19:19                         ` [PATCH 13/41] whiteout: tmpfs whiteout support Valerie Aurora
2009-10-21 19:19                           ` [PATCH 14/41] whiteout: Split of ext2_append_link() from ext2_add_link() Valerie Aurora
2009-10-21 19:19                             ` [PATCH 15/41] whiteout: ext2 whiteout support Valerie Aurora
2009-10-21 19:19                               ` [PATCH 16/41] whiteout: jffs2 " Valerie Aurora
2009-10-21 19:19                                 ` [PATCH 17/41] whiteout: Add path_whiteout() helper Valerie Aurora
2009-10-21 19:19                                   ` [PATCH 18/41] union-mount: Documentation Valerie Aurora
2009-10-21 19:19                                     ` [PATCH 19/41] union-mount: Introduce MNT_UNION and MS_UNION flags Valerie Aurora
2009-10-21 19:19                                       ` [PATCH 20/41] union-mount: Introduce union_mount structure Valerie Aurora
2009-10-21 19:19                                         ` Valerie Aurora [this message]
2009-10-21 19:19                                           ` [PATCH 22/41] union-mount: Some checks during namespace changes Valerie Aurora
2009-10-21 19:19                                             ` [PATCH 23/41] union-mount: Changes to the namespace handling Valerie Aurora
2009-10-21 19:19                                               ` [PATCH 24/41] union-mount: Make lookup work for union-mounted file systems Valerie Aurora
2009-10-21 19:19                                                 ` [PATCH 25/41] union-mount: stop lookup when directory has S_OPAQUE flag set Valerie Aurora
2009-10-21 19:19                                                   ` [PATCH 26/41] union-mount: stop lookup when finding a whiteout Valerie Aurora
2009-10-21 19:19                                                     ` [PATCH 27/41] union-mount: in-kernel file copy between union mounted filesystems Valerie Aurora
2009-10-21 19:19                                                       ` [PATCH 28/41] union-mount: call do_whiteout() on unlink and rmdir Valerie Aurora
2009-10-21 19:19                                                         ` [PATCH 29/41] union-mount: Always create topmost directory on open Valerie Aurora
2009-10-21 19:19                                                           ` [PATCH 30/41] fallthru: Basic fallthru definitions Valerie Aurora
2009-10-21 19:19                                                             ` [PATCH 31/41] fallthru: Support for fallthru entries in union mount lookup Valerie Aurora
2009-10-21 19:19                                                               ` [PATCH 32/41] fallthru: ext2 fallthru support Valerie Aurora
2009-10-21 19:19                                                                 ` [PATCH 33/41] fallthru: jffs2 " Valerie Aurora
2009-10-21 19:19                                                                   ` [PATCH 34/41] fallthru: tmpfs " Valerie Aurora
2009-10-21 19:19                                                                     ` [PATCH 35/41] union-mount: Copy up directory entries on first readdir() Valerie Aurora
2009-10-21 19:19                                                                       ` [PATCH 36/41] union-mount: Increment read-only users count for read-only layer Valerie Aurora
2009-10-21 19:19                                                                         ` [PATCH 37/41] union-mount: Check read-only/read-write status of layers Valerie Aurora
2009-10-21 19:19                                                                           ` [PATCH 38/41] union-mount: Make pivot_root work with union mounts Valerie Aurora
2009-10-21 19:19                                                                             ` [PATCH 39/41] union-mount: Ignore read-only file system in permission checks Valerie Aurora
2009-10-21 19:19                                                                               ` [PATCH 40/41] union-mount: Make truncate work in all its glorious UNIX variations Valerie Aurora
2009-10-21 19:19                                                                                 ` [PATCH 41/41] union-mount: Add support for rename by __union_copyup() Valerie Aurora
2009-12-01  4:57                                                                                   ` Erez Zadok
2009-12-01  4:50                                                                                 ` [PATCH 40/41] union-mount: Make truncate work in all its glorious UNIX variations Erez Zadok
2009-12-01  4:34                                                                               ` [PATCH 39/41] union-mount: Ignore read-only file system in permission checks Erez Zadok
2009-12-01  4:26                                                                             ` [PATCH 38/41] union-mount: Make pivot_root work with union mounts Erez Zadok
2009-12-01  4:18                                                                       ` [PATCH 35/41] union-mount: Copy up directory entries on first readdir() Erez Zadok
2009-12-01  4:17                                                                     ` [PATCH 34/41] fallthru: tmpfs fallthru support Erez Zadok
2009-12-01  4:17                                                                   ` [PATCH 33/41] fallthru: jffs2 " Erez Zadok
2009-12-01  4:17                                                                 ` [PATCH 32/41] fallthru: ext2 " Erez Zadok
2009-12-01  4:15                                                               ` [PATCH 31/41] fallthru: Support for fallthru entries in union mount lookup Erez Zadok
2009-12-01  4:14                                                             ` [PATCH 30/41] fallthru: Basic fallthru definitions Erez Zadok
2009-12-01  4:14                                                           ` [PATCH 29/41] union-mount: Always create topmost directory on open Erez Zadok
2009-12-01  4:13                                                       ` [PATCH 27/41] union-mount: in-kernel file copy between union mounted filesystems Erez Zadok
2009-12-01  4:11                                                     ` [PATCH 26/41] union-mount: stop lookup when finding a whiteout Erez Zadok
2009-12-01  4:10                                                   ` [PATCH 25/41] union-mount: stop lookup when directory has S_OPAQUE flag set Erez Zadok
2009-12-01  4:10                                                 ` [PATCH 24/41] union-mount: Make lookup work for union-mounted file systems Erez Zadok
2009-11-30  9:15                                               ` [PATCH 23/41] union-mount: Changes to the namespace handling Erez Zadok
2009-11-30  9:04                                             ` [PATCH 22/41] union-mount: Some checks during namespace changes Erez Zadok
2009-11-30  8:57                                           ` [PATCH 21/41] union-mount: Drive the union cache via dcache Erez Zadok
2009-11-30  8:46                                         ` [PATCH 20/41] union-mount: Introduce union_mount structure Erez Zadok
2010-01-26 22:38                                           ` Valerie Aurora
2009-11-30  8:02                                       ` [PATCH 19/41] union-mount: Introduce MNT_UNION and MS_UNION flags Erez Zadok
2010-01-26 20:03                                         ` Valerie Aurora
2009-12-01  5:37                                     ` [PATCH 18/41] union-mount: Documentation Erez Zadok
2009-11-30  7:57                                   ` [PATCH 17/41] whiteout: Add path_whiteout() helper Erez Zadok
2010-01-26 20:02                                     ` Valerie Aurora
2009-10-21 22:50                                 ` [PATCH 16/41] whiteout: jffs2 whiteout support David Woodhouse
2009-10-27  2:21                                   ` Valerie Aurora
2009-11-30  7:51                                 ` Erez Zadok
2010-01-26 19:52                                   ` Valerie Aurora
2009-10-21 21:17                               ` [PATCH 15/41] whiteout: ext2 " Andreas Dilger
2009-10-27  2:14                                 ` Valerie Aurora
2009-11-30  7:45                               ` Erez Zadok
2009-11-30  6:32                             ` [PATCH 14/41] whiteout: Split of ext2_append_link() from ext2_add_link() Erez Zadok
2009-11-30  6:26                           ` [PATCH 13/41] whiteout: tmpfs whiteout support Erez Zadok
2010-01-21  2:02                             ` Valerie Aurora
2009-11-30  6:13                         ` [PATCH 12/41] union-mount: Allow removal of a directory Erez Zadok
2010-01-21  0:52                           ` Valerie Aurora
2009-10-27 14:36                     ` [PATCH 10/41] whiteout: Add vfs_whiteout() and whiteout inode operation Eric Paris
2009-10-27 21:22                       ` Valerie Aurora
2009-11-30  3:04                     ` Erez Zadok
2010-01-21  0:35                       ` Valerie Aurora
2009-11-30  2:53                   ` [PATCH 09/41] whiteout: Don't return information about whiteouts to userspace Erez Zadok
2010-01-21  0:19                     ` Valerie Aurora
2009-11-30  2:44                 ` [PATCH 08/41] Don't replace nameidata path when following links Erez Zadok
2009-11-30  2:33               ` [PATCH 07/41] VFS: Add read-only users count to superblock Erez Zadok
2009-11-30  2:28             ` [PATCH 06/41] VFS: Introduce dput() variant that maintains a kill-list Erez Zadok
2010-01-20 23:31               ` Valerie Aurora
2009-11-30  2:11           ` [PATCH 05/41] VFS: Make real_lookup() return a struct path Erez Zadok
2009-11-30  2:07         ` [PATCH 04/41] VFS: Remove unnecessary micro-optimization in cached_lookup() Erez Zadok
2009-12-10 21:25           ` Valerie Aurora
2009-11-30  2:02       ` [PATCH 03/41] VFS: Make lookup_hash() return a struct path Erez Zadok
2009-12-10 21:23         ` Valerie Aurora
2009-11-30  6:04       ` Erez Zadok
2009-12-10 21:24         ` Valerie Aurora
2009-11-30  1:43   ` [PATCH 01/41] VFS: BUG() if somebody tries to rehash an already hashed dentry Erez Zadok
2009-12-10 20:20     ` Valerie Aurora
2009-10-22  2:44 ` [RFC PATCH 00/40] Writable overlays (union mounts) hooanon05
2009-10-27  2:23   ` Valerie Aurora

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1256152779-10054-22-git-send-email-vaurora@redhat.com \
    --to=vaurora@redhat.com \
    --cc=apw@canonical.com \
    --cc=hch@infradead.org \
    --cc=jblunck@suse.de \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=scott@canonica \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).