Subject: afs/fs/cachefs super.c,1.31,1.32 kcachefsd.c,1.11,1.12 journal.c,1.34,1.35 interface.c,1.12,1.13 inode.c,1.19,1.20 index.c,1.21,1.22 cachetest-main.c,1.10,1.11 block.c,1.6,1.7 aops.c,1.35,1.36

From: [email-masked]
Date: Tue, 10 Jun 2003 18:49:52 +0100

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

Modified Files:
	super.c kcachefsd.c journal.c interface.c inode.c index.c 
	cachetest-main.c block.c aops.c 
Log Message:
fix some oopses

Index: super.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/super.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- super.c	2 Jun 2003 09:17:42 -0000	1.31
+++ super.c	10 Jun 2003 17:49:49 -0000	1.32
@@ -736,9 +736,10 @@
 		remove_wait_queue(&super->vjnl_alloc_wq,&myself);
 	}
 
+	super->dmn_die = 1;
 	cachefs_trans_sync(super,1);
 
-	super->dmn_die = 1;
+	super->dmn_die = 2;
 	wake_up(&super->dmn_sleepq);
 	wait_for_completion(&super->dmn_dead);

Index: kcachefsd.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/kcachefsd.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- kcachefsd.c	23 May 2003 14:07:31 -0000	1.11
+++ kcachefsd.c	10 Jun 2003 17:49:49 -0000	1.12
@@ -74,17 +74,22 @@
 			discard_my_signals();
 
 			/* see if there's work to be done */
-			if (!super->alloc_node ||
-			    super->layout->bix_unready < super->layout->bix_end ||
-			    test_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags) ||
-			    test_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags) ||
+			if (super->dmn_die == 0) {
+				if (!super->alloc_node ||
+				    super->layout->bix_unready < super->layout->bix_end ||
+				    test_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags)
+				    )
+				break;
+			}
+
+			if (test_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags) ||
 			    !list_empty(&super->vjnl_unallocq) ||
 			    !list_empty(&super->vjnl_writtenq)
 			    )
 				break;
 
 			/* deal with the server being asked to die */
-			if (super->dmn_die) {
+			if (super->dmn_die > 1) {
 				remove_wait_queue(&super->dmn_sleepq,&myself);
 				_leave("");
 				complete_and_exit(&super->dmn_dead,0);
@@ -102,20 +107,27 @@
 		/* actually do some work */
 		_debug("@@@ Begin Cache Management");
 
-		/* decant the recycling queue */
-		if (test_and_clear_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags))
-			cachefs_recycle_reclaim(super);
-
-		/* transfer blocks from the unready data if possible */
-		if (super->layout->bix_unready<super->layout->bix_end) {
-			cachefs_recycle_unready_blocks(super);
-			if (super->layout->bix_unready==super->layout->bix_end) {
-				printk("CacheFS: all blocks now added to recycling stack\n");
-				cachefs_debug = 1;
-			}
-			else {
-				yield();
+		if (super->dmn_die == 0) {
+			/* decant the recycling queue */
+			if (test_and_clear_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags))
+				cachefs_recycle_reclaim(super);
+
+			/* transfer blocks from the unready data if possible */
+			if (super->layout->bix_unready<super->layout->bix_end) {
+				cachefs_recycle_unready_blocks(super);
+				if (super->layout->bix_unready==super->layout->bix_end) {
+					printk("CacheFS:"
+					       " all blocks now added to recycling stack\n");
+					cachefs_debug = 1;
+				}
+				else {
+					yield();
+				}
 			}
+
+			/* if there's no next node, then get one */
+			if (!super->alloc_node)
+				cachefs_recycle_transfer_stack(super);
 		}
 
 		/* deal with validity journal changes */
@@ -125,15 +137,11 @@
 		if (!list_empty(&super->vjnl_writtenq))
 			cachefs_vj_note_write_completion(super);
 
-		/* if there's no next node, then get one */
-		if (!super->alloc_node)
-			cachefs_recycle_transfer_stack(super);
-
 		/* write a batch of metadata if it's time to do so */
 		if (test_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags))
 			cachefs_trans_batch_write(super);
 
-//		super->dmn_die = 1;
+//		super->dmn_die = 2;
 
 		_debug("@@@ End Cache Management");

Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- journal.c	9 Jun 2003 16:07:43 -0000	1.34
+++ journal.c	10 Jun 2003 17:49:49 -0000	1.35
@@ -388,7 +388,8 @@
 		 trans->jentry->count,
 		 trans->jentry->alloc_cur,	trans->jentry->alloc_leaf,
 		 trans->jentry->recycle_cur,
-		 trans->jentry->rcyblock,	trans->jentry->rcynext,	trans->jentry->rcystop
+		 trans->jentry->rcm_block,	trans->jentry->rcm_ptrnext,
+		 trans->jentry->rcm_ptrstop
 		 );
 
 	/* link the transaction into the marked list */
