public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Dave Hansen <haveblue@us.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: miklos@szeredi.hu, hch@infradead.org, Dave Hansen <haveblue@us.ibm.com>
Subject: [RFC][PATCH 3/5] move mnt_want_write() out of may_open()
Date: Thu, 27 Sep 2007 11:52:12 -0700	[thread overview]
Message-ID: <20070927185212.B9CD77E6@kernel> (raw)
In-Reply-To: <20070927185210.FD980C90@kernel>


may_open() can fail in a lot of ways.  It is also named
such that it doesn't appear to be _taking_ action, just
checking a bunch of conditions.

So, it makes a poor place to take and release the mnt
writer count.  This moves the burder of taking the
mnt writer counts into the callers.  The callers have
the advantage of much more visibility of the filp.
Since we rely on the __fput(filp) to release the mnt
writer count, this is a good thing.

---

 lxc-dave/fs/namei.c  |   41 +++++++++++++++++++++++------------------
 lxc-dave/fs/nfsctl.c |   20 ++++++++++++++++++--
 2 files changed, 41 insertions(+), 20 deletions(-)

diff -puN fs/namei.c~move-mnt_want_write-out-of-may_open fs/namei.c
--- lxc/fs/namei.c~move-mnt_want_write-out-of-may_open	2007-09-27 11:51:32.000000000 -0700
+++ lxc-dave/fs/namei.c	2007-09-27 11:51:32.000000000 -0700
@@ -1621,14 +1621,6 @@ int may_open(struct nameidata *nd, int a
 			return -EACCES;
 
 		flag &= ~O_TRUNC;
-	} else if (flag & FMODE_WRITE) {
-		/*
-		 * effectively: !special_file()
-		 * balanced by __fput()
-		 */
-		error = mnt_want_write(nd->mnt);
-		if (error)
-			return error;
 	}
 
 	error = vfs_permission(nd, acc_mode);
@@ -1687,10 +1679,8 @@ static int open_namei_create(struct name
 	struct dentry *dir = nd->dentry;
 
 	/*
-	 * This ensures that the mnt stays writable
-	 * over the vfs_create() call to may_open(),
-	 * which takes a more persistent
-	 * mnt_want_write().
+	 * This mnt_want_write() is potentially persistent,
+	 * and balanced in __fput()
 	 */
 	error = mnt_want_write(nd->mnt);
 	if (error) {
@@ -1710,14 +1700,18 @@ static int open_namei_create(struct name
 	/* Don't check for write permission, don't truncate */
 	error = may_open(nd, 0, flag & ~O_TRUNC);
 out:
-	/*
-	 * if needed, may_open() has taken a write
-	 * on the mnt for us, so we can release ours.
-	 */
-	mnt_drop_write(nd->mnt);
+	if (error)
+		mnt_drop_write(nd->mnt);
 	return error;
 }
 
+static inline int write_may_occur_to_file(struct inode *inode, int acc_mode)
+{
+	if (special_file(inode->i_mode))
+		return 0;
+	return (acc_mode & FMODE_WRITE);
+}
+
 /*
  *	open_namei()
  *
@@ -1831,9 +1825,20 @@ do_last:
 	if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
 		goto exit;
 ok:
-	error = may_open(nd, acc_mode, flag);
+	/*
+	 * This mnt_want_write() is potentially persistent,
+	 * and balanced in __fput()
+	 */
+	if (write_may_occur_to_file(nd->dentry->d_inode, acc_mode))
+		error = mnt_want_write(nd->mnt);
 	if (error)
 		goto exit;
+	error = may_open(nd, acc_mode, flag);
+	if (error) {
+		if (write_may_occur_to_file(nd->dentry->d_inode, acc_mode))
+			mnt_drop_write(nd->mnt);
+		goto exit;
+	}
 	return 0;
 
 exit_mutex_unlock:
diff -puN fs/nfsctl.c~move-mnt_want_write-out-of-may_open fs/nfsctl.c
--- lxc/fs/nfsctl.c~move-mnt_want_write-out-of-may_open	2007-09-27 11:51:32.000000000 -0700
+++ lxc-dave/fs/nfsctl.c	2007-09-27 11:51:32.000000000 -0700
@@ -22,6 +22,7 @@
 
 static struct file *do_open(char *name, int flags)
 {
+	struct file *filp;
 	struct nameidata nd;
 	struct vfsmount *mnt;
 	int error;
@@ -35,14 +36,29 @@ static struct file *do_open(char *name, 
 	if (error)
 		return ERR_PTR(error);
 
+	/*
+	 * This is balanced when you __fput() the 'struct file'
+	 * returned by dentry_open() below.  If the may_open()
+	 * ever stops containing FMODE_WRITE, this needs to
+	 * be changed.
+	 */
+	error = mnt_want_write(mnt);
+	if (error)
+		return ERR_PTR(error);
 	if (flags == O_RDWR)
 		error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE);
 	else
 		error = may_open(&nd, MAY_WRITE, FMODE_WRITE);
 
-	if (!error)
-		return dentry_open(nd.dentry, nd.mnt, flags);
+	if (error)
+		goto out;
 
+	filp = dentry_open(nd.dentry, nd.mnt, flags);
+	if (!IS_ERR(filp))
+		return filp;
+	error = PTR_ERR(error);
+out:
+	mnt_drop_write(mnt);
 	path_release(&nd);
 	return ERR_PTR(error);
 }
_

  parent reply	other threads:[~2007-09-27 18:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-27 18:52 [RFC][PATCH 1/5] get mount write in __dentry_open() Dave Hansen
2007-09-27 18:52 ` [RFC][PATCH 2/5] move mnt_want_write() into open_namei_create() Dave Hansen
2007-09-27 18:52 ` Dave Hansen [this message]
2007-09-27 18:52 ` [RFC][PATCH 4/5] do namei_flags calculation inside open_namei() Dave Hansen
2007-09-27 18:52 ` [RFC][PATCH 5/5] make open_namei() return a filp Dave Hansen
2007-09-27 18:55   ` 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=20070927185212.B9CD77E6@kernel \
    --to=haveblue@us.ibm.com \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    /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