VFS quota: add a command to set a group quota
authorFrancois Tigeot <ftigeot@wolfpond.org>
Fri, 30 Mar 2012 18:47:36 +0000 (20:47 +0200)
committerFran├žois Tigeot <ftigeot@wolfpond.org>
Tue, 17 Apr 2012 17:21:15 +0000 (19:21 +0200)
sbin/vquota/vquota.8
sbin/vquota/vquota.c
sys/kern/vfs_quota.c

index 2d17ce2..92b368b 100644 (file)
@@ -98,6 +98,14 @@ bytes for the filesystem mounted under
 .Ar mount_point
 and the specified
 .Ar user .
+.\" ==== glim ====
+.It Cm glim Ar mount_point group size
+Set a quota of
+.Ar size
+bytes for the filesystem mounted under
+.Ar mount_point
+and the specified
+.Ar group .
 .El
 .
 .Sh EXAMPLES
index a1f3592..ec4d394 100644 (file)
@@ -64,6 +64,7 @@ usage(int retcode)
        fprintf(stderr, "       vquota [-Dhn] lsfs\n");
        fprintf(stderr, "       vquota [-Dhn] limit mount_point size\n");
        fprintf(stderr, "       vquota [-Dhn] ulim  mount_point user  size\n");
+       fprintf(stderr, "       vquota [-Dhn] glim  mount_point group size\n");
        fprintf(stderr, "       vquota [-Dhn] show mount_point\n");
        fprintf(stderr, "       vquota [-Dhn] sync mount_point\n");
        exit(retcode);
@@ -670,6 +671,33 @@ cmd_limit_uid(char *dirname, uid_t uid, uint64_t limit)
        return rv;
 }
 
+static int
+cmd_limit_gid(char *dirname, gid_t gid, uint64_t limit)
+{
+       prop_dictionary_t res, args;
+       int rv = 0;
+
+       args = prop_dictionary_create();
+       if (args == NULL)
+               printf("cmd_limit_gid(): couldn't create args dictionary\n");
+       res  = prop_dictionary_create();
+       if (res == NULL)
+               printf("cmd_limit_gid(): couldn't create res dictionary\n");
+
+       (void) prop_dictionary_set_uint32(args, "gid", gid);
+       (void) prop_dictionary_set_uint64(args, "limit", limit);
+
+       if (send_command(dirname, "set limit gid", args, &res) == false) {
+               printf("Failed to send message to kernel\n");
+               rv = 1;
+       }
+
+       prop_object_release(args);
+       prop_object_release(res);
+
+       return rv;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -731,6 +759,17 @@ main(int argc, char **argv)
 
                return cmd_limit_uid(argv[1], pwd->pw_uid, limit);
        }
+       if (strcmp(argv[0], "glim") == 0) {
+               struct group *grp;
+               if (argc != 4)
+                       usage(1);
+               if ((grp = getgrnam(argv[2])) == NULL)
+                       errx(1, "%s: no such group", argv[2]);
+               if (dehumanize_number(argv[3], &limit) < 0)
+                       err(1, "bad number for option: %s", argv[2]);
+
+               return cmd_limit_gid(argv[1], grp->gr_gid, limit);
+       }
 
        usage(0);
 }
index 26004e0..75a46ea 100644 (file)
@@ -304,6 +304,27 @@ cmd_set_limit_uid(struct mount *mp, prop_dictionary_t args)
        return 0;
 }
 
+static int
+cmd_set_limit_gid(struct mount *mp, prop_dictionary_t args)
+{
+       uint64_t limit;
+       gid_t gid;
+       struct ac_gnode gfind, *gnp;
+
+       prop_dictionary_get_uint32(args, "gid", &gid);
+       prop_dictionary_get_uint64(args, "limit", &limit);
+
+       gfind.left_bits = (gid >> ACCT_CHUNK_BITS);
+
+       spin_lock(&mp->mnt_acct.ac_spin);
+       if ((gnp = RB_FIND(ac_gtree, &mp->mnt_acct.ac_groot, &gfind)) == NULL)
+               gnp = gnode_insert(mp, gid);
+       gnp->gid_chunk[(gid & ACCT_CHUNK_MASK)].limit = limit;
+       spin_unlock(&mp->mnt_acct.ac_spin);
+
+       return 0;
+}
+
 int
 sys_vquotactl(struct vquotactl_args *vqa)
 /* const char *path, struct plistref *pref */
@@ -369,6 +390,10 @@ sys_vquotactl(struct vquotactl_args *vqa)
                error = cmd_set_limit_uid(mp, args);
                goto done;
        }
+       if (strcmp(cmd, "set limit gid") == 0) {
+               error = cmd_set_limit_gid(mp, args);
+               goto done;
+       }
        return EINVAL;
 
 done: