Skip to contentSkip to conversation

writeback: introduce queue_dirty()

PATCH New Fengguang Wu 1 participant 3 messages Aug 27, 2007 1 message not in the archive

Subsystems (4)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

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) {
#2 lore raw

PATCH 2/3 writeback: introduce dirty_volatile_interval

In reply to a message not in the archive

Introduce 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.

Cc Chris Mason <[email protected]>
Cc Jens Axboe <[email protected]>
Cc David Chinner <[email protected]>
Cc Ken Chen <[email protected]>
Cc Michael Rubin <[email protected]>
Cc Andrew Morton <[email protected]>
---
 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,
#3 lore raw

PATCH 3/3 writeback: writeback clustering by inode number

In reply to a message not in the archive

Organize 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.

Cc Chris Mason <[email protected]>
Cc Jens Axboe <[email protected]>
Cc David Chinner <[email protected]>
Cc Ken Chen <[email protected]>
Cc Michael Rubin <[email protected]>
Cc Andrew Morton <[email protected]>
---
 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_struc
 extern 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