Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/bouyer-quota2]: src/sys/ufs/ufs Implement clear command (quota2 only), w...
details: https://anonhg.NetBSD.org/src/rev/6e1f9af3d67b
branches: bouyer-quota2
changeset: 761113:6e1f9af3d67b
user: bouyer <bouyer%NetBSD.org@localhost>
date: Mon Feb 07 20:30:39 2011 +0000
description:
Implement clear command (quota2 only), which either free the specified
quota2 entry (if both disk and inode usage are 0) or revert its limits to
the default quota entry.
diffstat:
sys/ufs/ufs/ufs_quota.c | 73 ++++++++++++++++++++++-
sys/ufs/ufs/ufs_quota.h | 3 +-
sys/ufs/ufs/ufs_quota2.c | 149 ++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 208 insertions(+), 17 deletions(-)
diffs (truncated from 349 to 300 lines):
diff -r 6d892d6935c6 -r 6e1f9af3d67b sys/ufs/ufs/ufs_quota.c
--- a/sys/ufs/ufs/ufs_quota.c Mon Feb 07 16:24:13 2011 +0000
+++ b/sys/ufs/ufs/ufs_quota.c Mon Feb 07 20:30:39 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota.c,v 1.68.4.7 2011/01/31 21:09:53 bouyer Exp $ */
+/* $NetBSD: ufs_quota.c,v 1.68.4.8 2011/02/07 20:30:39 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.7 2011/01/31 21:09:53 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.8 2011/02/07 20:30:39 bouyer Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -68,6 +68,8 @@
prop_dictionary_t, int, prop_array_t);
static int quota_handle_cmd_getall(struct mount *, struct lwp *,
prop_dictionary_t, int, prop_array_t);
+static int quota_handle_cmd_clear(struct mount *, struct lwp *,
+ prop_dictionary_t, int, prop_array_t);
/*
* Initialize the quota fields of an inode.
*/
@@ -169,6 +171,10 @@
error = quota_handle_cmd_getall(mp, l, cmddict, q2type, datas);
goto end;
}
+ if (strcmp(cmd, "clear") == 0) {
+ error = quota_handle_cmd_clear(mp, l, cmddict, q2type, datas);
+ goto end;
+ }
error = EOPNOTSUPP;
end:
error = (prop_dictionary_set_int8(cmddict, "return",
@@ -371,6 +377,69 @@
}
static int
+quota_handle_cmd_clear(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_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;
+ } else {
+ defaultq = 0;
+ }
+ 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 QUOTA2
+ if (ump->um_flags & UFS_QUOTA2) {
+ error = quota2_handle_cmd_clear(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)
{
diff -r 6d892d6935c6 -r 6e1f9af3d67b sys/ufs/ufs/ufs_quota.h
--- a/sys/ufs/ufs/ufs_quota.h Mon Feb 07 16:24:13 2011 +0000
+++ b/sys/ufs/ufs/ufs_quota.h Mon Feb 07 20:30:39 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota.h,v 1.1.2.4 2011/01/31 15:24:10 bouyer Exp $ */
+/* $NetBSD: ufs_quota.h,v 1.1.2.5 2011/02/07 20:30:39 bouyer Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993, 1995
@@ -129,6 +129,7 @@
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_set(struct ufsmount *, int, int, int, prop_dictionary_t);
+int quota2_handle_cmd_clear(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 *);
diff -r 6d892d6935c6 -r 6e1f9af3d67b sys/ufs/ufs/ufs_quota2.c
--- a/sys/ufs/ufs/ufs_quota2.c Mon Feb 07 16:24:13 2011 +0000
+++ b/sys/ufs/ufs/ufs_quota2.c Mon Feb 07 20:30:39 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota2.c,v 1.1.2.8 2011/02/07 16:24:13 bouyer Exp $ */
+/* $NetBSD: ufs_quota2.c,v 1.1.2.9 2011/02/07 20:30:39 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.8 2011/02/07 16:24:13 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.1.2.9 2011/02/07 20:30:39 bouyer Exp $");
#include <sys/buf.h>
#include <sys/param.h>
@@ -229,6 +229,7 @@
u_long hash_mask;
const int needswap = UFS_MPNEEDSWAP(ump);
+ KASSERT(mutex_owned(&dq->dq_interlock));
KASSERT(mutex_owned(&dqlock));
error = getq2h(ump, type, &hbp, &q2h, B_MODIFY);
if (error)
@@ -530,6 +531,7 @@
if (error)
goto out_wapbl;
+ mutex_enter(&dq->dq_interlock);
if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) {
/* need to alloc a new on-disk quot */
mutex_enter(&dqlock);
@@ -539,29 +541,145 @@
error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff,
&bp, &q2ep, B_MODIFY);
}
- if (error) {
- dqrele(NULLVP, dq);
- goto out_wapbl;
- }
- mutex_enter(&dq->dq_interlock);
+ if (error)
+ goto out_il;
+
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);
- goto out_wapbl;
+ goto out_il;
}
quota2_ufs_rwq2e(&q2e, q2ep, needswap);
+ VOP_BWRITE(bp);
+
+out_il:
mutex_exit(&dq->dq_interlock);
dqrele(NULLVP, dq);
- VOP_BWRITE(bp);
-
out_wapbl:
UFS_WAPBL_END(ump->um_mountp);
return error;
}
+struct dq2clear_callback {
+ uid_t id;
+ struct dquot *dq;
+ struct quota2_header *q2h;
+};
+
+static int
+dq2clear_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e,
+ uint64_t off, void *v)
+{
+ struct dq2clear_callback *c = v;
+ const int needswap = UFS_MPNEEDSWAP(ump);
+ uint64_t myoff;
+
+ if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) {
+ KASSERT(mutex_owned(&c->dq->dq_interlock));
+ c->dq->dq2_lblkno = 0;
+ c->dq->dq2_blkoff = 0;
+ myoff = *offp;
+ /* remove from hash list */
+ *offp = q2e->q2e_next;
+ /* add to free list */
+ q2e->q2e_next = c->q2h->q2h_free;
+ c->q2h->q2h_free = myoff;
+ return Q2WL_ABORT;
+ }
+ return 0;
+}
+int
+quota2_handle_cmd_clear(struct ufsmount *ump, int type, int id,
+ int defaultq, prop_dictionary_t data)
+{
+ int error, i;
+ struct dquot *dq;
+ struct quota2_header *q2h;
+ struct quota2_entry q2e, *q2ep;
+ struct buf *hbp, *bp;
+ u_long hash_mask;
+ struct dq2clear_callback c;
+
+ if (ump->um_quotas[type] == NULLVP)
+ return ENODEV;
+ if (defaultq)
+ return EOPNOTSUPP;
+
+ /* get the default entry before locking the entry's buffer */
+ mutex_enter(&dqlock);
+ error = getq2h(ump, type, &hbp, &q2h, 0);
+ if (error) {
+ mutex_exit(&dqlock);
+ return error;
+ }
+ /* we'll copy to another disk entry, so no need to swap */
+ memcpy(&q2e, &q2h->q2h_defentry, sizeof(q2e));
+ mutex_exit(&dqlock);
+ brelse(hbp, 0);
+
+ error = dqget(NULLVP, id, ump, type, &dq);
+ if (error)
+ return error;
+
+ mutex_enter(&dq->dq_interlock);
+ if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) {
+ /* already clear, nothing to do */
+ error = ENOENT;
+ goto out_il;
+ }
+ error = UFS_WAPBL_BEGIN(ump->um_mountp);
+ if (error)
+ goto out_dq;
+
+ error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff,
+ &bp, &q2ep, B_MODIFY);
+ if (error)
+ goto out_wapbl;
+
+ if (q2ep->q2e_val[QL_BLOCK].q2v_cur != 0 ||
+ q2ep->q2e_val[QL_FILE].q2v_cur != 0) {
+ /* can't free this entry; revert to default */
+ for (i = 0; i < N_QL; i++) {
+ q2ep->q2e_val[i].q2v_softlimit =
+ q2e.q2e_val[i].q2v_softlimit;
+ q2ep->q2e_val[i].q2v_hardlimit =
+ q2e.q2e_val[i].q2v_hardlimit;
+ q2ep->q2e_val[i].q2v_grace =
+ q2e.q2e_val[i].q2v_grace;
+ q2ep->q2e_val[i].q2v_time = 0;
+ }
+ VOP_BWRITE(bp);
+ goto out_wapbl;
+ }
+ /* we can free it. release bp so we can walk the list */
+ brelse(bp, 0);
+ mutex_enter(&dqlock);
+ error = getq2h(ump, type, &hbp, &q2h, 0);
+ if (error)
+ goto out_dqlock;
+
+ hash_mask = ((1 << q2h->q2h_hash_shift) - 1);
+ c.dq = dq;
+ c.id = id;
+ c.q2h = q2h;
+ error = quota2_walk_list(ump, hbp, type,
+ &q2h->q2h_entries[id & hash_mask], B_MODIFY, &c,
+ dq2clear_callback);
+
+ VOP_BWRITE(hbp);
Home |
Main Index |
Thread Index |
Old Index