226 lines
7.3 KiB
Plaintext
226 lines
7.3 KiB
Plaintext
|
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
|