
diff -puN fs/reiser4/vfs_ops.c~reiser4-no-inode_lock fs/reiser4/vfs_ops.c


 fs/reiser4/as_ops.c           |   76 ++++++++++++++++++++++++++++++++++-
 fs/reiser4/inode.c            |    5 +-
 fs/reiser4/plugin/item/tail.c |    2 
 fs/reiser4/txnmgr.c           |    2 
 fs/reiser4/vfs_ops.c          |   90 ++++++++----------------------------------
 fs/reiser4/vfs_ops.h          |    8 +++
 6 files changed, 105 insertions(+), 78 deletions(-)

diff -puN fs/reiser4/as_ops.c~reiser4-no-inode_lock fs/reiser4/as_ops.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/as_ops.c~reiser4-no-inode_lock	2005-05-04 13:24:19.149040463 +0400
+++ linux-2.6.12-rc2-mm3-vs/fs/reiser4/as_ops.c	2005-05-04 13:24:19.236047214 +0400
@@ -40,8 +40,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/writeback.h>
-#include <linux/backing-dev.h>
+#include <linux/blkdev.h>
 #include <linux/quotaops.h>
 #include <linux/security.h>
 
@@ -557,6 +556,7 @@ reiser4_releasepage(struct page *page, i
 #undef INC_NSTAT
 #undef INC_STAT
 
+#if 0
 reiser4_internal void
 move_inode_out_from_sync_inodes_loop(struct address_space * mapping)
 {
@@ -569,6 +569,58 @@ move_inode_out_from_sync_inodes_loop(str
 	spin_unlock(&inode_lock);
 
 }
+#endif
+
+/*
+ * Called by reiser4_sync_inodes(), during speculative write-back (through
+ * pdflush, or balance_dirty_pages()).
+ */
+static void
+writeout(struct super_block *sb, struct writeback_control *wbc)
+{
+	long written = 0;
+	int repeats = 0;
+
+	/*
+	 * Performs early flushing, trying to free some memory. If there is
+	 * nothing to flush, commits some atoms.
+	 */
+
+	/* Commit all atoms if reiser4_writepages() is called from sys_sync() or
+	   sys_fsync(). */
+	if (wbc->sync_mode != WB_SYNC_NONE) {
+		txnmgr_force_commit_all(sb, 1);
+		return;
+	}
+
+	do {
+		long nr_submitted = 0;
+		struct inode *fake;
+
+		fake = get_super_fake(sb);
+		if (fake != NULL) {
+			struct address_space *mapping;
+
+			mapping = fake->i_mapping;
+			/* do not put more requests to overload write queue */
+			if (wbc->nonblocking &&
+			    bdi_write_congested(mapping->backing_dev_info)) {
+				blk_run_address_space(mapping);
+				wbc->encountered_congestion = 1;
+				break;
+			}
+		}
+		repeats ++;
+		flush_some_atom(&nr_submitted, wbc, JNODE_FLUSH_WRITE_BLOCKS);
+		if (!nr_submitted)
+			break;
+
+		wbc->nr_to_write -= nr_submitted;
+		written += nr_submitted;
+
+	} while (wbc->nr_to_write > 0);
+
+}
 
 /* reiser4 writepages() address space operation this captures anonymous pages
    and anonymous jnodes. Anonymous pages are pages which are dirtied via
@@ -578,10 +630,13 @@ reiser4_internal int
 reiser4_writepages(struct address_space *mapping,
 		   struct writeback_control *wbc)
 {
+	reiser4_context ctx;
 	int ret = 0;
 	struct inode *inode;
 	file_plugin *fplug;
 
+	init_context(&ctx, mapping->host->i_sb);
+
 	inode = mapping->host;
 	fplug = inode_file_plugin(inode);
 	if (fplug != NULL && fplug->capture != NULL)
@@ -589,7 +644,22 @@ reiser4_writepages(struct address_space 
 		   anonymous jnodes */
 		ret = fplug->capture(inode, wbc);
 
-	move_inode_out_from_sync_inodes_loop(mapping);
+	if (wbc->sync_mode == WB_SYNC_NONE && (wbc->bdi || wbc->nonblocking)) {
+		/* balance_dirty_pages or background_writeout */
+		struct reiser4_wbc *r4_wbc;
+
+		r4_wbc = container_of(wbc, struct reiser4_wbc, wbc);
+		assert("", r4_wbc->magic == REISER4_WBC_MAGIC);
+		if (r4_wbc->first) {
+			writeout(inode->i_sb, wbc);
+			r4_wbc->first = 0;
+		}
+	} else
+		/* fsync_super, or sync_inodes */
+		writeout(inode->i_sb, wbc);		
+
+	context_set_commit_async(&ctx);
+	reiser4_exit_context(&ctx);
 	return ret;
 }
 
diff -puN fs/reiser4/plugin/item/tail.c~reiser4-no-inode_lock fs/reiser4/plugin/item/tail.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/item/tail.c~reiser4-no-inode_lock	2005-05-04 13:24:19.169042015 +0400
+++ linux-2.6.12-rc2-mm3-vs/fs/reiser4/plugin/item/tail.c	2005-05-04 13:24:19.240047525 +0400
@@ -481,8 +481,6 @@ tail_balance_dirty_pages(struct address_
 		/* FIXME-VS: this is temporary: the problem is that bdp takes
 		   inodes from sb's dirty list and it looks like nobody puts
 		   there inodes of files which are built of tails */
-		move_inode_out_from_sync_inodes_loop(mapping);
-
 		uf_info = unix_file_inode_data(inode);
 		excl = unix_file_inode_data(inode)->exclusive_use;
 		if (excl)
diff -puN fs/reiser4/vfs_ops.c~reiser4-no-inode_lock fs/reiser4/vfs_ops.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/vfs_ops.c~reiser4-no-inode_lock	2005-05-04 13:24:19.183043102 +0400
+++ linux-2.6.12-rc2-mm3-vs/fs/reiser4/vfs_ops.c	2005-05-04 17:13:47.688704737 +0400
@@ -47,7 +47,6 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/writeback.h>
 #include <linux/blkdev.h>
 #include <linux/quotaops.h>
 #include <linux/security.h>
@@ -555,92 +554,35 @@ reiser4_put_inode(struct inode *inode)
 	reiser4_exit_context(&ctx);
 }
 
-/*
- * Called by reiser4_sync_inodes(), during speculative write-back (through
- * pdflush, or balance_dirty_pages()).
- */
+/* ->sync_inodes() method. This is called by pdflush, and synchronous
+ * writeback (throttling by balance_dirty_pages()). */
 static void
-writeout(struct super_block *sb, struct writeback_control *wbc)
+reiser4_sync_inodes(struct super_block *sb, struct writeback_control *wbc)
 {
-	long written = 0;
-	int repeats = 0;
-
-	/*
-	 * Performs early flushing, trying to free some memory. If there is
-	 * nothing to flush, commits some atoms.
-	 */
+	struct reiser4_wbc r4_wbc;
 
 	/* reiser4 has its own means of periodical write-out */
 	if (wbc->for_kupdate)
 		return;
 
-	/* Commit all atoms if reiser4_writepages() is called from sys_sync() or
-	   sys_fsync(). */
-	if (wbc->sync_mode != WB_SYNC_NONE) {
-		txnmgr_force_commit_all(sb, 1);
-		return;
-	}
-
-	do {
-		long nr_submitted = 0;
-		struct inode *fake;
-
-		fake = get_super_fake(sb);
-		if (fake != NULL) {
-			struct address_space *mapping;
-
-			mapping = fake->i_mapping;
-			/* do not put more requests to overload write queue */
-			if (wbc->nonblocking &&
-			    bdi_write_congested(mapping->backing_dev_info)) {
-
-				blk_run_address_space(mapping);
-				/*blk_run_queues();*/
-				wbc->encountered_congestion = 1;
-				break;
-			}
-		}
-		repeats ++;
-		flush_some_atom(&nr_submitted, wbc, JNODE_FLUSH_WRITE_BLOCKS);
-		if (!nr_submitted)
-			break;
-
-		wbc->nr_to_write -= nr_submitted;
-
-		written += nr_submitted;
-
-	} while (wbc->nr_to_write > 0);
-
-}
-
-/* ->sync_inodes() method. This is called by pdflush, and synchronous
- * writeback (throttling by balance_dirty_pages()). */
-static void
-reiser4_sync_inodes(struct super_block * sb, struct writeback_control * wbc)
-{
-	reiser4_context ctx;
-
-	init_context(&ctx, sb);
-	wbc->older_than_this = NULL;
+	assert("", wbc->older_than_this == NULL);
+	r4_wbc.wbc = *wbc;
+	r4_wbc.first = 1;
+	r4_wbc.magic = REISER4_WBC_MAGIC;
 
 	/*
-	 * What we are trying to do here is to capture all "anonymous" pages.
+	 * call reiser4_writepages for sb's dirty inodes. First of them will do
+	 * writeout
 	 */
-	generic_sync_sb_inodes(sb, wbc);
-	/*capture_reiser4_inodes(sb, wbc);*/
-	spin_unlock(&inode_lock);
-	writeout(sb, wbc);
-
-	/* avoid recursive calls to ->sync_inodes */
-	context_set_commit_async(&ctx);
-	reiser4_exit_context(&ctx);
-	spin_lock(&inode_lock);
+	generic_sync_sb_inodes(sb, &r4_wbc.wbc);
+	*wbc = r4_wbc.wbc;
 }
 
 void reiser4_throttle_write(struct inode * inode)
 {
-	txn_restart_current();
+ 	txn_restart_current();
 	balance_dirty_pages_ratelimited(inode->i_mapping);
+ 	txn_restart_current();
 }
 
 /* ->delete_inode() super operation */
@@ -653,6 +595,10 @@ reiser4_delete_inode(struct inode *objec
 	if (is_inode_loaded(object)) {
 		file_plugin *fplug;
 
+		/* this is to prevent unability to grab space when
+		 * reiser4_delete_inode is called via ..->balance_dirty_pages
+		 * -> generic_sync_sb_inodes -> iput->iput_final... */
+		txn_restart_current();
 		fplug = inode_file_plugin(object);
 		if (fplug != NULL && fplug->delete != NULL)
 			fplug->delete(object);
diff -puN fs/reiser4/vfs_ops.h~reiser4-no-inode_lock fs/reiser4/vfs_ops.h
--- linux-2.6.12-rc2-mm3/fs/reiser4/vfs_ops.h~reiser4-no-inode_lock	2005-05-04 13:24:19.190043645 +0400
+++ linux-2.6.12-rc2-mm3-vs/fs/reiser4/vfs_ops.h	2005-05-04 13:24:19.238047370 +0400
@@ -20,6 +20,7 @@
 #include <linux/dcache.h>	/* for struct dentry */
 #include <linux/mm.h>
 #include <linux/backing-dev.h>
+#include <linux/writeback.h>
 
 extern int reiser4_mark_inode_dirty(struct inode *object);
 extern int reiser4_update_sd(struct inode *object);
@@ -124,6 +125,13 @@ extern reiser4_file_fsdata *create_fsdat
 extern void reiser4_handle_error(void);
 extern int reiser4_parse_options (struct super_block *, char *);
 
+#define REISER4_WBC_MAGIC 0x2906405
+struct reiser4_wbc {
+	int first;
+	int magic;
+	struct writeback_control wbc;
+};
+
 /* __FS_REISER4_VFS_OPS_H__ */
 #endif
 
diff -puN fs/reiser4/inode.c~reiser4-no-inode_lock fs/reiser4/inode.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/inode.c~reiser4-no-inode_lock	2005-05-04 14:40:14.794800041 +0400
+++ linux-2.6.12-rc2-mm3-vs/fs/reiser4/inode.c	2005-05-04 17:13:07.990533825 +0400
@@ -413,7 +413,9 @@ reiser4_iget(struct super_block *super /
 	assert("nikita-302", super != NULL);
 	assert("nikita-303", key != NULL);
 
-	result = 0;
+	/* can not continue having transaction opened. It would deadlock with
+	   reiser4_writepages/writeout which runs having inode locked */
+	txn_restart_current();
 
 	/* call iget(). Our ->read_inode() is dummy, so this will either
 	    find inode in cache or return uninitialised inode */
@@ -439,6 +441,7 @@ reiser4_iget(struct super_block *super /
 	   info->loading.  The place in reiser4 which uses not initialized inode
 	   is the reiser4 repacker, see repacker-related functions in
 	   plugin/item/extent.c */
+	result = 0;
 	if (!is_inode_loaded(inode)) {
 		loading_down(info);
 		if (!is_inode_loaded(inode)) {
diff -puN fs/reiser4/txnmgr.c~reiser4-no-inode_lock fs/reiser4/txnmgr.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/txnmgr.c~reiser4-no-inode_lock	2005-05-04 17:07:08.392264602 +0400
+++ linux-2.6.12-rc2-mm3-vs/fs/reiser4/txnmgr.c	2005-05-04 17:13:00.072900260 +0400
@@ -526,6 +526,7 @@ txn_end(reiser4_context * context)
 reiser4_internal void
 txn_restart(reiser4_context * context)
 {
+	assert("", context == get_current_context());
 	txn_end(context);
 	preempt_point();
 	txn_begin(context);
@@ -535,6 +536,7 @@ reiser4_internal void
 txn_restart_current(void)
 {
 	txn_restart(get_current_context());
+	grab_space_enable();
 }
 
 /* TXN_ATOM */

_
