From: Reiser4 Development Subject: In-kernel dependencies for reiser4 Patch-mainline: Probably never This patch contains the in-kernel dependencies needed by reiser4. Acked-by: Jeff Mahoney --- 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