Subject: afs/fs/cachefs replay.c,NONE,1.1 super.c,1.37,1.38 rootdir.c,1.12,1.13 recycling.c,1.24,1.25 journal.c,1.38,1.39 interface.c,1.14,1.15 inode.c,1.22,1.23 index.c,1.25,1.26 dump-journal.c,1.12,1.13 cachefs-layout.h,1.28,1.29 cachefs-int.h,1.37,1.38 aops.c,1.39,1.40 Makefile,1.16,1.17

From: [email-masked]
Date: Wed, 09 Jul 2003 11:39:53 +0100

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

Modified Files:
	super.c rootdir.c recycling.c journal.c interface.c inode.c 
	index.c dump-journal.c cachefs-layout.h cachefs-int.h aops.c 
	Makefile 
Added Files:
	replay.c 
Log Message:
done some more cleaning up
include index entry data and index definition data in journal entry
made replaying mechanism regenerate transactions that need reapplying
implemented some replaying ops

--- NEW FILE replay.c ---
/* replay.c: replay the update journal
 *
 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells ([email-masked])
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <linux/bio.h>
#include "cachefs-int.h"

[...980 lines suppressed...]
/*
 * replay indirection block allocation
 */
static int cachefs_replay_ujnl_indirect_allocing(struct cachefs_super *super,
						 struct cachefs_ondisc_update_journal *jentry,
						 struct cachefs_transaction *trans)
{
	return -ENOANO;
} /* end cachefs_replay_ujnl_indirect_allocing() */

/*****************************************************************************/
/*
 * 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() */

Index: super.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/super.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- super.c	4 Jul 2003 14:25:39 -0000	1.37
+++ super.c	9 Jul 2003 10:39:50 -0000	1.38
@@ -23,7 +23,7 @@
 
 #define CACHEFS_FS_MAGIC 0x43414653 /* 'CAFS' */
 
-static void cachefs_i_init_once(void *foo, kmem_cache_t *cachep,
+static void cachefs_i_init_once(void *_inode, kmem_cache_t *cachep,
 				unsigned long flags);
 
 static struct super_block *cachefs_get_sb(struct file_system_type *fs_type,
@@ -168,7 +168,8 @@
 
 /*****************************************************************************/
 /*
- * submit a read or a write for the page count times starting at the specified block offset
+ * submit a read or a write for the page count times starting at the specified
+ * block offset
  */
 static int cachefs_bio_submit(struct super_block *sb, struct page *page,
 			      unsigned bix, size_t *count, int rw)
@@ -192,7 +193,7 @@
 	bio->bi_end_io	= cachefs_bio_completion;
 	bio->bi_private	= NULL;
 
-	for (loop=0; loop<*count; loop++)
+	for (loop = 0; loop < *count; loop++)
 		if (!bio_add_page(bio, page, PAGE_SIZE, 0))
 			break;
 	*count = loop;
@@ -257,7 +258,7 @@
 	if (!super->rcm_atm_list)
 		goto error;
 
-	super->vjnl_map = (unsigned long*) get_zeroed_page(GFP_KERNEL);
+	super->vjnl_map = (unsigned long *) get_zeroed_page(GFP_KERNEL);
 	if (!super->vjnl_map)
 		goto error;
 
@@ -292,6 +293,7 @@
 	INIT_LIST_HEAD(&super->ujnl_writeq);
 	INIT_LIST_HEAD(&super->ujnl_ackq);
 	INIT_LIST_HEAD(&super->ujnl_ackwq);
+	INIT_LIST_HEAD(&super->ujnl_replayq);
 
 	INIT_LIST_HEAD(&super->jnld_link);
 
@@ -360,14 +362,14 @@
 
 	if (memcmp(super->layout->magic,
 		   CACHEFS_SUPER_MAGIC,
-		   CACHEFS_SUPER_MAGIC_SIZE)==0
+		   CACHEFS_SUPER_MAGIC_SIZE) == 0
 	    ) {
 		printk("CacheFS: Found initialised cache\n");
 		jnlreplay = 1;
 	}
 	else if (memcmp(super->layout->magic,
 			CACHEFS_SUPER_MAGIC_NEEDS_INIT,
-			CACHEFS_SUPER_MAGIC_SIZE)==0
+			CACHEFS_SUPER_MAGIC_SIZE) == 0
 		 ) {
 		printk("CacheFS: Found uninitialised cache\n");
 		ret = cachefs_initialise_blockdev(super);
@@ -383,17 +385,17 @@
 	super->ujnl_jsof = super->layout->bix_ujournal;
 	super->ujnl_jsof <<= (PAGE_SHIFT - super->sb->s_blocksize_bits);
 
-	/* get and retain various meta-data inodes */
-	ret = cachefs_iget(super, CACHEFS_INO_METADATA, &super->imetadata);
-	if (ret < 0)
-		goto error;
-
 	if (jnlreplay) {
 		ret = cachefs_ujnl_replay(super);
 		if (ret < 0)
 			goto error;
 	}
 
+	/* get and retain various meta-data inodes */
+	ret = cachefs_iget(super, CACHEFS_INO_METADATA, &super->imetadata);
+	if (ret < 0)
+		goto error;
+
 	kcachefs_jnld_add_super(super);
 
 	/* start the manager daemon */
@@ -414,7 +416,7 @@
 
 	sb->s_root = root;
 
-	cachefs_add_cache((struct cachefs_super *) sb->s_fs_info,srch);
+	cachefs_add_cache((struct cachefs_super *) sb->s_fs_info, srch);
 
 	kleave(" = 0 [super=%p]", super);
 	return 0;
@@ -522,17 +524,17 @@
 		super->layout->bix_wbjournal + CACHEFS_ONDISC_WBJNL_SIZE;
 	super->layout->bix_unready =
 		super->layout->bix_cache;
-	super->layout->bix_end
-		= nblocks;
+	super->layout->bix_end =
+		nblocks;
 
 	printk("CacheFS: 00000000 super block\n");
 	printk("CacheFS: 00000001 initial vnodes (%u blocks)\n", ndirect);
 
-	printk("CacheFS: %08x update journal (%u recs of %u/%ub)\n",
+	printk("CacheFS: %08x update journal (recsize %u+%ub)\n",
 	       super->layout->bix_ujournal,
-	       qty,
 	       sizeof(struct cachefs_ondisc_update_journal),
-	       super->layout->ujnl_rsize);
+	       super->layout->ujnl_rsize -
+	       sizeof(struct cachefs_ondisc_update_journal));
 
 	printk("CacheFS: %08x validity journal\n",
 	       super->layout->bix_vjournal);
@@ -546,9 +548,9 @@
 	       super->layout->bix_end);
 
 	/* initialise the metadata entry for the metadata file itself */
-	memset(data,0,PAGE_SIZE);
+	memset(data, 0, PAGE_SIZE);
 
