writeback: introduce queue_dirty()
Subsystems (4)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/3 writeback: introduce queue_dirty()
Introduce queue_dirty() to enqueue a newly dirtied inode. It helps remove duplicate code.
--- fs/fs-writeback.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
fs/fs-writeback.c +13 -8
@@ -24,6 +24,15 @@#include <linux/buffer_head.h> #include "internal.h" +/* +* Enqueue a newly dirtied inode. +*/ +static void queue_dirty (struct inode *inode) +{ + inode->dirtied_when = jiffies; +list_move (&inode->i_list, &inode->i_sb->s_dirty); +} +/** * __mark_inode_dirty - internal function * @inode: inode to mark
@@ -121,10 +130,8 @@ void __mark_inode_dirty(struct inode *in* If the inode was already on s_dirty/s_io/s_more_io, don't * reposition it (that would break s_dirty time-ordering). */ -if (!was_dirty) { - inode->dirtied_when = jiffies; -list_move (&inode->i_list, &sb->s_dirty); - } +if (!was_dirty) +queue_dirty (inode); } out:spin_unlock (&inode_lock);
@@ -466,10 +473,8 @@ int generic_sync_sb_inodes(struct super_ err =__writeback_single_inode (inode, wbc);if (!ret) ret = err; -if (wbc->sync_mode ==WB_SYNC_HOLD ) { - inode->dirtied_when = jiffies; -list_move (&inode->i_list, &sb->s_dirty); - } +if (wbc->sync_mode ==WB_SYNC_HOLD ) +queue_dirty (inode);if (current_is_pdflush ())writeback_release (bdi);if (wbc->pages_skipped != pages_skipped) {
PATCH 2/3 writeback: introduce dirty_volatile_interval
In reply to a message not in the archiveIntroduce dirty_volatile_interval for the minimal dirty time. Inodes dirtied less than dirty_volatile_interval will not be considered for syncing by kupdate-style writeback.
This new parameter will be used in clustered writeback. The old dirty_expire_interval is still(but less) respected.
--- include/linux/writeback.h | 1 + kernel/sysctl.c | 7 +++++++ mm/page-writeback.c | 5 +++++ 3 files changed, 13 insertions(+)
include/linux/writeback.h +1 -0
@@ -101,6 +101,7 @@ extern int dirty_background_ratio;extern int vm_dirty_ratio;extern int dirty_writeback_interval;extern int dirty_expire_interval; +extern int dirty_volatile_interval;extern int block_dump;extern int laptop_mode;
mm/page-writeback.c +5 -0
@@ -85,6 +85,11 @@ int dirty_writeback_interval = 5 * HZ;int dirty_expire_interval =30 *HZ ;/* +* The shortest number of jiffies for which data should remain dirty +*/ +int dirty_volatile_interval =5 *HZ ; + +/* * Flag that makes the machine dump writes/reads and block dirtyings. */ int block_dump;
kernel/sysctl.c +7 -0
@@ -837,6 +837,13 @@ static struct ctl_table vm_table[] = { .proc_handler = &proc_dointvec_userhz_jiffies, }, { + .procname = "dirty_volatile_centisecs", + .data = &dirty_volatile_interval, + .maxlen = sizeof(dirty_volatile_interval), + .mode = 0644, + .proc_handler = &proc_dointvec_userhz_jiffies, + }, + { .ctl_name = VM_NR_PDFLUSH_THREADS, .procname = "nr_pdflush_threads", .data = &nr_pdflush_threads,
PATCH 3/3 writeback: writeback clustering by inode number
In reply to a message not in the archiveOrganize dirty inodes in the order of location instead of dirty time. It helps write extensive workloads to be more seek-friendly.
There are 2 candidates for this feature:
1) XFS style piggybacking
write all expired(age>30s) inodes, plus the ones near them(any ages)
2) elevator style sweep scanning
in each kupdate wake ups, walk 1/5 the partition and write all non-volatile(age>5s) inodes in that range
This patch implements the second scheme. The merits of it are:
- more predictable behavior
- can smooth out time-bursty writes
However, it does not help space-bursty caused by hot write areas.
For many filesystems(ext3/XFS/...), inode number is a good location hint for the inode. However inode data blocks may not necessarily lie close to the inode itself(i.e. XFS), hence we should somehow extend the location hint in future.
--- fs/fs-writeback.c | 129 +++++++++++++++++++++++++++++++++++++++++++ fs/super.c | 2 include/linux/fs.h | 10 +++ 3 files changed, 141 insertions(+)
fs/super.c +2 -0
@@ -61,6 +61,8 @@ static struct super_block *alloc_super(s s =NULL ; goto out; } +INIT_RADIX_TREE (&s->s_dirty_tree.inode_tree,GFP_ATOMIC ); +INIT_LIST_HEAD (&s->s_dirty_tree.inode_list);INIT_LIST_HEAD (&s->s_dirty);INIT_LIST_HEAD (&s->s_io);INIT_LIST_HEAD (&s->s_more_io);
include/linux/fs.h +10 -0
@@ -978,6 +978,15 @@ extern int send_sigurg(struct fown_strucextern struct list_head super_blocks;extern spinlock_t sb_lock; +struct dirty_inode_tree { +struct list_head inode_list; +struct radix_tree_root inode_tree; +unsigned long nr_inodes; +unsigned long max_index; +unsigned long start_jiffies;/* when the scan started? */ +unsigned long next_index;/* where it is in the scan? */ +}; +#define sb_entry (list) list_entry((list), struct super_block, s_list)#define S_BIAS (1<<30)struct super_block {
@@ -1007,6 +1016,7 @@ struct super_block {struct xattr_handler **s_xattr;struct list_head s_inodes;/* all inodes */ +struct dirty_inode_tree s_dirty_tree;struct list_head s_dirty;/* dirty inodes */ struct list_head s_io;/* parked for writeback */ struct list_head s_more_io;/* parked for more writeback */
fs/fs-writeback.c +129 -0
152 lines not on this page · raw message