xref: /openbsd-src/usr.sbin/makefs/ffs/ffs_subr.c (revision 8e544e80ad051c7ebb0293f80569ecb775fbd3bf)
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