linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mike Waychison <michael.waychison@sun.com>
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Cc: raven@themaw.net
Subject: [PATCH 3/28] VFS: Move expiry into vfs
Date: Mon, 25 Oct 2004 10:40:00 -0400	[thread overview]
Message-ID: <10987152003432@sun.com> (raw)
In-Reply-To: <10987151702831@sun.com>

This patch moves the recently added expiry functionality directly into the
VFS layer.  Doing this gives us a couple advantages:

  - Allows for configurable timeouts using a single consolidated timer
  - Keeps filesystems from having to each implement their own expiry logic
  - Provides a generic interface that can be used for _any_ filesystem, as
    desired by user applications and/or the system admninistrator.

This patch implements expiry by having the VFS recursively register work to
do.  Checks are done for expiry every 1 second, so expiry is configurable to
that granularity.

Signed-off-by: Mike Waychison <michael.waychison@sun.com>
---

 fs/namespace.c        |   75 ++++++++++++++++++++++++++++++++++++--------------
 include/linux/mount.h |    6 +---
 2 files changed, 57 insertions(+), 24 deletions(-)

Index: linux-2.6.9-quilt/include/linux/mount.h
===================================================================
--- linux-2.6.9-quilt.orig/include/linux/mount.h	2004-10-22 17:17:33.460377392 -0400
+++ linux-2.6.9-quilt/include/linux/mount.h	2004-10-22 17:17:34.147272968 -0400
@@ -68,10 +68,8 @@ extern struct vfsmount *do_kern_mount(co
 
 struct nameidata;
 
-extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
-			int mnt_flags, struct list_head *fslist);
-
-extern void mark_mounts_for_expiry(struct list_head *mounts);
+extern int do_graft_mount(struct vfsmount *newmnt, struct nameidata *nd);
+extern void mnt_expire(struct vfsmount *mnt, unsigned expire);
 
 extern spinlock_t vfsmount_lock;
 
Index: linux-2.6.9-quilt/fs/namespace.c
===================================================================
--- linux-2.6.9-quilt.orig/fs/namespace.c	2004-10-22 17:17:33.461377240 -0400
+++ linux-2.6.9-quilt/fs/namespace.c	2004-10-22 17:17:34.148272816 -0400
@@ -42,6 +42,13 @@ static struct list_head *mount_hashtable
 static int hash_mask, hash_bits;
 static kmem_cache_t *mnt_cache; 
 
+/* manage mountpoint expiry */
+static LIST_HEAD(expiry_list);
+static void do_expiry_run(void *nothing);
+static DECLARE_WORK(expiry_work, do_expiry_run, NULL);
+static DECLARE_MUTEX(expiry_sem);
+#define EXPIRE_PERIOD (HZ)
+
 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
 {
 	unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
@@ -431,6 +438,7 @@ static int do_umount(struct vfsmount *mn
 		return retval;
 	}
 
+	down(&expiry_sem);
 	down_write(&current->namespace->sem);
 	spin_lock(&vfsmount_lock);
 
@@ -446,14 +454,17 @@ static int do_umount(struct vfsmount *mn
 	}
 	retval = -EBUSY;
 	if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
-		if (!list_empty(&mnt->mnt_list))
+		if (!list_empty(&mnt->mnt_list)) {
+			list_del_init(&mnt->mnt_expire);
 			umount_tree(mnt);
+		}
 		retval = 0;
 	}
 	spin_unlock(&vfsmount_lock);
 	if (retval)
 		security_sb_umount_busy(mnt);
 	up_write(&current->namespace->sem);
+	up(&expiry_sem);
 	return retval;
 }
 
@@ -760,7 +771,7 @@ out:
  * create a new mount for userspace and request it to be added into the
  * namespace's tree
  */
