From 3663c79bb9a613029f55d70851882e5ffbd29dbf Mon Sep 17 00:00:00 2001 From: Francois Tigeot Date: Fri, 30 Mar 2012 20:47:36 +0200 Subject: [PATCH] VFS quota: add a command to set a group quota --- sbin/vquota/vquota.8 | 8 ++++++++ sbin/vquota/vquota.c | 39 +++++++++++++++++++++++++++++++++++++++ sys/kern/vfs_quota.c | 25 +++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 0 deletions(-) diff --git a/sbin/vquota/vquota.8 b/sbin/vquota/vquota.8 index 2d17ce2..92b368b 100644 --- a/sbin/vquota/vquota.8 +++ b/sbin/vquota/vquota.8 @@ -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 diff --git a/sbin/vquota/vquota.c b/sbin/vquota/vquota.c index a1f3592..ec4d394 100644 --- a/sbin/vquota/vquota.c +++ b/sbin/vquota/vquota.c @@ -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); } diff --git a/sys/kern/vfs_quota.c b/sys/kern/vfs_quota.c index 26004e0..75a46ea 100644 --- a/sys/kern/vfs_quota.c +++ b/sys/kern/vfs_quota.c @@ -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: -- 1.7.7.2