[Ocfs2-tools-commits] zab commits r246 - in trunk/fsck.ocfs2: . include

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Sep 21 16:51:08 CDT 2004


Author: zab
Date: 2004-09-21 16:51:06 -0500 (Tue, 21 Sep 2004)
New Revision: 246

Added:
   trunk/fsck.ocfs2/fsck.c
   trunk/fsck.ocfs2/include/
   trunk/fsck.ocfs2/include/fsck.h
   trunk/fsck.ocfs2/include/pass1.h
   trunk/fsck.ocfs2/pass1.c
Modified:
   trunk/fsck.ocfs2/Makefile
Log:

o Add a skeletal fsck so smarter people can point me in the right direction.



Modified: trunk/fsck.ocfs2/Makefile
===================================================================
--- trunk/fsck.ocfs2/Makefile	2004-09-21 21:05:09 UTC (rev 245)
+++ trunk/fsck.ocfs2/Makefile	2004-09-21 21:51:06 UTC (rev 246)
@@ -2,21 +2,17 @@
 
 include $(TOPDIR)/Preamble.make
 
-WARNINGS = -Wall -Wstrict-prototypes -Wno-format -Wmissing-prototypes \
-           -Wmissing-declarations
+SBIN_PROGRAMS = fsck.ocfs2
 
-ifdef OCFS_DEBUG
-OPTS = -g
-endif
 
-CFLAGS = $(OPTS) -fno-strict-aliasing $(WARNINGS) 
+INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include
+LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
 
-SBIN_PROGRAMS = fsck.ocfs2
+CFLAGS := -g -Wall -Wstrict-prototypes -Wno-format -Wmissing-prototypes \
+           -Wmissing-declarations -fno-strict-aliasing
 
-INCLUDES = -I$(TOPDIR)/libocfs2/include
+DEFINES = -DOCFS2_FLAT_INCLUDES
 
-OPTIMIZE = -O2
-
 ifeq ($(OCFS_PROCESSOR),x86_64)
   CFLAGS += -m64
 endif
@@ -26,17 +22,23 @@
   DEFINES += -D__ILP32__
 endif
 
-CFLAGS += $(OPTIMIZE)
+CFILES = fsck.c pass1.c
+HFILES = include/pass1.h
 
-VERSION_FILES = fsck.c 
-VERSION_SRC = fsck.c
+OBJS = $(subst .c,.o,$(CFILES))
+
+VERSION_FILES = $(CFILES) $(HFILES)
+VERSION_SRC = $(CFILES)
 VERSION_PREFIX = OCFS2
 
-#MANS = fsck.ocfs2.8
+DIST_FILES = $(CFILES) $(HFILES) 
 
-DIST_FILES = $(VERSION_FILES) $(VERSION_SRC) #mkfs.ocfs2.8.in
+DIST_RULES = dist-subdircreate
 
-fsck.ocfs2: fsck.o
-	$(LINK) 
+dist-subdircreate:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/include
 
+fsck.ocfs2: $(OBJS)
+	$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+
 include $(TOPDIR)/Postamble.make