-static int do_new_mount(struct nameidata *nd, char *type, int flags,
+static int do_add_mount(struct nameidata *nd, char *type, int flags,
 			int mnt_flags, char *name, void *data)
 {
 	struct vfsmount *mnt;
@@ -776,15 +787,15 @@ static int do_new_mount(struct nameidata
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
 
-	return do_add_mount(mnt, nd, mnt_flags, NULL);
+	mnt->mnt_flags = mnt_flags;
+	return do_graft_mount(mnt, nd);
 }
 
 /*
  * add a mount into a namespace's mount tree
  * - provide the option of adding the new mount to an expiration list
  */
-int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
-		 int mnt_flags, struct list_head *fslist)
+int do_graft_mount(struct vfsmount *newmnt, struct nameidata *nd)
 {
 	int err;
 
@@ -806,38 +817,52 @@ int do_add_mount(struct vfsmount *newmnt
 	if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
 		goto unlock;
 
-	newmnt->mnt_flags = mnt_flags;
 	err = graft_tree(newmnt, nd);
 
-	if (err == 0 && fslist) {
-		/* add to the specified expiration list */
-		spin_lock(&vfsmount_lock);
-		list_add_tail(&newmnt->mnt_expire, fslist);
-		spin_unlock(&vfsmount_lock);
-	}
 
 unlock:
 	up_write(&current->namespace->sem);
 	mntput(newmnt);
 	return err;
 }
+EXPORT_SYMBOL_GPL(do_graft_mount);
+
+void mnt_expire(struct vfsmount *mnt, unsigned expire)
+{
+	down(&expiry_sem);
+	spin_lock(&vfsmount_lock);
 
-EXPORT_SYMBOL_GPL(do_add_mount);
+	/* Expiry is not permitted on mounts that are not associated with a
+	 * namespace.  This is due to the fact that we cannot reliably handle
+	 * removing the mount from the expiry list when the mount is no longer
+	 * referenced */
+	if (!mnt->mnt_namespace)
+		goto out;
 
+	list_del_init(&mnt->mnt_expire);
+	if (expire > 0)
+		list_add_tail(&mnt->mnt_expire, &expiry_list);
+out:
+	spin_unlock(&vfsmount_lock);
+	up(&expiry_sem);
+}
+EXPORT_SYMBOL_GPL(mnt_expire);
+  
 /*
  * process a list of expirable mountpoints with the intent of discarding any
  * mountpoints that aren't in use and haven't been touched since last we came
  * here
  */
-void mark_mounts_for_expiry(struct list_head *mounts)
+static void do_expiry_run(void *nothing)
 {
 	struct namespace *namespace;
 	struct vfsmount *mnt, *next;
 	LIST_HEAD(graveyard);
 
-	if (list_empty(mounts))
+	if (list_empty(&expiry_list))
 		return;
 
+	down(&expiry_sem);
 	spin_lock(&vfsmount_lock);
 
 	/* extract from the expiration list every vfsmount that matches the
@@ -846,7 +871,7 @@ void mark_mounts_for_expiry(struct list_
 	 * - still marked for expiry (marked on the last call here; marks are
 	 *   cleared by mntput())
 	 */
-	list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
+	list_for_each_entry_safe(mnt, next, &expiry_list, mnt_expire) {
 		if (!xchg(&mnt->mnt_expiry_mark, 1) ||
 		    atomic_read(&mnt->mnt_count) != 1)
 			continue;
@@ -913,22 +938,29 @@ void mark_mounts_for_expiry(struct list_
 			/* someone brought it back to life whilst we didn't
 			 * have any locks held so return it to the expiration
 			 * list */
-			list_add_tail(&mnt->mnt_expire, mounts);
+			list_add_tail(&mnt->mnt_expire, &expiry_list);
 			spin_unlock(&vfsmount_lock);
 		}
 
 		up_write(&namespace->sem);
 
-		mntput(mnt);
+		_mntput(mnt);
 		put_namespace(namespace);
 
 		spin_lock(&vfsmount_lock);
 	}
 
 	spin_unlock(&vfsmount_lock);
+	up(&expiry_sem);
+	schedule_delayed_work(&expiry_work, EXPIRE_PERIOD);
 }
 
-EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
+static __init int start_expiry_work(void)
+{
+	schedule_delayed_work(&expiry_work, EXPIRE_PERIOD);
+	return 1;
+}
+late_initcall(start_expiry_work);
 
 int copy_mount_options (const void __user *data, unsigned long *where)
 {
@@ -1024,7 +1056,7 @@ long do_mount(char * dev_name, char * di
 	else if (flags & MS_MOVE)
 		retval = do_move_mount(&nd, dev_name);
 	else
-		retval = do_new_mount(&nd, type_page, flags, mnt_flags,
+		retval = do_add_mount(&nd, type_page, flags, mnt_flags,
 				      dev_name, data_page);
 dput_out:
 	path_release(&nd);
@@ -1421,15 +1453,18 @@ void __put_namespace(struct namespace *n
 {
 	struct vfsmount *mnt;
 
+	down(&expiry_sem);
 	down_write(&namespace->sem);
 	spin_lock(&vfsmount_lock);
 
 	list_for_each_entry(mnt, &namespace->list, mnt_list) {
 		mnt->mnt_namespace = NULL;
+		list_del_init(&mnt->mnt_expire);
 	}
 
 	umount_tree(namespace->root);
 	spin_unlock(&vfsmount_lock);
 	up_write(&namespace->sem);
+	up(&expiry_sem);
 	kfree(namespace);
 }


  reply	other threads:[~2004-10-25 14:40 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-25 14:38 [PATCH 0/28] Autofs NG Patchset 0.2 Mike Waychison
2004-10-25 14:39 ` [PATCH 1/28] VFS: Unexport umount_tree Mike Waychison
2004-10-25 14:39   ` [PATCH 2/28] VFS: mnt_fslink -> mnt_expire Mike Waychison
2004-10-25 14:40     ` Mike Waychison [this message]
2004-10-25 14:40       ` [PATCH 4/28] VFS: Stat shouldn't stop expire Mike Waychison
2004-10-25 14:41         ` [PATCH 5/28] VFS: Make expiry timeout configurable Mike Waychison
2004-10-25 14:41           ` [PATCH 6/28] VFS: Make expiry recursive Mike Waychison
2004-10-25 14:42             ` [PATCH 7/28] AFS: Update AFS to use new expiry interface Mike Waychison
2004-10-25 14:42               ` [PATCH 8/28] VFS: Remove MNT_EXPIRE support Mike Waychison
2004-10-25 14:43                 ` [PATCH 9/28] VFS: Give sane expiry semantics Mike Waychison
2004-10-25 14:43                   ` [PATCH 10/28] VFS: Move next_mnt() Mike Waychison
2004-10-25 14:44                     ` [PATCH 11/28] VFS: Allow for detachable subtrees Mike Waychison
2004-10-25 14:44                       ` [PATCH 12/28] VFS: Remove (now bogus) check_mnt Mike Waychison
2004-10-25 14:45                         ` [PATCH 13/28] VFS: Introduce soft reference counts Mike Waychison
2004-10-25 15:25                           ` Christoph Hellwig
2004-10-25 15:35                             ` [PATCH 14/28] VFS: Introduce Mountpoint file descriptors (resend) Mike Waychison
2004-10-25 17:20                           ` [PATCH 13/28] VFS: Introduce soft reference counts Mika Penttilä
2004-10-25 17:25                             ` Mike Waychison
2004-10-25 17:52                               ` Mika Penttilä
2004-10-25 17:56                                 ` [PATCH 11/28] VFS: Allow for detachable subtrees (resend) Mike Waychison
2004-10-25 15:09                         ` [PATCH 12/28] VFS: Remove (now bogus) check_mnt Christoph Hellwig
2004-10-25 15:15                           ` Mike Waychison
2004-10-25 15:04                 ` [PATCH 8/28] VFS: Remove MNT_EXPIRE support Christoph Hellwig
2004-10-25 15:12                   ` Mike Waychison
2004-10-25 15:16                     ` Christoph Hellwig
2004-10-25 15:30                       ` Mike Waychison
2004-10-25 17:16                   ` Mike Waychison
2004-10-25 17:29                     ` Mike Waychison
2004-10-25 15:04             ` [PATCH 6/28] VFS: Make expiry recursive Christoph Hellwig
2004-10-26 10:27         ` [PATCH 4/28] VFS: Stat shouldn't stop expire Christoph Hellwig
2004-10-27 18:36           ` Mike Waychison
2004-10-25 14:59       ` [PATCH 3/28] VFS: Move expiry into vfs Christoph Hellwig

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=10987152003432@sun.com \
    --to=michael.waychison@sun.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=raven@themaw.net \
    /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).