[Ocfs2-tools-commits] zab commits r368 - in trunk: fsck.ocfs2
fsck.ocfs2/include libocfs2 libocfs2/include
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Fri Nov 5 22:54:14 CST 2004
Author: zab
Date: 2004-11-05 22:54:12 -0600 (Fri, 05 Nov 2004)
New Revision: 368
Modified:
trunk/fsck.ocfs2/Makefile
trunk/fsck.ocfs2/fsck.c
trunk/fsck.ocfs2/include/fsck.h
trunk/fsck.ocfs2/include/pass2.h
trunk/fsck.ocfs2/pass0.c
trunk/fsck.ocfs2/pass1.c
trunk/fsck.ocfs2/pass2.c
trunk/fsck.ocfs2/pass3.c
trunk/fsck.ocfs2/pass4.c
trunk/libocfs2/Makefile
trunk/libocfs2/alloc.c
trunk/libocfs2/bitmap.c
trunk/libocfs2/chainalloc.c
trunk/libocfs2/include/bitmap.h
trunk/libocfs2/include/ocfs2.h
trunk/libocfs2/openfs.c
Log:
o add a lib helper to test the lib's in-memory allocators for a given inode
o read each node's allocator into memory late in pass0 after checking it
o sync each inode's bit in the allocators as it is iterated over in pass 1
o ask to write back chain allocators if we change them during pass 1
o after pass1 trust the lib to manage the chain allocators
o do pass4 with iteration and the allocators instead of fsck's redundant bitmap
o only use -O when building with debugging to make life suck less
o bring each node's allocator into ocfs2_filesys when needed
o add ocfs2_bitmap_foreach_region so chainalloc can iterate when writing
o add a bit_change_notify bitmap callback so chainalloc can keep counts in sync
o free the group descs when we free chain alloc's region private
o track dirty groups and inodes in chainalloc and write them when asked
Modified: trunk/fsck.ocfs2/Makefile
===================================================================
--- trunk/fsck.ocfs2/Makefile 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/Makefile 2004-11-06 04:54:12 UTC (rev 368)
@@ -7,8 +7,13 @@
INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include
LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
-# -O2 to get uninitialized warnings from gcc.
-CFLAGS := -O2 -g -Wall -Wstrict-prototypes -Wmissing-prototypes \
+ifdef OCFS_DEBUG
+OPTS += -O -g
+else
+OPTS += -O2
+endif
+
+CFLAGS := $(OPTS) -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wmissing-declarations
DEFINES = -DOCFS2_FLAT_INCLUDES
Modified: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/fsck.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -114,13 +114,6 @@
return ret;
}
- ret = ocfs2_block_bitmap_new(fs, "inodes in use",
- &ost->ost_used_inodes);
- if (ret) {
- com_err(whoami, ret, "while allocating used inodes bitmap");
- return ret;
- }
-
ret = ocfs2_block_bitmap_new(fs, "inodes with bad fields",
&ost->ost_bad_inodes);
if (ret) {
Modified: trunk/fsck.ocfs2/include/fsck.h
===================================================================
--- trunk/fsck.ocfs2/include/fsck.h 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/include/fsck.h 2004-11-06 04:54:12 UTC (rev 368)
@@ -30,7 +30,9 @@
typedef struct _o2fsck_state {
ocfs2_filesys *ost_fs;
- ocfs2_bitmap *ost_used_inodes;
+ ocfs2_cached_inode *ost_global_inode_alloc;
+ ocfs2_cached_inode **ost_inode_allocs;
+
ocfs2_bitmap *ost_bad_inodes;
ocfs2_bitmap *ost_dir_inodes;
ocfs2_bitmap *ost_reg_inodes;
@@ -52,10 +54,11 @@
struct rb_root ost_dir_parents;
- /* flags */
unsigned ost_ask:1, /* confirm with the user */
ost_answer:1, /* answer if we don't ask the user */
- ost_force:1; /* -f supplied; force check */
+ ost_force:1, /* -f supplied; force check */
+ ost_write_inode_alloc_asked:1,
+ ost_write_inode_alloc:1;
} o2fsck_state;
/* The idea is to let someone off-site run fsck and have it give us
Modified: trunk/fsck.ocfs2/include/pass2.h
===================================================================
--- trunk/fsck.ocfs2/include/pass2.h 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/include/pass2.h 2004-11-06 04:54:12 UTC (rev 368)
@@ -27,6 +27,7 @@
#include "fsck.h"
errcode_t o2fsck_pass2(o2fsck_state *ost);
+int o2fsck_test_inode_allocated(o2fsck_state *ost, uint64_t blkno);
#endif /* __O2FSCK_PASS2_H__ */
Modified: trunk/fsck.ocfs2/pass0.c
===================================================================
--- trunk/fsck.ocfs2/pass0.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/pass0.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -34,6 +34,7 @@
* track used blocks that iteration won't see?
* verify more inode fields?
* use prompt to mark soft errors
+ * make sure blocks don't overlap as part of cluster tracking
*/
#include <string.h>
@@ -396,6 +397,8 @@
char *blocks = NULL;
ocfs2_dinode *di = NULL;
ocfs2_filesys *fs = ost->ost_fs;
+ ocfs2_cached_inode **ci;
+ int max_nodes = OCFS2_RAW_SB(fs->fs_super)->s_max_nodes;
int i, type;
printf("Pass 0: Checking allocation structures\n");
@@ -407,12 +410,18 @@
}
di = (ocfs2_dinode *)blocks;
+ ret = ocfs2_malloc0(max_nodes * sizeof(ocfs2_cached_inode *),
+ &ost->ost_inode_allocs);
+ if (ret)
+ fatal_error(ret, "while allocating pointers for each nodes' "
+ "inode allocator bitmaps");
+
/* first the global inode alloc and then each of the node's
* inode allocators */
type = GLOBAL_INODE_ALLOC_SYSTEM_INODE;
i = -1;
- do {
+ for ( ; i < max_nodes; i++, type = INODE_ALLOC_SYSTEM_INODE) {
ret = ocfs2_lookup_system_inode(fs, type, i, &blkno);
if (ret) {
com_err(whoami, ret, "while looking up the inode "
@@ -439,9 +448,28 @@
if (ret)
goto out;
- type = INODE_ALLOC_SYSTEM_INODE;
- } while (++i < OCFS2_RAW_SB(fs->fs_super)->s_max_nodes);
+ if (i == -1)
+ ci = &ost->ost_global_inode_alloc;
+ else
+ ci = &ost->ost_inode_allocs[i];
+ ret = ocfs2_read_cached_inode(ost->ost_fs, blkno, ci);
+ if (ret) {
+ com_err(whoami, ret, "while reading node %d's inode "
+ "allocator inode %"PRIu64, i, blkno);
+ continue;
+ }
+
+ ret = ocfs2_load_chain_allocator(ost->ost_fs, *ci);
+ if (ret) {
+ com_err(whoami, ret, "while loading inode %"PRIu64" "
+ "as a chain allocator", blkno);
+ ocfs2_free_cached_inode(ost->ost_fs, *ci);
+ *ci = NULL;
+ continue;
+ }
+ }
+
out:
/* errors are only returned to this guy if they're fatal -- memory
* alloc or IO errors. the.. returnee had the responsibility of
Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/pass1.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -1,10 +1,6 @@
/* -*- mode: c; c-basic-offset: 8; -*-
* vim: noexpandtab sw=8 ts=8 sts=0:
*
- * pass1.c
- *
- * file system checker for OCFS2
- *
* Copyright (C) 2004 Oracle. All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -21,7 +17,8 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*
- * Authors: Zach Brown
+ * XXX
+ * make sure the inode's dtime/count/valid match in update_inode_alloc
*/
#include <string.h>
#include <inttypes.h>
@@ -52,13 +49,112 @@
return was_set;
}
-/* XXX should walk down all the i_fields to make sure we're veryfying
+/* update our in memory images of the inode chain alloc bitmaps. these
+ * will be written out at the end of pass1 and the library will read
+ * them off disk for use from then on.
+ *
+ * XXX this returns errors because inode iteration can return inode numbers
+ * that cause errors when given to the chain alloc bitmaps. I'm sure its
+ * easy to fix. */
+static void update_inode_alloc(o2fsck_state *ost, ocfs2_dinode *di,
+ uint64_t blkno, int val)
+{
+ uint16_t node, max_nodes, yn;
+ errcode_t ret = OCFS2_ET_INTERNAL_FAILURE;
+ ocfs2_cached_inode *cinode;
+ int oldval;
+
+ val = !!val;
+
+ /* XXX we could skip all this if we're not going to write it out
+ * anyway */
+
+ max_nodes = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes;
+
+ verbosef("updating inode %"PRIu64" alloc to %d\n", blkno, val);
+
+ for (node = ~0; node != max_nodes; node++,
+ ret = OCFS2_ET_INTERNAL_FAILURE) {
+
+ if (node == (uint16_t)~0)
+ cinode = ost->ost_global_inode_alloc;
+ else
+ cinode = ost->ost_inode_allocs[node];
+
+ /* we might have had trouble reading the chains in pass 0 */
+ if (cinode == NULL)
+ continue;
+
+ if (val)
+ ret = ocfs2_bitmap_set(cinode->ci_chains, blkno,
+ &oldval);
+ else
+ ret = ocfs2_bitmap_clear(cinode->ci_chains, blkno,
+ &oldval);
+
+ com_err(whoami, ret, "node %"PRIu16, node);
+
+ if (ret) {
+ if (ret != OCFS2_ET_INVALID_BIT)
+ com_err(whoami, ret, "while trying to set "
+ "inode %"PRIu64"'s allocation to '%d' "
+ "in node %u's chain", blkno, val,
+ node);
+ continue;
+ }
+
+ /* this node covers the inode. see if we've changed the
+ * bitmap and if the user wants us to keep tracking it and
+ * write back the new map */
+ if (oldval != val && !ost->ost_write_inode_alloc_asked) {
+ yn = prompt(ost, PY, "fsck found an inode whose "
+ "allocation does not match the chain "
+ "allocators. Fix the allocation of this "
+ "and all future inodes?");
+ ost->ost_write_inode_alloc_asked = 1;
+ ost->ost_write_inode_alloc = !!yn;
+ }
+ break;
+ }
+
+ if (ret) {
+ com_err(whoami, ret, "while trying to set inode %"PRIu64"'s "
+ "allocation to '%d'. None of the nodes chain "
+ "allocator's had a group covering the inode.",
+ blkno, val);
+ goto out;
+ }
+
+ verbosef("updated inode %"PRIu64" alloc to %d in node %"PRIu16"\n",
+ blkno, val, node);
+
+ /* make sure the inode's fields are consistent if it's allocated */
+ if (val == 1 && node != (uint16_t)di->i_suballoc_node &&
+ prompt(ost, PY, "Inode %"PRIu64" indicates that it was allocated "
+ "from node %"PRIu16" but node %"PRIu16"'s chain allocator "
+ "covers the inode. Fix the inode's record of where it is "
+ "allocated?",
+ blkno, di->i_suballoc_node, node)) {
+ di->i_suballoc_node = node;
+ o2fsck_write_inode(ost->ost_fs, di->i_blkno, di);
+ }
+out:
+ return;
+}
+
+/* Check the basics of the ocfs2_dinode itself. If we find problems
+ * we clear the VALID flag and the caller will see that and update
+ * inode allocations and write the inode to disk.
+ *
+ * XXX should walk down all the i_fields to make sure we're veryfying
* those that we can this early */
static void o2fsck_verify_inode_fields(ocfs2_filesys *fs, o2fsck_state *ost,
uint64_t blkno, ocfs2_dinode *di)
{
- int was_set;
+ int clear = 0;
+ verbosef("checking inode %"PRIu64"'s fields\n", blkno);
+
/* do we want to detect and delete corrupt system dir/files here
* so we can recreate them later ? */
@@ -70,11 +166,12 @@
* in use? orphaned? deleted? garbage?) to understand what
* fsck can do to fix it up */
if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
- strlen(OCFS2_INODE_SIGNATURE))) {
- goto bad;
+ strlen(OCFS2_INODE_SIGNATURE)) &&
+ prompt(ost, PY, "Inode %"PRIu64" doesn't have a valid signature. "
+ "Clear it?", blkno)) {
+ clear = 1;
+ goto out;
}
- if (di->i_flags & OCFS2_SUPER_BLOCK_FL)
- goto bad;
if (di->i_links_count)
o2fsck_icount_set(ost->ost_icount_in_inodes, di->i_blkno,
@@ -100,12 +197,6 @@
o2fsck_write_inode(fs, blkno, di);
}
- ocfs2_bitmap_set(ost->ost_used_inodes, blkno, &was_set);
- if (was_set) {
- fprintf(stderr, "duplicate inode %"PRIu64"?\n", blkno);
- goto bad;
- }
-
if (S_ISDIR(di->i_mode)) {
ocfs2_bitmap_set(ost->ost_dir_inodes, blkno, NULL);
o2fsck_add_dir_parent(&ost->ost_dir_parents, blkno, 0, 0);
@@ -117,16 +208,19 @@
* we walk the inode's blocks */
} else {
if (!S_ISCHR(di->i_mode) && !S_ISBLK(di->i_mode) &&
- !S_ISFIFO(di->i_mode) && !S_ISSOCK(di->i_mode))
- goto bad;
+ !S_ISFIFO(di->i_mode) && !S_ISSOCK(di->i_mode)) {
+ clear = 1;
+ goto out;
+ }
/* i_size? what other sanity testing for devices? */
}
- return;
-bad:
- /* XXX we don't actually do anything with this bitmap */
- ocfs2_bitmap_set(ost->ost_bad_inodes, blkno, NULL);
+out:
+ if (clear) {
+ di->i_flags &= ~OCFS2_SUPER_BLOCK_FL;
+ o2fsck_write_inode(fs, blkno, di);
+ }
}
struct verifying_blocks {
@@ -389,6 +483,41 @@
}
}
+static void write_inode_alloc(o2fsck_state *ost)
+{
+ int max_nodes = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes;
+ ocfs2_cached_inode **ci;
+ errcode_t ret;
+ int i = -1;
+
+ if (!ost->ost_write_inode_alloc)
+ return;
+
+ for ( ; i < max_nodes; i++) {
+ if (i == -1)
+ ci = &ost->ost_global_inode_alloc;
+ else
+ ci = &ost->ost_inode_allocs[i];
+
+ if (*ci == NULL)
+ continue;
+
+ verbosef("writing node %d's allocator\n", i);
+
+ ret = ocfs2_write_chain_allocator(ost->ost_fs, *ci);
+ if (ret)
+ com_err(whoami, ret, "while trying to write back node "
+ "%d's inode allocator", i);
+
+ ret = ocfs2_free_cached_inode(ost->ost_fs, *ci);
+ if (ret)
+ com_err(whoami, ret, "while trying to free node %d's "
+ "inode allocator", i);
+
+ *ci = NULL;
+ }
+}
+
errcode_t o2fsck_pass1(o2fsck_state *ost)
{
errcode_t ret;
@@ -431,23 +560,26 @@
break;
/* scanners have to skip over uninitialized inodes */
- if (!(di->i_flags & OCFS2_VALID_FL))
- continue;
+ if (di->i_flags & OCFS2_VALID_FL) {
+ o2fsck_verify_inode_fields(fs, ost, blkno, di);
- verbosef("found inode %"PRIu64"\n", blkno);
+ /* XXX be able to mark the blocks in the inode as
+ * bad if the inode was bad */
+ o2fsck_check_blocks(fs, ost, blkno, di);
+ }
- o2fsck_verify_inode_fields(fs, ost, blkno, di);
-
- /* XXX be able to mark the blocks in the inode as
- * bad if the inode was bad */
-
- o2fsck_check_blocks(fs, ost, blkno, di);
+ verbosef("blkno %"PRIu64" ino %"PRIu64"\n", blkno,
+ di->i_blkno);
+ update_inode_alloc(ost, di, blkno,
+ di->i_flags & OCFS2_VALID_FL);
}
if (ocfs2_bitmap_get_set_bits(ost->ost_dup_blocks))
fatal_error(OCFS2_ET_INTERNAL_FAILURE, "duplicate blocks "
"found, need to learn to fix.");
+ write_inode_alloc(ost);
+
out_close_scan:
ocfs2_close_inode_scan(scan);
out_free:
Modified: trunk/fsck.ocfs2/pass2.c
===================================================================
--- trunk/fsck.ocfs2/pass2.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/pass2.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -37,6 +37,23 @@
#include "strings.h"
#include "util.h"
+static const char *whoami = "pass2";
+
+int o2fsck_test_inode_allocated(o2fsck_state *ost, uint64_t blkno)
+{
+ errcode_t ret;
+ int was_set;
+
+ ret = ocfs2_test_inode_allocated(ost->ost_fs, blkno, &was_set);
+ /* XXX this should stop fsck from marking the fs clean */
+ if (ret) {
+ com_err(whoami, ret, "while testing if inode %"PRIu64" is "
+ "allocated. Continuing as though it is.", blkno);
+ was_set = 1;
+ }
+ return was_set;
+}
+
struct dirblock_data {
o2fsck_state *ost;
ocfs2_filesys *fs;
@@ -232,8 +249,6 @@
static int fix_dirent_inode(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
struct ocfs2_dir_entry *dirent, int offset)
{
- int was_set;
-
if (ocfs2_block_out_of_range(ost->ost_fs, dirent->inode)) {
if (prompt(ost, PY, "Directory entry '%.*s' refers to inode "
"number %"PRIu64" which is out of range, "
@@ -244,16 +259,12 @@
}
}
- /* XXX Do I care about possible bitmap_test errors here? */
- ocfs2_bitmap_test(ost->ost_used_inodes, dirent->inode, &was_set);
- if (!was_set) {
- if (prompt(ost, PY, "Directory entry '%.*s' refers to inode "
- "number %"PRIu64" which is unused, clear the "
- "entry?", dirent->name_len, dirent->name,
- dirent->inode)) {
- dirent->inode = 0;
- return OCFS2_DIRENT_CHANGED;
- }
+ if (!o2fsck_test_inode_allocated(ost, dbe->e_ino) &&
+ prompt(ost, PY, "Directory entry '%.*s' refers to inode number "
+ "%"PRIu64" which isn't allocated, clear the entry?",
+ dirent->name_len, dirent->name, dirent->inode)) {
+ dirent->inode = 0;
+ return OCFS2_DIRENT_CHANGED;
}
return 0;
}
@@ -421,8 +432,6 @@
return 0;
}
-
-
/* this could certainly be more clever to issue reads in groups */
static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
void *priv_data)
@@ -431,16 +440,15 @@
struct ocfs2_dir_entry *dirent, *prev = NULL;
unsigned int offset = 0, this_flags, ret_flags = 0;
o2fsck_strings strings;
- int was_set, dups_in_block = 0;
+ int dups_in_block = 0;
errcode_t retval;
- retval = ocfs2_bitmap_test(dd->ost->ost_used_inodes, dbe->e_ino,
- &was_set);
- if (retval)
- fatal_error(retval, "while checking for inode %"PRIu64" in "
- "the used bitmap", dbe->e_ino);
- if (!was_set)
+ if (!o2fsck_test_inode_allocated(dd->ost, dbe->e_ino)) {
+ printf("Directory block %"PRIu64" belongs to directory inode "
+ "%"PRIu64" which isn't allocated. Ignoring this "
+ "block.", dbe->e_blkno, dbe->e_ino);
return 0;
+ }
o2fsck_strings_init(&strings);
Modified: trunk/fsck.ocfs2/pass3.c
===================================================================
--- trunk/fsck.ocfs2/pass3.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/pass3.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -30,6 +30,7 @@
#include "dirparents.h"
#include "fsck.h"
+#include "pass2.h"
#include "pass3.h"
#include "problem.h"
#include "util.h"
@@ -38,9 +39,7 @@
{
int was_set;
- ocfs2_bitmap_test(ost->ost_used_inodes, ost->ost_fs->fs_root_blkno,
- &was_set);
- if (was_set) {
+ if (o2fsck_test_inode_allocated(ost, ost->ost_fs->fs_root_blkno)) {
ocfs2_bitmap_test(ost->ost_dir_inodes,
ost->ost_fs->fs_root_blkno, &was_set);
if (!was_set) {
Modified: trunk/fsck.ocfs2/pass4.c
===================================================================
--- trunk/fsck.ocfs2/pass4.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/fsck.ocfs2/pass4.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -1,10 +1,6 @@
/* -*- 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
@@ -21,7 +17,6 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*
- * Authors: Zach Brown
*/
#include <inttypes.h>
@@ -34,78 +29,100 @@
#include "problem.h"
#include "util.h"
+static const char *whoami = "pass4";
+
+static errcode_t check_link_counts(o2fsck_state *ost, ocfs2_dinode *di)
+{
+ uint16_t refs, in_inode;
+
+ refs = o2fsck_icount_get(ost->ost_icount_refs, di->i_blkno);
+ in_inode = o2fsck_icount_get(ost->ost_icount_in_inodes, di->i_blkno);
+
+ verbosef("ino %"PRIu64", refs %u in %u\n", di->i_blkno, refs,
+ in_inode);
+
+ /* XXX offer to remove files/dirs with no data? */
+ if (refs == 0 &&
+ prompt(ost, PY, "Inode %"PRIu64" isn't referenced by any "
+ "directory entries. Move it to lost+found?",
+ di->i_blkno)) {
+ o2fsck_reconnect_file(ost, di->i_blkno);
+ refs = o2fsck_icount_get(ost->ost_icount_refs, di->i_blkno);
+ }
+
+ if (refs == in_inode)
+ goto out;
+
+ if (in_inode != di->i_links_count)
+ com_err(whoami, OCFS2_ET_INTERNAL_FAILURE, "fsck's thinks "
+ "inode %"PRIu64" has a link count of %"PRIu16" but on "
+ "disk it is %"PRIu16, di->i_blkno, in_inode,
+ di->i_links_count);
+
+ if (prompt(ost, PY, "Inode %"PRIu64" has a link count of %"PRIu16" on "
+ "disk but directory entry references come to %"PRIu16". "
+ "Update the count on disk to match?", di->i_blkno, in_inode,
+ refs)) {
+ di->i_links_count = refs;
+ o2fsck_icount_set(ost->ost_icount_in_inodes, di->i_blkno,
+ refs);
+ o2fsck_write_inode(ost->ost_fs, di->i_blkno, di);
+ }
+
+out:
+ return 0;
+}
+
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;
+ errcode_t ret;
+ ocfs2_inode_scan *scan;
+ uint64_t blkno;
printf("Pass 4: Checking inodes link counts.\n");
- 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.
- */
+ ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf);
+ if (ret) {
+ com_err(whoami, ret, "while allocating space to read inodes");
+ goto out;
+ }
- refs = o2fsck_icount_get(ost->ost_icount_refs, ino);
- in_inode = o2fsck_icount_get(ost->ost_icount_in_inodes, ino);
+ di = (ocfs2_dinode *)buf;
- verbosef("ino %"PRIu64", refs %u in %u\n", ino, refs,
- in_inode);
+ ret = ocfs2_open_inode_scan(ost->ost_fs, &scan);
+ if (ret) {
+ com_err(whoami, ret,
+ "while opening inode scan");
+ goto out_free;
+ }
- if (refs == 0) {
- /* XXX offer to remove files/dirs with no data? */
- if (prompt(ost, PY, "Inode %"PRIu64" isn't referenced "
- "by any directory entries. Move it to "
- "lost+found?", ino)) {
- o2fsck_reconnect_file(ost, ino);
- refs = o2fsck_icount_get(ost->ost_icount_refs,
- ino);
- }
+ for(;;) {
+ ret = ocfs2_get_next_inode(scan, &blkno, buf);
+ if (ret) {
+ com_err(whoami, ret, "while reading next inode");
+ break;
}
+ if (blkno == 0)
+ break;
- if (refs == in_inode)
+ if (!(di->i_flags & OCFS2_VALID_FL))
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");
- }
+ /*
+ * 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.
+ */
- 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 (prompt(ost, PY, "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);
- }
+ check_link_counts(ost, di);
}
- return 0;
+ ocfs2_close_inode_scan(scan);
+out_free:
+ ocfs2_free(&buf);
+out:
+ return ret;
}
Modified: trunk/libocfs2/Makefile
===================================================================
--- trunk/libocfs2/Makefile 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/libocfs2/Makefile 2004-11-06 04:54:12 UTC (rev 368)
@@ -6,7 +6,9 @@
-Wmissing-declarations
ifdef OCFS_DEBUG
-OPTS += -g
+OPTS += -O -g
+else
+OPTS += -O2
endif
INCLUDES = -Iinclude
@@ -16,10 +18,6 @@
CFLAGS = $(OPTS) $(WARNINGS) -fPIC
CPPFLAGS += -DOCFS2_FLAT_INCLUDES
-OPTIMIZE = -O2
-
-CFLAGS += $(OPTIMIZE)
-
ifneq ($(OCFS2_DEBUG_EXE),)
DEBUG_EXE_FILES = $(shell awk '/DEBUG_EXE/{if (k[FILENAME] == 0) {print FILENAME; k[FILENAME] = 1;}}' $(CFILES))
DEBUG_EXE_PROGRAMS = $(addprefix debug_,$(subst .c,,$(DEBUG_EXE_FILES)))
Modified: trunk/libocfs2/alloc.c
===================================================================
--- trunk/libocfs2/alloc.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/libocfs2/alloc.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -94,11 +94,11 @@
errcode_t ret;
ret = ocfs2_load_allocator(fs, INODE_ALLOC_SYSTEM_INODE,
- 0, &fs->fs_inode_alloc);
+ 0, &fs->fs_inode_allocs[0]);
if (ret)
return ret;
- return ocfs2_chain_alloc_with_io(fs, fs->fs_inode_alloc, blkno);
+ return ocfs2_chain_alloc_with_io(fs, fs->fs_inode_allocs[0], blkno);
}
errcode_t ocfs2_new_system_inode(ocfs2_filesys *fs, uint64_t *blkno)
@@ -118,14 +118,53 @@
{
errcode_t ret;
+ /* XXX needs to delete from the allocator that has the inode */
+
ret = ocfs2_load_allocator(fs, INODE_ALLOC_SYSTEM_INODE,
- 0, &fs->fs_inode_alloc);
+ 0, &fs->fs_inode_allocs[0]);
if (ret)
return ret;
- return ocfs2_chain_free_with_io(fs, fs->fs_inode_alloc, blkno);
+ return ocfs2_chain_free_with_io(fs, fs->fs_inode_allocs[0], blkno);
}
+errcode_t ocfs2_test_inode_allocated(ocfs2_filesys *fs, uint64_t blkno,
+ int *is_allocated)
+{
+ uint16_t node, max_nodes = OCFS2_RAW_SB(fs->fs_super)->s_max_nodes;
+ ocfs2_cached_inode **ci;
+ int type;
+ errcode_t ret = OCFS2_ET_INTERNAL_FAILURE;
+
+ for (node = ~0; node != max_nodes; node++) {
+ if (node == (uint16_t)~0) {
+ type = GLOBAL_INODE_ALLOC_SYSTEM_INODE;
+ ci = &fs->fs_system_inode_alloc;
+ } else {
+ type = INODE_ALLOC_SYSTEM_INODE;
+ ci = &fs->fs_inode_allocs[node];
+ }
+
+ ret = ocfs2_load_allocator(fs, type, node, ci);
+ if (ret)
+ break;
+
+ /* XXX I don't understand why this isn't in
+ * ocfs2_load_allocator.. the _with_io guys in this file about
+ * chain_allocator */
+ if ((*ci)->ci_chains == NULL) {
+ ret = ocfs2_load_chain_allocator(fs, *ci);
+ if (ret)
+ break;
+ }
+
+ ret = ocfs2_chain_test(fs, *ci, blkno, is_allocated);
+ if (ret != OCFS2_ET_INVALID_BIT)
+ break;
+ }
+ return ret;
+}
+
void ocfs2_init_inode(ocfs2_filesys *fs, ocfs2_dinode *di,
uint64_t blkno)
{
Modified: trunk/libocfs2/bitmap.c
===================================================================
--- trunk/libocfs2/bitmap.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/libocfs2/bitmap.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -287,6 +287,25 @@
return 0;
}
+errcode_t ocfs2_bitmap_foreach_region(ocfs2_bitmap *bitmap,
+ ocfs2_bitmap_foreach_func func,
+ void *private_data)
+{
+ struct ocfs2_bitmap_region *br;
+ struct rb_node *node;
+ errcode_t ret = 0;
+
+ for (node = rb_first(&bitmap->b_regions); node; node = rb_next(node)) {
+ br = rb_entry(node, struct ocfs2_bitmap_region, br_node);
+
+ ret = func(br, private_data);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
/*
* Attempt to merge two regions. If the merge is successful, 0 will
* be returned and prev will be the only valid region. Next will
@@ -432,8 +451,12 @@
if (oldval)
*oldval = old_tmp;
- if (!old_tmp)
+ if (!old_tmp) {
br->br_set_bits++;
+ if (bitmap->b_ops->bit_change_notify)
+ (*bitmap->b_ops->bit_change_notify)(bitmap, br, bitno,
+ 1);
+ }
return 0;
}
@@ -453,8 +476,12 @@
if (oldval)
*oldval = old_tmp;
- if (old_tmp)
+ if (old_tmp) {
br->br_set_bits--;
+ if (bitmap->b_ops->bit_change_notify)
+ (*bitmap->b_ops->bit_change_notify)(bitmap, br, bitno,
+ 0);
+ }
return 0;
}
Modified: trunk/libocfs2/chainalloc.c
===================================================================
--- trunk/libocfs2/chainalloc.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/libocfs2/chainalloc.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -38,6 +38,7 @@
struct chainalloc_bitmap_private {
ocfs2_cached_inode *cb_cinode;
errcode_t cb_errcode;
+ int cb_dirty;
};
struct chainalloc_region_private {
@@ -51,9 +52,14 @@
{
struct rb_node *node = NULL;
struct ocfs2_bitmap_region *br;
+ struct chainalloc_region_private *cr;
for (node = rb_first(&bitmap->b_regions); node; node = rb_next(node)) {
br = rb_entry(node, struct ocfs2_bitmap_region, br_node);
+
+ cr = br->br_private;
+ if (cr->cr_ag)
+ ocfs2_free(&cr->cr_ag);
ocfs2_free(&br->br_private);
}
@@ -139,6 +145,54 @@
return ret;
}
+static errcode_t chainalloc_write_group(struct ocfs2_bitmap_region *br,
+ void *private_data)
+{
+ struct chainalloc_region_private *cr = br->br_private;
+ ocfs2_filesys *fs = private_data;
+ errcode_t ret = 0;
+
+ printf("want to write desc %"PRIu64"\n", cr->cr_ag->bg_blkno);
+
+ if (!cr->cr_dirty)
+ return 0;
+
+ memcpy(cr->cr_ag->bg_bitmap, br->br_bitmap, cr->cr_ag->bg_bits / 8);
+
+ ret = ocfs2_write_group_desc(fs, cr->cr_ag->bg_blkno,
+ (char *)cr->cr_ag);
+ if (ret == 0)
+ cr->cr_dirty = 0;
+
+ return ret;
+}
+
+static errcode_t chainalloc_write_bitmap(ocfs2_bitmap *bitmap)
+{
+ struct chainalloc_bitmap_private *cb = bitmap->b_private;
+ ocfs2_filesys *fs;
+ errcode_t ret;
+
+ if (!cb->cb_cinode)
+ return OCFS2_ET_INVALID_ARGUMENT;
+
+ if (!cb->cb_dirty)
+ return 0;
+
+ fs = cb->cb_cinode->ci_fs;
+
+ ret = ocfs2_bitmap_foreach_region(bitmap, chainalloc_write_group, fs);
+ if (ret)
+ goto out;
+
+ ret = ocfs2_write_cached_inode(fs, cb->cb_cinode);
+ if (ret == 0)
+ cb->cb_dirty = 0;
+
+out:
+ return ret;
+}
+
static int chainalloc_merge_region(ocfs2_bitmap *bitmap,
struct ocfs2_bitmap_region *prev,
struct ocfs2_bitmap_region *next)
@@ -147,6 +201,33 @@
return 0;
}
+/* update the free bit counts in the alloc group, chain rec, and inode so
+ * that they are valid if we're asked to write in the future */
+static void chainalloc_bit_change_notify(ocfs2_bitmap *bitmap,
+ struct ocfs2_bitmap_region *br,
+ uint64_t bitno,
+ int new_val)
+{
+ struct chainalloc_bitmap_private *cb = bitmap->b_private;
+ struct chainalloc_region_private *cr = br->br_private;
+ ocfs2_dinode *di = cb->cb_cinode->ci_inode;
+ ocfs2_group_desc *ag = cr->cr_ag;
+ ocfs2_chain_rec *rec = &di->id2.i_chain.cl_recs[ag->bg_chain];
+
+ if (new_val) {
+ ag->bg_free_bits_count--;
+ rec->c_free--;
+ di->id1.bitmap1.i_used++;
+ } else {
+ ag->bg_free_bits_count++;
+ rec->c_free++;
+ di->id1.bitmap1.i_used--;
+ }
+
+ cr->cr_dirty = 1;
+ cb->cb_dirty = 1;
+}
+
static struct ocfs2_bitmap_operations chainalloc_bitmap_ops = {
.set_bit = ocfs2_bitmap_set_generic,
.clear_bit = ocfs2_bitmap_clear_generic,
@@ -155,7 +236,9 @@
.find_next_clear = ocfs2_bitmap_find_next_clear_generic,
.merge_region = chainalloc_merge_region,
.read_bitmap = chainalloc_read_bitmap,
+ .write_bitmap = chainalloc_write_bitmap,
.destroy_notify = chainalloc_destroy_notify,
+ .bit_change_notify = chainalloc_bit_change_notify,
};
static errcode_t ocfs2_chainalloc_bitmap_new(ocfs2_filesys *fs,
@@ -273,7 +356,18 @@
return 0;
}
+errcode_t ocfs2_chain_test(ocfs2_filesys *fs,
+ ocfs2_cached_inode *cinode,
+ uint64_t blkno,
+ int *oldval)
+{
+ if (!cinode->ci_chains)
+ return OCFS2_ET_INVALID_ARGUMENT;
+ return ocfs2_bitmap_test(cinode->ci_chains, blkno, oldval);
+}
+
+
#ifdef DEBUG_EXE
#include <stdlib.h>
#include <getopt.h>
Modified: trunk/libocfs2/include/bitmap.h
===================================================================
--- trunk/libocfs2/include/bitmap.h 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/libocfs2/include/bitmap.h 2004-11-06 04:54:12 UTC (rev 368)
@@ -61,6 +61,10 @@
errcode_t (*read_bitmap)(ocfs2_bitmap *bitmap);
errcode_t (*write_bitmap)(ocfs2_bitmap *bitmap);
void (*destroy_notify)(ocfs2_bitmap *bitmap);
+ void (*bit_change_notify)(ocfs2_bitmap *bitmap,
+ struct ocfs2_bitmap_region *br,
+ uint64_t bitno,
+ int new_val);
};
struct _ocfs2_bitmap {
@@ -90,6 +94,11 @@
int total_bits);
errcode_t ocfs2_bitmap_insert_region(ocfs2_bitmap *bitmap,
struct ocfs2_bitmap_region *br);
+typedef errcode_t (*ocfs2_bitmap_foreach_func)(struct ocfs2_bitmap_region *br,
+ void *private_data);
+errcode_t ocfs2_bitmap_foreach_region(ocfs2_bitmap *bitmap,
+ ocfs2_bitmap_foreach_func func,
+ void *private_data);
errcode_t ocfs2_bitmap_set_generic(ocfs2_bitmap *bitmap,
uint64_t bitno, int *oldval);
errcode_t ocfs2_bitmap_clear_generic(ocfs2_bitmap *bitmap,
Modified: trunk/libocfs2/include/ocfs2.h
===================================================================
--- trunk/libocfs2/include/ocfs2.h 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/libocfs2/include/ocfs2.h 2004-11-06 04:54:12 UTC (rev 368)
@@ -180,7 +180,7 @@
/* Allocators */
ocfs2_cached_inode *fs_cluster_alloc;
- ocfs2_cached_inode *fs_inode_alloc;
+ ocfs2_cached_inode **fs_inode_allocs;
ocfs2_cached_inode *fs_system_inode_alloc;
ocfs2_cached_inode *fs_eb_alloc;
ocfs2_cached_inode *fs_system_eb_alloc;
@@ -425,7 +425,14 @@
errcode_t ocfs2_chain_free(ocfs2_filesys *fs,
ocfs2_cached_inode *cinode,
uint64_t blkno);
+errcode_t ocfs2_chain_test(ocfs2_filesys *fs,
+ ocfs2_cached_inode *cinode,
+ uint64_t blkno,
+ int *oldval);
+errcode_t ocfs2_test_inode_allocated(ocfs2_filesys *fs, uint64_t blkno,
+ int *is_allocated);
+
/*
* ${foo}_to_${bar} is a floor function. blocks_to_clusters will
* returns the cluster that contains a block, not the number of clusters
Modified: trunk/libocfs2/openfs.c
===================================================================
--- trunk/libocfs2/openfs.c 2004-11-05 20:50:15 UTC (rev 367)
+++ trunk/libocfs2/openfs.c 2004-11-06 04:54:12 UTC (rev 368)
@@ -234,6 +234,12 @@
if (OCFS2_RAW_SB(fs->fs_super)->s_max_nodes > OCFS2_MAX_NODES)
goto out;
+ ret = ocfs2_malloc0(OCFS2_RAW_SB(fs->fs_super)->s_max_nodes *
+ sizeof(ocfs2_cached_inode *),
+ &fs->fs_inode_allocs);
+ if (ret)
+ goto out;
+
ret = OCFS2_ET_UNEXPECTED_BLOCK_SIZE;
if (block_size !=
(1U << OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits))
@@ -258,6 +264,9 @@
return 0;
out:
+ if (fs->fs_inode_allocs)
+ ocfs2_free(&fs->fs_inode_allocs);
+
ocfs2_freefs(fs);
return ret;
More information about the Ocfs2-tools-commits
mailing list