@@ -1508,7 +1509,7 @@
 	struct file_ra_state ra;
 	read_descriptor_t desc;
 	loff_t ppos;
-	int loop;
+	int loop, ret;
 
 	kenter("");
 
@@ -1642,19 +1643,19 @@
 
 	/* reload the front nodes for the allocation and recycling stacks */
 	if (super->alloc_cur) {
-		super->alloc_node =
-			read_cache_page(super->imisc->i_mapping,
-					super->alloc_cur,
-					(filler_t*)super->imisc->i_mapping->a_ops->readpage,
-					NULL);
-
-		dbgpgalloc(super->alloc_node);
-		if (IS_ERR(super->alloc_node)) {
-			printk("CacheFS: failed to reload alloc stack: %ld\n",
-			       PTR_ERR(super->alloc_node));
-			return PTR_ERR(super->alloc_node);
+		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);
 		wait_on_page_locked(super->alloc_node);
 
 		node = kmap(super->alloc_node);
@@ -1665,19 +1666,19 @@
 	}
 
 	if (super->recycle_cur) {
-		super->recycle_node =
-			read_cache_page(super->imisc->i_mapping,
-					super->recycle_cur,
-					(filler_t*)super->imisc->i_mapping->a_ops->readpage,
-					NULL);
-
-		dbgpgalloc(super->recycle_node);
-		if (IS_ERR(super->recycle_node)) {
-			printk("CacheFS: failed to reload alloc stack: %ld\n",
-			       PTR_ERR(super->recycle_node));
-			return PTR_ERR(super->recycle_node);
+		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);

Index: interface.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/interface.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- interface.c	9 Jun 2003 13:52:03 -0000	1.12
+++ interface.c	10 Jun 2003 17:49:49 -0000	1.13
@@ -831,7 +831,7 @@
  * - if the cookie is not backed by a file:
  *   - -ENOBUFS will be returned and nothing more will be done
  * - else if the page is backed by a block in the cache:
- *   - a read will be started which will call end_io_data on completion
+ *   - a read will be started which will call end_io_func on completion
  *   - the wb-journal will be searched for an entry pertaining to this block
  *     - if an entry is found:
  *       - 1 will be returned
@@ -928,7 +928,7 @@
 	write_unlock(&pageio->mapped_block->ref_lock);
 
 	/* new block allocated, but no data */
-	_debug("no data [bix=%u]",pageio->mapped_block->bix);
+	_debug("no data [bix=%u ref=%p]",pageio->mapped_block->bix,pageio);
 	up_read(&cookie->sem);
 	_leave(" = -ENODATA");
 	return -ENODATA;
@@ -1090,7 +1090,7 @@
 	return -ENOBUFS;
 
  write:
-	_debug("write [bix=%u]",block->bix);
+	_debug("write [bix=%u ref=%p]",block->bix,pageio);
 	cachefs_block_get(block);
 	set_bit(CACHEFS_BLOCK_NETFSBUSY,&block->flags);
 
@@ -1152,7 +1152,7 @@
  * - if the block backing the page still has a vjentry then the block will be
  *   recycled
  */
-void __cachefs_uncache_page(struct cachefs_cookie *cookie, struct page *page)
+void cachefs_uncache_page(struct cachefs_cookie *cookie, struct page *page)
 {
 	struct cachefs_block *block, *xblock;
 	struct cachefs_page *pageio;
@@ -1179,8 +1179,11 @@
 	block = pageio->mapped_block;
 	if (block) {
 		pageio->mapped_block = NULL; /* pin the block */
+		pageio->flags = 0;
 		write_unlock(&pageio->lock);
 
+		BUG_ON(block->ref != pageio);
+
 		/* locking order needs to be reversed */
 		write_lock(&block->ref_lock);
 		write_lock(&pageio->lock);
@@ -1197,6 +1200,6 @@
 
 	_leave("");
 	return;
-} /* end __cachefs_uncache_page() */
+} /* end cachefs_uncache_page() */
 
-EXPORT_SYMBOL(__cachefs_uncache_page);
+EXPORT_SYMBOL(cachefs_uncache_page);

Index: inode.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/inode.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- inode.c	4 Jun 2003 14:25:41 -0000	1.19
+++ inode.c	10 Jun 2003 17:49:49 -0000	1.20
@@ -116,6 +116,8 @@
 	inode->index_esize	= inode->index_dsize;
 	inode->index_epp	= PAGE_SIZE / inode->index_esize;
 
+	__set_bit(CACHEFS_ACTIVE_INODE_ISINDEX,&inode->flags);
+
 	/* read the page containing this inode's meta-data */
 	pos = inode->vfs_inode.i_ino << super->layout->metadata_bits;
 	ret = cachefs_get_page(inode,pos/PAGE_SIZE,&inode->metadata_page);
@@ -234,6 +236,8 @@
 		inode->vfs_inode.i_nlink	= 2;
 		inode->vfs_inode.i_op		= &cachefs_root_inode_operations;
 		inode->vfs_inode.i_fop		= &cachefs_root_file_operations;
+
+		__set_bit(CACHEFS_ACTIVE_INODE_ISINDEX,&inode->flags);
 	}
 
 	_leave(" = %d",ret);