Added: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c	2004-09-21 21:05:09 UTC (rev 245)
+++ trunk/fsck.ocfs2/fsck.c	2004-09-21 21:51:06 UTC (rev 246)
@@ -0,0 +1,209 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * fsck.c
+ *
+ * file system checker for OCFS2
+ *
+ * Copyright (C) 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Zach Brown
+ */
+#include <getopt.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "ocfs2.h"
+
+#include "fsck.h"
+#include "pass1.h"
+
+static void print_usage(void)
+{
+	fprintf(stderr,
+		"Usage: fsck.ocfs2 [-s <superblock>] [-B <blksize>]\n"
+	       	"               <filename>\n");
+}
+
+static uint64_t read_number(const char *num)
+{
+	uint64_t val;
+	char *ptr;
+
+	val = strtoull(num, &ptr, 0);
+	if (!ptr || *ptr)
+		return 0;
+
+	return val;
+}
+
+extern int opterr, optind;
+extern char *optarg;
+
+static errcode_t o2fsck_state_init(ocfs2_filesys *fs, char *whoami, 
+				    o2fsck_state *ost)
+{
+	errcode_t ret;
+
+	memset(ost, 0, sizeof(*ost));
+
+	ret = ocfs2_block_bitmap_new(fs, "inodes in use", 
+				     &ost->ost_used_inodes);
+	if (ret) {
+		com_err(whoami, ret, "while allocating used inodes bitmap");
+		return ret;
+	}
+
+	ret = ocfs2_block_bitmap_new(fs, "inodes with bad fields", 
+				     &ost->ost_bad_inodes);
+	if (ret) {
+		com_err(whoami, ret, "while allocating bad inodes bitmap");
+		return ret;
+	}
+
+	ret = ocfs2_block_bitmap_new(fs, "directory inodes", 
+				     &ost->ost_dir_inodes);
+	if (ret) {
+		com_err(whoami, ret, "while allocating dir inodes bitmap");
+		return ret;
+	}
+
+	ret = ocfs2_block_bitmap_new(fs, "regular file inodes", 
+				     &ost->ost_reg_inodes);
+	if (ret) {
+		com_err(whoami, ret, "while allocating reg inodes bitmap");
+		return ret;
+	}
+
+	ret = ocfs2_block_bitmap_new(fs, "blocks off inodes",
+				     &ost->ost_found_blocks);
+	if (ret) {
+		com_err(whoami, ret, "while allocating found blocks bitmap");
+		return ret;
+	}
+
+	ret = ocfs2_block_bitmap_new(fs, "duplicate blocks",
+				     &ost->ost_dup_blocks);
+	if (ret) {
+		com_err(whoami, ret, "while allocating duplicate block bitmap");
+		return ret;
+	}
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	char *filename;
+	ocfs2_filesys *fs;
+	int64_t blkno, blksize;
+	o2fsck_state ost;
+	int c, ret;
+
+
+	/* These mean "autodetect" */
+	blksize = 0;
+	blkno = 0;
+
+	initialize_ocfs_error_table();
+
+	while((c = getopt(argc, argv, "s:B:")) != EOF) {
+		switch (c) {
+			case 's':
+				blkno = read_number(optarg);
+				if (blkno < OCFS2_SUPER_BLOCK_BLKNO) {
+					fprintf(stderr,
+						"Invalid blkno: %s\n",
+						optarg);
+					print_usage();
+					return 1;
+				}
+				break;
+
+			case 'B':
+				blksize = read_number(optarg);
+				if (blksize < OCFS2_MIN_BLOCKSIZE) {
+					fprintf(stderr, 
+						"Invalid blksize: %s\n",
+						optarg);
+					print_usage();
+					return 1;
+				}
+				break;
+
+			default:
+				print_usage();
+				return 1;
+				break;
+		}
+	}
+
+	if (blksize % OCFS2_MIN_BLOCKSIZE) {
+		fprintf(stderr, "Invalid blocksize: %lld\n", blksize);
+		print_usage();
+		return 1;
+	}
+
+	if (optind >= argc) {
+		fprintf(stderr, "Missing filename\n");
+		print_usage();
+		return 1;
+	}
+
+	filename = argv[optind];
+
+	/* XXX we'll decide on a policy for using o_direct in the future.
+	 * for now we want to test against loopback files in ext3, say. */
+	ret = ocfs2_open(filename, OCFS2_FLAG_RO | OCFS2_FLAG_BUFFERED, blkno,
+			 blksize, &fs);
+	if (ret) {
+		com_err(argv[0], ret,
+			"while opening file \"%s\"", filename);
+		goto out;
+	}
+
+	if (o2fsck_state_init(fs, argv[0], &ost)) {
+		fprintf(stderr, "error allocating run-time state, exiting..\n");
+		return 1;
+	}
+
+	fprintf(stdout, "OCFS2 filesystem on \"%s\":\n", filename);
+	fprintf(stdout,
+		"\tblocksize = %d\n"
+ 		"\tclustersize = %d\n"
+		"\tclusters = %u\n"
+		"\tblocks = %llu\n",
+ 		fs->fs_blocksize,
+		fs->fs_clustersize,
+		fs->fs_clusters,
+		fs->fs_blocks);
+
+	ret = o2fsck_pass1(fs, &ost);
+	if (ret)
+		com_err(argv[0], ret, "pass1 failed");
+
+	ret = ocfs2_close(fs);
+	if (ret) {
+		com_err(argv[0], ret,
+			"while closing file \"%s\"", filename);
+	}
+
+out:
+	return 0;
+}

