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

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Sat Dec 4 14:38:46 CST 2004


Author: zab
Date: 2004-12-04 14:38:44 -0600 (Sat, 04 Dec 2004)
New Revision: 462

Modified:
   trunk/fsck.ocfs2/fsck.c
   trunk/fsck.ocfs2/fsck.ocfs2.8.in
   trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in
   trunk/fsck.ocfs2/include/fsck.h
   trunk/fsck.ocfs2/include/journal.h
   trunk/fsck.ocfs2/include/problem.h
   trunk/fsck.ocfs2/include/util.h
   trunk/fsck.ocfs2/journal.c
   trunk/fsck.ocfs2/pass0.c
   trunk/fsck.ocfs2/pass1.c
   trunk/fsck.ocfs2/problem.c
   trunk/fsck.ocfs2/util.c
   trunk/libocfs2/include/ocfs2_fs.h
Log:
o always replay journals when their publish region is mounted
o only do a full check when mnt count or time are exceeded or -f
o add some messages to let the user know what is going on
o don't give replay access to o2fsck_state, it doesn't use it
o clean up the setting and clearing of bits in the global bitmap
o update the lastcheck field in the superblock and write it out


Modified: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/fsck.c	2004-12-04 20:38:44 UTC (rev 462)
@@ -140,11 +140,12 @@
 	return 0;
 }
 
-static errcode_t check_superblock(char *whoami, o2fsck_state *ost)
+static errcode_t check_superblock(o2fsck_state *ost)
 {
 	ocfs2_dinode *di = ost->ost_fs->fs_super;
 	ocfs2_super_block *sb = OCFS2_RAW_SB(di);
 	errcode_t ret = 0;
+	char *whoami = __FUNCTION__;
 
 	if (sb->s_max_nodes == 0) {
 		printf("The superblock max_nodes field is set to 0.\n");
@@ -166,14 +167,102 @@
 	return ret;
 }
 
-static void exit_if_skipping(o2fsck_state *ost)
+static errcode_t write_out_superblock(o2fsck_state *ost)
 {
+	ocfs2_dinode *di = ost->ost_fs->fs_super;
+	ocfs2_super_block *sb = OCFS2_RAW_SB(di);
+
+	sb->s_errors = ost->ost_saw_error;
+	sb->s_lastcheck = time(NULL);
+	sb->s_mnt_count = 0;
+
+	return ocfs2_write_super(ost->ost_fs);
+}
+
+static void scale_time(time_t secs, unsigned *scaled, char **units)
+{
+	if (secs < 60) {
+		*units = "seconds";
+		goto done;
+	}
+	secs /= 60;
+
+	if (secs < 60) {
+		*units = "minutes";
+		goto done;
+	}
+	secs /= 60;
+
+	if (secs < 24) {
+		*units = "hours";
+		goto done;
+	}
+	secs /= 24;
+	*units = "days";
+
+done:
+	*scaled = secs;
+}
+
+/* avoid "warning: `%c' yields only last 2 digits of year in some locales" */
+static size_t ftso_strftime(char *s, size_t max, const char *fmt,
+			    const struct tm *tm) {
+	return strftime(s, max, fmt, tm);
+}
+
+static int fs_is_clean(o2fsck_state *ost, char *filename)
+{
+	ocfs2_super_block *sb = OCFS2_RAW_SB(ost->ost_fs->fs_super);
+	time_t now = time(NULL);
+	time_t next = sb->s_lastcheck + sb->s_checkinterval;
+	static char reason[4096] = {'\0', };
+	struct tm local;
+
 	if (ost->ost_force)
-		return;
+		strcpy(reason, "was run with -f");
+	else if (sb->s_state & OCFS2_ERROR_FS)
+		strcpy(reason, "contains a file system with errors");
+	else if (sb->s_max_mnt_count > 0 &&
+		 sb->s_mnt_count > sb->s_max_mnt_count) {
+		sprintf(reason, "has been mounted %u times without being "
+			"checked", sb->s_mnt_count);
+	} else if (sb->s_checkinterval > 0 && now >= next) {
+		unsigned scaled_time;
+		char *scaled_units;
 
-	/* XXX do something with s_state, _mnt_count, checkinterval,
-	 * etc. */
-	return;
+		scale_time(now - sb->s_lastcheck, &scaled_time, &scaled_units);
+		sprintf(reason, "has gone %u %s without being checked",
+			scaled_time, scaled_units);
+	}
+
+	if (reason[0]) {
+		printf("%s %s, check forced.\n", filename, reason);
+		return 0;
+	}
+
+	reason[0] = '\0';
+
+	if (sb->s_max_mnt_count > 0)
+		sprintf(reason, "after %u additional mounts", 
+			sb->s_max_mnt_count - sb->s_mnt_count);
+
+	if (sb->s_checkinterval > 0) {
+		localtime_r(&next, &local);
+
+		if (reason[0])
+			ftso_strftime(reason + strlen(reason),
+				 sizeof(reason) - strlen(reason),
+			 	 " or by %c, whichever comes first", &local);
+		else
+			ftso_strftime(reason, sizeof(reason), "by %c", &local);
+	}
+
+	printf("%s is clean.", filename);
+
+	if (reason[0])
+		printf("  It will be checked %s.\n", reason);
+
+	return 1;
 }
 
 static void print_label(o2fsck_state *ost)
@@ -236,13 +325,91 @@
 	exit(FSCK_USAGE);
 }
 
