gjournal.c revision 163849
1163849Spjd/*-
2163849Spjd * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3163849Spjd * All rights reserved.
4163849Spjd *
5163849Spjd * Redistribution and use in source and binary forms, with or without
6163849Spjd * modification, are permitted provided that the following conditions
7163849Spjd * are met:
8163849Spjd * 1. Redistributions of source code must retain the above copyright
9163849Spjd *    notice, this list of conditions and the following disclaimer.
10163849Spjd * 2. Redistributions in binary form must reproduce the above copyright
11163849Spjd *    notice, this list of conditions and the following disclaimer in the
12163849Spjd *    documentation and/or other materials provided with the distribution.
13163849Spjd *
14163849Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15163849Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16163849Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17163849Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18163849Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19163849Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20163849Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21163849Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22163849Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23163849Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24163849Spjd * SUCH DAMAGE.
25163849Spjd *
26163849Spjd * Copyright (c) 1982, 1986, 1989, 1993
27163849Spjd *	The Regents of the University of California.  All rights reserved.
28163849Spjd *
29163849Spjd * Redistribution and use in source and binary forms, with or without
30163849Spjd * modification, are permitted provided that the following conditions
31163849Spjd * are met:
32163849Spjd * 1. Redistributions of source code must retain the above copyright
33163849Spjd *    notice, this list of conditions and the following disclaimer.
34163849Spjd * 2. Redistributions in binary form must reproduce the above copyright
35163849Spjd *    notice, this list of conditions and the following disclaimer in the
36163849Spjd *    documentation and/or other materials provided with the distribution.
37163849Spjd * 4. Neither the name of the University nor the names of its contributors
38163849Spjd *    may be used to endorse or promote products derived from this software
39163849Spjd *    without specific prior written permission.
40163849Spjd *
41163849Spjd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42163849Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43163849Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44163849Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45163849Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46163849Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47163849Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48163849Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49163849Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50163849Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51163849Spjd * SUCH DAMAGE.
52163849Spjd */
53163849Spjd
54163849Spjd#include <sys/cdefs.h>
55163849Spjd__FBSDID("$FreeBSD: head/sbin/fsck_ffs/gjournal.c 163849 2006-10-31 22:21:01Z pjd $");
56163849Spjd
57163849Spjd#include <sys/param.h>
58163849Spjd#include <sys/disklabel.h>
59163849Spjd#include <sys/mount.h>
60163849Spjd#include <sys/stat.h>
61163849Spjd
62163849Spjd#include <ufs/ufs/ufsmount.h>
63163849Spjd#include <ufs/ufs/dinode.h>
64163849Spjd#include <ufs/ffs/fs.h>
65163849Spjd
66163849Spjd#include <stdio.h>
67163849Spjd#include <stdlib.h>
68163849Spjd#include <stdint.h>
69163849Spjd#include <libufs.h>
70163849Spjd#include <strings.h>
71163849Spjd#include <err.h>
72163849Spjd#include <assert.h>
73163849Spjd
74163849Spjd#include "fsck.h"
75163849Spjd
76163849Spjdstruct cgchain {
77163849Spjd	union {
78163849Spjd		struct cg cgcu_cg;
79163849Spjd		char cgcu_buf[MAXBSIZE];
80163849Spjd	} cgc_union;
81163849Spjd	int	cgc_busy;
82163849Spjd	int	cgc_dirty;
83163849Spjd	LIST_ENTRY(cgchain) cgc_next;
84163849Spjd};
85163849Spjd#define cgc_cg	cgc_union.cgcu_cg
86163849Spjd
87163849Spjd#define	MAX_CACHED_CGS	1024
88163849Spjdstatic unsigned ncgs = 0;
89163849Spjdstatic LIST_HEAD(, cgchain) cglist = LIST_HEAD_INITIALIZER(&cglist);
90163849Spjd
91163849Spjdstatic const char *devnam;
92163849Spjdstatic struct uufsd *disk = NULL;
93163849Spjdstatic struct fs *fs = NULL;
94163849Spjdstruct ufs2_dinode ufs2_zino;
95163849Spjd
96163849Spjdstatic void putcgs(void);
97163849Spjd
98163849Spjd/*
99163849Spjd * Write current block of inodes.
100163849Spjd */
101163849Spjdstatic int
102163849Spjdputino(struct uufsd *disk, ino_t inode)
103163849Spjd{
104163849Spjd	caddr_t inoblock;
105163849Spjd	struct fs *fs;
106163849Spjd	ssize_t ret;
107163849Spjd
108163849Spjd	fs = &disk->d_fs;
109163849Spjd	inoblock = disk->d_inoblock;
110163849Spjd
111163849Spjd	assert(inoblock != NULL);
112163849Spjd	assert(inode >= disk->d_inomin && inode <= disk->d_inomax);
113163849Spjd	ret = bwrite(disk, fsbtodb(fs, ino_to_fsba(fs, inode)), inoblock,
114163849Spjd	    fs->fs_bsize);
115163849Spjd
116163849Spjd	return (ret == -1 ? -1 : 0);
117163849Spjd}
118163849Spjd
119163849Spjd/*
120163849Spjd * Return cylinder group from the cache or load it if it is not in the
121163849Spjd * cache yet.
122163849Spjd * Don't cache more than MAX_CACHED_CGS cylinder groups.
123163849Spjd */
124163849Spjdstatic struct cgchain *
125163849Spjdgetcg(int cg)
126163849Spjd{
127163849Spjd	struct cgchain *cgc;
128163849Spjd
129163849Spjd	assert(disk != NULL && fs != NULL);
130163849Spjd	LIST_FOREACH(cgc, &cglist, cgc_next) {
131163849Spjd		if (cgc->cgc_cg.cg_cgx == cg) {
132163849Spjd			//printf("%s: Found cg=%d\n", __func__, cg);
133163849Spjd			return (cgc);
134163849Spjd		}
135163849Spjd	}
136163849Spjd	/*
137163849Spjd	 * Our cache is full? Let's clean it up.
138163849Spjd	 */
139163849Spjd	if (ncgs >= MAX_CACHED_CGS) {
140163849Spjd		//printf("%s: Flushing CGs.\n", __func__);
141163849Spjd		putcgs();
142163849Spjd	}
143163849Spjd	cgc = malloc(sizeof(*cgc));
144163849Spjd	if (cgc == NULL) {
145163849Spjd		/*
146163849Spjd		 * Cannot allocate memory?
147163849Spjd		 * Let's put all currently loaded and not busy cylinder groups
148163849Spjd		 * on disk and try again.
149163849Spjd		 */
150163849Spjd		//printf("%s: No memory, flushing CGs.\n", __func__);
151163849Spjd		putcgs();
152163849Spjd		cgc = malloc(sizeof(*cgc));
153163849Spjd		if (cgc == NULL)
154163849Spjd			err(1, "malloc(%zu)", sizeof(*cgc));
155163849Spjd	}
156163849Spjd	if (cgread1(disk, cg) == -1)
157163849Spjd		err(1, "cgread1(%d)", cg);
158163849Spjd	bcopy(&disk->d_cg, &cgc->cgc_cg, sizeof(cgc->cgc_union));
159163849Spjd	cgc->cgc_busy = 0;
160163849Spjd	cgc->cgc_dirty = 0;
161163849Spjd	LIST_INSERT_HEAD(&cglist, cgc, cgc_next);
162163849Spjd	ncgs++;
163163849Spjd	//printf("%s: Read cg=%d\n", __func__, cg);
164163849Spjd	return (cgc);
165163849Spjd}
166163849Spjd
167163849Spjd/*
168163849Spjd * Mark cylinder group as dirty - it will be written back on putcgs().
169163849Spjd */
170163849Spjdstatic void
171163849Spjddirtycg(struct cgchain *cgc)
172163849Spjd{
173163849Spjd
174163849Spjd	cgc->cgc_dirty = 1;
175163849Spjd}
176163849Spjd
177163849Spjd/*
178163849Spjd * Mark cylinder group as busy - it will not be freed on putcgs().
179163849Spjd */
180163849Spjdstatic void
181163849Spjdbusycg(struct cgchain *cgc)
182163849Spjd{
183163849Spjd
184163849Spjd	cgc->cgc_busy = 1;
185163849Spjd}
186163849Spjd
187163849Spjd/*
188163849Spjd * Unmark the given cylinder group as busy.
189163849Spjd */
190163849Spjdstatic void
191163849Spjdunbusycg(struct cgchain *cgc)
192163849Spjd{
193163849Spjd
194163849Spjd	cgc->cgc_busy = 0;
195163849Spjd}
196163849Spjd
197163849Spjd/*
198163849Spjd * Write back all dirty cylinder groups.
199163849Spjd * Free all non-busy cylinder groups.
200163849Spjd */
201163849Spjdstatic void
202163849Spjdputcgs(void)
203163849Spjd{
204163849Spjd	struct cgchain *cgc, *cgc2;
205163849Spjd
206163849Spjd	assert(disk != NULL && fs != NULL);
207163849Spjd	LIST_FOREACH_SAFE(cgc, &cglist, cgc_next, cgc2) {
208163849Spjd		if (cgc->cgc_busy)
209163849Spjd			continue;
210163849Spjd		LIST_REMOVE(cgc, cgc_next);
211163849Spjd		ncgs--;
212163849Spjd		if (cgc->cgc_dirty) {
213163849Spjd			bcopy(&cgc->cgc_cg, &disk->d_cg,
214163849Spjd			    sizeof(cgc->cgc_union));
215163849Spjd			if (cgwrite1(disk, cgc->cgc_cg.cg_cgx) == -1)
216163849Spjd				err(1, "cgwrite1(%d)", cgc->cgc_cg.cg_cgx);
217163849Spjd			//printf("%s: Wrote cg=%d\n", __func__,
218163849Spjd			//    cgc->cgc_cg.cg_cgx);
219163849Spjd		}
220163849Spjd		free(cgc);
221163849Spjd	}
222163849Spjd}
223163849Spjd
224163849Spjd#if 0
225163849Spjd/*
226163849Spjd * Free all non-busy cylinder groups without storing the dirty ones.
227163849Spjd */
228163849Spjdstatic void
229163849Spjdcancelcgs(void)
230163849Spjd{
231163849Spjd	struct cgchain *cgc;
232163849Spjd
233163849Spjd	assert(disk != NULL && fs != NULL);
234163849Spjd	while ((cgc = LIST_FIRST(&cglist)) != NULL) {
235163849Spjd		if (cgc->cgc_busy)
236163849Spjd			continue;
237163849Spjd		LIST_REMOVE(cgc, cgc_next);
238163849Spjd		//printf("%s: Canceled cg=%d\n", __func__, cgc->cgc_cg.cg_cgx);
239163849Spjd		free(cgc);
240163849Spjd	}
241163849Spjd}
242163849Spjd#endif
243163849Spjd
244163849Spjd/*
245163849Spjd * Open the given provider, load statistics.
246163849Spjd */
247163849Spjdstatic void
248163849Spjdgetdisk(void)
249163849Spjd{
250163849Spjd	int i;
251163849Spjd
252163849Spjd	if (disk != NULL)
253163849Spjd		return;
254163849Spjd	disk = malloc(sizeof(*disk));
255163849Spjd	if (disk == NULL)
256163849Spjd		err(1, "malloc(%zu)", sizeof(*disk));
257163849Spjd	if (ufs_disk_fillout(disk, devnam) == -1) {
258163849Spjd		err(1, "ufs_disk_fillout(%s) failed: %s", devnam,
259163849Spjd		    disk->d_error);
260163849Spjd	}
261163849Spjd	fs = &disk->d_fs;
262163849Spjd	fs->fs_csp = malloc((size_t)fs->fs_cssize);
263163849Spjd	if (fs->fs_csp == NULL)
264163849Spjd		err(1, "malloc(%zu)", (size_t)fs->fs_cssize);
265163849Spjd	bzero(fs->fs_csp, (size_t)fs->fs_cssize);
266163849Spjd	for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) {
267163849Spjd		if (bread(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)),
268163849Spjd		    (void *)(((char *)fs->fs_csp) + i),
269163849Spjd		    (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize)) == -1) {
270163849Spjd			err(1, "bread: %s", disk->d_error);
271163849Spjd		}
272163849Spjd	}
273163849Spjd	if (fs->fs_contigsumsize > 0) {
274163849Spjd		fs->fs_maxcluster = malloc(fs->fs_ncg * sizeof(int32_t));
275163849Spjd		if (fs->fs_maxcluster == NULL)
276163849Spjd			err(1, "malloc(%zu)", fs->fs_ncg * sizeof(int32_t));
277163849Spjd		for (i = 0; i < fs->fs_ncg; i++)
278163849Spjd			fs->fs_maxcluster[i] = fs->fs_contigsumsize;
279163849Spjd	}
280163849Spjd}
281163849Spjd
282163849Spjd/*
283163849Spjd * Mark file system as clean, write the super-block back, close the disk.
284163849Spjd */
285163849Spjdstatic void
286163849Spjdclosedisk(void)
287163849Spjd{
288163849Spjd
289163849Spjd	free(fs->fs_csp);
290163849Spjd	if (fs->fs_contigsumsize > 0) {
291163849Spjd		free(fs->fs_maxcluster);
292163849Spjd		fs->fs_maxcluster = NULL;
293163849Spjd	}
294163849Spjd	fs->fs_clean = 1;
295163849Spjd	if (sbwrite(disk, 0) == -1)
296163849Spjd		err(1, "sbwrite(%s)", devnam);
297163849Spjd	if (ufs_disk_close(disk) == -1)
298163849Spjd		err(1, "ufs_disk_close(%s)", devnam);
299163849Spjd	free(disk);
300163849Spjd	disk = NULL;
301163849Spjd	fs = NULL;
302163849Spjd}
303163849Spjd
304163849Spjd/*
305163849Spjd * Write the statistics back, call closedisk().
306163849Spjd */
307163849Spjdstatic void
308163849Spjdputdisk(void)
309163849Spjd{
310163849Spjd	int i;
311163849Spjd
312163849Spjd	assert(disk != NULL && fs != NULL);
313163849Spjd	for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) {
314163849Spjd		if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)),
315163849Spjd		    (void *)(((char *)fs->fs_csp) + i),
316163849Spjd		    (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize)) == -1) {
317163849Spjd			err(1, "bwrite: %s", disk->d_error);
318163849Spjd		}
319163849Spjd	}
320163849Spjd	closedisk();
321163849Spjd}
322163849Spjd
323163849Spjd#if 0
324163849Spjd/*
325163849Spjd * Free memory, close the disk, but don't write anything back.
326163849Spjd */
327163849Spjdstatic void
328163849Spjdcanceldisk(void)
329163849Spjd{
330163849Spjd	int i;
331163849Spjd
332163849Spjd	assert(disk != NULL && fs != NULL);
333163849Spjd	free(fs->fs_csp);
334163849Spjd	if (fs->fs_contigsumsize > 0)
335163849Spjd		free(fs->fs_maxcluster);
336163849Spjd	if (ufs_disk_close(disk) == -1)
337163849Spjd		err(1, "ufs_disk_close(%s)", devnam);
338163849Spjd	free(disk);
339163849Spjd	disk = NULL;
340163849Spjd	fs = NULL;
341163849Spjd}
342163849Spjd#endif
343163849Spjd
344163849Spjdstatic int
345163849Spjdisblock(unsigned char *cp, ufs1_daddr_t h)
346163849Spjd{
347163849Spjd	unsigned char mask;
348163849Spjd
349163849Spjd	switch ((int)fs->fs_frag) {
350163849Spjd	case 8:
351163849Spjd		return (cp[h] == 0xff);
352163849Spjd	case 4:
353163849Spjd		mask = 0x0f << ((h & 0x1) << 2);
354163849Spjd		return ((cp[h >> 1] & mask) == mask);
355163849Spjd	case 2:
356163849Spjd		mask = 0x03 << ((h & 0x3) << 1);
357163849Spjd		return ((cp[h >> 2] & mask) == mask);
358163849Spjd	case 1:
359163849Spjd		mask = 0x01 << (h & 0x7);
360163849Spjd		return ((cp[h >> 3] & mask) == mask);
361163849Spjd	default:
362163849Spjd		assert(!"isblock: invalid number of fragments");
363163849Spjd	}
364163849Spjd	return (0);
365163849Spjd}
366163849Spjd
367163849Spjd/*
368163849Spjd * put a block into the map
369163849Spjd */
370163849Spjdstatic void
371163849Spjdsetblock(unsigned char *cp, ufs1_daddr_t h)
372163849Spjd{
373163849Spjd
374163849Spjd	switch ((int)fs->fs_frag) {
375163849Spjd	case 8:
376163849Spjd		cp[h] = 0xff;
377163849Spjd		return;
378163849Spjd	case 4:
379163849Spjd		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
380163849Spjd		return;
381163849Spjd	case 2:
382163849Spjd		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
383163849Spjd		return;
384163849Spjd	case 1:
385163849Spjd		cp[h >> 3] |= (0x01 << (h & 0x7));
386163849Spjd		return;
387163849Spjd	default:
388163849Spjd		assert(!"setblock: invalid number of fragments");
389163849Spjd	}
390163849Spjd}
391163849Spjd
392163849Spjd/*
393163849Spjd * check if a block is free
394163849Spjd */
395163849Spjdstatic int
396163849Spjdisfreeblock(u_char *cp, ufs1_daddr_t h)
397163849Spjd{
398163849Spjd
399163849Spjd	switch ((int)fs->fs_frag) {
400163849Spjd	case 8:
401163849Spjd		return (cp[h] == 0);
402163849Spjd	case 4:
403163849Spjd		return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
404163849Spjd	case 2:
405163849Spjd		return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
406163849Spjd	case 1:
407163849Spjd		return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
408163849Spjd	default:
409163849Spjd		assert(!"isfreeblock: invalid number of fragments");
410163849Spjd	}
411163849Spjd	return (0);
412163849Spjd}
413163849Spjd
414163849Spjd/*
415163849Spjd * Update the frsum fields to reflect addition or deletion
416163849Spjd * of some frags.
417163849Spjd */
418163849Spjdvoid
419163849Spjdfragacct(int fragmap, int32_t fraglist[], int cnt)
420163849Spjd{
421163849Spjd	int inblk;
422163849Spjd	int field, subfield;
423163849Spjd	int siz, pos;
424163849Spjd
425163849Spjd	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
426163849Spjd	fragmap <<= 1;
427163849Spjd	for (siz = 1; siz < fs->fs_frag; siz++) {
428163849Spjd		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
429163849Spjd			continue;
430163849Spjd		field = around[siz];
431163849Spjd		subfield = inside[siz];
432163849Spjd		for (pos = siz; pos <= fs->fs_frag; pos++) {
433163849Spjd			if ((fragmap & field) == subfield) {
434163849Spjd				fraglist[siz] += cnt;
435163849Spjd				pos += siz;
436163849Spjd				field <<= siz;
437163849Spjd				subfield <<= siz;
438163849Spjd			}
439163849Spjd			field <<= 1;
440163849Spjd			subfield <<= 1;
441163849Spjd		}
442163849Spjd	}
443163849Spjd}
444163849Spjd
445163849Spjdstatic void
446163849Spjdclusteracct(struct cg *cgp, ufs1_daddr_t blkno)
447163849Spjd{
448163849Spjd	int32_t *sump;
449163849Spjd	int32_t *lp;
450163849Spjd	u_char *freemapp, *mapp;
451163849Spjd	int i, start, end, forw, back, map, bit;
452163849Spjd
453163849Spjd	if (fs->fs_contigsumsize <= 0)
454163849Spjd		return;
455163849Spjd	freemapp = cg_clustersfree(cgp);
456163849Spjd	sump = cg_clustersum(cgp);
457163849Spjd	/*
458163849Spjd	 * Clear the actual block.
459163849Spjd	 */
460163849Spjd	setbit(freemapp, blkno);
461163849Spjd	/*
462163849Spjd	 * Find the size of the cluster going forward.
463163849Spjd	 */
464163849Spjd	start = blkno + 1;
465163849Spjd	end = start + fs->fs_contigsumsize;
466163849Spjd	if (end >= cgp->cg_nclusterblks)
467163849Spjd		end = cgp->cg_nclusterblks;
468163849Spjd	mapp = &freemapp[start / NBBY];
469163849Spjd	map = *mapp++;
470163849Spjd	bit = 1 << (start % NBBY);
471163849Spjd	for (i = start; i < end; i++) {
472163849Spjd		if ((map & bit) == 0)
473163849Spjd			break;
474163849Spjd		if ((i & (NBBY - 1)) != (NBBY - 1)) {
475163849Spjd			bit <<= 1;
476163849Spjd		} else {
477163849Spjd			map = *mapp++;
478163849Spjd			bit = 1;
479163849Spjd		}
480163849Spjd	}
481163849Spjd	forw = i - start;
482163849Spjd	/*
483163849Spjd	 * Find the size of the cluster going backward.
484163849Spjd	 */
485163849Spjd	start = blkno - 1;
486163849Spjd	end = start - fs->fs_contigsumsize;
487163849Spjd	if (end < 0)
488163849Spjd		end = -1;
489163849Spjd	mapp = &freemapp[start / NBBY];
490163849Spjd	map = *mapp--;
491163849Spjd	bit = 1 << (start % NBBY);
492163849Spjd	for (i = start; i > end; i--) {
493163849Spjd		if ((map & bit) == 0)
494163849Spjd			break;
495163849Spjd		if ((i & (NBBY - 1)) != 0) {
496163849Spjd			bit >>= 1;
497163849Spjd		} else {
498163849Spjd			map = *mapp--;
499163849Spjd			bit = 1 << (NBBY - 1);
500163849Spjd		}
501163849Spjd	}
502163849Spjd	back = start - i;
503163849Spjd	/*
504163849Spjd	 * Account for old cluster and the possibly new forward and
505163849Spjd	 * back clusters.
506163849Spjd	 */
507163849Spjd	i = back + forw + 1;
508163849Spjd	if (i > fs->fs_contigsumsize)
509163849Spjd		i = fs->fs_contigsumsize;
510163849Spjd	sump[i]++;
511163849Spjd	if (back > 0)
512163849Spjd		sump[back]--;
513163849Spjd	if (forw > 0)
514163849Spjd		sump[forw]--;
515163849Spjd	/*
516163849Spjd	 * Update cluster summary information.
517163849Spjd	 */
518163849Spjd	lp = &sump[fs->fs_contigsumsize];
519163849Spjd	for (i = fs->fs_contigsumsize; i > 0; i--)
520163849Spjd		if (*lp-- > 0)
521163849Spjd			break;
522163849Spjd	fs->fs_maxcluster[cgp->cg_cgx] = i;
523163849Spjd}
524163849Spjd
525163849Spjdstatic void
526163849Spjdblkfree(ufs2_daddr_t bno, long size)
527163849Spjd{
528163849Spjd	struct cgchain *cgc;
529163849Spjd	struct cg *cgp;
530163849Spjd	ufs1_daddr_t fragno, cgbno;
531163849Spjd	int i, cg, blk, frags, bbase;
532163849Spjd	u_int8_t *blksfree;
533163849Spjd
534163849Spjd	cg = dtog(fs, bno);
535163849Spjd	cgc = getcg(cg);
536163849Spjd	dirtycg(cgc);
537163849Spjd	cgp = &cgc->cgc_cg;
538163849Spjd	cgbno = dtogd(fs, bno);
539163849Spjd	blksfree = cg_blksfree(cgp);
540163849Spjd	if (size == fs->fs_bsize) {
541163849Spjd		fragno = fragstoblks(fs, cgbno);
542163849Spjd		if (!isfreeblock(blksfree, fragno))
543163849Spjd			assert(!"blkfree: freeing free block");
544163849Spjd		setblock(blksfree, fragno);
545163849Spjd		clusteracct(cgp, fragno);
546163849Spjd		cgp->cg_cs.cs_nbfree++;
547163849Spjd		fs->fs_cstotal.cs_nbfree++;
548163849Spjd		fs->fs_cs(fs, cg).cs_nbfree++;
549163849Spjd	} else {
550163849Spjd		bbase = cgbno - fragnum(fs, cgbno);
551163849Spjd		/*
552163849Spjd		 * decrement the counts associated with the old frags
553163849Spjd		 */
554163849Spjd		blk = blkmap(fs, blksfree, bbase);
555163849Spjd		fragacct(blk, cgp->cg_frsum, -1);
556163849Spjd		/*
557163849Spjd		 * deallocate the fragment
558163849Spjd		 */
559163849Spjd		frags = numfrags(fs, size);
560163849Spjd		for (i = 0; i < frags; i++) {
561163849Spjd			if (isset(blksfree, cgbno + i))
562163849Spjd				assert(!"blkfree: freeing free frag");
563163849Spjd			setbit(blksfree, cgbno + i);
564163849Spjd		}
565163849Spjd		cgp->cg_cs.cs_nffree += i;
566163849Spjd		fs->fs_cstotal.cs_nffree += i;
567163849Spjd		fs->fs_cs(fs, cg).cs_nffree += i;
568163849Spjd		/*
569163849Spjd		 * add back in counts associated with the new frags
570163849Spjd		 */
571163849Spjd		blk = blkmap(fs, blksfree, bbase);
572163849Spjd		fragacct(blk, cgp->cg_frsum, 1);
573163849Spjd		/*
574163849Spjd		 * if a complete block has been reassembled, account for it
575163849Spjd		 */
576163849Spjd		fragno = fragstoblks(fs, bbase);
577163849Spjd		if (isblock(blksfree, fragno)) {
578163849Spjd			cgp->cg_cs.cs_nffree -= fs->fs_frag;
579163849Spjd			fs->fs_cstotal.cs_nffree -= fs->fs_frag;
580163849Spjd			fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
581163849Spjd			clusteracct(cgp, fragno);
582163849Spjd			cgp->cg_cs.cs_nbfree++;
583163849Spjd			fs->fs_cstotal.cs_nbfree++;
584163849Spjd			fs->fs_cs(fs, cg).cs_nbfree++;
585163849Spjd		}
586163849Spjd	}
587163849Spjd}
588163849Spjd
589163849Spjd/*
590163849Spjd * Recursively free all indirect blocks.
591163849Spjd */
592163849Spjdstatic void
593163849Spjdfreeindir(ufs2_daddr_t blk, int level)
594163849Spjd{
595163849Spjd	char sblks[MAXBSIZE];
596163849Spjd	ufs2_daddr_t *blks;
597163849Spjd	int i;
598163849Spjd
599163849Spjd	if (bread(disk, fsbtodb(fs, blk), (void *)&sblks, (size_t)fs->fs_bsize) == -1)
600163849Spjd		err(1, "bread: %s", disk->d_error);
601163849Spjd	blks = (ufs2_daddr_t *)&sblks;
602163849Spjd	for (i = 0; i < howmany(fs->fs_bsize, sizeof(ufs2_daddr_t)); i++) {
603163849Spjd		if (blks[i] == 0)
604163849Spjd			break;
605163849Spjd		if (level == 0)
606163849Spjd			blkfree(blks[i], fs->fs_bsize);
607163849Spjd		else
608163849Spjd			freeindir(blks[i], level - 1);
609163849Spjd	}
610163849Spjd	blkfree(blk, fs->fs_bsize);
611163849Spjd}
612163849Spjd
613163849Spjd#define	dblksize(fs, dino, lbn) \
614163849Spjd	((dino)->di_size >= smalllblktosize(fs, (lbn) + 1) \
615163849Spjd	    ? (fs)->fs_bsize \
616163849Spjd	    : fragroundup(fs, blkoff(fs, (dino)->di_size)))
617163849Spjd
618163849Spjd/*
619163849Spjd * Free all blocks associated with the given inode.
620163849Spjd */
621163849Spjdstatic void
622163849Spjdclear_inode(struct ufs2_dinode *dino)
623163849Spjd{
624163849Spjd	ufs2_daddr_t bn;
625163849Spjd	int extblocks, i, level;
626163849Spjd	off_t osize;
627163849Spjd	long bsize;
628163849Spjd
629163849Spjd	extblocks = 0;
630163849Spjd	if (fs->fs_magic == FS_UFS2_MAGIC && dino->di_extsize > 0)
631163849Spjd		extblocks = btodb(fragroundup(fs, dino->di_extsize));
632163849Spjd	/* deallocate external attributes blocks */
633163849Spjd	if (extblocks > 0) {
634163849Spjd		osize = dino->di_extsize;
635163849Spjd		dino->di_blocks -= extblocks;
636163849Spjd		dino->di_extsize = 0;
637163849Spjd		for (i = 0; i < NXADDR; i++) {
638163849Spjd			if (dino->di_extb[i] == 0)
639163849Spjd				continue;
640163849Spjd			blkfree(dino->di_extb[i], sblksize(fs, osize, i));
641163849Spjd		}
642163849Spjd	}
643163849Spjd#define	SINGLE	0	/* index of single indirect block */
644163849Spjd#define	DOUBLE	1	/* index of double indirect block */
645163849Spjd#define	TRIPLE	2	/* index of triple indirect block */
646163849Spjd	/* deallocate indirect blocks */
647163849Spjd	for (level = SINGLE; level <= TRIPLE; level++) {
648163849Spjd		if (dino->di_ib[level] == 0)
649163849Spjd			break;
650163849Spjd		freeindir(dino->di_ib[level], level);
651163849Spjd	}
652163849Spjd	/* deallocate direct blocks and fragments */
653163849Spjd	for (i = 0; i < NDADDR; i++) {
654163849Spjd		bn = dino->di_db[i];
655163849Spjd		if (bn == 0)
656163849Spjd			continue;
657163849Spjd		bsize = dblksize(fs, dino, i);
658163849Spjd		blkfree(bn, bsize);
659163849Spjd	}
660163849Spjd}
661163849Spjd
662163849Spjdvoid
663163849Spjdgjournal_check(const char *filesys)
664163849Spjd{
665163849Spjd	struct ufs2_dinode *dino;
666163849Spjd	struct cgchain *cgc;
667163849Spjd	struct cg *cgp;
668163849Spjd	uint8_t *inosused, *blksfree;
669163849Spjd	ino_t cino, ino;
670163849Spjd	int cg, mode;
671163849Spjd
672163849Spjd	devnam = filesys;
673163849Spjd	getdisk();
674163849Spjd	/* Are there any unreferenced inodes in this cylinder group? */
675163849Spjd	if (fs->fs_unrefs == 0) {
676163849Spjd		//printf("No unreferenced inodes.\n");
677163849Spjd		closedisk();
678163849Spjd		return;
679163849Spjd	}
680163849Spjd
681163849Spjd	for (cg = 0; cg < fs->fs_ncg; cg++) {
682163849Spjd		/* Show progress if requested. */
683163849Spjd		if (got_siginfo) {
684163849Spjd			printf("%s: phase j: cyl group %d of %d (%d%%)\n",
685163849Spjd			    cdevname, cg, fs->fs_ncg, cg * 100 / fs->fs_ncg);
686163849Spjd			got_siginfo = 0;
687163849Spjd		}
688163849Spjd		if (got_sigalarm) {
689163849Spjd			setproctitle("%s pj %d%%", cdevname,
690163849Spjd			     cg * 100 / fs->fs_ncg);
691163849Spjd			got_sigalarm = 0;
692163849Spjd		}
693163849Spjd		cgc = getcg(cg);
694163849Spjd		cgp = &cgc->cgc_cg;
695163849Spjd		/* Are there any unreferenced inodes in this cylinder group? */
696163849Spjd		if (cgp->cg_unrefs == 0)
697163849Spjd			continue;
698163849Spjd		//printf("Analizing cylinder group %d (count=%d)\n", cg, cgp->cg_unrefs);
699163849Spjd		/*
700163849Spjd		 * We are going to modify this cylinder group, so we want it to
701163849Spjd		 * be written back.
702163849Spjd		 */
703163849Spjd		dirtycg(cgc);
704163849Spjd		/* We don't want it to be freed in the meantime. */
705163849Spjd		busycg(cgc);
706163849Spjd		inosused = cg_inosused(cgp);
707163849Spjd		blksfree = cg_blksfree(cgp);
708163849Spjd		/*
709163849Spjd		 * Now go through the list of all inodes in this cylinder group
710163849Spjd		 * to find unreferenced ones.
711163849Spjd		 */
712163849Spjd		for (cino = 0; cino < fs->fs_ipg; cino++) {
713163849Spjd			ino = fs->fs_ipg * cg + cino;
714163849Spjd			/* Unallocated? Skip it. */
715163849Spjd			if (isclr(inosused, cino))
716163849Spjd				continue;
717163849Spjd			if (getino(disk, (void **)&dino, ino, &mode) == -1)
718163849Spjd				err(1, "getino(cg=%d ino=%d)", cg, ino);
719163849Spjd			/* Not a regular file nor directory? Skip it. */
720163849Spjd			if (!S_ISREG(dino->di_mode) && !S_ISDIR(dino->di_mode))
721163849Spjd				continue;
722163849Spjd			/* Has reference(s)? Skip it. */
723163849Spjd			if (dino->di_nlink > 0)
724163849Spjd				continue;
725163849Spjd			//printf("Clearing inode=%d (size=%jd)\n", ino, (intmax_t)dino->di_size);
726163849Spjd			/* Free inode's blocks. */
727163849Spjd			clear_inode(dino);
728163849Spjd			/* Deallocate it. */
729163849Spjd			clrbit(inosused, cino);
730163849Spjd			/* Update position of last used inode. */
731163849Spjd			if (ino < cgp->cg_irotor)
732163849Spjd				cgp->cg_irotor = ino;
733163849Spjd			/* Update statistics. */
734163849Spjd			cgp->cg_cs.cs_nifree++;
735163849Spjd			fs->fs_cs(fs, cg).cs_nifree++;
736163849Spjd			fs->fs_cstotal.cs_nifree++;
737163849Spjd			cgp->cg_unrefs--;
738163849Spjd			fs->fs_unrefs--;
739163849Spjd			/* If this is directory, update related statistics. */
740163849Spjd			if (S_ISDIR(dino->di_mode)) {
741163849Spjd				cgp->cg_cs.cs_ndir--;
742163849Spjd				fs->fs_cs(fs, cg).cs_ndir--;
743163849Spjd				fs->fs_cstotal.cs_ndir--;
744163849Spjd			}
745163849Spjd			/* Zero-fill the inode. */
746163849Spjd			*dino = ufs2_zino;
747163849Spjd			/* Write the inode back. */
748163849Spjd			if (putino(disk, ino) == -1)
749163849Spjd				err(1, "putino(cg=%d ino=%d)", cg, ino);
750163849Spjd			if (cgp->cg_unrefs == 0) {
751163849Spjd				//printf("No more unreferenced inodes in cg=%d.\n", cg);
752163849Spjd				break;
753163849Spjd			}
754163849Spjd		}
755163849Spjd		/*
756163849Spjd		 * We don't need this cylinder group anymore, so feel free to
757163849Spjd		 * free it if needed.
758163849Spjd		 */
759163849Spjd		unbusycg(cgc);
760163849Spjd		/*
761163849Spjd		 * If there are no more unreferenced inodes, there is no need to
762163849Spjd		 * check other cylinder groups.
763163849Spjd		 */
764163849Spjd		if (fs->fs_unrefs == 0) {
765163849Spjd			//printf("No more unreferenced inodes (cg=%d/%d).\n", cg,
766163849Spjd			//    fs->fs_ncg);
767163849Spjd			break;
768163849Spjd		}
769163849Spjd	}
770163849Spjd	/* Write back modified cylinder groups. */
771163849Spjd	putcgs();
772163849Spjd	/* Write back updated statistics and super-block. */
773163849Spjd	putdisk();
774163849Spjd}
775