Module Name: src Committed By: bouyer Date: Sun Jan 30 00:25:20 UTC 2011
Modified Files: src/sys/ufs/ufs [bouyer-quota2]: quota2_prop.c quota2_prop.h ufs_quota.c ufs_quota.h ufs_quota2.c Log Message: Implement 'set' command for quota2. To generate a diff of this commit: cvs rdiff -u -r1.1.2.2 -r1.1.2.3 src/sys/ufs/ufs/quota2_prop.c \ src/sys/ufs/ufs/quota2_prop.h src/sys/ufs/ufs/ufs_quota.h cvs rdiff -u -r1.68.4.3 -r1.68.4.4 src/sys/ufs/ufs/ufs_quota.c cvs rdiff -u -r1.1.2.4 -r1.1.2.5 src/sys/ufs/ufs/ufs_quota2.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/ufs/ufs/quota2_prop.c diff -u src/sys/ufs/ufs/quota2_prop.c:1.1.2.2 src/sys/ufs/ufs/quota2_prop.c:1.1.2.3 --- src/sys/ufs/ufs/quota2_prop.c:1.1.2.2 Fri Jan 21 16:58:06 2011 +++ src/sys/ufs/ufs/quota2_prop.c Sun Jan 30 00:25:19 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: quota2_prop.c,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */ +/* $NetBSD: quota2_prop.c,v 1.1.2.3 2011/01/30 00:25:19 bouyer Exp $ */ /*- * Copyright (c) 2010 Manuel Bouyer * All rights reserved. @@ -72,6 +72,22 @@ } int +quota2_dict_update_q2e_limits(prop_dictionary_t data, struct quota2_entry *q2e) +{ + int i, error; + prop_dictionary_t val; + for (i = 0; i < NQ2V; i++) { + val = prop_dictionary_get_dict(data, quota2_valnames[i]); + if (val == NULL) + continue; + error = quota2_dict_get_q2v_limits(val, &q2e->q2e_val[i], 1); + if (error) + return error; + } + return 0; +} + +int quota2_dict_get_q2v_usage(prop_dictionary_t dict, struct quota2_val *q2v) { uint64_t vu; Index: src/sys/ufs/ufs/quota2_prop.h diff -u src/sys/ufs/ufs/quota2_prop.h:1.1.2.2 src/sys/ufs/ufs/quota2_prop.h:1.1.2.3 --- src/sys/ufs/ufs/quota2_prop.h:1.1.2.2 Fri Jan 21 16:58:06 2011 +++ src/sys/ufs/ufs/quota2_prop.h Sun Jan 30 00:25:19 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: quota2_prop.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */ +/* $NetBSD: quota2_prop.h,v 1.1.2.3 2011/01/30 00:25:19 bouyer Exp $ */ /*- * Copyright (c) 2010 Manuel Bouyer * All rights reserved. @@ -32,6 +32,7 @@ prop_dictionary_t prop_dictionary_get_dict(prop_dictionary_t, const char *); int quota2_dict_get_q2v_limits(prop_dictionary_t, struct quota2_val *, bool); +int quota2_dict_update_q2e_limits(prop_dictionary_t, struct quota2_entry *); int quota2_dict_get_q2v_usage(prop_dictionary_t, struct quota2_val *); int quota2_dict_get_q2e_usage(prop_dictionary_t, struct quota2_entry *); int quota2_get_cmds(prop_dictionary_t, prop_array_t *); Index: src/sys/ufs/ufs/ufs_quota.h diff -u src/sys/ufs/ufs/ufs_quota.h:1.1.2.2 src/sys/ufs/ufs/ufs_quota.h:1.1.2.3 --- src/sys/ufs/ufs/ufs_quota.h:1.1.2.2 Fri Jan 21 16:58:06 2011 +++ src/sys/ufs/ufs/ufs_quota.h Sun Jan 30 00:25:20 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_quota.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */ +/* $NetBSD: ufs_quota.h,v 1.1.2.3 2011/01/30 00:25:20 bouyer Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 @@ -128,8 +128,8 @@ int chkdq2(struct inode *, int64_t, kauth_cred_t, int); int chkiq2(struct inode *, int32_t, kauth_cred_t, int); -int quota2_handle_cmd_get(struct ufsmount *, int, int, int, - prop_array_t); +int quota2_handle_cmd_get(struct ufsmount *, int, int, int, prop_array_t); +int quota2_handle_cmd_set(struct ufsmount *, int, int, int, prop_dictionary_t); int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t); int q2sync(struct mount *); int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *); Index: src/sys/ufs/ufs/ufs_quota.c diff -u src/sys/ufs/ufs/ufs_quota.c:1.68.4.3 src/sys/ufs/ufs/ufs_quota.c:1.68.4.4 --- src/sys/ufs/ufs/ufs_quota.c:1.68.4.3 Sat Jan 29 23:22:00 2011 +++ src/sys/ufs/ufs/ufs_quota.c Sun Jan 30 00:25:19 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_quota.c,v 1.68.4.3 2011/01/29 23:22:00 bouyer Exp $ */ +/* $NetBSD: ufs_quota.c,v 1.68.4.4 2011/01/30 00:25:19 bouyer Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.3 2011/01/29 23:22:00 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.4 2011/01/30 00:25:19 bouyer Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -62,6 +62,8 @@ static int quota_handle_cmd_get(struct mount *, struct lwp *, prop_dictionary_t, int, prop_array_t); +static int quota_handle_cmd_set(struct mount *, struct lwp *, + prop_dictionary_t, int, prop_array_t); static int quota_handle_cmd_getall(struct mount *, struct lwp *, prop_dictionary_t, int, prop_array_t); /* @@ -153,6 +155,10 @@ error = quota_handle_cmd_get(mp, l, cmddict, q2type, datas); goto end; } + if (strcmp(cmd, "set") == 0) { + error = quota_handle_cmd_set(mp, l, cmddict, q2type, datas); + goto end; + } if (strcmp(cmd, "getall") == 0) { error = quota_handle_cmd_getall(mp, l, cmddict, q2type, datas); goto end; @@ -243,6 +249,72 @@ } static int +quota_handle_cmd_set(struct mount *mp, struct lwp *l, + prop_dictionary_t cmddict, int type, prop_array_t datas) +{ + prop_array_t replies; + prop_object_iterator_t iter; + prop_dictionary_t data; + uint32_t id; + struct ufsmount *ump = VFSTOUFS(mp); + int error, defaultq = 0; + const char *idstr; + + if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) + return EOPNOTSUPP; + + replies = prop_array_create(); + if (replies == NULL) + return ENOMEM; + + iter = prop_array_iterator(datas); + if (iter == NULL) { + prop_object_release(replies); + return ENOMEM; + } + while ((data = prop_object_iterator_next(iter)) != NULL) { + if (!prop_dictionary_get_uint32(data, "id", &id)) { + if (!prop_dictionary_get_cstring_nocopy(data, "id", + &idstr)) + continue; + if (strcmp(idstr, "default")) + continue; + id = 0; + defaultq = 1; + } + error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, + KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(id), NULL); + if (error != 0) { + prop_object_release(replies); + return error; + } +#ifdef QUOTA + if (ump->um_flags & UFS_QUOTA) + error = quota1_handle_cmd_get(ump, type, id, data); + else +#endif +#ifdef QUOTA2 + if (ump->um_flags & UFS_QUOTA2) { + error = quota2_handle_cmd_set(ump, type, id, defaultq, + data); + } else +#endif + panic("quota_handle_cmd_get: no support ?"); + + if (error && error != ENOENT) { + prop_object_release(replies); + return error; + } + } + if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { + error = ENOMEM; + } else { + error = 0; + } + return error; +} + +static int quota_handle_cmd_getall(struct mount *mp, struct lwp *l, prop_dictionary_t cmddict, int type, prop_array_t datas) { Index: src/sys/ufs/ufs/ufs_quota2.c diff -u src/sys/ufs/ufs/ufs_quota2.c:1.1.2.4 src/sys/ufs/ufs/ufs_quota2.c:1.1.2.5 --- src/sys/ufs/ufs/ufs_quota2.c:1.1.2.4 Sat Jan 29 23:22:00 2011 +++ src/sys/ufs/ufs/ufs_quota2.c Sun Jan 30 00:25:20 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_quota2.c,v 1.1.2.4 2011/01/29 23:22:00 bouyer Exp $ */ +/* $NetBSD: ufs_quota2.c,v 1.1.2.5 2011/01/30 00:25:20 bouyer Exp $ */ /*- * Copyright (c) 2010 Manuel Bouyer * All rights reserved. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.1.2.4 2011/01/29 23:22:00 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.1.2.5 2011/01/30 00:25:20 bouyer Exp $"); #include <sys/buf.h> #include <sys/param.h> @@ -409,6 +409,73 @@ return quota2_check(ip, Q2V_FILE, change, cred, flags); } +int +quota2_handle_cmd_set(struct ufsmount *ump, int type, int id, + int defaultq, prop_dictionary_t data) +{ + int error; + struct dquot *dq; + struct quota2_header *q2h; + struct quota2_entry q2e, *q2ep; + struct buf *bp; + const int needswap = UFS_MPNEEDSWAP(ump); + + if (ump->um_quotas[type] == NULLVP) + return ENODEV; + if (defaultq) { + mutex_enter(&dqlock); + error = getq2h(ump, type, &bp, &q2h, B_MODIFY); + if (error) { + mutex_exit(&dqlock); + return error; + } + quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); + error = quota2_dict_update_q2e_limits(data, &q2e); + if (error) { + mutex_exit(&dqlock); + brelse(bp, 0); + return error; + } + quota2_ufs_rwq2e(&q2e, &q2h->q2h_defentry, needswap); + mutex_exit(&dqlock); + VOP_BWRITE(bp); + return error; + } + + error = dqget(NULLVP, id, ump, type, &dq); + if (error) + return error; + + if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { + /* need to alloc a new on-disk quot */ + mutex_enter(&dqlock); + error = quota2_q2ealloc(ump, type, id, dq, &bp, &q2ep); + mutex_exit(&dqlock); + } else { + error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff, + &bp, &q2ep, B_MODIFY); + } + if (error) { + dqrele(NULLVP, dq); + return error; + } + mutex_enter(&dq->dq_interlock); + quota2_ufs_rwq2e(q2ep, &q2e, needswap); + error = quota2_dict_update_q2e_limits(data, &q2e); + if (error) { + mutex_exit(&dq->dq_interlock); + dqrele(NULLVP, dq); + brelse(bp, 0); + return error; + } + quota2_ufs_rwq2e(&q2e, q2ep, needswap); + mutex_exit(&dq->dq_interlock); + dqrele(NULLVP, dq); + VOP_BWRITE(bp); + + return error; +} + static int quota2_array_add_q2e(struct ufsmount *ump, int type, int id, prop_array_t replies)