<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto">FYI, I noticed this new patch submitted upstream.<div><br></div><div>If it gets included upstream, there is a patch forward to allow the<div>standard quota tools to query Lustre quota data.&nbsp;<br><br><div dir="ltr">Cheers, Andreas</div><div dir="ltr"><br>Begin forwarded message:<br><br></div><blockquote type="cite"><div dir="ltr"><b>From:</b> Sascha Hauer &lt;s.hauer@pengutronix.de&gt;<br><b>Date:</b> January 22, 2021 at 07:17:45 PST<br><b>To:</b> linux-fsdevel@vger.kernel.org<br><b>Cc:</b> Richard Weinberger &lt;richard@nod.at&gt;, linux-mtd@lists.infradead.org, kernel@pengutronix.de, Jan Kara &lt;jack@suse.com&gt;, Sascha Hauer &lt;s.hauer@pengutronix.de&gt;<br><b>Subject:</b> <b>[PATCH 1/8] quota: Allow to pass mount path to quotactl</b><br><br></div></blockquote><blockquote type="cite"><div dir="ltr">\ufeff<span>This patch introduces the Q_PATH flag to the quotactl cmd argument.</span><br><span>When given, the path given in the special argument to quotactl will</span><br><span>be the mount path where the filesystem is mounted, instead of a path</span><br><span>to the block device.</span><br><span>This is necessary for filesystems which do not have a block device as</span><br><span>backing store. Particularly this is done for upcoming UBIFS support.</span><br><span></span><br><span>Signed-off-by: Sascha Hauer &lt;s.hauer@pengutronix.de&gt;</span><br><span>---</span><br><span> fs/quota/quota.c &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 66 ++++++++++++++++++++++++++++----------</span><br><span> include/uapi/linux/quota.h | &nbsp;1 +</span><br><span> 2 files changed, 50 insertions(+), 17 deletions(-)</span><br><span></span><br><span>diff --git a/fs/quota/quota.c b/fs/quota/quota.c</span><br><span>index 6d16b2be5ac4..f653b27a9a4e 100644</span><br><span>--- a/fs/quota/quota.c</span><br><span>+++ b/fs/quota/quota.c</span><br><span>@@ -17,6 +17,7 @@</span><br><span> #include &lt;linux/capability.h&gt;</span><br><span> #include &lt;linux/quotaops.h&gt;</span><br><span> #include &lt;linux/types.h&gt;</span><br><span>+#include &lt;linux/mount.h&gt;</span><br><span> #include &lt;linux/writeback.h&gt;</span><br><span> #include &lt;linux/nospec.h&gt;</span><br><span> #include "compat.h"</span><br><span>@@ -859,25 +860,10 @@ static bool quotactl_cmd_onoff(int cmd)</span><br><span>  &nbsp; &nbsp; &nbsp; &nbsp; (cmd == Q_XQUOTAON) || (cmd == Q_XQUOTAOFF);</span><br><span> }</span><br><span></span><br><span>-/*</span><br><span>- * look up a superblock on which quota ops will be performed</span><br><span>- * - use the name of a block device to find the superblock thereon</span><br><span>- */</span><br><span>-static struct super_block *quotactl_block(const char __user *special, int cmd)</span><br><span>+static struct super_block *quotactl_sb(dev_t dev, int cmd)</span><br><span> {</span><br><span>-#ifdef CONFIG_BLOCK</span><br><span>  &nbsp; &nbsp;struct super_block *sb;</span><br><span>- &nbsp; &nbsp;struct filename *tmp = getname(special);</span><br><span>  &nbsp; &nbsp;bool excl = false, thawed = false;</span><br><span>- &nbsp; &nbsp;int error;</span><br><span>- &nbsp; &nbsp;dev_t dev;</span><br><span>-</span><br><span>- &nbsp; &nbsp;if (IS_ERR(tmp))</span><br><span>- &nbsp; &nbsp; &nbsp; &nbsp;return ERR_CAST(tmp);</span><br><span>- &nbsp; &nbsp;error = lookup_bdev(tmp-&gt;name, &amp;dev);</span><br><span>- &nbsp; &nbsp;putname(tmp);</span><br><span>- &nbsp; &nbsp;if (error)</span><br><span>- &nbsp; &nbsp; &nbsp; &nbsp;return ERR_PTR(error);</span><br><span></span><br><span>  &nbsp; &nbsp;if (quotactl_cmd_onoff(cmd)) {</span><br><span>  &nbsp; &nbsp; &nbsp; &nbsp;excl = true;</span><br><span>@@ -901,12 +887,50 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)</span><br><span>  &nbsp; &nbsp; &nbsp; &nbsp;goto retry;</span><br><span>  &nbsp; &nbsp;}</span><br><span>  &nbsp; &nbsp;return sb;</span><br><span>+}</span><br><span>+</span><br><span>+/*</span><br><span>+ * look up a superblock on which quota ops will be performed</span><br><span>+ * - use the name of a block device to find the superblock thereon</span><br><span>+ */</span><br><span>+static struct super_block *quotactl_block(const char __user *special, int cmd)</span><br><span>+{</span><br><span>+#ifdef CONFIG_BLOCK</span><br><span>+ &nbsp; &nbsp;struct filename *tmp = getname(special);</span><br><span>+ &nbsp; &nbsp;int error;</span><br><span>+ &nbsp; &nbsp;dev_t dev;</span><br><span></span><br><span>+ &nbsp; &nbsp;if (IS_ERR(tmp))</span><br><span>+ &nbsp; &nbsp; &nbsp; &nbsp;return ERR_CAST(tmp);</span><br><span>+ &nbsp; &nbsp;error = lookup_bdev(tmp-&gt;name, &amp;dev);</span><br><span>+ &nbsp; &nbsp;putname(tmp);</span><br><span>+ &nbsp; &nbsp;if (error)</span><br><span>+ &nbsp; &nbsp; &nbsp; &nbsp;return ERR_PTR(error);</span><br><span>+</span><br><span>+ &nbsp; &nbsp;return quotactl_sb(dev, cmd);</span><br><span> #else</span><br><span>  &nbsp; &nbsp;return ERR_PTR(-ENODEV);</span><br><span> #endif</span><br><span> }</span><br><span></span><br><span>+static struct super_block *quotactl_path(const char __user *special, int cmd)</span><br><span>+{</span><br><span>+ &nbsp; &nbsp;struct super_block *sb;</span><br><span>+ &nbsp; &nbsp;struct path path;</span><br><span>+ &nbsp; &nbsp;int error;</span><br><span>+</span><br><span>+ &nbsp; &nbsp;error = user_path_at(AT_FDCWD, special, LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT,</span><br><span>+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&amp;path);</span><br><span>+ &nbsp; &nbsp;if (error)</span><br><span>+ &nbsp; &nbsp; &nbsp; &nbsp;return ERR_PTR(error);</span><br><span>+</span><br><span>+ &nbsp; &nbsp;sb = quotactl_sb(path.mnt-&gt;mnt_sb-&gt;s_dev, cmd);</span><br><span>+</span><br><span>+ &nbsp; &nbsp;path_put(&amp;path);</span><br><span>+</span><br><span>+ &nbsp; &nbsp;return sb;</span><br><span>+}</span><br><span>+</span><br><span> /*</span><br><span> &nbsp;* This is the system call interface. This communicates with</span><br><span> &nbsp;* the user-level programs. Currently this only supports diskquota</span><br><span>@@ -920,6 +944,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,</span><br><span>  &nbsp; &nbsp;struct super_block *sb = NULL;</span><br><span>  &nbsp; &nbsp;struct path path, *pathp = NULL;</span><br><span>  &nbsp; &nbsp;int ret;</span><br><span>+ &nbsp; &nbsp;bool q_path;</span><br><span></span><br><span>  &nbsp; &nbsp;cmds = cmd &gt;&gt; SUBCMDSHIFT;</span><br><span>  &nbsp; &nbsp;type = cmd &amp; SUBCMDMASK;</span><br><span>@@ -927,6 +952,9 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,</span><br><span>  &nbsp; &nbsp;if (type &gt;= MAXQUOTAS)</span><br><span>  &nbsp; &nbsp; &nbsp; &nbsp;return -EINVAL;</span><br><span></span><br><span>+ &nbsp; &nbsp;q_path = cmds &amp; Q_PATH;</span><br><span>+ &nbsp; &nbsp;cmds &amp;= ~Q_PATH;</span><br><span>+</span><br><span>  &nbsp; &nbsp;/*</span><br><span>  &nbsp; &nbsp; * As a special case Q_SYNC can be called without a specific device.</span><br><span>  &nbsp; &nbsp; * It will iterate all superblocks that have quota enabled and call</span><br><span>@@ -951,7 +979,11 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,</span><br><span>  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pathp = &amp;path;</span><br><span>  &nbsp; &nbsp;}</span><br><span></span><br><span>- &nbsp; &nbsp;sb = quotactl_block(special, cmds);</span><br><span>+ &nbsp; &nbsp;if (q_path)</span><br><span>+ &nbsp; &nbsp; &nbsp; &nbsp;sb = quotactl_path(special, cmds);</span><br><span>+ &nbsp; &nbsp;else</span><br><span>+ &nbsp; &nbsp; &nbsp; &nbsp;sb = quotactl_block(special, cmds);</span><br><span>+</span><br><span>  &nbsp; &nbsp;if (IS_ERR(sb)) {</span><br><span>  &nbsp; &nbsp; &nbsp; &nbsp;ret = PTR_ERR(sb);</span><br><span>  &nbsp; &nbsp; &nbsp; &nbsp;goto out;</span><br><span>diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h</span><br><span>index f17c9636a859..e1787c0df601 100644</span><br><span>--- a/include/uapi/linux/quota.h</span><br><span>+++ b/include/uapi/linux/quota.h</span><br><span>@@ -71,6 +71,7 @@</span><br><span> #define Q_GETQUOTA 0x800007 &nbsp; &nbsp;/* get user quota structure */</span><br><span> #define Q_SETQUOTA 0x800008 &nbsp; &nbsp;/* set user quota structure */</span><br><span> #define Q_GETNEXTQUOTA 0x800009 &nbsp; &nbsp;/* get disk limits and usage &gt;= ID */</span><br><span>+#define Q_PATH &nbsp;&nbsp;&nbsp;&nbsp;0x400000 &nbsp; &nbsp;/* quotactl special arg contains mount path */</span><br><span></span><br><span> /* Quota format type IDs */</span><br><span> #define &nbsp; &nbsp;QFMT_VFS_OLD 1</span><br><span>-- </span><br><span>2.20.1</span><br><span></span><br></div></blockquote></div></div></body></html>