Subject: afs/fs/cachefs rootdir.c,1.13,1.14 replay.c,1.1,1.2 recycling.c,1.25,1.26 journal.c,1.39,1.40 interface.c,1.15,1.16 index.c,1.26,1.27 dump-journal.c,1.13,1.14 cachefs-layout.h,1.29,1.30 cachefs-int.h,1.38,1.39 block.c,1.8,1.9

From: [email-masked]
Date: Thu, 10 Jul 2003 15:21:26 +0100

Update of /home/cvs/afs/fs/cachefs
In directory phoenix.infradead.org:/tmp/cvs-serv15220/fs/cachefs

Modified Files:
	rootdir.c replay.c recycling.c journal.c interface.c index.c 
	dump-journal.c cachefs-layout.h cachefs-int.h block.c 
Log Message:
started fleshing out the replaying properly
fixed a few bugs (including those introduced by the above)

Index: rootdir.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/rootdir.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- rootdir.c	9 Jul 2003 10:39:50 -0000	1.13
+++ rootdir.c	10 Jul 2003 14:21:23 -0000	1.14
@@ -641,14 +641,17 @@
  */
 static int cachefs_root_rmdir_unlink(struct inode *dir, struct dentry *dentry)
 {
+	struct cachefs_ondisc_index_entry *xent;
 	struct cachefs_ondisc_metadata *metadata;
 	struct cachefs_transaction *trans;
-	struct cachefs_inode *inode;
 	struct cachefs_super *super = dir->i_sb->s_fs_info;
+	struct cachefs_inode *inode, *index;
 	unsigned long flags;
+	struct page *ixpage;
 	int ret;
 
-	_enter("{%lx},{%s,%p}", dir->i_ino, dentry->d_name.name, dentry->d_inode);
+	_enter("{%lx},{%s,%p}",
+	       dir->i_ino, dentry->d_name.name, dentry->d_inode);
 
 	if (!dentry->d_inode) {
 		printk("&&& no inode &&&\n");
@@ -657,6 +660,7 @@
 	}
 
 	inode = CACHEFS_FS_I(dentry->d_inode);
+	index = CACHEFS_FS_I(dir);
 
 	/* mark for reclamation under journalling */
 	trans = cachefs_trans_alloc(super, GFP_KERNEL);
@@ -667,20 +671,52 @@
 
 	trans->jentry->mark	= CACHEFS_ONDISC_UJNL_INODE_MARK_RECLAIM;
 	trans->jentry->ino	= inode->vfs_inode.i_ino;
+	trans->jentry->auxblock	= inode->metadata->bix;
+	trans->jentry->auxentry	= inode->metadata_offset;
+
+	metadata = cachefs_metadata_preread(inode);
+	trans->jentry->index	= metadata->pindex;
+	trans->jentry->ixentry	= metadata->pindex_entry;
+	cachefs_metadata_postread(inode);
+
+	BUG_ON(trans->jentry->index != dir->i_ino);
+
+	trans->jentry->pgnum = trans->jentry->index / index->index_epp;
+	trans->jentry->entry =
+		(trans->jentry->index % index->index_epp) * index->index_esize;
+
+	ret = cachefs_get_page(index, trans->jentry->pgnum, &ixpage);
+	if (ret < 0) {
+		cachefs_trans_put(trans);
+		_leave(" = %d", ret);
+		return ret;
+	}
+
+	trans->jentry->block = __cachefs_get_page_block(ixpage)->bix;
 
 	cachefs_trans_affects_inode(trans, inode);
+	cachefs_trans_affects_page(trans, __cachefs_page_get_private(ixpage),
+				   trans->jentry->entry, sizeof(*xent));
 
 	ret = cachefs_trans_mark(trans);
 	if (ret < 0) {
+		cachefs_put_page(ixpage);
 		cachefs_trans_put(trans);
 		_leave(" = %d", ret);
 		return ret;
 	}
 
+	cachefs_page_modify(super, &ixpage);
+
 	/* modify the inode metadata entry */
 	metadata = cachefs_metadata_prewrite(inode);
 	metadata->header.state = CACHEFS_ONDISC_INDEX_RECYCLE;
 	cachefs_metadata_postwrite(inode);
+
+	/* modify the index entry */
+	xent = kmap(ixpage) + trans->jentry->entry;
+	xent->state = CACHEFS_ONDISC_INDEX_RECYCLE;
+	kunmap(ixpage);
 
 	cachefs_trans_commit(trans);

Index: replay.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/replay.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- replay.c	9 Jul 2003 10:39:50 -0000	1.1
+++ replay.c	10 Jul 2003 14:21:23 -0000	1.2
@@ -18,6 +18,9 @@
 #include "cachefs-int.h"
 
 #define UJNL_WRAP(X) ((X) & (CACHEFS_ONDISC_UJNL_NUMENTS - 1))
+#define BLOCK_VALID(BLOCK,JENTRY) \
+	((BLOCK) && \
+	 (u_int16_t) (unsigned long) (BLOCK)->ref <= (JENTRY)->serial)
 
 struct cachefs_replay_find_batch_desc {
 	read_descriptor_t	desc;
@@ -63,9 +66,6 @@
 static int cachefs_replay_ujnl_index_extending(struct cachefs_super *super,
 					       struct cachefs_ondisc_update_journal *jentry,
 					       struct cachefs_transaction *trans);
-static int cachefs_replay_ujnl_index_creating(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry,
-					      struct cachefs_transaction *trans);
 static int cachefs_replay_ujnl_index_modifying(struct cachefs_super *super,
 					       struct cachefs_ondisc_update_journal *jentry,
 					       struct cachefs_transaction *trans);
@@ -102,7 +102,7 @@
 	[CACHEFS_ONDISC_UJNL_INDIRECT_ALLOCING]	= cachefs_replay_ujnl_indirect_allocing,
 	[CACHEFS_ONDISC_UJNL_INDIRECT_FREEING]	= cachefs_replay_ujnl_indirect_freeing,
 	[CACHEFS_ONDISC_UJNL_INDEX_EXTENDING]	= cachefs_replay_ujnl_index_extending,
-	[CACHEFS_ONDISC_UJNL_INDEX_CREATING]	= cachefs_replay_ujnl_index_creating,
+	[CACHEFS_ONDISC_UJNL_INDEX_CREATING]	= cachefs_replay_ujnl_inode_creating,
 	[CACHEFS_ONDISC_UJNL_INDEX_UPDATING]	= cachefs_replay_ujnl_index_modifying
 };
 
@@ -469,6 +469,7 @@
 {
 	struct cachefs_replay_find_batch_desc find_batch;
 	struct cachefs_ondisc_free_node *node;
+	struct cachefs_block *block;
 	struct file_ra_state ra;
 	loff_t ppos;
 	int loop, ret;
@@ -507,54 +508,65 @@
 	       find_batch.batch_end,
 	       find_batch.batch_ack);
 
-	if (find_batch.batch_end != ~0u && find_batch.batch_ack != ~0u)
-		goto reload_tracking;
+	if (find_batch.batch_end == ~0u || find_batch.batch_ack == ~0u) {
+		if (find_batch.batch_first == ~0u) {
+			clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
+			printk("CacheFS: corrupted journal:"
+			       " ujnl batch has no start entry\n");
+			return -EINVAL;
+		}
 
-	if (find_batch.batch_first == ~0u) {
-		clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
-		printk("CacheFS: corrupted journal:"
-		       " ujnl batch has no start entry\n");
-		return -EINVAL;
-	}
+		if (find_batch.batch_ack != ~0u) {
+			clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
+			printk("CacheFS: corrupted journal:"
+			       " ujnl batch has ACK but no end marker\n");
+			return -EINVAL;
+		}
 
-	if (find_batch.batch_ack != ~0u) {
-		clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
-		printk("CacheFS: corrupted journal:"
-		       " ujnl batch has ACK but no end marker\n");
-		return -EINVAL;
-	}
+		if (find_batch.batch_count != super->ujnl_serial) {
+			clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
+			printk("CacheFS: corrupted journal:"
+			       " ujnl batch has missing marks\n");
+			return -EINVAL;
+		}
 
-	if (find_batch.batch_count != super->ujnl_serial) {
-		clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
-		printk("CacheFS: corrupted journal:"
-		       " ujnl batch has missing marks\n");
-		return -EINVAL;
-	}
+		/* all checks bear out that we have a valid - though incomplete
+		 * - update journal batch */
+		printk("CacheFS: Need to replay update journal\n");
+
+		super->ujnl_tail = find_batch.batch_first;
+		super->ujnl_head = UJNL_WRAP(find_batch.batch_end - 1);
+
+		ret = cachefs_ujnl_replay_aux(
+			super, &ra, cachefs_ujnl_determine_overlap_actor);
+
+		if (ret == 0)
+			ret = cachefs_ujnl_replay_aux(
+				super, &ra, cachefs_ujnl_replay_actor);
+
+		while (!list_empty(&super->ujnl_replayq)) {
+			block = list_entry(super->ujnl_replayq.next,
+					   struct cachefs_block, batch_link);
+		
+			list_del_init(&block->batch_link);
+			block->ref = NULL;
+			cachefs_block_put(block);
+		}
 
-	/* all checks bear out that we have a valid - though incomplete -
-	 * update journal batch */
-	super->ujnl_tail = find_batch.batch_first;
-	super->ujnl_head = UJNL_WRAP(find_batch.batch_end - 1);
-
-	ret = cachefs_ujnl_replay_aux(super, &ra,
-				      cachefs_ujnl_determine_overlap_actor);
-	if (ret < 0) {
-		clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
-		return ret;
-	}
+		if (ret < 0) {
+			clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
+			printk("CacheFS: Failed to replay update journal\n");
+			return ret;
+		}
 
-	ret = cachefs_ujnl_replay_aux(super, &ra,
-				      cachefs_ujnl_replay_actor);
-	if (ret < 0) {
-		clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
-		return ret;
+		/* write all blocks that are marked for writeback */
+		cachefs_trans_batch_write(super);
+
+		printk("CacheFS: Finished replaying update journal\n");
 	}
 
-	/* write all blocks that are marked for writeback */
-	cachefs_trans_batch_write(super);
 	clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
 
- reload_tracking:
 	kdebug("reload_tracking");
 	super->ujnl_batch++;
 	super->ujnl_serial	= 0;
@@ -632,7 +644,7 @@
 	}

-	_leave(" = 0");
+	kleave(" = 0");
 	return 0;
 } /* end cachefs_ujnl_replay() */
 