Added: trunk/fsck.ocfs2/include/fsck.h
===================================================================
--- trunk/fsck.ocfs2/include/fsck.h	2004-09-21 21:05:09 UTC (rev 245)
+++ trunk/fsck.ocfs2/include/fsck.h	2004-09-21 21:51:06 UTC (rev 246)
@@ -0,0 +1,38 @@
+/*
+ * fsck.h
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Author: Zach Brown
+ */
+
+#ifndef __O2FSCK_FSCK_H__
+#define __O2FSCK_FSCK_H__
+
+typedef struct _o2fsck_state {
+	ocfs2_bitmap	*ost_used_inodes;
+	ocfs2_bitmap	*ost_bad_inodes;
+	ocfs2_bitmap	*ost_dir_inodes;
+	ocfs2_bitmap	*ost_reg_inodes;
+
+	ocfs2_bitmap	*ost_found_blocks;
+	ocfs2_bitmap	*ost_dup_blocks;
+} o2fsck_state;
+
+#endif /* __O2FSCK_FSCK_H__ */
+

Added: trunk/fsck.ocfs2/include/pass1.h
===================================================================
--- trunk/fsck.ocfs2/include/pass1.h	2004-09-21 21:05:09 UTC (rev 245)
+++ trunk/fsck.ocfs2/include/pass1.h	2004-09-21 21:51:06 UTC (rev 246)
@@ -0,0 +1,30 @@
+/*
+ * pass1.h
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Author: Zach Brown
+ */
+
+#ifndef __O2FSCK_PASS1_H__
+#define __O2FSCK_PASS1_H__
+
+errcode_t o2fsck_pass1(ocfs2_filesys *fs, o2fsck_state *ost);
+
+#endif /* __O2FSCK_PASS1_H__ */
+

