* [Cluster-devel] cluster/gfs2 fsck/fsck.h fsck/initialize.c fsc ...
@ 2007-01-23 19:30 rpeterso
0 siblings, 0 replies; only message in thread
From: rpeterso @ 2007-01-23 19:30 UTC (permalink / raw)
To: cluster-devel.redhat.com
CVSROOT: /cvs/cluster
Module name: cluster
Branch: RHEL5
Changes by: rpeterso at sourceware.org 2007-01-23 19:30:19
Modified files:
gfs2/fsck : fsck.h initialize.c main.c pass1.c pass1b.c
pass1c.c pass2.c pass3.c pass4.c pass5.c util.c
gfs2/libgfs2 : gfs2_log.c libgfs2.h
Log message:
Resolves: bz 223506: gfs2_fsck: fatal: invalid metadata block
This is a crosswrite from gfs1.
1. Fix a memory leak in pass1b.
2. Improve performance of pass1b by combining loops through fs.
3. Give an error message and abort if file system > 16TB and node
architecture is 32-bits.
4. Give users an "Abort" "Continue" and "Skip" if they interrupt
with ctrl-c. Also, report progress for that pass on interrupt.
5. Added more "percent complete" messages for other passes.
See bz comments for more details.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/fsck.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/initialize.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6&r2=1.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/main.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass1.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass1b.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass1c.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass2.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass3.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass4.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass5.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/util.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/gfs2_log.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/libgfs2.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.7.2.1&r2=1.7.2.2
--- cluster/gfs2/fsck/fsck.h 2006/06/12 20:41:43 1.3
+++ cluster/gfs2/fsck/fsck.h 2007/01/23 19:30:19 1.3.2.1
@@ -58,7 +58,8 @@
extern osi_list_t dir_hash[FSCK_HASH_SIZE];
extern osi_list_t inode_hash[FSCK_HASH_SIZE];
extern struct gfs2_block_list *bl;
-extern uint64_t last_fs_block;
+extern uint64_t last_fs_block, last_reported_block;
+extern int skip_this_pass, fsck_abort, fsck_query;
extern uint64_t last_data_block;
extern uint64_t first_data_block;
extern osi_list_t dup_list;
--- cluster/gfs2/fsck/initialize.c 2006/09/20 16:43:25 1.6
+++ cluster/gfs2/fsck/initialize.c 2007/01/23 19:30:19 1.6.2.1
@@ -95,6 +95,7 @@
{
uint32_t i;
+ log_info("Freeing buffers.\n");
while(!osi_list_empty(&sdp->rglist)){
struct rgrp_list *rgd;
@@ -157,6 +158,12 @@
}
last_fs_block = rmax;
+ if (last_fs_block > 0xffffffff && sizeof(unsigned long) <= 4) {
+ log_crit("This file system is too big for this computer to handle.\n");
+ log_crit("Last fs block = 0x%llx, but sizeof(unsigned long) is %d bytes.\n",
+ last_fs_block, sizeof(unsigned long));
+ goto fail;
+ }
last_data_block = rmax;
first_data_block = rmin;
--- cluster/gfs2/fsck/main.c 2006/06/15 18:48:45 1.4
+++ cluster/gfs2/fsck/main.c 2007/01/23 19:30:19 1.4.2.1
@@ -17,6 +17,8 @@
#include <libgen.h>
#include <string.h>
#include <stdarg.h>
+#include <ctype.h>
+#include <signal.h>
#include "copyright.cf"
#include "libgfs2.h"
@@ -28,7 +30,9 @@
osi_list_t dir_hash[FSCK_HASH_SIZE];
osi_list_t inode_hash[FSCK_HASH_SIZE];
struct gfs2_block_list *bl;
-uint64_t last_fs_block;
+uint64_t last_fs_block, last_reported_block = -1;
+int skip_this_pass = FALSE, fsck_abort = FALSE;
+const char *pass = "";
uint64_t last_data_block;
uint64_t first_data_block;
osi_list_t dup_list;
@@ -133,6 +137,61 @@
return 0;
}
+void interrupt(int sig)
+{
+ fd_set rfds;
+ struct timeval tv;
+ char response;
+ int err;
+
+ if (opts.query) /* if we're asking them a question */
+ return; /* ignore the interrupt signal */
+ FD_ZERO(&rfds);
+ FD_SET(STDIN_FILENO, &rfds);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ /* Make sure there isn't extraneous input before asking the
+ * user the question */
+ while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
+ if(err < 0) {
+ log_debug("Error in select() on stdin\n");
+ break;
+ }
+ read(STDIN_FILENO, &response, sizeof(char));
+ }
+ while (TRUE) {
+ printf("\ngfs_fsck interrupted in %s: ", pass);
+ if (!last_reported_block || last_reported_block == last_fs_block)
+ printf("progress unknown.\n");
+ else
+ printf("processing block %" PRIu64 " out of %" PRIu64 "\n",
+ last_reported_block, last_fs_block);
+ printf("Do you want to abort gfs_fsck, skip the rest of %s or continue (a/s/c)?", pass);
+
+ /* Make sure query is printed out */
+ fflush(stdout);
+ read(STDIN_FILENO, &response, sizeof(char));
+
+ if(tolower(response) == 's') {
+ skip_this_pass = TRUE;
+ return;
+ }
+ else if (tolower(response) == 'a') {
+ fsck_abort = TRUE;
+ return;
+ }
+ else if (tolower(response) == 'c')
+ return;
+ else {
+ while(response != '\n')
+ read(STDIN_FILENO, &response, sizeof(char));
+ printf("Bad response, please type 'c', 'a' or 's'.\n");
+ continue;
+ }
+ }
+}
+
int main(int argc, char **argv)
{
struct gfs2_sbd sb;
@@ -148,41 +207,97 @@
if (initialize(sbp))
return 1;
+ signal(SIGINT, interrupt);
log_notice("Starting pass1\n");
+ pass = "pass 1";
+ last_reported_block = 0;
if (pass1(sbp))
return 1;
- log_notice("Pass1 complete \n");
-
- log_notice("Starting pass1b\n");
- if(pass1b(sbp))
- return 1;
- log_notice("Pass1b complete\n");
-
- log_notice("Starting pass1c\n");
- if(pass1c(sbp))
- return 1;
- log_notice("Pass1c complete\n");
-
- log_notice("Starting pass2\n");
- if (pass2(sbp))
- return 1;
- log_notice("Pass2 complete \n");
-
- log_notice("Starting pass3\n");
- if (pass3(sbp))
- return 1;
- log_notice("Pass3 complete \n");
-
- log_notice("Starting pass4\n");
- if (pass4(sbp))
- return 1;
- log_notice("Pass4 complete \n");
-
- log_notice("Starting pass5\n");
- if (pass5(sbp))
- return 1;
- log_notice("Pass5 complete \n");
+ if (skip_this_pass || fsck_abort) {
+ skip_this_pass = FALSE;
+ log_notice("Pass1 interrupted \n");
+ }
+ else
+ log_notice("Pass1 complete \n");
+ if (!fsck_abort) {
+ last_reported_block = 0;
+ pass = "pass 1b";
+ log_notice("Starting pass1b\n");
+ if(pass1b(sbp))
+ return 1;
+ if (skip_this_pass || fsck_abort) {
+ skip_this_pass = FALSE;
+ log_notice("Pass1b interrupted \n");
+ }
+ else
+ log_notice("Pass1b complete\n");
+ }
+ if (!fsck_abort) {
+ last_reported_block = 0;
+ pass = "pass 1c";
+ log_notice("Starting pass1c\n");
+ if(pass1c(sbp))
+ return 1;
+ if (skip_this_pass || fsck_abort) {
+ skip_this_pass = FALSE;
+ log_notice("Pass1c interrupted \n");
+ }
+ else
+ log_notice("Pass1c complete\n");
+ }
+ if (!fsck_abort) {
+ last_reported_block = 0;
+ pass = "pass 2";
+ log_notice("Starting pass2\n");
+ if (pass2(sbp))
+ return 1;
+ if (skip_this_pass || fsck_abort) {
+ skip_this_pass = FALSE;
+ log_notice("Pass2 interrupted \n");
+ }
+ else
+ log_notice("Pass2 complete \n");
+ }
+ if (!fsck_abort) {
+ last_reported_block = 0;
+ pass = "pass 3";
+ log_notice("Starting pass3\n");
+ if (pass3(sbp))
+ return 1;
+ if (skip_this_pass || fsck_abort) {
+ skip_this_pass = FALSE;
+ log_notice("Pass3 interrupted \n");
+ }
+ else
+ log_notice("Pass3 complete \n");
+ }
+ if (!fsck_abort) {
+ last_reported_block = 0;
+ pass = "pass 4";
+ log_notice("Starting pass4\n");
+ if (pass4(sbp))
+ return 1;
+ if (skip_this_pass || fsck_abort) {
+ skip_this_pass = FALSE;
+ log_notice("Pass4 interrupted \n");
+ }
+ else
+ log_notice("Pass4 complete \n");
+ }
+ if (!fsck_abort) {
+ last_reported_block = 0;
+ pass = "pass 5";
+ log_notice("Starting pass5\n");
+ if (pass5(sbp))
+ return 1;
+ if (skip_this_pass || fsck_abort) {
+ skip_this_pass = FALSE;
+ log_notice("Pass5 interrupted \n");
+ }
+ else
+ log_notice("Pass5 complete \n");
+ }
/* Free up our system inodes */
inode_put(sbp->md.inum, updated);
inode_put(sbp->md.statfs, updated);
--- cluster/gfs2/fsck/pass1.c 2006/06/20 18:30:55 1.4
+++ cluster/gfs2/fsck/pass1.c 2007/01/23 19:30:19 1.4.2.1
@@ -801,6 +801,13 @@
if (gfs2_next_rg_meta(rgd, &block, first))
break;
warm_fuzzy_stuff(block);
+ if (fsck_abort) /* if asked to abort */
+ return 0;
+ if (skip_this_pass) {
+ printf("Skipping pass 1 is not a good idea.\n");
+ skip_this_pass = FALSE;
+ fflush(stdout);
+ }
bh = bread(sbp, block);
if (scan_meta(sbp, bh, block)) {
--- cluster/gfs2/fsck/pass1b.c 2006/06/12 20:41:43 1.3
+++ cluster/gfs2/fsck/pass1b.c 2007/01/23 19:30:19 1.3.2.1
@@ -466,6 +466,7 @@
osi_list_t *tmp;
struct metawalk_fxns find_dirents = {0};
find_dirents.check_dentry = &find_dentry;
+ int rc = 0;
osi_list_init(&dup_list);
/* Shove all blocks marked as duplicated into a list */
@@ -484,11 +485,15 @@
log_debug("Filesystem has %"PRIu64" (0x%" PRIx64 ") blocks total\n",
last_fs_block, last_fs_block);
for(i = 0; i < last_fs_block; i += 1) {
+ warm_fuzzy_stuff(i);
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ goto out;
log_debug("Scanning block %" PRIu64 " (0x%" PRIx64 ") for inodes\n",
i, i);
if(gfs2_block_check(bl, i, &q)) {
stack;
- return -1;
+ rc = -1;
+ goto out;
}
if((q.block_type == gfs2_inode_dir) ||
(q.block_type == gfs2_inode_file) ||
@@ -501,33 +506,26 @@
b = osi_list_entry(tmp, struct blocks, list);
if(find_block_ref(sbp, i, b)) {
stack;
- return -1;
+ rc = -1;
+ goto out;
}
}
}
- }
-
- /* Rescan the fs looking for directory entries to the inodes
- * with duplicate blocks - might need this to deal with the
- * inode correctly */
- log_info("Looking through directory entries for inodes with duplicate blocks...\n");
- for(i = 0; i < last_fs_block; i++) {
- if(gfs2_block_check(bl, i, &q)) {
- stack;
- return 0;
- }
if(q.block_type == gfs2_inode_dir) {
check_dir(sbp, i, &find_dirents);
}
}
-
/* Fix dups here - it's going to slow things down a lot to fix
* it later */
log_info("Handling duplicate blocks\n");
- osi_list_foreach(tmp, &dup_list) {
+out:
+ while (!osi_list_empty(&dup_list)) {
b = osi_list_entry(tmp, struct blocks, list);
- handle_dup_blk(sbp, b);
+ if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */
+ handle_dup_blk(sbp, b);
+ osi_list_del(&b->list);
+ free(b);
}
- return 0;
+ return rc;
}
--- cluster/gfs2/fsck/pass1c.c 2006/06/20 18:30:55 1.4
+++ cluster/gfs2/fsck/pass1c.c 2007/01/23 19:30:19 1.4.2.1
@@ -235,6 +235,8 @@
log_info("Looking for inodes containing ea blocks...\n");
while (!gfs2_find_next_block_type(bl, gfs2_eattr_block, &block_no)) {
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
log_info("EA in inode %"PRIu64" (0x%" PRIx64 ")\n", block_no,
block_no);
bh = bread(sbp, block_no);
--- cluster/gfs2/fsck/pass2.c 2006/06/15 18:48:45 1.4
+++ cluster/gfs2/fsck/pass2.c 2007/01/23 19:30:19 1.4.2.1
@@ -757,8 +757,13 @@
stack;
return -1;
}
+ log_info("Checking directory inodes.\n");
/* Grab each directory inode, and run checks on it */
for(i = 0; i < last_fs_block; i++) {
+ warm_fuzzy_stuff(i);
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
+
/* Skip the root inode - it's checked above */
if(i == sbp->md.rooti->i_di.di_num.no_addr)
continue;
--- cluster/gfs2/fsck/pass3.c 2006/06/15 18:48:45 1.4
+++ cluster/gfs2/fsck/pass3.c 2007/01/23 19:30:19 1.4.2.1
@@ -214,6 +214,8 @@
/* FIXME: Change this so it returns success or
* failure and put the parent inode in a
* param */
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
tdi = mark_and_return_parent(sbp, di);
/* FIXME: Factor this ? */
--- cluster/gfs2/fsck/pass4.c 2006/06/15 18:48:45 1.4
+++ cluster/gfs2/fsck/pass4.c 2007/01/23 19:30:19 1.4.2.1
@@ -48,6 +48,8 @@
/* FIXME: should probably factor this out into a generic
* scanning fxn */
osi_list_foreach(tmp, list) {
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
f = not_updated;
if(!(ii = osi_list_entry(tmp, struct inode_info, list))) {
log_crit("osi_list_foreach broken in scan_info_list!!\n");
@@ -165,6 +167,8 @@
lf_dip->i_di.di_entries);
log_info("Checking inode reference counts.\n");
for (i = 0; i < FSCK_HASH_SIZE; i++) {
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
list = &inode_hash[i];
if(scan_inode_list(sbp, list)) {
stack;
--- cluster/gfs2/fsck/pass5.c 2006/06/12 20:41:43 1.3
+++ cluster/gfs2/fsck/pass5.c 2007/01/23 19:30:19 1.3.2.1
@@ -77,7 +77,10 @@
while(byte < end) {
rg_status = ((*byte >> bit) & GFS2_BIT_MASK);
block = rg_data + *rg_block;
+ log_debug("Checking block %" PRIu64 "\n", block);
warm_fuzzy_stuff(block);
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
gfs2_block_check(bl, block, &q);
block_status = convert_mark(q.block_type, count);
@@ -128,6 +131,8 @@
/* update the bitmaps */
check_block_status(sbp, rgp->bh[i]->b_data + bits->bi_offset,
bits->bi_len, &rg_block, rgp->ri.ri_data0, count);
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
}
/* actually adjust counters and write out to disk */
@@ -180,6 +185,8 @@
for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){
enum update_flags f;
+ if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+ return 0;
log_info("Verifying Resource Group #%" PRIu64 "\n", rg_count);
memset(count, 0, sizeof(count));
rgp = osi_list_entry(tmp, struct rgrp_list, list);
--- cluster/gfs2/fsck/util.c 2006/06/15 18:48:45 1.4
+++ cluster/gfs2/fsck/util.c 2007/01/23 19:30:19 1.4.2.1
@@ -60,16 +60,19 @@
{
static struct timeval tv;
static uint32_t seconds = 0;
-
+
+ last_reported_block = block;
gettimeofday(&tv, NULL);
if (!seconds)
- seconds = tv.tv_sec;
+ seconds = tv.tv_sec;
if (tv.tv_sec - seconds) {
uint64_t percent;
seconds = tv.tv_sec;
- percent = (block * 100) / last_fs_block;
- log_notice("\r%" PRIu64 " percent complete.\r", percent);
+ if (last_fs_block) {
+ percent = (block * 100) / last_fs_block;
+ log_notice("\r%" PRIu64 " percent complete.\r", percent);
+ }
}
}
--- cluster/gfs2/libgfs2/gfs2_log.c 2006/06/15 18:45:22 1.2
+++ cluster/gfs2/libgfs2/gfs2_log.c 2007/01/23 19:30:19 1.2.2.1
@@ -103,6 +103,7 @@
if(opts->no)
return 0;
+ opts->query = TRUE;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
@@ -150,5 +151,6 @@
read(STDIN_FILENO, &response, sizeof(char));
}
+ opts->query = FALSE;
return ret;
}
--- cluster/gfs2/libgfs2/libgfs2.h 2006/11/30 15:29:48 1.7.2.1
+++ cluster/gfs2/libgfs2/libgfs2.h 2007/01/23 19:30:19 1.7.2.2
@@ -437,6 +437,7 @@
char *device;
int yes:1;
int no:1;
+ int query:1;
};
#define MSG_DEBUG 7
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2007-01-23 19:30 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-23 19:30 [Cluster-devel] cluster/gfs2 fsck/fsck.h fsck/initialize.c fsc rpeterso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).