@@ -676,7 +688,7 @@
 
 	/* we need to fix up the recycling block node header if the block is
 	 * currently part of one of the recycling chains */
-	if ((u_int16_t) (unsigned long) block->ref <= jentry->serial) {
+	if (BLOCK_VALID(block, jentry)) {
 		node = kmap(page);
 
 		if (node->next != jentry->auxblock) {
@@ -719,7 +731,7 @@
 		if (ret < 0)
 			goto error;
 
-		if ((u_int16_t) (unsigned long) block->ref <= jentry->serial) {
+		if (BLOCK_VALID(block, jentry)) {
 			node = kmap(page);
 
 			if (node->next || node->count) {
@@ -771,7 +783,7 @@
 		goto error2;
 	}
 
-	if ((u_int16_t) (unsigned long) block->ref <= jentry->serial) {
+	if (BLOCK_VALID(block, jentry)) {
 		node = kmap(page);
 
 		if (memcmp(&node->leaves[jentry->auxblock],
@@ -842,7 +854,7 @@
 	kunmap(spage);
 
 	/* we need to reload the pointers cached into the recycling block */
-	if ((u_int16_t) (unsigned long) block->ref <= jentry->serial) {
+	if (BLOCK_VALID(block, jentry)) {
 		node = kmap(page);
 
 		if (memcmp(&node->leaves[jentry->auxblock],
@@ -872,85 +884,358 @@
 
 /*****************************************************************************/
 /*
- * replay the creation of a new data inode
- * - since we don't know what index data was associated with it, all we can do
- *   is mark it for reclamation
+ * replay the creation of a new data or index inode
  */
 static int cachefs_replay_ujnl_inode_creating(struct cachefs_super *super,
 					      struct cachefs_ondisc_update_journal *jentry,
 					      struct cachefs_transaction *trans)
 {
-	return -ENOANO;
+	struct cachefs_ondisc_index_entry *xent;
+	struct cachefs_ondisc_ujnl_index *jindex;
+	struct cachefs_ondisc_metadata *metadata;
+	struct cachefs_block *metameta, *inometa, *indexmeta, *indexdata;
+	struct page *metapage, *inompage, *ixmpage, *ixdatapage;
+	u_int32_t type;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	jindex = &jentry->ixdata[0];
+
+	ret = cachefs_block_read(super, NULL, 1, 0, &metameta, &metapage);
+	if (ret < 0)
+		goto error;
+
+	ret = cachefs_block_read(super, NULL, jentry->auxblock, 0,
+				 &inometa, &inompage);
+	if (ret < 0)
+		goto error2;
+
+	ret = cachefs_block_read(super, NULL, jentry->upblock, 0,
+				 &indexmeta, &ixmpage);
+	if (ret < 0)
+		goto error3;
+
+	ret = cachefs_block_read(super, NULL, jentry->block, 0,
+				 &indexdata, &ixdatapage);
+	if (ret < 0)
+		goto error4;
+
+	type = CACHEFS_ONDISC_INDEX_DATAFILE;
+	if (jentry->mark == CACHEFS_ONDISC_UJNL_INDEX_CREATING)
+		type = CACHEFS_ONDISC_INDEX_INDEXFILE;
+
+	/* make sure the metadata file's freelink pointer is correct */
+	if (BLOCK_VALID(metameta, jentry)) {
+		metadata = kmap(metapage);
+		if (metadata->freelink != jindex->next_ino) {
+			metadata->freelink = jindex->next_ino;
+			cachefs_trans_replays_effect(trans, metameta);
+		}
+		kunmap(metapage);
+	}
+
+	/* make sure the index file's freelink pointer is correct */
+	if (BLOCK_VALID(indexmeta, jentry)) {
+		metadata = kmap(ixmpage);
+		if (metadata->freelink	!= jindex->next_index ||
+		    metadata->size	!= jentry->size) {
+			metadata->freelink	= jindex->next_index;
+			metadata->size		= jentry->size;
+			cachefs_trans_replays_effect(trans, indexmeta);
+		}
+		kunmap(ixmpage);
+	}
+
+	/* make sure the new inode's metadata contains the right data */
+	if (BLOCK_VALID(inometa, jentry)) {
+		metadata = kmap(inompage);
+		if (metadata->header.state != CACHEFS_ONDISC_INDEX_ACTIVE ||
+		    metadata->header.type  != type ||
+		    metadata->header.ino   != 0xfefdfc ||
+		    metadata->freelink     != UINT_MAX ||
+		    metadata->pindex       != jentry->index ||
+		    metadata->pindex_entry != jentry->ixentry ||
+		    memcmp(&metadata->index,
+			   &jindex->def,
+			   sizeof(metadata->index)) != 0
+		    ) {
+			metadata->header.state	= CACHEFS_ONDISC_INDEX_ACTIVE;
+			metadata->header.type	= type;
+			metadata->header.ino	= 0xfefdfc;
+			metadata->freelink	= UINT_MAX;
+			metadata->atime		= CURRENT_TIME.tv_sec;
+			metadata->pindex	= jentry->index;
+			metadata->pindex_entry	= jentry->ixentry;
+
+			memcpy(&metadata->index,
+			       &jindex->def,
+			       sizeof(metadata->index));
+
+			cachefs_trans_replays_effect(trans, inometa);
+		}
+		kunmap(inompage);
+	}
+
+	/* make sure the index data is written into the index entry */
+	if (BLOCK_VALID(indexdata, jentry)) {
+		xent = kmap(ixdatapage);
+		if (xent->state	!= CACHEFS_ONDISC_INDEX_ACTIVE	||
+		    xent->type	!= type				||
+		    xent->ino	!= jentry->ino			||
+		    memcmp(xent->data, jindex->data, jindex->def.dsize) != 0
+		    ) {
+			xent->state	= CACHEFS_ONDISC_INDEX_ACTIVE;
+			xent->type	= type;
+			xent->ino	= jentry->ino;
+
+			memcpy(xent->data, jindex->data, jindex->def.dsize);
+
+			cachefs_trans_replays_effect(trans, indexdata);
+		}
+		kunmap(ixdatapage);
+	}
+
+	cachefs_block_put(indexdata);
+	cachefs_put_page(ixdatapage);
+ error4:
+	cachefs_block_put(indexmeta);
+	cachefs_put_page(ixmpage);
+ error3:
+	cachefs_block_put(inometa);
+	cachefs_put_page(inompage);
+ error2:
+	cachefs_block_put(metameta);
+	cachefs_put_page(metapage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_inode_creating() */
 
 /*****************************************************************************/
 /*
  * replay the updating of the information stored in an inode
- * - since we don't know what changes were to be made, we can't actually do
- *   anything, so we trust that the inode version number will suffice to cause
- *   an update upon accessing if need be
  */
 static int cachefs_replay_ujnl_inode_updating(struct cachefs_super *super,
 					      struct cachefs_ondisc_update_journal *jentry,
 					      struct cachefs_transaction *trans)
 {
-	return 0;
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	/* we don't do this yet */
+	return -EINVAL;
 } /* end cachefs_replay_ujnl_inode_updating() */
 
 /*****************************************************************************/
 /*
- * not yet supported
+ * replay the deletion of an inode and its associated index entry
  */
 static int cachefs_replay_ujnl_inode_deleting(struct cachefs_super *super,
 					      struct cachefs_ondisc_update_journal *jentry,
 					      struct cachefs_transaction *trans)
 {
-	return -EIO;
+	struct cachefs_ondisc_index_entry *xent;
+	struct cachefs_ondisc_ujnl_index *jindex;
+	struct cachefs_ondisc_metadata *metadata;
+	struct cachefs_block *metameta, *inometa;
+	struct cachefs_block *indexmeta = NULL, *indexdata = NULL;
+	struct page *metapage, *inompage, *ixmpage = NULL, *ixdatapage = NULL;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	jindex = &jentry->ixdata[0];
+
+	ret = cachefs_block_read(super, NULL, 1, 0, &metameta, &metapage);
+	if (ret < 0)
+		goto error;
+
+	ret = cachefs_block_read(super, NULL, jentry->auxblock, 0,
+				 &inometa, &inompage);
+	if (ret < 0)
+		goto error2;
+
+	if (jentry->index) {
+		ret = cachefs_block_read(super, NULL, jentry->upblock, 0,
+					 &indexmeta, &ixmpage);
+		if (ret < 0)
+			goto error3;
+
+		ret = cachefs_block_read(super, NULL, jentry->block, 0,
+					 &indexdata, &ixdatapage);
+		if (ret < 0)
+			goto error4;
+	}
+
+	/* make sure the metadata file's freelink pointer is correct */
+	if (BLOCK_VALID(metameta, jentry)) {
+		metadata = kmap(metapage);
+		if (metadata->freelink != jindex->next_ino) {
+			metadata->freelink = jindex->next_ino;
+			cachefs_trans_replays_effect(trans, metameta);
+		}
+		kunmap(metapage);
+	}
+
+	/* make sure the index file's freelink pointer is correct */
+	if (BLOCK_VALID(indexmeta, jentry)) {
+		metadata = kmap(ixmpage);
+		if (metadata->freelink	!= jindex->next_index ||
+		    metadata->size	!= jentry->size) {
+			metadata->freelink	= jindex->next_index;
+			metadata->size		= jentry->size;
+			cachefs_trans_replays_effect(trans, indexmeta);
+		}
+		kunmap(ixmpage);
+	}
+
+	/* make sure the deleted inode's metadata contains the right data */
+	if (BLOCK_VALID(inometa, jentry)) {
+		metadata = kmap(inompage);
+		if (metadata->header.state	!= CACHEFS_ONDISC_INDEX_FREE ||
+		    metadata->header.type	!= 0			||
+		    metadata->header.ino	!= 0xfefdfc		||
+		    metadata->freelink		!= jindex->next_ino	||
+		    metadata->pindex		!= 0			||
+		    metadata->pindex_entry	!= 0
+		    ) {
+			memset(metadata, 0, super->layout->metadata_size);
+
+			metadata->header.state	= CACHEFS_ONDISC_INDEX_FREE;
+			metadata->header.ino	= 0xfefdfc;
+			metadata->freelink	= jindex->next_ino;
+			metadata->atime		= CURRENT_TIME.tv_sec;
+			metadata->pindex	= 0;
+			metadata->pindex_entry	= 0;
+
+			cachefs_trans_replays_effect(trans, inometa);
+		}
+		kunmap(inompage);
+	}
+
+	/* make sure the index data is written into the index entry */
+	if (BLOCK_VALID(indexdata, jentry)) {
+		xent = kmap(ixdatapage);
+		if (xent->state	!= CACHEFS_ONDISC_INDEX_FREE	||
+		    xent->type	!= 0				||
+		    xent->ino	!= 0				||
+		    xent->freelink[0] != jindex->next_index
+		    ) {
+			xent->state	= CACHEFS_ONDISC_INDEX_FREE;
+			xent->type	= 0;
+			xent->ino	= 0;
+			xent->freelink[0] = jindex->next_index;
+
+			cachefs_trans_replays_effect(trans, indexdata);
+		}
+		kunmap(ixdatapage);
+	}
+
+	cachefs_block_put(indexdata);
+	cachefs_put_page(ixdatapage);
+ error4:
+	cachefs_block_put(indexmeta);
+	cachefs_put_page(ixmpage);
+ error3:
+	cachefs_block_put(inometa);
+	cachefs_put_page(inompage);
+ error2:
+	cachefs_block_put(metameta);
+	cachefs_put_page(metapage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_inode_deleting() */
 
 /*****************************************************************************/
 /*
- * replay an inode being marked for reclamation
+ * replay the marking of an inode for reclamation
  */
 static int cachefs_replay_ujnl_inode_mark_reclaim(struct cachefs_super *super,
 						  struct cachefs_ondisc_update_journal *jentry,
 						  struct cachefs_transaction *trans)
 {
-	return -ENOANO;
+	struct cachefs_ondisc_index_entry *xent;
+	struct cachefs_ondisc_ujnl_index *jindex;
+	struct cachefs_ondisc_metadata *metadata;
+	struct cachefs_block *inometa, *indexdata;
+	struct page *inompage, *ixdatapage;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	jindex = &jentry->ixdata[0];
+
+	ret = cachefs_block_read(super, NULL, jentry->auxblock, 0,
+				 &inometa, &inompage);
+	if (ret < 0)
+		goto error;
+
+	ret = cachefs_block_read(super, NULL, jentry->block, 0,
+				 &indexdata, &ixdatapage);
+	if (ret < 0)
+		goto error2;
+
+	/* make sure the inode's metadata is set to the right state */
+	if (BLOCK_VALID(inometa, jentry)) {
+		metadata = kmap(inompage);
+		if (metadata->header.state != CACHEFS_ONDISC_INDEX_RECYCLE) {
+			metadata->header.state = CACHEFS_ONDISC_INDEX_FREE;
+
+			cachefs_trans_replays_effect(trans, inometa);
+		}
+		kunmap(inompage);
+	}
+
+	/* make sure the index entry is also set to the right state */
+	if (BLOCK_VALID(indexdata, jentry)) {
+		xent = kmap(ixdatapage);
+		if (xent->state	!= CACHEFS_ONDISC_INDEX_FREE) {
+			xent->state	= CACHEFS_ONDISC_INDEX_FREE;
+
+			cachefs_trans_replays_effect(trans, indexdata);
+		}
+		kunmap(ixdatapage);
+	}
+
+	cachefs_block_put(indexdata);
+	cachefs_put_page(ixdatapage);
+ error2:
+	cachefs_block_put(inometa);
+	cachefs_put_page(inompage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_inode_mark_reclaim() */
 
 /*****************************************************************************/
 /*
- *
+ * replay the initiation of inode reclamation
  */
 static int cachefs_replay_ujnl_inode_reclaiming(struct cachefs_super *super,
 						struct cachefs_ondisc_update_journal *jentry,
 						struct cachefs_transaction *trans)
 {
-	return -ENOANO;
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	/* nothing needs to be done here - it's all handled implicitly by the
+	 * caller */
+	return 0;
+
 } /* end cachefs_replay_ujnl_inode_reclaiming() */
 
 /*****************************************************************************/
 /*
- *
+ * replay the extension of an index file
  */
 static int cachefs_replay_ujnl_index_extending(struct cachefs_super *super,
 					       struct cachefs_ondisc_update_journal *jentry,
 					       struct cachefs_transaction *trans)
 {
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_index_extending() */
+	
 
-/*****************************************************************************/
-/*
- *
- */
-static int cachefs_replay_ujnl_index_creating(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry,
-					      struct cachefs_transaction *trans)
-{
 	return -ENOANO;
-} /* end cachefs_replay_ujnl_index_creating() */
+} /* end cachefs_replay_ujnl_index_extending() */
 
 /*****************************************************************************/
 /*

Index: recycling.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/recycling.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- recycling.c	9 Jul 2003 10:39:50 -0000	1.25
+++ recycling.c	10 Jul 2003 14:21:24 -0000	1.26
@@ -481,6 +481,7 @@
 static int cachefs_recycle_reclaim_inode_metadata(struct cachefs_super *super)
 {
 	struct cachefs_ondisc_index_entry *xent;
+	struct cachefs_ondisc_ujnl_index *jindex;
 	struct cachefs_ondisc_metadata *metadata;
 	struct cachefs_transaction *trans = NULL;
 	struct cachefs_inode *iinode = NULL;
@@ -519,37 +520,44 @@
 	if (!trans)
 		goto error;
 
+	jindex = &trans->jentry->ixdata[0];
+	jindex->next_ino	= UINT_MAX;
+	jindex->next_index	= UINT_MAX;
+
 	trans->jentry->mark	= CACHEFS_ONDISC_UJNL_INODE_DELETING;
-	trans->jentry->index	= iino;
-	trans->jentry->ixentry	= ixentry;
 	trans->jentry->ino	= super->rcm_ino;
-	trans->jentry->entry	= offset;
-
-	if (ixpage) {
-		trans->jentry->pgnum = ixpage->index;
-		trans->jentry->block = __cachefs_get_page_block(ixpage)->bix;
-	}
 
 	if (iinode) {
-		trans->jentry->size  = iinode->vfs_inode.i_size;
-		trans->jentry->count = iinode->index_esize;
+		trans->jentry->index	= iino;
+		trans->jentry->ixentry	= ixentry;
+		trans->jentry->pgnum	= ixpage->index;
+		trans->jentry->block	=
+			__cachefs_get_page_block(ixpage)->bix;
+		trans->jentry->entry	= offset;
+		trans->jentry->upblock	= iinode->metadata->bix;
+		trans->jentry->upentry	= iinode->metadata_offset;
+		trans->jentry->size	= iinode->vfs_inode.i_size;
+		trans->jentry->count	= iinode->index_dsize;
 
 		metadata = cachefs_metadata_preread(iinode);
-		trans->jentry->upblock = metadata->freelink;
+		jindex->next_index = metadata->freelink;
 		cachefs_metadata_postread(iinode);
 
 		cachefs_trans_affects_page(trans,
 					   __cachefs_page_get_private(ixpage),
-					   offset,
-					   iinode->index_esize);
+					   trans->jentry->entry,
+					   trans->jentry->count);
 
 		cachefs_trans_affects_inode(trans, iinode);
 	}
 
 	metadata = cachefs_metadata_preread(super->imetadata);
-	trans->jentry->auxblock	= metadata->freelink;
+	jindex->next_ino = metadata->freelink;
 	cachefs_metadata_postread(super->imetadata);
 
+	trans->jentry->auxblock	= super->rcm_inode->metadata->bix;
+	trans->jentry->auxentry	= super->rcm_inode->metadata_offset;
+
 	cachefs_trans_affects_inode(trans, super->rcm_inode);
 	cachefs_trans_affects_inode(trans, super->imetadata);
 
@@ -563,14 +571,15 @@
 
 		xent = kmap(ixpage) + offset;
 		xent->state		= CACHEFS_ONDISC_INDEX_FREE;
+		xent->type		= 0;
 		xent->ino		= 0;
-		xent->freelink[0]	= trans->jentry->upblock;
+		xent->freelink[0]	= jindex->next_index;
 		memset(xent->data, 0, iinode->index_dsize);
 		kunmap(ixpage);
 
 		/* modify the index inode metadata entry */
 		metadata = cachefs_metadata_prewrite(iinode);
-		metadata->freelink	= ixentry;
+		metadata->freelink = ixentry;
 		cachefs_metadata_postwrite(iinode);
 	}
 
@@ -579,7 +588,7 @@
 	memset(metadata, 0, sizeof(super->imetadata->index_esize));
 
 	metadata->header.state	= CACHEFS_ONDISC_INDEX_FREE;
-	metadata->freelink	= trans->jentry->auxblock;
+	metadata->freelink	= jindex->next_ino;
 	metadata->mtime		= CURRENT_TIME.tv_sec;
 	metadata->atime		= CURRENT_TIME.tv_sec;
 	cachefs_metadata_postwrite(super->rcm_inode);
@@ -654,12 +663,12 @@
  again:
 	indirect++;
 
-	/* clear out then entries in an index */
+	/* iterate through an index clearing out the entries it contains */
 	if (indirect == 1) {
 		if (super->rcm_inode->index_dsize == 0)
 			goto again;
 
-		if (cachefs_index_zap(super) < 0)
+		if (cachefs_index_reclaim_one_entry(super) < 0)
 			goto error2;
 		goto again;
 	}
@@ -780,7 +789,7 @@
 		goto again;
 	}
  error2:
-	kleave(" [error %d]", ret);
+	kdebug("[error %d]", ret);
 	goto set;
 } /* end cachefs_recycle_reclaim_inode() */

Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- journal.c	9 Jul 2003 10:39:50 -0000	1.39
+++ journal.c	10 Jul 2003 14:21:24 -0000	1.40
@@ -104,6 +104,8 @@
 
 	_enter("");
 
+	BUG_ON(super->dmn_die > 0);
+
 	trans = kmalloc(sizeof(struct cachefs_transaction), gfp);
 	if (!trans) {
 		_leave(" = 0 [ENOMEM]");
@@ -277,6 +279,8 @@
 	 */
 	down_read(&super->batch_ctrl_sem);
 
+	BUG_ON(super->dmn_die > 0);
+
 	/* make sure any changes we make to memory don't end up on disc just
 	 * yet, either:
 	 * (1) wait for the page to be written back to disc, or:
@@ -1138,13 +1142,20 @@
 
 	_enter("");
 
-	/* see if any blocks are ready to be cleaned up */
+	/* see if any blocks are ready to be cleaned up
+	 * - note the checks made on the three queues must be done atomically
+	 *   or else list_move_tail() may cause a problem by having a node in
+	 *   transit
+	 */
  try_again:
+	spin_lock_irqsave(&super->batch_qlock, flags);
+
 	if (list_empty(&super->batch_writeq))
 		wait = 0;
 
 	if (list_empty(&super->batch_doneq) &&
 	    list_empty(&super->batch_errorq)) {
+		spin_unlock_irqrestore(&super->batch_qlock, flags);
 		if (!wait) {
 			_leave(" [nothing]");
 			return;
@@ -1161,6 +1172,8 @@
 
 		remove_wait_queue(&super->batch_done_wq, &myself);
 		set_current_state(TASK_RUNNING);
+
+		spin_lock_irqsave(&super->batch_qlock, flags);
 	}
 
 	if (wait == 1)
@@ -1168,8 +1181,6 @@
 
 	/* clean up as many blocks as we can */
 	error = 0;
-
-	spin_lock_irqsave(&super->batch_qlock, flags);
 
 	if (!list_empty(&super->batch_errorq)) {
 		list_splice_init(&super->batch_errorq, &myblocks);

Index: interface.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/interface.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- interface.c	9 Jul 2003 10:39:50 -0000	1.15
+++ interface.c	10 Jul 2003 14:21:24 -0000	1.16
@@ -211,7 +211,11 @@
 	}
 	spin_unlock(&super->ino_list_lock);
 
-	/* mark all active blocks a being withdrawn */
+	/* make sure all pages pinned by operations on behalf of the netfs are
+	 * written to disc */
+	cachefs_trans_sync(super, CACHEFS_TRANS_SYNC_WAIT_FOR_ACK);
+
+	/* mark all active blocks as being withdrawn */
 	cachefs_block_withdraw(super);
 
 	/* we now have to destroy all the active inodes pertaining to this
@@ -648,7 +652,6 @@
 				return;
 			}
 		}
-		
 	}
 
 	/* if no parent cookie, then don't create one here either */
@@ -1278,7 +1281,10 @@
 		pageio->flags = 0;
 		write_unlock(&pageio->lock);
 
-		BUG_ON(block->ref != pageio);
+		if (unlikely(block->ref != pageio)) {
+			printk("%p != %p", block->ref, pageio);
+			BUG();
+		}
 
 		/* locking order needs to be reversed */
 		write_lock(&block->ref_lock);

Index: index.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/index.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- index.c	9 Jul 2003 10:39:50 -0000	1.26
+++ index.c	10 Jul 2003 14:21:24 -0000	1.27
@@ -58,6 +58,8 @@
 
 	_enter(",{%lx},%u,%u,%u", ixpage->index, ixentry, ixoffset, ino);
 
+	kdebug("SEARCH/DELETE %u", ino);
+
 	super = ixpage->mapping->host->i_sb->s_fs_info;
 
 	ret = cachefs_iget(super, ino, &inode);
@@ -66,6 +68,8 @@
 		return;
 	}
 
+	BUG_ON(!list_empty(&inode->cookie_link));
+
 	ret = -ENOMEM;
 	trans = cachefs_trans_alloc(super, GFP_KERNEL);
 	if (!trans)
@@ -76,10 +80,10 @@
 	trans->jentry->index	= rec->iinode->vfs_inode.i_ino;
 	trans->jentry->ixentry	= ixentry;
 	trans->jentry->pgnum	= ixpage->index;
-	trans->jentry->block	= inode->metadata->bix;
-	trans->jentry->entry	= inode->metadata_offset;
-	trans->jentry->upblock	= __cachefs_get_page_block(ixpage)->bix;
-	trans->jentry->upentry	= ixoffset;
+	trans->jentry->block	= __cachefs_get_page_block(ixpage)->bix;
+	trans->jentry->entry	= ixoffset;
+	trans->jentry->auxblock	= inode->metadata->bix;
+	trans->jentry->auxentry	= inode->metadata_offset;
 
 	cachefs_trans_affects_page(trans, __cachefs_page_get_private(ixpage),
 				   ixoffset, sizeof(*xent));
@@ -535,8 +539,8 @@
 		      struct cachefs_cookie *cookie,
 		      unsigned *_newino)
 {
-	struct cachefs_ondisc_ujnl_index *jindex;
 	struct cachefs_ondisc_index_entry *xent;
+	struct cachefs_ondisc_ujnl_index *jindex;
 	struct cachefs_ondisc_metadata *metadata;
 	struct cachefs_search_result *srch;
 	struct cachefs_transaction *trans;
@@ -578,6 +582,9 @@
 
 	offset = (ixentry % index->index_epp) * index->index_esize;
 
+	ino_offset = ino % super->imetadata->index_epp;
+	ino_offset <<= super->layout->metadata_bits;
+
 	trans->jentry->mark = CACHEFS_ONDISC_UJNL_INDEX_CREATING;
 	if (!cookie->idef)
 		trans->jentry->mark = CACHEFS_ONDISC_UJNL_INODE_CREATING;
@@ -590,11 +597,13 @@
 	trans->jentry->block	= __cachefs_get_page_block(ixpage)->bix;
 	trans->jentry->entry	= offset;
 	trans->jentry->count	= index->index_esize;
-	trans->jentry->auxblock	= inonext;
-	trans->jentry->upblock	= ixnext;
+	trans->jentry->auxblock	= __cachefs_get_page_block(inopage)->bix;
+	trans->jentry->auxentry	= ino_offset;
+	trans->jentry->upblock	= index->metadata->bix;
+	trans->jentry->upentry	= index->metadata_offset;
 
-	ino_offset = ino % super->imetadata->index_epp;
-	ino_offset <<= super->layout->metadata_bits;
+	jindex->next_ino	= inonext;
+	jindex->next_index	= ixnext;
 
 	cachefs_trans_affects_page(trans, __cachefs_page_get_private(ixpage),
 				   offset, index->index_esize);
@@ -646,7 +655,7 @@
 	if (cookie->idef)
 		xent->type = CACHEFS_ONDISC_INDEX_INDEXFILE;
 
-	memcpy(xent->data, jindex->data, jindex->def.dsize);
+	memcpy(xent->data, jindex->data, index->index_dsize);
 
 	kunmap(ixpage);
 
@@ -707,7 +716,7 @@
  * mark the next inode pinned by an entry in the index currently being
  * reclaimed as being obsolete
  */
-int cachefs_index_zap(struct cachefs_super *super)
+int cachefs_index_reclaim_one_entry(struct cachefs_super *super)
 {
 	struct cachefs_ondisc_index_entry *xent;
 	struct cachefs_ondisc_metadata *metadata;
@@ -760,6 +769,11 @@
 	trans->jentry->ino	= inode->vfs_inode.i_ino;
 	trans->jentry->index	= super->rcm_ino;
 	trans->jentry->ixentry	= super->rcm_block;
+	trans->jentry->pgnum	= page->index;
+	trans->jentry->block	= __cachefs_get_page_block(page)->bix;
+	trans->jentry->entry	= offset;
+	trans->jentry->auxblock	= inode->metadata->bix;
+	trans->jentry->auxentry	= inode->metadata_offset;
 
 	cachefs_trans_affects_inode(trans, inode);
 
@@ -807,4 +821,4 @@
 
 	_leave(" = %d", ret);
 	return ret;
-} /* end cachefs_index_zap() */
+} /* end cachefs_index_reclaim_one_entry() */

Index: dump-journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/dump-journal.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- dump-journal.c	9 Jul 2003 10:39:50 -0000	1.13
+++ dump-journal.c	10 Jul 2003 14:21:24 -0000	1.14
@@ -169,7 +169,7 @@
 		       " " CYAN		"%5u"	GREY	"."	NORMAL	"%-5u"	NORMAL
 		       " "		"%s"		" %4d"
 		       " " YELLOW	"%8x"	NORMAL	" %8u"
-		       " " YELLOW	"%8u"	GREY	":"	NORMAL	"%-4hu"
+		       " " YELLOW	"%8x"	GREY	":"	NORMAL	"%-4hu"
 		       " " YELLOW	"%8d"	GREY	"+"	NORMAL	"%-4hu"
 		       " " YELLOW	"%8d"	GREY	"+"	NORMAL	"%-4hu"
 		       " " YELLOW	"%8d"	GREY	"+"	NORMAL	"%-4hu"

Index: cachefs-layout.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-layout.h,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- cachefs-layout.h	9 Jul 2003 10:39:50 -0000	1.29
+++ cachefs-layout.h	10 Jul 2003 14:21:24 -0000	1.30
@@ -248,19 +248,46 @@
 	 * - block	= block holding index entry being allocated
 	 * - entry	= offset of entry in block
 	 * - ino	= inode being attached to hold index contents
-	 * - upblock	= next free index file entry
-	 * - count	= size of entry in block
+	 * - auxblock	= metadata file block holding inode metadata
+	 * - auxentry	= offset of entry in auxblock
+	 * - upblock	= metadata file block holding index metadata
+	 * - upentry	= offset of entry in upblock
+	 * - count	= size of index entry in block
+	 * - ixdata	= index data
+	 * - next_ino	= next free metadata file entry
+	 * - next_index	= next free index file entry
 	 */
 	CACHEFS_ONDISC_UJNL_INODE_CREATING,
 
 	/* data file being updated */
 	CACHEFS_ONDISC_UJNL_INODE_UPDATING,
 
-	/* data or index file being deleted */
+	/* data or index file being deleted
+	 * - index	= parent index being attached to [opt]
+	 * - ixentry	= entry in parent index [opt]
+	 * - pgnum	= page in file holding index entry being allocated [opt]
+	 * - block	= block holding index entry being allocated [opt]
+	 * - entry	= offset of entry in block [opt]
+	 * - ino	= inode being attached to hold index contents
+	 * - auxblock	= metadata file block holding inode metadata
+	 * - auxentry	= offset of entry in auxblock
+	 * - upblock	= metadata file block holding index metadata [opt]
+	 * - upentry	= offset of entry in upblock [opt]
+	 * - count	= size of index entry in block [opt]
+	 * - next_ino	= next free metadata file entry
+	 * - next_index	= next free index file entry [opt]
+	 */
 	CACHEFS_ONDISC_UJNL_INODE_DELETING,
 
 	/* inode being marked for reclamation
 	 * - ino	= target inode
+	 * - index	= inode's parent index
+	 * - ixentry	= inode's parent index entry
+	 * - pgnum	= page in index holding entry being marked
+	 * - block	= metadata file block holding index metadata
+	 * - entry	= offset of entry in upblock
+	 * - auxblock	= metadata file block holding inode metadata
+	 * - auxentry	= offset of entry in auxblock
 	 */
 	CACHEFS_ONDISC_UJNL_INODE_MARK_RECLAIM,
 
@@ -268,6 +295,11 @@
 	 * - ino	= target inode
 	 * - index	= inode's parent index
 	 * - ixentry	= inode's parent index entry
+	 * - pgnum	= page in index holding entry being marked
+	 * - block	= metadata file block holding index metadata
+	 * - entry	= offset of entry in upblock
+	 * - auxblock	= metadata file block holding inode metadata
+	 * - auxentry	= offset of entry in auxblock
 	 */
 	CACHEFS_ONDISC_UJNL_INODE_RECLAIMING,
 
@@ -337,8 +369,14 @@
 	 * - block	= block holding index entry being allocated
 	 * - entry	= offset of entry in block
 	 * - ino	= inode being attached to hold index contents
-	 * - upblock	= next free index file entry
-	 * - count	= size of entry in block
+	 * - auxblock	= metadata file block holding inode metadata
+	 * - auxentry	= offset of entry in auxblock
+	 * - upblock	= metadata file block holding index metadata
+	 * - upentry	= offset of entry in upblock
+	 * - count	= size of index entry in block
+	 * - ixdata	= index definition and data
+	 * - next_ino	= next free metadata file entry
+	 * - next_index	= next free index file entry
 	 */
 	CACHEFS_ONDISC_UJNL_INDEX_CREATING,
 
@@ -349,6 +387,7 @@
 	 * - block	= block holding index entry being allocated
 	 * - entry	= offset of entry in block
 	 * - count	= size of entry in block
+	 * - ixdata	= revised index data
 	 */
 	CACHEFS_ONDISC_UJNL_INDEX_UPDATING,
 
@@ -357,6 +396,8 @@
 
 struct cachefs_ondisc_ujnl_index {
 	struct cachefs_ondisc_index_def	def;
+	u_int32_t			next_ino;	/* next inode entry */
+	u_int32_t			next_index;	/* next index entry */
 	u_int8_t			data[0];
 };

Index: cachefs-int.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-int.h,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- cachefs-int.h	9 Jul 2003 10:39:50 -0000	1.38
+++ cachefs-int.h	10 Jul 2003 14:21:24 -0000	1.39
@@ -451,7 +451,7 @@
 			     struct cachefs_cookie *cookie,
 			     unsigned *_newino);
 
-extern int cachefs_index_zap(struct cachefs_super *super);
+extern int cachefs_index_reclaim_one_entry(struct cachefs_super *super);
 
 /*****************************************************************************/
 /*

Index: block.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/block.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- block.c	4 Jul 2003 09:04:44 -0000	1.8
+++ block.c	10 Jul 2003 14:21:24 -0000	1.9
@@ -435,6 +435,8 @@
 
 	*_block = NULL;
 
+	BUG_ON(bix > super->sb->s_bdev->bd_inode->i_size / PAGE_SIZE);
+
 	/* allocate a block record just in case */
 	newblock = kmem_cache_alloc(cachefs_block_jar, SLAB_KERNEL);
 	if (!newblock)