Index: index.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/index.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- index.c	4 Jun 2003 14:25:41 -0000	1.21
+++ index.c	10 Jun 2003 17:49:49 -0000	1.22
@@ -245,7 +245,7 @@
 	newentry = metadata->freelink;
 	cachefs_metadata_postread(iinode);
 
-	_debug("free entry: %u",newentry);
+	_debug("free entry: %u [size %Lu]",newentry,iinode->vfs_inode.i_size);
 
 	/* we may need to extend the index file */
 	if (newentry==UINT_MAX) {
@@ -293,6 +293,8 @@
 		}
 	}
 
+	BUG_ON(!__cachefs_get_page_block(page));
+
 	*_page = page;
 	*_newentry = newentry;
 
@@ -306,7 +308,7 @@
 	return 0;
 
  error2:
-	page_cache_release(page);
+	cachefs_put_page(page);
  error:
 	_leave(" = %d",ret);
 	return ret;
@@ -464,9 +466,9 @@
 	*_newino = ino;
 
  error:
-	if (trans)	cachefs_trans_put(trans);
-	if (inopage)	page_cache_release(inopage);
-	if (ixpage)	page_cache_release(ixpage);
+	cachefs_trans_put(trans);
+	cachefs_put_page(inopage);
+	cachefs_put_page(ixpage);
 
 	_leave(" = %d",ret);
 	return ret;
@@ -562,13 +564,14 @@
 	ret = -EAGAIN;
 
  error_skip:
-	if (inode)	cachefs_iput(inode);
-	if (trans)	cachefs_trans_put(trans);
-	if (page)	put_page(page);
-	if (ret==-EIO)	super->rcm_block++;
+	cachefs_iput(inode);
+	cachefs_trans_put(trans);
+	cachefs_put_page(page);
+	if (ret==-EIO)
+		super->rcm_block++;
+
 	_leave(" = %d",ret);
 	return ret;
-
 } /* end cachefs_index_zap() */
 
 /*****************************************************************************/

Index: cachetest-main.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachetest-main.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- cachetest-main.c	3 Jun 2003 17:45:27 -0000	1.10
+++ cachetest-main.c	10 Jun 2003 17:49:49 -0000	1.11
@@ -133,8 +133,11 @@
 	.lock		= RW_LOCK_UNLOCKED,
 };
 
