Subject: afs/fs/cachefs replay.c,1.2,1.3 journal.c,1.41,1.42 dump-journal.c,1.15,1.16 cachefs-layout.h,1.32,1.33cachefs-int.h,1.39,1.40

From: [email-masked]
Date: Fri, 18 Jul 2003 09:55:01 +0100

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

Modified Files:
	replay.c journal.c dump-journal.c cachefs-layout.h 
	cachefs-int.h 
Log Message:
finished writing u-journal replay functions

Index: replay.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/replay.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- replay.c	10 Jul 2003 14:21:23 -0000	1.2
+++ replay.c	18 Jul 2003 08:54:58 -0000	1.3
@@ -18,9 +18,11 @@
 #include "cachefs-int.h"
 
 #define UJNL_WRAP(X) ((X) & (CACHEFS_ONDISC_UJNL_NUMENTS - 1))
-#define BLOCK_VALID(BLOCK,JENTRY) \
+#define BLOCK_VALID(BLOCK,PAGE,JENTRY) \
 	((BLOCK) && \
-	 (u_int16_t) (unsigned long) (BLOCK)->ref <= (JENTRY)->serial)
+	 (u_int16_t) (unsigned long) (BLOCK)->ref <= (JENTRY)->serial && \
+	 (wait_on_page_locked((PAGE)), 1) \
+	)
 
 struct cachefs_replay_find_batch_desc {
 	read_descriptor_t	desc;
@@ -82,9 +84,6 @@
 static int cachefs_replay_ujnl_indirect_allocing(struct cachefs_super *super,
 						 struct cachefs_ondisc_update_journal *jentry,
 						 struct cachefs_transaction *trans);
-static int cachefs_replay_ujnl_indirect_freeing(struct cachefs_super *super,
-						struct cachefs_ondisc_update_journal *jentry,
-						struct cachefs_transaction *trans);
 
 static const cachefs_ujnl_replay_func_t cachefs_ujnl_replay_tbl[CACHEFS_ONDISC_UJNL__LAST] = {
 	[CACHEFS_ONDISC_UJNL_RECYC_BEGIN_NEW]	= cachefs_replay_ujnl_recyc_begin_new,
@@ -100,7 +99,6 @@
 	[CACHEFS_ONDISC_UJNL_DATA_WRITTEN]	= cachefs_replay_ujnl_data_written,
 	[CACHEFS_ONDISC_UJNL_DATA_UNALLOCING]	= cachefs_replay_ujnl_data_unallocing,
 	[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_inode_creating,
 	[CACHEFS_ONDISC_UJNL_INDEX_UPDATING]	= cachefs_replay_ujnl_index_modifying
@@ -229,12 +227,12 @@
 				super->rcm_ino		= jentry->rcm_ino;
 
 				kdebug("UJNL[%u] ACK %u"
-				       " { a=%u[%u] r=%u R=%u:%u:%u[%u-%u] }"
+				       " { a=%x[%u] r=%x R=%x:%u:%x[%u-%u] }"
 				       " hi=%u",
 				       slot,
 				       jentry->batch,
-				       super->alloc_leaf,
 				       super->alloc_cur,
+				       super->alloc_leaf,
 				       super->recycle_cur,
 				       super->rcm_ino,
 				       super->rcm_indirect,
@@ -547,7 +545,7 @@
 		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);
@@ -575,9 +573,9 @@
 
 	kdebug("UJNL slot window: next head=%hu tail=%hu",
 	       super->ujnl_head, super->ujnl_tail);
-	kdebug("UJNL Alloc stacks: A=%u[%u] R=%u",
+	kdebug("UJNL Alloc stacks: A=%x[%u] R=%x",
 	       super->alloc_cur, super->alloc_leaf, super->recycle_cur);
-	kdebug("UJNL Recycling: %u:%u:%u:%u-%u",
+	kdebug("UJNL Recycling: %x.%u: %x:%u-%u",
 	       super->rcm_ino, super->rcm_indirect, super->rcm_block,
 	       super->rcm_ptrnext, super->rcm_ptrstop);
 
@@ -688,13 +686,12 @@
 
 	/* we need to fix up the recycling block node header if the block is
 	 * currently part of one of the recycling chains */
-	if (BLOCK_VALID(block, jentry)) {
+	if (BLOCK_VALID(block, page, jentry)) {
 		node = kmap(page);
-
-		if (node->next != jentry->auxblock) {
-			node->next = jentry->auxblock;
-			cachefs_trans_replays_effect(trans, block);
-		}
+		clear_page(node);
+		node->next  = jentry->index;
+		node->count = jentry->ixentry;
+		cachefs_trans_replays_effect(trans, block);
 		kunmap(page);
 	}
 
@@ -731,7 +728,7 @@
 		if (ret < 0)
 			goto error;
 
-		if (BLOCK_VALID(block, jentry)) {
+		if (BLOCK_VALID(block, page, jentry)) {
 			node = kmap(page);
 
 			if (node->next || node->count) {
@@ -783,7 +780,7 @@
 		goto error2;
 	}
 
-	if (BLOCK_VALID(block, jentry)) {
+	if (BLOCK_VALID(block, page, jentry)) {
 		node = kmap(page);
 
 		if (memcmp(&node->leaves[jentry->auxblock],
@@ -854,7 +851,7 @@
 	kunmap(spage);
 
 	/* we need to reload the pointers cached into the recycling block */
-	if (BLOCK_VALID(block, jentry)) {
+	if (BLOCK_VALID(block, page, jentry)) {
 		node = kmap(page);
 
 		if (memcmp(&node->leaves[jentry->auxblock],
@@ -926,8 +923,9 @@
 		type = CACHEFS_ONDISC_INDEX_INDEXFILE;
 
 	/* make sure the metadata file's freelink pointer is correct */
-	if (BLOCK_VALID(metameta, jentry)) {
-		metadata = kmap(metapage);
+	if (BLOCK_VALID(metameta, metapage, jentry)) {
+		metadata = kmap(metapage) +
+			super->layout->metadata_size * CACHEFS_INO_METADATA;
 		if (metadata->freelink != jindex->next_ino) {
 			metadata->freelink = jindex->next_ino;
 			cachefs_trans_replays_effect(trans, metameta);
@@ -936,8 +934,8 @@
 	}
 
 	/* make sure the index file's freelink pointer is correct */
-	if (BLOCK_VALID(indexmeta, jentry)) {
-		metadata = kmap(ixmpage);
+	if (BLOCK_VALID(indexmeta, ixmpage, jentry)) {
+		metadata = kmap(ixmpage) + jentry->upentry;
 		if (metadata->freelink	!= jindex->next_index ||
 		    metadata->size	!= jentry->size) {
 			metadata->freelink	= jindex->next_index;
@@ -948,8 +946,8 @@
 	}
 
 	/* make sure the new inode's metadata contains the right data */
-	if (BLOCK_VALID(inometa, jentry)) {
-		metadata = kmap(inompage);
+	if (BLOCK_VALID(inometa, inompage, jentry)) {
+		metadata = kmap(inompage) + jentry->auxentry;
 		if (metadata->header.state != CACHEFS_ONDISC_INDEX_ACTIVE ||
 		    metadata->header.type  != type ||
 		    metadata->header.ino   != 0xfefdfc ||
@@ -978,8 +976,8 @@
 	}
 
 	/* make sure the index data is written into the index entry */
-	if (BLOCK_VALID(indexdata, jentry)) {
-		xent = kmap(ixdatapage);
+	if (BLOCK_VALID(indexdata, ixdatapage, jentry)) {
+		xent = kmap(ixdatapage) + jentry->entry;
 		if (xent->state	!= CACHEFS_ONDISC_INDEX_ACTIVE	||
 		    xent->type	!= type				||
 		    xent->ino	!= jentry->ino			||
@@ -1068,8 +1066,9 @@
 	}
 
 	/* make sure the metadata file's freelink pointer is correct */
-	if (BLOCK_VALID(metameta, jentry)) {
-		metadata = kmap(metapage);
+	if (BLOCK_VALID(metameta, metapage, jentry)) {
+		metadata = kmap(metapage) +
+			super->layout->metadata_size * CACHEFS_INO_METADATA;
 		if (metadata->freelink != jindex->next_ino) {
 			metadata->freelink = jindex->next_ino;
 			cachefs_trans_replays_effect(trans, metameta);
@@ -1078,8 +1077,8 @@
 	}
 
 	/* make sure the index file's freelink pointer is correct */
-	if (BLOCK_VALID(indexmeta, jentry)) {
-		metadata = kmap(ixmpage);
+	if (BLOCK_VALID(indexmeta, ixmpage, jentry)) {
+		metadata = kmap(ixmpage) + jentry->upentry;;
 		if (metadata->freelink	!= jindex->next_index ||
 		    metadata->size	!= jentry->size) {
 			metadata->freelink	= jindex->next_index;
@@ -1090,8 +1089,8 @@
 	}
 
 	/* make sure the deleted inode's metadata contains the right data */
-	if (BLOCK_VALID(inometa, jentry)) {
-		metadata = kmap(inompage);
+	if (BLOCK_VALID(inometa, inompage, jentry)) {
+		metadata = kmap(inompage) + jentry->auxentry;
 		if (metadata->header.state	!= CACHEFS_ONDISC_INDEX_FREE ||
 		    metadata->header.type	!= 0			||
 		    metadata->header.ino	!= 0xfefdfc		||
@@ -1114,8 +1113,8 @@
 	}
 
 	/* make sure the index data is written into the index entry */
-	if (BLOCK_VALID(indexdata, jentry)) {
-		xent = kmap(ixdatapage);
+	if (BLOCK_VALID(indexdata, ixdatapage, jentry)) {
+		xent = kmap(ixdatapage) + jentry->entry;
 		if (xent->state	!= CACHEFS_ONDISC_INDEX_FREE	||
 		    xent->type	!= 0				||
 		    xent->ino	!= 0				||
@@ -1177,8 +1176,8 @@
 		goto error2;
 
 	/* make sure the inode's metadata is set to the right state */
-	if (BLOCK_VALID(inometa, jentry)) {
-		metadata = kmap(inompage);
+	if (BLOCK_VALID(inometa, inompage, jentry)) {
+		metadata = kmap(inompage) + jentry->auxentry;
 		if (metadata->header.state != CACHEFS_ONDISC_INDEX_RECYCLE) {
 			metadata->header.state = CACHEFS_ONDISC_INDEX_FREE;
 
@@ -1188,8 +1187,8 @@
 	}
 
 	/* make sure the index entry is also set to the right state */
-	if (BLOCK_VALID(indexdata, jentry)) {
-		xent = kmap(ixdatapage);
+	if (BLOCK_VALID(indexdata, ixdatapage, jentry)) {
+		xent = kmap(ixdatapage) + jentry->entry;
 		if (xent->state	!= CACHEFS_ONDISC_INDEX_FREE) {
 			xent->state	= CACHEFS_ONDISC_INDEX_FREE;
 
@@ -1232,31 +1231,212 @@
 					       struct cachefs_ondisc_update_journal *jentry,
 					       struct cachefs_transaction *trans)
 {
-	
+	struct cachefs_ondisc_index_entry *xent;
+	struct cachefs_ondisc_metadata *metadata;
+	struct cachefs_block *indexmeta, *indexptr, *indexdata;
+	cachefs_blockix_t *ptr;
+	struct page *metapage, *ptrpage, *datapage;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	ret = cachefs_block_read(super, NULL, jentry->auxblock, 0,
+				 &indexmeta, &metapage);
+	if (ret < 0)
+		goto error;
+
+	ret = cachefs_block_read(super, NULL, jentry->upblock, 0,
+				 &indexptr, &ptrpage);
+	if (ret < 0)
+		goto error2;
+
+	ret = cachefs_block_read(super, NULL, jentry->block, 0,
+				 &indexdata, &datapage);
+	if (ret < 0)
+		goto error3;
 
-	return -ENOANO;
+	/* make sure the index file's freelink pointer is correct */
+	if (BLOCK_VALID(indexmeta, metapage, jentry)) {
+		metadata = kmap(metapage) + jentry->auxentry;
+		if (metadata->freelink	!= jentry->ixentry ||
+		    metadata->size	!= jentry->size) {
+			metadata->freelink	= jentry->ixentry;
+			metadata->size		= jentry->size;
+			cachefs_trans_replays_effect(trans, indexmeta);
+		}
+		kunmap(metapage);
+	}
+
+	/* make sure the new block is pointed to by the appropriate pointer */
+	if (BLOCK_VALID(indexptr, ptrpage, jentry)) {
+		ptr = kmap(ptrpage) + jentry->upentry;
+		if (*ptr != jentry->block) {
+			*ptr = jentry->block;
+
+			cachefs_trans_replays_effect(trans, indexptr);
+		}
+		kunmap(ptrpage);
+	}
+
+	/* make sure the index data page is initialised */
+	if (BLOCK_VALID(indexdata, datapage, jentry)) {
+		u_int32_t entry, next;
+		void *content;
+		int loop;
+
+		next = jentry->index;
+		entry = jentry->ixentry;
+
+		content = kmap(datapage);
+		clear_page(content);
+
+		for (loop = PAGE_SIZE / jentry->count - 1; loop >= 0; loop--) {
+			xent = content + loop * jentry->count;
+			xent->state		= CACHEFS_ONDISC_INDEX_FREE;
+			xent->freelink[0]	= next;
+			next = entry + loop;
+		}
+
+		cachefs_trans_replays_effect(trans, indexdata);
+		kunmap(datapage);
+	}
+
+	cachefs_block_put(indexdata);
+	cachefs_put_page(datapage);
+ error3:
+	cachefs_block_put(indexptr);
+	cachefs_put_page(ptrpage);
+ error2:
+	cachefs_block_put(indexmeta);
+	cachefs_put_page(metapage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_index_extending() */
 
 /*****************************************************************************/
 /*
- *
+ * replay the modification of the data in an index entry
  */
 static int cachefs_replay_ujnl_index_modifying(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_block *indexdata;
+	struct page *ixdatapage;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	jindex = &jentry->ixdata[0];
+
+	ret = cachefs_block_read(super, NULL, jentry->block, 0,
+				 &indexdata, &ixdatapage);
+	if (ret < 0)
+		goto error;
+
+	/* make sure the index data is written into the index entry */
+	if (BLOCK_VALID(indexdata, ixdatapage, jentry)) {
+		xent = kmap(ixdatapage) + jentry->entry;
+		if (memcmp(xent->data, jindex->data, jindex->def.dsize) != 0) {
+			memcpy(xent->data, jindex->data, jindex->def.dsize);
+
+			cachefs_trans_replays_effect(trans, indexdata);
+		}
+		kunmap(ixdatapage);
+	}
+
+	cachefs_block_put(indexdata);
+	cachefs_put_page(ixdatapage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_index_modifying() */
 
 /*****************************************************************************/
 /*
- * replay data block allocation and v-journal set
+ * replay data block allocation and v-journal entry marking
  */
 static int cachefs_replay_ujnl_data_allocing(struct cachefs_super *super,
 					     struct cachefs_ondisc_update_journal *jentry,
 					     struct cachefs_transaction *trans)
 {
-	return -ENOANO;
+	struct cachefs_ondisc_validity_journal *vjentry;
+	struct cachefs_ondisc_metadata *metadata;
+	struct cachefs_block *metablock, *ptrblock, *vjblock;
+	cachefs_blockix_t *ptr, vjbix;
+	struct page *metapage, *ptrpage, *vjpage;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	ret = cachefs_block_read(super, NULL, jentry->auxblock, 0,
+				 &metablock, &metapage);
+	if (ret < 0)
+		goto error;
+
+	ret = cachefs_block_read(super, NULL, jentry->upblock, 0,
+				 &ptrblock, &ptrpage);
+	if (ret < 0)
+		goto error2;
+
+	vjbix = super->layout->bix_vjournal;
+	vjbix += (jentry->auxmark / CACHEFS_ONDISC_VJNL_ENTPERPAGE) *
+		sizeof(struct cachefs_ondisc_validity_journal);
+
+	ret = cachefs_block_read(super, NULL, vjbix, 0,
+				 &vjblock, &vjpage);
+	if (ret < 0)
+		goto error3;
+
+	/* make sure the datafile's size is correct */
+	if (BLOCK_VALID(metablock, metapage, jentry)) {
+		metadata = kmap(metapage) + jentry->auxentry;
+		if (metadata->size	!= jentry->size) {
+			metadata->size		= jentry->size;
+			cachefs_trans_replays_effect(trans, metablock);
+		}
+		kunmap(metapage);
+	}
+
+	/* make sure the new block is pointed to by the appropriate pointer */
+	if (BLOCK_VALID(ptrblock, ptrpage, jentry)) {
+		ptr = kmap(ptrpage) + jentry->upentry;
+		if (*ptr != jentry->block) {
+			*ptr = jentry->block;
+
+			cachefs_trans_replays_effect(trans, ptrblock);
+		}
+		kunmap(ptrpage);
+	}
+
+	/* make sure the vjournal entry is marked */
+	vjentry = kmap(vjpage) + 
+		(jentry->auxmark % CACHEFS_ONDISC_VJNL_ENTPERPAGE) *
+		sizeof(struct cachefs_ondisc_validity_journal);
+
+	if (vjentry->ino	!= jentry->ino &&
+	    vjentry->pgnum	!= jentry->pgnum) {
+		vjentry->ino	= jentry->ino;
+		vjentry->pgnum	= jentry->pgnum;
+
+		cachefs_trans_replays_effect(trans, vjblock);
+	}
+	kunmap(vjpage);
+
+	cachefs_block_put(vjblock);
+	cachefs_put_page(vjpage);
+ error3:
+	cachefs_block_put(ptrblock);
+	cachefs_put_page(ptrpage);
+ error2:
+	cachefs_block_put(metablock);
+	cachefs_put_page(metapage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_data_allocing() */
 
 /*****************************************************************************/
@@ -1267,7 +1447,42 @@
 					    struct cachefs_ondisc_update_journal *jentry,
 					    struct cachefs_transaction *trans)
 {
-	return -ENOANO;
+	struct cachefs_ondisc_validity_journal *vjentry;
+	struct cachefs_block *vjblock;
+	cachefs_blockix_t vjbix;
+	struct page *vjpage;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	vjbix = super->layout->bix_vjournal;
+	vjbix += (jentry->auxmark / CACHEFS_ONDISC_VJNL_ENTPERPAGE) *
+		sizeof(struct cachefs_ondisc_validity_journal);
+
+	ret = cachefs_block_read(super, NULL, vjbix, 0,
+				 &vjblock, &vjpage);
+	if (ret < 0)
+		goto error;
+
+	/* make sure the vjournal entry is cleared */
+	vjentry = kmap(vjpage) + 
+		(jentry->auxmark % CACHEFS_ONDISC_VJNL_ENTPERPAGE) *
+		sizeof(struct cachefs_ondisc_validity_journal);
+
+	if (vjentry->ino	!= 0 &&
+	    vjentry->pgnum	!= 0) {
+		vjentry->ino	= 0;
+		vjentry->pgnum	= 0;
+
+		cachefs_trans_replays_effect(trans, vjblock);
+	}
+	kunmap(vjpage);
+
+	cachefs_block_put(vjblock);
+	cachefs_put_page(vjpage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_data_written() */
 
 /*****************************************************************************/
@@ -1278,7 +1493,107 @@
 					       struct cachefs_ondisc_update_journal *jentry,
 					       struct cachefs_transaction *trans)
 {
-	return -ENOANO;
+	struct cachefs_ondisc_validity_journal *vjentry;
+	struct cachefs_ondisc_free_node *node;
+	struct cachefs_block *ptrblock, *vjblock;
+	struct cachefs_block *deadblock = NULL, *rcyblock = NULL;
+	cachefs_blockix_t vjbix, *pbix;
+	struct page *ptrpage, *vjpage;
+	struct page *deadpage = NULL, *rcypage = NULL;
+	int ret;
+
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	ret = cachefs_block_read(super, NULL, jentry->upblock, 0,
+				 &ptrblock, &ptrpage);
+	if (ret < 0)
+		goto error;
+
+	vjbix = super->layout->bix_vjournal;
+	vjbix += (jentry->auxmark / CACHEFS_ONDISC_VJNL_ENTPERPAGE) *
+		sizeof(struct cachefs_ondisc_validity_journal);
+
+	ret = cachefs_block_read(super, NULL, vjbix, 0,
+				 &vjblock, &vjpage);
+	if (ret < 0)
+		goto error2;
+
+	if (trans->jentry->auxentry == (u_int16_t) ~0) {
+		/* block made new node on recycling stack */
+		ret = cachefs_block_read(super, NULL, trans->jentry->block, 0,
+					 &deadblock, &deadpage);
+		if (ret < 0)
+			goto error3;
+	} else {
+		/* block depends from current node in recycling stack */
+		ret = cachefs_block_read(super, NULL, trans->jentry->auxblock,
+					 0, &rcyblock, &rcypage);
+		if (ret < 0)
+			goto error3;
+	}
+
+	/* make sure the block is no longer pointed to by the appropriate pointer */
+	if (BLOCK_VALID(ptrblock, ptrpage, jentry)) {
+		pbix = kmap(ptrpage) + jentry->upentry;
+		if (*pbix != 0) {
+			*pbix = 0;
+
+			cachefs_trans_replays_effect(trans, ptrblock);
+		}
+		kunmap(ptrpage);
+	}
+
+	/* make sure the vjournal entry is cleared */
+	vjentry = kmap(vjpage) + 
+		(jentry->auxmark % CACHEFS_ONDISC_VJNL_ENTPERPAGE) *
+		sizeof(struct cachefs_ondisc_validity_journal);
+
+	if (vjentry->ino	!= 0 &&
+	    vjentry->pgnum	!= 0) {
+		vjentry->ino	= 0;
+		vjentry->pgnum	= 0;
+
+		cachefs_trans_replays_effect(trans, vjblock);
+	}
+	kunmap(vjpage);
+
+	/* make sure the dead block is correctly set up as a node in the
+	 * recycling stack */
+	if (BLOCK_VALID(deadblock, deadpage, jentry)) {
+		node = kmap(deadpage);
+		clear_page(node);
+		node->next  = trans->jentry->index;
+		node->count = trans->jentry->ixentry;
+		kunmap(deadpage);
+
+		cachefs_trans_replays_effect(trans, deadblock);
+	}
+
+	/* alternatively, make sure the dead block now depends from a node in
+	 * the recycling stack */
+	if (BLOCK_VALID(rcyblock, rcypage, jentry)) {
+		node = kmap(rcypage);
+		pbix = &node->leaves[trans->jentry->auxentry];
+		if (*pbix != trans->jentry->block) {
+			*pbix = trans->jentry->block;
+			cachefs_trans_replays_effect(trans, rcyblock);
+		}
+		kunmap(deadpage);
+	}
+
+	cachefs_block_put(rcyblock);
+	cachefs_put_page(rcypage);
+	cachefs_block_put(deadblock);
+	cachefs_put_page(deadpage);
+ error3:
+	cachefs_block_put(vjblock);
+	cachefs_put_page(vjpage);
+ error2:
+	cachefs_block_put(ptrblock);
+	cachefs_put_page(ptrpage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
 } /* end cachefs_replay_ujnl_data_unallocing() */
 
 /*****************************************************************************/
@@ -1289,16 +1604,49 @@
 						 struct cachefs_ondisc_update_journal *jentry,
 						 struct cachefs_transaction *trans)
 {
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_indirect_allocing() */
+	struct cachefs_block *ptrblock, *indblock;
+	cachefs_blockix_t *ptr;
+	struct page *ptrpage, *indpage;
+	void *content;
+	int ret;
 
-/*****************************************************************************/
-/*
- * replay indirection block freeing
- */
-static int cachefs_replay_ujnl_indirect_freeing(struct cachefs_super *super,
-						struct cachefs_ondisc_update_journal *jentry,
-						struct cachefs_transaction *trans)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_indirect_freeing() */
+	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+
+	ret = cachefs_block_read(super, NULL, jentry->upblock, 0,
+				 &ptrblock, &ptrpage);
+	if (ret < 0)
+		goto error;
+
+	ret = cachefs_block_read(super, NULL, jentry->block, 0,
+				 &indblock, &indpage);
+	if (ret < 0)
+		goto error2;
+
+	/* make sure the new block is pointed to by the appropriate pointer */
+	if (BLOCK_VALID(ptrblock, ptrpage, jentry)) {
+		ptr = kmap(ptrpage) + jentry->upentry;
+		if (*ptr != jentry->block) {
+			*ptr = jentry->block;
+
+			cachefs_trans_replays_effect(trans, ptrblock);
+		}
+		kunmap(ptrpage);
+	}
+
+	/* make sure the indirection block is cleared */
+	if (BLOCK_VALID(indblock, indpage, jentry)) {
+		content = kmap(indpage);
+		clear_page(content);
+		cachefs_trans_replays_effect(trans, indblock);
+		kunmap(indpage);
+	}
+
+	cachefs_block_put(indblock);
+	cachefs_put_page(indpage);
+ error2:
+	cachefs_block_put(ptrblock);
+	cachefs_put_page(ptrpage);
+ error:
+	kleave(" = %d", ret);
+	return ret;
+} /* end cachefs_replay_ujnl_indirect_allocing() */

Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- journal.c	17 Jul 2003 12:02:13 -0000	1.41
+++ journal.c	18 Jul 2003 08:54:58 -0000	1.42
@@ -37,7 +37,6 @@
 	"DataWritn",
 	"DataUnalc",
 	"AllocIndr",
-	"FreeIndr ",
 	"ExtendIdx",
 	"CreateIdx",
 	"UpdateIdx",

Index: dump-journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/dump-journal.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- dump-journal.c	17 Jul 2003 12:02:13 -0000	1.15
+++ dump-journal.c	18 Jul 2003 08:54:58 -0000	1.16
@@ -52,13 +52,12 @@
 	BRIGHT	"CrtData  "	NORMAL,
 	BRIGHT	"UpdData  "	NORMAL,
 	BRIGHT	"DelInode "	NORMAL,
-	BRIGHT	"InoMkRcm "	NORMAL,
-	BRIGHT	"InoRcming"	NORMAL,
+	BRIGHT	"MarkReclm"	NORMAL,
+	BRIGHT	"Reclaim  "	NORMAL,
 	BRIGHT	"DataAlloc"	NORMAL,
 	BRIGHT	"DataWrite"	NORMAL,
 	BRIGHT	"DataUnalc"	NORMAL,
 	BRIGHT	"IndrAlloc"	NORMAL,
-	BRIGHT	"IndrFree "	NORMAL,
 	BRIGHT	"ExtnIndex"	NORMAL,
 	BRIGHT	"CrtIndex "	NORMAL,
 	BRIGHT	"UpdIndex "	NORMAL,

Index: cachefs-layout.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-layout.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- cachefs-layout.h	17 Jul 2003 12:02:13 -0000	1.32
+++ cachefs-layout.h	18 Jul 2003 08:54:58 -0000	1.33
@@ -352,16 +352,6 @@
 	 */
 	CACHEFS_ONDISC_UJNL_INDIRECT_ALLOCING,
 
-	/* indirection block being detached for recycling
-	 * - ino	= inode to which indirection block or pointers belong
-	 * - block	= block holding pointer array being processed
-	 * - entry	= index into block[] of first pointer to process
-	 * - count	= number of pointers to process
-	 * - upblock	= block holding pointer that points to this block
-	 * - upentry	= index into auxblock[] of pointer to indirection block
-	 */
-	CACHEFS_ONDISC_UJNL_INDIRECT_FREEING,
-
 	/* index file being extended (as for data block allocation)
 	 * - ino	= index inode
 	 * - pgnum	= page in file holding index entry being allocated

Index: cachefs-int.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-int.h,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- cachefs-int.h	10 Jul 2003 14:21:24 -0000	1.39
+++ cachefs-int.h	18 Jul 2003 08:54:58 -0000	1.40
@@ -451,7 +451,8 @@
 			     struct cachefs_cookie *cookie,
 			     unsigned *_newino);
 
-extern int cachefs_index_reclaim_one_entry(struct cachefs_super *super);
+extern int cachefs_index_reclaim_one_entry(struct cachefs_super *super,
+					   struct cachefs_transaction **_trans);
 
 /*****************************************************************************/
 /*
@@ -518,6 +519,14 @@
 	struct list_head		sblink;		/* next transaction in superblock's list */
 
 	atomic_t			usage;
+
+	/* keep track of special changes that must only take effect under
+	 * certain circumstances */
+	u_int16_t			changed;
+#define CACHEFS_TRANS_CHANGED_ALLOC	0x0001	/* alloc stack/leaf changed */
+#define CACHEFS_TRANS_CHANGED_RECYCLE	0x0002	/* recycle stack changed */
+#define CACHEFS_TRANS_CHANGED_RCMBLOCK	0x0004	/* inode/block being reclaimed changed */
+#define CACHEFS_TRANS_CHANGED_RCMPTR	0x0008	/* pointer being reclaimed changed */
 
 	/* tracking for blocks being modified by this transaction */
 	unsigned			eff_active;