All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: linux-fsdevel@vger.kernel.org
Cc: linux-mtd@lists.infradead.org, Jan Kara <jack@suse.com>,
	Richard Weinberger <richard@nod.at>,
	kernel@pengutronix.de, Sascha Hauer <s.hauer@pengutronix.de>
Subject: [PATCH 05/11] quota: Allow to pass quotactl a mountpoint
Date: Wed, 14 Aug 2019 14:18:28 +0200	[thread overview]
Message-ID: <20190814121834.13983-6-s.hauer@pengutronix.de> (raw)
In-Reply-To: <20190814121834.13983-1-s.hauer@pengutronix.de>

So far quotactl only allows a path to a block device to specify a
filesystem to work on. For filesystems that don't work on block devices
such as UBIFS there is no block device, so let quotactl take the
mountpoint as an alternative way.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/quota/quota.c   | 69 ++++++++++++++++++++++++++++++++--------------
 fs/super.c         | 17 ++++++++++++
 include/linux/fs.h |  1 +
 3 files changed, 67 insertions(+), 20 deletions(-)

diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 64a212576a72..6d9807092ae1 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 #include <linux/writeback.h>
 #include <linux/nospec.h>
+#include <linux/mount.h>
 
 static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
 				     qid_t id)
@@ -781,16 +782,53 @@ static bool quotactl_cmd_onoff(int cmd)
 		 (cmd == Q_XQUOTAON) || (cmd == Q_XQUOTAOFF);
 }
 
