Subject: afs/fs/cachefs replay.c,1.4,1.5 journal.c,1.42,1.43 dump-journal.c,1.18,1.19 block.c,1.9,1.10

From: [email-masked]
Date: Fri, 12 Sep 2003 10:52:41 +0100

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

Modified Files:
	replay.c journal.c dump-journal.c block.c 
Log Message:
u-journal replaying now basically works

Index: replay.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/replay.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- replay.c	13 Aug 2003 10:05:28 -0000	1.4
+++ replay.c	12 Sep 2003 09:52:38 -0000	1.5
@@ -127,9 +127,12 @@
 			    struct cachefs_replay_find_batch_desc,
 			    desc);
 
-	_enter("{%x},{%lu},%lu,%lu",
+	_enter("{%zx},{%lu},%lu,%lu",
 	       desc->desc.count, page->index, offset, size);
 
+	if (size > desc->desc.count)
+		size = desc->desc.count;
+
 	BUG_ON(size != PAGE_SIZE);
 	BUG_ON(offset != 0);
 
@@ -284,7 +287,10 @@
 	unsigned long stop;
 	void *data;
 
-	kenter("{%x},{%lu},%lu,%lu", desc->count, page->index, offset, size);
+	kenter("{%zx},{%lu},%lu,%lu", desc->count, page->index, offset, size);
+
+	if (size > desc->count)
+		size = desc->count;
 
 	BUG_ON(offset % super->layout->ujnl_rsize);
 	BUG_ON(size % super->layout->ujnl_rsize);
@@ -344,7 +350,10 @@
 	unsigned long stop;
 	void *data;
 
-	kenter("{%x},{%lu},%lu,%lu", desc->count, page->index, offset, size);
+	kenter("{%zx},{%lu},%lu,%lu", desc->count, page->index, offset, size);
+
+	if (size > desc->count)
+		size = desc->count;
 
 	BUG_ON(offset % super->layout->ujnl_rsize);
 	BUG_ON(size % super->layout->ujnl_rsize);
@@ -378,6 +387,7 @@
 		if (replay) {
 			desc->error = replay(super, jentry, trans);
 			if (desc->error < 0) {
+				trans->phase = CACHEFS_TRANS_DEAD;
 				cachefs_trans_put(trans);
 				break;
 			}
@@ -419,6 +429,8 @@
 	read_descriptor_t desc;
 	loff_t ppos;
 
+	kenter("{%hx-%hx},,", super->ujnl_head, super->ujnl_tail);
+
 	if (super->ujnl_head < super->ujnl_tail) {
 		memset(&desc, 0, sizeof(desc));
 		desc.count = CACHEFS_ONDISC_UJNL_NUMENTS - super->ujnl_tail;
@@ -499,29 +511,31 @@
 		return find_batch.desc.error;
 	}
 
-	kdebug("UJNL: last batch=%d { s=%u f=%u b=%u a=%u }",
+	kdebug("UJNL: last batch=%d { s=%u #=%u f=%u b=%u a=%u }",
 	       super->ujnl_batch,
 	       super->ujnl_serial,
+	       find_batch.batch_count,
 	       find_batch.batch_first,
 	       find_batch.batch_end,
 	       find_batch.batch_ack);
 
-	if (find_batch.batch_end == ~0u || find_batch.batch_ack == ~0u) {
-		if (find_batch.batch_first == ~0u) {
+	if (find_batch.batch_end == (unsigned short) ~0u ||
+	    find_batch.batch_ack == (unsigned short) ~0u) {
+		if (find_batch.batch_first == (unsigned short) ~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) {
+		if (find_batch.batch_ack != (unsigned short) ~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) {
+		if (find_batch.batch_count != super->ujnl_serial + 1) {
 			clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
 			printk("CacheFS: corrupted journal:"
 			       " ujnl batch has missing marks\n");
@@ -530,10 +544,11 @@
 
 		/* 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);
+		super->ujnl_head = UJNL_WRAP(find_batch.batch_end + 1);
+
+		printk("CacheFS: Need to replay update journal t=%hu h=%hu\n",
+		       super->ujnl_tail, super->ujnl_head);
 
 		ret = cachefs_ujnl_replay_aux(
 			super, &ra, cachefs_ujnl_determine_overlap_actor);
@@ -558,18 +573,22 @@
 		}
 
 		/* write all blocks that are marked for writeback */
+		kdebug("write back pages touched by replay");
 		cachefs_trans_batch_write(super);
+		super->ujnl_head	= super->ujnl_tail;
 
 		printk("CacheFS: Finished replaying update journal\n");
 	}
+	else {
+		super->ujnl_head	= UJNL_WRAP(find_batch.batch_ack + 1);
+		super->ujnl_tail	= super->ujnl_head;
+	}
 
 	clear_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags);
 
 	kdebug("reload_tracking");
 	super->ujnl_batch++;
 	super->ujnl_serial	= 0;
-	super->ujnl_head	= UJNL_WRAP(find_batch.batch_ack + 1);
-	super->ujnl_tail	= super->ujnl_head;
 
 	kdebug("UJNL slot window: next head=%hu tail=%hu",
 	       super->ujnl_head, super->ujnl_tail);
@@ -655,7 +674,7 @@
 {
 	int ix = trans->eff_active;
 
-	_enter("%p{efa=%d},{%u}", trans, ix, block->bix);
+	kenter("%p{efa=%d},{%u}", trans, ix, block->bix);
 
 	get_page(block->page);
 
@@ -678,7 +697,7 @@
 	struct page *page;
 	int ret;
 
-	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+	_enter(",{%hd.%hu}", jentry->batch, jentry->serial);
 
 	ret = cachefs_block_read(super, NULL, jentry->block, 0, &block, &page);
 	if (ret < 0)
@@ -699,7 +718,7 @@
 	cachefs_put_page(page);
 
  error:
-	kleave(" = %d", ret);
+	_leave(" = %d", ret);
 	return ret;
 } /* end cachefs_replay_ujnl_recyc_begin_new() */
 
@@ -717,7 +736,7 @@
 	struct page *page;
 	int ret;
 
-	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+	_enter(",{%hd.%hu}", jentry->batch, jentry->serial);
 	ret = 0;
 
 	/* we need to break the link from the recycling stack TOS to the new
@@ -744,7 +763,7 @@
 	}
 
  error:
-	kleave(" = %d", ret);
+	_leave(" = %d", ret);
 	return ret;
 } /* end cachefs_replay_ujnl_recyc_transfer() */
 
@@ -817,12 +836,13 @@
 	struct cachefs_ondisc_superblock *layout;
 	struct cachefs_ondisc_free_node *node;
 	struct cachefs_block *block, *superblock;
+	cachefs_blockix_t bix;
 	struct page *page, *spage;
-	int ret;
+	int loop, changed, ret;
 
-	kenter(",{%hd.%hu}", jentry->batch, jentry->serial);
+	_enter(",{%hd.%hu}", jentry->batch, jentry->serial);
 
-	ret = cachefs_block_read(super, NULL, jentry->auxblock, 0,
+	ret = cachefs_block_read(super, NULL, jentry->block, 0,
 				 &block, &page);
 	if (ret < 0)
 		goto error;
@@ -833,8 +853,8 @@
 
 	ret = -EINVAL;
 	if (jentry->entry >= CACHEFS_ONDISC_LEAVES_PER_FREE_NODE ||
-	    jentry->entry + jentry->count >=
-	    CACHEFS_ONDISC_LEAVES_PER_FREE_NODE) {
+	    jentry->entry + jentry->count > CACHEFS_ONDISC_LEAVES_PER_FREE_NODE
+	    ) {
 		printk("CacheFS:"
 		       " UJNL MakeReady entry specifies out-of-range"
 		       " dest window\n");
@@ -844,8 +864,8 @@
 	/* we need to make sure the superblock keeps track of the top of the
 	 * ready area */
 	layout = kmap(spage);
-	if (layout->bix_ujournal < jentry->pgnum) {
-		layout->bix_ujournal = jentry->pgnum;
+	if (layout->bix_unready < jentry->pgnum) {
+		layout->bix_unready = jentry->pgnum;
 		cachefs_trans_replays_effect(trans, superblock);
 	}
 	kunmap(spage);
@@ -854,15 +874,17 @@
 	if (BLOCK_VALID(block, page, jentry)) {
 		node = kmap(page);
 
-		if (memcmp(&node->leaves[jentry->auxblock],
-			   &jentry->rcyptrs[0],
-			   jentry->count * sizeof(cachefs_blockix_t)
-			   ) != 0) {
-			memcpy(&node->leaves[jentry->auxblock],
-			       &jentry->rcyptrs[0],
-			       jentry->count * sizeof(cachefs_blockix_t));
-			cachefs_trans_replays_effect(trans, block);
+		changed = 0;
+		bix = jentry->auxblock;
+		for (loop = 0; loop < jentry->count; loop++, bix++) {
+			if (node->leaves[loop] != bix) {
+				changed = 1;
+				node->leaves[loop] = bix;
+			}
 		}
+
+		if (changed)
+			cachefs_trans_replays_effect(trans, block);
 		kunmap(page);
 	}
 
@@ -875,7 +897,7 @@
 	cachefs_block_put(block);
 	cachefs_put_page(page);
  error:
-	kleave(" = %d", ret);
+	_leave(" = %d", ret);
 	return ret;
 } /* end cachefs_replay_ujnl_recyc_makeready() */

Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- journal.c	18 Jul 2003 08:54:58 -0000	1.42
+++ journal.c	12 Sep 2003 09:52:38 -0000	1.43
@@ -159,6 +159,9 @@
 	trans->phase	= CACHEFS_TRANS_MARKED;
 	trans->index	= 0;
 
+	atomic_inc(&super->cnt_ujnl_mkrq);
+	atomic_inc(&super->cnt_ujnl_mkgr);
+
 	_leave(" = %p", trans);
 	return trans;
 } /* end cachefs_trans_alloc_replay() */
@@ -539,6 +542,9 @@
 	int loop;
 
 	if (!trans->eff_active) {
+		cachefs_ujnl_set_phase(trans,
+				       CACHEFS_TRANS_DEAD,
+				       CACHEFS_TRANS_MARKED);
 		cachefs_trans_put(trans);
 		return;
 	}
@@ -561,20 +567,26 @@
  * - mark all modified journalling and data blocks for writeback
  * - mark data for COW
  */
-static inline
+static
 void cachefs_trans_batch_write_prep_trans(struct cachefs_super *super,
 					  struct cachefs_transaction *trans)
 {
 	struct cachefs_block *block;
 	int loop;
 
+	_enter("");
+
 	/* mark u-journal page */
-	block = trans->jblock;
-	if (!test_and_set_bit(CACHEFS_BLOCK_WRITEBACK, &block->flags)) {
-		list_add_tail(&block->batch_link, &super->batch_writeq);
-		block->writeback = block->page;
-		get_page(block->writeback);
-		flush_dcache_page(block->writeback);
+	if (!test_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags)) {
+		block = trans->jblock;
+		if (!test_and_set_bit(CACHEFS_BLOCK_WRITEBACK, &block->flags)
+		    ) {
+			list_add_tail(&block->batch_link,
+				      &super->batch_writeq);
+			block->writeback = block->page;
+			get_page(block->writeback);
+			flush_dcache_page(block->writeback);
+		}
 	}
 
 	/* mark data blocks */
@@ -615,13 +627,17 @@
 	struct cachefs_ondisc_update_journal *ajentry;
 	struct cachefs_transaction *trans;
 	struct cachefs_block *block;
-	struct list_head *_p;
 	unsigned short jstop;
 	unsigned long flags;
 
 	_enter("");
 
+	/* permit cachefs_trans_sync() to detect end of batch write */
 	down(&super->batch_sem);
+
+	/* prevent critical blocks from being reused for netfs data caching
+	 * - normally released by cachefs_trans_marker_written()
+	 */
 	down(&super->batch_uj_sem);
 
 	spin_lock_irqsave(&super->ujnl_mk_lock, flags);
@@ -637,8 +653,7 @@
 
 	BUG_ON(!list_empty(&super->ujnl_markq));
 
-	list_for_each(_p, &super->ujnl_commitq) {
-		trans = list_entry(_p, struct cachefs_transaction, sblink);
+	list_for_each_entry(trans, &super->ujnl_commitq, sblink) {
 		cachefs_trans_batch_write_prep_trans(super, trans);
 	}
 
@@ -646,9 +661,7 @@
 	list_splice_init(&super->ujnl_commitq, &super->ujnl_writeq);
 	spin_unlock_irqrestore(&super->ujnl_mk_lock, flags);
 
-	list_for_each(_p, &super->batch_writeq) {
-		block = list_entry(_p, struct cachefs_block, batch_link);
-
+	list_for_each_entry(block, &super->batch_writeq, batch_link) {
 		_debug(" >>> block %05u fl=%04lx pg=%p wb=%p",
 		       block->bix, block->flags, block->page,
 		       block->writeback);
@@ -690,12 +703,15 @@
 
 	if (!test_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags))
 		cachefs_trans_batch_write_marker(super, jstop, ajentry);
+	else
+		up(&super->batch_uj_sem);
 
 	cachefs_trans_batch_write_data(super);
 	cachefs_trans_batch_process_written_blocks(super, 2);
 
 	/* polish off with an ACK */
-	jstop = UJNL_WRAP(jstop + 1);
+	if (!test_bit(CACHEFS_SUPER_REPLAYING_UJNL, &super->flags))
+		jstop = UJNL_WRAP(jstop + 1);
 
 	ajentry->mark = CACHEFS_ONDISC_UJNL_ACK;
 	ajentry->serial++;
@@ -703,7 +719,7 @@
 	cachefs_trans_batch_write_ack(super, jstop, ajentry);
 	kfree(ajentry);
 
-	super->ujnl_tail = UJNL_WRAP(super->ujnl_tail + 2);
+	super->ujnl_tail = UJNL_WRAP(jstop + 1);
 
 	/* clean up the transactions that we've now written */
 	while (!list_empty(&super->ujnl_writeq)) {
@@ -722,6 +738,7 @@
 
 	wake_up_all(&super->batch_sync_wq);
 
+	_leave("");
 } /* end cachefs_trans_batch_write() */
 
 /*****************************************************************************/
@@ -1109,6 +1126,10 @@
 		BUG();
 
 	//dump_bio(bio,1);
+
+#if 0
+	BUG(); /* TODO: remove (for replay testing) */
+#endif
 
 	submit_bio(WRITE | (1 << BIO_RW_BARRIER), bio);

Index: dump-journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/dump-journal.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- dump-journal.c	10 Sep 2003 14:57:12 -0000	1.18
+++ dump-journal.c	12 Sep 2003 09:52:38 -0000	1.19
@@ -16,6 +16,7 @@
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <stdint.h>
 
 #include "cachefs-layout.h"
 
@@ -70,6 +71,7 @@
 	struct cachefs_ondisc_superblock *super;
 	struct sector *ujournal;
 	struct stat st;
+	const char *markname;
 	unsigned numujnl, jsof;
 	int devfd, loop, delta;
 
@@ -164,6 +166,13 @@
 		if (jentry->mark == CACHEFS_ONDISC_UJNL_NULL)
 			continue;
 
+		if (jentry->mark >=
+		    sizeof(cachefs_ondisc_ujnl_marks) /
+		    sizeof(cachefs_ondisc_ujnl_marks[0]))
+			markname = BP_RED "?????????" NORMAL;
+		else
+			markname = cachefs_ondisc_ujnl_marks[jentry->mark];
+
 		printf("%s%4u" NORMAL
 		       " " CYAN		"%5u"	GREY	"."	NORMAL	"%-5u"	NORMAL
 		       " "		"%s"		" %4d"
@@ -181,7 +190,7 @@
 		       loop&7 ? NORMAL : GREEN,
 		       loop,
 		       jentry->batch,		jentry->serial,
-		       cachefs_ondisc_ujnl_marks[jentry->mark],jentry->auxmark,
+		       markname			,jentry->auxmark,
 		       jentry->ino,		jentry->pgnum,
 		       jentry->index,		jentry->ixentry,
 		       jentry->block,		jentry->entry,

Index: block.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/block.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- block.c	10 Jul 2003 14:21:24 -0000	1.9
+++ block.c	12 Sep 2003 09:52:38 -0000	1.10
@@ -431,11 +431,15 @@
 	struct rb_node *parent, **p;
 	unsigned long flags;
 
-	_enter(",%u,",bix);
+	_enter(",%u,", bix);
 
 	*_block = NULL;
 
-	BUG_ON(bix > super->sb->s_bdev->bd_inode->i_size / PAGE_SIZE);
+	if (bix > super->sb->s_bdev->bd_inode->i_size / PAGE_SIZE) {
+		printk("CacheFS: trying to insert out of range block %x/%Lx\n",
+		       bix, super->sb->s_bdev->bd_inode->i_size / PAGE_SIZE);
+		BUG();
+	}
 
 	/* allocate a block record just in case */
 	newblock = kmem_cache_alloc(cachefs_block_jar, SLAB_KERNEL);