1*8e544e80Sjsg /* $OpenBSD: ffs_subr.c,v 1.6 2022/01/11 05:34:33 jsg Exp $ */
2f54008ebSnatano /* $NetBSD: ffs_subr.c,v 1.49 2016/05/07 11:59:08 maxv Exp $ */
3f54008ebSnatano
4f54008ebSnatano /*
5f54008ebSnatano * Copyright (c) 1982, 1986, 1989, 1993
6f54008ebSnatano * The Regents of the University of California. All rights reserved.
7f54008ebSnatano *
8f54008ebSnatano * Redistribution and use in source and binary forms, with or without
9f54008ebSnatano * modification, are permitted provided that the following conditions
10f54008ebSnatano * are met:
11f54008ebSnatano * 1. Redistributions of source code must retain the above copyright
12f54008ebSnatano * notice, this list of conditions and the following disclaimer.
13f54008ebSnatano * 2. Redistributions in binary form must reproduce the above copyright
14f54008ebSnatano * notice, this list of conditions and the following disclaimer in the
15f54008ebSnatano * documentation and/or other materials provided with the distribution.
16f54008ebSnatano * 3. Neither the name of the University nor the names of its contributors
17f54008ebSnatano * may be used to endorse or promote products derived from this software
18f54008ebSnatano * without specific prior written permission.
19f54008ebSnatano *
20f54008ebSnatano * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21f54008ebSnatano * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22f54008ebSnatano * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23f54008ebSnatano * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24f54008ebSnatano * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25f54008ebSnatano * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26f54008ebSnatano * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27f54008ebSnatano * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28f54008ebSnatano * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29f54008ebSnatano * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30f54008ebSnatano * SUCH DAMAGE.
31f54008ebSnatano *
32f54008ebSnatano * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95
33f54008ebSnatano */
34f54008ebSnatano
354874b543Sderaadt #include <sys/param.h> /* setbit clrbit NBBY */
364874b543Sderaadt #include <sys/types.h>
376c4d9c1cSnatano #include <ufs/ufs/dinode.h>
386c4d9c1cSnatano #include <ufs/ffs/fs.h>
39f54008ebSnatano
404874b543Sderaadt #include <limits.h>
41b35c7f73Snatano #include <err.h>
42b35c7f73Snatano
43f54008ebSnatano #include "ffs/ffs_extern.h"
44f54008ebSnatano
45f54008ebSnatano
46f54008ebSnatano /*
47f54008ebSnatano * block operations
48f54008ebSnatano *
49f54008ebSnatano * check if a block is available
50*8e544e80Sjsg * returns true if all the corresponding bits in the free map are 1
51f54008ebSnatano * returns false if any corresponding bit in the free map is 0
52f54008ebSnatano */
53f54008ebSnatano int
ffs_isblock(struct fs * fs,u_char * cp,int32_t h)54f54008ebSnatano ffs_isblock(struct fs *fs, u_char *cp, int32_t h)
55f54008ebSnatano {
56f54008ebSnatano u_char mask;
57f54008ebSnatano
58f54008ebSnatano switch ((int)fs->fs_fragshift) {
59f54008ebSnatano case 3:
60f54008ebSnatano return (cp[h] == 0xff);
61f54008ebSnatano case 2:
62f54008ebSnatano mask = 0x0f << ((h & 0x1) << 2);
63f54008ebSnatano return ((cp[h >> 1] & mask) == mask);
64f54008ebSnatano case 1:
65f54008ebSnatano mask = 0x03 << ((h & 0x3) << 1);
66f54008ebSnatano return ((cp[h >> 2] & mask) == mask);
67f54008ebSnatano case 0:
68f54008ebSnatano mask = 0x01 << (h & 0x7);
69f54008ebSnatano return ((cp[h >> 3] & mask) == mask);
70f54008ebSnatano default:
71b35c7f73Snatano errx(1, "ffs_isblock: unknown fs_fragshift %d",
72f54008ebSnatano (int)fs->fs_fragshift);
73f54008ebSnatano }
74f54008ebSnatano }
75f54008ebSnatano
76f54008ebSnatano /*
77f54008ebSnatano * take a block out of the map
78f54008ebSnatano */
79f54008ebSnatano void
ffs_clrblock(struct fs * fs,u_char * cp,int32_t h)80f54008ebSnatano ffs_clrblock(struct fs *fs, u_char *cp, int32_t h)
81f54008ebSnatano {
82f54008ebSnatano
83f54008ebSnatano switch ((int)fs->fs_fragshift) {
84f54008ebSnatano case 3:
85f54008ebSnatano cp[h] = 0;
86f54008ebSnatano return;
87f54008ebSnatano case 2:
88f54008ebSnatano cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
89f54008ebSnatano return;
90f54008ebSnatano case 1:
91f54008ebSnatano cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
92f54008ebSnatano return;
93f54008ebSnatano case 0:
94f54008ebSnatano cp[h >> 3] &= ~(0x01 << (h & 0x7));
95f54008ebSnatano return;
96f54008ebSnatano default:
97b35c7f73Snatano errx(1, "ffs_clrblock: unknown fs_fragshift %d",
98f54008ebSnatano (int)fs->fs_fragshift);
99f54008ebSnatano }
100f54008ebSnatano }
101f54008ebSnatano
102f54008ebSnatano /*
103f54008ebSnatano * put a block into the map
104f54008ebSnatano */
105f54008ebSnatano void
ffs_setblock(struct fs * fs,u_char * cp,int32_t h)106f54008ebSnatano ffs_setblock(struct fs *fs, u_char *cp, int32_t h)
107f54008ebSnatano {
108f54008ebSnatano
109f54008ebSnatano switch ((int)fs->fs_fragshift) {
110f54008ebSnatano case 3:
111f54008ebSnatano cp[h] = 0xff;
112f54008ebSnatano return;
113f54008ebSnatano case 2:
114f54008ebSnatano cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
115f54008ebSnatano return;
116f54008ebSnatano case 1:
117f54008ebSnatano cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
118f54008ebSnatano return;
119f54008ebSnatano case 0:
120f54008ebSnatano cp[h >> 3] |= (0x01 << (h & 0x7));
121f54008ebSnatano return;
122f54008ebSnatano default:
123b35c7f73Snatano errx(1, "ffs_setblock: unknown fs_fragshift %d",
124f54008ebSnatano (int)fs->fs_fragshift);
125f54008ebSnatano }
126f54008ebSnatano }
127f54008ebSnatano
128f54008ebSnatano /*
129f54008ebSnatano * Update the cluster map because of an allocation or free.
130f54008ebSnatano *
131f54008ebSnatano * Cnt == 1 means free; cnt == -1 means allocating.
132f54008ebSnatano */
133f54008ebSnatano void
ffs_clusteracct(struct fs * fs,struct cg * cgp,int32_t blkno,int cnt)134f54008ebSnatano ffs_clusteracct(struct fs *fs, struct cg *cgp, int32_t blkno, int cnt)
135f54008ebSnatano {
136f54008ebSnatano int32_t *sump;
137f54008ebSnatano int32_t *lp;
138f54008ebSnatano u_char *freemapp, *mapp;
139f54008ebSnatano int i, start, end, forw, back, map, bit;
140f54008ebSnatano
141f54008ebSnatano /* KASSERT(mutex_owned(&ump->um_lock)); */
142f54008ebSnatano
143f54008ebSnatano if (fs->fs_contigsumsize <= 0)
144f54008ebSnatano return;
1456c4d9c1cSnatano freemapp = cg_clustersfree(cgp);
1466c4d9c1cSnatano sump = cg_clustersum(cgp);
147f54008ebSnatano /*
148f54008ebSnatano * Allocate or clear the actual block.
149f54008ebSnatano */
150f54008ebSnatano if (cnt > 0)
151f54008ebSnatano setbit(freemapp, blkno);
152f54008ebSnatano else
153f54008ebSnatano clrbit(freemapp, blkno);
154f54008ebSnatano /*
155f54008ebSnatano * Find the size of the cluster going forward.
156f54008ebSnatano */
157f54008ebSnatano start = blkno + 1;
158f54008ebSnatano end = start + fs->fs_contigsumsize;
1597247f83aSnatano if ((uint32_t)end >= cgp->cg_nclusterblks)
1607247f83aSnatano end = cgp->cg_nclusterblks;
161f54008ebSnatano mapp = &freemapp[start / NBBY];
162f54008ebSnatano map = *mapp++;
163f54008ebSnatano bit = 1 << (start % NBBY);
164f54008ebSnatano for (i = start; i < end; i++) {
165f54008ebSnatano if ((map & bit) == 0)
166f54008ebSnatano break;
167f54008ebSnatano if ((i & (NBBY - 1)) != (NBBY - 1)) {
168f54008ebSnatano bit <<= 1;
169f54008ebSnatano } else {
170f54008ebSnatano map = *mapp++;
171f54008ebSnatano bit = 1;
172f54008ebSnatano }
173f54008ebSnatano }
174f54008ebSnatano forw = i - start;
175f54008ebSnatano /*
176f54008ebSnatano * Find the size of the cluster going backward.
177f54008ebSnatano */
178f54008ebSnatano start = blkno - 1;
179f54008ebSnatano end = start - fs->fs_contigsumsize;
180f54008ebSnatano if (end < 0)
181f54008ebSnatano end = -1;
182f54008ebSnatano mapp = &freemapp[start / NBBY];
183f54008ebSnatano map = *mapp--;
184f54008ebSnatano bit = 1 << (start % NBBY);
185f54008ebSnatano for (i = start; i > end; i--) {
186f54008ebSnatano if ((map & bit) == 0)
187f54008ebSnatano break;
188f54008ebSnatano if ((i & (NBBY - 1)) != 0) {
189f54008ebSnatano bit >>= 1;
190f54008ebSnatano } else {
191f54008ebSnatano map = *mapp--;
192f54008ebSnatano bit = 1 << (NBBY - 1);
193f54008ebSnatano }
194f54008ebSnatano }
195f54008ebSnatano back = start - i;
196f54008ebSnatano /*
197f54008ebSnatano * Account for old cluster and the possibly new forward and
198f54008ebSnatano * back clusters.
199f54008ebSnatano */
200f54008ebSnatano i = back + forw + 1;
201f54008ebSnatano if (i > fs->fs_contigsumsize)
202f54008ebSnatano i = fs->fs_contigsumsize;
203f54008ebSnatano sump[i] += cnt;
204f54008ebSnatano if (back > 0)
205f54008ebSnatano sump[back] -= cnt;
206f54008ebSnatano if (forw > 0)
207f54008ebSnatano sump[forw] -= cnt;
208f54008ebSnatano
209f54008ebSnatano /*
210f54008ebSnatano * Update cluster summary information.
211f54008ebSnatano */
212f54008ebSnatano lp = &sump[fs->fs_contigsumsize];
213f54008ebSnatano for (i = fs->fs_contigsumsize; i > 0; i--)
2147247f83aSnatano if (*lp-- > 0)
215f54008ebSnatano break;
216f54008ebSnatano }
217