+static struct super_block *quotactl_block(const char __user *special)
+{
+#ifdef CONFIG_BLOCK
+	struct block_device *bdev;
+	struct filename *tmp = getname(special);
+
+	if (IS_ERR(tmp))
+		return ERR_CAST(tmp);
+	bdev = lookup_bdev(tmp->name);
+	putname(tmp);
+	if (IS_ERR(bdev))
+		return ERR_CAST(bdev);
+
+	bdput(bdev);
+
+	return get_super(bdev);
+#else
+	return ERR_PTR(-ENODEV);
+#endif
+}
+
+static struct super_block *quotactl_path(const char __user *special)
+{
+	struct super_block *sb;
+	struct path path;
+	int ret;
+
+	ret = user_path_at(AT_FDCWD, special, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+	if (ret)
+		return ERR_PTR(ret);
+
+	sb = path.mnt->mnt_sb;
+
+	reference_super(sb);
+
+	path_put(&path);
+
+	return sb;
+}
+
 /*
  * look up a superblock on which quota ops will be performed
  * - use the name of a block device to find the superblock thereon
  */
-static struct super_block *quotactl_block(const char __user *special, int cmd)
+static struct super_block *quotactl_get_super(const char __user *special, int cmd)
 {
-#ifdef CONFIG_BLOCK
-	struct block_device *bdev;
 	struct super_block *sb;
-	struct filename *tmp = getname(special);
 	bool thawed = false, exclusive;
 	int ret;
 
@@ -802,18 +840,12 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
 		exclusive = false;
 	}
 
-	if (IS_ERR(tmp))
-		return ERR_CAST(tmp);
-	bdev = lookup_bdev(tmp->name);
-	putname(tmp);
-	if (IS_ERR(bdev))
-		return ERR_CAST(bdev);
-
-	bdput(bdev);
-
-	sb = get_super(bdev);
-	if (!sb)
-		return ERR_PTR(-ENODEV);
+	sb = quotactl_block(special);
+	if (IS_ERR(sb)) {
+		sb = quotactl_path(special);
+		if (IS_ERR(sb))
+			return ERR_CAST(sb);
+	}
 
 	if (thawed) {
 		ret = wait_super_thawed(sb, exclusive);
@@ -827,9 +859,6 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
 	}
 
 	return sb;
-#else
-	return ERR_PTR(-ENODEV);
-#endif
 }
 
 /*
@@ -873,7 +902,7 @@ int kernel_quotactl(unsigned int cmd, const char __user *special,
 			pathp = &path;
 	}
 
-	sb = quotactl_block(special, cmds);
+	sb = quotactl_get_super(special, cmds);
 	if (IS_ERR(sb)) {
 		ret = PTR_ERR(sb);
 		goto out;
diff --git a/fs/super.c b/fs/super.c
index 13380ffcbd8d..b23641f94557 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -819,6 +819,23 @@ int wait_super_thawed(struct super_block *sb, bool excl)
 }
 EXPORT_SYMBOL(wait_super_thawed);
 
+/**
+ * reference_super - get a reference to a given superblock
+ * @sb: superblock to get the reference from
+ *
+ * Takes a reference to a superblock. Can be used as when the superblock
+ * is known and leaves it in a state as if get_super had been called.
+ */
+void reference_super(struct super_block *sb)
+{
+	spin_lock(&sb_lock);
+	sb->s_count++;
+	spin_unlock(&sb_lock);
+
+	down_read(&sb->s_umount);
+}
+EXPORT_SYMBOL_GPL(reference_super);
+
 /**
  * get_active_super - get an active reference to the superblock of a device
  * @bdev: device to get the superblock for
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 59d9ea62942a..66aa9e5490d0 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3223,6 +3223,7 @@ extern struct super_block *get_super(struct block_device *);
 extern int wait_super_thawed(struct super_block *sb, bool excl);
 extern struct super_block *get_active_super(struct block_device *bdev);
 extern int super_wait_thawed(struct super_block *sb, bool excl);
+extern void reference_super(struct super_block *sb);
 extern void drop_super(struct super_block *sb);
 extern void drop_super_exclusive(struct super_block *sb);
 extern void iterate_supers(void (*)(struct super_block *, void *), void *);
-- 
2.20.1


WARNING: multiple messages have this Message-ID (diff)
From: Sascha Hauer <s.hauer@pengutronix.de>
To: linux-fsdevel@vger.kernel.org
Cc: Richard Weinberger <richard@nod.at>,
	Sascha Hauer <s.hauer@pengutronix.de>,
	linux-mtd@lists.infradead.org, kernel@pengutronix.de,
	Jan Kara <jack@suse.com>
Subject: [PATCH 05/11] quota: Allow to pass quotactl a mountpoint
Date: Wed, 14 Aug 2019 14:18:28 +0200	[thread overview]
Message-ID: <20190814121834.13983-6-s.hauer@pengutronix.de> (raw)
In-Reply-To: <20190814121834.13983-1-s.hauer@pengutronix.de>

So far quotactl only allows a path to a block device to specify a
filesystem to work on. For filesystems that don't work on block devices
such as UBIFS there is no block device, so let quotactl take the
mountpoint as an alternative way.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/quota/quota.c   | 69 ++++++++++++++++++++++++++++++++--------------
 fs/super.c         | 17 ++++++++++++
 include/linux/fs.h |  1 +
 3 files changed, 67 insertions(+), 20 deletions(-)

diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 64a212576a72..6d9807092ae1 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 #include <linux/writeback.h>
 #include <linux/nospec.h>
+#include <linux/mount.h>
 
 static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
 				     qid_t id)
@@ -781,16 +782,53 @@ static bool quotactl_cmd_onoff(int cmd)
 		 (cmd == Q_XQUOTAON) || (cmd == Q_XQUOTAOFF);
 }
 
+static struct super_block *quotactl_block(const char __user *special)
+{
+#ifdef CONFIG_BLOCK
+	struct block_device *bdev;
+	struct filename *tmp = getname(special);
+
+	if (IS_ERR(tmp))
+		return ERR_CAST(tmp);
+	bdev = lookup_bdev(tmp->name);
+	putname(tmp);
+	if (IS_ERR(bdev))
+		return ERR_CAST(bdev);
+
+	bdput(bdev);
+
+	return get_super(bdev);
+#else
+	return ERR_PTR(-ENODEV);
+#endif
+}
+
+static struct super_block *quotactl_path(const char __user *special)
+{
+	struct super_block *sb;
+	struct path path;
+	int ret;
+
+	ret = user_path_at(AT_FDCWD, special, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+	if (ret)
+		return ERR_PTR(ret);
+
+	sb = path.mnt->mnt_sb;
+
+	reference_super(sb);
+
+	path_put(&path);
+
+	return sb;
+}
+
 /*
  * look up a superblock on which quota ops will be performed
  * - use the name of a block device to find the superblock thereon
  */
-static struct super_block *quotactl_block(const char __user *special, int cmd)
+static struct super_block *quotactl_get_super(const char __user *special, int cmd)
 {
-#ifdef CONFIG_BLOCK
-	struct block_device *bdev;
 	struct super_block *sb;
-	struct filename *tmp = getname(special);
 	bool thawed = false, exclusive;
 	int ret;
 
@@ -802,18 +840,12 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
 		exclusive = false;
 	}
 
-	if (IS_ERR(tmp))
-		return ERR_CAST(tmp);
-	bdev = lookup_bdev(tmp->name);
-	putname(tmp);
-	if (IS_ERR(bdev))
-		return ERR_CAST(bdev);
-
-	bdput(bdev);
-
-	sb = get_super(bdev);
-	if (!sb)
-		return ERR_PTR(-ENODEV);
+	sb = quotactl_block(special);
+	if (IS_ERR(sb)) {
+		sb = quotactl_path(special);
+		if (IS_ERR(sb))
+			return ERR_CAST(sb);
+	}
 
 	if (thawed) {
 		ret = wait_super_thawed(sb, exclusive);
@@ -827,9 +859,6 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
 	}
 
 	return sb;