-static void afs_page_cache_write_complete(void *cookie_data, struct page *page, void *data);
-static void afs_page_cache_read_complete(void *cookie_data, struct page *page, void *data);
+static void afs_page_cache_write_complete(void *cookie_data, struct page *page, void *data,
+					  int error);
+
+static void afs_page_cache_read_complete(void *cookie_data, struct page *page, void *data,
+					 int error);
 
 /*****************************************************************************/
 /*
@@ -229,8 +232,8 @@
 {
 	printk(KERN_INFO "cachefstest: general fs caching v0.1 tester unregistering.\n");
 
-	cachefs_uncache_page(afs_root_dir.cache,afs_data_page ,&afs_data_page_cookie );
-	cachefs_uncache_page(afs_root_dir.cache,afs_data_page2,&afs_data_page2_cookie);
+	cachefs_uncache_page(afs_root_dir.cache,afs_data_page);
+	cachefs_uncache_page(afs_root_dir.cache,afs_data_page2);
 
 	__free_pages(afs_data_page,1);
 
@@ -337,9 +340,10 @@
 /*
  * 
  */
-static void afs_page_cache_write_complete(void *cookie_data, struct page *page, void *data)
+static void afs_page_cache_write_complete(void *cookie_data, struct page *page, void *data,
+					  int error)
 {
-	kenter("%p,%p,%p",cookie_data,page,data);
+	kenter("%p,%p,%p,%d",cookie_data,page,data,error);
 
 } /* end afs_page_cache_write_complete() */
 
@@ -347,9 +351,10 @@
 /*
  * 
  */
-static void afs_page_cache_read_complete(void *cookie_data, struct page *page, void *data)
+static void afs_page_cache_read_complete(void *cookie_data, struct page *page, void *data,
+					 int error)
 {
-	kenter("%p,%p,%p",cookie_data,page,data);
+	kenter("%p,%p,%p,%d",cookie_data,page,data,error);
 
 } /* end afs_page_cache_write_complete() */

Index: block.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/block.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- block.c	4 Jun 2003 14:25:41 -0000	1.6
+++ block.c	10 Jun 2003 17:49:49 -0000	1.7
@@ -599,6 +599,8 @@
 		write_lock(&block->ref_lock);
 		pageio = block->ref;
 		if (pageio) {
+			BUG_ON(pageio->mapped_block != block);
+
 			write_lock(&pageio->lock);
 			xblock = pageio->mapped_block;
 			pageio->mapped_block = NULL;

Index: aops.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/aops.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- aops.c	9 Jun 2003 15:03:34 -0000	1.35
+++ aops.c	10 Jun 2003 17:49:49 -0000	1.36
@@ -55,6 +55,8 @@
 static int cachefs_writepages(struct address_space *mapping, struct writeback_control *wbc);
 static int cachefs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to);
 static int cachefs_commit_write(struct file *file, struct page *page, unsigned from, unsigned to);
