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