]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
quota-util: add methods to read and set project IDs
authorAndres Beltran <abeltran@microsoft.com>
Mon, 16 Jun 2025 23:39:25 +0000 (23:39 +0000)
committerAndres Beltran <abeltran@microsoft.com>
Mon, 7 Jul 2025 17:28:47 +0000 (17:28 +0000)
src/shared/quota-util.c
src/shared/quota-util.h

index a592b2fb0011cdacd583d8a4c5e05a379afd291e..06f27e85f25a911f93ae8717f80fdb587602b845 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "alloc-util.h"
 #include "blockdev-util.h"
+#include "chattr-util.h"
 #include "device-util.h"
 #include "errno-util.h"
 #include "missing_syscall.h"
@@ -33,3 +34,66 @@ int quotactl_fd_with_fallback(int fd, int cmd, int id, void *addr) {
 
         return RET_NERRNO(quotactl(cmd, devnode, id, addr));
 }
+
+int quota_query_proj_id(int fd, uint32_t proj_id, struct dqblk *ret_req) {
+        int r;
+
+        assert(fd >= 0);
+        assert(ret_req);
+
+        r = quotactl_fd_with_fallback(fd, QCMD_FIXED(Q_GETQUOTA, PRJQUOTA), proj_id, ret_req);
+        if (r == -ESRCH || ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r)) {
+                zero(ret_req);
+                return false;
+        }
+        if (r < 0)
+                return r;
+
+        return true;
+}
+
+int quota_proj_id_set_recursive(int fd, uint32_t proj_id, bool verify_exclusive) {
+        int r;
+
+        assert(fd >= 0);
+
+        /* Confirm only the current inode has the project id (in case of race conditions) */
+        if (verify_exclusive) {
+                /* Set to top level first because of the case where directories already exist with multiple subdirectories,
+                 * in which case, number of inodes will be > 1 if applied recursively only */
+                r = set_proj_id(fd, proj_id);
+                if (r < 0)
+                        return r;
+
+                struct dqblk req;
+                r = quotactl_fd_with_fallback(fd, QCMD_FIXED(Q_GETQUOTA, PRJQUOTA), proj_id, &req);
+                if (r < 0)
+                        return r;
+
+                if (req.dqb_curinodes == 0)
+                        return -ENOTRECOVERABLE;
+
+                if (req.dqb_curinodes != 1)
+                        return false;
+        }
+
+        r = set_proj_id_recursive(fd, proj_id);
+        if (r < 0)
+                return r;
+
+        return true;
+}
+
+bool quota_dqblk_is_populated(const struct dqblk *req) {
+        assert(req);
+
+        return FLAGS_SET(req->dqb_valid, QIF_BLIMITS|QIF_SPACE|QIF_ILIMITS|QIF_INODES|QIF_BTIME|QIF_ITIME) &&
+                (req->dqb_bhardlimit > 0 ||
+                 req->dqb_bsoftlimit > 0 ||
+                 req->dqb_ihardlimit > 0 ||
+                 req->dqb_isoftlimit > 0 ||
+                 req->dqb_curspace > 0 ||
+                 req->dqb_curinodes > 0 ||
+                 req->dqb_btime > 0 ||
+                 req->dqb_itime > 0);
+}
index 5e878a5d398a7913582bfb68595d0bbef148cb6e..ec4da0cbb89fe9bb4c36073a9006bfec98fd7513 100644 (file)
@@ -16,3 +16,6 @@ static inline int QCMD_FIXED(uint32_t cmd, uint32_t type) {
 }
 
 int quotactl_fd_with_fallback(int fd, int cmd, int id, void *addr);
+int quota_query_proj_id(int fd, uint32_t proj_id, struct dqblk *ret_req);
+int quota_proj_id_set_recursive(int fd, uint32_t proj_id, bool verify_exclusive);
+bool quota_dqblk_is_populated(const struct dqblk *dqblk);