1*2fa7e141Sandvar /* $NetBSD: inode.c,v 1.2 2022/04/08 10:17:53 andvar Exp $ */
29255b46fSuch
39255b46fSuch /*-
49255b46fSuch * Copyright (c) 2011 The NetBSD Foundation, Inc.
59255b46fSuch * All rights reserved.
69255b46fSuch *
79255b46fSuch * This code is derived from software contributed to The NetBSD Foundation
89255b46fSuch * by UCHIYAMA Yasushi.
99255b46fSuch *
109255b46fSuch * Redistribution and use in source and binary forms, with or without
119255b46fSuch * modification, are permitted provided that the following conditions
129255b46fSuch * are met:
139255b46fSuch * 1. Redistributions of source code must retain the above copyright
149255b46fSuch * notice, this list of conditions and the following disclaimer.
159255b46fSuch * 2. Redistributions in binary form must reproduce the above copyright
169255b46fSuch * notice, this list of conditions and the following disclaimer in the
179255b46fSuch * documentation and/or other materials provided with the distribution.
189255b46fSuch *
199255b46fSuch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209255b46fSuch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219255b46fSuch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229255b46fSuch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239255b46fSuch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249255b46fSuch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259255b46fSuch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269255b46fSuch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279255b46fSuch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289255b46fSuch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299255b46fSuch * POSSIBILITY OF SUCH DAMAGE.
309255b46fSuch */
319255b46fSuch
329255b46fSuch #include <sys/cdefs.h>
339255b46fSuch #ifndef lint
34*2fa7e141Sandvar __RCSID("$NetBSD: inode.c,v 1.2 2022/04/08 10:17:53 andvar Exp $");
359255b46fSuch #endif /* not lint */
369255b46fSuch
379255b46fSuch #include <sys/types.h>
389255b46fSuch #include <stdio.h>
399255b46fSuch #include <string.h>
409255b46fSuch
419255b46fSuch #include "v7fs.h"
429255b46fSuch #include "v7fs_impl.h"
439255b46fSuch #include "v7fs_inode.h"
449255b46fSuch #include "v7fs_superblock.h"
459255b46fSuch #include "fsck_v7fs.h"
469255b46fSuch
479255b46fSuch struct ilistcheck_arg {
489255b46fSuch int total;
499255b46fSuch int alloc;
509255b46fSuch };
519255b46fSuch
529255b46fSuch int
freeinode_check(struct v7fs_self * fs)539255b46fSuch freeinode_check(struct v7fs_self *fs)
549255b46fSuch {
559255b46fSuch struct v7fs_superblock *sb = &fs->superblock;
569255b46fSuch v7fs_ino_t *f = sb->freeinode;
579255b46fSuch int16_t n = sb->nfreeinode;
589255b46fSuch int16_t i, j;
599255b46fSuch int bogus = false;
609255b46fSuch
619255b46fSuch /* Check # of cached free inode. */
629255b46fSuch if (n > V7FS_MAX_FREEINODE || n < 0) {
639255b46fSuch pwarn("*** corrupt nfreeinode %d (0-%d)***", n,
649255b46fSuch V7FS_MAX_FREEINODE);
659255b46fSuch
669255b46fSuch if (reply("PURGE?")) {
679255b46fSuch sb->nfreeinode = 0;
689255b46fSuch sb->modified = 1;
699255b46fSuch v7fs_superblock_writeback(fs);
709255b46fSuch return FSCK_EXIT_UNRESOLVED;
719255b46fSuch }
729255b46fSuch return FSCK_EXIT_CHECK_FAILED;
739255b46fSuch }
749255b46fSuch
759255b46fSuch /* Check dup. */
769255b46fSuch for (i = 0; i < n; i++)
779255b46fSuch for (j = 0; j < i; j++)
789255b46fSuch if (f[i] == f[j]) {
799255b46fSuch pwarn("*** freeinode DUP %d %d", i, j);
809255b46fSuch bogus = true;
819255b46fSuch }
829255b46fSuch if (bogus) {
839255b46fSuch if (reply("PURGE?")) {
849255b46fSuch memset(sb->freeinode, 0, sizeof(*sb->freeinode));
859255b46fSuch sb->nfreeinode = 0;
869255b46fSuch sb->modified = 1;
879255b46fSuch v7fs_superblock_writeback(fs);
889255b46fSuch return FSCK_EXIT_UNRESOLVED;
899255b46fSuch } else {
909255b46fSuch return FSCK_EXIT_CHECK_FAILED;
919255b46fSuch }
929255b46fSuch }
939255b46fSuch
949255b46fSuch return FSCK_EXIT_OK;
959255b46fSuch }
969255b46fSuch
97*2fa7e141Sandvar /* Counting freeinode and find partially allocated inode. */
989255b46fSuch static int
v7fs_inode_check(struct v7fs_self * fs,struct v7fs_inode * p,v7fs_ino_t ino)999255b46fSuch v7fs_inode_check(struct v7fs_self *fs, struct v7fs_inode *p, v7fs_ino_t ino)
1009255b46fSuch {
1019255b46fSuch int error = 0;
1029255b46fSuch
1039255b46fSuch if (v7fs_inode_allocated(p) && !p->nlink) {
104*2fa7e141Sandvar pwarn("*** partially allocated inode #%d", ino);
1059255b46fSuch v7fs_inode_dump(p);
1069255b46fSuch if (reply_trivial("REMOVE?")) {
1079255b46fSuch memset(p, 0, sizeof(*p));
1089255b46fSuch v7fs_inode_deallocate(fs, ino);
1099255b46fSuch } else {
1109255b46fSuch error = FSCK_EXIT_CHECK_FAILED;
1119255b46fSuch }
1129255b46fSuch }
1139255b46fSuch
1149255b46fSuch return error;
1159255b46fSuch }
1169255b46fSuch
1179255b46fSuch static int
ilistcheck_subr(struct v7fs_self * fs,void * ctx,struct v7fs_inode * p,v7fs_ino_t ino)1189255b46fSuch ilistcheck_subr(struct v7fs_self *fs, void *ctx, struct v7fs_inode *p,
1199255b46fSuch v7fs_ino_t ino)
1209255b46fSuch {
1219255b46fSuch struct ilistcheck_arg *arg = (struct ilistcheck_arg *)ctx;
1229255b46fSuch int error = 0;
1239255b46fSuch
1249255b46fSuch if (ino != 1)
1259255b46fSuch error = v7fs_inode_check(fs, p, ino);
1269255b46fSuch
1279255b46fSuch arg->total++;
1289255b46fSuch if (v7fs_inode_allocated(p))
1299255b46fSuch arg->alloc++;
1309255b46fSuch
1319255b46fSuch return error;
1329255b46fSuch }
1339255b46fSuch
1349255b46fSuch int
ilist_check(struct v7fs_self * fs)1359255b46fSuch ilist_check(struct v7fs_self *fs)
1369255b46fSuch {
1379255b46fSuch struct v7fs_superblock *sb = &fs->superblock;
1389255b46fSuch struct ilistcheck_arg arg = { .total = 0, .alloc = 0 };
1399255b46fSuch int error = 0;
1409255b46fSuch
1419255b46fSuch if ((error = v7fs_ilist_foreach(fs, ilistcheck_subr, &arg)))
1429255b46fSuch return error;
1439255b46fSuch int nfree = arg.total - arg.alloc;
1449255b46fSuch
1459255b46fSuch if (nfree != sb->total_freeinode) {
1469255b46fSuch pwarn("*** corrupt total freeinode. %d(sb) != %d(cnt)\n",
1479255b46fSuch sb->total_freeinode, nfree);
1489255b46fSuch if (reply_trivial("CORRECT?")) {
1499255b46fSuch sb->total_freeinode = nfree;
1509255b46fSuch sb->modified = true;
1519255b46fSuch v7fs_superblock_writeback(fs);
1529255b46fSuch v7fs_superblock_dump(fs);
1539255b46fSuch } else {
1549255b46fSuch error = FSCK_EXIT_CHECK_FAILED;
1559255b46fSuch }
1569255b46fSuch }
1579255b46fSuch
1589255b46fSuch pwarn("\ninode usage: %d/%d (%d)\n", arg.alloc, arg.total, nfree);
1599255b46fSuch return error;
1609255b46fSuch }
161