diff options
| author | Curt Wohlgemuth <curtw@google.com> | 2011-10-07 21:54:10 -0600 | 
|---|---|---|
| committer | Wu Fengguang <fengguang.wu@intel.com> | 2011-10-31 00:33:36 +0800 | 
| commit | 0e175a1835ffc979e55787774e58ec79e41957d7 (patch) | |
| tree | 6ec4b65a8de4e9d1c12d26a1079079ed81d79450 /fs/fs-writeback.c | |
| parent | ad4e38dd6a33bb3a4882c487d7abe621e583b982 (diff) | |
| download | olio-linux-3.10-0e175a1835ffc979e55787774e58ec79e41957d7.tar.xz olio-linux-3.10-0e175a1835ffc979e55787774e58ec79e41957d7.zip  | |
writeback: Add a 'reason' to wb_writeback_work
This creates a new 'reason' field in a wb_writeback_work
structure, which unambiguously identifies who initiates
writeback activity.  A 'wb_reason' enumeration has been
added to writeback.h, to enumerate the possible reasons.
The 'writeback_work_class' and tracepoint event class and
'writeback_queue_io' tracepoints are updated to include the
symbolic 'reason' in all trace events.
And the 'writeback_inodes_sbXXX' family of routines has had
a wb_stats parameter added to them, so callers can specify
why writeback is being started.
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Curt Wohlgemuth <curtw@google.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Diffstat (limited to 'fs/fs-writeback.c')
| -rw-r--r-- | fs/fs-writeback.c | 49 | 
1 files changed, 36 insertions, 13 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c5102969360..73c3992b2bb 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -41,11 +41,23 @@ struct wb_writeback_work {  	unsigned int for_kupdate:1;  	unsigned int range_cyclic:1;  	unsigned int for_background:1; +	enum wb_reason reason;		/* why was writeback initiated? */  	struct list_head list;		/* pending work list */  	struct completion *done;	/* set if the caller waits */  }; +const char *wb_reason_name[] = { +	[WB_REASON_BACKGROUND]		= "background", +	[WB_REASON_TRY_TO_FREE_PAGES]	= "try_to_free_pages", +	[WB_REASON_SYNC]		= "sync", +	[WB_REASON_PERIODIC]		= "periodic", +	[WB_REASON_LAPTOP_TIMER]	= "laptop_timer", +	[WB_REASON_FREE_MORE_MEM]	= "free_more_memory", +	[WB_REASON_FS_FREE_SPACE]	= "fs_free_space", +	[WB_REASON_FORKER_THREAD]	= "forker_thread" +}; +  /*   * Include the creation of the trace points after defining the   * wb_writeback_work structure so that the definition remains local to this @@ -115,7 +127,7 @@ static void bdi_queue_work(struct backing_dev_info *bdi,  static void  __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, -		      bool range_cyclic) +		      bool range_cyclic, enum wb_reason reason)  {  	struct wb_writeback_work *work; @@ -135,6 +147,7 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,  	work->sync_mode	= WB_SYNC_NONE;  	work->nr_pages	= nr_pages;  	work->range_cyclic = range_cyclic; +	work->reason	= reason;  	bdi_queue_work(bdi, work);  } @@ -150,9 +163,10 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,   *   completion. Caller need not hold sb s_umount semaphore.   *   */ -void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages) +void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, +			enum wb_reason reason)  { -	__bdi_start_writeback(bdi, nr_pages, true); +	__bdi_start_writeback(bdi, nr_pages, true, reason);  }  /** @@ -641,12 +655,14 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb,  	return wrote;  } -long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages) +long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, +				enum wb_reason reason)  {  	struct wb_writeback_work work = {  		.nr_pages	= nr_pages,  		.sync_mode	= WB_SYNC_NONE,  		.range_cyclic	= 1, +		.reason		= reason,  	};  	spin_lock(&wb->list_lock); @@ -825,6 +841,7 @@ static long wb_check_background_flush(struct bdi_writeback *wb)  			.sync_mode	= WB_SYNC_NONE,  			.for_background	= 1,  			.range_cyclic	= 1, +			.reason		= WB_REASON_BACKGROUND,  		};  		return wb_writeback(wb, &work); @@ -858,6 +875,7 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb)  			.sync_mode	= WB_SYNC_NONE,  			.for_kupdate	= 1,  			.range_cyclic	= 1, +			.reason		= WB_REASON_PERIODIC,  		};  		return wb_writeback(wb, &work); @@ -976,7 +994,7 @@ int bdi_writeback_thread(void *data)   * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back   * the whole world.   */ -void wakeup_flusher_threads(long nr_pages) +void wakeup_flusher_threads(long nr_pages, enum wb_reason reason)  {  	struct backing_dev_info *bdi; @@ -989,7 +1007,7 @@ void wakeup_flusher_threads(long nr_pages)  	list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {  		if (!bdi_has_dirty_io(bdi))  			continue; -		__bdi_start_writeback(bdi, nr_pages, false); +		__bdi_start_writeback(bdi, nr_pages, false, reason);  	}  	rcu_read_unlock();  } @@ -1210,7 +1228,9 @@ static void wait_sb_inodes(struct super_block *sb)   * on how many (if any) will be written, and this function does not wait   * for IO completion of submitted IO.   */ -void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr) +void writeback_inodes_sb_nr(struct super_block *sb, +			    unsigned long nr, +			    enum wb_reason reason)  {  	DECLARE_COMPLETION_ONSTACK(done);  	struct wb_writeback_work work = { @@ -1219,6 +1239,7 @@ void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr)  		.tagged_writepages	= 1,  		.done			= &done,  		.nr_pages		= nr, +		.reason			= reason,  	};  	WARN_ON(!rwsem_is_locked(&sb->s_umount)); @@ -1235,9 +1256,9 @@ EXPORT_SYMBOL(writeback_inodes_sb_nr);   * on how many (if any) will be written, and this function does not wait   * for IO completion of submitted IO.   */ -void writeback_inodes_sb(struct super_block *sb) +void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason)  { -	return writeback_inodes_sb_nr(sb, get_nr_dirty_pages()); +	return writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason);  }  EXPORT_SYMBOL(writeback_inodes_sb); @@ -1248,11 +1269,11 @@ EXPORT_SYMBOL(writeback_inodes_sb);   * Invoke writeback_inodes_sb if no writeback is currently underway.   * Returns 1 if writeback was started, 0 if not.   */ -int writeback_inodes_sb_if_idle(struct super_block *sb) +int writeback_inodes_sb_if_idle(struct super_block *sb, enum wb_reason reason)  {  	if (!writeback_in_progress(sb->s_bdi)) {  		down_read(&sb->s_umount); -		writeback_inodes_sb(sb); +		writeback_inodes_sb(sb, reason);  		up_read(&sb->s_umount);  		return 1;  	} else @@ -1269,11 +1290,12 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle);   * Returns 1 if writeback was started, 0 if not.   */  int writeback_inodes_sb_nr_if_idle(struct super_block *sb, -				   unsigned long nr) +				   unsigned long nr, +				   enum wb_reason reason)  {  	if (!writeback_in_progress(sb->s_bdi)) {  		down_read(&sb->s_umount); -		writeback_inodes_sb_nr(sb, nr); +		writeback_inodes_sb_nr(sb, nr, reason);  		up_read(&sb->s_umount);  		return 1;  	} else @@ -1297,6 +1319,7 @@ void sync_inodes_sb(struct super_block *sb)  		.nr_pages	= LONG_MAX,  		.range_cyclic	= 0,  		.done		= &done, +		.reason		= WB_REASON_SYNC,  	};  	WARN_ON(!rwsem_is_locked(&sb->s_umount));  |