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

_