| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ufs_quota2.c,v 1.7 2012/01/29 06:41:42 dholland Exp $ */ | | 1 | /* $NetBSD: ufs_quota2.c,v 1.8 2012/01/29 06:46:50 dholland Exp $ */ |
2 | /*- | | 2 | /*- |
3 | * Copyright (c) 2010 Manuel Bouyer | | 3 | * Copyright (c) 2010 Manuel Bouyer |
4 | * All rights reserved. | | 4 | * All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -16,27 +16,27 @@ | | | @@ -16,27 +16,27 @@ |
16 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 16 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
17 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 17 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
18 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 18 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
19 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 19 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 | * POSSIBILITY OF SUCH DAMAGE. | | 25 | * POSSIBILITY OF SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #include <sys/cdefs.h> | | 28 | #include <sys/cdefs.h> |
29 | __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.7 2012/01/29 06:41:42 dholland Exp $"); | | 29 | __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.8 2012/01/29 06:46:50 dholland Exp $"); |
30 | | | 30 | |
31 | #include <sys/buf.h> | | 31 | #include <sys/buf.h> |
32 | #include <sys/param.h> | | 32 | #include <sys/param.h> |
33 | #include <sys/kernel.h> | | 33 | #include <sys/kernel.h> |
34 | #include <sys/systm.h> | | 34 | #include <sys/systm.h> |
35 | #include <sys/malloc.h> | | 35 | #include <sys/malloc.h> |
36 | #include <sys/namei.h> | | 36 | #include <sys/namei.h> |
37 | #include <sys/file.h> | | 37 | #include <sys/file.h> |
38 | #include <sys/proc.h> | | 38 | #include <sys/proc.h> |
39 | #include <sys/vnode.h> | | 39 | #include <sys/vnode.h> |
40 | #include <sys/mount.h> | | 40 | #include <sys/mount.h> |
41 | #include <sys/fstrans.h> | | 41 | #include <sys/fstrans.h> |
42 | #include <sys/kauth.h> | | 42 | #include <sys/kauth.h> |
| @@ -64,52 +64,44 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c | | | @@ -64,52 +64,44 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c |
64 | | | 64 | |
65 | static int quota2_bwrite(struct mount *, struct buf *); | | 65 | static int quota2_bwrite(struct mount *, struct buf *); |
66 | static int getinoquota2(struct inode *, bool, bool, struct buf **, | | 66 | static int getinoquota2(struct inode *, bool, bool, struct buf **, |
67 | struct quota2_entry **); | | 67 | struct quota2_entry **); |
68 | static int getq2h(struct ufsmount *, int, struct buf **, | | 68 | static int getq2h(struct ufsmount *, int, struct buf **, |
69 | struct quota2_header **, int); | | 69 | struct quota2_header **, int); |
70 | static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **, | | 70 | static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **, |
71 | struct quota2_entry **, int); | | 71 | struct quota2_entry **, int); |
72 | static int quota2_walk_list(struct ufsmount *, struct buf *, int, | | 72 | static int quota2_walk_list(struct ufsmount *, struct buf *, int, |
73 | uint64_t *, int, void *, | | 73 | uint64_t *, int, void *, |
74 | int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, | | 74 | int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, |
75 | uint64_t, void *)); | | 75 | uint64_t, void *)); |
76 | | | 76 | |
77 | static int quota2_dict_update_q2e_limits(prop_dictionary_t, | | | |
78 | struct quota2_entry *); | | | |
79 | static prop_dictionary_t q2etoprop(struct quota2_entry *, int); | | 77 | static prop_dictionary_t q2etoprop(struct quota2_entry *, int); |
80 | | | 78 | |
81 | static const char *limnames[] = INITQLNAMES; | | 79 | static const char *limnames[] = INITQLNAMES; |
82 | | | 80 | |
83 | static int | | 81 | static void |
84 | quota2_dict_update_q2e_limits(prop_dictionary_t data, | | 82 | quota2_dict_update_q2e_limits(const struct quotaval *blocks, |
| | | 83 | const struct quotaval *files, |
85 | struct quota2_entry *q2e) | | 84 | struct quota2_entry *q2e) |
86 | { | | 85 | { |
87 | const char *val_limitsonly_names[] = INITQVNAMES_LIMITSONLY; | | 86 | q2e->q2e_val[QL_BLOCK].q2v_hardlimit = blocks->qv_hardlimit; |
88 | | | 87 | q2e->q2e_val[QL_BLOCK].q2v_softlimit = blocks->qv_softlimit; |
89 | int i, error; | | 88 | q2e->q2e_val[QL_BLOCK].q2v_grace = blocks->qv_grace; |
90 | prop_dictionary_t val; | | 89 | |
91 | | | 90 | q2e->q2e_val[QL_FILE].q2v_hardlimit = blocks->qv_hardlimit; |
92 | for (i = 0; i < N_QL; i++) { | | 91 | q2e->q2e_val[QL_FILE].q2v_softlimit = blocks->qv_softlimit; |
93 | if (!prop_dictionary_get_dict(data, limnames[i], &val)) | | 92 | q2e->q2e_val[QL_FILE].q2v_grace = blocks->qv_grace; |
94 | return EINVAL; | | | |
95 | error = quotaprop_dict_get_uint64(val, | | | |
96 | &q2e->q2e_val[i].q2v_hardlimit, | | | |
97 | val_limitsonly_names, N_QV, true); | | | |
98 | if (error) | | | |
99 | return error; | | | |
100 | } | | | |
101 | return 0; | | | |
102 | } | | 93 | } |
| | | 94 | |
103 | static prop_dictionary_t | | 95 | static prop_dictionary_t |
104 | q2etoprop(struct quota2_entry *q2e, int def) | | 96 | q2etoprop(struct quota2_entry *q2e, int def) |
105 | { | | 97 | { |
106 | const char *val_names[] = INITQVNAMES_ALL; | | 98 | const char *val_names[] = INITQVNAMES_ALL; |
107 | prop_dictionary_t dict1 = prop_dictionary_create(); | | 99 | prop_dictionary_t dict1 = prop_dictionary_create(); |
108 | prop_dictionary_t dict2; | | 100 | prop_dictionary_t dict2; |
109 | int i; | | 101 | int i; |
110 | | | 102 | |
111 | if (dict1 == NULL) | | 103 | if (dict1 == NULL) |
112 | return NULL; | | 104 | return NULL; |
113 | | | 105 | |
114 | if (def) { | | 106 | if (def) { |
115 | if (!prop_dictionary_set_cstring_nocopy(dict1, "id", | | 107 | if (!prop_dictionary_set_cstring_nocopy(dict1, "id", |
| @@ -611,84 +603,75 @@ int | | | @@ -611,84 +603,75 @@ int |
611 | chkdq2(struct inode *ip, int64_t change, kauth_cred_t cred, int flags) | | 603 | chkdq2(struct inode *ip, int64_t change, kauth_cred_t cred, int flags) |
612 | { | | 604 | { |
613 | return quota2_check(ip, QL_BLOCK, change, cred, flags); | | 605 | return quota2_check(ip, QL_BLOCK, change, cred, flags); |
614 | } | | 606 | } |
615 | | | 607 | |
616 | int | | 608 | int |
617 | chkiq2(struct inode *ip, int32_t change, kauth_cred_t cred, int flags) | | 609 | chkiq2(struct inode *ip, int32_t change, kauth_cred_t cred, int flags) |
618 | { | | 610 | { |
619 | return quota2_check(ip, QL_FILE, change, cred, flags); | | 611 | return quota2_check(ip, QL_FILE, change, cred, flags); |
620 | } | | 612 | } |
621 | | | 613 | |
622 | int | | 614 | int |
623 | quota2_handle_cmd_set(struct ufsmount *ump, int type, int id, | | 615 | quota2_handle_cmd_set(struct ufsmount *ump, int type, int id, |
624 | int defaultq, prop_dictionary_t data) | | 616 | int defaultq, const struct quotaval *blocks, const struct quotaval *files) |
625 | { | | 617 | { |
626 | int error; | | 618 | int error; |
627 | struct dquot *dq; | | 619 | struct dquot *dq; |
628 | struct quota2_header *q2h; | | 620 | struct quota2_header *q2h; |
629 | struct quota2_entry q2e, *q2ep; | | 621 | struct quota2_entry q2e, *q2ep; |
630 | struct buf *bp; | | 622 | struct buf *bp; |
631 | const int needswap = UFS_MPNEEDSWAP(ump); | | 623 | const int needswap = UFS_MPNEEDSWAP(ump); |
632 | | | 624 | |
633 | if (ump->um_quotas[type] == NULLVP) | | 625 | if (ump->um_quotas[type] == NULLVP) |
634 | return ENODEV; | | 626 | return ENODEV; |
635 | error = UFS_WAPBL_BEGIN(ump->um_mountp); | | 627 | error = UFS_WAPBL_BEGIN(ump->um_mountp); |
636 | if (error) | | 628 | if (error) |
637 | return error; | | 629 | return error; |
638 | | | 630 | |
639 | if (defaultq) { | | 631 | if (defaultq) { |
640 | mutex_enter(&dqlock); | | 632 | mutex_enter(&dqlock); |
641 | error = getq2h(ump, type, &bp, &q2h, B_MODIFY); | | 633 | error = getq2h(ump, type, &bp, &q2h, B_MODIFY); |
642 | if (error) { | | 634 | if (error) { |
643 | mutex_exit(&dqlock); | | 635 | mutex_exit(&dqlock); |
644 | goto out_wapbl; | | 636 | goto out_wapbl; |
645 | } | | 637 | } |
646 | quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); | | 638 | quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); |
647 | error = quota2_dict_update_q2e_limits(data, &q2e); | | 639 | quota2_dict_update_q2e_limits(blocks, files, &q2e); |
648 | if (error) { | | | |
649 | mutex_exit(&dqlock); | | | |
650 | brelse(bp, 0); | | | |
651 | goto out_wapbl; | | | |
652 | } | | | |
653 | quota2_ufs_rwq2e(&q2e, &q2h->q2h_defentry, needswap); | | 640 | quota2_ufs_rwq2e(&q2e, &q2h->q2h_defentry, needswap); |
654 | mutex_exit(&dqlock); | | 641 | mutex_exit(&dqlock); |
655 | quota2_bwrite(ump->um_mountp, bp); | | 642 | quota2_bwrite(ump->um_mountp, bp); |
656 | goto out_wapbl; | | 643 | goto out_wapbl; |
657 | } | | 644 | } |
658 | | | 645 | |
659 | error = dqget(NULLVP, id, ump, type, &dq); | | 646 | error = dqget(NULLVP, id, ump, type, &dq); |
660 | if (error) | | 647 | if (error) |
661 | goto out_wapbl; | | 648 | goto out_wapbl; |
662 | | | 649 | |
663 | mutex_enter(&dq->dq_interlock); | | 650 | mutex_enter(&dq->dq_interlock); |
664 | if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { | | 651 | if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { |
665 | /* need to alloc a new on-disk quot */ | | 652 | /* need to alloc a new on-disk quot */ |
666 | mutex_enter(&dqlock); | | 653 | mutex_enter(&dqlock); |
667 | error = quota2_q2ealloc(ump, type, id, dq, &bp, &q2ep); | | 654 | error = quota2_q2ealloc(ump, type, id, dq, &bp, &q2ep); |
668 | mutex_exit(&dqlock); | | 655 | mutex_exit(&dqlock); |
669 | } else { | | 656 | } else { |
670 | error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff, | | 657 | error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff, |
671 | &bp, &q2ep, B_MODIFY); | | 658 | &bp, &q2ep, B_MODIFY); |
672 | } | | 659 | } |
673 | if (error) | | 660 | if (error) |
674 | goto out_il; | | 661 | goto out_il; |
675 | | | 662 | |
676 | quota2_ufs_rwq2e(q2ep, &q2e, needswap); | | 663 | quota2_ufs_rwq2e(q2ep, &q2e, needswap); |
677 | error = quota2_dict_update_q2e_limits(data, &q2e); | | 664 | quota2_dict_update_q2e_limits(blocks, files, &q2e); |
678 | if (error) { | | | |
679 | brelse(bp, 0); | | | |
680 | goto out_il; | | | |
681 | } | | | |
682 | quota2_ufs_rwq2e(&q2e, q2ep, needswap); | | 665 | quota2_ufs_rwq2e(&q2e, q2ep, needswap); |
683 | quota2_bwrite(ump->um_mountp, bp); | | 666 | quota2_bwrite(ump->um_mountp, bp); |
684 | | | 667 | |
685 | out_il: | | 668 | out_il: |
686 | mutex_exit(&dq->dq_interlock); | | 669 | mutex_exit(&dq->dq_interlock); |
687 | dqrele(NULLVP, dq); | | 670 | dqrele(NULLVP, dq); |
688 | out_wapbl: | | 671 | out_wapbl: |
689 | UFS_WAPBL_END(ump->um_mountp); | | 672 | UFS_WAPBL_END(ump->um_mountp); |
690 | return error; | | 673 | return error; |
691 | } | | 674 | } |
692 | | | 675 | |
693 | struct dq2clear_callback { | | 676 | struct dq2clear_callback { |
694 | uid_t id; | | 677 | uid_t id; |