-#else
-	return ERR_PTR(-ENODEV);
-#endif
 }
 
 /*
@@ -873,7 +902,7 @@ int kernel_quotactl(unsigned int cmd, const char __user *special,
 			pathp = &path;
 	}
 
-	sb = quotactl_block(special, cmds);
+	sb = quotactl_get_super(special, cmds);
 	if (IS_ERR(sb)) {
 		ret = PTR_ERR(sb);
 		goto out;
diff --git a/fs/super.c b/fs/super.c
index 13380ffcbd8d..b23641f94557 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -819,6 +819,23 @@ int wait_super_thawed(struct super_block *sb, bool excl)
 }
 EXPORT_SYMBOL(wait_super_thawed);
 
+/**
+ * reference_super - get a reference to a given superblock
+ * @sb: superblock to get the reference from
+ *
+ * Takes a reference to a superblock. Can be used as when the superblock
+ * is known and leaves it in a state as if get_super had been called.
+ */
+void reference_super(struct super_block *sb)
+{
+	spin_lock(&sb_lock);
+	sb->s_count++;
+	spin_unlock(&sb_lock);
+
+	down_read(&sb->s_umount);
+}
+EXPORT_SYMBOL_GPL(reference_super);
+
 /**
  * get_active_super - get an active reference to the superblock of a device
  * @bdev: device to get the superblock for
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 59d9ea62942a..66aa9e5490d0 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3223,6 +3223,7 @@ extern struct super_block *get_super(struct block_device *);
 extern int wait_super_thawed(struct super_block *sb, bool excl);
 extern struct super_block *get_active_super(struct block_device *bdev);
 extern int super_wait_thawed(struct super_block *sb, bool excl);
+extern void reference_super(struct super_block *sb);
 extern void drop_super(struct super_block *sb);
 extern void drop_super_exclusive(struct super_block *sb);
 extern void iterate_supers(void (*)(struct super_block *, void *), void *);
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

  parent reply	other threads:[~2019-08-14 12:19 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-14 12:18 [PATCH 00/11] Add quota support to UBIFS Sascha Hauer
2019-08-14 12:18 ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 01/11] quota: Make inode optional Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 02/11] quota: Only module_put the format when existing Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-15 11:18   ` Jan Kara
2019-08-15 11:18     ` Jan Kara
2019-08-16 11:49     ` Sascha Hauer
2019-08-16 11:49       ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 03/11] fs: move __get_super() out of loop Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 23:32   ` Al Viro
2019-08-14 23:32     ` Al Viro
2019-08-14 12:18 ` [PATCH 04/11] fs, quota: introduce wait_super_thawed() to wait until a superblock is thawed Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 23:35   ` Al Viro
2019-08-14 23:35     ` Al Viro
2019-08-14 12:18 ` Sascha Hauer [this message]
2019-08-14 12:18   ` [PATCH 05/11] quota: Allow to pass quotactl a mountpoint Sascha Hauer
2019-08-14 22:42   ` kbuild test robot
2019-08-14 22:42     ` kbuild test robot
2019-08-14 23:33   ` kbuild test robot
2019-08-14 23:33     ` kbuild test robot
2019-08-14 23:36   ` Al Viro
2019-08-14 23:36     ` Al Viro
2019-08-14 23:39     ` Al Viro
2019-08-14 23:39       ` Al Viro
2019-08-14 23:51       ` Al Viro
2019-08-14 23:51         ` Al Viro
2019-08-15  9:53         ` Jan Kara
2019-08-15  9:53           ` Jan Kara
2019-08-15  7:46       ` Sascha Hauer
2019-08-15  7:46         ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 06/11] ubifs: move checks and preparation into setflags() Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 07/11] ubifs: Add support for FS_IOC_FS[SG]ETXATTR ioctls Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 14:11   ` Mainz, Roland
2019-08-14 14:11     ` Mainz, Roland
2019-08-15  7:31     ` Sascha Hauer
2019-08-15  7:31       ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 08/11] ubifs: do not ubifs_inode() on potentially NULL pointer Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 09/11] ubifs: Add support for project id Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 10/11] ubifs: export get_znode Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-14 12:18 ` [PATCH 11/11] ubifs: Add quota support Sascha Hauer
2019-08-14 12:18   ` Sascha Hauer
2019-08-15 11:17   ` Jan Kara
2019-08-15 11:17     ` Jan Kara

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=20190814121834.13983-6-s.hauer@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=jack@suse.com \
    --cc=kernel@pengutronix.de \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=richard@nod.at \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.