[Ocfs2-tools-commits] zab commits r322 - in trunk: fsck.ocfs2
fsck.ocfs2/include libocfs2 libocfs2/include
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Thu Oct 7 18:19:05 CDT 2004
Author: zab
Date: 2004-10-07 18:19:04 -0500 (Thu, 07 Oct 2004)
New Revision: 322
Added:
trunk/fsck.ocfs2/include/pass4.h
trunk/fsck.ocfs2/pass4.c
Modified:
trunk/fsck.ocfs2/Makefile
trunk/fsck.ocfs2/fsck.c
trunk/fsck.ocfs2/icount.c
trunk/fsck.ocfs2/include/fsck.h
trunk/fsck.ocfs2/include/icount.h
trunk/fsck.ocfs2/include/pass3.h
trunk/fsck.ocfs2/pass2.c
trunk/fsck.ocfs2/pass3.c
trunk/libocfs2/bitmap.c
trunk/libocfs2/include/bitmap.h
trunk/libocfs2/include/ocfs2.h
Log:
o Add pass4: verify that i_links_count matches dirent references
o add ocfs2_bitmap_find_next_set()
o track inode references from directory entries
o add o2fsck_icount_get so pass4 can lookup the icount tracking :)
o flesh out reconnect_file a little more and export it
o fix lame bug in fix_dirent_filetype which didn't read into a full block
Modified: trunk/fsck.ocfs2/Makefile
===================================================================
--- trunk/fsck.ocfs2/Makefile 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/Makefile 2004-10-07 23:19:04 UTC (rev 322)
@@ -19,6 +19,7 @@
pass1.c \
pass2.c \
pass3.c \
+ pass4.c \
problem.c \
strings.c \
util.c
@@ -30,6 +31,7 @@
include/pass1.h \
include/pass2.h \
include/pass3.h \
+ include/pass4.h \
include/problem.h \
include/strings.h \
include/util.h
Modified: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/fsck.c 2004-10-07 23:19:04 UTC (rev 322)
@@ -37,6 +37,7 @@
#include "pass1.h"
#include "pass2.h"
#include "pass3.h"
+#include "pass4.h"
#include "util.h"
int verbose = 0;
@@ -271,6 +272,9 @@
if (ret)
com_err(argv[0], ret, "pass3 failed");
+ ret = o2fsck_pass4(ost);
+ if (ret)
+ com_err(argv[0], ret, "pass4 failed");
ret = ocfs2_close(ost->ost_fs);
if (ret) {
Modified: trunk/fsck.ocfs2/icount.c
===================================================================
--- trunk/fsck.ocfs2/icount.c 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/icount.c 2004-10-07 23:19:04 UTC (rev 322)
@@ -116,6 +116,22 @@
}
}
+uint16_t o2fsck_icount_get(o2fsck_icount *icount, uint64_t blkno)
+{
+ icount_node *in;
+ int was_set;
+
+ ocfs2_bitmap_test(icount->ic_single_bm, blkno, &was_set);
+ if (was_set)
+ return 1;
+
+ in = icount_search(icount, blkno);
+ if (in)
+ return in->in_icount;
+
+ return 0;
+}
+
/* again, simple before efficient. We just find the old value and
* use _set to make sure that the new value updates both the bitmap
* and the tree */
Modified: trunk/fsck.ocfs2/include/fsck.h
===================================================================
--- trunk/fsck.ocfs2/include/fsck.h 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/include/fsck.h 2004-10-07 23:19:04 UTC (rev 322)
@@ -40,7 +40,12 @@
ocfs2_bitmap *ost_rebuild_dirs;
+ /* This is no more than a cache of what we know the i_link_count
+ * in each inode to currently be. If an inode is marked in used_inodes
+ * this had better be up to date. */
o2fsck_icount *ost_icount_in_inodes;
+ /* this records references to each inode from other directory
+ * entries, including '.' and '..'. */
o2fsck_icount *ost_icount_refs;
o2fsck_dirblocks ost_dirblocks;
Modified: trunk/fsck.ocfs2/include/icount.h
===================================================================
--- trunk/fsck.ocfs2/include/icount.h 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/include/icount.h 2004-10-07 23:19:04 UTC (rev 322)
@@ -33,6 +33,7 @@
void 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);
void o2fsck_icount_delta(o2fsck_icount *icount, uint64_t blkno,
Modified: trunk/fsck.ocfs2/include/pass3.h
===================================================================
--- trunk/fsck.ocfs2/include/pass3.h 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/include/pass3.h 2004-10-07 23:19:04 UTC (rev 322)
@@ -27,6 +27,7 @@
#include "fsck.h"
errcode_t o2fsck_pass3(o2fsck_state *ost);
+void o2fsck_reconnect_file(o2fsck_state *ost, uint64_t inode);
#endif /* __O2FSCK_PASS3_H__ */
Added: trunk/fsck.ocfs2/include/pass4.h
===================================================================
--- trunk/fsck.ocfs2/include/pass4.h 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/include/pass4.h 2004-10-07 23:19:04 UTC (rev 322)
@@ -0,0 +1,32 @@
+/*
+ * pass4.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_PASS4_H__
+#define __O2FSCK_PASS4_H__
+
+#include "fsck.h"
+
+errcode_t o2fsck_pass4(o2fsck_state *ost);
+
+#endif /* __O2FSCK_PASS4_H__ */
+
Modified: trunk/fsck.ocfs2/pass2.c
===================================================================
--- trunk/fsck.ocfs2/pass2.c 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/pass2.c 2004-10-07 23:19:04 UTC (rev 322)
@@ -286,7 +286,8 @@
static int fix_dirent_filetype(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
struct ocfs2_dir_entry *dirent, int offset)
{
- ocfs2_dinode dinode;
+ char *buf;
+ ocfs2_dinode *dinode;
uint8_t expected_type;
errcode_t err;
int was_set;
@@ -311,12 +312,19 @@
goto check;
}
- err = ocfs2_read_inode(ost->ost_fs, dirent->inode, (char *)&dinode);
+ err = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf);
if (err)
+ fatal_error(err, "while allocating inode buffer to verify an "
+ "inode's file type");
+
+ err = ocfs2_read_inode(ost->ost_fs, dirent->inode, buf);
+ if (err)
fatal_error(err, "reading inode %"PRIu64" when verifying "
"an entry's file type", dirent->inode);
- expected_type = ocfs_type_by_mode[(dinode.i_mode & S_IFMT)>>S_SHIFT];
+ dinode = (ocfs2_dinode *)buf;
+ expected_type = ocfs_type_by_mode[(dinode->i_mode & S_IFMT)>>S_SHIFT];
+ ocfs2_free(&buf);
check:
/* XXX do we care to have expected 0 -> lead to "set" rather than
@@ -333,6 +341,7 @@
return OCFS2_DIRENT_CHANGED;
}
+
return 0;
}
@@ -509,6 +518,12 @@
ret_flags |= fix_dirent_dups(dd->ost, dbe, dirent, &strings,
&dups_in_block);
+ if (dirent->inode == 0)
+ goto next;
+
+ verbosef("dirent %.*s refs ino %"PRIu64"\n", dirent->name_len,
+ dirent->name, dirent->inode);
+ o2fsck_icount_delta(dd->ost->ost_icount_refs, dirent->inode, 1);
next:
offset += dirent->rec_len;
prev = dirent;
Modified: trunk/fsck.ocfs2/pass3.c
===================================================================
--- trunk/fsck.ocfs2/pass3.c 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/pass3.c 2004-10-07 23:19:04 UTC (rev 322)
@@ -61,6 +61,9 @@
/* XXX */
printf("I don't actually create anything yet..\n");
exit(FSCK_ERROR);
+
+ /* set both icount refs to 2. add dir info for it. put it
+ * in used, dir bitmaps. */
}
struct fix_dot_dot_args {
@@ -122,10 +125,22 @@
dir->dp_dot_dot = dir->dp_dirent;
}
-static int reconnect_file(o2fsck_state *ost, uint64_t inode)
+/* add a directory entry that points to a given inode in lost+found. */
+void o2fsck_reconnect_file(o2fsck_state *ost, uint64_t inode)
{
+ o2fsck_dir_parent *dp;
fatal_error(OCFS2_ET_INTERNAL_FAILURE, "not implemented yet");
- return 0;
+ /* up the icount ref */
+ dp = o2fsck_dir_parent_lookup(&ost->ost_dir_parents,
+ dp->dp_ino);
+ if (dp == NULL)
+ fatal_error(OCFS2_ET_INTERNAL_FAILURE,
+ "no dir parents for reconnected inode "
+ "%"PRIu64, dp->dp_ino);
+ dp->dp_dirent = 1/* XXX lost and found */;
+ fix_dot_dot(ost, dp);
+ /* XXX mark invalid if this fails */
+ return;
}
static uint64_t loop_no = 0;
@@ -169,20 +184,9 @@
fix = should_fix(ost, FIX_DEFYES, "directory inode %"PRIu64" "
"isn't connected to the filesystem. Move it "
"to lost+found?", dp->dp_ino);
- if (!fix)
- break;
- if (reconnect_file(ost, dp->dp_ino)) {
- /* XXX mark invalid */
- break;
- }
- dp = o2fsck_dir_parent_lookup(&ost->ost_dir_parents,
- dp->dp_ino);
- if (dp == NULL)
- fatal_error(OCFS2_ET_INTERNAL_FAILURE,
- "no dir parents for reconnected inode "
- "%"PRIu64, dp->dp_ino);
- dp->dp_dirent = 1/* XXX lost and found */;
- fix_dot_dot(ost, dp);
+ if (fix)
+ o2fsck_reconnect_file(ost, dp->dp_ino);
+
break;
}
Added: trunk/fsck.ocfs2/pass4.c
===================================================================
--- trunk/fsck.ocfs2/pass4.c 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/fsck.ocfs2/pass4.c 2004-10-07 23:19:04 UTC (rev 322)
@@ -0,0 +1,110 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * pass4.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 <inttypes.h>
+
+#include <ocfs2.h>
+
+#include "fsck.h"
+#include "icount.h"
+#include "pass3.h"
+#include "pass4.h"
+#include "problem.h"
+#include "util.h"
+
+errcode_t o2fsck_pass4(o2fsck_state *ost)
+{
+ uint64_t ino = 0;
+ uint16_t refs, in_inode;
+ ocfs2_dinode *di;
+ char *buf = NULL;
+ errcode_t err;
+
+ for (ino = 0;
+ ocfs2_bitmap_find_next_set(ost->ost_used_inodes, ino, &ino) != 0;
+ ino++) {
+ /*
+ * XXX e2fsck skips some inodes by their presence in other
+ * bitmaps. I think we should use this loop to verify their
+ * i_links_count as well and just make sure that we update refs
+ * to match our expectations in previous passes.
+ */
+
+ refs = o2fsck_icount_get(ost->ost_icount_refs, ino);
+ in_inode = o2fsck_icount_get(ost->ost_icount_in_inodes, ino);
+
+ verbosef("ino %"PRIu64", refs %u in %u\n", ino, refs,
+ in_inode);
+
+ if (refs == 0) {
+ /* XXX offer to remove files/dirs with no data? */
+ if (should_fix(ost, FIX_DEFYES, "Inode %"PRIu64" "
+ "isn't referenced by any directory "
+ "entries. Move it to lost+found?")) {
+ o2fsck_reconnect_file(ost, ino);
+ refs = o2fsck_icount_get(ost->ost_icount_refs,
+ ino);
+ }
+ }
+
+ if (refs == in_inode)
+ continue;
+
+ if (buf == NULL) {
+ err = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf);
+ if (err)
+ fatal_error(err, "while allocating inode "
+ "buffer to verify an inode's "
+ "link count");
+ }
+
+ err = ocfs2_read_inode(ost->ost_fs, ino, buf);
+ if (err)
+ fatal_error(err, "while reading inode %"PRIu64" to "
+ "verify its link count", ino);
+
+ di = (ocfs2_dinode *)buf;
+
+ if (in_inode != di->i_links_count)
+ fatal_error(OCFS2_ET_INTERNAL_FAILURE,
+ "fsck's thinks inode %"PRIu64" has a link "
+ "count of %"PRIu16" but on disk it is "
+ "%"PRIu16, ino, in_inode,
+ di->i_links_count);
+
+ if (should_fix(ost, FIX_DEFYES, "Inode %"PRIu64" has a link "
+ "count of %"PRIu16" on disk but directory "
+ "entry references come to %"PRIu16", update "
+ "the count on disk to match?", ino,
+ in_inode, refs)) {
+ di->i_links_count = refs;
+ o2fsck_icount_set(ost->ost_icount_in_inodes, ino,
+ refs);
+ o2fsck_write_inode(ost->ost_fs, ino, di);
+ }
+ }
+
+ return 0;
+}
Modified: trunk/libocfs2/bitmap.c
===================================================================
--- trunk/libocfs2/bitmap.c 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/libocfs2/bitmap.c 2004-10-07 23:19:04 UTC (rev 322)
@@ -118,6 +118,12 @@
return ret;
}
+int ocfs2_bitmap_find_next_set(ocfs2_bitmap *bitmap, uint64_t start,
+ uint64_t *found)
+{
+ return (*bitmap->b_ops->find_next_set)(bitmap, start, found);
+}
+
uint64_t ocfs2_bitmap_get_set_bits(ocfs2_bitmap *bitmap)
{
return bitmap->b_set_bits;
@@ -293,18 +299,28 @@
return 0;
}
-/* Find a bitmap cluster in the tree that intersects the bit region
- * that is passed in. The rb_node garbage lets insertion share this
- * searching code, most trivial callers will pass in NULLs. */
+/*
+ * Find a bitmap cluster in the tree that intersects the bit region
+ * that is passed in.
+ *
+ * _p and _parent are set so that callers can use rb_link_node and
+ * rb_insert_color to insert a node after finding that their bit
+ * wasn't found.
+ *
+ * _next is only used if a bitmap_cluster isn't found. it is set
+ * to the next node in the tree greater than the bitmap range
+ * that was searched.
+ */
static
struct ocfs2_bitmap_cluster *ocfs2_bitmap_lookup(ocfs2_bitmap *bitmap,
uint64_t bitno,
uint64_t total_bits,
struct rb_node ***ret_p,
- struct rb_node **ret_parent)
+ struct rb_node **ret_parent,
+ struct rb_node **ret_next)
{
struct rb_node **p = &bitmap->b_clusters.rb_node;
- struct rb_node *parent = NULL;
+ struct rb_node *parent = NULL, *last_left = NULL;
struct ocfs2_bitmap_cluster *bc = NULL;
while (*p)
@@ -314,6 +330,7 @@
if (bitno + total_bits <= bc->bc_start_bit) {
p = &(*p)->rb_left;
+ last_left = *p;
bc = NULL;
} else if (bitno >= (bc->bc_start_bit + bc->bc_total_bits)) {
p = &(*p)->rb_right;
@@ -325,6 +342,8 @@
*ret_p = p;
if (ret_parent != NULL)
*ret_parent = parent;
+ if (bc == NULL && ret_next != NULL)
+ *ret_next = last_left;
return bc;
}
@@ -339,7 +358,7 @@
/* we shouldn't find an existing cluster that intersects our new one */
bc_tmp = ocfs2_bitmap_lookup(bitmap, bc->bc_start_bit,
- bc->bc_total_bits, &p, &parent);
+ bc->bc_total_bits, &p, &parent, NULL);
if (bc_tmp)
return OCFS2_ET_INVALID_BIT;
@@ -374,7 +393,7 @@
struct ocfs2_bitmap_cluster *bc;
int old_tmp;
- bc = ocfs2_bitmap_lookup(bitmap, bitno, 1, NULL, NULL);
+ bc = ocfs2_bitmap_lookup(bitmap, bitno, 1, NULL, NULL, NULL);
if (!bc)
return OCFS2_ET_INVALID_BIT;
@@ -395,7 +414,7 @@
struct ocfs2_bitmap_cluster *bc;
int old_tmp;
- bc = ocfs2_bitmap_lookup(bitmap, bitno, 1, NULL, NULL);
+ bc = ocfs2_bitmap_lookup(bitmap, bitno, 1, NULL, NULL, NULL);
if (!bc)
return OCFS2_ET_INVALID_BIT;
@@ -415,7 +434,7 @@
{
struct ocfs2_bitmap_cluster *bc;
- bc = ocfs2_bitmap_lookup(bitmap, bitno, 1, NULL, NULL);
+ bc = ocfs2_bitmap_lookup(bitmap, bitno, 1, NULL, NULL, NULL);
if (!bc)
return OCFS2_ET_INVALID_BIT;
@@ -424,7 +443,38 @@
return 0;
}
+static int ocfs2_bitmap_find_next_set_generic(ocfs2_bitmap *bitmap,
+ uint64_t start, uint64_t *found)
+{
+ struct ocfs2_bitmap_cluster *bc;
+ struct rb_node *node = NULL;
+ int offset, ret;
+ /* start from either the node whose's bc contains the bit or
+ * the next greatest node in the tree */
+ bc = ocfs2_bitmap_lookup(bitmap, start, 1, NULL, NULL, &node);
+ if (bc)
+ node = &bc->bc_node;
+
+ for (; node != NULL; node = rb_next(node)) {
+ bc = rb_entry(node, struct ocfs2_bitmap_cluster, bc_node);
+
+ if (start > bc->bc_start_bit)
+ offset = start - bc->bc_start_bit;
+ else
+ offset = 0;
+
+ ret = ocfs2_find_next_bit_set(bc->bc_bitmap, bc->bc_total_bits,
+ offset);
+ if (ret != bc->bc_total_bits) {
+ *found = bc->bc_start_bit + ret;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/*
* Helper functions for a bitmap with holes in it.
* If a bit doesn't have memory allocated for it, we allocate.
@@ -476,10 +526,17 @@
return 0;
}
+static int ocfs2_bitmap_find_next_set_holes(ocfs2_bitmap *bitmap,
+ uint64_t start, uint64_t *found)
+{
+ return ocfs2_bitmap_find_next_set_generic(bitmap, start, found);
+}
+
static struct ocfs2_bitmap_operations global_cluster_ops = {
.set_bit = ocfs2_bitmap_set_generic,
.clear_bit = ocfs2_bitmap_clear_generic,
- .test_bit = ocfs2_bitmap_test_generic
+ .test_bit = ocfs2_bitmap_test_generic,
+ .find_next_set = ocfs2_bitmap_find_next_set_generic,
};
errcode_t ocfs2_cluster_bitmap_new(ocfs2_filesys *fs,
@@ -536,7 +593,8 @@
static struct ocfs2_bitmap_operations global_block_ops = {
.set_bit = ocfs2_bitmap_set_holes,
.clear_bit = ocfs2_bitmap_clear_holes,
- .test_bit = ocfs2_bitmap_test_holes
+ .test_bit = ocfs2_bitmap_test_holes,
+ .find_next_set = ocfs2_bitmap_find_next_set_holes,
};
errcode_t ocfs2_block_bitmap_new(ocfs2_filesys *fs,
Modified: trunk/libocfs2/include/bitmap.h
===================================================================
--- trunk/libocfs2/include/bitmap.h 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/libocfs2/include/bitmap.h 2004-10-07 23:19:04 UTC (rev 322)
@@ -50,6 +50,8 @@
int *oldval);
errcode_t (*test_bit)(ocfs2_bitmap *bm, uint64_t bit,
int *val);
+ int (*find_next_set)(ocfs2_bitmap *bm, uint64_t start,
+ uint64_t *found);
errcode_t (*merge_cluster)(ocfs2_bitmap *bm,
struct ocfs2_bitmap_cluster *prev,
struct ocfs2_bitmap_cluster *next);
Modified: trunk/libocfs2/include/ocfs2.h
===================================================================
--- trunk/libocfs2/include/ocfs2.h 2004-10-07 21:26:18 UTC (rev 321)
+++ trunk/libocfs2/include/ocfs2.h 2004-10-07 23:19:04 UTC (rev 322)
@@ -360,6 +360,8 @@
int *oldval);
errcode_t ocfs2_bitmap_test(ocfs2_bitmap *bitmap, uint64_t bitno,
int *val);
+int ocfs2_bitmap_find_next_set(ocfs2_bitmap *bitmap, uint64_t start,
+ uint64_t *found);
uint64_t ocfs2_bitmap_get_set_bits(ocfs2_bitmap *bitmap);
errcode_t ocfs2_get_device_size(const char *file, int blocksize,
More information about the Ocfs2-tools-commits
mailing list