<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. <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 <s.hauer@pengutronix.de><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 <richard@nod.at>, linux-mtd@lists.infradead.org, kernel@pengutronix.de, Jan Kara <jack@suse.com>, Sascha Hauer <s.hauer@pengutronix.de><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"><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 <s.hauer@pengutronix.de></span><br><span>---</span><br><span> fs/quota/quota.c           | 66 ++++++++++++++++++++++++++++----------</span><br><span> include/uapi/linux/quota.h |  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 <linux/capability.h></span><br><span> #include <linux/quotaops.h></span><br><span> #include <linux/types.h></span><br><span>+#include <linux/mount.h></span><br><span> #include <linux/writeback.h></span><br><span> #include <linux/nospec.h></span><br><span> #include "compat.h"</span><br><span>@@ -859,25 +860,10 @@ static bool quotactl_cmd_onoff(int cmd)</span><br><span>          (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>     struct super_block *sb;</span><br><span>-    struct filename *tmp = getname(special);</span><br><span>     bool excl = false, thawed = false;</span><br><span>-    int error;</span><br><span>-    dev_t dev;</span><br><span>-</span><br><span>-    if (IS_ERR(tmp))</span><br><span>-        return ERR_CAST(tmp);</span><br><span>-    error = lookup_bdev(tmp->name, &dev);</span><br><span>-    putname(tmp);</span><br><span>-    if (error)</span><br><span>-        return ERR_PTR(error);</span><br><span></span><br><span>     if (quotactl_cmd_onoff(cmd)) {</span><br><span>         excl = true;</span><br><span>@@ -901,12 +887,50 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)</span><br><span>         goto retry;</span><br><span>     }</span><br><span>     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>+    struct filename *tmp = getname(special);</span><br><span>+    int error;</span><br><span>+    dev_t dev;</span><br><span></span><br><span>+    if (IS_ERR(tmp))</span><br><span>+        return ERR_CAST(tmp);</span><br><span>+    error = lookup_bdev(tmp->name, &dev);</span><br><span>+    putname(tmp);</span><br><span>+    if (error)</span><br><span>+        return ERR_PTR(error);</span><br><span>+</span><br><span>+    return quotactl_sb(dev, cmd);</span><br><span> #else</span><br><span>     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>+    struct super_block *sb;</span><br><span>+    struct path path;</span><br><span>+    int error;</span><br><span>+</span><br><span>+    error = user_path_at(AT_FDCWD, special, LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT,</span><br><span>+               &path);</span><br><span>+    if (error)</span><br><span>+        return ERR_PTR(error);</span><br><span>+</span><br><span>+    sb = quotactl_sb(path.mnt->mnt_sb->s_dev, cmd);</span><br><span>+</span><br><span>+    path_put(&path);</span><br><span>+</span><br><span>+    return sb;</span><br><span>+}</span><br><span>+</span><br><span> /*</span><br><span>  * This is the system call interface. This communicates with</span><br><span>  * 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>     struct super_block *sb = NULL;</span><br><span>     struct path path, *pathp = NULL;</span><br><span>     int ret;</span><br><span>+    bool q_path;</span><br><span></span><br><span>     cmds = cmd >> SUBCMDSHIFT;</span><br><span>     type = cmd & SUBCMDMASK;</span><br><span>@@ -927,6 +952,9 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,</span><br><span>     if (type >= MAXQUOTAS)</span><br><span>         return -EINVAL;</span><br><span></span><br><span>+    q_path = cmds & Q_PATH;</span><br><span>+    cmds &= ~Q_PATH;</span><br><span>+</span><br><span>     /*</span><br><span>      * As a special case Q_SYNC can be called without a specific device.</span><br><span>      * 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>             pathp = &path;</span><br><span>     }</span><br><span></span><br><span>-    sb = quotactl_block(special, cmds);</span><br><span>+    if (q_path)</span><br><span>+        sb = quotactl_path(special, cmds);</span><br><span>+    else</span><br><span>+        sb = quotactl_block(special, cmds);</span><br><span>+</span><br><span>     if (IS_ERR(sb)) {</span><br><span>         ret = PTR_ERR(sb);</span><br><span>         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    /* get user quota structure */</span><br><span> #define Q_SETQUOTA 0x800008    /* set user quota structure */</span><br><span> #define Q_GETNEXTQUOTA 0x800009    /* get disk limits and usage >= ID */</span><br><span>+#define Q_PATH     0x400000    /* quotactl special arg contains mount path */</span><br><span></span><br><span> /* Quota format type IDs */</span><br><span> #define    QFMT_VFS_OLD 1</span><br><span>-- </span><br><span>2.20.1</span><br><span></span><br></div></blockquote></div></div></body></html>