-	for (tmp=0; tmp<PAGE_SIZE; tmp+=super->layout->metadata_size) {
+	for (tmp = 0; tmp < PAGE_SIZE; tmp += super->layout->metadata_size) {
 		metadata = (struct cachefs_ondisc_metadata *) (data + tmp);
 
 		metadata->header.state = CACHEFS_ONDISC_INDEX_FREE;
@@ -565,11 +567,11 @@
 	metadata->mtime		= CURRENT_TIME.tv_sec;
 	metadata->atime		= CURRENT_TIME.tv_sec;
 
-	metadata->index_dsize	= super->layout->metadata_size;
-	metadata->index_dsize	-= sizeof(struct cachefs_ondisc_index_entry);
-	metadata->index_esize	= super->layout->metadata_size;
+	metadata->index.dsize	= super->layout->metadata_size;
+	metadata->index.dsize	-= sizeof(struct cachefs_ondisc_index_entry);
+	metadata->index.esize	= super->layout->metadata_size;
 
-	strncpy(metadata->index_type, ".METADAT", 9);
+	strncpy(metadata->index.type, ".METADAT", 9);
 
 	for (tmp = 0; tmp < ndirect; tmp++)
 		metadata->direct[tmp] = tmp + 1; /* point to itself */
@@ -586,12 +588,12 @@
 	metadata->mtime		= CURRENT_TIME.tv_sec;
 	metadata->atime		= CURRENT_TIME.tv_sec;
 
-	metadata->index_dsize	= sizeof(struct cachefs_ondisc_fsdef);
-	metadata->index_esize	= sizeof(struct cachefs_ondisc_index_entry);
-	metadata->index_esize	+= metadata->index_dsize;
-	metadata->index_keys[0]	= CACHEFS_ONDISC_INDEXKEY_ASCIIZ | 24;
+	metadata->index.dsize	= sizeof(struct cachefs_ondisc_fsdef);
+	metadata->index.esize	= sizeof(struct cachefs_ondisc_index_entry);
+	metadata->index.esize	+= metadata->index.dsize;
+	metadata->index.keys[0]	= CACHEFS_ONDISC_INDEXKEY_ASCIIZ | 24;
 
-	strncpy(metadata->index_type, ".FSDEF", 8);
+	strncpy(metadata->index.type, ".FSDEF", 8);
 
 	tmp = 1;
 	ret = cachefs_bio_submit(super->sb, page, 1, &tmp, WRITE);
@@ -668,7 +670,8 @@
 	tmp = super->layout->bix_end;
 	tmp -= super->layout->bix_cache;
 	tmp <<= PAGE_SIZE - super->sb->s_blocksize_bits;
-	if (tmp > LONG_MAX) tmp = LONG_MAX;
+	if (tmp > LONG_MAX)
+		tmp = LONG_MAX;
 
 	buf->f_files	= tmp;
 	buf->f_ffree	= tmp;
@@ -749,7 +752,7 @@
 		}
 
 		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&super->vjnl_alloc_wq,&myself);
+		remove_wait_queue(&super->vjnl_alloc_wq, &myself);
 	}
 
 	super->dmn_die = 1;

Index: rootdir.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/rootdir.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- rootdir.c	4 Jul 2003 09:04:43 -0000	1.12
+++ rootdir.c	9 Jul 2003 10:39:50 -0000	1.13
@@ -260,7 +260,7 @@
 	rec.epp		= inode->index_esize;
 
 	metadata = cachefs_metadata_preread(inode);
-	memcpy(rec.keys, metadata->index_keys, sizeof(rec.keys));
+	memcpy(rec.keys, metadata->index.keys, sizeof(rec.keys));
 	cachefs_metadata_postread(inode);
 
 	switch (file->f_pos) {
@@ -470,7 +470,7 @@
 
 	/* construct a key to search the FSDEF index with */
 	metadata = cachefs_metadata_preread(dir);
-	memcpy(rec.keys, metadata->index_keys, sizeof(rec.keys));
+	memcpy(rec.keys, metadata->index.keys, sizeof(rec.keys));
 	cachefs_metadata_postread(dir);
 
 	for (loop = 0; loop < 4; loop++)

Index: recycling.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/recycling.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- recycling.c	4 Jul 2003 14:25:39 -0000	1.24
+++ recycling.c	9 Jul 2003 10:39:50 -0000	1.25
@@ -133,7 +133,7 @@
 	struct cachefs_ondisc_free_node *node;
 	struct cachefs_transaction *trans;
 	cachefs_blockix_t *pbix;
-	unsigned loop, qty;
+	unsigned loop, qty, pos;
 	int ret;
 
 	_enter("");
@@ -153,6 +153,8 @@
 	if (qty > super->recycle_room)
 		qty = super->recycle_room;
 
+	pos = CACHEFS_ONDISC_LEAVES_PER_FREE_NODE - super->recycle_room;
+
 	/* journal what we're going to do */
 	trans = cachefs_trans_alloc(super, GFP_KERNEL);
 	if (!trans) {
@@ -165,6 +167,7 @@
 
 	trans->jentry->mark	= CACHEFS_ONDISC_UJNL_RECYC_MAKEREADY;
 	trans->jentry->block	= super->recycle_cur;
+	trans->jentry->entry	= pos;
 	trans->jentry->auxblock	= super->layout->bix_unready;
 	trans->jentry->pgnum	= super->layout->bix_unready + qty;
 	trans->jentry->count	= qty;
@@ -994,53 +997,3 @@
 	kleave(" [error %d]", ret);
 
 } /* end cachefs_recycle_unallocate_data_block() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_recyc_empty_node(struct cachefs_super *super,
-					 struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_recyc_empty_node() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_recyc_begin_new(struct cachefs_super *super,
-					struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_recyc_begin_new() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_recyc_transfer(struct cachefs_super *super,
-				       struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_recyc_transfer() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_recyc_scavenge(struct cachefs_super *super,
-				       struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_recyc_scavenge() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_recyc_makeready(struct cachefs_super *super,
-					struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_recyc_makeready() */

Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- journal.c	4 Jul 2003 14:25:40 -0000	1.38
+++ journal.c	9 Jul 2003 10:39:50 -0000	1.39
@@ -19,15 +19,6 @@
 
 #define UJNL_WRAP(X) ((X) & (CACHEFS_ONDISC_UJNL_NUMENTS - 1))
 
-struct cachefs_replay_find_batch_desc {
-	read_descriptor_t	desc;
-	unsigned short		batch_first;	/* sector holding first entry in batch */
-	unsigned short		batch_end;	/* batch mark sector for ujnl_batch */
-	unsigned short		batch_ack;	/* batch ACK sector for ujnl_batch */
-	unsigned short		batch_count;	/* number of marks in batch */
-	int16_t			ack_hi;		/* highest batch with ACK number */
-};
-
 const char *cachefs_ondisc_ujnl_marks[] = {
 	"Null     ",
 	"Batch    ",
@@ -87,30 +78,6 @@
 	}								\
 } while(0)
 
