xref: /netbsd-src/sbin/fsck_v7fs/inode.c (revision 2fa7e14158d403140e8fb3c233c9e17417a69d87)
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