xref: /freebsd/sys/ufs/ffs/ffs_subr.c (revision 51369649b03ece2aed3eb61b0c8214b9aa5b2fa2)
160727d8bSWarner Losh /*-
2*51369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3*51369649SPedro F. Giffuni  *
4df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1989, 1993
5df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
6df8bae1dSRodney W. Grimes  *
7df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
8df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
9df8bae1dSRodney W. Grimes  * are met:
10df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
11df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
12df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
13df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
14df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
1515c377c3SEd Maste  * 3. Neither the name of the University nor the names of its contributors
16df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
17df8bae1dSRodney W. Grimes  *    without specific prior written permission.
18df8bae1dSRodney W. Grimes  *
19df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
30df8bae1dSRodney W. Grimes  *
31996c772fSJohn Dyson  *	@(#)ffs_subr.c	8.5 (Berkeley) 3/21/95
32df8bae1dSRodney W. Grimes  */
33df8bae1dSRodney W. Grimes 
34f4636c59SDavid E. O'Brien #include <sys/cdefs.h>
35f4636c59SDavid E. O'Brien __FBSDID("$FreeBSD$");
36f4636c59SDavid E. O'Brien 
37df8bae1dSRodney W. Grimes #include <sys/param.h>
38df8bae1dSRodney W. Grimes 
39c4473420SPeter Wemm #ifndef _KERNEL
40996c772fSJohn Dyson #include <ufs/ufs/dinode.h>
411c85e6a3SKirk McKusick #include <ufs/ffs/fs.h>
42996c772fSJohn Dyson #else
43df8bae1dSRodney W. Grimes #include <sys/systm.h>
441cd52ec3SBruce Evans #include <sys/lock.h>
451c85e6a3SKirk McKusick #include <sys/malloc.h>
461c85e6a3SKirk McKusick #include <sys/mount.h>
47df8bae1dSRodney W. Grimes #include <sys/vnode.h>
489626b608SPoul-Henning Kamp #include <sys/bio.h>
49df8bae1dSRodney W. Grimes #include <sys/buf.h>
5008637435SBruce Evans #include <sys/ucred.h>
5108637435SBruce Evans 
52df8bae1dSRodney W. Grimes #include <ufs/ufs/quota.h>
53df8bae1dSRodney W. Grimes #include <ufs/ufs/inode.h>
541c85e6a3SKirk McKusick #include <ufs/ufs/extattr.h>
551c85e6a3SKirk McKusick #include <ufs/ufs/ufsmount.h>
561c85e6a3SKirk McKusick #include <ufs/ufs/ufs_extern.h>
57996c772fSJohn Dyson #include <ufs/ffs/ffs_extern.h>
581c85e6a3SKirk McKusick #include <ufs/ffs/fs.h>
59df8bae1dSRodney W. Grimes 
60df8bae1dSRodney W. Grimes /*
61df8bae1dSRodney W. Grimes  * Return buffer with the contents of block "offset" from the beginning of
62df8bae1dSRodney W. Grimes  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
63df8bae1dSRodney W. Grimes  * remaining space in the directory.
64df8bae1dSRodney W. Grimes  */
65df8bae1dSRodney W. Grimes int
6615c377c3SEd Maste ffs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
67df8bae1dSRodney W. Grimes {
68df8bae1dSRodney W. Grimes 	struct inode *ip;
6905f4ff5dSPoul-Henning Kamp 	struct fs *fs;
70df8bae1dSRodney W. Grimes 	struct buf *bp;
711c85e6a3SKirk McKusick 	ufs_lbn_t lbn;
72df8bae1dSRodney W. Grimes 	int bsize, error;
73df8bae1dSRodney W. Grimes 
74cec0f20cSPoul-Henning Kamp 	ip = VTOI(vp);
75e1db6897SKonstantin Belousov 	fs = ITOFS(ip);
76cec0f20cSPoul-Henning Kamp 	lbn = lblkno(fs, offset);
77df8bae1dSRodney W. Grimes 	bsize = blksize(fs, ip, lbn);
78df8bae1dSRodney W. Grimes 
79cec0f20cSPoul-Henning Kamp 	*bpp = NULL;
80cec0f20cSPoul-Henning Kamp 	error = bread(vp, lbn, bsize, NOCRED, &bp);
81c1d9efcbSPoul-Henning Kamp 	if (error) {
82df8bae1dSRodney W. Grimes 		brelse(bp);
83df8bae1dSRodney W. Grimes 		return (error);
84df8bae1dSRodney W. Grimes 	}
85cec0f20cSPoul-Henning Kamp 	if (res)
86cec0f20cSPoul-Henning Kamp 		*res = (char *)bp->b_data + blkoff(fs, offset);
87cec0f20cSPoul-Henning Kamp 	*bpp = bp;
88df8bae1dSRodney W. Grimes 	return (0);
89df8bae1dSRodney W. Grimes }
901c85e6a3SKirk McKusick 
911c85e6a3SKirk McKusick /*
921c85e6a3SKirk McKusick  * Load up the contents of an inode and copy the appropriate pieces
931c85e6a3SKirk McKusick  * to the incore copy.
941c85e6a3SKirk McKusick  */
951c85e6a3SKirk McKusick void
9615c377c3SEd Maste ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino)
971c85e6a3SKirk McKusick {
981c85e6a3SKirk McKusick 
99e1db6897SKonstantin Belousov 	if (I_IS_UFS1(ip)) {
1001c85e6a3SKirk McKusick 		*ip->i_din1 =
1011c85e6a3SKirk McKusick 		    *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1021c85e6a3SKirk McKusick 		ip->i_mode = ip->i_din1->di_mode;
1031c85e6a3SKirk McKusick 		ip->i_nlink = ip->i_din1->di_nlink;
1041c85e6a3SKirk McKusick 		ip->i_size = ip->i_din1->di_size;
1051c85e6a3SKirk McKusick 		ip->i_flags = ip->i_din1->di_flags;
1061c85e6a3SKirk McKusick 		ip->i_gen = ip->i_din1->di_gen;
1071c85e6a3SKirk McKusick 		ip->i_uid = ip->i_din1->di_uid;
1081c85e6a3SKirk McKusick 		ip->i_gid = ip->i_din1->di_gid;
1091c85e6a3SKirk McKusick 	} else {
1101c85e6a3SKirk McKusick 		*ip->i_din2 =
1111c85e6a3SKirk McKusick 		    *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1121c85e6a3SKirk McKusick 		ip->i_mode = ip->i_din2->di_mode;
1131c85e6a3SKirk McKusick 		ip->i_nlink = ip->i_din2->di_nlink;
1141c85e6a3SKirk McKusick 		ip->i_size = ip->i_din2->di_size;
1151c85e6a3SKirk McKusick 		ip->i_flags = ip->i_din2->di_flags;
1161c85e6a3SKirk McKusick 		ip->i_gen = ip->i_din2->di_gen;
1171c85e6a3SKirk McKusick 		ip->i_uid = ip->i_din2->di_uid;
1181c85e6a3SKirk McKusick 		ip->i_gid = ip->i_din2->di_gid;
1191c85e6a3SKirk McKusick 	}
1201c85e6a3SKirk McKusick }
1211c85e6a3SKirk McKusick #endif /* KERNEL */
122df8bae1dSRodney W. Grimes 
123df8bae1dSRodney W. Grimes /*
124df8bae1dSRodney W. Grimes  * Update the frsum fields to reflect addition or deletion
125df8bae1dSRodney W. Grimes  * of some frags.
126df8bae1dSRodney W. Grimes  */
127df8bae1dSRodney W. Grimes void
12815c377c3SEd Maste ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt)
129df8bae1dSRodney W. Grimes {
130df8bae1dSRodney W. Grimes 	int inblk;
13105f4ff5dSPoul-Henning Kamp 	int field, subfield;
13205f4ff5dSPoul-Henning Kamp 	int siz, pos;
133df8bae1dSRodney W. Grimes 
134df8bae1dSRodney W. Grimes 	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
135df8bae1dSRodney W. Grimes 	fragmap <<= 1;
136df8bae1dSRodney W. Grimes 	for (siz = 1; siz < fs->fs_frag; siz++) {
137df8bae1dSRodney W. Grimes 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
138df8bae1dSRodney W. Grimes 			continue;
139df8bae1dSRodney W. Grimes 		field = around[siz];
140df8bae1dSRodney W. Grimes 		subfield = inside[siz];
141df8bae1dSRodney W. Grimes 		for (pos = siz; pos <= fs->fs_frag; pos++) {
142df8bae1dSRodney W. Grimes 			if ((fragmap & field) == subfield) {
143df8bae1dSRodney W. Grimes 				fraglist[siz] += cnt;
144df8bae1dSRodney W. Grimes 				pos += siz;
145df8bae1dSRodney W. Grimes 				field <<= siz;
146df8bae1dSRodney W. Grimes 				subfield <<= siz;
147df8bae1dSRodney W. Grimes 			}
148df8bae1dSRodney W. Grimes 			field <<= 1;
149df8bae1dSRodney W. Grimes 			subfield <<= 1;
150df8bae1dSRodney W. Grimes 		}
151df8bae1dSRodney W. Grimes 	}
152df8bae1dSRodney W. Grimes }
153df8bae1dSRodney W. Grimes 
154df8bae1dSRodney W. Grimes /*
155df8bae1dSRodney W. Grimes  * block operations
156df8bae1dSRodney W. Grimes  *
157df8bae1dSRodney W. Grimes  * check if a block is available
158df8bae1dSRodney W. Grimes  */
159df8bae1dSRodney W. Grimes int
16015c377c3SEd Maste ffs_isblock(struct fs *fs, unsigned char *cp, ufs1_daddr_t h)
161df8bae1dSRodney W. Grimes {
162df8bae1dSRodney W. Grimes 	unsigned char mask;
163df8bae1dSRodney W. Grimes 
164df8bae1dSRodney W. Grimes 	switch ((int)fs->fs_frag) {
165df8bae1dSRodney W. Grimes 	case 8:
166df8bae1dSRodney W. Grimes 		return (cp[h] == 0xff);
167df8bae1dSRodney W. Grimes 	case 4:
168df8bae1dSRodney W. Grimes 		mask = 0x0f << ((h & 0x1) << 2);
169df8bae1dSRodney W. Grimes 		return ((cp[h >> 1] & mask) == mask);
170df8bae1dSRodney W. Grimes 	case 2:
171df8bae1dSRodney W. Grimes 		mask = 0x03 << ((h & 0x3) << 1);
172df8bae1dSRodney W. Grimes 		return ((cp[h >> 2] & mask) == mask);
173df8bae1dSRodney W. Grimes 	case 1:
174df8bae1dSRodney W. Grimes 		mask = 0x01 << (h & 0x7);
175df8bae1dSRodney W. Grimes 		return ((cp[h >> 3] & mask) == mask);
176df8bae1dSRodney W. Grimes 	default:
177113db2ddSJeff Roberson #ifdef _KERNEL
178df8bae1dSRodney W. Grimes 		panic("ffs_isblock");
179113db2ddSJeff Roberson #endif
180113db2ddSJeff Roberson 		break;
181113db2ddSJeff Roberson 	}
182113db2ddSJeff Roberson 	return (0);
183113db2ddSJeff Roberson }
184113db2ddSJeff Roberson 
185113db2ddSJeff Roberson /*
186113db2ddSJeff Roberson  * check if a block is free
187113db2ddSJeff Roberson  */
188113db2ddSJeff Roberson int
18915c377c3SEd Maste ffs_isfreeblock(struct fs *fs, u_char *cp, ufs1_daddr_t h)
190113db2ddSJeff Roberson {
191113db2ddSJeff Roberson 
192113db2ddSJeff Roberson 	switch ((int)fs->fs_frag) {
193113db2ddSJeff Roberson 	case 8:
194113db2ddSJeff Roberson 		return (cp[h] == 0);
195113db2ddSJeff Roberson 	case 4:
196113db2ddSJeff Roberson 		return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
197113db2ddSJeff Roberson 	case 2:
198113db2ddSJeff Roberson 		return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
199113db2ddSJeff Roberson 	case 1:
200113db2ddSJeff Roberson 		return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
201113db2ddSJeff Roberson 	default:
202113db2ddSJeff Roberson #ifdef _KERNEL
203113db2ddSJeff Roberson 		panic("ffs_isfreeblock");
204113db2ddSJeff Roberson #endif
205113db2ddSJeff Roberson 		break;
206df8bae1dSRodney W. Grimes 	}
207589c7af9SKirk McKusick 	return (0);
208df8bae1dSRodney W. Grimes }
209df8bae1dSRodney W. Grimes 
210df8bae1dSRodney W. Grimes /*
211df8bae1dSRodney W. Grimes  * take a block out of the map
212df8bae1dSRodney W. Grimes  */
213df8bae1dSRodney W. Grimes void
21415c377c3SEd Maste ffs_clrblock(struct fs *fs, u_char *cp, ufs1_daddr_t h)
215df8bae1dSRodney W. Grimes {
216df8bae1dSRodney W. Grimes 
217df8bae1dSRodney W. Grimes 	switch ((int)fs->fs_frag) {
218df8bae1dSRodney W. Grimes 	case 8:
219df8bae1dSRodney W. Grimes 		cp[h] = 0;
220df8bae1dSRodney W. Grimes 		return;
221df8bae1dSRodney W. Grimes 	case 4:
222df8bae1dSRodney W. Grimes 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
223df8bae1dSRodney W. Grimes 		return;
224df8bae1dSRodney W. Grimes 	case 2:
225df8bae1dSRodney W. Grimes 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
226df8bae1dSRodney W. Grimes 		return;
227df8bae1dSRodney W. Grimes 	case 1:
228df8bae1dSRodney W. Grimes 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
229df8bae1dSRodney W. Grimes 		return;
230df8bae1dSRodney W. Grimes 	default:
231113db2ddSJeff Roberson #ifdef _KERNEL
232df8bae1dSRodney W. Grimes 		panic("ffs_clrblock");
233113db2ddSJeff Roberson #endif
234113db2ddSJeff Roberson 		break;
235df8bae1dSRodney W. Grimes 	}
236df8bae1dSRodney W. Grimes }
237df8bae1dSRodney W. Grimes 
238df8bae1dSRodney W. Grimes /*
239df8bae1dSRodney W. Grimes  * put a block into the map
240df8bae1dSRodney W. Grimes  */
241df8bae1dSRodney W. Grimes void
24215c377c3SEd Maste ffs_setblock(struct fs *fs, unsigned char *cp, ufs1_daddr_t h)
243df8bae1dSRodney W. Grimes {
244df8bae1dSRodney W. Grimes 
245df8bae1dSRodney W. Grimes 	switch ((int)fs->fs_frag) {
246df8bae1dSRodney W. Grimes 
247df8bae1dSRodney W. Grimes 	case 8:
248df8bae1dSRodney W. Grimes 		cp[h] = 0xff;
249df8bae1dSRodney W. Grimes 		return;
250df8bae1dSRodney W. Grimes 	case 4:
251df8bae1dSRodney W. Grimes 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
252df8bae1dSRodney W. Grimes 		return;
253df8bae1dSRodney W. Grimes 	case 2:
254df8bae1dSRodney W. Grimes 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
255df8bae1dSRodney W. Grimes 		return;
256df8bae1dSRodney W. Grimes 	case 1:
257df8bae1dSRodney W. Grimes 		cp[h >> 3] |= (0x01 << (h & 0x7));
258df8bae1dSRodney W. Grimes 		return;
259df8bae1dSRodney W. Grimes 	default:
260113db2ddSJeff Roberson #ifdef _KERNEL
261df8bae1dSRodney W. Grimes 		panic("ffs_setblock");
262113db2ddSJeff Roberson #endif
263113db2ddSJeff Roberson 		break;
264df8bae1dSRodney W. Grimes 	}
265df8bae1dSRodney W. Grimes }
266113db2ddSJeff Roberson 
267113db2ddSJeff Roberson /*
268113db2ddSJeff Roberson  * Update the cluster map because of an allocation or free.
269113db2ddSJeff Roberson  *
270113db2ddSJeff Roberson  * Cnt == 1 means free; cnt == -1 means allocating.
271113db2ddSJeff Roberson  */
272113db2ddSJeff Roberson void
27315c377c3SEd Maste ffs_clusteracct(struct fs *fs, struct cg *cgp, ufs1_daddr_t blkno, int cnt)
274113db2ddSJeff Roberson {
275113db2ddSJeff Roberson 	int32_t *sump;
276113db2ddSJeff Roberson 	int32_t *lp;
277113db2ddSJeff Roberson 	u_char *freemapp, *mapp;
278113db2ddSJeff Roberson 	int i, start, end, forw, back, map, bit;
279113db2ddSJeff Roberson 
280113db2ddSJeff Roberson 	if (fs->fs_contigsumsize <= 0)
281113db2ddSJeff Roberson 		return;
282113db2ddSJeff Roberson 	freemapp = cg_clustersfree(cgp);
283113db2ddSJeff Roberson 	sump = cg_clustersum(cgp);
284113db2ddSJeff Roberson 	/*
285113db2ddSJeff Roberson 	 * Allocate or clear the actual block.
286113db2ddSJeff Roberson 	 */
287113db2ddSJeff Roberson 	if (cnt > 0)
288113db2ddSJeff Roberson 		setbit(freemapp, blkno);
289113db2ddSJeff Roberson 	else
290113db2ddSJeff Roberson 		clrbit(freemapp, blkno);
291113db2ddSJeff Roberson 	/*
292113db2ddSJeff Roberson 	 * Find the size of the cluster going forward.
293113db2ddSJeff Roberson 	 */
294113db2ddSJeff Roberson 	start = blkno + 1;
295113db2ddSJeff Roberson 	end = start + fs->fs_contigsumsize;
296113db2ddSJeff Roberson 	if (end >= cgp->cg_nclusterblks)
297113db2ddSJeff Roberson 		end = cgp->cg_nclusterblks;
298113db2ddSJeff Roberson 	mapp = &freemapp[start / NBBY];
299113db2ddSJeff Roberson 	map = *mapp++;
300113db2ddSJeff Roberson 	bit = 1 << (start % NBBY);
301113db2ddSJeff Roberson 	for (i = start; i < end; i++) {
302113db2ddSJeff Roberson 		if ((map & bit) == 0)
303113db2ddSJeff Roberson 			break;
304113db2ddSJeff Roberson 		if ((i & (NBBY - 1)) != (NBBY - 1)) {
305113db2ddSJeff Roberson 			bit <<= 1;
306113db2ddSJeff Roberson 		} else {
307113db2ddSJeff Roberson 			map = *mapp++;
308113db2ddSJeff Roberson 			bit = 1;
309113db2ddSJeff Roberson 		}
310113db2ddSJeff Roberson 	}
311113db2ddSJeff Roberson 	forw = i - start;
312113db2ddSJeff Roberson 	/*
313113db2ddSJeff Roberson 	 * Find the size of the cluster going backward.
314113db2ddSJeff Roberson 	 */
315113db2ddSJeff Roberson 	start = blkno - 1;
316113db2ddSJeff Roberson 	end = start - fs->fs_contigsumsize;
317113db2ddSJeff Roberson 	if (end < 0)
318113db2ddSJeff Roberson 		end = -1;
319113db2ddSJeff Roberson 	mapp = &freemapp[start / NBBY];
320113db2ddSJeff Roberson 	map = *mapp--;
321113db2ddSJeff Roberson 	bit = 1 << (start % NBBY);
322113db2ddSJeff Roberson 	for (i = start; i > end; i--) {
323113db2ddSJeff Roberson 		if ((map & bit) == 0)
324113db2ddSJeff Roberson 			break;
325113db2ddSJeff Roberson 		if ((i & (NBBY - 1)) != 0) {
326113db2ddSJeff Roberson 			bit >>= 1;
327113db2ddSJeff Roberson 		} else {
328113db2ddSJeff Roberson 			map = *mapp--;
329113db2ddSJeff Roberson 			bit = 1 << (NBBY - 1);
330113db2ddSJeff Roberson 		}
331113db2ddSJeff Roberson 	}
332113db2ddSJeff Roberson 	back = start - i;
333113db2ddSJeff Roberson 	/*
334113db2ddSJeff Roberson 	 * Account for old cluster and the possibly new forward and
335113db2ddSJeff Roberson 	 * back clusters.
336113db2ddSJeff Roberson 	 */
337113db2ddSJeff Roberson 	i = back + forw + 1;
338113db2ddSJeff Roberson 	if (i > fs->fs_contigsumsize)
339113db2ddSJeff Roberson 		i = fs->fs_contigsumsize;
340113db2ddSJeff Roberson 	sump[i] += cnt;
341113db2ddSJeff Roberson 	if (back > 0)
342113db2ddSJeff Roberson 		sump[back] -= cnt;
343113db2ddSJeff Roberson 	if (forw > 0)
344113db2ddSJeff Roberson 		sump[forw] -= cnt;
345113db2ddSJeff Roberson 	/*
346113db2ddSJeff Roberson 	 * Update cluster summary information.
347113db2ddSJeff Roberson 	 */
348113db2ddSJeff Roberson 	lp = &sump[fs->fs_contigsumsize];
349113db2ddSJeff Roberson 	for (i = fs->fs_contigsumsize; i > 0; i--)
350113db2ddSJeff Roberson 		if (*lp-- > 0)
351113db2ddSJeff Roberson 			break;
352113db2ddSJeff Roberson 	fs->fs_maxcluster[cgp->cg_cgx] = i;
353113db2ddSJeff Roberson }
354