public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Mike Waychison <Michael.Waychison@Sun.COM>
To: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
Cc: John McCutchan <ttb@tentacle.dhs.org>,
	linux-kernel@vger.kernel.org, gamin-list@gnome.org,
	rml@novell.com, akpm@osdl.org, bkonrath@redhat.com,
	greg@kroah.com
Subject: Re: [ANNOUNCE] inotify 0.18
Date: Tue, 25 Jan 2005 16:29:47 -0500	[thread overview]
Message-ID: <41F6BA4B.2000303@sun.com> (raw)
In-Reply-To: <20050125200100.GC8859@parcelfarce.linux.theplanet.co.uk>

[-- Attachment #1: Type: text/plain, Size: 1877 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Al Viro wrote:
> +static struct inode * find_inode(const char __user *dirname)
> +{
> +	struct inode *inode;
> +	struct nameidata nd;
> +	int error;
> +
> +	error = __user_walk(dirname, LOOKUP_FOLLOW, &nd);
> +	if (error)
> +		return ERR_PTR(error);
> +
> +	inode = nd.dentry->d_inode;
> +
> +	/* you can only watch an inode if you have read permissions on it */
> +	error = permission(inode, MAY_READ, NULL);
> +	if (error) {
> +		inode = ERR_PTR(error);
> +		goto release_and_out;
> +	}
> +
> +	spin_lock(&inode_lock);
> +	__iget(inode);
> +	spin_unlock(&inode_lock);
> +release_and_out:
> +	path_release(&nd);
> +	return inode;
> +}
> 
> Yawn...  OK, so what happens if we get umount in the middle of your
> find_inode(), so that path_release() in there drops the last remaining
> reference to vfsmount (and superblock)?

How about inotify hold on to the nameidata until it is sure to have
updated the watches?  That way, the inode will be seen by
inotify_super_block_umount when called by generic_shutdown_super.

There remains a small race though, in that the inotify ioctl may return
success for an added watch after the umount, but this would have to be
resolved by synchronizing in userspace anyway.

Incremental patch attached.

- --
Mike Waychison
Sun Microsystems, Inc.
1 (650) 352-5299 voice
1 (416) 202-8336 voice

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NOTICE:  The opinions expressed in this email are held by me,
and may not represent the views of Sun Microsystems, Inc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFB9rpKdQs4kOxk3/MRAl0RAJ9vssocI3P93AnfO+zwyhf/BX1V9wCffy9N
r6t7TV0ZxpT3bT5pcYfpCHk=
=RmBk
-----END PGP SIGNATURE-----

[-- Attachment #2: fix_find_inode.patch --]
[-- Type: text/x-patch, Size: 3208 bytes --]

Hold on to the nameidata of the watched file until we have successfully 
added/updated the watch on the inode.

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

---

 inotify.c |   48 ++++++++++++++++++++++++++----------------------
 1 files changed, 26 insertions(+), 22 deletions(-)

Index: linux-2.6.10/drivers/char/inotify.c
===================================================================
--- linux-2.6.10.orig/drivers/char/inotify.c	2005-01-25 15:47:15.000000000 -0500
+++ linux-2.6.10/drivers/char/inotify.c	2005-01-25 16:25:11.151174408 -0500
@@ -181,33 +181,24 @@ static inline void put_inode_data(struct
 }
 
 /*
- * find_inode - resolve a user-given path to a specific inode and iget() it
+ * find_inode - resolve a user-given path to a specific inode and return a nd
  */
-static struct inode * find_inode(const char __user *dirname)
+static int find_inode(const char __user *dirname, struct nameidata *nd)
 {
-	struct inode *inode;
-	struct nameidata nd;
 	int error;
 
-	error = __user_walk(dirname, LOOKUP_FOLLOW, &nd);
+	error = __user_walk(dirname, LOOKUP_FOLLOW, nd);
 	if (error)
-		return ERR_PTR(error);
-
-	inode = nd.dentry->d_inode;
+		return error;
 
 	/* you can only watch an inode if you have read permissions on it */
-	error = permission(inode, MAY_READ, NULL);
+	error = permission(nd->dentry->d_inode, MAY_READ, NULL);
 	if (error) {
-		inode = ERR_PTR(error);
 		goto release_and_out;
 	}
 
-	spin_lock(&inode_lock);
-	__iget(inode);
-	spin_unlock(&inode_lock);
 release_and_out:
-	path_release(&nd);
-	return inode;
+	return error;
 }
 
 struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
@@ -911,11 +902,15 @@ static int inotify_add_watch(struct inot
 {
 	struct inode *inode;
 	struct inotify_watch *watch;
+	struct nameidata nd;
 	int ret;
 
-	inode = find_inode((const char __user*) request->dirname);
-	if (IS_ERR(inode))
-		return PTR_ERR(inode);
+	ret = find_inode((const char __user*) request->dirname, &nd);
+	if (ret)
+		return ret;
+
+	/* Held in place by references in nd */
+	inode = nd.dentry->d_inode;
 
 	spin_lock(&dev->lock);
 
@@ -930,7 +925,7 @@ static int inotify_add_watch(struct inot
 		owatch->mask = request->mask;
 		inode_update_watch_mask(inode);
 		spin_unlock(&dev->lock);
-		iput(inode);
+		path_release(&nd);
 
 		return owatch->wd;
 	}
@@ -939,7 +934,7 @@ static int inotify_add_watch(struct inot
 
 	watch = create_watch(dev, request->mask, inode);
 	if (!watch) {
-		iput(inode);
+		path_release(&nd);
 		return -ENOSPC;
 	}
 
@@ -949,7 +944,7 @@ static int inotify_add_watch(struct inot
 	if (inotify_dev_add_watch(dev, watch)) {
 		delete_watch(dev, watch);
 		spin_unlock(&dev->lock);
-		iput(inode);
+		path_release(&nd);
 		return -EINVAL;
 	}
 
@@ -958,12 +953,21 @@ static int inotify_add_watch(struct inot
 		list_del_init(&watch->d_list);
 		delete_watch(dev, watch);
 		spin_unlock(&dev->lock);
-		iput(inode);
+		path_release(&nd);
 		return ret;
 	}
 
 	spin_unlock(&dev->lock);
 
+	/*
+	 * demote the references in nd to a reference to inode held
+	 * by the watch.
+	 */
+	spin_lock(&inode_lock);
+	__iget(inode);
+	spin_unlock(&inode_lock);
+	path_release(&nd);
+
 	return watch->wd;
 }
 

  reply	other threads:[~2005-01-25 21:35 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1106682112.23615.3.camel@vertex>
2005-01-25 20:01 ` [ANNOUNCE] inotify 0.18 Al Viro
2005-01-25 21:29   ` Mike Waychison [this message]
2005-01-26 23:18     ` Robert Love
2005-01-25 20:02 ` Al Viro

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=41F6BA4B.2000303@sun.com \
    --to=michael.waychison@sun.com \
    --cc=akpm@osdl.org \
    --cc=bkonrath@redhat.com \
    --cc=gamin-list@gnome.org \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rml@novell.com \
    --cc=ttb@tentacle.dhs.org \
    --cc=viro@parcelfarce.linux.theplanet.co.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