-typedef int (*cachefs_ujnl_replay_func_t)(struct cachefs_super *super,
-					  struct cachefs_ondisc_update_journal *jentry);
-
-static const cachefs_ujnl_replay_func_t cachefs_ujnl_replay_tbl[CACHEFS_ONDISC_UJNL__LAST] = {
-	[CACHEFS_ONDISC_UJNL_RECYC_EMPTY_NODE]	= cachefs_replay_ujnl_recyc_empty_node,
-	[CACHEFS_ONDISC_UJNL_RECYC_BEGIN_NEW]	= cachefs_replay_ujnl_recyc_begin_new,
-	[CACHEFS_ONDISC_UJNL_RECYC_TRANSFER]	= cachefs_replay_ujnl_recyc_transfer,
-	[CACHEFS_ONDISC_UJNL_RECYC_SCAVENGE]	= cachefs_replay_ujnl_recyc_scavenge,
-	[CACHEFS_ONDISC_UJNL_RECYC_MAKEREADY]	= cachefs_replay_ujnl_recyc_makeready,
-	[CACHEFS_ONDISC_UJNL_INODE_CREATING]	= cachefs_replay_ujnl_inode_creating,
-	[CACHEFS_ONDISC_UJNL_INODE_UPDATING]	= cachefs_replay_ujnl_inode_updating,
-	[CACHEFS_ONDISC_UJNL_INODE_DELETING]	= cachefs_replay_ujnl_inode_deleting,
-	[CACHEFS_ONDISC_UJNL_INODE_MARK_RECLAIM]= cachefs_replay_ujnl_inode_mark_reclaim,
-	[CACHEFS_ONDISC_UJNL_INODE_RECLAIMING]	= cachefs_replay_ujnl_inode_reclaiming,
-	[CACHEFS_ONDISC_UJNL_DATA_ALLOCING]	= cachefs_replay_ujnl_data_allocing,
-	[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_index_creating,
-	[CACHEFS_ONDISC_UJNL_INDEX_UPDATING]	= cachefs_replay_ujnl_index_modifying
-};
-
 /*****************************************************************************/
 /*
  * batch write timer callback
@@ -163,6 +130,40 @@
 
 /*****************************************************************************/
 /*
+ * allocate an update-journalled transaction record and initialise it for
+ * replay
+ */
+struct cachefs_transaction *
+cachefs_trans_alloc_replay(struct cachefs_super *super,
+			   struct cachefs_ondisc_update_journal *jentry)
+{
+	struct cachefs_transaction *trans;
+
+	_enter("");
+
+	trans = kmalloc(sizeof(struct cachefs_transaction), GFP_KERNEL);
+	if (!trans) {
+		_leave(" = 0 [ENOMEM]");
+		return NULL;
+	}
+
+	memset(trans, 0, sizeof(*trans));
+
+	atomic_set(&trans->usage, 1);
+	INIT_LIST_HEAD(&trans->sblink);
+
+	trans->super	= super;
+	trans->batch	= jentry->batch;
+	trans->serial	= jentry->serial;
+	trans->phase	= CACHEFS_TRANS_MARKED;
+	trans->index	= 0;
+
+	_leave(" = %p", trans);
+	return trans;
+} /* end cachefs_trans_alloc_replay() */
+
+/*****************************************************************************/
+/*
  * release a reference to a transaction and ultimately free it
  */
 void __cachefs_trans_put(struct cachefs_transaction *trans)
@@ -184,8 +185,8 @@
 		return;
 	}
 
-	BUG_ON(trans->phase!=CACHEFS_TRANS_PREPARING &&
-	       trans->phase!=CACHEFS_TRANS_DEAD);
+	BUG_ON(trans->phase != CACHEFS_TRANS_PREPARING &&
+	       trans->phase != CACHEFS_TRANS_DEAD);
 
 	spin_lock_irqsave(&trans->super->ujnl_mk_lock, flags);
 	list_del(&trans->sblink);
@@ -467,7 +468,7 @@
 			       CACHEFS_TRANS_COMMITTING,
 			       CACHEFS_TRANS_MARKED);
 
-	for (loop=0; loop<CACHEFS_EFFECTS_PER_TRANS; loop++)
+	for (loop = 0; loop < CACHEFS_EFFECTS_PER_TRANS; loop++)
 		if (trans->effects[loop].held_page)
 			SetPageWriteback(trans->effects[loop].held_page);
 
@@ -500,6 +501,32 @@
 
 /*****************************************************************************/
 /*
+ * commit a replay transaction 
+ * - discard any transaction that is "ineffective"
+ */
+void cachefs_trans_commit_replay(struct cachefs_transaction *trans)
+{
+	int loop;
+
+	if (!trans->eff_active) {
+		cachefs_trans_put(trans);
+		return;
+	}
+
+	cachefs_ujnl_set_phase(trans,
+			       CACHEFS_TRANS_COMMITTING,
+			       CACHEFS_TRANS_MARKED);
+
+	for (loop = 0; loop < CACHEFS_EFFECTS_PER_TRANS; loop++)
+		if (trans->effects[loop].held_page)
+			SetPageWriteback(trans->effects[loop].held_page);
+
+	list_add_tail(&trans->sblink, &trans->super->ujnl_commitq);
+
+} /* end cachefs_trans_commit_replay() */
+
+/*****************************************************************************/
+/*
  * prepare a transaction for writing
  * - mark all modified journalling and data blocks for writeback
  * - mark data for COW
@@ -510,7 +537,7 @@
 {
 	struct cachefs_block *block;
 	int loop;
-	
+
 	/* mark u-journal page */
 	block = trans->jblock;
 	if (!test_and_set_bit(CACHEFS_BLOCK_WRITEBACK, &block->flags)) {
@@ -538,7 +565,7 @@
 			plist = &super->batch_writeq;
 			if (test_bit(CACHEFS_BLOCK_NETFSDATA, &block->flags)) {
 				plist = &super->batch_doneq;
-				kdebug("skip meta block %u", block->bix);
+				_debug("skip meta block %u", block->bix);
 			}
 
 			list_add_tail(&block->batch_link, plist);
@@ -597,8 +624,7 @@
 		       block->writeback);
 	}
 
-	/* decide where to put the BATCH and ACK marks and what the data for it
-	 * is */
+	/* invent BATCH and ACK marks */
 	jstop = super->ujnl_head;
 	super->ujnl_head = UJNL_WRAP(jstop + 2);
 
@@ -624,13 +650,17 @@
 
 	up_write(&super->batch_ctrl_sem);
 
-	/* write to the update journal with a barrier and then write the
-	 * data */
-	cachefs_trans_batch_write_ujnl(super, jstop);
+	/* write to the update journal with a barrier if we're not replaying
+	 * and then write the data (if we're replaying, all the journal entries
+	 * bar the ACK already reside on disc) */
+	if (!test_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags))
+		cachefs_trans_batch_write_ujnl(super, jstop);
 
 	ajentry->mark = CACHEFS_ONDISC_UJNL_BATCH;
 
-	cachefs_trans_batch_write_marker(super, jstop, ajentry);
+	if (!test_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags))
+		cachefs_trans_batch_write_marker(super, jstop, ajentry);
+
 	cachefs_trans_batch_write_data(super);
 	cachefs_trans_batch_process_written_blocks(super, 2);
 
@@ -1377,447 +1407,3 @@
 
 	kleave("");
 } /* end cachefs_trans_sync() */