+static errcode_t open_and_check(o2fsck_state *ost, char *filename,
+				int open_flags, uint64_t blkno,
+				uint64_t blksize)
+{
+	errcode_t ret;
+	char *whoami = __FUNCTION__;
+
+	ret = ocfs2_open(filename, open_flags, blkno, blksize, &ost->ost_fs);
+	if (ret) {
+		com_err(whoami, ret, "while opening file \"%s\"", filename);
+		goto out;
+	}
+
+	ret = check_superblock(ost);
+	if (ret)
+		goto out;
+
+	ret = o2fsck_read_publish(ost);
+	if (ret)
+		goto out;
+
+out:
+	return ret;
+}
+
+static errcode_t maybe_replay_journals(o2fsck_state *ost, char *filename,
+				       int open_flags, uint64_t blkno,
+				       uint64_t blksize)
+{	
+	int replayed = 0;
+	errcode_t ret = 0;
+	char *whoami = __FUNCTION__;
+
+	if (!ost->ost_stale_mounts)
+		goto out;
+
+	if (!(ost->ost_fs->fs_flags & OCFS2_FLAG_RW)) {
+		printf("** Skipping journal replay because -n was "
+		       "given.  There may be spurious errors that "
+		       "journal replay would fix. **\n");
+		goto out;
+	}
+
+	printf("%s wasn't cleanly unmounted by all nodes.  Attempting to "
+	       "replay the journals for nodes that didn't unmount cleanly",
+	       filename);
+
+	/* journal replay is careful not to use ost as we only really
+	 * build it up after spraying the journal all over the disk
+	 * and reopening */
+	ret = o2fsck_replay_journals(ost->ost_fs, ost->ost_publish,
+				     &replayed);
+	if (ret)
+		goto out;
+
+	/* if the journals were replayed we close the fs and start
+	 * over */
+	if (!replayed)
+		goto out;
+
+	ret = ocfs2_close(ost->ost_fs);
+	if (ret) {
+		com_err(whoami, ret, "while closing \"%s\"", filename);
+		goto out;
+	}
+
+	ret = open_and_check(ost, filename, open_flags, blkno, blksize);
+	if (ret) {
+		printf("fsck saw unrecoverable errors while "
+		       "re-opening the super block and will not "
+		       "continue.\n");
+		goto out;
+	}
+out:
+	return ret;
+}
+
 int main(int argc, char **argv)
 {
 	char *filename;
 	int64_t blkno, blksize;
 	o2fsck_state _ost, *ost = &_ost;
-	int c, ret, open_flags = OCFS2_FLAG_RW;
+	int c, open_flags = OCFS2_FLAG_RW;
 	int fsck_mask = FSCK_OK;
+	errcode_t ret;
 
 	memset(ost, 0, sizeof(o2fsck_state));
 	ost->ost_ask = 1;
@@ -257,7 +424,7 @@
 	setlinebuf(stderr);
 	setlinebuf(stdout);
 
-	while((c = getopt(argc, argv, "b:B:GnpuvVy")) != EOF) {
+	while((c = getopt(argc, argv, "b:B:fGnpuvVy")) != EOF) {
 		switch (c) {
 			case 'b':
 				blkno = read_number(optarg);
@@ -346,30 +513,47 @@
 
 	filename = argv[optind];
 
-	ret = ocfs2_open(filename, open_flags, blkno, blksize, &ost->ost_fs);
+	ret = open_and_check(ost, filename, open_flags, blkno, blksize);
 	if (ret) {
-		com_err(argv[0], ret,
-			"while opening file \"%s\"", filename);
+		printf("fsck saw unrecoverable errors in the super block and "
+		       "will not continue.\n");
 		fsck_mask |= FSCK_ERROR;
 		goto out;
 	}
 
+	printf("Checking OCFS2 filesystem in %s:\n", filename);
+	printf("  label:              ");
+	print_label(ost);
+	printf("  uuid:               ");
+	print_uuid(ost);
+	printf("  number of blocks:   %"PRIu64"\n", ost->ost_fs->fs_blocks);
+	printf("  bytes per block:    %u\n", ost->ost_fs->fs_blocksize);
+	printf("  number of clusters: %"PRIu32"\n", ost->ost_fs->fs_clusters);
+	printf("  bytes per cluster:  %u\n", ost->ost_fs->fs_clustersize);
+	printf("  max nodes:          %u\n\n", 
+	       OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes);
+
+	ret = maybe_replay_journals(ost, filename, open_flags, blkno, blksize);
+	if (ret) {
+		printf("fsck encountered unrecoverable errors while "
+		       "replaying the journals and will not continue\n");
+		fsck_mask |= FSCK_ERROR;
+		goto out;
+	}
+
+	/* allocate all this junk after we've replayed the journal and the
+	 * sb should be stable */
 	if (o2fsck_state_init(ost->ost_fs, argv[0], ost)) {
 		fprintf(stderr, "error allocating run-time state, exiting..\n");
 		fsck_mask |= FSCK_ERROR;
 		goto out;
 	}
 
-	ret = check_superblock(argv[0], ost);
-	if (ret) {
-		printf("fsck saw unrecoverable errors in the super block and "
-		       "will not continue.\n");
-		fsck_mask |= FSCK_ERROR;
+	if (fs_is_clean(ost, filename)) {
+		fsck_mask = FSCK_OK;
 		goto out;
 	}
 
-	exit_if_skipping(ost);
-
 #if 0
 	o2fsck_mark_block_used(ost, 0);
 	o2fsck_mark_block_used(ost, 1);
@@ -379,60 +563,61 @@
 
 	/* XXX we don't use the bad blocks inode, do we? */
 
-	printf("Checking OCFS2 filesystem in %s:\n", filename);
-	printf("  label:              ");
-	print_label(ost);
-	printf("  uuid:               ");
-	print_uuid(ost);
-	printf("  number of blocks:   %"PRIu64"\n", ost->ost_fs->fs_blocks);
-	printf("  bytes per block:    %u\n", ost->ost_fs->fs_blocksize);
-	printf("  number of clusters: %"PRIu32"\n", ost->ost_fs->fs_clusters);
-	printf("  bytes per cluster:  %u\n", ost->ost_fs->fs_clustersize);
-	printf("  max nodes:          %u\n", 
-	       OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes);
 
-	ret = o2fsck_replay_journals(ost);
+	/* XXX for now it is assumed that errors returned from a pass
+	 * are fatal.  these can be fixed over time. */
+	ret = o2fsck_pass0(ost);
 	if (ret) {
-		printf("fsck encountered unrecoverable errors while replaying "
-		       "the journals and will not continue\n");
-		fsck_mask |= FSCK_ERROR;
-		goto out;
+		com_err(argv[0], ret, "while performing pass 0");
+		goto done;
 	}
 
-	/* XXX think harder about these error cases. */
-	ret = o2fsck_pass0(ost);
+	ret = o2fsck_pass1(ost);
 	if (ret) {
-		printf("fsck encountered unrecoverable errors in pass 0 and "
-		       "will not continue\n");
-		fsck_mask |= FSCK_ERROR;
-		goto out;
+		com_err(argv[0], ret, "while performing pass 1");
+		goto done;
 	}
 
-	ret = o2fsck_pass1(ost);
-	if (ret)
-		com_err(argv[0], ret, "pass1 failed");
-
 	ret = o2fsck_pass2(ost);
-	if (ret)
-		com_err(argv[0], ret, "pass2 failed");
+	if (ret) {
+		com_err(argv[0], ret, "while performing pass 2");
+		goto done;
+	}
 
 	ret = o2fsck_pass3(ost);
-	if (ret)
-		com_err(argv[0], ret, "pass3 failed");
+	if (ret) {
+		com_err(argv[0], ret, "while performing pass 3");
+		goto done;
+	}
 
 	ret = o2fsck_pass4(ost);
+	if (ret) {
+		com_err(argv[0], ret, "while performing pass 4");
+		goto done;
+	}
+
+done:
 	if (ret)
-		com_err(argv[0], ret, "pass4 failed");
+		fsck_mask |= FSCK_ERROR;
+	else {
+		ost->ost_saw_error = 0;
+		printf("All passes succeeded.\n");
+	}
 
+	if (ost->ost_fs->fs_flags & OCFS2_FLAG_RW) {
+		ret = write_out_superblock(ost);
+		if (ret)
+			com_err(argv[0], ret, "while writing back the "
+				"superblock");
+	}
+
 	ret = ocfs2_close(ost->ost_fs);
 	if (ret) {
-		com_err(argv[0], ret,
-			"while closing file \"%s\"", filename);
-	}
+		com_err(argv[0], ret, "while closing file \"%s\"", filename);
+		/* XXX I wonder about this error.. */
+		fsck_mask |= FSCK_ERROR;
+	} 
 
-	/* XXX check if the fs is modified and yell something. */
-	printf("fsck completed successfully.\n");
-
 out:
 	return fsck_mask;
 }

Modified: trunk/fsck.ocfs2/fsck.ocfs2.8.in
===================================================================
--- trunk/fsck.ocfs2/fsck.ocfs2.8.in	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/fsck.ocfs2.8.in	2004-12-04 20:38:44 UTC (rev 462)
@@ -2,7 +2,7 @@
 .SH "NAME"
 fsck.ocfs2 \- Check an OCFS2 file system.
 .SH "SYNOPSIS"
-\fBfsck.ocfs2\fR [ \fB\-Gnpuvy\fR ] [ \fB\-b\fR \fIsuperblock block\fR ] [ \fB\-B\fR \fIblock size\fR ] \fIdevice\fR
+\fBfsck.ocfs2\fR [ \fB\-fGnpuvy\fR ] [ \fB\-b\fR \fIsuperblock block\fR ] [ \fB\-B\fR \fIblock size\fR ] \fIdevice\fR
 .SH "DESCRIPTION"
 .PP 
 \fBfsck.ocfs2\fR is used to check an OCFS2 file system.

Modified: trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in
===================================================================
--- trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in	2004-12-04 20:38:44 UTC (rev 462)
@@ -16,14 +16,6 @@
 
 .SH "CHECKS"
 
-.SS "1"
-Each node's journals are usually empty after an orderly shut down of the
-file system.  A node was marked as not having shut down properly so its
-journal should be replayed.
-
-Answering yes replays the given node's journal.  Each block in the journal will be written
-to its intended location in the file system. 
-
 .SS "2"
 The group descriptors that make up the global bitmap chain allocator are
 static and should be found in specific chains in the allocator.  A given

Modified: trunk/fsck.ocfs2/include/fsck.h
===================================================================
--- trunk/fsck.ocfs2/include/fsck.h	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/include/fsck.h	2004-12-04 20:38:44 UTC (rev 462)
@@ -26,6 +26,7 @@
 
 #include "icount.h"
 #include "dirblocks.h"
+#include "ocfs2_disk_dlm.h"
 
 typedef struct _o2fsck_state {
 	ocfs2_filesys 	*ost_fs;
@@ -49,6 +50,8 @@
 	 * entries, including '.' and '..'. */
 	o2fsck_icount	*ost_icount_refs;
 
+	ocfs_publish	*ost_publish;
+
 	o2fsck_dirblocks	ost_dirblocks;
 
 	uint32_t	ost_fs_generation;
@@ -63,7 +66,12 @@
 			ost_write_inode_alloc:1,
 			ost_write_error:1,
 			ost_write_cluster_alloc_asked:1,
-			ost_write_cluster_alloc:1,
+ 			ost_write_cluster_alloc:1,
+ 			ost_saw_error:1, /* if we think there are still errors
+ 					  * on disk we'll mark the sb as having
+ 					  * errors as we exit */
+ 			ost_stale_mounts:1, /* set when reading publish blocks
+ 					     * that still indicated mounted */
 			ost_fix_fs_gen:1;
 } o2fsck_state;
 

Modified: trunk/fsck.ocfs2/include/journal.h
===================================================================
--- trunk/fsck.ocfs2/include/journal.h	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/include/journal.h	2004-12-04 20:38:44 UTC (rev 462)
@@ -26,7 +26,8 @@
 
 #include "fsck.h"
 
-errcode_t o2fsck_replay_journals(o2fsck_state *ost);
+errcode_t o2fsck_replay_journals(ocfs2_filesys *fs, ocfs_publish *pub,
+				 int *replayed);
 
 #endif /* __O2FSCK_JOURNAL_H__ */
 

Modified: trunk/fsck.ocfs2/include/problem.h
===================================================================
--- trunk/fsck.ocfs2/include/problem.h	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/include/problem.h	2004-12-04 20:38:44 UTC (rev 462)
@@ -33,7 +33,7 @@
 /* returns non-zero for yes and zero for no.  The caller is expected to
  * provide a thorough description of the state and the action that will
  * be taken depending on the answer.  Without \n termination. */
-int prompt(o2fsck_state *ost, unsigned flags, unsigned code, 
+int prompt(o2fsck_state *ost, unsigned flags, uint16_t code, 
 	   const char *fmt, ...)
 	 __attribute__ ((format (printf, 4, 5)));
 

Modified: trunk/fsck.ocfs2/include/util.h
===================================================================
--- trunk/fsck.ocfs2/include/util.h	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/include/util.h	2004-12-04 20:38:44 UTC (rev 462)
@@ -49,5 +49,6 @@
 				    uint32_t num);
 errcode_t o2fsck_type_from_dinode(o2fsck_state *ost, uint64_t ino,
 				  uint8_t *type);
+errcode_t o2fsck_read_publish(o2fsck_state *ost);
 
 #endif /* __O2FSCK_UTIL_H__ */

Modified: trunk/fsck.ocfs2/journal.c
===================================================================
--- trunk/fsck.ocfs2/journal.c	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/journal.c	2004-12-04 20:38:44 UTC (rev 462)
@@ -23,8 +23,7 @@
  * replayed.  IO errors during replay will just result in partial journal
  * replay, just like jbd does in the kernel.  Journals that don't pass
  * consistency checks, like having overlapping blocks or strange fields, are
- * ignored and left for later passes to clean up.  Overlap testing is done
- * using o2fsck_state's used block bitmap.  
+ * ignored and left for later passes to clean up.  
 
  * XXX
  * 	future passes need to guarantee journals exist and are the same size 
@@ -44,7 +43,6 @@
 #undef be32_to_cpu
 #include "jfs_user.h"
 #include "ocfs2.h"
-#include "ocfs2_disk_dlm.h"
 #include "pass1.h"
 #include "problem.h"
 #include "util.h"
@@ -201,7 +199,7 @@
 	return block;
 }
 
-static errcode_t count_tags(o2fsck_state *ost, char *buf, size_t size,
+static errcode_t count_tags(ocfs2_filesys *fs, char *buf, size_t size,
 			    uint64_t *nr_ret)
 {
 	journal_block_tag_t *tag, *last;
@@ -215,7 +213,7 @@
 
 	for(; tag <= last; tag++) {
 		nr++;
-		if (ocfs2_block_out_of_range(ost->ost_fs, 
+		if (ocfs2_block_out_of_range(fs, 
 					     be32_to_cpu(tag->t_blocknr)))
 			return OCFS2_ET_BAD_JOURNAL_TAG;
 
@@ -230,7 +228,7 @@
 	return 0;
 }
 
-static errcode_t lookup_journal_block(o2fsck_state *ost, 
+static errcode_t lookup_journal_block(ocfs2_filesys *fs, 
 				      struct journal_info *ji, 
 				      uint64_t blkoff,
 				      uint64_t *blkno,
@@ -263,7 +261,7 @@
 	return ret;
 }
 
-static errcode_t read_journal_block(o2fsck_state *ost, 
+static errcode_t read_journal_block(ocfs2_filesys *fs, 
 				    struct journal_info *ji, 
 				    uint64_t blkoff, 
 				    char *buf,
@@ -272,11 +270,11 @@
 	errcode_t err;
 	uint64_t	blkno;
 
-	err = lookup_journal_block(ost, ji, blkoff, &blkno, check_dup);
+	err = lookup_journal_block(fs, ji, blkoff, &blkno, check_dup);
 	if (err)
 		return err;
 
-	err = io_read_block(ost->ost_fs->fs_io, blkno, 1, buf);
+	err = io_read_block(fs->fs_io, blkno, 1, buf);
 	if (err)
 		com_err(whoami, err, "while reading block %"PRIu64" of node "
 			"%d's journal", blkno, ji->ji_node);
@@ -284,7 +282,7 @@
 	return err;
 }
 
-static errcode_t replay_blocks(o2fsck_state *ost, struct journal_info *ji,
+static errcode_t replay_blocks(ocfs2_filesys *fs, struct journal_info *ji,
 			       char *buf, uint64_t seq, uint64_t *next_block)
 {
 	journal_block_tag_t tag, *tagp;
@@ -296,7 +294,7 @@
 	num = (ji->ji_jsb->s_blocksize - sizeof(journal_header_t)) / 
 	      sizeof(tag);
 
-	ret = ocfs2_malloc_blocks(ost->ost_fs->fs_io, 1, &io_buf);
+	ret = ocfs2_malloc_blocks(fs->fs_io, 1, &io_buf);
 	if (ret) {
 		com_err(whoami, ret, "while allocating a block buffer");
 		goto out;
@@ -315,7 +313,7 @@
 		if (revoke_this_block(&ji->ji_revoke, tag.t_blocknr, seq))
 			goto skip_io;
 
-		err = read_journal_block(ost, ji, *next_block, io_buf, 1);
+		err = read_journal_block(fs, ji, *next_block, io_buf, 1);
 		if (err) {
 			ret = err;
 			goto skip_io;
@@ -326,7 +324,7 @@
 			memcpy(io_buf, &magic, sizeof(magic));
 		}
 
-		err = io_write_block(ost->ost_fs->fs_io, tag.t_blocknr, 1, 
+		err = io_write_block(fs->fs_io, tag.t_blocknr, 1, 
 				     io_buf);
 		if (err)
 			ret = err;
@@ -345,7 +343,7 @@
 	return ret;
 }
 
-static errcode_t walk_journal(o2fsck_state *ost, int node, 
+static errcode_t walk_journal(ocfs2_filesys *fs, int node, 
 			      struct journal_info *ji, char *buf, int recover)
 {
 	errcode_t err, ret = 0;
@@ -373,7 +371,7 @@
 			break;
 
 		/* only mark the blocks used on the first pass */
-		err = read_journal_block(ost, ji, next_block, buf, !recover);
+		err = read_journal_block(fs, ji, next_block, buf, !recover);
 		if (err) {
 			ret = err;
 			break;
@@ -402,7 +400,7 @@
 			verbosef("found a desc type %x\n", jh.h_blocktype);
 			/* replay the blocks described in the desc block */
 			if (recover) {
-				err = replay_blocks(ost, ji, buf, next_seq, 
+				err = replay_blocks(fs, ji, buf, next_seq, 
 						    &next_block);
 				if (err)
 					ret = err;
@@ -410,7 +408,7 @@
 			}
 
 			/* just record the blocks as used and carry on */ 
-			err = count_tags(ost, buf, jsb->s_blocksize, &nr);
+			err = count_tags(fs, buf, jsb->s_blocksize, &nr);
 			if (err)
 				ret = err;
 			else
@@ -451,7 +449,7 @@
 	return ret;
 }
 
-static errcode_t prep_journal_info(o2fsck_state *ost, int node,
+static errcode_t prep_journal_info(ocfs2_filesys *fs, int node,
 			           struct journal_info *ji)
 {
 	errcode_t err;
@@ -459,12 +457,12 @@
 	ji->ji_revoke = RB_ROOT;
 	ji->ji_node = node;
 
-	err = ocfs2_malloc_blocks(ost->ost_fs->fs_io, 1, &ji->ji_jsb);
+	err = ocfs2_malloc_blocks(fs->fs_io, 1, &ji->ji_jsb);
 	if (err)
 		com_err(whoami, err, "while allocating space for node %d's "
 			    "journal superblock", node);
 
-	err = ocfs2_lookup_system_inode(ost->ost_fs, JOURNAL_SYSTEM_INODE,
+	err = ocfs2_lookup_system_inode(fs, JOURNAL_SYSTEM_INODE,
 					node, &ji->ji_ino);
 	if (err) {
 		com_err(whoami, err, "while looking up the journal inode for "
@@ -472,26 +470,26 @@
 		goto out;
 	}
 
-	err = ocfs2_read_cached_inode(ost->ost_fs, ji->ji_ino, &ji->ji_cinode);
+	err = ocfs2_read_cached_inode(fs, ji->ji_ino, &ji->ji_cinode);
 	if (err) {
 		com_err(whoami, err, "while reading cached inode %"PRIu64" "
 			"for node %d's journal", ji->ji_ino, node);
 		goto out;
 	}
 
-	err = ocfs2_extent_map_init(ost->ost_fs, ji->ji_cinode);
+	err = ocfs2_extent_map_init(fs, ji->ji_cinode);
 	if (err) {
 		com_err(whoami, err, "while initializing extent map");
 		goto out;
 	}
 
-	err = lookup_journal_block(ost, ji, 0, &ji->ji_jsb_block, 1);
+	err = lookup_journal_block(fs, ji, 0, &ji->ji_jsb_block, 1);
 	if (err)
 		goto out;
 
 	/* XXX be smarter about reading in the whole super block if it
 	 * spans multiple blocks */
-	err = ocfs2_read_journal_superblock(ost->ost_fs, ji->ji_jsb_block, 
+	err = ocfs2_read_journal_superblock(fs, ji->ji_jsb_block, 
 					    (char *)ji->ji_jsb);
 	if (err) {
 		com_err(whoami, err, "while reading block %"PRIu64" as node "
@@ -500,46 +498,35 @@
 		goto out;
 	}
 
-	verbosef("jsb start %u maxlen %u\n", ji->ji_jsb->s_start,
-		 ji->ji_jsb->s_maxlen);
+	verbosef("node: %d jsb start %u maxlen %u\n", node,
+		 ji->ji_jsb->s_start, ji->ji_jsb->s_maxlen);
 out:
 	return err;
 }
 
-static int publish_mounted_set(ocfs2_filesys *fs, char *buf, int node, 
-			       int max_nodes)
-{
-	int b_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
-	/* magic! */
-	ocfs_publish *pub = (ocfs_publish *)(buf + ((2 + 4 + max_nodes + node)
-			       			<< b_bits));
-	verbosef("node %d's publish: %u\n", node, le32_to_cpu(pub->mounted));
-
-	return pub->mounted;
-}
-
 /* Try and replay the nodes journals if they're dirty.  This only returns
  * a non-zero error if the caller should not continue. */
-errcode_t o2fsck_replay_journals(o2fsck_state *ost)
+errcode_t o2fsck_replay_journals(ocfs2_filesys *fs, ocfs_publish *pub,
+				 int *replayed)
 {
 	errcode_t err = 0, ret = 0;
 	struct journal_info *jis, *ji;
 	journal_superblock_t *jsb;
-	char *buf = NULL, *dlm_buf = NULL;
-	int i, max_nodes, buflen, journal_trouble = 0;
-	uint64_t dlm_ino;
+	char *buf = NULL;
+	int journal_trouble = 0;
+	uint16_t i, max_nodes;
 	ocfs2_bitmap *used_blocks = NULL;
 
-	max_nodes = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes;
+	max_nodes = OCFS2_RAW_SB(fs->fs_super)->s_max_nodes;
 
-	ret = ocfs2_block_bitmap_new(ost->ost_fs, "journal blocks",
+	ret = ocfs2_block_bitmap_new(fs, "journal blocks",
 				     &used_blocks);
 	if (ret) {
 		com_err(whoami, ret, "while allocating journal block bitmap"); 
 		goto out;
 	}
 
-	ret = ocfs2_malloc_blocks(ost->ost_fs->fs_io, 1, &buf);
+	ret = ocfs2_malloc_blocks(fs->fs_io, 1, &buf);
 	if (ret) {
 		com_err(whoami, ret, "while allocating room to read journal "
 			    "blocks");
@@ -553,32 +540,19 @@
 		goto out;
 	}
 
-	ret = ocfs2_lookup_system_inode(ost->ost_fs, DLM_SYSTEM_INODE,
-					0, &dlm_ino);
-	if (ret) {
-		com_err(whoami, ret, "while looking up the dlm system inode");
-		goto out;
-	}
-
-	ret = ocfs2_read_whole_file(ost->ost_fs, dlm_ino, &dlm_buf, &buflen);
-	if (ret) {
-		com_err(whoami, ret, "while reading dlm file");
-		goto out;
-	}
-
 	printf("Checking each node's journal.\n");
 
 	for (i = 0, ji = jis; i < max_nodes; i++, ji++) {
-		if (!publish_mounted_set(ost->ost_fs, dlm_buf, i, max_nodes)) {
+		if (!pub[i].mounted) {
 			verbosef("node %d is clean\n", i);
 			continue;
 		}
 		ji->ji_replay = 1;
 		ji->ji_used_blocks = used_blocks;
 
-		err = prep_journal_info(ost, i, ji);
+		err = prep_journal_info(fs, i, ji);
 		if (err == 0)
-			err = walk_journal(ost, i, ji, buf, 0);
+			err = walk_journal(fs, i, ji, buf, 0);
 
 		if (err) {
 			ji->ji_replay = 0;
@@ -591,13 +565,9 @@
 		if (!ji->ji_replay)
 			continue;
 
-		if (!prompt(ost, PY, 1, "Node %d's journal needs to be "
-			    "replayed. Do so?", i)) {
-			journal_trouble = 1;
-			continue;
-		}
+		printf("Replaying node %d's journal.\n", i);
 
-		err = walk_journal(ost, i, ji, buf, 1);
+		err = walk_journal(fs, i, ji, buf, 1);
 		if (err) {
 			journal_trouble = 1;
 			continue;
@@ -614,16 +584,18 @@
 		 * have to also include having recovered the orphan dir.  we
 		 * updated s_start, though, so we won't replay the journal
 		 * again. */
-		err = ocfs2_write_journal_superblock(ost->ost_fs,
+		err = ocfs2_write_journal_superblock(fs,
 						     ji->ji_jsb_block,
 						     (char *)ji->ji_jsb);
 		if (err) {
 			com_err(whoami, err, "while writing node %d's journal "
 				"super block", i);
 			journal_trouble = 1;
+		} else {
+			printf("Node %d's journal replayed successfully.\n",
+			       i);
+			*replayed = 1;
 		}
-
-		printf("Node %d's journal replayed successfully.\n", i);
 	}
 
 	/* this is awkward, but we want fsck -n to tell us as much as it
@@ -641,7 +613,7 @@
 			if (ji->ji_jsb)
 				ocfs2_free(&ji->ji_jsb);
 			if (ji->ji_cinode)
-				ocfs2_free_cached_inode(ost->ost_fs, 
+				ocfs2_free_cached_inode(fs, 
 							ji->ji_cinode);
 			revoke_free_all(&ji->ji_revoke);
 		}
@@ -650,8 +622,6 @@
 
 	if (buf)
 		ocfs2_free(&buf);
-	if (dlm_buf)
-		ocfs2_free(&dlm_buf);
 	if (used_blocks)
 		ocfs2_bitmap_free(used_blocks);
 

Modified: trunk/fsck.ocfs2/pass0.c
===================================================================
--- trunk/fsck.ocfs2/pass0.c	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/pass0.c	2004-12-04 20:38:44 UTC (rev 462)
@@ -165,7 +165,7 @@
 				"descriptor to block %"PRIu64" somewhere in "
 				"chain %d in group allocator inode %"PRIu64, 
 				bg->bg_blkno, cs->cs_chain_no, di->i_blkno);
-			ost->ost_write_error = 1;
+			ost->ost_saw_error = 1;
 		}
 	}
 
@@ -354,7 +354,7 @@
 				"descriptor to block %"PRIu64" somewhere in "
 				"chain %d in group allocator inode %"PRIu64, 
 				bg1->bg_blkno, cs->cs_chain_no, di->i_blkno);
-			ost->ost_write_error = 1;
+			ost->ost_saw_error = 1;
 		}
 	}
 
@@ -513,7 +513,7 @@
 		if (ret) {
 			com_err(whoami, ret, "while writing inode alloc inode "
 				    "%"PRIu64, di->i_blkno);
-			ost->ost_write_error = 1;
+			ost->ost_saw_error = 1;
 			ret = 0;
 		}
 	}
@@ -600,7 +600,7 @@
 				com_err(whoami, ret, "while writing a cluster "
 					"group descriptor at block %"PRIu64,
 					blkno);
-				ost->ost_write_error = 1;
+				ost->ost_saw_error = 1;
 				continue;
 			}
 		}
@@ -646,7 +646,7 @@
 		if (ret) {
 			com_err(whoami, ret, "while writing a cluster group "
 				"descriptor at block %"PRIu64, blkno);
-			ost->ost_write_error = 1;
+			ost->ost_saw_error = 1;
 			continue;
 		}
 
@@ -669,7 +669,7 @@
 		if (ret) {
 			com_err(whoami, ret, "while writing inode alloc inode "
 				    "%"PRIu64, di->i_blkno);
-			ost->ost_write_error = 1;
+			ost->ost_saw_error = 1;
 			ret = 0;
 		}
 	}

Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/pass1.c	2004-12-04 20:38:44 UTC (rev 462)
@@ -821,6 +821,35 @@
 	return;
 }
 
+/* XXX we really need to get the latch stuff straight */
+static errcode_t force_cluster_bit(o2fsck_state *ost, 
+				   ocfs2_cached_inode *ci,
+				   uint64_t bit,
+				   int val)
+{
+	errcode_t ret;
+	char *reason;
+
+	if (!val) {
+		reason = "Cluster %u is marked in the global cluster "
+			 "bitmap but it isn't in use.  Clear its bit "
+			 "in the bitmap?";
+	} else {
+		reason = "Cluster %u is in use but isn't set in the "
+			 "global cluster bitmap.  Set its bit in the "
+			 "bitmap?";
+	}
+
+	if (!prompt(ost, PY, 0, reason, bit))
+		return 0;
+
+	ret = ocfs2_chain_force_val(ost->ost_fs, ci, bit, !!val, NULL);
+	if (ret)
+		com_err(whoami, ret, "while trying to %s bit %"PRIu64" in the "
+			"cluster bitmap", val ? "set" : "clear", bit);
+	return ret;
+}
+
 /* once we've iterated all the inodes we should have the current working
  * set of which blocks we think are in use.  we use this to derive the set
  * of clusters that should be allocated in the cluster chain allocators.  we
@@ -893,27 +922,9 @@
 		if (cbit_found == cbit)
 			continue;
 
-		if (!ost->ost_write_cluster_alloc_asked) {
-			int yn;
-			yn = prompt(ost, PY, 0, "The cluster bitmap doesn't "
-				    "match what fsck thinks should be in use "
-				    "and freed.  Update the bitmap on disk?");
-			ost->ost_write_cluster_alloc_asked = 1;
-			ost->ost_write_cluster_alloc = !!yn;
-			if (!ost->ost_write_cluster_alloc)
-				goto out;
-		}
-
 		/* clear set bits that should have been clear up to cbit */
 		while (cbit_found < cbit) {
-			ret = ocfs2_chain_force_val(ost->ost_fs, ci,
-						    cbit_found, 0, NULL);
-			if (ret) {
-				com_err(whoami, ret, "while trying to clear "
-					"bit %"PRIu64" in the cluster bitmap.",
-					cbit_found);
-				goto out;
-			}
+			force_cluster_bit(ost, ci, cbit_found, 0);
 			cbit_found++;
 			ret = ocfs2_bitmap_find_next_set(ci->ci_chains, cbit, 
 							 &cbit_found);
@@ -922,16 +933,8 @@
 		}
 
 		/* make sure cbit is set before moving on */
-		if (cbit_found != cbit && cbit != ost->ost_fs->fs_clusters) {
-			ret = ocfs2_chain_force_val(ost->ost_fs, ci, cbit, 1,
-						    NULL);
-			if (ret) {
-				com_err(whoami, ret, "while trying to set bit "
-					"%"PRIu64" in the cluster bitmap.",
-					cbit);
-				goto out;
-			}
-		}
+		if (cbit_found != cbit && cbit != ost->ost_fs->fs_clusters)
+			force_cluster_bit(ost, ci, cbit, 1);
 	}
 
 	ret = ocfs2_write_chain_allocator(ost->ost_fs, ci);

Modified: trunk/fsck.ocfs2/problem.c
===================================================================
--- trunk/fsck.ocfs2/problem.c	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/problem.c	2004-12-04 20:38:44 UTC (rev 462)
@@ -146,7 +146,7 @@
  * and have a notion of grouping, as well.  The caller is expected to provide
  * a fully formed question that isn't terminated with a newline.
  */
-int prompt(o2fsck_state *ost, unsigned flags, unsigned code, const char *fmt,
+int prompt(o2fsck_state *ost, unsigned flags, uint16_t code, const char *fmt,
 	   ...)
 {
 	va_list ap;

Modified: trunk/fsck.ocfs2/util.c
===================================================================
--- trunk/fsck.ocfs2/util.c	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/fsck.ocfs2/util.c	2004-12-04 20:38:44 UTC (rev 462)
@@ -26,6 +26,7 @@
  *
  */
 #include <inttypes.h>
+#include <string.h>
 #include "ocfs2.h"
 
 #include "util.h"
@@ -39,7 +40,6 @@
 		com_err(whoami, OCFS2_ET_INTERNAL_FAILURE, "when asked to "
 			"write an inode with an i_blkno of %"PRIu64" to block "
 			"%"PRIu64, di->i_blkno, blkno);
-		ost->ost_write_error = 1;
 		return;
 	}
 
@@ -47,7 +47,7 @@
 	if (ret) {
 		com_err(whoami, ret, "while writing inode %"PRIu64, 
 		        di->i_blkno);
-		ost->ost_write_error = 1;
+		ost->ost_saw_error = 1;
 	}
 }
 
@@ -101,3 +101,56 @@
 		ocfs2_free(&buf);
 	return ret;
 }
+
+errcode_t o2fsck_read_publish(o2fsck_state *ost)
+{
+	uint16_t i, max_nodes;
+	char *dlm_buf = NULL;
+	uint64_t dlm_ino;
+	errcode_t ret;
+	int buflen;
+	char *whoami = "read_publish";
+
+	if (ost->ost_publish)
+		ocfs2_free(&ost->ost_publish);
+
+	max_nodes = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes;
+
+	ret = ocfs2_malloc0(sizeof(ocfs_publish) * max_nodes,
+			    &ost->ost_publish);
+	if (ret) {
+		com_err(whoami, ret, "while allocating an array to store each "
+			"node's publish block");
+		goto out;
+	}
+
+	ret = ocfs2_lookup_system_inode(ost->ost_fs, DLM_SYSTEM_INODE,
+					0, &dlm_ino);
+	if (ret) {
+		com_err(whoami, ret, "while looking up the dlm system inode");
+		goto out;
+	}
+
+	ret = ocfs2_read_whole_file(ost->ost_fs, dlm_ino, &dlm_buf, &buflen);
+	if (ret) {
+		com_err(whoami, ret, "while reading dlm file");
+		goto out;
+	}
+
+	/* I have no idea what that magic math is really doing. */
+	for (i = 0; i < max_nodes; i++) {
+		int b_bits = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_blocksize_bits;
+
+		memcpy(&ost->ost_publish[i],
+		       dlm_buf + ((2 + 4 + max_nodes + i) << b_bits),
+		       sizeof(ocfs_publish));
+		if (ost->ost_publish[i].mounted)
+			ost->ost_stale_mounts = 1;
+	}
+out:
+	if (ret && ost->ost_publish)
+		ocfs2_free(&ost->ost_publish);
+	if (dlm_buf)
+		ocfs2_free(&dlm_buf);
+	return ret;
+}

Modified: trunk/libocfs2/include/ocfs2_fs.h
===================================================================
--- trunk/libocfs2/include/ocfs2_fs.h	2004-12-04 03:00:43 UTC (rev 461)
+++ trunk/libocfs2/include/ocfs2_fs.h	2004-12-04 20:38:44 UTC (rev 462)
@@ -96,6 +96,11 @@
 #define OCFS2_DLM_FL		(0x00000200)	/* DLM area */
 #define OCFS2_CHAIN_FL		(0x00000400)	/* Chain allocator */
 
+/*
+ * superblock s_state flags
+ */
+#define OCFS2_ERROR_FS		(0x00000001)	/* FS saw errors */
+
 /* Limit of space in ocfs2_dir_entry */
 #define OCFS2_MAX_FILENAME_LENGTH       255
 



More information about the Ocfs2-tools-commits mailing list