From: Reiser4 Development <reiserfs-devel@vger.kernel.org>
Subject: In-kernel dependencies for reiser4
Patch-mainline: Probably never

 This patch contains the in-kernel dependencies needed by reiser4.

Acked-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/fs-writeback.c         |   48 +++++++++++++++++++++++++++++++++++++++-------
 fs/inode.c                |    1 
 include/linux/fs.h        |   14 ++++++++++++-
 include/linux/mm.h        |    1 
 include/linux/writeback.h |    3 ++
 mm/filemap.c              |    2 +
 mm/page-writeback.c       |   26 ++++++++++++++++++++++++
 7 files changed, 87 insertions(+), 8 deletions(-)

--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -461,8 +461,10 @@ static bool pin_sb_for_writeback(struct
  * Return 1, if the caller writeback routine should be
  * interrupted. Otherwise return 0.
  */
-static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
-		struct writeback_control *wbc, bool only_this_sb)
+int generic_writeback_sb_inodes(struct super_block *sb,
+				struct bdi_writeback *wb,
+				struct writeback_control *wbc,
+				bool only_this_sb)
 {
 	while (!list_empty(&wb->b_io)) {
 		long pages_skipped;
@@ -548,7 +550,10 @@ void writeback_inodes_wb(struct bdi_writ
 			requeue_io(inode);
 			continue;
 		}
-		ret = writeback_sb_inodes(sb, wb, wbc, false);
+		if (sb->s_op->writeback_inodes)
+			ret = sb->s_op->writeback_inodes(sb, wb, wbc, false);
+		else
+			ret = generic_writeback_sb_inodes(sb, wb, wbc, false);
 		drop_super(sb);
 
 		if (ret)
@@ -557,18 +562,21 @@ void writeback_inodes_wb(struct bdi_writ
 	spin_unlock(&inode_lock);
 	/* Leave any unwritten inodes on b_io */
 }
+EXPORT_SYMBOL(writeback_inodes_wb);
 
-static void __writeback_inodes_sb(struct super_block *sb,
+void __writeback_inodes_sb(struct super_block *sb,
 		struct bdi_writeback *wb, struct writeback_control *wbc)
 {
-	WARN_ON(!rwsem_is_locked(&sb->s_umount));
-
 	spin_lock(&inode_lock);
 	if (!wbc->for_kupdate || list_empty(&wb->b_io))
 		queue_io(wb, wbc->older_than_this);
-	writeback_sb_inodes(sb, wb, wbc, true);
+	if (sb->s_op->writeback_inodes)
+		sb->s_op->writeback_inodes(sb, wb, wbc, true);
+	else
+		generic_writeback_sb_inodes(sb, wb, wbc, true);
 	spin_unlock(&inode_lock);
 }
+EXPORT_SYMBOL(__writeback_inodes_sb);
 
 /*
  * The maximum number of pages to writeout in a single bdi flush/kupdate
@@ -688,6 +696,32 @@ static long wb_writeback(struct bdi_writ
 
 	return wrote;
 }
+EXPORT_SYMBOL(generic_writeback_sb_inodes);
+
+/*
+ * This function is for file systems which have their
+ * own means of periodical write-out of old data.
+ * NOTE: inode_lock should be hold.
+ *
+ * Skip a portion of b_io inodes which belong to @sb
+ * and go sequentially in reverse order.
+ */
+void writeback_skip_sb_inodes(struct super_block *sb,
+			      struct bdi_writeback *wb)
+{
+	while (1) {
+		struct inode *inode;
+
+		if (list_empty(&wb->b_io))
+			break;
+		inode = list_entry(wb->b_io.prev, struct inode, i_wb_list);
+		if (sb != inode->i_sb)
+			break;
+		redirty_tail(inode);
+	}
+}
+EXPORT_SYMBOL(writeback_skip_sb_inodes);
+
 
 /*
  * Return the next wb_writeback_work struct that hasn't been processed yet.
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -82,6 +82,7 @@ static struct hlist_head *inode_hashtabl
  * the i_state of an inode while it is in use..
  */
 DEFINE_SPINLOCK(inode_lock);
+EXPORT_SYMBOL_GPL(inode_lock);
 
 /*
  * iprune_sem provides exclusion between the kswapd or try_to_free_pages
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -522,6 +522,7 @@ enum positive_aop_returns {
 struct page;
 struct address_space;
 struct writeback_control;
+struct bdi_writeback;
 
 struct iov_iter {
 	const struct iovec *iov;
@@ -1605,7 +1606,12 @@ struct super_operations {
 	int (*statfs) (struct dentry *, struct kstatfs *);
 	int (*remount_fs) (struct super_block *, int *, char *);
 	void (*umount_begin) (struct super_block *);
-
+	int (*writeback_inodes)(struct super_block *sb,
+				struct bdi_writeback *wb,
+				struct writeback_control *wbc,
+				bool only_this_sb);
+	void (*sync_inodes) (struct super_block *sb,
+				struct writeback_control *wbc);
 	int (*show_options)(struct seq_file *, struct vfsmount *);
 	int (*show_stats)(struct seq_file *, struct vfsmount *);
 #ifdef CONFIG_QUOTA
@@ -2133,6 +2139,12 @@ extern int invalidate_inode_pages2(struc
 extern int invalidate_inode_pages2_range(struct address_space *mapping,
 					 pgoff_t start, pgoff_t end);
 extern int write_inode_now(struct inode *, int);
+extern void writeback_skip_sb_inodes(struct super_block *sb,
+				     struct bdi_writeback *wb);
+extern int generic_writeback_sb_inodes(struct super_block *sb,
+				       struct bdi_writeback *wb,
+				       struct writeback_control *wbc,
+				       bool only_this_sb);
 extern int filemap_fdatawrite(struct address_space *);
 extern int filemap_flush(struct address_space *);
 extern int filemap_fdatawait(struct address_space *);
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -875,6 +875,7 @@ void account_page_dirtied(struct page *p
 void account_page_writeback(struct page *page);
 int set_page_dirty(struct page *page);
 int set_page_dirty_lock(struct page *page);
+int set_page_dirty_notag(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
 
 /* Is the vma a continuation of the stack vma above it? */
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -64,6 +64,9 @@ int writeback_inodes_sb_nr_if_idle(struc
 void sync_inodes_sb(struct super_block *);
 void writeback_inodes_wb(struct bdi_writeback *wb,
 		struct writeback_control *wbc);
+void __writeback_inodes_sb(struct super_block *sb,
+			   struct bdi_writeback *wb,
+			   struct writeback_control *wbc);
 long wb_do_writeback(struct bdi_writeback *wb, int force_wait);
 void wakeup_flusher_threads(long nr_pages);
 
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -139,6 +139,7 @@ void __remove_from_page_cache(struct pag
 		dec_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE);
 	}
 }
+EXPORT_SYMBOL(__remove_from_page_cache);
 
 void remove_from_page_cache(struct page *page)
 {
@@ -967,6 +968,7 @@ static void shrink_readahead_size_eio(st
 {
 	ra->ra_pages /= 4;
 }
+EXPORT_SYMBOL(find_get_pages);
 
 /**
  * do_generic_file_read - generic file read routine
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1180,6 +1180,32 @@ int __set_page_dirty_nobuffers(struct pa
 EXPORT_SYMBOL(__set_page_dirty_nobuffers);
 
 /*
+ * set_page_dirty_notag() -- similar to __set_page_dirty_nobuffers()
+ * except it doesn't tag the page dirty in the page-cache radix tree.
+ * This means that the address space using this cannot use the regular
+ * filemap ->writepages() helpers and must provide its own means of
+ * tracking and finding non-tagged dirty pages.
+ *
+ * NOTE: furthermore, this version also doesn't handle truncate races.
+ */
+int set_page_dirty_notag(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+
+	if (!TestSetPageDirty(page)) {
+		unsigned long flags;
+		WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
+		local_irq_save(flags);
+		account_page_dirtied(page, mapping);
+		local_irq_restore(flags);
+		__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+		return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(set_page_dirty_notag);
+
+/*
  * When a writepage implementation decides that it doesn't want to write this
  * page for some reason, it should redirty the locked page via
  * redirty_page_for_writepage() and it should then unlock the page and return 0