-
-/*****************************************************************************/
-/*
- * journal replay actor for determining bounds of the latest batch of journal
- * entries
- * - each batch is a cyclically adjacent collection of entries with the same
- *   batch number, hopefully ending in a BATCH mark and an ACK mark
- */
-static int cachefs_ujnl_find_batch_actor(read_descriptor_t *_desc,
-					 struct page *page,
-					 unsigned long offset,
-					 unsigned long size)
-{
-	struct cachefs_replay_find_batch_desc *desc;
-	struct cachefs_ondisc_update_journal *jentry;
-	struct cachefs_super *super = (struct cachefs_super *) _desc->buf;
-	unsigned short slot;
-	u_int8_t *data;
-	int tmp;
-
-	desc = container_of(_desc,
-			    struct cachefs_replay_find_batch_desc,
-			    desc);
-
-	_enter("{%x},{%lu},%lu,%lu",
-	       desc->desc.count, page->index, offset, size);
-
-	BUG_ON(size != PAGE_SIZE);
-	BUG_ON(offset != 0);
-
-	data = (u_int8_t *) kmap(page);
-
-	slot = (page->index - super->layout->bix_ujournal);
-	slot *= super->layout->ujnl_recperblk;
-
-	while (offset < size) {
-		jentry = (struct cachefs_ondisc_update_journal *) (data + offset);
-
-		if (slot == 0) {
-			/* just paste the values of the very first slot in directly */
-			_debug("UJNL[%04x] mk=%s s=%hu.%hu",
-			       slot,
-			       cachefs_ondisc_ujnl_marks[jentry->mark],
-			       (unsigned) jentry->batch,
-			       jentry->serial);
-
-			super->ujnl_batch	= jentry->batch;
-			super->ujnl_serial	= jentry->serial;
-			super->ujnl_head	= slot;
-			desc->batch_first	= ~0;
-			desc->batch_end		= ~0;
-			desc->batch_ack		= ~0;
-			desc->batch_count	= 1;
-			desc->ack_hi		= jentry->batch - 1;
-
-			if (jentry->serial == 0) {
-				desc->batch_first = slot;
-				super->ujnl_tail = slot;
-			}
-
-		}
-		else if (jentry->mark == CACHEFS_ONDISC_UJNL_NULL) {
-			/* do nothing */
-		}
-		else {
-			_debug("UJNL[%04x] mk=%s s=%d.%u { b=%d s=%u }",
-			       slot,
-			       cachefs_ondisc_ujnl_marks[jentry->mark],
-			       jentry->batch,
-			       jentry->serial,
-			       super->ujnl_batch,
-			       super->ujnl_serial);
-
-			tmp = jentry->batch - super->ujnl_batch;
-			if (tmp > 0) {
-				super->ujnl_batch	= jentry->batch;
-				super->ujnl_serial	= jentry->serial;
-				desc->batch_first	= ~0;
-				desc->batch_end		= ~0;
-				desc->batch_ack		= ~0;
-				desc->batch_count	= 1;
-				super->ujnl_head	= slot;
-
-				if (jentry->serial == 0) {
-					desc->batch_first = slot;
-					super->ujnl_tail = slot;
-				}
-			}
-			else if (tmp == 0) {
-				desc->batch_count++;
-
-				if (super->ujnl_serial < jentry->serial) {
-					super->ujnl_serial = jentry->serial;
-					super->ujnl_head = slot;
-				}
-
-				if (jentry->serial == 0)
-					desc->batch_first = slot;
-			}
-		}
-
-		switch (jentry->mark) {
-		case CACHEFS_ONDISC_UJNL_BATCH:
-			if (super->ujnl_serial == jentry->serial)
-				desc->batch_end = slot;
-			break;
-
-		case CACHEFS_ONDISC_UJNL_ACK:
-			if (super->ujnl_serial == jentry->serial)
-				desc->batch_ack	= slot;
-
-			if (jentry->batch - desc->ack_hi > 0) {
-				super->alloc_leaf	= jentry->alloc_leaf;
-				super->alloc_cur	= jentry->alloc_cur;
-				super->recycle_cur	= jentry->recycle_cur;
-				super->rcm_block	= jentry->rcm_block;
-				super->rcm_ptrnext	= jentry->rcm_ptrnext;
-				super->rcm_ptrstop	= jentry->rcm_ptrstop;
-				super->rcm_indirect	= jentry->rcm_indirect;
-				super->rcm_ino		= jentry->rcm_ino;
-
-				kdebug("UJNL[%u] ACK %u"
-				       " { a=%u[%u] r=%u R=%u:%u:%u[%u-%u] }"
-				       " hi=%u",
-				       slot,
-				       jentry->batch,
-				       super->alloc_leaf,
-				       super->alloc_cur,
-				       super->recycle_cur,
-				       super->rcm_ino,
-				       super->rcm_indirect,
-				       super->rcm_block,
-				       super->rcm_ptrnext,
-				       super->rcm_ptrstop,
-				       desc->ack_hi);
-
-				desc->ack_hi = jentry->batch;
-			}
-			else {
-				kdebug("UJNL[%u] ACK %u { hi=%u }",
-				       slot,
-				       jentry->batch,
-				       desc->ack_hi);
-			}
-
-			break;
-
-		default:
-			break;
-		}
-
-		offset += super->layout->ujnl_rsize;
-		slot++;
-	}
-
-	kunmap(page);
-
-	desc->desc.count	-= size;
-	desc->desc.written	+= size;
-	return size;
-} /* end cachefs_ujnl_find_batch_actor() */
-
-/*****************************************************************************/
-/*
- * replay entries from the update journal
- */
-static int cachefs_ujnl_replay_actor(read_descriptor_t *desc,
-				     struct page *page,
-				     unsigned long offset,
-				     unsigned long size)
-{
-	struct cachefs_ondisc_update_journal *jentry;
-	struct cachefs_super *super = (struct cachefs_super *) desc->buf;
-	unsigned long stop;
-	void *data;
-
-	kenter("{%x},{%lu},%lu,%lu", desc->count, page->index, offset, size);
-
-	BUG_ON(offset % super->layout->ujnl_rsize);
-	BUG_ON(size % super->layout->ujnl_rsize);
-
-	stop = offset + size;
-
-	data = kmap(page) + offset;
-
-	while (offset<stop) {
-		cachefs_ujnl_replay_func_t replay;
-
-		jentry = (struct cachefs_ondisc_update_journal *) data;
-
-		if ((unsigned) jentry->mark >=
-		    (unsigned) CACHEFS_ONDISC_UJNL__LAST) {
-			kunmap(page);
-			printk("CacheFS: unimplemented ujnl mark (%x) found\n",
-			       jentry->mark);
-			return -EIO;
-		}
-
-		replay = cachefs_ujnl_replay_tbl[jentry->mark];
-		if (replay) {
-			desc->error = replay(super, jentry);
-			if (desc->error < 0)
-				break;
-		}
-
-		super->alloc_leaf	= jentry->alloc_leaf;
-		super->alloc_cur	= jentry->alloc_cur;
-		super->recycle_cur	= jentry->recycle_cur;
-		super->rcm_block	= jentry->rcm_block;
-		super->rcm_ptrnext	= jentry->rcm_ptrnext;
-		super->rcm_ptrstop	= jentry->rcm_ptrstop;
-		super->rcm_indirect	= jentry->rcm_indirect;
-		super->rcm_ino		= jentry->rcm_ino;
-
-		offset += super->layout->ujnl_rsize;
-	}
-
-	kunmap(page);
-
-	desc->count	-= size;
-	desc->written	+= size;
-	return size;
-} /* end cachefs_ujnl_replay_actor() */
-
-/*****************************************************************************/
-/*
- * replay the journal upon mounting to determine various parameters and to fix
- * up changes that failed to be made
- */
-int cachefs_ujnl_replay(struct cachefs_super *super)
-{
-	struct cachefs_replay_find_batch_desc find_batch;
-	struct cachefs_ondisc_update_journal *ajentry;
-	struct cachefs_ondisc_free_node *node;
-	struct file_ra_state ra;
-	read_descriptor_t desc;
-	loff_t ppos;
-	int loop, ret;
-
-	kenter("");
-
-	file_ra_state_init(&ra, super->imisc->i_mapping);
-
-	/* first of all scan to determine the bounds of the latest batch of
-	 * u-journal entries */
-	memset(&find_batch, 0, sizeof(find_batch));
-	find_batch.desc.count = super->layout->bix_vjournal;
-	find_batch.desc.count -= super->layout->bix_ujournal;
-	find_batch.desc.count *= super->layout->bsize;
-	find_batch.desc.buf   = (char *) super;
-
-	ppos = super->layout->bix_ujournal;
-	ppos *= super->layout->bsize;
-
-	do_generic_mapping_read(super->imisc->i_mapping, &ra, NULL, &ppos,
-				&find_batch.desc,
-				cachefs_ujnl_find_batch_actor);
-	if (find_batch.desc.error < 0) {
-		printk("CacheFS: failed to replay ujournal: %d\n",
-		       find_batch.desc.error);
-		return find_batch.desc.error;
-	}
-
-	kdebug("UJNL: last batch=%d { s=%u f=%u b=%u a=%u }",
-	       super->ujnl_batch,
-	       super->ujnl_serial,
-	       find_batch.batch_first,
-	       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_first == ~0u) {
-		printk("CacheFS: corrupted journal:"
-		       " ujnl batch has no start entry\n");
-		return -EIO;
-	}
-
-	if (find_batch.batch_ack != ~0u) {
-		printk("CacheFS: corrupted journal:"
-		       " ujnl batch has ACK but no end marker\n");
-		return -EIO;
-	}
-
-	if (find_batch.batch_count != super->ujnl_serial) {
-		printk("CacheFS: corrupted journal:"
-		       " ujnl batch has missing marks\n");
-		return -EIO;
-	}
-
-	/* need to replay journal - note it may need to be done in two chunks
-	 * if the batch wraps over the end of the journal space */
-	if (super->ujnl_head < super->ujnl_tail) {
-		memset(&desc, 0, sizeof(desc));
-		desc.count = CACHEFS_ONDISC_UJNL_NUMENTS - super->ujnl_tail;
-		desc.count *= super->layout->ujnl_rsize;
-		desc.buf   = (char *) super;
-
-		ppos = super->layout->bix_ujournal;
-		ppos *= super->layout->bsize;
-		ppos += super->ujnl_tail * super->layout->ujnl_rsize;
-
-		do_generic_mapping_read(super->imisc->i_mapping, &ra, NULL,
-					&ppos, &desc,
-					cachefs_ujnl_replay_actor);
-		if (desc.error < 0) {
-			printk("CacheFS: failed to replay ujournal: %d\n",
-			       desc.error);
-			return desc.error;
-		}
-
-		super->ujnl_tail = 0;
-	}
-
-	memset(&desc, 0, sizeof(desc));
-	desc.count = super->ujnl_head - super->ujnl_tail;
-	desc.count *= super->layout->ujnl_rsize;
-	desc.buf   = (char *) super;
-
-	ppos = super->layout->bix_ujournal;
-	ppos *= super->layout->bsize;
-	ppos += super->ujnl_tail * super->layout->ujnl_rsize;
-
-	do_generic_mapping_read(super->imisc->i_mapping, &ra, NULL, &ppos,
-				&desc, cachefs_ujnl_replay_actor);
-	if (desc.error < 0) {
-		printk("CacheFS: failed to replay ujournal: %d\n",
-		       desc.error);
-		return desc.error;
-	}
-
-	/* write all blocks that are marked for writeback */
-	cachefs_trans_batch_write_data(super);
-	cachefs_trans_batch_process_written_blocks(super, 2);
-
-	/* seal the replayed batch with BATCH and ACK markers */
-	ajentry = kmalloc(super->layout->ujnl_rsize, GFP_KERNEL);
-	if (!ajentry)
-		return -ENOMEM;
-
-	memset(ajentry, 0, sizeof(*ajentry));
-
-	ajentry->batch		= super->ujnl_batch;
-	ajentry->serial		= super->ujnl_serial;
-	ajentry->alloc_leaf	= super->alloc_leaf;
-	ajentry->alloc_cur	= super->alloc_cur;
-	ajentry->recycle_cur	= super->recycle_cur;
-	ajentry->rcm_ino	= super->rcm_ino;
-	ajentry->rcm_indirect	= super->rcm_indirect;
-	ajentry->rcm_block	= super->rcm_block;
-	ajentry->rcm_ptrnext	= super->rcm_ptrnext;
-	ajentry->rcm_ptrstop	= super->rcm_ptrstop;
-
-	if (find_batch.batch_end == ~0u) {
-		cachefs_trans_batch_write_marker(super, super->ujnl_head,
-						 ajentry);
-		super->ujnl_head = UJNL_WRAP(super->ujnl_head + 1);
-		ajentry->serial++;
-	}
-
-	find_batch.batch_ack = super->ujnl_head;
-	cachefs_trans_batch_write_ack(super, super->ujnl_head, ajentry);
-
-	kfree(ajentry);
-
- reload_tracking:
-	kdebug("reload_tracking");
-	super->ujnl_batch++;
-	super->ujnl_serial	= 0;
-	super->ujnl_head	= find_batch.batch_ack + 1;
-	super->ujnl_head	&= CACHEFS_ONDISC_UJNL_NUMENTS - 1;
-	super->ujnl_tail	= super->ujnl_head;
-
-	kdebug("UJNL slot window: next head=%hu tail=%hu",
-	       super->ujnl_head, super->ujnl_tail);
-	kdebug("UJNL Alloc stacks: A=%u[%u] R=%u",
-	       super->alloc_cur, super->alloc_leaf, super->recycle_cur);
-	kdebug("UJNL Recycling: %u:%u:%u:%u-%u",
-	       super->rcm_ino, super->rcm_indirect, super->rcm_block,
-	       super->rcm_ptrnext, super->rcm_ptrstop);
-
-	/* reload the front nodes for the allocation and recycling stacks */
-	if (super->alloc_cur) {
-		ret = cachefs_block_read(super,
-					 CACHEFS_FS_I(super->imisc),
-					 super->alloc_cur,
-					 0,
-					 &super->alloc_block,
-					 &super->alloc_node);
-
-		if (ret < 0) {
-			printk("CacheFS: failed to reload alloc stack: %d\n",
-			       ret);
-			return ret;
-		}
-
-		dbgpgalloc(super->alloc_node);
-
-		set_bit(CACHEFS_BLOCK_CRITICAL, &super->alloc_block->flags);
-		wait_on_page_locked(super->alloc_node);
-
-		node = kmap(super->alloc_node);
-		super->alloc_cur_n = node->count;
-		kunmap(node);
-
-		super->alloc_cur_n +=
-			CACHEFS_ONDISC_LEAVES_PER_FREE_NODE -
-			super->alloc_leaf;
-	}
-
-	if (super->recycle_cur) {
-		ret = cachefs_block_read(super,
-					 CACHEFS_FS_I(super->imisc),
-					 super->recycle_cur,
-					 0,
-					 &super->recycle_block,
-					 &super->recycle_node);
-
-		if (ret<0) {
-			printk("CacheFS: failed to reload recycling stack: %d\n",
-			       ret);
-			return ret;
-		}
-
-		dbgpgalloc(super->recycle_node);
-		wait_on_page_locked(super->recycle_node);
-
-		node = kmap(super->recycle_node);
-
-		for (loop = 0; loop < CACHEFS_ONDISC_LEAVES_PER_FREE_NODE; loop++)
-			if (!node->leaves[loop])
-				break;
-
-		super->recycle_room = CACHEFS_ONDISC_LEAVES_PER_FREE_NODE - loop;
-		super->recycle_cur_n = node->count + super->recycle_room;
-
-		kunmap(node);
-	}
-
-
-	_leave(" = 0");
-	return 0;
-} /* end cachefs_ujnl_replay() */

