[Ocfs2-tools-commits] zab commits r463 - in trunk/fsck.ocfs2: .
include
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Sat Dec 4 19:28:06 CST 2004
Author: zab
Date: 2004-12-04 19:28:04 -0600 (Sat, 04 Dec 2004)
New Revision: 463
Modified:
trunk/fsck.ocfs2/dirblocks.c
trunk/fsck.ocfs2/dirparents.c
trunk/fsck.ocfs2/fsck.c
trunk/fsck.ocfs2/icount.c
trunk/fsck.ocfs2/include/dirblocks.h
trunk/fsck.ocfs2/include/dirparents.h
trunk/fsck.ocfs2/include/icount.h
trunk/fsck.ocfs2/include/util.h
trunk/fsck.ocfs2/pass1.c
trunk/fsck.ocfs2/pass2.c
trunk/fsck.ocfs2/pass3.c
Log:
o kill fatal_error and bubble up errcode_ts instead. this nicely lead to
checking some errors that weren't going unchecked, fixing up some awkward
constructs in pass2, and now passes 2 and 3 return real errors to fsck.c
Modified: trunk/fsck.ocfs2/dirblocks.c
===================================================================
--- trunk/fsck.ocfs2/dirblocks.c 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/dirblocks.c 2004-12-05 01:28:04 UTC (rev 463)
@@ -34,17 +34,19 @@
#include "dirblocks.h"
#include "util.h"
-void o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino, uint64_t blkno,
- uint64_t blkcount)
+errcode_t o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino,
+ uint64_t blkno, uint64_t blkcount)
{
struct rb_node ** p = &db->db_root.rb_node;
struct rb_node * parent = NULL;
o2fsck_dirblock_entry *dbe, *tmp_dbe;
+ errcode_t ret = 0;
dbe = calloc(1, sizeof(*dbe));
- if (dbe == NULL)
- fatal_error(OCFS2_ET_NO_MEMORY,
- "while allocating directory entries");
+ if (dbe == NULL) {
+ ret = OCFS2_ET_NO_MEMORY;
+ goto out;
+ }
dbe->e_ino = ino;
dbe->e_blkno = blkno;
@@ -63,6 +65,9 @@
rb_link_node(&dbe->e_node, parent, p);
rb_insert_color(&dbe->e_node, &db->db_root);
+
+out:
+ return ret;
}
void o2fsck_dir_block_iterate(o2fsck_dirblocks *db, dirblock_iterator func,
Modified: trunk/fsck.ocfs2/dirparents.c
===================================================================
--- trunk/fsck.ocfs2/dirparents.c 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/dirparents.c 2004-12-05 01:28:04 UTC (rev 463)
@@ -37,17 +37,21 @@
/* XXX callers are supposed to make sure they don't call with dup inodes.
* we'll see. */
-void o2fsck_add_dir_parent(struct rb_root *root, uint64_t ino, uint64_t dot_dot,
- uint64_t dirent)
+errcode_t o2fsck_add_dir_parent(struct rb_root *root,
+ uint64_t ino,
+ uint64_t dot_dot,
+ uint64_t dirent)
{
struct rb_node ** p = &root->rb_node;
struct rb_node * parent = NULL;
o2fsck_dir_parent *dp, *tmp_dp;
+ errcode_t ret = 0;
dp = calloc(1, sizeof(*dp));
- if (dp == NULL)
- fatal_error(OCFS2_ET_NO_MEMORY,
- "while allocating directory entries");
+ if (dp == NULL) {
+ ret = OCFS2_ET_NO_MEMORY;
+ goto out;
+ }
dp->dp_ino = ino;
dp->dp_dot_dot = dot_dot;
@@ -64,14 +68,16 @@
p = &(*p)->rb_left;
else if (dp->dp_ino > tmp_dp->dp_ino)
p = &(*p)->rb_right;
- else
- fatal_error(OCFS2_ET_INTERNAL_FAILURE, "while adding "
- "unique dir parent tracking for dir inode "
- "%"PRIu64, ino);
+ else {
+ ret = OCFS2_ET_INTERNAL_FAILURE;
+ goto out;
+ }
}
rb_link_node(&dp->dp_node, parent, p);
rb_insert_color(&dp->dp_node, root);
+out:
+ return ret;
}
o2fsck_dir_parent *o2fsck_dir_parent_lookup(struct rb_root *root, uint64_t ino)
Modified: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/fsck.c 2004-12-05 01:28:04 UTC (rev 463)
@@ -36,9 +36,14 @@
* _should not_ write to the file system unless it has asked prompt() to do
* so. It should also not exit if prompt() returns 0. prompt() should give
* as much detail as possible as it becomes an error log.
- * - to make life simpler, memory allocation is a fatal error. We should
- * have reasonable memory demands in relation to the size of the fs.
- * - I'm still of mixed opinions about IO errors. thoughts?
+ * - to make life simpler, memory allocation is a fatal error. It would be
+ * very exciting to have allocation failure trick fsck -y into tearing
+ * apart the fs because it didn't have memorty to track what was in use.
+ * We should have reasonable memory demands in relation to the size of
+ * the fs.
+ * - I'm still of mixed opinions about IO errors. For now they're fatal.
+ * One needs to dd a volume off a busted device before fixing it.
+ * thoughts?
*/
#include <getopt.h>
#include <limits.h>
Modified: trunk/fsck.ocfs2/icount.c
===================================================================
--- trunk/fsck.ocfs2/icount.c 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/icount.c 2004-12-05 01:28:04 UTC (rev 463)
@@ -87,10 +87,11 @@
}
/* keep it simple for now by always updating both data structures */
-void o2fsck_icount_set(o2fsck_icount *icount, uint64_t blkno,
- uint16_t count)
+errcode_t o2fsck_icount_set(o2fsck_icount *icount, uint64_t blkno,
+ uint16_t count)
{
icount_node *in;
+ errcode_t ret = 0;
if (count == 1)
ocfs2_bitmap_set(icount->ic_single_bm, blkno, NULL);
@@ -107,14 +108,18 @@
}
} else if (count > 1) {
in = calloc(1, sizeof(*in));
- if (in == NULL)
- fatal_error(OCFS2_ET_NO_MEMORY,
- "while allocating to track icount");
+ if (in == NULL) {
+ ret = OCFS2_ET_NO_MEMORY;
+ goto out;
+ }
in->in_blkno = blkno;
in->in_icount = count;
icount_insert(icount, in);
}
+
+out:
+ return ret;
}
uint16_t o2fsck_icount_get(o2fsck_icount *icount, uint64_t blkno)
@@ -162,9 +167,9 @@
}
if (prev_count + delta < 0)
- fatal_error(OCFS2_ET_INTERNAL_FAILURE, "while droping icount "
- "from %"PRIu16" bt %d for inode %"PRIu64,
- prev_count, delta, blkno);
+ com_err(__FUNCTION__, OCFS2_ET_INTERNAL_FAILURE,
+ "while droping icount from %"PRIu16" bt %d for "
+ "inode %"PRIu64, prev_count, delta, blkno);
o2fsck_icount_set(icount, blkno, prev_count + delta);
}
Modified: trunk/fsck.ocfs2/include/dirblocks.h
===================================================================
--- trunk/fsck.ocfs2/include/dirblocks.h 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/include/dirblocks.h 2004-12-05 01:28:04 UTC (rev 463)
@@ -40,8 +40,8 @@
typedef unsigned (*dirblock_iterator)(o2fsck_dirblock_entry *,
void *priv_data);
-void o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino, uint64_t blkno,
- uint64_t blkcount);
+errcode_t o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino,
+ uint64_t blkno, uint64_t blkcount);
void o2fsck_dir_block_iterate(o2fsck_dirblocks *db, dirblock_iterator func,
void *priv_data);
Modified: trunk/fsck.ocfs2/include/dirparents.h
===================================================================
--- trunk/fsck.ocfs2/include/dirparents.h 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/include/dirparents.h 2004-12-05 01:28:04 UTC (rev 463)
@@ -40,8 +40,10 @@
int dp_connected;
} o2fsck_dir_parent;
-void o2fsck_add_dir_parent(struct rb_root *root, uint64_t ino,
- uint64_t dot_dot, uint64_t dirent);
+errcode_t o2fsck_add_dir_parent(struct rb_root *root,
+ uint64_t ino,
+ uint64_t dot_dot,
+ uint64_t dirent);
o2fsck_dir_parent *o2fsck_dir_parent_lookup(struct rb_root *root,
uint64_t ino);
Modified: trunk/fsck.ocfs2/include/icount.h
===================================================================
--- trunk/fsck.ocfs2/include/icount.h 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/include/icount.h 2004-12-05 01:28:04 UTC (rev 463)
@@ -31,8 +31,8 @@
struct rb_root ic_multiple_tree;
} o2fsck_icount;
-void o2fsck_icount_set(o2fsck_icount *icount, uint64_t blkno,
- uint16_t count);
+errcode_t o2fsck_icount_set(o2fsck_icount *icount, uint64_t blkno,
+ uint16_t count);
uint16_t o2fsck_icount_get(o2fsck_icount *icount, uint64_t blkno);
errcode_t o2fsck_icount_new(ocfs2_filesys *fs, o2fsck_icount **ret);
void o2fsck_icount_free(o2fsck_icount *icount);
Modified: trunk/fsck.ocfs2/include/util.h
===================================================================
--- trunk/fsck.ocfs2/include/util.h 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/include/util.h 2004-12-05 01:28:04 UTC (rev 463)
@@ -37,12 +37,6 @@
#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
#define FSCK_LIBRARY 128 /* Shared library error */
-/* no va_list variant of com_err */
-#define fatal_error(errcode, fmt...) do { \
- com_err("o2fsck", errcode, fmt); \
- exit(FSCK_ERROR); \
-} while (0)
-
void o2fsck_write_inode(o2fsck_state *ost, uint64_t blkno, ocfs2_dinode *di);
void o2fsck_mark_cluster_allocated(o2fsck_state *ost, uint32_t cluster);
void o2fsck_mark_clusters_allocated(o2fsck_state *ost, uint32_t cluster,
Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/pass1.c 2004-12-05 01:28:04 UTC (rev 463)
@@ -418,6 +418,7 @@
int vb_errors;
o2fsck_state *vb_ost;
ocfs2_dinode *vb_di;
+ errcode_t vb_ret;
};
/* last_block and num_blocks would be different in a sparse file */
@@ -428,25 +429,27 @@
vb->vb_last_block = bcount;
}
-static void process_link_block(struct verifying_blocks *vb, uint64_t blkno)
+static errcode_t process_link_block(struct verifying_blocks *vb,
+ uint64_t blkno)
{
char *buf, *null;
- errcode_t ret;
+ errcode_t ret = 0;
unsigned int blocksize = vb->vb_ost->ost_fs->fs_blocksize;
if (vb->vb_saw_link_null)
- return;
+ goto out;
ret = ocfs2_malloc_blocks(vb->vb_ost->ost_fs->fs_io, 1, &buf);
- if (ret)
- fatal_error(ret, "while allocating room to read a block of "
- "link data");
-
- ret = io_read_block(vb->vb_ost->ost_fs->fs_io, blkno, 1, buf);
if (ret) {
+ com_err(whoami, ret, "while allocating room to read a block "
+ "of link data");
goto out;
}
+ ret = io_read_block(vb->vb_ost->ost_fs->fs_io, blkno, 1, buf);
+ if (ret)
+ goto out;
+
null = memchr(buf, 0, blocksize);
if (null != NULL) {
vb->vb_link_len += null - buf;
@@ -457,6 +460,7 @@
out:
ocfs2_free(&buf);
+ return ret;
}
static void check_link_data(struct verifying_blocks *vb)
@@ -524,6 +528,7 @@
struct verifying_blocks *vb = priv_data;
ocfs2_dinode *di = vb->vb_di;
o2fsck_state *ost = vb->vb_ost;
+ errcode_t ret = 0;
/* someday we may want to worry about holes in files here */
@@ -551,13 +556,20 @@
if (S_ISDIR(di->i_mode)) {
verbosef("adding dir block %"PRIu64"\n", blkno);
- o2fsck_add_dir_block(&ost->ost_dirblocks, di->i_blkno, blkno,
- bcount);
+ ret = o2fsck_add_dir_block(&ost->ost_dirblocks, di->i_blkno,
+ blkno, bcount);
+ if (ret) {
+ com_err(whoami, ret, "while trying to track block in "
+ "directory inode %"PRIu64, di->i_blkno);
+ }
+ } else if (S_ISLNK(di->i_mode))
+ ret = process_link_block(vb, blkno);
+
+ if (ret) {
+ vb->vb_ret = ret;
+ return OCFS2_BLOCK_ABORT;
}
- if (S_ISLNK(di->i_mode))
- process_link_block(vb, blkno);
-
vb_saw_block(vb, bcount);
return 0;
@@ -579,16 +591,16 @@
}
-static void o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
- uint64_t blkno, ocfs2_dinode *di)
+static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
+ uint64_t blkno, ocfs2_dinode *di)
{
- struct verifying_blocks vb = {0, };
uint64_t expected = 0;
errcode_t ret;
+ struct verifying_blocks vb = {
+ .vb_ost = ost,
+ .vb_di = di,
+ };
- vb.vb_ost = ost;
- vb.vb_di = di;
-
if (di->i_flags & OCFS2_LOCAL_ALLOC_FL)
ret = 0;
else if (di->i_flags & OCFS2_CHAIN_FL)
@@ -598,11 +610,14 @@
if (ret == 0)
ret = ocfs2_block_iterate_inode(fs, di, 0,
verify_block, &vb);
+ if (vb.vb_ret)
+ ret = vb.vb_ret;
}
if (ret) {
- fatal_error(ret, "while iterating over the blocks for inode "
- "%"PRIu64, di->i_blkno);
+ com_err(whoami, ret, "while iterating over the blocks for "
+ "inode %"PRIu64, di->i_blkno);
+ goto out;
}
if (S_ISLNK(di->i_mode))
@@ -654,6 +669,8 @@
di->i_clusters = expected;
o2fsck_write_inode(ost, blkno, di);
}
+out:
+ return ret;
}
static void sync_local_bitmap(o2fsck_state *ost, ocfs2_dinode *di,
@@ -991,8 +1008,7 @@
ret = ocfs2_malloc_block(fs->fs_io, &buf);
if (ret) {
- com_err(whoami, ret,
- "while allocating inode buffer");
+ com_err(whoami, ret, "while allocating inode buffer");
goto out;
}
@@ -1000,8 +1016,7 @@
ret = ocfs2_open_inode_scan(fs, &scan);
if (ret) {
- com_err(whoami, ret,
- "while opening inode scan");
+ com_err(whoami, ret, "while opening inode scan");
goto out_free;
}
@@ -1032,8 +1047,11 @@
if (di->i_flags & OCFS2_VALID_FL)
o2fsck_verify_inode_fields(fs, ost, blkno, di);
- if (di->i_flags & OCFS2_VALID_FL)
- o2fsck_check_blocks(fs, ost, blkno, di);
+ if (di->i_flags & OCFS2_VALID_FL) {
+ ret = o2fsck_check_blocks(fs, ost, blkno, di);
+ if (ret)
+ goto out;
+ }
valid = di->i_flags & OCFS2_VALID_FL;
}
@@ -1051,5 +1069,5 @@
ocfs2_free(&buf);
out:
- return 0;
+ return ret;
}
Modified: trunk/fsck.ocfs2/pass2.c
===================================================================
--- trunk/fsck.ocfs2/pass2.c 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/pass2.c 2004-12-05 01:28:04 UTC (rev 463)
@@ -69,6 +69,7 @@
o2fsck_state *ost;
ocfs2_filesys *fs;
char *buf;
+ errcode_t ret;
};
static int dirent_has_dots(struct ocfs2_dir_entry *dirent, int num_dots)
@@ -94,22 +95,25 @@
return 0;
}
-static int fix_dirent_dots(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
- struct ocfs2_dir_entry *dirent, int offset,
- int left)
+static errcode_t fix_dirent_dots(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
+ struct ocfs2_dir_entry *dirent, int offset,
+ int left, int *flags)
{
int expect_dots = expected_dots(dbe, offset);
- int ret_flags = 0, changed_len = 0;
+ int changed_len = 0;
struct ocfs2_dir_entry *next;
uint16_t new_len;
+ errcode_t ret = 0;
if (!expect_dots) {
if (!dirent_has_dots(dirent, 1) && !dirent_has_dots(dirent, 2))
+ goto out;
return 0;
if (prompt(ost, PY, 0, "Duplicate '%.*s' directory entry found, "
"remove it?", dirent->name_len, dirent->name)) {
dirent->inode = 0;
- return OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
+ goto out;
}
}
@@ -123,7 +127,7 @@
dirent->name_len = expect_dots;
memset(dirent->name, '.', expect_dots);
changed_len = 1;
- ret_flags = OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
/* we only record where .. points for now and that ends the
@@ -132,14 +136,14 @@
o2fsck_dir_parent *dp;
dp = o2fsck_dir_parent_lookup(&ost->ost_dir_parents,
dbe->e_ino);
- if (dp == NULL)
- fatal_error(OCFS2_ET_INTERNAL_FAILURE,
- "no dir parents for '..' entry for "
- "inode %"PRIu64, dbe->e_ino);
+ if (dp == NULL) {
+ ret = OCFS2_ET_INTERNAL_FAILURE;
+ com_err(whoami, ret, "no dir parents for '..' entry "
+ "for inode %"PRIu64, dbe->e_ino);
+ } else
+ dp->dp_dot_dot = dirent->inode;
- dp->dp_dot_dot = dirent->inode;
-
- return ret_flags;
+ goto out;
}
if ((dirent->inode != dbe->e_ino) &&
@@ -147,7 +151,7 @@
"points to inode %"PRIu64" instead of itself. Fix "
"the '.' entry?", dbe->e_ino, dirent->inode)) {
dirent->inode = dbe->e_ino;
- ret_flags = OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
/*
@@ -168,29 +172,19 @@
next->inode = 0;
next->name_len = 0;
next->rec_len = OCFS2_DIR_REC_LEN(next->rec_len);
- ret_flags = OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
- return ret_flags;
+
+out:
+ return ret;
}
/* we just copy ext2's fixing behaviour here. 'left' is the number of bytes
* from the start of the dirent struct to the end of the block. */
-static int fix_dirent_lengths(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
- struct ocfs2_dir_entry *dirent, int offset,
- int left, struct ocfs2_dir_entry *prev)
+static void fix_dirent_lengths(struct ocfs2_dir_entry *dirent,
+ int left, struct ocfs2_dir_entry *prev,
+ int *flags)
{
- if ((dirent->rec_len >= OCFS2_DIR_REC_LEN(1)) &&
- ((dirent->rec_len & OCFS2_DIR_ROUND) == 0) &&
- (dirent->rec_len <= left) &&
- (OCFS2_DIR_REC_LEN(dirent->name_len) <= dirent->rec_len))
- return 0;
-
- if (!prompt(ost, PY, 0, "Directory inode %"PRIu64" corrupted in logical "
- "block %"PRIu64" physical block %"PRIu64" offset %d. "
- "Attempt to repair this block's directory entries?",
- dbe->e_ino, dbe->e_blkcount, dbe->e_blkno, offset))
- fatal_error(OCFS2_ET_DIR_CORRUPTED, "in pass2");
-
/* special casing an empty dirent that doesn't include the
* extra rec_len alignment */
if ((left >= OCFS2_DIR_MEMBER_LEN) &&
@@ -199,14 +193,14 @@
left -= dirent->rec_len;
memmove(cp, cp + dirent->rec_len, left);
memset(cp + left, 0, dirent->rec_len);
- return OCFS2_DIRENT_CHANGED;
+ goto out;
}
/* clamp rec_len to the remainder of the block if name_len
* is within the block */
if (dirent->rec_len > left && dirent->name_len <= left) {
dirent->rec_len = left;
- return OCFS2_DIRENT_CHANGED;
+ goto out;
}
/* from here on in we're losing directory entries by adding their
@@ -223,20 +217,22 @@
dirent->file_type = OCFS2_FT_UNKNOWN;
}
- return OCFS2_DIRENT_CHANGED;
+out:
+ *flags |= OCFS2_DIRENT_CHANGED;
}
-static int fix_dirent_name(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
- struct ocfs2_dir_entry *dirent, int offset)
+static void fix_dirent_name(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
+ struct ocfs2_dir_entry *dirent, int offset,
+ int *flags)
{
char *chr = dirent->name;
- int len = dirent->name_len, fix = 0, ret_flags = 0;
+ int len = dirent->name_len, fix = 0;
if (len == 0) {
if (prompt(ost, PY, 0, "Directory entry has a zero-length name, "
"clear it?")) {
dirent->inode = 0;
- ret_flags = OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
}
@@ -248,26 +244,25 @@
"them with dots?", dirent->name_len,
dirent->name);
if (!fix)
- return 0;
+ break;
}
*chr = '.';
- ret_flags = OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
-
- return ret_flags;
}
-static int fix_dirent_inode(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
- struct ocfs2_dir_entry *dirent, int offset)
+static void fix_dirent_inode(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
+ struct ocfs2_dir_entry *dirent, int offset,
+ int *flags)
{
- if (ocfs2_block_out_of_range(ost->ost_fs, dirent->inode)) {
- if (prompt(ost, PY, 0, "Directory entry '%.*s' refers to inode "
- "number %"PRIu64" which is out of range, "
- "clear the entry?", dirent->name_len, dirent->name,
- dirent->inode)) {
- dirent->inode = 0;
- return OCFS2_DIRENT_CHANGED;
- }
+ if (ocfs2_block_out_of_range(ost->ost_fs, dirent->inode) &&
+ prompt(ost, PY, 0, "Directory entry '%.*s' refers to inode "
+ "number %"PRIu64" which is out of range, clear the entry?",
+ dirent->name_len, dirent->name, dirent->inode)) {
+
+ dirent->inode = 0;
+ *flags |= OCFS2_DIRENT_CHANGED;
+ goto out;
}
if (!o2fsck_test_inode_allocated(ost, dbe->e_ino) &&
@@ -275,9 +270,10 @@
"%"PRIu64" which isn't allocated, clear the entry?",
dirent->name_len, dirent->name, dirent->inode)) {
dirent->inode = 0;
- return OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
- return 0;
+out:
+ return;
}
#define type_entry(type) [type] = #type
@@ -301,35 +297,42 @@
return file_types[type];
}
-static int fix_dirent_filetype(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
- struct ocfs2_dir_entry *dirent, int offset)
+static errcode_t fix_dirent_filetype(o2fsck_state *ost,
+ o2fsck_dirblock_entry *dbe,
+ struct ocfs2_dir_entry *dirent,
+ int offset,
+ int *flags)
{
uint8_t expected_type;
- errcode_t err;
+ errcode_t ret;
int was_set;
- /* XXX Do I care about possible bitmap_test errors here? */
-
- ocfs2_bitmap_test(ost->ost_dir_inodes, dirent->inode, &was_set);
+ ret = ocfs2_bitmap_test(ost->ost_dir_inodes, dirent->inode, &was_set);
+ if (ret)
+ goto out;
if (was_set) {
expected_type = OCFS2_FT_DIR;
goto check;
}
- ocfs2_bitmap_test(ost->ost_reg_inodes, dirent->inode, &was_set);
+ ret = ocfs2_bitmap_test(ost->ost_reg_inodes, dirent->inode, &was_set);
+ if (ret)
+ goto out;
if (was_set) {
expected_type = OCFS2_FT_REG_FILE;
goto check;
}
- ocfs2_bitmap_test(ost->ost_bad_inodes, dirent->inode, &was_set);
+ ret = ocfs2_bitmap_test(ost->ost_bad_inodes, dirent->inode, &was_set);
+ if (ret)
+ goto out;
if (was_set) {
expected_type = OCFS2_FT_UNKNOWN;
goto check;
}
- err = o2fsck_type_from_dinode(ost, dirent->inode, &expected_type);
- if (err) /* XXX propogate this? */
+ ret = o2fsck_type_from_dinode(ost, dirent->inode, &expected_type);
+ if (ret)
goto out;
check:
@@ -343,44 +346,55 @@
file_type_string(expected_type), expected_type)) {
dirent->file_type = expected_type;
- return OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
out:
- return 0;
+ if (ret)
+ com_err(whoami, ret, "while trying to verify the file type "
+ "of directory entry %.*s", dirent->name_len,
+ dirent->name);
+
+ return ret;
}
-static int fix_dirent_linkage(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
- struct ocfs2_dir_entry *dirent, int offset)
+static errcode_t fix_dirent_linkage(o2fsck_state *ost,
+ o2fsck_dirblock_entry *dbe,
+ struct ocfs2_dir_entry *dirent,
+ int offset,
+ int *flags)
{
int expect_dots = expected_dots(dbe, offset);
o2fsck_dir_parent *dp;
- errcode_t err;
+ errcode_t ret = 0;
int is_dir;
/* we already took care of special-casing the dots */
if (expect_dots)
- return 0;
+ goto out;
/* we're only checking the linkage if we already found the dir
* this inode claims to be pointing to */
- err = ocfs2_bitmap_test(ost->ost_dir_inodes, dirent->inode, &is_dir);
- if (err)
- fatal_error(err, "while checking for inode %"PRIu64" in the "
- "dir bitmap", dirent->inode);
+ ret = ocfs2_bitmap_test(ost->ost_dir_inodes, dirent->inode, &is_dir);
+ if (ret)
+ com_err(whoami, ret, "while checking for inode %"PRIu64" in "
+ "the dir bitmap", dirent->inode);
if (!is_dir)
- return 0;
+ goto out;
dp = o2fsck_dir_parent_lookup(&ost->ost_dir_parents, dirent->inode);
- if (dp == NULL)
- fatal_error(OCFS2_ET_INTERNAL_FAILURE, "no dir parents for "
- "'..' entry for inode %"PRIu64, dbe->e_ino);
+ if (dp == NULL) {
+ ret = OCFS2_ET_INTERNAL_FAILURE;
+ com_err(whoami, ret, "no dir parents recorded for inode "
+ "%"PRIu64, dirent->inode);
+ goto out;
+ }
/* if no dirents have pointed to this inode yet we record ours
* as the first and move on */
if (dp->dp_dirent == 0) {
dp->dp_dirent = dbe->e_ino;
- return 0;
+ goto out;
}
if (prompt(ost, 0, 0, "Directory inode %"PRIu64" is not the first to "
@@ -390,57 +404,73 @@
dirent->name_len, dirent->name, dirent->inode)) {
dirent->inode = 0;
- return OCFS2_DIRENT_CHANGED;
+ *flags |= OCFS2_DIRENT_CHANGED;
}
- return 0;
+out:
+ return ret;
}
-static int fix_dirent_dups(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
- struct ocfs2_dir_entry *dirent,
- o2fsck_strings *strings, int *dups_in_block)
+static errcode_t fix_dirent_dups(o2fsck_state *ost,
+ o2fsck_dirblock_entry *dbe,
+ struct ocfs2_dir_entry *dirent,
+ o2fsck_strings *strings,
+ int *dups_in_block,
+ int *flags)
{
- errcode_t err;
+ errcode_t ret = 0;
int was_set;
if (*dups_in_block)
- return 0;
+ goto out;
- /* does this need to be fatal? It appears e2fsck just ignores
- * the error. */
- err = o2fsck_strings_insert(strings, dirent->name, dirent->name_len,
- &was_set);
- if (err)
- fatal_error(err, "while allocating space to find duplicate "
- "directory entries");
+ ret = o2fsck_strings_insert(strings, dirent->name, dirent->name_len,
+ &was_set);
+ if (ret) {
+ com_err(whoami, ret, "while allocating space to find "
+ "duplicate directory entries");
+ goto out;
+ }
if (!was_set)
- return 0;
+ goto out;
- fprintf(stderr, "Duplicate directory entry '%.*s' found.\n",
- dirent->name_len, dirent->name);
- fprintf(stderr, "Marking its parent %"PRIu64" for rebuilding.\n",
+ printf("Duplicate directory entry '%.*s' found.\n",
+ dirent->name_len, dirent->name);
+ printf("Marking its parent %"PRIu64" for rebuilding.\n", dbe->e_ino);
+
+ ret = ocfs2_bitmap_set(ost->ost_rebuild_dirs, dbe->e_ino, &was_set);
+ if (ret)
+ com_err(whoami, ret, "while recording that inode %"PRIu64" "
+ "needs to have duplicate entries removed.",
dbe->e_ino);
- err = ocfs2_bitmap_test(ost->ost_rebuild_dirs, dbe->e_ino, &was_set);
- if (err)
- fatal_error(err, "while checking for inode %"PRIu64" in "
- "the used bitmap", dbe->e_ino);
-
*dups_in_block = 1;
- return 0;
+out:
+ return ret;
}
+static int corrupt_dirent(struct ocfs2_dir_entry *dirent, int left)
+{
+ if ((dirent->rec_len >= OCFS2_DIR_REC_LEN(1)) &&
+ ((dirent->rec_len & OCFS2_DIR_ROUND) == 0) &&
+ (dirent->rec_len <= left) &&
+ (OCFS2_DIR_REC_LEN(dirent->name_len) <= dirent->rec_len))
+ return 0;
+
+ return 1;
+}
+
/* this could certainly be more clever to issue reads in groups */
static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
void *priv_data)
{
struct dirblock_data *dd = priv_data;
struct ocfs2_dir_entry *dirent, *prev = NULL;
- unsigned int offset = 0, this_flags, ret_flags = 0;
+ unsigned int offset = 0, ret_flags = 0;
o2fsck_strings strings;
int dups_in_block = 0;
- errcode_t retval;
+ errcode_t ret;
if (!o2fsck_test_inode_allocated(dd->ost, dbe->e_ino)) {
printf("Directory block %"PRIu64" belongs to directory inode "
@@ -451,12 +481,11 @@
o2fsck_strings_init(&strings);
- retval = ocfs2_read_dir_block(dd->fs, dbe->e_blkno, dd->buf);
- if (retval && retval != OCFS2_ET_DIR_CORRUPTED) {
- /* XXX hum, ask to continue here. more a prompt than a
- * fix. need to expand problem.c's vocabulary. */
- fatal_error(retval, "while reading dir block %"PRIu64,
- dbe->e_blkno);
+ ret = ocfs2_read_dir_block(dd->fs, dbe->e_blkno, dd->buf);
+ if (ret && ret != OCFS2_ET_DIR_CORRUPTED) {
+ com_err(whoami, ret, "while reading dir block %"PRIu64,
+ dbe->e_blkno);
+ goto out;
}
verbosef("dir block %"PRIu64"\n", dbe->e_blkno);
@@ -472,24 +501,26 @@
/* XXX I wonder if we should be checking that the padding
* is 0 */
+ /* if we can't trust this dirent then fix it up or skip
+ * the whole block */
+ if (corrupt_dirent(dirent, dd->fs->fs_blocksize - offset)) {
+ if (!prompt(dd->ost, PY, 0, "Directory inode %"PRIu64" "
+ "corrupted in logical block %"PRIu64" "
+ "physical block %"PRIu64" offset %d. "
+ "Attempt to repair this block's directory "
+ "entries?", dbe->e_ino, dbe->e_blkcount,
+ dbe->e_blkno, offset))
+ break;
- /* first verify that we can trust the dirent's lengths
- * to navigate to the next in the block. This can try to
- * get rid of a broken dirent by trying to shift remaining
- * dirents into its place. The 'contiune' attempts to let
- * us recheck the current dirent.
- *
- * XXX this will have to do some swabbing as it tries
- * to salvage as read_dir_block stops swabbing
- * when it sees bad entries.
- */
- this_flags = fix_dirent_lengths(dd->ost, dbe, dirent, offset,
- dd->fs->fs_blocksize - offset,
- prev);
- ret_flags |= this_flags;
- if (this_flags & OCFS2_DIRENT_CHANGED)
+ /* we edit the dirent in place so we try to parse
+ * it again after fixing it */
+ fix_dirent_lengths(dirent,
+ dd->fs->fs_blocksize - offset,
+ prev, &ret_flags);
continue;
+ }
+
/*
* In general, these calls mark ->inode as 0 when they want it
* to be seen as deleted; ignored by fsck and reclaimed by the
@@ -499,29 +530,40 @@
*
* XXX should verify that ocfs2 reclaims entries like that.
*/
- ret_flags |= fix_dirent_dots(dd->ost, dbe, dirent, offset,
- dd->fs->fs_blocksize - offset);
+ ret = fix_dirent_dots(dd->ost, dbe, dirent, offset,
+ dd->fs->fs_blocksize - offset,
+ &ret_flags);
+ if (ret)
+ goto out;
if (dirent->inode == 0)
goto next;
- ret_flags |= fix_dirent_name(dd->ost, dbe, dirent, offset);
+ fix_dirent_name(dd->ost, dbe, dirent, offset, &ret_flags);
if (dirent->inode == 0)
goto next;
- ret_flags |= fix_dirent_inode(dd->ost, dbe, dirent, offset);
+ fix_dirent_inode(dd->ost, dbe, dirent, offset, &ret_flags);
if (dirent->inode == 0)
goto next;
- ret_flags |= fix_dirent_filetype(dd->ost, dbe, dirent, offset);
+ ret = fix_dirent_filetype(dd->ost, dbe, dirent, offset,
+ &ret_flags);
+ if (ret)
+ goto out;
if (dirent->inode == 0)
goto next;
- ret_flags |= fix_dirent_linkage(dd->ost, dbe, dirent, offset);
+ ret = fix_dirent_linkage(dd->ost, dbe, dirent, offset,
+ &ret_flags);
+ if (ret)
+ goto out;
if (dirent->inode == 0)
goto next;
- ret_flags |= fix_dirent_dups(dd->ost, dbe, dirent, &strings,
- &dups_in_block);
+ ret = fix_dirent_dups(dd->ost, dbe, dirent, &strings,
+ &dups_in_block, &ret_flags);
+ if (ret)
+ goto out;
if (dirent->inode == 0)
goto next;
@@ -534,16 +576,18 @@
}
if (ret_flags & OCFS2_DIRENT_CHANGED) {
- retval = ocfs2_write_dir_block(dd->fs, dbe->e_blkno, dd->buf);
- if (retval) {
- /* XXX hum, ask to continue here. more a prompt than a
- * fix. need to expand problem.c's vocabulary. */
- fatal_error(retval, "while writing dir block %"PRIu64,
- dbe->e_blkno);
+ ret = ocfs2_write_dir_block(dd->fs, dbe->e_blkno, dd->buf);
+ if (ret) {
+ com_err(whoami, ret, "while writing dir block %"PRIu64,
+ dbe->e_blkno);
+ dd->ost->ost_write_error = 1;
}
}
o2fsck_strings_free(&strings);
+out:
+ if (ret)
+ dd->ret = ret;
return ret_flags;
}
Modified: trunk/fsck.ocfs2/pass3.c
===================================================================
--- trunk/fsck.ocfs2/pass3.c 2004-12-04 20:38:44 UTC (rev 462)
+++ trunk/fsck.ocfs2/pass3.c 2004-12-05 01:28:04 UTC (rev 463)
@@ -118,9 +118,15 @@
* inode and the "." dirent in its dirblock */
o2fsck_icount_set(ost->ost_icount_in_inodes, blkno, 2);
o2fsck_icount_set(ost->ost_icount_refs, blkno, 2);
- o2fsck_add_dir_parent(&ost->ost_dir_parents, blkno,
- ost->ost_fs->fs_root_blkno,
- ost->ost_fs->fs_root_blkno);
+ ret = o2fsck_add_dir_parent(&ost->ost_dir_parents, blkno,
+ ost->ost_fs->fs_root_blkno,
+ ost->ost_fs->fs_root_blkno);
+ if (ret) {
+ com_err(whoami, ret, "while recording a new /lost+found "
+ "directory");
+ goto out;
+ }
+
/* we've already iterated through the dirblocks in pass2 so there
* is no need to register l+f's new dir block */
@@ -272,9 +278,11 @@
static uint64_t loop_no = 0;
-static void connect_directory(o2fsck_state *ost, o2fsck_dir_parent *dir)
+static errcode_t connect_directory(o2fsck_state *ost,
+ o2fsck_dir_parent *dir)
{
o2fsck_dir_parent *dp = dir, *par;
+ errcode_t ret = 0;
int fix;
verbosef("checking dir inode %"PRIu64" parent %"PRIu64" dot_dot "
@@ -294,10 +302,12 @@
if (dp->dp_dirent) {
par = o2fsck_dir_parent_lookup(&ost->ost_dir_parents,
dp->dp_dirent);
- if (par == NULL)
- fatal_error(OCFS2_ET_INTERNAL_FAILURE,
- "no dir info for parent "
- "%"PRIu64, dp->dp_dirent);
+ if (par == NULL) {
+ ret = OCFS2_ET_INTERNAL_FAILURE;
+ com_err(whoami, ret, "no dir info for parent "
+ "%"PRIu64, dp->dp_dirent);
+ goto out;
+ }
if (par->dp_loop_no != loop_no) {
par->dp_loop_no = loop_no;
dp = par;
@@ -327,11 +337,14 @@
if (fix)
fix_dot_dot(ost, dir);
}
+out:
+ return ret;
}
errcode_t o2fsck_pass3(o2fsck_state *ost)
{
o2fsck_dir_parent *dp;
+ errcode_t ret = 0;
printf("Pass 3: Checking directory connectivity.\n");
@@ -343,25 +356,33 @@
dp = o2fsck_dir_parent_lookup(&ost->ost_dir_parents,
ost->ost_fs->fs_root_blkno);
- if (dp == NULL)
- fatal_error(OCFS2_ET_INTERNAL_FAILURE, "root inode %"PRIu64" "
- "wasn't marked as a directory in pass1",
- ost->ost_fs->fs_root_blkno);
+ if (dp == NULL) {
+ ret = OCFS2_ET_INTERNAL_FAILURE;
+ com_err(whoami, ret, "root inode %"PRIu64" wasn't marked as "
+ "a directory in pass1", ost->ost_fs->fs_root_blkno);
+ goto out;
+ }
dp->dp_connected = 1;
dp = o2fsck_dir_parent_lookup(&ost->ost_dir_parents,
ost->ost_fs->fs_sysdir_blkno);
- if (dp == NULL)
- fatal_error(OCFS2_ET_INTERNAL_FAILURE, "system dir inode "
- "%"PRIu64" wasn't marked as a directory in "
- "pass1", ost->ost_fs->fs_sysdir_blkno);
+ if (dp == NULL) {
+ ret = OCFS2_ET_INTERNAL_FAILURE;
+ com_err(whoami, ret, "system dir inode %"PRIu64" wasn't "
+ "marked as a directory in pass1",
+ ost->ost_fs->fs_sysdir_blkno);
+ goto out;
+ }
dp->dp_connected = 1;
for(dp = o2fsck_dir_parent_first(&ost->ost_dir_parents) ;
dp; dp = o2fsck_dir_parent_next(dp)) {
/* XXX hmm, make sure dir->ino is in the dir map? */
- connect_directory(ost, dp);
+ ret = connect_directory(ost, dp);
+ if (ret)
+ goto out;
}
- return 0;
+out:
+ return ret;
}
More information about the Ocfs2-tools-commits
mailing list