+static int cachefs_invalidatepage(struct page *page, unsigned long offset);
+static int cachefs_releasepage(struct page *page, int gfp_flags);
 
 struct address_space_operations cachefs_addrspace_operations = {
 	.readpage		= cachefs_readpage,
@@ -292,56 +294,62 @@
 		goto error;
 
 	last_block = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	if (page->index < last_block) {
-		if (inode->i_ino==CACHEFS_INO_METADATA && page->index==0) {
-			ret = cachefs_block_set2(inode->i_sb->s_fs_info,1,page,pageio,NULL);
-			if (ret<0)
-				goto error;
-		}
-		else {
-			ret = cachefs_get_block(inode,page,pageio,0);
-			if (ret<0)
-				goto error;
-		}
-	}
+	if (page->index >= last_block)
+		goto hole;
 
-	/* handle a hole */
-	if (!pageio->mapped_block) {
-		memset(kmap(page),0,PAGE_SIZE);
-		flush_dcache_page(page);
-		kunmap(page);
-		SetPageUptodate(page);
-		unlock_page(page);
+	if (inode->i_ino == CACHEFS_INO_METADATA && page->index == 0) {
+		ret = cachefs_block_set2(inode->i_sb->s_fs_info,1,page,pageio,NULL);
+		if (ret<0)
+			goto error;
 	}
 	else {
-		/* this page will go to BIO.  Do we need to send this BIO off first? */
-		if (*_bio && *last_block_in_bio != pageio->mapped_block->bix-1)
-			cachefs_io_bio_submit(READ,_bio);
-
-	alloc_new:
-		if (!*_bio) {
-			ret = cachefs_io_alloc(inode->i_sb,pageio->mapped_block->bix,
-					       nr_pages,GFP_KERNEL,_bio);
-			if (ret<0)
-				goto error;
-		}
+		ret = cachefs_get_block(inode,page,pageio,0);
+		if (ret<0)
+			goto error;
+	}
 
-		if (!bio_add_page(*_bio,page,PAGE_SIZE,0)) {
-			cachefs_io_bio_submit(READ,_bio);
-			goto alloc_new;
-		}
+	/* handle a hole */
+	if (!pageio->mapped_block)
+		goto hole;
 
-		if (test_bit(CACHEFS_PAGE_BOUNDARY,&pageio->flags))
-			cachefs_io_bio_submit(READ,_bio);
-		else
-			*last_block_in_bio = pageio->mapped_block->bix;
+	/* this page will go to BIO.  Do we need to send this BIO off first? */
+	if (*_bio && *last_block_in_bio != pageio->mapped_block->bix-1)
+		cachefs_io_bio_submit(READ,_bio);
+
+ alloc_new:
+	if (!*_bio) {
+		ret = cachefs_io_alloc(inode->i_sb,pageio->mapped_block->bix,
+				       nr_pages,GFP_KERNEL,_bio);
+		if (ret<0)
+			goto error;
 	}
 
+	if (!bio_add_page(*_bio,page,PAGE_SIZE,0)) {
+		cachefs_io_bio_submit(READ,_bio);
+		goto alloc_new;
+	}
+
+	if (test_bit(CACHEFS_PAGE_BOUNDARY,&pageio->flags))
+		cachefs_io_bio_submit(READ,_bio);
+	else
+		*last_block_in_bio = pageio->mapped_block->bix;
+
 	_leave(" = 0");
 	return 0;
 
+ hole:
+	ret = -ENODATA;
+	if (test_bit(CACHEFS_ACTIVE_INODE_ISINDEX,&CACHEFS_FS_I(inode)->flags)) {
+		printk("CacheFS: found unexpected hole in index/metadata file: ino=%lu pg=%lu\n",
+		       inode->i_ino,page->index);
+		ret = -EIO;
+	}
+
  error:
-	if (*_bio) cachefs_io_bio_submit(READ,_bio);
+	if (*_bio)
+		cachefs_io_bio_submit(READ,_bio);
+	unlock_page(page);
+
 	_leave("= %d",ret);
 	return ret;
 } /* end cachefs_do_readpage() */
@@ -805,7 +813,7 @@
 /*
  * invalidate part or all of a page
  */
-int cachefs_invalidatepage(struct page *page, unsigned long offset)
+static int cachefs_invalidatepage(struct page *page, unsigned long offset)
 {
 	struct cachefs_block *block;
 	struct cachefs_page *pageio;
@@ -837,13 +845,11 @@
 	return ret;
 } /* end cachefs_invalidatepage() */
 
-EXPORT_SYMBOL(cachefs_invalidatepage);
-
 /*****************************************************************************/
 /*
  * release a page and cleanup its private data
  */
-int cachefs_releasepage(struct page *page, int gfp_flags)
+static int cachefs_releasepage(struct page *page, int gfp_flags)
 {
 	struct cachefs_block *block;
 	struct cachefs_page *pageio;
@@ -868,8 +874,6 @@
 	return 0;
 } /* end cachefs_releasepage() */
 
-EXPORT_SYMBOL(cachefs_releasepage);
-
 /*****************************************************************************/
 /*
  * allocate a block
@@ -960,6 +964,7 @@
 	if (super->alloc_leaf==CACHEFS_ONDISC_LEAVES_PER_FREE_NODE) {
 		/* no dependent blocks left - take the alloc node itself */
 		block = super->alloc_block;
+		BUG_ON(!block);
 
 		jentry->block = super->alloc_cur;
 		BUG_ON(!jentry->block);
@@ -1101,6 +1106,7 @@
 	    test_bit(CACHEFS_BLOCK_CRITICAL,&block->flags)
 	    ) {
 		cachefs_trans_sync(super,0);
+		// TODO: wait for CRITICAL to be unset
 	}
 
 	cachefs_block_put(block);