Index: interface.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/interface.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- interface.c	4 Jul 2003 09:04:44 -0000	1.14
+++ interface.c	9 Jul 2003 10:39:50 -0000	1.15
@@ -600,6 +600,57 @@
 	       idef ? (char *) idef->name : "<file>",
 	       netfs_data);
 
+	if (idef) {
+		int dsize;
+		int loop;
+
+		dsize = CACHEFS_ONDISC_UJNL_MIN_REC_SIZE -
+			sizeof(struct cachefs_ondisc_update_journal);
+
+		if (!idef->name[0]) {
+			printk("CacheFS: %s.%s.%p: nameless index\n",
+			       iparent->netfs->name,
+			       iparent->idef->name,
+			       idef);
+			return;
+		}
+
+		if (idef->data_size > dsize) {
+			printk("CacheFS: %s.%s.%s:"
+			       " index data size exceeds maximum %u>%d\n",
+			       iparent->netfs->name,
+			       iparent->idef->name,
+			       idef->name,
+			       idef->data_size,
+			       dsize);
+			return;
+		}
+
+		for (loop = 0; loop < 4; loop++) {
+			if (idef->keys[loop].type >=
+			    CACHEFS_INDEX_KEYS__LAST) {
+				printk("CacheFS: %s.%s.%s:"
+				       " index type %u unsupported\n",
+				       iparent->netfs->name,
+				       iparent->idef->name,
+				       idef->name,
+				       idef->keys[loop].type);
+				return;
+			}
+
+			dsize -= idef->keys[loop].len;
+			if (dsize < 0) {
+				printk("CacheFS: %s.%s.%s:"
+				       " index key size exceeds data size\n",
+				       iparent->netfs->name,
+				       iparent->idef->name,
+				       idef->name);
+				return;
+			}
+		}
+		
+	}
+
 	/* if no parent cookie, then don't create one here either */
 	if (!iparent) {
 		*_cookie = NULL;

Index: inode.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/inode.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- inode.c	4 Jul 2003 15:22:59 -0000	1.22
+++ inode.c	9 Jul 2003 10:39:50 -0000	1.23
@@ -147,9 +147,9 @@
 	inode->vfs_inode.i_mtime.tv_sec	= metadata->mtime;
 	inode->vfs_inode.i_ctime.tv_sec	= metadata->mtime;
 
-	inode->index_dsize	= metadata->index_dsize;
-	inode->index_esize	= metadata->index_esize;
-	inode->index_epp	= PAGE_SIZE / metadata->index_esize;
+	inode->index_dsize	= metadata->index.dsize;
+	inode->index_esize	= metadata->index.esize;
+	inode->index_epp	= PAGE_SIZE / metadata->index.esize;
 
 	cachefs_metadata_postread(inode);
 
@@ -229,15 +229,15 @@
 	inode->vfs_inode.i_fop		= &cachefs_file_operations;
 	inode->vfs_inode.i_mapping->a_ops = &cachefs_addrspace_operations;
 
-	inode->index_dsize = metadata->index_dsize;
-	inode->index_esize = metadata->index_esize;
+	inode->index_dsize = metadata->index.dsize;
+	inode->index_esize = metadata->index.esize;
 
 	cachefs_metadata_postread(inode);
 
 	inode->index_epp = 0;
 	if (inode->index_esize ||
 	    inode->vfs_inode.i_ino == CACHEFS_INO_ROOTDIR) {
-		inode->index_epp = PAGE_SIZE / metadata->index_esize;
+		inode->index_epp = PAGE_SIZE / inode->index_esize;
 		inode->vfs_inode.i_mode	= S_IFDIR | S_IRUGO | S_IXUGO;
 		inode->vfs_inode.i_nlink = 2;
 		inode->vfs_inode.i_op	= &cachefs_root_inode_operations;

Index: index.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/index.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- index.c	4 Jul 2003 14:25:40 -0000	1.25
+++ index.c	9 Jul 2003 10:39:50 -0000	1.26
@@ -170,6 +170,9 @@
 	cachefs_trans_affects_page(trans, __cachefs_page_get_private(ixpage),
 				   ixoffset, sizeof(*xent));
 
+	rec->index->idef->update(rec->target->netfs_data,
+				 trans->jentry->ixdata[0].data);
+
 	ret = cachefs_trans_mark(trans);
 	if (ret < 0)
 		goto error;
@@ -177,9 +180,9 @@
 	cachefs_page_modify(super, &ixpage);
 
 	xent = kmap(ixpage) + ixoffset;
-
-	rec->index->idef->update(rec->target->netfs_data, xent->data);
-
+	memcpy(xent->data,
+	       trans->jentry->ixdata[0].data,
+	       rec->iinode->index_dsize);
 	kunmap(ixpage);
 
 	cachefs_trans_commit(trans);
@@ -532,6 +535,7 @@
 		      struct cachefs_cookie *cookie,
 		      unsigned *_newino)
 {
+	struct cachefs_ondisc_ujnl_index *jindex;
 	struct cachefs_ondisc_index_entry *xent;
 	struct cachefs_ondisc_metadata *metadata;
 	struct cachefs_search_result *srch;
@@ -570,6 +574,8 @@
 	if (!trans)
 		goto error;
 
+	jindex = &trans->jentry->ixdata[0];
+
 	offset = (ixentry % index->index_epp) * index->index_esize;
 
 	trans->jentry->mark = CACHEFS_ONDISC_UJNL_INDEX_CREATING;
@@ -598,6 +604,32 @@
 	cachefs_trans_affects_inode(trans, index);
 	cachefs_trans_affects_inode(trans, super->imetadata);
 
+	index->cookie->idef->update(cookie->netfs_data, jindex->data);
+
+	if (cookie->idef) {
+		struct cachefs_index_def *definition = cookie->idef;
+
+		jindex->def.dsize = definition->data_size;
+		jindex->def.esize = definition->data_size;
+		jindex->def.esize +=
+			sizeof(struct cachefs_ondisc_index_entry);
+
+		if (jindex->def.esize < CACHEFS_ONDISC_INDEX_ENTRY_MINSIZE)
+			jindex->def.esize = CACHEFS_ONDISC_INDEX_ENTRY_MINSIZE;
+
+		for (loop = 0; loop < 4; loop++) {
+			jindex->def.keys[loop] =
+				definition->keys[loop].len &
+				CACHEFS_ONDISC_INDEXKEY_KLEN;
+			jindex->def.keys[loop] |=
+				definition->keys[loop].type << 12;
+		}
+
+		strncpy(jindex->def.type,
+			definition->name,
+			sizeof(jindex->def.type));
+	}
+
 	ret = cachefs_trans_mark(trans);
 	if (ret < 0)
 		goto error;
@@ -614,7 +646,7 @@
 	if (cookie->idef)
 		xent->type = CACHEFS_ONDISC_INDEX_INDEXFILE;
 
-	index->cookie->idef->update(cookie->netfs_data, xent->data);
+	memcpy(xent->data, jindex->data, jindex->def.dsize);
 
 	kunmap(ixpage);
 
@@ -637,30 +669,7 @@
 	metadata->pindex	= index->vfs_inode.i_ino;
 	metadata->pindex_entry	= ixentry;
 
-	if (cookie->idef) {
-		struct cachefs_index_def *definition = cookie->idef;
-
-		metadata->index_dsize = definition->data_size;
-		metadata->index_esize = metadata->index_dsize;
-		metadata->index_esize +=
-			sizeof(struct cachefs_ondisc_index_entry);
-
-		if (metadata->index_esize < CACHEFS_ONDISC_INDEX_ENTRY_MINSIZE)
-			metadata->index_esize =
-				CACHEFS_ONDISC_INDEX_ENTRY_MINSIZE;
-
-		for (loop = 0; loop < 4; loop++) {
-			metadata->index_keys[loop] =
-				definition->keys[loop].len &
-				CACHEFS_ONDISC_INDEXKEY_KLEN;
-			metadata->index_keys[loop] |=
-				definition->keys[loop].type << 12;
-		}
-
-		strncpy(metadata->index_type,
-			definition->name,
-			sizeof(metadata->index_type));
-	}
+	struct_cpy(&metadata->index, &jindex->def);
 
 	kunmap(inopage);
 
@@ -799,89 +808,3 @@
 	_leave(" = %d", ret);
 	return ret;
 } /* end cachefs_index_zap() */
-
-/*****************************************************************************/
-/*
- * 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
- */
-int cachefs_replay_ujnl_inode_creating(struct cachefs_super *super,
-				       struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* 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
- */
-int cachefs_replay_ujnl_inode_updating(struct cachefs_super *super,
-				       struct cachefs_ondisc_update_journal *jentry)
-{
-	return 0;
-} /* end cachefs_replay_ujnl_inode_updating() */
-
-/*****************************************************************************/
-/*
- * not yet supported
- */
-int cachefs_replay_ujnl_inode_deleting(struct cachefs_super *super,
-				       struct cachefs_ondisc_update_journal *jentry)
-{
-	printk("CacheFS: u-jnl mark UJNL_INODE_DELETING not yet supported\n");
-	return -EIO;
-} /* end cachefs_replay_ujnl_inode_deleting() */
-
-/*****************************************************************************/
-/*
- * replay an inode being marked for reclamation
- */
-int cachefs_replay_ujnl_inode_mark_reclaim(struct cachefs_super *super,
-					   struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_inode_mark_reclaim() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_inode_reclaiming(struct cachefs_super *super,
-					 struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_inode_reclaiming() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_index_extending(struct cachefs_super *super,
-					struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_index_extending() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_index_creating(struct cachefs_super *super,
-				       struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_index_creating() */
-
-/*****************************************************************************/
-/*
- *
- */
-int cachefs_replay_ujnl_index_modifying(struct cachefs_super *super,
-					struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_index_modifying() */

Index: dump-journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/dump-journal.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- dump-journal.c	4 Jul 2003 14:25:40 -0000	1.12
+++ dump-journal.c	9 Jul 2003 10:39:50 -0000	1.13
@@ -45,7 +45,6 @@
 	BRIGHT	"Null     "	NORMAL,
 	GREY	"Batch    "	NORMAL,
 	GREY	"Ack      "	NORMAL,
-	BRIGHT	"RcycEmpty"	NORMAL,
 	BRIGHT	"RcycBegin"	NORMAL,
 	BRIGHT	"RcycXfer "	NORMAL,
 	BRIGHT	"RcycScvng"	NORMAL,

Index: cachefs-layout.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-layout.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- cachefs-layout.h	4 Jul 2003 15:22:59 -0000	1.28
+++ cachefs-layout.h	9 Jul 2003 10:39:50 -0000	1.29
@@ -88,6 +88,25 @@
 #define CACHEFS_ONDISC_INDEX_ENTRY_MINSIZE \
 	(sizeof(struct cachefs_ondisc_index_entry) + sizeof(u_int32_t))
 
+/* index definition description */
+struct cachefs_ondisc_index_def
+{
+	u_int16_t			dsize;
+	u_int16_t			esize;
+	u_int16_t			keys[4];
+	u_int8_t			type[8];
+
+#define CACHEFS_ONDISC_INDEXKEY_KLEN	0x0FFF	/* length of key segment */
+#define CACHEFS_ONDISC_INDEXKEY_TYPE	0xF000	/* type of key segment */
+#define CACHEFS_ONDISC_INDEXKEY_NOTUSED	0x0000	/* - segment not used */
+#define CACHEFS_ONDISC_INDEXKEY_BIN	0x1000	/* - binary data */
+#define CACHEFS_ONDISC_INDEXKEY_ASCIIZ	0x2000	/* - null-terminated string */
+#define CACHEFS_ONDISC_INDEXKEY_IPV4	0x3000	/* - IPv4 address */
+#define CACHEFS_ONDISC_INDEXKEY_IPV6	0x4000	/* - IPv6 address */
+
+	u_int8_t			data[0];
+};
+
 /*****************************************************************************/
 /*
  * on-disc metadata record
@@ -111,18 +130,7 @@
 	u_int64_t			size;		/* size of file */
 
 	/* index file definition */
-	u_int16_t			index_dsize;	/* index entry data size */
-	u_int16_t			index_esize;	/* index entry size */
-	u_int16_t			index_keys[4];	/* key->ascii translation */
-	u_int8_t			index_type[8];	/* name of index type */
-
-#define CACHEFS_ONDISC_INDEXKEY_KLEN	0x0FFF	/* length of key segment */
-#define CACHEFS_ONDISC_INDEXKEY_TYPE	0xF000	/* type of key segment */
-#define CACHEFS_ONDISC_INDEXKEY_NOTUSED	0x0000	/* - segment not used */
-#define CACHEFS_ONDISC_INDEXKEY_BIN	0x1000	/* - binary data */
-#define CACHEFS_ONDISC_INDEXKEY_ASCIIZ	0x2000	/* - null-terminated string */
-#define CACHEFS_ONDISC_INDEXKEY_IPV4	0x3000	/* - IPv4 address */
-#define CACHEFS_ONDISC_INDEXKEY_IPV6	0x4000	/* - IPv6 address */
+	struct cachefs_ondisc_index_def	index;
 
 	/* file contents - recycling depends on triple_indirect being first */
 	cachefs_blockix_t		triple_indirect; /* triple indirect block index */
@@ -200,11 +208,6 @@
 	/* batch completion mark */
 	CACHEFS_ONDISC_UJNL_ACK,
 
-	/* front alloc_stk node recycled
-	 * - block	= block being recycled
-	 */
-	CACHEFS_ONDISC_UJNL_RECYC_EMPTY_NODE,
-
 	/* beginning new recycle_stk front node
 	 * - block	= block being begun
 	 * - auxblock	= old front recycling node
@@ -231,12 +234,23 @@
 
 	/* transfer bix_unready to recycle_stk
 	 * - block	= recycling node that blocks were pasted into
+	 * - entry	= index into block[] of first pointer inserted
 	 * - auxblock	= first unready block transferred
 	 * - pgnum	= new super->layout.bix_unready
+	 * - count	= number of blocks pasted
 	 */
 	CACHEFS_ONDISC_UJNL_RECYC_MAKEREADY,
 
-	/* data file being created */
+	/* data file being created
+	 * - index	= parent index being attached to
+	 * - ixentry	= entry in parent index
+	 * - pgnum	= page in file holding index entry being allocated
+	 * - 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
+	 */
 	CACHEFS_ONDISC_UJNL_INODE_CREATING,
 
 	/* data file being updated */
@@ -341,6 +355,11 @@
 	CACHEFS_ONDISC_UJNL__LAST
 } __attribute__((packed));
 
+struct cachefs_ondisc_ujnl_index {
+	struct cachefs_ondisc_index_def	def;
+	u_int8_t			data[0];
+};
+
 struct cachefs_ondisc_update_journal
 {
 	enum cachefs_ondisc_ujnl_mark	mark;
@@ -377,11 +396,19 @@
 	cachefs_blockix_t		recycle_cur;	/* current block recycling node */
 
 	union {
-		cachefs_blockix_t	rcyptrs[0];	/* recycled pointers */
+		/* recycled pointers */
+		cachefs_blockix_t rcyptrs[0];
+
+		/* new/updated index entry */
+		struct cachefs_ondisc_ujnl_index ixdata[0];
+
+		/* miscellaneous data */
+		u_int8_t data[0];
 	};
 };
 
-#define CACHEFS_ONDISC_UJNL_NUMENTS	4096		/* number of entries in the u-journal */
+#define CACHEFS_ONDISC_UJNL_NUMENTS		4096	/* number of entries in the u-journal */
+#define CACHEFS_ONDISC_UJNL_MIN_REC_SIZE	512	/* minimum u-journal record size */
 
 /*****************************************************************************/
 /*

Index: cachefs-int.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-int.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- cachefs-int.h	4 Jul 2003 09:04:44 -0000	1.37
+++ cachefs-int.h	9 Jul 2003 10:39:50 -0000	1.38
@@ -77,6 +77,7 @@
 #define CACHEFS_SUPER_RCM_IMM_SCAN	3		/* T if should scan for immediately
 							 * reclaimable inodes */
 #define CACHEFS_SUPER_WITHDRAWN		4		/* T if cache has been withdrawn */
+#define CACHEFS_SUPER_REPLAYING_UJNL	5		/* T if replaying u-journal */
 
 	/* index management */
 	struct list_head		ino_list;	/* list of data/index inodes */
@@ -143,6 +144,7 @@
 	struct list_head		ujnl_writeq;	/* transactions being written */
 	struct list_head		ujnl_ackq;	/* marks ACK'd by transaction completion */
 	struct list_head		ujnl_ackwq;	/* marks awaiting on-disc ACK */
+	struct list_head		ujnl_replayq;	/* blocks having allocation replayed */
 
 	struct semaphore		batch_sem;	/* batching mutex */
 	struct semaphore		batch_uj_sem;	/* ujnl written sync mutex */
@@ -202,17 +204,6 @@
 extern void cachefs_recycle_reclaim(struct cachefs_super *super);
 extern void cachefs_recycle_unallocate_data_block(struct cachefs_super *super);
 
-extern int cachefs_replay_ujnl_recyc_empty_node(struct cachefs_super *super,
-						struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_recyc_begin_new(struct cachefs_super *super,
-					       struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_recyc_transfer(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_recyc_scavenge(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_recyc_makeready(struct cachefs_super *super,
-					       struct cachefs_ondisc_update_journal *jentry);
-
 /*****************************************************************************/
 /*
  * block management record
@@ -462,36 +453,6 @@
 
 extern int cachefs_index_zap(struct cachefs_super *super);
 
-extern int cachefs_replay_ujnl_inode_creating(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_inode_updating(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_inode_deleting(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_inode_mark_reclaim(struct cachefs_super *super,
-						  struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_inode_reclaiming(struct cachefs_super *super,
-						struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_index_extending(struct cachefs_super *super,
-					       struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_index_creating(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_index_modifying(struct cachefs_super *super,
-					       struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_index_deleting(struct cachefs_super *super,
-					      struct cachefs_ondisc_update_journal *jentry);
-
-extern int cachefs_replay_ujnl_data_allocing(struct cachefs_super *super,
-					     struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_data_written(struct cachefs_super *super,
-					    struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_data_unallocing(struct cachefs_super *super,
-					       struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_indirect_allocing(struct cachefs_super *super,
-						 struct cachefs_ondisc_update_journal *jentry);
-extern int cachefs_replay_ujnl_indirect_freeing(struct cachefs_super *super,
-						struct cachefs_ondisc_update_journal *jentry);
-
 /*****************************************************************************/
 /*
  * record of as-yet invalid data block for which a v-journal entry exists
@@ -567,6 +528,11 @@
 struct cachefs_transaction *cachefs_trans_alloc(struct cachefs_super *super,
 						unsigned long gfp);
 
+extern
+struct cachefs_transaction *
+cachefs_trans_alloc_replay(struct cachefs_super *super,
+			   struct cachefs_ondisc_update_journal *jentry);
+
 extern void __cachefs_trans_put(struct cachefs_transaction *trans);
 static inline void cachefs_trans_put(struct cachefs_transaction *trans)
 {
@@ -612,7 +578,7 @@
 
 extern int  cachefs_trans_mark(struct cachefs_transaction *trans);
 extern void cachefs_trans_commit(struct cachefs_transaction *trans);
-extern void cachefs_trans_cancel(struct cachefs_transaction *trans);
+extern void cachefs_trans_commit_replay(struct cachefs_transaction *trans);
 extern void cachefs_trans_batch_write(struct cachefs_super *super);
 extern void cachefs_trans_batch_timer(unsigned long data);

Index: aops.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/aops.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- aops.c	4 Jul 2003 09:04:44 -0000	1.39
+++ aops.c	9 Jul 2003 10:39:50 -0000	1.40
@@ -1525,53 +1525,3 @@
 	return ret;
 
 } /* end cachefs_file_readpage() */
-
-/*****************************************************************************/
-/*
- * replay data block allocation and v-journal set
- */
-int cachefs_replay_ujnl_data_allocing(struct cachefs_super *super,
-				      struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_data_allocing() */
-
-/*****************************************************************************/
-/*
- * replay data write and v-journal clear
- */
-int cachefs_replay_ujnl_data_written(struct cachefs_super *super,
-				     struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_data_written() */
-
-/*****************************************************************************/
-/*
- * replay data block unallocation and v-journal clear
- */
-int cachefs_replay_ujnl_data_unallocing(struct cachefs_super *super,
-					struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_data_unallocing() */
-
-/*****************************************************************************/
-/*
- * replay indirection block allocation
- */
-int cachefs_replay_ujnl_indirect_allocing(struct cachefs_super *super,
-					  struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_indirect_allocing() */
-
-/*****************************************************************************/
-/*
- * replay indirection block freeing
- */
-int cachefs_replay_ujnl_indirect_freeing(struct cachefs_super *super,
-					 struct cachefs_ondisc_update_journal *jentry)
-{
-	return -ENOANO;
-} /* end cachefs_replay_ujnl_indirect_freeing() */

Index: Makefile
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/Makefile,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- Makefile	23 May 2003 12:59:22 -0000	1.16
+++ Makefile	9 Jul 2003 10:39:51 -0000	1.17
@@ -16,6 +16,7 @@
 	kcachefsd.o \
 	main.o \
 	recycling.o \
+	replay.o \
 	rootdir.o \
 	status.o \
 	super.o \