2 * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause-FreeBSD
4 * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Copyright (c) 1982, 1986, 1989, 1993
29 * The Regents of the University of California. All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD$");
59 #include <sys/param.h>
60 #include <sys/disklabel.h>
61 #include <sys/mount.h>
64 #include <ufs/ufs/ufsmount.h>
65 #include <ufs/ufs/dinode.h>
66 #include <ufs/ffs/fs.h>
81 char cgcu_buf[MAXBSIZE];
85 LIST_ENTRY(cgchain) cgc_next;
87 #define cgc_cg cgc_union.cgcu_cg
89 #define MAX_CACHED_CGS 1024
90 static unsigned ncgs = 0;
91 static LIST_HEAD(, cgchain) cglist = LIST_HEAD_INITIALIZER(cglist);
93 static const char *devnam;
94 static struct uufsd *diskp = NULL;
95 static struct fs *fs = NULL;
96 struct ufs2_dinode ufs2_zino;
98 static void putcgs(void);
101 * Return cylinder group from the cache or load it if it is not in the
103 * Don't cache more than MAX_CACHED_CGS cylinder groups.
105 static struct cgchain *
110 assert(diskp != NULL && fs != NULL);
111 LIST_FOREACH(cgc, &cglist, cgc_next) {
112 if (cgc->cgc_cg.cg_cgx == cg) {
113 //printf("%s: Found cg=%d\n", __func__, cg);
118 * Our cache is full? Let's clean it up.
120 if (ncgs >= MAX_CACHED_CGS) {
121 //printf("%s: Flushing CGs.\n", __func__);
124 cgc = malloc(sizeof(*cgc));
127 * Cannot allocate memory?
128 * Let's put all currently loaded and not busy cylinder groups
129 * on disk and try again.
131 //printf("%s: No memory, flushing CGs.\n", __func__);
133 cgc = malloc(sizeof(*cgc));
135 err(1, "malloc(%zu)", sizeof(*cgc));
137 if (cgget(diskp, cg, &cgc->cgc_cg) == -1)
138 err(1, "cgget(%d)", cg);
141 LIST_INSERT_HEAD(&cglist, cgc, cgc_next);
143 //printf("%s: Read cg=%d\n", __func__, cg);
148 * Mark cylinder group as dirty - it will be written back on putcgs().
151 dirtycg(struct cgchain *cgc)
158 * Mark cylinder group as busy - it will not be freed on putcgs().
161 busycg(struct cgchain *cgc)
168 * Unmark the given cylinder group as busy.
171 unbusycg(struct cgchain *cgc)
178 * Write back all dirty cylinder groups.
179 * Free all non-busy cylinder groups.
184 struct cgchain *cgc, *cgc2;
186 assert(diskp != NULL && fs != NULL);
187 LIST_FOREACH_SAFE(cgc, &cglist, cgc_next, cgc2) {
190 LIST_REMOVE(cgc, cgc_next);
192 if (cgc->cgc_dirty) {
193 if (cgput(diskp, &cgc->cgc_cg) == -1)
194 err(1, "cgput(%d)", cgc->cgc_cg.cg_cgx);
195 //printf("%s: Wrote cg=%d\n", __func__,
196 // cgc->cgc_cg.cg_cgx);
204 * Free all non-busy cylinder groups without storing the dirty ones.
211 assert(diskp != NULL && fs != NULL);
212 while ((cgc = LIST_FIRST(&cglist)) != NULL) {
215 LIST_REMOVE(cgc, cgc_next);
216 //printf("%s: Canceled cg=%d\n", __func__, cgc->cgc_cg.cg_cgx);
223 * Open the given provider, load superblock.
231 if (ufs_disk_fillout(diskp, devnam) == -1) {
232 err(1, "ufs_disk_fillout(%s) failed: %s", devnam,
239 * Mark file system as clean, write the super-block back, close the disk.
246 if (sbwrite(diskp, 0) == -1)
247 err(1, "sbwrite(%s)", devnam);
248 if (ufs_disk_close(diskp) == -1)
249 err(1, "ufs_disk_close(%s)", devnam);
256 blkfree(ufs2_daddr_t bno, long size)
260 ufs1_daddr_t fragno, cgbno;
261 int i, cg, blk, frags, bbase;
268 cgbno = dtogd(fs, bno);
269 blksfree = cg_blksfree(cgp);
270 if (size == fs->fs_bsize) {
271 fragno = fragstoblks(fs, cgbno);
272 if (!ffs_isfreeblock(fs, blksfree, fragno))
273 assert(!"blkfree: freeing free block");
274 ffs_setblock(fs, blksfree, fragno);
275 ffs_clusteracct(fs, cgp, fragno, 1);
276 cgp->cg_cs.cs_nbfree++;
277 fs->fs_cstotal.cs_nbfree++;
278 fs->fs_cs(fs, cg).cs_nbfree++;
280 bbase = cgbno - fragnum(fs, cgbno);
282 * decrement the counts associated with the old frags
284 blk = blkmap(fs, blksfree, bbase);
285 ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
287 * deallocate the fragment
289 frags = numfrags(fs, size);
290 for (i = 0; i < frags; i++) {
291 if (isset(blksfree, cgbno + i))
292 assert(!"blkfree: freeing free frag");
293 setbit(blksfree, cgbno + i);
295 cgp->cg_cs.cs_nffree += i;
296 fs->fs_cstotal.cs_nffree += i;
297 fs->fs_cs(fs, cg).cs_nffree += i;
299 * add back in counts associated with the new frags
301 blk = blkmap(fs, blksfree, bbase);
302 ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
304 * if a complete block has been reassembled, account for it
306 fragno = fragstoblks(fs, bbase);
307 if (ffs_isblock(fs, blksfree, fragno)) {
308 cgp->cg_cs.cs_nffree -= fs->fs_frag;
309 fs->fs_cstotal.cs_nffree -= fs->fs_frag;
310 fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
311 ffs_clusteracct(fs, cgp, fragno, 1);
312 cgp->cg_cs.cs_nbfree++;
313 fs->fs_cstotal.cs_nbfree++;
314 fs->fs_cs(fs, cg).cs_nbfree++;
320 * Recursively free all indirect blocks.
323 freeindir(ufs2_daddr_t blk, int level)
325 char sblks[MAXBSIZE];
329 if (bread(diskp, fsbtodb(fs, blk), (void *)&sblks, (size_t)fs->fs_bsize) == -1)
330 err(1, "bread: %s", diskp->d_error);
331 blks = (ufs2_daddr_t *)&sblks;
332 for (i = 0; i < NINDIR(fs); i++) {
336 blkfree(blks[i], fs->fs_bsize);
338 freeindir(blks[i], level - 1);
340 blkfree(blk, fs->fs_bsize);
343 #define dblksize(fs, dino, lbn) \
344 ((dino)->di_size >= smalllblktosize(fs, (lbn) + 1) \
346 : fragroundup(fs, blkoff(fs, (dino)->di_size)))
349 * Free all blocks associated with the given inode.
352 clear_inode(struct ufs2_dinode *dino)
355 int extblocks, i, level;
360 if (fs->fs_magic == FS_UFS2_MAGIC && dino->di_extsize > 0)
361 extblocks = btodb(fragroundup(fs, dino->di_extsize));
362 /* deallocate external attributes blocks */
364 osize = dino->di_extsize;
365 dino->di_blocks -= extblocks;
366 dino->di_extsize = 0;
367 for (i = 0; i < UFS_NXADDR; i++) {
368 if (dino->di_extb[i] == 0)
370 blkfree(dino->di_extb[i], sblksize(fs, osize, i));
373 #define SINGLE 0 /* index of single indirect block */
374 #define DOUBLE 1 /* index of double indirect block */
375 #define TRIPLE 2 /* index of triple indirect block */
376 /* deallocate indirect blocks */
377 for (level = SINGLE; level <= TRIPLE; level++) {
378 if (dino->di_ib[level] == 0)
380 freeindir(dino->di_ib[level], level);
382 /* deallocate direct blocks and fragments */
383 for (i = 0; i < UFS_NDADDR; i++) {
387 bsize = dblksize(fs, dino, i);
393 gjournal_check(const char *filesys)
404 /* Are there any unreferenced inodes in this file system? */
405 if (fs->fs_unrefs == 0) {
406 //printf("No unreferenced inodes.\n");
411 for (cg = 0; cg < fs->fs_ncg; cg++) {
412 /* Show progress if requested. */
414 printf("%s: phase j: cyl group %d of %d (%d%%)\n",
415 cdevname, cg, fs->fs_ncg, cg * 100 / fs->fs_ncg);
419 setproctitle("%s pj %d%%", cdevname,
420 cg * 100 / fs->fs_ncg);
425 /* Are there any unreferenced inodes in this cylinder group? */
426 if (cgp->cg_unrefs == 0)
428 //printf("Analizing cylinder group %d (count=%d)\n", cg, cgp->cg_unrefs);
430 * We are going to modify this cylinder group, so we want it to
434 /* We don't want it to be freed in the meantime. */
436 inosused = cg_inosused(cgp);
438 * Now go through the list of all inodes in this cylinder group
439 * to find unreferenced ones.
441 for (cino = 0; cino < fs->fs_ipg; cino++) {
442 ino = fs->fs_ipg * cg + cino;
443 /* Unallocated? Skip it. */
444 if (isclr(inosused, cino))
446 if (getinode(diskp, &dp, ino) == -1)
447 err(1, "getinode (cg=%d ino=%ju) %s",
448 cg, (uintmax_t)ino, diskp->d_error);
449 /* Not a regular file nor directory? Skip it. */
450 if (!S_ISREG(dp.dp2->di_mode) &&
451 !S_ISDIR(dp.dp2->di_mode))
453 /* Has reference(s)? Skip it. */
454 if (dp.dp2->di_nlink > 0)
456 /* printf("Clearing inode=%d (size=%jd)\n", ino,
457 (intmax_t)dp.dp2->di_size); */
458 /* Free inode's blocks. */
461 clrbit(inosused, cino);
462 /* Update position of last used inode. */
463 if (ino < cgp->cg_irotor)
464 cgp->cg_irotor = ino;
465 /* Update statistics. */
466 cgp->cg_cs.cs_nifree++;
467 fs->fs_cs(fs, cg).cs_nifree++;
468 fs->fs_cstotal.cs_nifree++;
471 /* If this is directory, update related statistics. */
472 if (S_ISDIR(dp.dp2->di_mode)) {
473 cgp->cg_cs.cs_ndir--;
474 fs->fs_cs(fs, cg).cs_ndir--;
475 fs->fs_cstotal.cs_ndir--;
477 /* Zero-fill the inode. */
479 /* Write the inode back. */
480 if (putinode(diskp) == -1)
481 err(1, "putinode (cg=%d ino=%ju) %s",
482 cg, (uintmax_t)ino, diskp->d_error);
483 if (cgp->cg_unrefs == 0) {
484 //printf("No more unreferenced inodes in cg=%d.\n", cg);
489 * We don't need this cylinder group anymore, so feel free to
494 * If there are no more unreferenced inodes, there is no need to
495 * check other cylinder groups.
497 if (fs->fs_unrefs == 0) {
498 //printf("No more unreferenced inodes (cg=%d/%d).\n", cg,
503 /* Write back modified cylinder groups. */
505 /* Write back updated statistics and super-block. */