1 /* $NetBSD: quota2_subr.c,v 1.7 2023/08/24 14:56:03 andvar Exp $ */ 2 /*- 3 * Copyright (c) 2010, 2011 Manuel Bouyer 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 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 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 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: quota2_subr.c,v 1.7 2023/08/24 14:56:03 andvar Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/time.h> 33 34 #include <ufs/ufs/dinode.h> 35 #include <ufs/ffs/fs.h> 36 #include <ufs/ffs/ffs_extern.h> 37 #include <ufs/ufs/ufs_bswap.h> 38 #include <ufs/ufs/quota2.h> 39 40 #ifndef _KERNEL 41 #include <string.h> 42 #endif 43 44 void 45 quota2_addfreeq2e(struct quota2_header *q2h, void *bp, uint64_t baseoff, 46 uint64_t bsize, int ns) 47 { 48 uint64_t blkoff = baseoff % bsize; 49 int i, nq2e; 50 struct quota2_entry *q2e; 51 52 q2e = (void *)((char *)bp + blkoff); 53 nq2e = (bsize - blkoff) / sizeof(*q2e); 54 for (i = 0; i < nq2e; i++) { 55 q2e[i].q2e_next = q2h->q2h_free; 56 q2h->q2h_free = ufs_rw64(i * sizeof(*q2e) + baseoff, ns); 57 } 58 } 59 60 void 61 quota2_create_blk0(uint64_t bsize, void *bp, int q2h_hash_shift, int type, 62 int ns) 63 { 64 struct quota2_header *q2h; 65 const int quota2_hash_size = 1 << q2h_hash_shift; 66 const int quota2_full_header_size = sizeof(struct quota2_header) + 67 sizeof(q2h->q2h_entries[0]) * quota2_hash_size; 68 int i; 69 70 memset(bp, 0, bsize); 71 q2h = bp; 72 q2h->q2h_magic_number = ufs_rw32(Q2_HEAD_MAGIC, ns); 73 q2h->q2h_type = type; 74 q2h->q2h_hash_shift = q2h_hash_shift; 75 q2h->q2h_hash_size = ufs_rw16(quota2_hash_size, ns); 76 /* setup default entry: unlimited, 7 days grace */ 77 for (i = 0; i < N_QL; i++) { 78 q2h->q2h_defentry.q2e_val[i].q2v_hardlimit = 79 q2h->q2h_defentry.q2e_val[i].q2v_softlimit = 80 ufs_rw64(UQUAD_MAX, ns); 81 q2h->q2h_defentry.q2e_val[i].q2v_grace = 82 ufs_rw64(7ULL * 24ULL * 3600ULL, ns); 83 } 84 85 /* first quota entry, after the hash table */ 86 quota2_addfreeq2e(q2h, bp, quota2_full_header_size, bsize, ns); 87 } 88 89 void 90 quota2_ufs_rwq2v(const struct quota2_val *s, struct quota2_val *d, 91 int needswap) 92 { 93 d->q2v_hardlimit = ufs_rw64(s->q2v_hardlimit, needswap); 94 d->q2v_softlimit = ufs_rw64(s->q2v_softlimit, needswap); 95 d->q2v_cur = ufs_rw64(s->q2v_cur, needswap); 96 d->q2v_time = ufs_rw64(s->q2v_time, needswap); 97 d->q2v_grace = ufs_rw64(s->q2v_grace, needswap); 98 } 99 100 void 101 quota2_ufs_rwq2e(const struct quota2_entry *s, struct quota2_entry *d, 102 int needswap) 103 { 104 quota2_ufs_rwq2v(&s->q2e_val[QL_BLOCK], &d->q2e_val[QL_BLOCK], 105 needswap); 106 quota2_ufs_rwq2v(&s->q2e_val[QL_FILE], &d->q2e_val[QL_FILE], 107 needswap); 108 d->q2e_uid = ufs_rw32(s->q2e_uid, needswap); 109 } 110 111 int 112 quota_check_limit(uint64_t cur, uint64_t change, uint64_t soft, uint64_t hard, 113 time_t expire, time_t now) 114 { 115 if (cur + change > hard) { 116 if (cur <= soft) 117 return (QL_F_CROSS | QL_S_DENY_HARD); 118 return QL_S_DENY_HARD; 119 } else if (cur + change > soft) { 120 if (cur <= soft) 121 return (QL_F_CROSS | QL_S_ALLOW_SOFT); 122 if (now > expire) { 123 return QL_S_DENY_GRACE; 124 } 125 return QL_S_ALLOW_SOFT; 126 } 127 return QL_S_ALLOW_OK; 128 } 129