1 1.118 riastrad /* $NetBSD: ufs_quota.c,v 1.118 2023/02/22 21:49:45 riastradh Exp $ */ 2 1.2 cgd 3 1.1 mycroft /* 4 1.11 fvdl * Copyright (c) 1982, 1986, 1990, 1993, 1995 5 1.1 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 mycroft * 7 1.1 mycroft * This code is derived from software contributed to Berkeley by 8 1.1 mycroft * Robert Elz at The University of Melbourne. 9 1.1 mycroft * 10 1.1 mycroft * Redistribution and use in source and binary forms, with or without 11 1.1 mycroft * modification, are permitted provided that the following conditions 12 1.1 mycroft * are met: 13 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 14 1.1 mycroft * notice, this list of conditions and the following disclaimer. 15 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 17 1.1 mycroft * documentation and/or other materials provided with the distribution. 18 1.28 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 mycroft * may be used to endorse or promote products derived from this software 20 1.1 mycroft * without specific prior written permission. 21 1.1 mycroft * 22 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 mycroft * SUCH DAMAGE. 33 1.1 mycroft * 34 1.11 fvdl * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 35 1.1 mycroft */ 36 1.22 lukem 37 1.22 lukem #include <sys/cdefs.h> 38 1.118 riastrad __KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.118 2023/02/22 21:49:45 riastradh Exp $"); 39 1.22 lukem 40 1.69 bouyer #if defined(_KERNEL_OPT) 41 1.69 bouyer #include "opt_quota.h" 42 1.118 riastrad #endif 43 1.1 mycroft #include <sys/param.h> 44 1.1 mycroft #include <sys/kernel.h> 45 1.1 mycroft #include <sys/systm.h> 46 1.1 mycroft #include <sys/namei.h> 47 1.1 mycroft #include <sys/file.h> 48 1.1 mycroft #include <sys/proc.h> 49 1.1 mycroft #include <sys/vnode.h> 50 1.1 mycroft #include <sys/mount.h> 51 1.39 elad #include <sys/kauth.h> 52 1.1 mycroft 53 1.71 dholland #include <sys/quotactl.h> 54 1.1 mycroft #include <ufs/ufs/quota.h> 55 1.1 mycroft #include <ufs/ufs/inode.h> 56 1.1 mycroft #include <ufs/ufs/ufsmount.h> 57 1.1 mycroft #include <ufs/ufs/ufs_extern.h> 58 1.69 bouyer #include <ufs/ufs/ufs_quota.h> 59 1.1 mycroft 60 1.69 bouyer kmutex_t dqlock; 61 1.69 bouyer kcondvar_t dqcv; 62 1.110 dholland const char *quotatypes[MAXQUOTAS] = INITQFNAMES; 63 1.48 hannken 64 1.48 hannken /* 65 1.69 bouyer * Code pertaining to management of the in-core dquot data structures. 66 1.1 mycroft */ 67 1.69 bouyer #define DQHASH(dqvp, id) \ 68 1.69 bouyer (((((long)(dqvp)) >> 8) + id) & dqhash) 69 1.69 bouyer static LIST_HEAD(dqhashhead, dquot) *dqhashtbl; 70 1.69 bouyer static u_long dqhash; 71 1.69 bouyer static pool_cache_t dquot_cache; 72 1.1 mycroft 73 1.1 mycroft 74 1.101 dholland static int quota_handle_cmd_stat(struct mount *, struct lwp *, 75 1.107 dholland struct quotactl_args *args); 76 1.106 dholland static int quota_handle_cmd_idtypestat(struct mount *, struct lwp *, 77 1.107 dholland struct quotactl_args *args); 78 1.106 dholland static int quota_handle_cmd_objtypestat(struct mount *, struct lwp *, 79 1.107 dholland struct quotactl_args *args); 80 1.69 bouyer static int quota_handle_cmd_get(struct mount *, struct lwp *, 81 1.107 dholland struct quotactl_args *args); 82 1.85 dholland static int quota_handle_cmd_put(struct mount *, struct lwp *, 83 1.107 dholland struct quotactl_args *args); 84 1.98 dholland static int quota_handle_cmd_cursorget(struct mount *, struct lwp *, 85 1.107 dholland struct quotactl_args *args); 86 1.117 dholland static int quota_handle_cmd_del(struct mount *, struct lwp *, 87 1.107 dholland struct quotactl_args *args); 88 1.118 riastrad static int quota_handle_cmd_quotaon(struct mount *, struct lwp *, 89 1.107 dholland struct quotactl_args *args); 90 1.118 riastrad static int quota_handle_cmd_quotaoff(struct mount *, struct lwp *, 91 1.107 dholland struct quotactl_args *args); 92 1.93 dholland static int quota_handle_cmd_cursoropen(struct mount *, struct lwp *, 93 1.107 dholland struct quotactl_args *args); 94 1.93 dholland static int quota_handle_cmd_cursorclose(struct mount *, struct lwp *, 95 1.107 dholland struct quotactl_args *args); 96 1.98 dholland static int quota_handle_cmd_cursorskipidtype(struct mount *, struct lwp *, 97 1.107 dholland struct quotactl_args *args); 98 1.98 dholland static int quota_handle_cmd_cursoratend(struct mount *, struct lwp *, 99 1.107 dholland struct quotactl_args *args); 100 1.98 dholland static int quota_handle_cmd_cursorrewind(struct mount *, struct lwp *, 101 1.107 dholland struct quotactl_args *args); 102 1.72 dholland 103 1.1 mycroft /* 104 1.48 hannken * Initialize the quota fields of an inode. 105 1.48 hannken */ 106 1.48 hannken void 107 1.48 hannken ufsquota_init(struct inode *ip) 108 1.48 hannken { 109 1.48 hannken int i; 110 1.48 hannken 111 1.48 hannken for (i = 0; i < MAXQUOTAS; i++) 112 1.48 hannken ip->i_dquot[i] = NODQUOT; 113 1.48 hannken } 114 1.48 hannken 115 1.48 hannken /* 116 1.48 hannken * Release the quota fields from an inode. 117 1.48 hannken */ 118 1.48 hannken void 119 1.48 hannken ufsquota_free(struct inode *ip) 120 1.48 hannken { 121 1.48 hannken int i; 122 1.48 hannken 123 1.48 hannken for (i = 0; i < MAXQUOTAS; i++) { 124 1.48 hannken dqrele(ITOV(ip), ip->i_dquot[i]); 125 1.48 hannken ip->i_dquot[i] = NODQUOT; 126 1.48 hannken } 127 1.48 hannken } 128 1.48 hannken 129 1.48 hannken /* 130 1.1 mycroft * Update disk usage, and take corrective action. 131 1.1 mycroft */ 132 1.1 mycroft int 133 1.39 elad chkdq(struct inode *ip, int64_t change, kauth_cred_t cred, int flags) 134 1.1 mycroft { 135 1.69 bouyer /* do not track snapshot usage, or we will deadlock */ 136 1.69 bouyer if ((ip->i_flags & SF_SNAPSHOT) != 0) 137 1.69 bouyer return 0; 138 1.1 mycroft 139 1.69 bouyer #ifdef QUOTA 140 1.69 bouyer if (ip->i_ump->um_flags & UFS_QUOTA) 141 1.69 bouyer return chkdq1(ip, change, cred, flags); 142 1.69 bouyer #endif 143 1.69 bouyer #ifdef QUOTA2 144 1.69 bouyer if (ip->i_ump->um_flags & UFS_QUOTA2) 145 1.69 bouyer return chkdq2(ip, change, cred, flags); 146 1.69 bouyer #endif 147 1.69 bouyer return 0; 148 1.1 mycroft } 149 1.1 mycroft 150 1.1 mycroft /* 151 1.69 bouyer * Check the inode limit, applying corrective action. 152 1.1 mycroft */ 153 1.69 bouyer int 154 1.69 bouyer chkiq(struct inode *ip, int32_t change, kauth_cred_t cred, int flags) 155 1.1 mycroft { 156 1.69 bouyer /* do not track snapshot usage, or we will deadlock */ 157 1.69 bouyer if ((ip->i_flags & SF_SNAPSHOT) != 0) 158 1.69 bouyer return 0; 159 1.69 bouyer #ifdef QUOTA 160 1.69 bouyer if (ip->i_ump->um_flags & UFS_QUOTA) 161 1.69 bouyer return chkiq1(ip, change, cred, flags); 162 1.69 bouyer #endif 163 1.69 bouyer #ifdef QUOTA2 164 1.69 bouyer if (ip->i_ump->um_flags & UFS_QUOTA2) 165 1.69 bouyer return chkiq2(ip, change, cred, flags); 166 1.69 bouyer #endif 167 1.69 bouyer return 0; 168 1.1 mycroft } 169 1.1 mycroft 170 1.1 mycroft int 171 1.103 dholland quota_handle_cmd(struct mount *mp, struct lwp *l, 172 1.107 dholland struct quotactl_args *args) 173 1.69 bouyer { 174 1.69 bouyer int error = 0; 175 1.69 bouyer 176 1.103 dholland switch (args->qc_op) { 177 1.118 riastrad case QUOTACTL_STAT: 178 1.101 dholland error = quota_handle_cmd_stat(mp, l, args); 179 1.71 dholland break; 180 1.118 riastrad case QUOTACTL_IDTYPESTAT: 181 1.106 dholland error = quota_handle_cmd_idtypestat(mp, l, args); 182 1.106 dholland break; 183 1.118 riastrad case QUOTACTL_OBJTYPESTAT: 184 1.106 dholland error = quota_handle_cmd_objtypestat(mp, l, args); 185 1.106 dholland break; 186 1.118 riastrad case QUOTACTL_QUOTAON: 187 1.72 dholland error = quota_handle_cmd_quotaon(mp, l, args); 188 1.71 dholland break; 189 1.118 riastrad case QUOTACTL_QUOTAOFF: 190 1.72 dholland error = quota_handle_cmd_quotaoff(mp, l, args); 191 1.71 dholland break; 192 1.118 riastrad case QUOTACTL_GET: 193 1.72 dholland error = quota_handle_cmd_get(mp, l, args); 194 1.71 dholland break; 195 1.118 riastrad case QUOTACTL_PUT: 196 1.85 dholland error = quota_handle_cmd_put(mp, l, args); 197 1.71 dholland break; 198 1.118 riastrad case QUOTACTL_CURSORGET: 199 1.98 dholland error = quota_handle_cmd_cursorget(mp, l, args); 200 1.71 dholland break; 201 1.118 riastrad case QUOTACTL_DEL: 202 1.117 dholland error = quota_handle_cmd_del(mp, l, args); 203 1.71 dholland break; 204 1.118 riastrad case QUOTACTL_CURSOROPEN: 205 1.93 dholland error = quota_handle_cmd_cursoropen(mp, l, args); 206 1.93 dholland break; 207 1.118 riastrad case QUOTACTL_CURSORCLOSE: 208 1.93 dholland error = quota_handle_cmd_cursorclose(mp, l, args); 209 1.93 dholland break; 210 1.118 riastrad case QUOTACTL_CURSORSKIPIDTYPE: 211 1.98 dholland error = quota_handle_cmd_cursorskipidtype(mp, l, args); 212 1.98 dholland break; 213 1.118 riastrad case QUOTACTL_CURSORATEND: 214 1.98 dholland error = quota_handle_cmd_cursoratend(mp, l, args); 215 1.98 dholland break; 216 1.118 riastrad case QUOTACTL_CURSORREWIND: 217 1.98 dholland error = quota_handle_cmd_cursorrewind(mp, l, args); 218 1.98 dholland break; 219 1.118 riastrad default: 220 1.103 dholland panic("Invalid quotactl operation %d\n", args->qc_op); 221 1.69 bouyer } 222 1.71 dholland 223 1.69 bouyer return error; 224 1.69 bouyer } 225 1.69 bouyer 226 1.118 riastrad static int 227 1.118 riastrad quota_handle_cmd_stat(struct mount *mp, struct lwp *l, 228 1.107 dholland struct quotactl_args *args) 229 1.1 mycroft { 230 1.69 bouyer struct ufsmount *ump = VFSTOUFS(mp); 231 1.108 dholland struct quotastat *info; 232 1.72 dholland 233 1.102 dholland KASSERT(args->qc_op == QUOTACTL_STAT); 234 1.108 dholland info = args->u.stat.qc_info; 235 1.69 bouyer 236 1.69 bouyer if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 237 1.69 bouyer return EOPNOTSUPP; 238 1.69 bouyer 239 1.69 bouyer #ifdef QUOTA 240 1.69 bouyer if (ump->um_flags & UFS_QUOTA) { 241 1.108 dholland strcpy(info->qs_implname, "ufs/ffs quota v1"); 242 1.108 dholland info->qs_numidtypes = MAXQUOTAS; 243 1.101 dholland /* XXX no define for this */ 244 1.108 dholland info->qs_numobjtypes = 2; 245 1.108 dholland info->qs_restrictions = 0; 246 1.108 dholland info->qs_restrictions |= QUOTA_RESTRICT_NEEDSQUOTACHECK; 247 1.108 dholland info->qs_restrictions |= QUOTA_RESTRICT_UNIFORMGRACE; 248 1.108 dholland info->qs_restrictions |= QUOTA_RESTRICT_32BIT; 249 1.69 bouyer } else 250 1.69 bouyer #endif 251 1.69 bouyer #ifdef QUOTA2 252 1.69 bouyer if (ump->um_flags & UFS_QUOTA2) { 253 1.108 dholland strcpy(info->qs_implname, "ufs/ffs quota v2"); 254 1.108 dholland info->qs_numidtypes = MAXQUOTAS; 255 1.108 dholland info->qs_numobjtypes = N_QL; 256 1.108 dholland info->qs_restrictions = 0; 257 1.69 bouyer } else 258 1.69 bouyer #endif 259 1.73 dholland return EOPNOTSUPP; 260 1.73 dholland 261 1.73 dholland return 0; 262 1.1 mycroft } 263 1.1 mycroft 264 1.118 riastrad static int 265 1.118 riastrad quota_handle_cmd_idtypestat(struct mount *mp, struct lwp *l, 266 1.107 dholland struct quotactl_args *args) 267 1.106 dholland { 268 1.106 dholland struct ufsmount *ump = VFSTOUFS(mp); 269 1.106 dholland int idtype; 270 1.106 dholland struct quotaidtypestat *info; 271 1.106 dholland const char *name; 272 1.106 dholland 273 1.106 dholland KASSERT(args->qc_op == QUOTACTL_IDTYPESTAT); 274 1.106 dholland idtype = args->u.idtypestat.qc_idtype; 275 1.106 dholland info = args->u.idtypestat.qc_info; 276 1.106 dholland 277 1.106 dholland if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 278 1.106 dholland return EOPNOTSUPP; 279 1.106 dholland 280 1.106 dholland /* 281 1.106 dholland * These are the same for both QUOTA and QUOTA2. 282 1.106 dholland */ 283 1.106 dholland switch (idtype) { 284 1.118 riastrad case QUOTA_IDTYPE_USER: 285 1.106 dholland name = "user"; 286 1.106 dholland break; 287 1.118 riastrad case QUOTA_IDTYPE_GROUP: 288 1.106 dholland name = "group"; 289 1.106 dholland break; 290 1.118 riastrad default: 291 1.106 dholland return EINVAL; 292 1.106 dholland } 293 1.106 dholland strlcpy(info->qis_name, name, sizeof(info->qis_name)); 294 1.106 dholland return 0; 295 1.106 dholland } 296 1.106 dholland 297 1.118 riastrad static int 298 1.118 riastrad quota_handle_cmd_objtypestat(struct mount *mp, struct lwp *l, 299 1.107 dholland struct quotactl_args *args) 300 1.106 dholland { 301 1.106 dholland struct ufsmount *ump = VFSTOUFS(mp); 302 1.106 dholland int objtype; 303 1.106 dholland struct quotaobjtypestat *info; 304 1.106 dholland const char *name; 305 1.106 dholland int isbytes; 306 1.106 dholland 307 1.106 dholland KASSERT(args->qc_op == QUOTACTL_OBJTYPESTAT); 308 1.106 dholland objtype = args->u.objtypestat.qc_objtype; 309 1.106 dholland info = args->u.objtypestat.qc_info; 310 1.106 dholland 311 1.106 dholland if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 312 1.106 dholland return EOPNOTSUPP; 313 1.106 dholland 314 1.106 dholland /* 315 1.106 dholland * These are the same for both QUOTA and QUOTA2. 316 1.106 dholland */ 317 1.106 dholland switch (objtype) { 318 1.118 riastrad case QUOTA_OBJTYPE_BLOCKS: 319 1.106 dholland name = "block"; 320 1.106 dholland isbytes = 1; 321 1.106 dholland break; 322 1.118 riastrad case QUOTA_OBJTYPE_FILES: 323 1.106 dholland name = "file"; 324 1.106 dholland isbytes = 0; 325 1.106 dholland break; 326 1.118 riastrad default: 327 1.106 dholland return EINVAL; 328 1.106 dholland } 329 1.106 dholland strlcpy(info->qos_name, name, sizeof(info->qos_name)); 330 1.106 dholland info->qos_isbytes = isbytes; 331 1.106 dholland return 0; 332 1.106 dholland } 333 1.106 dholland 334 1.69 bouyer /* XXX shouldn't all this be in kauth ? */ 335 1.48 hannken static int 336 1.69 bouyer quota_get_auth(struct mount *mp, struct lwp *l, uid_t id) { 337 1.69 bouyer /* The user can always query about his own quota. */ 338 1.112 manu if (id == kauth_cred_geteuid(l->l_cred)) 339 1.69 bouyer return 0; 340 1.69 bouyer return kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 341 1.69 bouyer KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(id), NULL); 342 1.69 bouyer } 343 1.69 bouyer 344 1.118 riastrad static int 345 1.118 riastrad quota_handle_cmd_get(struct mount *mp, struct lwp *l, 346 1.107 dholland struct quotactl_args *args) 347 1.69 bouyer { 348 1.69 bouyer struct ufsmount *ump = VFSTOUFS(mp); 349 1.74 dholland int error; 350 1.78 dholland const struct quotakey *qk; 351 1.108 dholland struct quotaval *qv; 352 1.72 dholland 353 1.102 dholland KASSERT(args->qc_op == QUOTACTL_GET); 354 1.78 dholland qk = args->u.get.qc_key; 355 1.108 dholland qv = args->u.get.qc_val; 356 1.69 bouyer 357 1.69 bouyer if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 358 1.69 bouyer return EOPNOTSUPP; 359 1.118 riastrad 360 1.79 dholland error = quota_get_auth(mp, l, qk->qk_id); 361 1.118 riastrad if (error != 0) 362 1.79 dholland return error; 363 1.69 bouyer #ifdef QUOTA 364 1.79 dholland if (ump->um_flags & UFS_QUOTA) { 365 1.108 dholland error = quota1_handle_cmd_get(ump, qk, qv); 366 1.79 dholland } else 367 1.69 bouyer #endif 368 1.69 bouyer #ifdef QUOTA2 369 1.79 dholland if (ump->um_flags & UFS_QUOTA2) { 370 1.108 dholland error = quota2_handle_cmd_get(ump, qk, qv); 371 1.79 dholland } else 372 1.69 bouyer #endif 373 1.79 dholland panic("quota_handle_cmd_get: no support ?"); 374 1.118 riastrad 375 1.79 dholland if (error != 0) 376 1.79 dholland return error; 377 1.74 dholland 378 1.69 bouyer return error; 379 1.69 bouyer } 380 1.69 bouyer 381 1.118 riastrad static int 382 1.118 riastrad quota_handle_cmd_put(struct mount *mp, struct lwp *l, 383 1.107 dholland struct quotactl_args *args) 384 1.69 bouyer { 385 1.11 fvdl struct ufsmount *ump = VFSTOUFS(mp); 386 1.84 dholland const struct quotakey *qk; 387 1.83 dholland const struct quotaval *qv; 388 1.84 dholland id_t kauth_id; 389 1.80 dholland int error; 390 1.72 dholland 391 1.102 dholland KASSERT(args->qc_op == QUOTACTL_PUT); 392 1.85 dholland qk = args->u.put.qc_key; 393 1.85 dholland qv = args->u.put.qc_val; 394 1.1 mycroft 395 1.69 bouyer if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 396 1.69 bouyer return EOPNOTSUPP; 397 1.61 ad 398 1.84 dholland kauth_id = qk->qk_id; 399 1.84 dholland if (kauth_id == QUOTA_DEFAULTID) { 400 1.84 dholland kauth_id = 0; 401 1.84 dholland } 402 1.84 dholland 403 1.86 dholland error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 404 1.86 dholland KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(kauth_id), 405 1.86 dholland NULL); 406 1.87 dholland if (error != 0) { 407 1.87 dholland return error; 408 1.87 dholland } 409 1.87 dholland 410 1.69 bouyer #ifdef QUOTA 411 1.86 dholland if (ump->um_flags & UFS_QUOTA) 412 1.86 dholland error = quota1_handle_cmd_put(ump, qk, qv); 413 1.86 dholland else 414 1.69 bouyer #endif 415 1.69 bouyer #ifdef QUOTA2 416 1.86 dholland if (ump->um_flags & UFS_QUOTA2) { 417 1.86 dholland error = quota2_handle_cmd_put(ump, qk, qv); 418 1.86 dholland } else 419 1.69 bouyer #endif 420 1.86 dholland panic("quota_handle_cmd_get: no support ?"); 421 1.118 riastrad 422 1.87 dholland if (error == ENOENT) { 423 1.87 dholland error = 0; 424 1.87 dholland } 425 1.80 dholland 426 1.69 bouyer return error; 427 1.69 bouyer } 428 1.69 bouyer 429 1.118 riastrad static int 430 1.118 riastrad quota_handle_cmd_del(struct mount *mp, struct lwp *l, 431 1.107 dholland struct quotactl_args *args) 432 1.69 bouyer { 433 1.88 dholland struct ufsmount *ump = VFSTOUFS(mp); 434 1.92 dholland const struct quotakey *qk; 435 1.92 dholland id_t kauth_id; 436 1.88 dholland int error; 437 1.72 dholland 438 1.117 dholland KASSERT(args->qc_op == QUOTACTL_DEL); 439 1.117 dholland qk = args->u.del.qc_key; 440 1.92 dholland 441 1.92 dholland kauth_id = qk->qk_id; 442 1.92 dholland if (kauth_id == QUOTA_DEFAULTID) { 443 1.92 dholland kauth_id = 0; 444 1.92 dholland } 445 1.33 perry 446 1.69 bouyer if ((ump->um_flags & UFS_QUOTA2) == 0) 447 1.69 bouyer return EOPNOTSUPP; 448 1.53 ad 449 1.88 dholland /* avoid whitespace changes */ 450 1.88 dholland { 451 1.69 bouyer error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 452 1.92 dholland KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(kauth_id), 453 1.92 dholland NULL); 454 1.69 bouyer if (error != 0) 455 1.69 bouyer goto err; 456 1.69 bouyer #ifdef QUOTA2 457 1.69 bouyer if (ump->um_flags & UFS_QUOTA2) { 458 1.117 dholland error = quota2_handle_cmd_del(ump, qk); 459 1.69 bouyer } else 460 1.69 bouyer #endif 461 1.69 bouyer panic("quota_handle_cmd_get: no support ?"); 462 1.118 riastrad 463 1.69 bouyer if (error && error != ENOENT) 464 1.69 bouyer goto err; 465 1.50 hannken } 466 1.88 dholland 467 1.88 dholland return 0; 468 1.88 dholland err: 469 1.69 bouyer return error; 470 1.1 mycroft } 471 1.1 mycroft 472 1.118 riastrad static int 473 1.118 riastrad quota_handle_cmd_cursorget(struct mount *mp, struct lwp *l, 474 1.107 dholland struct quotactl_args *args) 475 1.1 mycroft { 476 1.1 mycroft struct ufsmount *ump = VFSTOUFS(mp); 477 1.1 mycroft int error; 478 1.72 dholland 479 1.102 dholland KASSERT(args->qc_op == QUOTACTL_CURSORGET); 480 1.1 mycroft 481 1.69 bouyer if ((ump->um_flags & UFS_QUOTA2) == 0) 482 1.69 bouyer return EOPNOTSUPP; 483 1.118 riastrad 484 1.69 bouyer error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 485 1.69 bouyer KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL); 486 1.8 christos if (error) 487 1.69 bouyer return error; 488 1.118 riastrad 489 1.69 bouyer #ifdef QUOTA2 490 1.69 bouyer if (ump->um_flags & UFS_QUOTA2) { 491 1.114 mrg struct quotakcursor *cursor = args->u.cursorget.qc_cursor; 492 1.114 mrg struct quotakey *keys = args->u.cursorget.qc_keys; 493 1.114 mrg struct quotaval *vals = args->u.cursorget.qc_vals; 494 1.114 mrg unsigned maxnum = args->u.cursorget.qc_maxnum; 495 1.114 mrg unsigned *ret = args->u.cursorget.qc_ret; 496 1.114 mrg 497 1.98 dholland error = quota2_handle_cmd_cursorget(ump, cursor, keys, vals, 498 1.98 dholland maxnum, ret); 499 1.69 bouyer } else 500 1.69 bouyer #endif 501 1.98 dholland panic("quota_handle_cmd_cursorget: no support ?"); 502 1.95 dholland 503 1.69 bouyer return error; 504 1.1 mycroft } 505 1.1 mycroft 506 1.118 riastrad static int 507 1.118 riastrad quota_handle_cmd_cursoropen(struct mount *mp, struct lwp *l, 508 1.107 dholland struct quotactl_args *args) 509 1.93 dholland { 510 1.105 para #ifdef QUOTA2 511 1.93 dholland struct ufsmount *ump = VFSTOUFS(mp); 512 1.115 dholland struct quotakcursor *cursor = args->u.cursoropen.qc_cursor; 513 1.105 para #endif 514 1.93 dholland int error; 515 1.93 dholland 516 1.102 dholland KASSERT(args->qc_op == QUOTACTL_CURSOROPEN); 517 1.93 dholland 518 1.93 dholland error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 519 1.93 dholland KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL); 520 1.93 dholland if (error) 521 1.93 dholland return error; 522 1.93 dholland 523 1.93 dholland #ifdef QUOTA2 524 1.93 dholland if (ump->um_flags & UFS_QUOTA2) { 525 1.93 dholland error = quota2_handle_cmd_cursoropen(ump, cursor); 526 1.93 dholland } else 527 1.93 dholland #endif 528 1.93 dholland error = EOPNOTSUPP; 529 1.93 dholland 530 1.93 dholland return error; 531 1.93 dholland } 532 1.93 dholland 533 1.118 riastrad static int 534 1.118 riastrad quota_handle_cmd_cursorclose(struct mount *mp, struct lwp *l, 535 1.107 dholland struct quotactl_args *args) 536 1.93 dholland { 537 1.105 para #ifdef QUOTA2 538 1.93 dholland struct ufsmount *ump = VFSTOUFS(mp); 539 1.115 dholland struct quotakcursor *cursor = args->u.cursorclose.qc_cursor; 540 1.105 para #endif 541 1.93 dholland int error; 542 1.93 dholland 543 1.102 dholland KASSERT(args->qc_op == QUOTACTL_CURSORCLOSE); 544 1.93 dholland 545 1.93 dholland error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 546 1.93 dholland KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL); 547 1.93 dholland if (error) 548 1.93 dholland return error; 549 1.93 dholland 550 1.93 dholland #ifdef QUOTA2 551 1.93 dholland if (ump->um_flags & UFS_QUOTA2) { 552 1.93 dholland error = quota2_handle_cmd_cursorclose(ump, cursor); 553 1.93 dholland } else 554 1.93 dholland #endif 555 1.93 dholland error = EOPNOTSUPP; 556 1.93 dholland 557 1.93 dholland return error; 558 1.93 dholland } 559 1.93 dholland 560 1.118 riastrad static int 561 1.118 riastrad quota_handle_cmd_cursorskipidtype(struct mount *mp, struct lwp *l, 562 1.107 dholland struct quotactl_args *args) 563 1.98 dholland { 564 1.105 para #ifdef QUOTA2 565 1.98 dholland struct ufsmount *ump = VFSTOUFS(mp); 566 1.115 dholland struct quotakcursor *cursor = args->u.cursorskipidtype.qc_cursor; 567 1.115 dholland int idtype = args->u.cursorskipidtype.qc_idtype; 568 1.105 para #endif 569 1.98 dholland int error; 570 1.98 dholland 571 1.102 dholland KASSERT(args->qc_op == QUOTACTL_CURSORSKIPIDTYPE); 572 1.98 dholland 573 1.98 dholland #ifdef QUOTA2 574 1.98 dholland if (ump->um_flags & UFS_QUOTA2) { 575 1.98 dholland error = quota2_handle_cmd_cursorskipidtype(ump, cursor, idtype); 576 1.98 dholland } else 577 1.98 dholland #endif 578 1.98 dholland error = EOPNOTSUPP; 579 1.98 dholland 580 1.98 dholland return error; 581 1.98 dholland } 582 1.98 dholland 583 1.118 riastrad static int 584 1.118 riastrad quota_handle_cmd_cursoratend(struct mount *mp, struct lwp *l, 585 1.107 dholland struct quotactl_args *args) 586 1.98 dholland { 587 1.105 para #ifdef QUOTA2 588 1.98 dholland struct ufsmount *ump = VFSTOUFS(mp); 589 1.115 dholland struct quotakcursor *cursor = args->u.cursoratend.qc_cursor; 590 1.115 dholland unsigned *ret = args->u.cursoratend.qc_ret; 591 1.105 para #endif 592 1.98 dholland int error; 593 1.98 dholland 594 1.102 dholland KASSERT(args->qc_op == QUOTACTL_CURSORATEND); 595 1.98 dholland 596 1.98 dholland #ifdef QUOTA2 597 1.98 dholland if (ump->um_flags & UFS_QUOTA2) { 598 1.98 dholland error = quota2_handle_cmd_cursoratend(ump, cursor, ret); 599 1.98 dholland } else 600 1.98 dholland #endif 601 1.98 dholland error = EOPNOTSUPP; 602 1.98 dholland 603 1.98 dholland return error; 604 1.98 dholland } 605 1.98 dholland 606 1.118 riastrad static int 607 1.118 riastrad quota_handle_cmd_cursorrewind(struct mount *mp, struct lwp *l, 608 1.107 dholland struct quotactl_args *args) 609 1.98 dholland { 610 1.105 para #ifdef QUOTA2 611 1.98 dholland struct ufsmount *ump = VFSTOUFS(mp); 612 1.115 dholland struct quotakcursor *cursor = args->u.cursorrewind.qc_cursor; 613 1.105 para #endif 614 1.98 dholland int error; 615 1.98 dholland 616 1.102 dholland KASSERT(args->qc_op == QUOTACTL_CURSORREWIND); 617 1.98 dholland 618 1.98 dholland #ifdef QUOTA2 619 1.98 dholland if (ump->um_flags & UFS_QUOTA2) { 620 1.98 dholland error = quota2_handle_cmd_cursorrewind(ump, cursor); 621 1.98 dholland } else 622 1.98 dholland #endif 623 1.98 dholland error = EOPNOTSUPP; 624 1.98 dholland 625 1.98 dholland return error; 626 1.98 dholland } 627 1.98 dholland 628 1.118 riastrad static int 629 1.118 riastrad quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l, 630 1.107 dholland struct quotactl_args *args) 631 1.1 mycroft { 632 1.1 mycroft struct ufsmount *ump = VFSTOUFS(mp); 633 1.1 mycroft int error; 634 1.72 dholland 635 1.102 dholland KASSERT(args->qc_op == QUOTACTL_QUOTAON); 636 1.69 bouyer 637 1.69 bouyer if ((ump->um_flags & UFS_QUOTA2) != 0) 638 1.69 bouyer return EBUSY; 639 1.118 riastrad 640 1.69 bouyer error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 641 1.69 bouyer KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); 642 1.69 bouyer if (error != 0) { 643 1.69 bouyer return error; 644 1.69 bouyer } 645 1.69 bouyer #ifdef QUOTA 646 1.113 christos int idtype = args->u.quotaon.qc_idtype; 647 1.113 christos const char *qfile = args->u.quotaon.qc_quotafile; 648 1.99 dholland error = quota1_handle_cmd_quotaon(l, ump, idtype, qfile); 649 1.69 bouyer #else 650 1.69 bouyer error = EOPNOTSUPP; 651 1.69 bouyer #endif 652 1.118 riastrad 653 1.69 bouyer return error; 654 1.1 mycroft } 655 1.1 mycroft 656 1.118 riastrad static int 657 1.118 riastrad quota_handle_cmd_quotaoff(struct mount *mp, struct lwp *l, 658 1.107 dholland struct quotactl_args *args) 659 1.1 mycroft { 660 1.1 mycroft struct ufsmount *ump = VFSTOUFS(mp); 661 1.69 bouyer int error; 662 1.72 dholland 663 1.102 dholland KASSERT(args->qc_op == QUOTACTL_QUOTAOFF); 664 1.1 mycroft 665 1.69 bouyer if ((ump->um_flags & UFS_QUOTA2) != 0) 666 1.69 bouyer return EOPNOTSUPP; 667 1.118 riastrad 668 1.69 bouyer error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 669 1.69 bouyer KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); 670 1.69 bouyer if (error != 0) { 671 1.69 bouyer return error; 672 1.1 mycroft } 673 1.69 bouyer #ifdef QUOTA 674 1.113 christos int idtype = args->u.quotaoff.qc_idtype; 675 1.100 dholland error = quota1_handle_cmd_quotaoff(l, ump, idtype); 676 1.69 bouyer #else 677 1.69 bouyer error = EOPNOTSUPP; 678 1.69 bouyer #endif 679 1.118 riastrad 680 1.69 bouyer return error; 681 1.1 mycroft } 682 1.1 mycroft 683 1.1 mycroft /* 684 1.1 mycroft * Initialize the quota system. 685 1.1 mycroft */ 686 1.1 mycroft void 687 1.35 thorpej dqinit(void) 688 1.1 mycroft { 689 1.47 pooka 690 1.50 hannken mutex_init(&dqlock, MUTEX_DEFAULT, IPL_NONE); 691 1.50 hannken cv_init(&dqcv, "quota"); 692 1.60 ad dqhashtbl = hashinit(desiredvnodes, HASH_LIST, true, &dqhash); 693 1.55 ad dquot_cache = pool_cache_init(sizeof(struct dquot), 0, 0, 0, "ufsdq", 694 1.55 ad NULL, IPL_NONE, NULL, NULL, NULL); 695 1.14 jdolecek } 696 1.14 jdolecek 697 1.21 chs void 698 1.35 thorpej dqreinit(void) 699 1.21 chs { 700 1.21 chs struct dquot *dq; 701 1.21 chs struct dqhashhead *oldhash, *hash; 702 1.21 chs struct vnode *dqvp; 703 1.21 chs u_long oldmask, mask, hashval; 704 1.21 chs int i; 705 1.21 chs 706 1.60 ad hash = hashinit(desiredvnodes, HASH_LIST, true, &mask); 707 1.50 hannken mutex_enter(&dqlock); 708 1.21 chs oldhash = dqhashtbl; 709 1.21 chs oldmask = dqhash; 710 1.21 chs dqhashtbl = hash; 711 1.21 chs dqhash = mask; 712 1.21 chs for (i = 0; i <= oldmask; i++) { 713 1.21 chs while ((dq = LIST_FIRST(&oldhash[i])) != NULL) { 714 1.21 chs dqvp = dq->dq_ump->um_quotas[dq->dq_type]; 715 1.21 chs LIST_REMOVE(dq, dq_hash); 716 1.21 chs hashval = DQHASH(dqvp, dq->dq_id); 717 1.21 chs LIST_INSERT_HEAD(&dqhashtbl[hashval], dq, dq_hash); 718 1.21 chs } 719 1.21 chs } 720 1.50 hannken mutex_exit(&dqlock); 721 1.60 ad hashdone(oldhash, HASH_LIST, oldmask); 722 1.21 chs } 723 1.21 chs 724 1.14 jdolecek /* 725 1.14 jdolecek * Free resources held by quota system. 726 1.14 jdolecek */ 727 1.14 jdolecek void 728 1.35 thorpej dqdone(void) 729 1.14 jdolecek { 730 1.47 pooka 731 1.55 ad pool_cache_destroy(dquot_cache); 732 1.60 ad hashdone(dqhashtbl, HASH_LIST, dqhash); 733 1.50 hannken cv_destroy(&dqcv); 734 1.50 hannken mutex_destroy(&dqlock); 735 1.1 mycroft } 736 1.1 mycroft 737 1.1 mycroft /* 738 1.69 bouyer * Set up the quotas for an inode. 739 1.69 bouyer * 740 1.69 bouyer * This routine completely defines the semantics of quotas. 741 1.69 bouyer * If other criterion want to be used to establish quotas, the 742 1.69 bouyer * MAXQUOTAS value in quotas.h should be increased, and the 743 1.69 bouyer * additional dquots set up here. 744 1.69 bouyer */ 745 1.69 bouyer int 746 1.69 bouyer getinoquota(struct inode *ip) 747 1.69 bouyer { 748 1.69 bouyer struct ufsmount *ump = ip->i_ump; 749 1.69 bouyer struct vnode *vp = ITOV(ip); 750 1.69 bouyer int i, error; 751 1.69 bouyer u_int32_t ino_ids[MAXQUOTAS]; 752 1.69 bouyer 753 1.69 bouyer /* 754 1.69 bouyer * To avoid deadlocks never update quotas for quota files 755 1.69 bouyer * on the same file system 756 1.69 bouyer */ 757 1.69 bouyer for (i = 0; i < MAXQUOTAS; i++) 758 1.69 bouyer if (vp == ump->um_quotas[i]) 759 1.69 bouyer return 0; 760 1.69 bouyer 761 1.69 bouyer ino_ids[USRQUOTA] = ip->i_uid; 762 1.69 bouyer ino_ids[GRPQUOTA] = ip->i_gid; 763 1.69 bouyer for (i = 0; i < MAXQUOTAS; i++) { 764 1.69 bouyer /* 765 1.69 bouyer * If the file id changed the quota needs update. 766 1.69 bouyer */ 767 1.69 bouyer if (ip->i_dquot[i] != NODQUOT && 768 1.69 bouyer ip->i_dquot[i]->dq_id != ino_ids[i]) { 769 1.69 bouyer dqrele(ITOV(ip), ip->i_dquot[i]); 770 1.69 bouyer ip->i_dquot[i] = NODQUOT; 771 1.69 bouyer } 772 1.69 bouyer /* 773 1.69 bouyer * Set up the quota based on file id. 774 1.69 bouyer * ENODEV means that quotas are not enabled. 775 1.69 bouyer */ 776 1.69 bouyer if (ip->i_dquot[i] == NODQUOT && 777 1.69 bouyer (error = dqget(vp, ino_ids[i], ump, i, &ip->i_dquot[i])) && 778 1.69 bouyer error != ENODEV) 779 1.69 bouyer return (error); 780 1.69 bouyer } 781 1.69 bouyer return 0; 782 1.69 bouyer } 783 1.69 bouyer 784 1.69 bouyer /* 785 1.1 mycroft * Obtain a dquot structure for the specified identifier and quota file 786 1.1 mycroft * reading the information from the file if necessary. 787 1.1 mycroft */ 788 1.69 bouyer int 789 1.35 thorpej dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, 790 1.35 thorpej struct dquot **dqp) 791 1.1 mycroft { 792 1.50 hannken struct dquot *dq, *ndq; 793 1.21 chs struct dqhashhead *dqh; 794 1.11 fvdl struct vnode *dqvp; 795 1.69 bouyer int error = 0; /* XXX gcc */ 796 1.1 mycroft 797 1.50 hannken /* Lock to see an up to date value for QTF_CLOSING. */ 798 1.50 hannken mutex_enter(&dqlock); 799 1.69 bouyer if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) { 800 1.50 hannken mutex_exit(&dqlock); 801 1.1 mycroft *dqp = NODQUOT; 802 1.69 bouyer return (ENODEV); 803 1.69 bouyer } 804 1.69 bouyer dqvp = ump->um_quotas[type]; 805 1.69 bouyer #ifdef QUOTA 806 1.69 bouyer if (ump->um_flags & UFS_QUOTA) { 807 1.69 bouyer if (dqvp == NULLVP || (ump->umq1_qflags[type] & QTF_CLOSING)) { 808 1.69 bouyer mutex_exit(&dqlock); 809 1.69 bouyer *dqp = NODQUOT; 810 1.69 bouyer return (ENODEV); 811 1.69 bouyer } 812 1.1 mycroft } 813 1.69 bouyer #endif 814 1.69 bouyer #ifdef QUOTA2 815 1.69 bouyer if (ump->um_flags & UFS_QUOTA2) { 816 1.69 bouyer if (dqvp == NULLVP) { 817 1.69 bouyer mutex_exit(&dqlock); 818 1.69 bouyer *dqp = NODQUOT; 819 1.69 bouyer return (ENODEV); 820 1.69 bouyer } 821 1.69 bouyer } 822 1.69 bouyer #endif 823 1.50 hannken KASSERT(dqvp != vp); 824 1.1 mycroft /* 825 1.1 mycroft * Check the cache first. 826 1.1 mycroft */ 827 1.21 chs dqh = &dqhashtbl[DQHASH(dqvp, id)]; 828 1.21 chs LIST_FOREACH(dq, dqh, dq_hash) { 829 1.1 mycroft if (dq->dq_id != id || 830 1.1 mycroft dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 831 1.1 mycroft continue; 832 1.50 hannken KASSERT(dq->dq_cnt > 0); 833 1.37 chs dqref(dq); 834 1.50 hannken mutex_exit(&dqlock); 835 1.1 mycroft *dqp = dq; 836 1.1 mycroft return (0); 837 1.1 mycroft } 838 1.1 mycroft /* 839 1.1 mycroft * Not in cache, allocate a new one. 840 1.1 mycroft */ 841 1.50 hannken mutex_exit(&dqlock); 842 1.55 ad ndq = pool_cache_get(dquot_cache, PR_WAITOK); 843 1.1 mycroft /* 844 1.1 mycroft * Initialize the contents of the dquot structure. 845 1.1 mycroft */ 846 1.50 hannken memset((char *)ndq, 0, sizeof *ndq); 847 1.50 hannken ndq->dq_flags = 0; 848 1.50 hannken ndq->dq_id = id; 849 1.50 hannken ndq->dq_ump = ump; 850 1.50 hannken ndq->dq_type = type; 851 1.50 hannken mutex_init(&ndq->dq_interlock, MUTEX_DEFAULT, IPL_NONE); 852 1.50 hannken mutex_enter(&dqlock); 853 1.49 hannken dqh = &dqhashtbl[DQHASH(dqvp, id)]; 854 1.50 hannken LIST_FOREACH(dq, dqh, dq_hash) { 855 1.50 hannken if (dq->dq_id != id || 856 1.50 hannken dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 857 1.50 hannken continue; 858 1.50 hannken /* 859 1.50 hannken * Another thread beat us allocating this dquot. 860 1.50 hannken */ 861 1.50 hannken KASSERT(dq->dq_cnt > 0); 862 1.50 hannken dqref(dq); 863 1.50 hannken mutex_exit(&dqlock); 864 1.64 bouyer mutex_destroy(&ndq->dq_interlock); 865 1.55 ad pool_cache_put(dquot_cache, ndq); 866 1.50 hannken *dqp = dq; 867 1.50 hannken return 0; 868 1.50 hannken } 869 1.50 hannken dq = ndq; 870 1.5 mycroft LIST_INSERT_HEAD(dqh, dq, dq_hash); 871 1.37 chs dqref(dq); 872 1.50 hannken mutex_enter(&dq->dq_interlock); 873 1.50 hannken mutex_exit(&dqlock); 874 1.69 bouyer #ifdef QUOTA 875 1.69 bouyer if (ump->um_flags & UFS_QUOTA) 876 1.69 bouyer error = dq1get(dqvp, id, ump, type, dq); 877 1.69 bouyer #endif 878 1.69 bouyer #ifdef QUOTA2 879 1.69 bouyer if (ump->um_flags & UFS_QUOTA2) 880 1.69 bouyer error = dq2get(dqvp, id, ump, type, dq); 881 1.69 bouyer #endif 882 1.1 mycroft /* 883 1.1 mycroft * I/O error in reading quota file, release 884 1.1 mycroft * quota structure and reflect problem to caller. 885 1.1 mycroft */ 886 1.1 mycroft if (error) { 887 1.50 hannken mutex_enter(&dqlock); 888 1.5 mycroft LIST_REMOVE(dq, dq_hash); 889 1.50 hannken mutex_exit(&dqlock); 890 1.49 hannken mutex_exit(&dq->dq_interlock); 891 1.1 mycroft dqrele(vp, dq); 892 1.1 mycroft *dqp = NODQUOT; 893 1.1 mycroft return (error); 894 1.1 mycroft } 895 1.49 hannken mutex_exit(&dq->dq_interlock); 896 1.1 mycroft *dqp = dq; 897 1.1 mycroft return (0); 898 1.1 mycroft } 899 1.1 mycroft 900 1.1 mycroft /* 901 1.1 mycroft * Obtain a reference to a dquot. 902 1.1 mycroft */ 903 1.69 bouyer void 904 1.35 thorpej dqref(struct dquot *dq) 905 1.1 mycroft { 906 1.1 mycroft 907 1.50 hannken KASSERT(mutex_owned(&dqlock)); 908 1.1 mycroft dq->dq_cnt++; 909 1.46 hannken KASSERT(dq->dq_cnt > 0); 910 1.1 mycroft } 911 1.1 mycroft 912 1.1 mycroft /* 913 1.1 mycroft * Release a reference to a dquot. 914 1.1 mycroft */ 915 1.69 bouyer void 916 1.35 thorpej dqrele(struct vnode *vp, struct dquot *dq) 917 1.1 mycroft { 918 1.1 mycroft 919 1.1 mycroft if (dq == NODQUOT) 920 1.1 mycroft return; 921 1.50 hannken mutex_enter(&dq->dq_interlock); 922 1.50 hannken for (;;) { 923 1.50 hannken mutex_enter(&dqlock); 924 1.50 hannken if (dq->dq_cnt > 1) { 925 1.50 hannken dq->dq_cnt--; 926 1.50 hannken mutex_exit(&dqlock); 927 1.50 hannken mutex_exit(&dq->dq_interlock); 928 1.50 hannken return; 929 1.50 hannken } 930 1.50 hannken if ((dq->dq_flags & DQ_MOD) == 0) 931 1.50 hannken break; 932 1.50 hannken mutex_exit(&dqlock); 933 1.69 bouyer #ifdef QUOTA 934 1.69 bouyer if (dq->dq_ump->um_flags & UFS_QUOTA) 935 1.69 bouyer (void) dq1sync(vp, dq); 936 1.69 bouyer #endif 937 1.69 bouyer #ifdef QUOTA2 938 1.69 bouyer if (dq->dq_ump->um_flags & UFS_QUOTA2) 939 1.69 bouyer (void) dq2sync(vp, dq); 940 1.69 bouyer #endif 941 1.1 mycroft } 942 1.50 hannken KASSERT(dq->dq_cnt == 1 && (dq->dq_flags & DQ_MOD) == 0); 943 1.50 hannken LIST_REMOVE(dq, dq_hash); 944 1.50 hannken mutex_exit(&dqlock); 945 1.50 hannken mutex_exit(&dq->dq_interlock); 946 1.50 hannken mutex_destroy(&dq->dq_interlock); 947 1.55 ad pool_cache_put(dquot_cache, dq); 948 1.1 mycroft } 949 1.1 mycroft 950 1.69 bouyer int 951 1.69 bouyer qsync(struct mount *mp) 952 1.1 mycroft { 953 1.69 bouyer struct ufsmount *ump = VFSTOUFS(mp); 954 1.69 bouyer #ifdef QUOTA 955 1.69 bouyer if (ump->um_flags & UFS_QUOTA) 956 1.69 bouyer return q1sync(mp); 957 1.69 bouyer #endif 958 1.69 bouyer #ifdef QUOTA2 959 1.69 bouyer if (ump->um_flags & UFS_QUOTA2) 960 1.69 bouyer return q2sync(mp); 961 1.69 bouyer #endif 962 1.69 bouyer return 0; 963 1.1 mycroft } 964 1.1 mycroft 965 1.50 hannken #ifdef DIAGNOSTIC 966 1.1 mycroft /* 967 1.50 hannken * Check the hash chains for stray dquot's. 968 1.1 mycroft */ 969 1.69 bouyer void 970 1.35 thorpej dqflush(struct vnode *vp) 971 1.1 mycroft { 972 1.50 hannken struct dquot *dq; 973 1.50 hannken int i; 974 1.1 mycroft 975 1.50 hannken mutex_enter(&dqlock); 976 1.50 hannken for (i = 0; i <= dqhash; i++) 977 1.50 hannken LIST_FOREACH(dq, &dqhashtbl[i], dq_hash) 978 1.50 hannken KASSERT(dq->dq_ump->um_quotas[dq->dq_type] != vp); 979 1.50 hannken mutex_exit(&dqlock); 980 1.1 mycroft } 981 1.50 hannken #endif 982