Added: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c	2004-09-21 21:05:09 UTC (rev 245)
+++ trunk/fsck.ocfs2/pass1.c	2004-09-21 21:51:06 UTC (rev 246)
@@ -0,0 +1,209 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * pass1.c
+ *
+ * file system checker for OCFS2
+ *
+ * Copyright (C) 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Zach Brown
+ */
+#include <string.h>
+
+#include "ocfs2.h"
+
+#include "fsck.h"
+#include "pass1.h"
+
+const char *whoami = "pass1";
+
+/*
+ * for now we're just building up info, we're not actually
+ * writing to disk.
+ *
+ * for each inode:
+ * - verify that i_mode is legal
+ *
+ * We collect the following for future passes:
+ *
+ * - a bitmap of inodes which are in use
+ * - a bitmap of inodes which have bad fields
+ * - a bitmap of data blocks on inodes
+ * - a bitmap of data blocks duplicated between inodes
+ */
+
+static void o2fsck_verify_inode_fields(o2fsck_state *ost, uint64_t blkno, 
+					ocfs2_dinode *di)
+{
+	int was_set;
+
+	fprintf(stdout, "inode %llu with size %llu\n",
+		blkno, di->i_size);
+
+	/* do we want to detect and delete corrupt system dir/files here
+	 * so we can recreate them later ? */
+
+	/* also make sure the journal inode is ok? */
+
+	/* clamp inodes to > OCFS2_SUPER_BLOCK_BLKNO && < fs->fs_blocks? */
+
+	/* what's our deletion story?  i_links_count, dtime, etc.. */
+
+	/* XXX it seems these are expected sometimes? */
+	if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
+		   strlen(OCFS2_INODE_SIGNATURE))) {
+		printf("inode %llu has invalid signature\n", blkno);
+		goto bad;
+	}
+	if (!(di->i_flags & OCFS2_VALID_FL)) {
+		printf("inode %llu missing valid flag\n", blkno);
+		goto bad;
+	}
+
+	ocfs2_bitmap_set(ost->ost_used_inodes, blkno, &was_set);
+	if (was_set) {
+		fprintf(stderr, "duplicate inode %llu?\n", blkno);
+		goto bad;
+	}
+
+	if (S_ISDIR(di->i_mode)) {
+		/* XXX record dir for dir block walk */
+		ocfs2_bitmap_set(ost->ost_dir_inodes, blkno, NULL);
+	} else if (S_ISREG(di->i_mode)) {
+		ocfs2_bitmap_set(ost->ost_reg_inodes, blkno, NULL);
+	} else if (S_ISLNK(di->i_mode)) {
+		/* make sure fast symlinks are ok, etc */
+	} else {
+		if (!S_ISCHR(di->i_mode) && !S_ISBLK(di->i_mode) &&
+			!S_ISFIFO(di->i_mode) && !S_ISSOCK(di->i_mode))
+			goto bad;
+
+		/* i_size?  what other sanity testing for devices? */
+	}
+
+	return;
+bad:
+	ocfs2_bitmap_set(ost->ost_bad_inodes, blkno, NULL);
+}
+
+struct verifying_blocks {
+       unsigned		vb_mark_dir_blocks;	
+       uint64_t		vb_blocks;	
+       o2fsck_state 	*vb_ost;
+       ocfs2_dinode	*vb_di;
+};
+
+static int verify_block(ocfs2_filesys *fs,
+			    uint64_t blkno,
+			    uint64_t bcount,
+			    void *priv_data)
+{
+	struct verifying_blocks *vb = priv_data;
+	ocfs2_dinode *di = vb->vb_di;
+	int was_set;
+
+	ocfs2_bitmap_set(vb->vb_ost->ost_found_blocks, blkno, &was_set);
+	if (was_set) {
+		fprintf(stderr, "duplicate block %llu?\n", blkno);
+		ocfs2_bitmap_set(vb->vb_ost->ost_dup_blocks, blkno, NULL);
+	}
+
+	if (S_ISDIR(di->i_mode)) {
+		/* do we want libocfs2 to record directory blocks or should
+		 * we? */
+	}
+
+	vb->vb_blocks++;
+	return 0;
+}
+
+static errcode_t o2fsck_verify_inode_data(ocfs2_filesys *fs, o2fsck_state *ost,
+					  uint64_t blkno, ocfs2_dinode *di)
+{
+	struct verifying_blocks vb = {0, };
+	errcode_t ret;
+
+	vb.vb_ost = ost;
+	vb.vb_di = di;
+
+	ret = ocfs2_block_iterate(fs, blkno, 0, verify_block, &vb);
+	if (ret) {
+		com_err(whoami, ret, "walking data blocks");
+		goto out;
+	}
+
+#if 0 /* hmm. */
+	if (vb.vb_blocks != di->i_blocks) {
+		fprintf(stderr, "inode %llu claimed %llu blocks, found"
+				" %llu blocks.\n", di->i_ino, di->i_blocks,
+				vb.vb_blocks);
+	}
+#endif
+
+out:
+	return ret;
+}
+
+errcode_t o2fsck_pass1(ocfs2_filesys *fs, o2fsck_state *ost)
+{
+	errcode_t ret;
+	uint64_t blkno;
+	char *buf;
+	ocfs2_dinode *di;
+	ocfs2_inode_scan *scan;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret) {
+		com_err(whoami, ret,
+			"while allocating inode buffer");
+		goto out;
+	}
+
+	di = (ocfs2_dinode *)buf;
+
+	ret = ocfs2_open_inode_scan(fs, &scan);
+	if (ret) {
+		com_err(whoami, ret,
+			"while opening inode scan");
+		goto out_free;
+	}
+
+	for(;;) {
+		ret = ocfs2_get_next_inode(scan, &blkno, buf);
+		if (ret) {
+			com_err(whoami, ret,
+				"while getting next inode");
+			goto out_close_scan;
+		}
+		if (blkno == 0)
+			break;
+
+		o2fsck_verify_inode_fields(ost, blkno, di);
+		/* XXX be able to mark the blocks in the inode as 
+		 * bad if the inode was bad */
+		o2fsck_verify_inode_data(fs, ost, blkno, di);
+	}
+
+out_close_scan:
+	ocfs2_close_inode_scan(scan);
+out_free:
+	ocfs2_free(&buf);
+
+out:
+	return 0;
+}



More information about the Ocfs2-tools-commits mailing list