| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ufs_quota2.c,v 1.19 2012/01/29 07:03:47 dholland Exp $ */ | | 1 | /* $NetBSD: ufs_quota2.c,v 1.20 2012/01/29 07:04:21 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.19 2012/01/29 07:03:47 dholland Exp $"); | | 29 | __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.20 2012/01/29 07:04:21 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> |
| @@ -951,90 +951,121 @@ quota2_handle_cmd_get(struct ufsmount *u | | | @@ -951,90 +951,121 @@ quota2_handle_cmd_get(struct ufsmount *u |
951 | (void)id2; | | 951 | (void)id2; |
952 | } else | | 952 | } else |
953 | error = quota2_fetch_q2e(ump, qk, ret); | | 953 | error = quota2_fetch_q2e(ump, qk, ret); |
954 | | | 954 | |
955 | return error; | | 955 | return error; |
956 | } | | 956 | } |
957 | | | 957 | |
958 | struct ufsq2_cursor { | | 958 | struct ufsq2_cursor { |
959 | uint32_t q2c_magic; /* magic number */ | | 959 | uint32_t q2c_magic; /* magic number */ |
960 | int q2c_hashsize; /* size of hash table at last go */ | | 960 | int q2c_hashsize; /* size of hash table at last go */ |
961 | | | 961 | |
962 | int q2c_defaults_done; /* true if we've returned the default values */ | | 962 | int q2c_defaults_done; /* true if we've returned the default values */ |
963 | int q2c_hashpos; /* slot to start at in hash table */ | | 963 | int q2c_hashpos; /* slot to start at in hash table */ |
| | | 964 | int q2c_uidpos; /* number of ids we've handled */ |
964 | int q2c_blocks_done; /* true if we've returned the blocks value */ | | 965 | int q2c_blocks_done; /* true if we've returned the blocks value */ |
965 | }; | | 966 | }; |
966 | | | 967 | |
967 | #define Q2C_MAGIC (0xbeebe111) | | 968 | #define Q2C_MAGIC (0xbeebe111) |
968 | | | 969 | |
969 | #define Q2CURSOR(qkc) ((struct ufsq2_cursor *)&qkc->u.qkc_space[0]) | | 970 | #define Q2CURSOR(qkc) ((struct ufsq2_cursor *)&qkc->u.qkc_space[0]) |
970 | | | 971 | |
| | | 972 | static int |
| | | 973 | q2cursor_check(struct ufsq2_cursor *cursor) |
| | | 974 | { |
| | | 975 | if (cursor->q2c_magic != Q2C_MAGIC) { |
| | | 976 | return EINVAL; |
| | | 977 | } |
| | | 978 | if (cursor->q2c_hashsize < 0) { |
| | | 979 | return EINVAL; |
| | | 980 | } |
| | | 981 | |
| | | 982 | if (cursor->q2c_defaults_done != 0 && cursor->q2c_defaults_done != 1) { |
| | | 983 | return EINVAL; |
| | | 984 | } |
| | | 985 | if (cursor->q2c_hashpos < 0 || cursor->q2c_uidpos < 0) { |
| | | 986 | return EINVAL; |
| | | 987 | } |
| | | 988 | if (cursor->q2c_blocks_done != 0 && cursor->q2c_blocks_done != 1) { |
| | | 989 | return EINVAL; |
| | | 990 | } |
| | | 991 | return 0; |
| | | 992 | } |
971 | | | 993 | |
972 | struct getuids { | | 994 | struct getuids { |
973 | long nuids; /* number of uids in array */ | | 995 | long nuids; /* number of uids in array */ |
974 | long size; /* size of array */ | | 996 | long size; /* size of array */ |
975 | uid_t *uids; /* array of uids, dynamically allocated */ | | 997 | uid_t *uids; /* array of uids, dynamically allocated */ |
| | | 998 | long skip; |
| | | 999 | long seen; |
976 | }; | | 1000 | }; |
977 | | | 1001 | |
978 | static int | | 1002 | static int |
979 | quota2_getuids_callback(struct ufsmount *ump, uint64_t *offp, | | 1003 | quota2_getuids_callback(struct ufsmount *ump, uint64_t *offp, |
980 | struct quota2_entry *q2ep, uint64_t off, void *v) | | 1004 | struct quota2_entry *q2ep, uint64_t off, void *v) |
981 | { | | 1005 | { |
982 | struct getuids *gu = v; | | 1006 | struct getuids *gu = v; |
983 | uid_t *newuids; | | 1007 | uid_t *newuids; |
984 | #ifdef FFS_EI | | 1008 | #ifdef FFS_EI |
985 | const int needswap = UFS_MPNEEDSWAP(ump); | | 1009 | const int needswap = UFS_MPNEEDSWAP(ump); |
986 | #endif | | 1010 | #endif |
987 | | | 1011 | |
| | | 1012 | if (gu->skip > 0) { |
| | | 1013 | gu->skip--; |
| | | 1014 | return 0; |
| | | 1015 | } |
988 | if (gu->nuids == gu->size) { | | 1016 | if (gu->nuids == gu->size) { |
989 | newuids = realloc(gu->uids, gu->size + PAGE_SIZE, M_TEMP, | | 1017 | newuids = realloc(gu->uids, gu->size + PAGE_SIZE, M_TEMP, |
990 | M_WAITOK); | | 1018 | M_WAITOK); |
991 | if (newuids == NULL) { | | 1019 | if (newuids == NULL) { |
992 | free(gu->uids, M_TEMP); | | 1020 | free(gu->uids, M_TEMP); |
993 | return ENOMEM; | | 1021 | return ENOMEM; |
994 | } | | 1022 | } |
995 | gu->uids = newuids; | | 1023 | gu->uids = newuids; |
996 | gu->size += (PAGE_SIZE / sizeof(uid_t)); | | 1024 | gu->size += (PAGE_SIZE / sizeof(uid_t)); |
997 | } | | 1025 | } |
998 | gu->uids[gu->nuids] = ufs_rw32(q2ep->q2e_uid, needswap); | | 1026 | gu->uids[gu->nuids] = ufs_rw32(q2ep->q2e_uid, needswap); |
999 | gu->nuids++; | | 1027 | gu->nuids++; |
| | | 1028 | gu->seen++; |
1000 | return 0; | | 1029 | return 0; |
1001 | } | | 1030 | } |
1002 | | | 1031 | |
1003 | int | | 1032 | int |
1004 | quota2_handle_cmd_getall(struct ufsmount *ump, struct quotakcursor *qkc, | | 1033 | quota2_handle_cmd_getall(struct ufsmount *ump, struct quotakcursor *qkc, |
1005 | int idtype, struct quota_getall_result *result) | | 1034 | int idtype, struct quota_getall_result *result) |
1006 | { | | 1035 | { |
1007 | int error; | | 1036 | int error; |
1008 | struct ufsq2_cursor *cursor; | | 1037 | struct ufsq2_cursor *cursor; |
1009 | struct quota2_header *q2h; | | 1038 | struct quota2_header *q2h; |
1010 | struct quota2_entry q2e; | | 1039 | struct quota2_entry q2e; |
1011 | struct buf *hbp; | | 1040 | struct buf *hbp; |
1012 | uint64_t offset; | | 1041 | uint64_t offset; |
1013 | int i, j; | | 1042 | int i, j; |
1014 | int quota2_hash_size; | | 1043 | int quota2_hash_size; |
1015 | const int needswap = UFS_MPNEEDSWAP(ump); | | 1044 | const int needswap = UFS_MPNEEDSWAP(ump); |
1016 | struct getuids gu; | | 1045 | struct getuids gu; |
1017 | id_t junkid; | | 1046 | id_t junkid; |
1018 | struct quotaval qv; | | 1047 | struct quotaval qv; |
1019 | unsigned num, maxnum; | | 1048 | unsigned num, maxnum; |
1020 | | | 1049 | |
1021 | cursor = Q2CURSOR(qkc); | | 1050 | cursor = Q2CURSOR(qkc); |
1022 | if (cursor->q2c_magic != Q2C_MAGIC) { | | 1051 | error = q2cursor_check(cursor); |
1023 | return EINVAL; | | 1052 | if (error) { |
| | | 1053 | return error; |
1024 | } | | 1054 | } |
1025 | | | 1055 | |
1026 | if (ump->um_quotas[idtype] == NULLVP) | | 1056 | if (ump->um_quotas[idtype] == NULLVP) { |
1027 | return ENODEV; | | 1057 | return ENODEV; |
| | | 1058 | } |
1028 | | | 1059 | |
1029 | mutex_enter(&dqlock); | | 1060 | mutex_enter(&dqlock); |
1030 | error = getq2h(ump, idtype, &hbp, &q2h, 0); | | 1061 | error = getq2h(ump, idtype, &hbp, &q2h, 0); |
1031 | if (error) { | | 1062 | if (error) { |
1032 | mutex_exit(&dqlock); | | 1063 | mutex_exit(&dqlock); |
1033 | return error; | | 1064 | return error; |
1034 | } | | 1065 | } |
1035 | | | 1066 | |
1036 | if (cursor->q2c_defaults_done == 0) { | | 1067 | if (cursor->q2c_defaults_done == 0) { |
1037 | quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); | | 1068 | quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); |
1038 | if (cursor->q2c_blocks_done == 0) { | | 1069 | if (cursor->q2c_blocks_done == 0) { |
1039 | q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &qv); | | 1070 | q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &qv); |
1040 | result->qr_defblocks = qv; | | 1071 | result->qr_defblocks = qv; |
| @@ -1055,43 +1086,41 @@ quota2_handle_cmd_getall(struct ufsmount | | | @@ -1055,43 +1086,41 @@ quota2_handle_cmd_getall(struct ufsmount |
1055 | * and then read entries for these uids | | 1086 | * and then read entries for these uids |
1056 | */ | | 1087 | */ |
1057 | memset(&gu, 0, sizeof(gu)); | | 1088 | memset(&gu, 0, sizeof(gu)); |
1058 | quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap); | | 1089 | quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap); |
1059 | | | 1090 | |
1060 | /* if the table size has changed, make the caller start over */ | | 1091 | /* if the table size has changed, make the caller start over */ |
1061 | if (cursor->q2c_hashsize == 0) { | | 1092 | if (cursor->q2c_hashsize == 0) { |
1062 | cursor->q2c_hashsize = quota2_hash_size; | | 1093 | cursor->q2c_hashsize = quota2_hash_size; |
1063 | } else if (cursor->q2c_hashsize != quota2_hash_size) { | | 1094 | } else if (cursor->q2c_hashsize != quota2_hash_size) { |
1064 | error = EDEADLK; | | 1095 | error = EDEADLK; |
1065 | goto fail; | | 1096 | goto fail; |
1066 | } | | 1097 | } |
1067 | | | 1098 | |
1068 | /* why are these variables signed? */ | | 1099 | gu.skip = cursor->q2c_uidpos; |
1069 | if (cursor->q2c_hashpos < 0) { | | 1100 | gu.seen = 0; |
1070 | error = EINVAL; | | | |
1071 | goto fail; | | | |
1072 | } | | | |
1073 | | | | |
1074 | for (i = cursor->q2c_hashpos; i < quota2_hash_size ; i++) { | | 1101 | for (i = cursor->q2c_hashpos; i < quota2_hash_size ; i++) { |
1075 | offset = q2h->q2h_entries[i]; | | 1102 | offset = q2h->q2h_entries[i]; |
| | | 1103 | gu.seen = 0; |
1076 | error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu, | | 1104 | error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu, |
1077 | quota2_getuids_callback); | | 1105 | quota2_getuids_callback); |
1078 | if (error) { | | 1106 | if (error) { |
1079 | if (gu.uids != NULL) | | 1107 | if (gu.uids != NULL) |
1080 | free(gu.uids, M_TEMP); | | 1108 | free(gu.uids, M_TEMP); |
1081 | break; | | 1109 | break; |
1082 | } | | 1110 | } |
1083 | } | | 1111 | } |
1084 | cursor->q2c_hashpos = i; | | 1112 | cursor->q2c_hashpos = i; |
| | | 1113 | cursor->q2c_uidpos = gu.seen; |
1085 | | | 1114 | |
1086 | fail: | | 1115 | fail: |
1087 | mutex_exit(&dqlock); | | 1116 | mutex_exit(&dqlock); |
1088 | brelse(hbp, 0); | | 1117 | brelse(hbp, 0); |
1089 | if (error) | | 1118 | if (error) |
1090 | return error; | | 1119 | return error; |
1091 | | | 1120 | |
1092 | maxnum = gu.nuids*2; | | 1121 | maxnum = gu.nuids*2; |
1093 | result->qr_keys = malloc(maxnum * sizeof(result->qr_keys[0]), | | 1122 | result->qr_keys = malloc(maxnum * sizeof(result->qr_keys[0]), |
1094 | M_TEMP, M_WAITOK); | | 1123 | M_TEMP, M_WAITOK); |
1095 | result->qr_vals = malloc(maxnum * sizeof(result->qr_vals[0]), | | 1124 | result->qr_vals = malloc(maxnum * sizeof(result->qr_vals[0]), |
1096 | M_TEMP, M_WAITOK); | | 1125 | M_TEMP, M_WAITOK); |
1097 | | | 1126 | |
| @@ -1111,40 +1140,44 @@ fail: | | | @@ -1111,40 +1140,44 @@ fail: |
1111 | return error; | | 1140 | return error; |
1112 | } | | 1141 | } |
1113 | | | 1142 | |
1114 | int | | 1143 | int |
1115 | quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc) | | 1144 | quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc) |
1116 | { | | 1145 | { |
1117 | struct ufsq2_cursor *cursor; | | 1146 | struct ufsq2_cursor *cursor; |
1118 | | | 1147 | |
1119 | CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space)); | | 1148 | CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space)); |
1120 | cursor = Q2CURSOR(qkc); | | 1149 | cursor = Q2CURSOR(qkc); |
1121 | | | 1150 | |
1122 | cursor->q2c_magic = Q2C_MAGIC; | | 1151 | cursor->q2c_magic = Q2C_MAGIC; |
1123 | cursor->q2c_hashsize = 0; | | 1152 | cursor->q2c_hashsize = 0; |
1124 | cursor->q2c_hashpos = 0; | | 1153 | |
1125 | cursor->q2c_defaults_done = 0; | | 1154 | cursor->q2c_defaults_done = 0; |
| | | 1155 | cursor->q2c_hashpos = 0; |
| | | 1156 | cursor->q2c_uidpos = 0; |
1126 | cursor->q2c_blocks_done = 0; | | 1157 | cursor->q2c_blocks_done = 0; |
1127 | return 0; | | 1158 | return 0; |
1128 | } | | 1159 | } |
1129 | | | 1160 | |
1130 | int | | 1161 | int |
1131 | quota2_handle_cmd_cursorclose(struct ufsmount *ump, struct quotakcursor *qkc) | | 1162 | quota2_handle_cmd_cursorclose(struct ufsmount *ump, struct quotakcursor *qkc) |
1132 | { | | 1163 | { |
1133 | struct ufsq2_cursor *cursor; | | 1164 | struct ufsq2_cursor *cursor; |
| | | 1165 | int error; |
1134 | | | 1166 | |
1135 | cursor = Q2CURSOR(qkc); | | 1167 | cursor = Q2CURSOR(qkc); |
1136 | if (cursor->q2c_magic != Q2C_MAGIC) { | | 1168 | error = q2cursor_check(cursor); |
1137 | return EINVAL; | | 1169 | if (error) { |
| | | 1170 | return error; |
1138 | } | | 1171 | } |
1139 | | | 1172 | |
1140 | /* nothing to do */ | | 1173 | /* nothing to do */ |
1141 | | | 1174 | |
1142 | return 0; | | 1175 | return 0; |
1143 | } | | 1176 | } |
1144 | | | 1177 | |
1145 | int | | 1178 | int |
1146 | q2sync(struct mount *mp) | | 1179 | q2sync(struct mount *mp) |
1147 | { | | 1180 | { |
1148 | return 0; | | 1181 | return 0; |
1149 | } | | 1182 | } |
1150 | | | 1183 | |