Skip to contentSkip to conversation

pin kern mounts as writable

RFC PATCH In review Dave Hansen 2 participants 3 messages Aug 3, 2009 – Sep 12, 2009 VFS

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/2 pin kern mounts as writable

If we are going to continue to use mnt_clone_write() inside of init_file(), then we're going to need some kind of extra handling.

What I want to do in the next patch is add a debugging check in mnt_clone_write() to double-check that there *is* a real writer on the mount before mnt_clone_write() succeeds. To do that, we either need to check for MS_KERNMOUNT around that debug check, or we need to make sure that these kern mounts *have* a write already.

I'm choosing to make sure they always have a write.

---

 linux-2.6.git-dave/fs/super.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
fs/super.c renamed from fs/super.c~pin-mnt-writable +13 -1
diff -puN fs/super.c~pin-mnt-writable fs/super.c
@@ -948,7 +948,19 @@ EXPORT_SYMBOL_GPL(do_kern_mount);
 
 struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
 {
-	return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+	int err = 0;
+	struct vfsmount *mnt;
+	mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+	if (IS_ERR(mnt))
+		return mnt;
+	/*
+	 * We will never allow this mount to be r/o.  Doing
+	 * this makes it explicit and allows mnt_clone_write()
+	 * to be used unconditionally on this mount.
+	 */
+	err = mnt_want_write(mnt);
+	WARN_ON(err);
+	return mnt;
 }
 
 EXPORT_SYMBOL_GPL(kern_mount_data);

diff -puN include/linux/mount.h~pin-mnt-writable include/linux/mount.h _

#1 lore raw

RFC PATCH 2/2 fix mnt_want_write_file() on special files

mnt_want_write_file() uses the basic assumption that we can use a refernce to a 'struct file' with FMODE_WRITE set in lieu of all of the expensive checks to avoid remount,ro races.

The problem is that FMODE_WRITE is not enough. Special files never had a mnt_want_write() done for them, so we have to exclude them.

This also adds a commented-out BUG_ON() that will reliably detect if anyone tries this again. However, it comes at the cost of destroying any and all performance gains that mnt_clone_write() would have offered (and then some).

---

 linux-2.6.git-dave/fs/namespace.c |   24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)
fs/namespace.c renamed from fs/namespace.c~mnt_want_write_file-0 +19 -5
diff -puN fs/namespace.c~mnt_want_write_file-0 fs/namespace.c
@@ -294,9 +294,17 @@ EXPORT_SYMBOL_GPL(mnt_want_write);
  *
  * After finished, mnt_drop_write must be called as usual to
  * drop the reference.
+ *
+ * Be very careful using this.  You must *guarantee* that
+ * this vfsmount has at least one existing, persistent writer
+ * that can not possibly go away, before calling this.
  */
 int mnt_clone_write(struct vfsmount *mnt)
 {
+	/* This would kill the performance
+	 * optimization in this function
+	BUG_ON(count_mnt_writers(mnt) <= 0);
+	 */
 	/* superblock may be r/o */
 	if (__mnt_is_readonly(mnt))
 		return -EROFS;
@@ -312,14 +320,20 @@ EXPORT_SYMBOL_GPL(mnt_clone_write);
  * @file: the file who's mount on which to take a write
  *
  * This is like mnt_want_write, but it takes a file and can
- * do some optimisations if the file is open for write already
+ * do some optimisations if the file is open for write already.
+ * We do not do mnt_want_write() on read-only or special files,
+ * so we can not use mnt_clone_write() for them.
  */
 int mnt_want_write_file(struct file *file)
 {
-	if (!(file->f_mode & FMODE_WRITE))
-		return mnt_want_write(file->f_path.mnt);
-	else
-		return mnt_clone_write(file->f_path.mnt);
+	struct path *path = &file->f_path;
+	struct inode *inode = path->dentry->d_inode;
+
+	if ((file->f_mode & FMODE_WRITE) &&
+	    !special_file(inode->i_mode))
+		return mnt_clone_write(path->mnt);
+
+	return mnt_want_write(path->mnt);
 }
 EXPORT_SYMBOL_GPL(mnt_want_write_file);
 

diff -puN ./lib/Kconfig.debug~mnt_want_write_file-0 ./lib/Kconfig.debug _

maintainer
#2 lore raw
In reply to Dave Hansen
Quoted 13 lines · Dave Hansen

If we are going to continue to use mnt_clone_write() inside of init_file(), then we're going to need some kind of extra handling.

What I want to do in the next patch is add a debugging check in mnt_clone_write() to double-check that there *is* a real writer on the mount before mnt_clone_write() succeeds. To do that, we either need to check for MS_KERNMOUNT around that debug check, or we need to make sure that these kern mounts *have* a write already.

I'm choosing to make sure they always have a write.

fs/super.c EXPORT_SYMBOL_GPL(do_kern_mount); · line 962

Quoted 2 lines
fs/super.c renamed from fs/super.c~pin-mnt-writable +2 -0
+	err = mnt_want_write(mnt);
+	WARN_ON(err);

And what would happen to that when we do it to a filesystem that is made read-only by its ->get_sb()?