2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* fs/fs-writeback.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2002, Linus Torvalds.
|
|
|
|
*
|
|
|
|
* Contains all the functions related to writing back and waiting
|
|
|
|
* upon dirty inodes against superblocks, and writing back dirty
|
|
|
|
* pages against inodes. ie: data writeback. Writeout of the
|
|
|
|
* inode itself is not handled here.
|
|
|
|
*
|
2008-10-16 13:01:59 +08:00
|
|
|
* 10Apr2002 Andrew Morton
|
2005-04-17 06:20:36 +08:00
|
|
|
* Split out of fs/inode.c
|
|
|
|
* Additions for address_space-based writeback
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
2011-11-17 12:57:37 +08:00
|
|
|
#include <linux/export.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/spinlock.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/mm.h>
|
2012-01-08 10:41:55 +08:00
|
|
|
#include <linux/pagemap.h>
|
2009-09-09 15:08:54 +08:00
|
|
|
#include <linux/kthread.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/writeback.h>
|
|
|
|
#include <linux/blkdev.h>
|
|
|
|
#include <linux/backing-dev.h>
|
2010-07-07 11:24:06 +08:00
|
|
|
#include <linux/tracepoint.h>
|
2013-09-29 23:24:49 +08:00
|
|
|
#include <linux/device.h>
|
2015-05-29 02:50:49 +08:00
|
|
|
#include <linux/memcontrol.h>
|
2006-10-01 02:52:18 +08:00
|
|
|
#include "internal.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-01-08 10:41:55 +08:00
|
|
|
/*
|
|
|
|
* 4MB minimal write chunk size
|
|
|
|
*/
|
|
|
|
#define MIN_WRITEBACK_PAGES (4096UL >> (PAGE_CACHE_SHIFT - 10))
|
|
|
|
|
2015-05-23 05:13:58 +08:00
|
|
|
struct wb_completion {
|
|
|
|
atomic_t cnt;
|
|
|
|
};
|
|
|
|
|
2009-09-16 21:18:25 +08:00
|
|
|
/*
|
|
|
|
* Passed into wb_writeback(), essentially a subset of writeback_control
|
|
|
|
*/
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work {
|
2009-09-16 21:18:25 +08:00
|
|
|
long nr_pages;
|
|
|
|
struct super_block *sb;
|
2014-02-21 18:19:04 +08:00
|
|
|
unsigned long *older_than_this;
|
2009-09-16 21:18:25 +08:00
|
|
|
enum writeback_sync_modes sync_mode;
|
2010-06-07 00:38:15 +08:00
|
|
|
unsigned int tagged_writepages:1;
|
2010-04-02 09:36:30 +08:00
|
|
|
unsigned int for_kupdate:1;
|
|
|
|
unsigned int range_cyclic:1;
|
|
|
|
unsigned int for_background:1;
|
2013-07-02 20:38:35 +08:00
|
|
|
unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */
|
2015-05-23 05:13:57 +08:00
|
|
|
unsigned int auto_free:1; /* free on completion */
|
2011-10-08 11:54:10 +08:00
|
|
|
enum wb_reason reason; /* why was writeback initiated? */
|
2009-09-16 21:18:25 +08:00
|
|
|
|
2009-09-16 02:04:57 +08:00
|
|
|
struct list_head list; /* pending work list */
|
2015-05-23 05:13:58 +08:00
|
|
|
struct wb_completion *done; /* set if the caller waits */
|
2009-09-09 15:08:54 +08:00
|
|
|
};
|
|
|
|
|
2015-05-23 05:13:58 +08:00
|
|
|
/*
|
|
|
|
* If one wants to wait for one or more wb_writeback_works, each work's
|
|
|
|
* ->done should be set to a wb_completion defined using the following
|
|
|
|
* macro. Once all work items are issued with wb_queue_work(), the caller
|
|
|
|
* can wait for the completion of all using wb_wait_for_completion(). Work
|
|
|
|
* items which are waited upon aren't freed automatically on completion.
|
|
|
|
*/
|
|
|
|
#define DEFINE_WB_COMPLETION_ONSTACK(cmpl) \
|
|
|
|
struct wb_completion cmpl = { \
|
|
|
|
.cnt = ATOMIC_INIT(1), \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-18 00:23:19 +08:00
|
|
|
/*
|
|
|
|
* If an inode is constantly having its pages dirtied, but then the
|
|
|
|
* updates stop dirtytime_expire_interval seconds in the past, it's
|
|
|
|
* possible for the worst case time between when an inode has its
|
|
|
|
* timestamps updated and when they finally get written out to be two
|
|
|
|
* dirtytime_expire_intervals. We set the default to 12 hours (in
|
|
|
|
* seconds), which means most of the time inodes will have their
|
|
|
|
* timestamps written to disk after 12 hours, but in the worst case a
|
|
|
|
* few inodes might not their timestamps updated for 24 hours.
|
|
|
|
*/
|
|
|
|
unsigned int dirtytime_expire_interval = 12 * 60 * 60;
|
|
|
|
|
2010-10-21 08:49:30 +08:00
|
|
|
static inline struct inode *wb_inode(struct list_head *head)
|
|
|
|
{
|
|
|
|
return list_entry(head, struct inode, i_wb_list);
|
|
|
|
}
|
|
|
|
|
2012-01-18 01:18:56 +08:00
|
|
|
/*
|
|
|
|
* Include the creation of the trace points after defining the
|
|
|
|
* wb_writeback_work structure and inline functions so that the definition
|
|
|
|
* remains local to this file.
|
|
|
|
*/
|
|
|
|
#define CREATE_TRACE_POINTS
|
|
|
|
#include <trace/events/writeback.h>
|
|
|
|
|
2014-02-06 23:47:47 +08:00
|
|
|
EXPORT_TRACEPOINT_SYMBOL_GPL(wbc_writepage);
|
|
|
|
|
2015-05-23 05:13:45 +08:00
|
|
|
static bool wb_io_lists_populated(struct bdi_writeback *wb)
|
|
|
|
{
|
|
|
|
if (wb_has_dirty_io(wb)) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
set_bit(WB_has_dirty_io, &wb->state);
|
2015-05-23 05:13:47 +08:00
|
|
|
WARN_ON_ONCE(!wb->avg_write_bandwidth);
|
2015-05-23 05:13:46 +08:00
|
|
|
atomic_long_add(wb->avg_write_bandwidth,
|
|
|
|
&wb->bdi->tot_write_bandwidth);
|
2015-05-23 05:13:45 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wb_io_lists_depopulated(struct bdi_writeback *wb)
|
|
|
|
{
|
|
|
|
if (wb_has_dirty_io(wb) && list_empty(&wb->b_dirty) &&
|
2015-05-23 05:13:46 +08:00
|
|
|
list_empty(&wb->b_io) && list_empty(&wb->b_more_io)) {
|
2015-05-23 05:13:45 +08:00
|
|
|
clear_bit(WB_has_dirty_io, &wb->state);
|
2015-05-23 05:13:47 +08:00
|
|
|
WARN_ON_ONCE(atomic_long_sub_return(wb->avg_write_bandwidth,
|
|
|
|
&wb->bdi->tot_write_bandwidth) < 0);
|
2015-05-23 05:13:46 +08:00
|
|
|
}
|
2015-05-23 05:13:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* inode_wb_list_move_locked - move an inode onto a bdi_writeback IO list
|
|
|
|
* @inode: inode to be moved
|
|
|
|
* @wb: target bdi_writeback
|
|
|
|
* @head: one of @wb->b_{dirty|io|more_io}
|
|
|
|
*
|
|
|
|
* Move @inode->i_wb_list to @list of @wb and set %WB_has_dirty_io.
|
|
|
|
* Returns %true if @inode is the first occupant of the !dirty_time IO
|
|
|
|
* lists; otherwise, %false.
|
|
|
|
*/
|
|
|
|
static bool inode_wb_list_move_locked(struct inode *inode,
|
|
|
|
struct bdi_writeback *wb,
|
|
|
|
struct list_head *head)
|
|
|
|
{
|
|
|
|
assert_spin_locked(&wb->list_lock);
|
|
|
|
|
|
|
|
list_move(&inode->i_wb_list, head);
|
|
|
|
|
|
|
|
/* dirty_time doesn't count as dirty_io until expiration */
|
|
|
|
if (head != &wb->b_dirty_time)
|
|
|
|
return wb_io_lists_populated(wb);
|
|
|
|
|
|
|
|
wb_io_lists_depopulated(wb);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* inode_wb_list_del_locked - remove an inode from its bdi_writeback IO list
|
|
|
|
* @inode: inode to be removed
|
|
|
|
* @wb: bdi_writeback @inode is being removed from
|
|
|
|
*
|
|
|
|
* Remove @inode which may be on one of @wb->b_{dirty|io|more_io} lists and
|
|
|
|
* clear %WB_has_dirty_io if all are empty afterwards.
|
|
|
|
*/
|
|
|
|
static void inode_wb_list_del_locked(struct inode *inode,
|
|
|
|
struct bdi_writeback *wb)
|
|
|
|
{
|
|
|
|
assert_spin_locked(&wb->list_lock);
|
|
|
|
|
|
|
|
list_del_init(&inode->i_wb_list);
|
|
|
|
wb_io_lists_depopulated(wb);
|
|
|
|
}
|
|
|
|
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
static void wb_wakeup(struct bdi_writeback *wb)
|
2014-04-04 05:46:23 +08:00
|
|
|
{
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
spin_lock_bh(&wb->work_lock);
|
|
|
|
if (test_bit(WB_registered, &wb->state))
|
|
|
|
mod_delayed_work(bdi_wq, &wb->dwork, 0);
|
|
|
|
spin_unlock_bh(&wb->work_lock);
|
2014-04-04 05:46:23 +08:00
|
|
|
}
|
|
|
|
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
static void wb_queue_work(struct bdi_writeback *wb,
|
|
|
|
struct wb_writeback_work *work)
|
2011-01-14 07:45:44 +08:00
|
|
|
{
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
trace_writeback_queue(wb->bdi, work);
|
2011-01-14 07:45:44 +08:00
|
|
|
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
spin_lock_bh(&wb->work_lock);
|
2015-08-19 05:54:53 +08:00
|
|
|
if (!test_bit(WB_registered, &wb->state))
|
2014-04-04 05:46:23 +08:00
|
|
|
goto out_unlock;
|
2015-05-23 05:13:58 +08:00
|
|
|
if (work->done)
|
|
|
|
atomic_inc(&work->done->cnt);
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
list_add_tail(&work->list, &wb->work_list);
|
|
|
|
mod_delayed_work(bdi_wq, &wb->dwork, 0);
|
2014-04-04 05:46:23 +08:00
|
|
|
out_unlock:
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
spin_unlock_bh(&wb->work_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-05-23 05:13:58 +08:00
|
|
|
/**
|
|
|
|
* wb_wait_for_completion - wait for completion of bdi_writeback_works
|
|
|
|
* @bdi: bdi work items were issued to
|
|
|
|
* @done: target wb_completion
|
|
|
|
*
|
|
|
|
* Wait for one or more work items issued to @bdi with their ->done field
|
|
|
|
* set to @done, which should have been defined with
|
|
|
|
* DEFINE_WB_COMPLETION_ONSTACK(). This function returns after all such
|
|
|
|
* work items are completed. Work items which are waited upon aren't freed
|
|
|
|
* automatically on completion.
|
|
|
|
*/
|
|
|
|
static void wb_wait_for_completion(struct backing_dev_info *bdi,
|
|
|
|
struct wb_completion *done)
|
|
|
|
{
|
|
|
|
atomic_dec(&done->cnt); /* put down the initial count */
|
|
|
|
wait_event(bdi->wb_waitq, !atomic_read(&done->cnt));
|
|
|
|
}
|
|
|
|
|
2015-05-23 05:13:44 +08:00
|
|
|
#ifdef CONFIG_CGROUP_WRITEBACK
|
|
|
|
|
2015-05-29 02:50:51 +08:00
|
|
|
/* parameters for foreign inode detection, see wb_detach_inode() */
|
|
|
|
#define WB_FRN_TIME_SHIFT 13 /* 1s = 2^13, upto 8 secs w/ 16bit */
|
|
|
|
#define WB_FRN_TIME_AVG_SHIFT 3 /* avg = avg * 7/8 + new * 1/8 */
|
|
|
|
#define WB_FRN_TIME_CUT_DIV 2 /* ignore rounds < avg / 2 */
|
|
|
|
#define WB_FRN_TIME_PERIOD (2 * (1 << WB_FRN_TIME_SHIFT)) /* 2s */
|
|
|
|
|
|
|
|
#define WB_FRN_HIST_SLOTS 16 /* inode->i_wb_frn_history is 16bit */
|
|
|
|
#define WB_FRN_HIST_UNIT (WB_FRN_TIME_PERIOD / WB_FRN_HIST_SLOTS)
|
|
|
|
/* each slot's duration is 2s / 16 */
|
|
|
|
#define WB_FRN_HIST_THR_SLOTS (WB_FRN_HIST_SLOTS / 2)
|
|
|
|
/* if foreign slots >= 8, switch */
|
|
|
|
#define WB_FRN_HIST_MAX_SLOTS (WB_FRN_HIST_THR_SLOTS / 2 + 1)
|
|
|
|
/* one round can affect upto 5 slots */
|
|
|
|
|
2015-05-29 02:50:49 +08:00
|
|
|
void __inode_attach_wb(struct inode *inode, struct page *page)
|
|
|
|
{
|
|
|
|
struct backing_dev_info *bdi = inode_to_bdi(inode);
|
|
|
|
struct bdi_writeback *wb = NULL;
|
|
|
|
|
|
|
|
if (inode_cgwb_enabled(inode)) {
|
|
|
|
struct cgroup_subsys_state *memcg_css;
|
|
|
|
|
|
|
|
if (page) {
|
|
|
|
memcg_css = mem_cgroup_css_from_page(page);
|
|
|
|
wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
|
|
|
|
} else {
|
|
|
|
/* must pin memcg_css, see wb_get_create() */
|
|
|
|
memcg_css = task_get_css(current, memory_cgrp_id);
|
|
|
|
wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
|
|
|
|
css_put(memcg_css);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!wb)
|
|
|
|
wb = &bdi->wb;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There may be multiple instances of this function racing to
|
|
|
|
* update the same inode. Use cmpxchg() to tell the winner.
|
|
|
|
*/
|
|
|
|
if (unlikely(cmpxchg(&inode->i_wb, NULL, wb)))
|
|
|
|
wb_put(wb);
|
|
|
|
}
|
|
|
|
|
2015-05-29 02:50:52 +08:00
|
|
|
/**
|
|
|
|
* locked_inode_to_wb_and_lock_list - determine a locked inode's wb and lock it
|
|
|
|
* @inode: inode of interest with i_lock held
|
|
|
|
*
|
|
|
|
* Returns @inode's wb with its list_lock held. @inode->i_lock must be
|
|
|
|
* held on entry and is released on return. The returned wb is guaranteed
|
|
|
|
* to stay @inode's associated wb until its list_lock is released.
|
|
|
|
*/
|
|
|
|
static struct bdi_writeback *
|
|
|
|
locked_inode_to_wb_and_lock_list(struct inode *inode)
|
|
|
|
__releases(&inode->i_lock)
|
|
|
|
__acquires(&wb->list_lock)
|
|
|
|
{
|
|
|
|
while (true) {
|
|
|
|
struct bdi_writeback *wb = inode_to_wb(inode);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* inode_to_wb() association is protected by both
|
|
|
|
* @inode->i_lock and @wb->list_lock but list_lock nests
|
|
|
|
* outside i_lock. Drop i_lock and verify that the
|
|
|
|
* association hasn't changed after acquiring list_lock.
|
|
|
|
*/
|
|
|
|
wb_get(wb);
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
spin_lock(&wb->list_lock);
|
|
|
|
wb_put(wb); /* not gonna deref it anymore */
|
|
|
|
|
2015-05-29 02:50:55 +08:00
|
|
|
/* i_wb may have changed inbetween, can't use inode_to_wb() */
|
|
|
|
if (likely(wb == inode->i_wb))
|
2015-05-29 02:50:52 +08:00
|
|
|
return wb; /* @inode already has ref */
|
|
|
|
|
|
|
|
spin_unlock(&wb->list_lock);
|
|
|
|
cpu_relax();
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* inode_to_wb_and_lock_list - determine an inode's wb and lock it
|
|
|
|
* @inode: inode of interest
|
|
|
|
*
|
|
|
|
* Same as locked_inode_to_wb_and_lock_list() but @inode->i_lock isn't held
|
|
|
|
* on entry.
|
|
|
|
*/
|
|
|
|
static struct bdi_writeback *inode_to_wb_and_lock_list(struct inode *inode)
|
|
|
|
__acquires(&wb->list_lock)
|
|
|
|
{
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
return locked_inode_to_wb_and_lock_list(inode);
|
|
|
|
}
|
|
|
|
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
struct inode_switch_wbs_context {
|
|
|
|
struct inode *inode;
|
|
|
|
struct bdi_writeback *new_wb;
|
|
|
|
|
|
|
|
struct rcu_head rcu_head;
|
|
|
|
struct work_struct work;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void inode_switch_wbs_work_fn(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct inode_switch_wbs_context *isw =
|
|
|
|
container_of(work, struct inode_switch_wbs_context, work);
|
|
|
|
struct inode *inode = isw->inode;
|
2015-05-29 02:50:56 +08:00
|
|
|
struct address_space *mapping = inode->i_mapping;
|
|
|
|
struct bdi_writeback *old_wb = inode->i_wb;
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
struct bdi_writeback *new_wb = isw->new_wb;
|
2015-05-29 02:50:56 +08:00
|
|
|
struct radix_tree_iter iter;
|
|
|
|
bool switched = false;
|
|
|
|
void **slot;
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* By the time control reaches here, RCU grace period has passed
|
|
|
|
* since I_WB_SWITCH assertion and all wb stat update transactions
|
|
|
|
* between unlocked_inode_to_wb_begin/end() are guaranteed to be
|
|
|
|
* synchronizing against mapping->tree_lock.
|
2015-05-29 02:50:56 +08:00
|
|
|
*
|
|
|
|
* Grabbing old_wb->list_lock, inode->i_lock and mapping->tree_lock
|
|
|
|
* gives us exclusion against all wb related operations on @inode
|
|
|
|
* including IO list manipulations and stat updates.
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
*/
|
2015-05-29 02:50:56 +08:00
|
|
|
if (old_wb < new_wb) {
|
|
|
|
spin_lock(&old_wb->list_lock);
|
|
|
|
spin_lock_nested(&new_wb->list_lock, SINGLE_DEPTH_NESTING);
|
|
|
|
} else {
|
|
|
|
spin_lock(&new_wb->list_lock);
|
|
|
|
spin_lock_nested(&old_wb->list_lock, SINGLE_DEPTH_NESTING);
|
|
|
|
}
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
2015-05-29 02:50:56 +08:00
|
|
|
spin_lock_irq(&mapping->tree_lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Once I_FREEING is visible under i_lock, the eviction path owns
|
|
|
|
* the inode and we shouldn't modify ->i_wb_list.
|
|
|
|
*/
|
|
|
|
if (unlikely(inode->i_state & I_FREEING))
|
|
|
|
goto skip_switch;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Count and transfer stats. Note that PAGECACHE_TAG_DIRTY points
|
|
|
|
* to possibly dirty pages while PAGECACHE_TAG_WRITEBACK points to
|
|
|
|
* pages actually under underwriteback.
|
|
|
|
*/
|
|
|
|
radix_tree_for_each_tagged(slot, &mapping->page_tree, &iter, 0,
|
|
|
|
PAGECACHE_TAG_DIRTY) {
|
|
|
|
struct page *page = radix_tree_deref_slot_protected(slot,
|
|
|
|
&mapping->tree_lock);
|
|
|
|
if (likely(page) && PageDirty(page)) {
|
|
|
|
__dec_wb_stat(old_wb, WB_RECLAIMABLE);
|
|
|
|
__inc_wb_stat(new_wb, WB_RECLAIMABLE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
radix_tree_for_each_tagged(slot, &mapping->page_tree, &iter, 0,
|
|
|
|
PAGECACHE_TAG_WRITEBACK) {
|
|
|
|
struct page *page = radix_tree_deref_slot_protected(slot,
|
|
|
|
&mapping->tree_lock);
|
|
|
|
if (likely(page)) {
|
|
|
|
WARN_ON_ONCE(!PageWriteback(page));
|
|
|
|
__dec_wb_stat(old_wb, WB_WRITEBACK);
|
|
|
|
__inc_wb_stat(new_wb, WB_WRITEBACK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wb_get(new_wb);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Transfer to @new_wb's IO list if necessary. The specific list
|
|
|
|
* @inode was on is ignored and the inode is put on ->b_dirty which
|
|
|
|
* is always correct including from ->b_dirty_time. The transfer
|
|
|
|
* preserves @inode->dirtied_when ordering.
|
|
|
|
*/
|
|
|
|
if (!list_empty(&inode->i_wb_list)) {
|
|
|
|
struct inode *pos;
|
|
|
|
|
|
|
|
inode_wb_list_del_locked(inode, old_wb);
|
|
|
|
inode->i_wb = new_wb;
|
|
|
|
list_for_each_entry(pos, &new_wb->b_dirty, i_wb_list)
|
|
|
|
if (time_after_eq(inode->dirtied_when,
|
|
|
|
pos->dirtied_when))
|
|
|
|
break;
|
|
|
|
inode_wb_list_move_locked(inode, new_wb, pos->i_wb_list.prev);
|
|
|
|
} else {
|
|
|
|
inode->i_wb = new_wb;
|
|
|
|
}
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
|
2015-05-29 02:50:56 +08:00
|
|
|
/* ->i_wb_frn updates may race wbc_detach_inode() but doesn't matter */
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
inode->i_wb_frn_winner = 0;
|
|
|
|
inode->i_wb_frn_avg_time = 0;
|
|
|
|
inode->i_wb_frn_history = 0;
|
2015-05-29 02:50:56 +08:00
|
|
|
switched = true;
|
|
|
|
skip_switch:
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
/*
|
|
|
|
* Paired with load_acquire in unlocked_inode_to_wb_begin() and
|
|
|
|
* ensures that the new wb is visible if they see !I_WB_SWITCH.
|
|
|
|
*/
|
|
|
|
smp_store_release(&inode->i_state, inode->i_state & ~I_WB_SWITCH);
|
|
|
|
|
2015-05-29 02:50:56 +08:00
|
|
|
spin_unlock_irq(&mapping->tree_lock);
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
spin_unlock(&inode->i_lock);
|
2015-05-29 02:50:56 +08:00
|
|
|
spin_unlock(&new_wb->list_lock);
|
|
|
|
spin_unlock(&old_wb->list_lock);
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
|
2015-05-29 02:50:56 +08:00
|
|
|
if (switched) {
|
|
|
|
wb_wakeup(new_wb);
|
|
|
|
wb_put(old_wb);
|
|
|
|
}
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
wb_put(new_wb);
|
2015-05-29 02:50:56 +08:00
|
|
|
|
|
|
|
iput(inode);
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
kfree(isw);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head)
|
|
|
|
{
|
|
|
|
struct inode_switch_wbs_context *isw = container_of(rcu_head,
|
|
|
|
struct inode_switch_wbs_context, rcu_head);
|
|
|
|
|
|
|
|
/* needs to grab bh-unsafe locks, bounce to work item */
|
|
|
|
INIT_WORK(&isw->work, inode_switch_wbs_work_fn);
|
|
|
|
schedule_work(&isw->work);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* inode_switch_wbs - change the wb association of an inode
|
|
|
|
* @inode: target inode
|
|
|
|
* @new_wb_id: ID of the new wb
|
|
|
|
*
|
|
|
|
* Switch @inode's wb association to the wb identified by @new_wb_id. The
|
|
|
|
* switching is performed asynchronously and may fail silently.
|
|
|
|
*/
|
|
|
|
static void inode_switch_wbs(struct inode *inode, int new_wb_id)
|
|
|
|
{
|
|
|
|
struct backing_dev_info *bdi = inode_to_bdi(inode);
|
|
|
|
struct cgroup_subsys_state *memcg_css;
|
|
|
|
struct inode_switch_wbs_context *isw;
|
|
|
|
|
|
|
|
/* noop if seems to be already in progress */
|
|
|
|
if (inode->i_state & I_WB_SWITCH)
|
|
|
|
return;
|
|
|
|
|
|
|
|
isw = kzalloc(sizeof(*isw), GFP_ATOMIC);
|
|
|
|
if (!isw)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* find and pin the new wb */
|
|
|
|
rcu_read_lock();
|
|
|
|
memcg_css = css_from_id(new_wb_id, &memory_cgrp_subsys);
|
|
|
|
if (memcg_css)
|
|
|
|
isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
|
|
|
|
rcu_read_unlock();
|
|
|
|
if (!isw->new_wb)
|
|
|
|
goto out_free;
|
|
|
|
|
|
|
|
/* while holding I_WB_SWITCH, no one else can update the association */
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
if (inode->i_state & (I_WB_SWITCH | I_FREEING) ||
|
|
|
|
inode_to_wb(inode) == isw->new_wb) {
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
goto out_free;
|
|
|
|
}
|
|
|
|
inode->i_state |= I_WB_SWITCH;
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
|
|
|
|
ihold(inode);
|
|
|
|
isw->inode = inode;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In addition to synchronizing among switchers, I_WB_SWITCH tells
|
|
|
|
* the RCU protected stat update paths to grab the mapping's
|
|
|
|
* tree_lock so that stat transfer can synchronize against them.
|
|
|
|
* Let's continue after I_WB_SWITCH is guaranteed to be visible.
|
|
|
|
*/
|
|
|
|
call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
|
|
|
|
return;
|
|
|
|
|
|
|
|
out_free:
|
|
|
|
if (isw->new_wb)
|
|
|
|
wb_put(isw->new_wb);
|
|
|
|
kfree(isw);
|
|
|
|
}
|
|
|
|
|
2015-06-02 22:39:48 +08:00
|
|
|
/**
|
|
|
|
* wbc_attach_and_unlock_inode - associate wbc with target inode and unlock it
|
|
|
|
* @wbc: writeback_control of interest
|
|
|
|
* @inode: target inode
|
|
|
|
*
|
|
|
|
* @inode is locked and about to be written back under the control of @wbc.
|
|
|
|
* Record @inode's writeback context into @wbc and unlock the i_lock. On
|
|
|
|
* writeback completion, wbc_detach_inode() should be called. This is used
|
|
|
|
* to track the cgroup writeback context.
|
|
|
|
*/
|
|
|
|
void wbc_attach_and_unlock_inode(struct writeback_control *wbc,
|
|
|
|
struct inode *inode)
|
|
|
|
{
|
2015-06-17 06:48:30 +08:00
|
|
|
if (!inode_cgwb_enabled(inode)) {
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-02 22:39:48 +08:00
|
|
|
wbc->wb = inode_to_wb(inode);
|
2015-05-29 02:50:51 +08:00
|
|
|
wbc->inode = inode;
|
|
|
|
|
|
|
|
wbc->wb_id = wbc->wb->memcg_css->id;
|
|
|
|
wbc->wb_lcand_id = inode->i_wb_frn_winner;
|
|
|
|
wbc->wb_tcand_id = 0;
|
|
|
|
wbc->wb_bytes = 0;
|
|
|
|
wbc->wb_lcand_bytes = 0;
|
|
|
|
wbc->wb_tcand_bytes = 0;
|
|
|
|
|
2015-06-02 22:39:48 +08:00
|
|
|
wb_get(wbc->wb);
|
|
|
|
spin_unlock(&inode->i_lock);
|
2015-05-29 02:50:57 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* A dying wb indicates that the memcg-blkcg mapping has changed
|
|
|
|
* and a new wb is already serving the memcg. Switch immediately.
|
|
|
|
*/
|
|
|
|
if (unlikely(wb_dying(wbc->wb)))
|
|
|
|
inode_switch_wbs(inode, wbc->wb_id);
|
2015-06-02 22:39:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-05-29 02:50:51 +08:00
|
|
|
* wbc_detach_inode - disassociate wbc from inode and perform foreign detection
|
|
|
|
* @wbc: writeback_control of the just finished writeback
|
2015-06-02 22:39:48 +08:00
|
|
|
*
|
|
|
|
* To be called after a writeback attempt of an inode finishes and undoes
|
|
|
|
* wbc_attach_and_unlock_inode(). Can be called under any context.
|
2015-05-29 02:50:51 +08:00
|
|
|
*
|
|
|
|
* As concurrent write sharing of an inode is expected to be very rare and
|
|
|
|
* memcg only tracks page ownership on first-use basis severely confining
|
|
|
|
* the usefulness of such sharing, cgroup writeback tracks ownership
|
|
|
|
* per-inode. While the support for concurrent write sharing of an inode
|
|
|
|
* is deemed unnecessary, an inode being written to by different cgroups at
|
|
|
|
* different points in time is a lot more common, and, more importantly,
|
|
|
|
* charging only by first-use can too readily lead to grossly incorrect
|
|
|
|
* behaviors (single foreign page can lead to gigabytes of writeback to be
|
|
|
|
* incorrectly attributed).
|
|
|
|
*
|
|
|
|
* To resolve this issue, cgroup writeback detects the majority dirtier of
|
|
|
|
* an inode and transfers the ownership to it. To avoid unnnecessary
|
|
|
|
* oscillation, the detection mechanism keeps track of history and gives
|
|
|
|
* out the switch verdict only if the foreign usage pattern is stable over
|
|
|
|
* a certain amount of time and/or writeback attempts.
|
|
|
|
*
|
|
|
|
* On each writeback attempt, @wbc tries to detect the majority writer
|
|
|
|
* using Boyer-Moore majority vote algorithm. In addition to the byte
|
|
|
|
* count from the majority voting, it also counts the bytes written for the
|
|
|
|
* current wb and the last round's winner wb (max of last round's current
|
|
|
|
* wb, the winner from two rounds ago, and the last round's majority
|
|
|
|
* candidate). Keeping track of the historical winner helps the algorithm
|
|
|
|
* to semi-reliably detect the most active writer even when it's not the
|
|
|
|
* absolute majority.
|
|
|
|
*
|
|
|
|
* Once the winner of the round is determined, whether the winner is
|
|
|
|
* foreign or not and how much IO time the round consumed is recorded in
|
|
|
|
* inode->i_wb_frn_history. If the amount of recorded foreign IO time is
|
|
|
|
* over a certain threshold, the switch verdict is given.
|
2015-06-02 22:39:48 +08:00
|
|
|
*/
|
|
|
|
void wbc_detach_inode(struct writeback_control *wbc)
|
|
|
|
{
|
2015-05-29 02:50:51 +08:00
|
|
|
struct bdi_writeback *wb = wbc->wb;
|
|
|
|
struct inode *inode = wbc->inode;
|
2015-06-17 06:48:30 +08:00
|
|
|
unsigned long avg_time, max_bytes, max_time;
|
|
|
|
u16 history;
|
2015-05-29 02:50:51 +08:00
|
|
|
int max_id;
|
|
|
|
|
2015-06-17 06:48:30 +08:00
|
|
|
if (!wb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
history = inode->i_wb_frn_history;
|
|
|
|
avg_time = inode->i_wb_frn_avg_time;
|
|
|
|
|
2015-05-29 02:50:51 +08:00
|
|
|
/* pick the winner of this round */
|
|
|
|
if (wbc->wb_bytes >= wbc->wb_lcand_bytes &&
|
|
|
|
wbc->wb_bytes >= wbc->wb_tcand_bytes) {
|
|
|
|
max_id = wbc->wb_id;
|
|
|
|
max_bytes = wbc->wb_bytes;
|
|
|
|
} else if (wbc->wb_lcand_bytes >= wbc->wb_tcand_bytes) {
|
|
|
|
max_id = wbc->wb_lcand_id;
|
|
|
|
max_bytes = wbc->wb_lcand_bytes;
|
|
|
|
} else {
|
|
|
|
max_id = wbc->wb_tcand_id;
|
|
|
|
max_bytes = wbc->wb_tcand_bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate the amount of IO time the winner consumed and fold it
|
|
|
|
* into the running average kept per inode. If the consumed IO
|
|
|
|
* time is lower than avag / WB_FRN_TIME_CUT_DIV, ignore it for
|
|
|
|
* deciding whether to switch or not. This is to prevent one-off
|
|
|
|
* small dirtiers from skewing the verdict.
|
|
|
|
*/
|
|
|
|
max_time = DIV_ROUND_UP((max_bytes >> PAGE_SHIFT) << WB_FRN_TIME_SHIFT,
|
|
|
|
wb->avg_write_bandwidth);
|
|
|
|
if (avg_time)
|
|
|
|
avg_time += (max_time >> WB_FRN_TIME_AVG_SHIFT) -
|
|
|
|
(avg_time >> WB_FRN_TIME_AVG_SHIFT);
|
|
|
|
else
|
|
|
|
avg_time = max_time; /* immediate catch up on first run */
|
|
|
|
|
|
|
|
if (max_time >= avg_time / WB_FRN_TIME_CUT_DIV) {
|
|
|
|
int slots;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The switch verdict is reached if foreign wb's consume
|
|
|
|
* more than a certain proportion of IO time in a
|
|
|
|
* WB_FRN_TIME_PERIOD. This is loosely tracked by 16 slot
|
|
|
|
* history mask where each bit represents one sixteenth of
|
|
|
|
* the period. Determine the number of slots to shift into
|
|
|
|
* history from @max_time.
|
|
|
|
*/
|
|
|
|
slots = min(DIV_ROUND_UP(max_time, WB_FRN_HIST_UNIT),
|
|
|
|
(unsigned long)WB_FRN_HIST_MAX_SLOTS);
|
|
|
|
history <<= slots;
|
|
|
|
if (wbc->wb_id != max_id)
|
|
|
|
history |= (1U << slots) - 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Switch if the current wb isn't the consistent winner.
|
|
|
|
* If there are multiple closely competing dirtiers, the
|
|
|
|
* inode may switch across them repeatedly over time, which
|
|
|
|
* is okay. The main goal is avoiding keeping an inode on
|
|
|
|
* the wrong wb for an extended period of time.
|
|
|
|
*/
|
writeback: implement unlocked_inode_to_wb transaction and use it for stat updates
The mechanism for detecting whether an inode should switch its wb
(bdi_writeback) association is now in place. This patch build the
framework for the actual switching.
This patch adds a new inode flag I_WB_SWITCHING, which has two
functions. First, the easy one, it ensures that there's only one
switching in progress for a give inode. Second, it's used as a
mechanism to synchronize wb stat updates.
The two stats, WB_RECLAIMABLE and WB_WRITEBACK, aren't event counters
but track the current number of dirty pages and pages under writeback
respectively. As such, when an inode is moved from one wb to another,
the inode's portion of those stats have to be transferred together;
unfortunately, this is a bit tricky as those stat updates are percpu
operations which are performed without holding any lock in some
places.
This patch solves the problem in a similar way as memcg. Each such
lockless stat updates are wrapped in transaction surrounded by
unlocked_inode_to_wb_begin/end(). During normal operation, they map
to rcu_read_lock/unlock(); however, if I_WB_SWITCHING is asserted,
mapping->tree_lock is grabbed across the transaction.
In turn, the switching path sets I_WB_SWITCHING and waits for a RCU
grace period to pass before actually starting to switch, which
guarantees that all stat update paths are synchronizing against
mapping->tree_lock.
This patch still doesn't implement the actual switching.
v3: Updated on top of the recent cancel_dirty_page() updates.
unlocked_inode_to_wb_begin() now nests inside
mem_cgroup_begin_page_stat() to match the locking order.
v2: The i_wb access transaction will be used for !stat accesses too.
Function names and comments updated accordingly.
s/inode_wb_stat_unlocked_{begin|end}/unlocked_inode_to_wb_{begin|end}/
s/switch_wb/switch_wbs/
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-29 02:50:53 +08:00
|
|
|
if (hweight32(history) > WB_FRN_HIST_THR_SLOTS)
|
|
|
|
inode_switch_wbs(inode, max_id);
|
2015-05-29 02:50:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Multiple instances of this function may race to update the
|
|
|
|
* following fields but we don't mind occassional inaccuracies.
|
|
|
|
*/
|
|
|
|
inode->i_wb_frn_winner = max_id;
|
|
|
|
inode->i_wb_frn_avg_time = min(avg_time, (unsigned long)U16_MAX);
|
|
|
|
inode->i_wb_frn_history = history;
|
|
|
|
|
2015-06-02 22:39:48 +08:00
|
|
|
wb_put(wbc->wb);
|
|
|
|
wbc->wb = NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-29 02:50:51 +08:00
|
|
|
/**
|
|
|
|
* wbc_account_io - account IO issued during writeback
|
|
|
|
* @wbc: writeback_control of the writeback in progress
|
|
|
|
* @page: page being written out
|
|
|
|
* @bytes: number of bytes being written out
|
|
|
|
*
|
|
|
|
* @bytes from @page are about to written out during the writeback
|
|
|
|
* controlled by @wbc. Keep the book for foreign inode detection. See
|
|
|
|
* wbc_detach_inode().
|
|
|
|
*/
|
|
|
|
void wbc_account_io(struct writeback_control *wbc, struct page *page,
|
|
|
|
size_t bytes)
|
|
|
|
{
|
|
|
|
int id;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pageout() path doesn't attach @wbc to the inode being written
|
|
|
|
* out. This is intentional as we don't want the function to block
|
|
|
|
* behind a slow cgroup. Ultimately, we want pageout() to kick off
|
|
|
|
* regular writeback instead of writing things out itself.
|
|
|
|
*/
|
|
|
|
if (!wbc->wb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
id = mem_cgroup_css_from_page(page)->id;
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
if (id == wbc->wb_id) {
|
|
|
|
wbc->wb_bytes += bytes;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id == wbc->wb_lcand_id)
|
|
|
|
wbc->wb_lcand_bytes += bytes;
|
|
|
|
|
|
|
|
/* Boyer-Moore majority vote algorithm */
|
|
|
|
if (!wbc->wb_tcand_bytes)
|
|
|
|
wbc->wb_tcand_id = id;
|
|
|
|
if (id == wbc->wb_tcand_id)
|
|
|
|
wbc->wb_tcand_bytes += bytes;
|
|
|
|
else
|
|
|
|
wbc->wb_tcand_bytes -= min(bytes, wbc->wb_tcand_bytes);
|
|
|
|
}
|
2015-07-24 02:27:09 +08:00
|
|
|
EXPORT_SYMBOL_GPL(wbc_account_io);
|
2015-05-29 02:50:51 +08:00
|
|
|
|
2015-05-23 05:13:44 +08:00
|
|
|
/**
|
|
|
|
* inode_congested - test whether an inode is congested
|
|
|
|
* @inode: inode to test for congestion
|
|
|
|
* @cong_bits: mask of WB_[a]sync_congested bits to test
|
|
|
|
*
|
|
|
|
* Tests whether @inode is congested. @cong_bits is the mask of congestion
|
|
|
|
* bits to test and the return value is the mask of set bits.
|
|
|
|
*
|
|
|
|
* If cgroup writeback is enabled for @inode, the congestion state is
|
|
|
|
* determined by whether the cgwb (cgroup bdi_writeback) for the blkcg
|
|
|
|
* associated with @inode is congested; otherwise, the root wb's congestion
|
|
|
|
* state is used.
|
|
|
|
*/
|
|
|
|
int inode_congested(struct inode *inode, int cong_bits)
|
|
|
|
{
|
2015-05-29 02:50:54 +08:00
|
|
|
/*
|
|
|
|
* Once set, ->i_wb never becomes NULL while the inode is alive.
|
|
|
|
* Start transaction iff ->i_wb is visible.
|
|
|
|
*/
|
2015-05-29 02:50:55 +08:00
|
|
|
if (inode && inode_to_wb_is_valid(inode)) {
|
2015-05-29 02:50:54 +08:00
|
|
|
struct bdi_writeback *wb;
|
|
|
|
bool locked, congested;
|
|
|
|
|
|
|
|
wb = unlocked_inode_to_wb_begin(inode, &locked);
|
|
|
|
congested = wb_congested(wb, cong_bits);
|
|
|
|
unlocked_inode_to_wb_end(inode, locked);
|
|
|
|
return congested;
|
2015-05-23 05:13:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return wb_congested(&inode_to_bdi(inode)->wb, cong_bits);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(inode_congested);
|
|
|
|
|
2015-05-23 05:13:55 +08:00
|
|
|
/**
|
|
|
|
* wb_split_bdi_pages - split nr_pages to write according to bandwidth
|
|
|
|
* @wb: target bdi_writeback to split @nr_pages to
|
|
|
|
* @nr_pages: number of pages to write for the whole bdi
|
|
|
|
*
|
|
|
|
* Split @wb's portion of @nr_pages according to @wb's write bandwidth in
|
|
|
|
* relation to the total write bandwidth of all wb's w/ dirty inodes on
|
|
|
|
* @wb->bdi.
|
|
|
|
*/
|
|
|
|
static long wb_split_bdi_pages(struct bdi_writeback *wb, long nr_pages)
|
|
|
|
{
|
|
|
|
unsigned long this_bw = wb->avg_write_bandwidth;
|
|
|
|
unsigned long tot_bw = atomic_long_read(&wb->bdi->tot_write_bandwidth);
|
|
|
|
|
|
|
|
if (nr_pages == LONG_MAX)
|
|
|
|
return LONG_MAX;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This may be called on clean wb's and proportional distribution
|
|
|
|
* may not make sense, just use the original @nr_pages in those
|
|
|
|
* cases. In general, we wanna err on the side of writing more.
|
|
|
|
*/
|
|
|
|
if (!tot_bw || this_bw >= tot_bw)
|
|
|
|
return nr_pages;
|
|
|
|
else
|
|
|
|
return DIV_ROUND_UP_ULL((u64)nr_pages * this_bw, tot_bw);
|
|
|
|
}
|
|
|
|
|
2015-05-23 05:14:01 +08:00
|
|
|
/**
|
|
|
|
* bdi_split_work_to_wbs - split a wb_writeback_work to all wb's of a bdi
|
|
|
|
* @bdi: target backing_dev_info
|
|
|
|
* @base_work: wb_writeback_work to issue
|
|
|
|
* @skip_if_busy: skip wb's which already have writeback in progress
|
|
|
|
*
|
|
|
|
* Split and issue @base_work to all wb's (bdi_writeback's) of @bdi which
|
|
|
|
* have dirty inodes. If @base_work->nr_page isn't %LONG_MAX, it's
|
|
|
|
* distributed to the busy wbs according to each wb's proportion in the
|
|
|
|
* total active write bandwidth of @bdi.
|
|
|
|
*/
|
|
|
|
static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
|
|
|
|
struct wb_writeback_work *base_work,
|
|
|
|
bool skip_if_busy)
|
|
|
|
{
|
2015-08-19 05:54:52 +08:00
|
|
|
int next_memcg_id = 0;
|
2015-05-23 05:14:01 +08:00
|
|
|
struct bdi_writeback *wb;
|
|
|
|
struct wb_iter iter;
|
|
|
|
|
|
|
|
might_sleep();
|
|
|
|
|
|
|
|
if (!bdi_has_dirty_io(bdi))
|
|
|
|
return;
|
|
|
|
restart:
|
|
|
|
rcu_read_lock();
|
2015-08-19 05:54:52 +08:00
|
|
|
bdi_for_each_wb(wb, bdi, &iter, next_memcg_id) {
|
2015-08-19 05:54:53 +08:00
|
|
|
DEFINE_WB_COMPLETION_ONSTACK(fallback_work_done);
|
|
|
|
struct wb_writeback_work fallback_work;
|
|
|
|
struct wb_writeback_work *work;
|
|
|
|
long nr_pages;
|
|
|
|
|
2015-05-23 05:14:01 +08:00
|
|
|
if (!wb_has_dirty_io(wb) ||
|
|
|
|
(skip_if_busy && writeback_in_progress(wb)))
|
|
|
|
continue;
|
|
|
|
|
2015-08-19 05:54:53 +08:00
|
|
|
nr_pages = wb_split_bdi_pages(wb, base_work->nr_pages);
|
|
|
|
|
|
|
|
work = kmalloc(sizeof(*work), GFP_ATOMIC);
|
|
|
|
if (work) {
|
|
|
|
*work = *base_work;
|
|
|
|
work->nr_pages = nr_pages;
|
|
|
|
work->auto_free = 1;
|
|
|
|
wb_queue_work(wb, work);
|
|
|
|
continue;
|
2015-05-23 05:14:01 +08:00
|
|
|
}
|
2015-08-19 05:54:53 +08:00
|
|
|
|
|
|
|
/* alloc failed, execute synchronously using on-stack fallback */
|
|
|
|
work = &fallback_work;
|
|
|
|
*work = *base_work;
|
|
|
|
work->nr_pages = nr_pages;
|
|
|
|
work->auto_free = 0;
|
|
|
|
work->done = &fallback_work_done;
|
|
|
|
|
|
|
|
wb_queue_work(wb, work);
|
|
|
|
|
|
|
|
next_memcg_id = wb->memcg_css->id + 1;
|
|
|
|
rcu_read_unlock();
|
|
|
|
wb_wait_for_completion(bdi, &fallback_work_done);
|
|
|
|
goto restart;
|
2015-05-23 05:14:01 +08:00
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
}
|
|
|
|
|
2015-05-23 05:13:55 +08:00
|
|
|
#else /* CONFIG_CGROUP_WRITEBACK */
|
|
|
|
|
2015-05-29 02:50:52 +08:00
|
|
|
static struct bdi_writeback *
|
|
|
|
locked_inode_to_wb_and_lock_list(struct inode *inode)
|
|
|
|
__releases(&inode->i_lock)
|
|
|
|
__acquires(&wb->list_lock)
|
|
|
|
{
|
|
|
|
struct bdi_writeback *wb = inode_to_wb(inode);
|
|
|
|
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
spin_lock(&wb->list_lock);
|
|
|
|
return wb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bdi_writeback *inode_to_wb_and_lock_list(struct inode *inode)
|
|
|
|
__acquires(&wb->list_lock)
|
|
|
|
{
|
|
|
|
struct bdi_writeback *wb = inode_to_wb(inode);
|
|
|
|
|
|
|
|
spin_lock(&wb->list_lock);
|
|
|
|
return wb;
|
|
|
|
}
|
|
|
|
|
2015-05-23 05:13:55 +08:00
|
|
|
static long wb_split_bdi_pages(struct bdi_writeback *wb, long nr_pages)
|
|
|
|
{
|
|
|
|
return nr_pages;
|
|
|
|
}
|
|
|
|
|
2015-05-23 05:14:01 +08:00
|
|
|
static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
|
|
|
|
struct wb_writeback_work *base_work,
|
|
|
|
bool skip_if_busy)
|
|
|
|
{
|
|
|
|
might_sleep();
|
|
|
|
|
|
|
|
if (bdi_has_dirty_io(bdi) &&
|
|
|
|
(!skip_if_busy || !writeback_in_progress(&bdi->wb))) {
|
|
|
|
base_work->auto_free = 0;
|
|
|
|
wb_queue_work(&bdi->wb, base_work);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-23 05:13:44 +08:00
|
|
|
#endif /* CONFIG_CGROUP_WRITEBACK */
|
|
|
|
|
2015-05-23 05:13:51 +08:00
|
|
|
void wb_start_writeback(struct bdi_writeback *wb, long nr_pages,
|
|
|
|
bool range_cyclic, enum wb_reason reason)
|
2009-09-16 21:13:54 +08:00
|
|
|
{
|
2015-05-23 05:13:51 +08:00
|
|
|
struct wb_writeback_work *work;
|
|
|
|
|
|
|
|
if (!wb_has_dirty_io(wb))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is WB_SYNC_NONE writeback, so if allocation fails just
|
|
|
|
* wakeup the thread for old dirty data writeback
|
|
|
|
*/
|
|
|
|
work = kzalloc(sizeof(*work), GFP_ATOMIC);
|
|
|
|
if (!work) {
|
|
|
|
trace_writeback_nowork(wb->bdi);
|
|
|
|
wb_wakeup(wb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
work->sync_mode = WB_SYNC_NONE;
|
|
|
|
work->nr_pages = nr_pages;
|
|
|
|
work->range_cyclic = range_cyclic;
|
|
|
|
work->reason = reason;
|
2015-05-23 05:13:57 +08:00
|
|
|
work->auto_free = 1;
|
2015-05-23 05:13:51 +08:00
|
|
|
|
|
|
|
wb_queue_work(wb, work);
|
2010-06-09 00:15:15 +08:00
|
|
|
}
|
2009-09-23 20:33:40 +08:00
|
|
|
|
2010-06-09 00:15:15 +08:00
|
|
|
/**
|
2015-05-23 05:13:54 +08:00
|
|
|
* wb_start_background_writeback - start background writeback
|
|
|
|
* @wb: bdi_writback to write from
|
2010-06-09 00:15:15 +08:00
|
|
|
*
|
|
|
|
* Description:
|
2011-01-14 07:45:44 +08:00
|
|
|
* This makes sure WB_SYNC_NONE background writeback happens. When
|
2015-05-23 05:13:54 +08:00
|
|
|
* this function returns, it is only guaranteed that for given wb
|
2011-01-14 07:45:44 +08:00
|
|
|
* some IO is happening if we are over background dirty threshold.
|
|
|
|
* Caller need not hold sb s_umount semaphore.
|
2010-06-09 00:15:15 +08:00
|
|
|
*/
|
2015-05-23 05:13:54 +08:00
|
|
|
void wb_start_background_writeback(struct bdi_writeback *wb)
|
2010-06-09 00:15:15 +08:00
|
|
|
{
|
2011-01-14 07:45:44 +08:00
|
|
|
/*
|
|
|
|
* We just wake up the flusher thread. It will perform background
|
|
|
|
* writeback as soon as there is no other work to do.
|
|
|
|
*/
|
2015-05-23 05:13:54 +08:00
|
|
|
trace_writeback_wake_background(wb->bdi);
|
|
|
|
wb_wakeup(wb);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2011-03-22 19:23:41 +08:00
|
|
|
/*
|
|
|
|
* Remove the inode from the writeback list it is on.
|
|
|
|
*/
|
|
|
|
void inode_wb_list_del(struct inode *inode)
|
|
|
|
{
|
2015-05-29 02:50:52 +08:00
|
|
|
struct bdi_writeback *wb;
|
2011-04-22 08:19:44 +08:00
|
|
|
|
2015-05-29 02:50:52 +08:00
|
|
|
wb = inode_to_wb_and_lock_list(inode);
|
2015-05-23 05:13:45 +08:00
|
|
|
inode_wb_list_del_locked(inode, wb);
|
2015-05-23 05:13:37 +08:00
|
|
|
spin_unlock(&wb->list_lock);
|
2011-03-22 19:23:41 +08:00
|
|
|
}
|
|
|
|
|
2007-10-17 14:30:32 +08:00
|
|
|
/*
|
|
|
|
* Redirty an inode: set its when-it-was dirtied timestamp and move it to the
|
|
|
|
* furthest end of its superblock's dirty-inode list.
|
|
|
|
*
|
|
|
|
* Before stamping the inode's ->dirtied_when, we check to see whether it is
|
2009-09-02 15:19:46 +08:00
|
|
|
* already the most-recently-dirtied inode on the b_dirty list. If that is
|
2007-10-17 14:30:32 +08:00
|
|
|
* the case then the inode must have been redirtied while it was being written
|
|
|
|
* out and we don't reset its dirtied_when.
|
|
|
|
*/
|
2011-04-22 08:19:44 +08:00
|
|
|
static void redirty_tail(struct inode *inode, struct bdi_writeback *wb)
|
2007-10-17 14:30:32 +08:00
|
|
|
{
|
2009-09-09 15:08:54 +08:00
|
|
|
if (!list_empty(&wb->b_dirty)) {
|
2009-09-02 15:19:46 +08:00
|
|
|
struct inode *tail;
|
2007-10-17 14:30:32 +08:00
|
|
|
|
2010-10-21 08:49:30 +08:00
|
|
|
tail = wb_inode(wb->b_dirty.next);
|
2009-09-02 15:19:46 +08:00
|
|
|
if (time_before(inode->dirtied_when, tail->dirtied_when))
|
2007-10-17 14:30:32 +08:00
|
|
|
inode->dirtied_when = jiffies;
|
|
|
|
}
|
2015-05-23 05:13:45 +08:00
|
|
|
inode_wb_list_move_locked(inode, wb, &wb->b_dirty);
|
2007-10-17 14:30:32 +08:00
|
|
|
}
|
|
|
|
|
2007-10-17 14:30:34 +08:00
|
|
|
/*
|
2009-09-02 15:19:46 +08:00
|
|
|
* requeue inode for re-scanning after bdi->b_io list is exhausted.
|
2007-10-17 14:30:34 +08:00
|
|
|
*/
|
2011-04-22 08:19:44 +08:00
|
|
|
static void requeue_io(struct inode *inode, struct bdi_writeback *wb)
|
2007-10-17 14:30:34 +08:00
|
|
|
{
|
2015-05-23 05:13:45 +08:00
|
|
|
inode_wb_list_move_locked(inode, wb, &wb->b_more_io);
|
2007-10-17 14:30:34 +08:00
|
|
|
}
|
|
|
|
|
2007-10-17 14:30:44 +08:00
|
|
|
static void inode_sync_complete(struct inode *inode)
|
|
|
|
{
|
2012-05-03 20:47:55 +08:00
|
|
|
inode->i_state &= ~I_SYNC;
|
2012-11-27 08:29:51 +08:00
|
|
|
/* If inode is clean an unused, put it into LRU now... */
|
|
|
|
inode_add_lru(inode);
|
2012-05-03 20:47:55 +08:00
|
|
|
/* Waiters must see I_SYNC cleared before being woken up */
|
2007-10-17 14:30:44 +08:00
|
|
|
smp_mb();
|
|
|
|
wake_up_bit(&inode->i_state, __I_SYNC);
|
|
|
|
}
|
|
|
|
|
2009-04-03 07:56:37 +08:00
|
|
|
static bool inode_dirtied_after(struct inode *inode, unsigned long t)
|
|
|
|
{
|
|
|
|
bool ret = time_after(inode->dirtied_when, t);
|
|
|
|
#ifndef CONFIG_64BIT
|
|
|
|
/*
|
|
|
|
* For inodes being constantly redirtied, dirtied_when can get stuck.
|
|
|
|
* It _appears_ to be in the future, but is actually in distant past.
|
|
|
|
* This test is necessary to prevent such wrapped-around relative times
|
2009-09-24 01:37:09 +08:00
|
|
|
* from permanently stopping the whole bdi writeback.
|
2009-04-03 07:56:37 +08:00
|
|
|
*/
|
|
|
|
ret = ret && time_before_eq(inode->dirtied_when, jiffies);
|
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-02 13:37:00 +08:00
|
|
|
#define EXPIRE_DIRTY_ATIME 0x0001
|
|
|
|
|
2007-10-17 14:30:39 +08:00
|
|
|
/*
|
2012-09-11 08:28:18 +08:00
|
|
|
* Move expired (dirtied before work->older_than_this) dirty inodes from
|
2012-03-09 23:26:22 +08:00
|
|
|
* @delaying_queue to @dispatch_queue.
|
2007-10-17 14:30:39 +08:00
|
|
|
*/
|
2011-04-24 02:27:27 +08:00
|
|
|
static int move_expired_inodes(struct list_head *delaying_queue,
|
2007-10-17 14:30:39 +08:00
|
|
|
struct list_head *dispatch_queue,
|
2015-02-02 13:37:00 +08:00
|
|
|
int flags,
|
2011-10-08 11:51:56 +08:00
|
|
|
struct wb_writeback_work *work)
|
2007-10-17 14:30:39 +08:00
|
|
|
{
|
2015-02-02 13:37:00 +08:00
|
|
|
unsigned long *older_than_this = NULL;
|
|
|
|
unsigned long expire_time;
|
2009-09-24 20:42:33 +08:00
|
|
|
LIST_HEAD(tmp);
|
|
|
|
struct list_head *pos, *node;
|
2009-09-24 21:12:57 +08:00
|
|
|
struct super_block *sb = NULL;
|
2009-09-24 20:42:33 +08:00
|
|
|
struct inode *inode;
|
2009-09-24 21:12:57 +08:00
|
|
|
int do_sb_sort = 0;
|
2011-04-24 02:27:27 +08:00
|
|
|
int moved = 0;
|
2009-09-24 20:42:33 +08:00
|
|
|
|
2015-02-02 13:37:00 +08:00
|
|
|
if ((flags & EXPIRE_DIRTY_ATIME) == 0)
|
|
|
|
older_than_this = work->older_than_this;
|
2015-03-18 00:23:19 +08:00
|
|
|
else if (!work->for_sync) {
|
|
|
|
expire_time = jiffies - (dirtytime_expire_interval * HZ);
|
2015-02-02 13:37:00 +08:00
|
|
|
older_than_this = &expire_time;
|
|
|
|
}
|
2007-10-17 14:30:39 +08:00
|
|
|
while (!list_empty(delaying_queue)) {
|
2010-10-21 08:49:30 +08:00
|
|
|
inode = wb_inode(delaying_queue->prev);
|
2015-02-02 13:37:00 +08:00
|
|
|
if (older_than_this &&
|
|
|
|
inode_dirtied_after(inode, *older_than_this))
|
2007-10-17 14:30:39 +08:00
|
|
|
break;
|
2013-07-09 22:36:45 +08:00
|
|
|
list_move(&inode->i_wb_list, &tmp);
|
|
|
|
moved++;
|
2015-02-02 13:37:00 +08:00
|
|
|
if (flags & EXPIRE_DIRTY_ATIME)
|
|
|
|
set_bit(__I_DIRTY_TIME_EXPIRED, &inode->i_state);
|
2013-07-09 22:36:45 +08:00
|
|
|
if (sb_is_blkdev_sb(inode->i_sb))
|
|
|
|
continue;
|
2009-09-24 21:12:57 +08:00
|
|
|
if (sb && sb != inode->i_sb)
|
|
|
|
do_sb_sort = 1;
|
|
|
|
sb = inode->i_sb;
|
2009-09-24 20:42:33 +08:00
|
|
|
}
|
|
|
|
|
2009-09-24 21:12:57 +08:00
|
|
|
/* just one sb in list, splice to dispatch_queue and we're done */
|
|
|
|
if (!do_sb_sort) {
|
|
|
|
list_splice(&tmp, dispatch_queue);
|
2011-04-24 02:27:27 +08:00
|
|
|
goto out;
|
2009-09-24 21:12:57 +08:00
|
|
|
}
|
|
|
|
|
2009-09-24 20:42:33 +08:00
|
|
|
/* Move inodes from one superblock together */
|
|
|
|
while (!list_empty(&tmp)) {
|
2010-10-21 08:49:30 +08:00
|
|
|
sb = wb_inode(tmp.prev)->i_sb;
|
2009-09-24 20:42:33 +08:00
|
|
|
list_for_each_prev_safe(pos, node, &tmp) {
|
2010-10-21 08:49:30 +08:00
|
|
|
inode = wb_inode(pos);
|
2009-09-24 20:42:33 +08:00
|
|
|
if (inode->i_sb == sb)
|
2010-10-21 08:49:30 +08:00
|
|
|
list_move(&inode->i_wb_list, dispatch_queue);
|
2009-09-24 20:42:33 +08:00
|
|
|
}
|
2007-10-17 14:30:39 +08:00
|
|
|
}
|
2011-04-24 02:27:27 +08:00
|
|
|
out:
|
|
|
|
return moved;
|
2007-10-17 14:30:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Queue all expired dirty inodes for io, eldest first.
|
2010-08-12 05:17:42 +08:00
|
|
|
* Before
|
|
|
|
* newly dirtied b_dirty b_io b_more_io
|
|
|
|
* =============> gf edc BA
|
|
|
|
* After
|
|
|
|
* newly dirtied b_dirty b_io b_more_io
|
|
|
|
* =============> g fBAedc
|
|
|
|
* |
|
|
|
|
* +--> dequeue for IO
|
2007-10-17 14:30:39 +08:00
|
|
|
*/
|
2011-10-08 11:51:56 +08:00
|
|
|
static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work)
|
2009-09-02 15:19:46 +08:00
|
|
|
{
|
2011-04-24 02:27:27 +08:00
|
|
|
int moved;
|
2015-02-02 13:37:00 +08:00
|
|
|
|
2011-04-22 08:19:44 +08:00
|
|
|
assert_spin_locked(&wb->list_lock);
|
2010-08-12 05:17:42 +08:00
|
|
|
list_splice_init(&wb->b_more_io, &wb->b_io);
|
2015-02-02 13:37:00 +08:00
|
|
|
moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, 0, work);
|
|
|
|
moved += move_expired_inodes(&wb->b_dirty_time, &wb->b_io,
|
|
|
|
EXPIRE_DIRTY_ATIME, work);
|
2015-05-23 05:13:45 +08:00
|
|
|
if (moved)
|
|
|
|
wb_io_lists_populated(wb);
|
2011-10-08 11:51:56 +08:00
|
|
|
trace_writeback_queue_io(wb, work, moved);
|
2009-09-02 15:19:46 +08:00
|
|
|
}
|
|
|
|
|
2010-03-05 16:21:37 +08:00
|
|
|
static int write_inode(struct inode *inode, struct writeback_control *wbc)
|
2007-10-17 14:30:39 +08:00
|
|
|
{
|
2013-01-12 05:06:37 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode)) {
|
|
|
|
trace_writeback_write_inode_start(inode, wbc);
|
|
|
|
ret = inode->i_sb->s_op->write_inode(inode, wbc);
|
|
|
|
trace_writeback_write_inode(inode, wbc);
|
|
|
|
return ret;
|
|
|
|
}
|
2009-09-09 15:08:54 +08:00
|
|
|
return 0;
|
2007-10-17 14:30:39 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2012-05-03 20:48:03 +08:00
|
|
|
* Wait for writeback on an inode to complete. Called with i_lock held.
|
|
|
|
* Caller must make sure inode cannot go away when we drop i_lock.
|
2009-06-08 19:35:40 +08:00
|
|
|
*/
|
2012-05-03 20:48:03 +08:00
|
|
|
static void __inode_wait_for_writeback(struct inode *inode)
|
|
|
|
__releases(inode->i_lock)
|
|
|
|
__acquires(inode->i_lock)
|
2009-06-08 19:35:40 +08:00
|
|
|
{
|
|
|
|
DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC);
|
|
|
|
wait_queue_head_t *wqh;
|
|
|
|
|
|
|
|
wqh = bit_waitqueue(&inode->i_state, __I_SYNC);
|
2011-03-22 19:23:36 +08:00
|
|
|
while (inode->i_state & I_SYNC) {
|
|
|
|
spin_unlock(&inode->i_lock);
|
sched: Remove proliferation of wait_on_bit() action functions
The current "wait_on_bit" interface requires an 'action'
function to be provided which does the actual waiting.
There are over 20 such functions, many of them identical.
Most cases can be satisfied by one of just two functions, one
which uses io_schedule() and one which just uses schedule().
So:
Rename wait_on_bit and wait_on_bit_lock to
wait_on_bit_action and wait_on_bit_lock_action
to make it explicit that they need an action function.
Introduce new wait_on_bit{,_lock} and wait_on_bit{,_lock}_io
which are *not* given an action function but implicitly use
a standard one.
The decision to error-out if a signal is pending is now made
based on the 'mode' argument rather than being encoded in the action
function.
All instances of the old wait_on_bit and wait_on_bit_lock which
can use the new version have been changed accordingly and their
action functions have been discarded.
wait_on_bit{_lock} does not return any specific error code in the
event of a signal so the caller must check for non-zero and
interpolate their own error code as appropriate.
The wait_on_bit() call in __fscache_wait_on_invalidate() was
ambiguous as it specified TASK_UNINTERRUPTIBLE but used
fscache_wait_bit_interruptible as an action function.
David Howells confirms this should be uniformly
"uninterruptible"
The main remaining user of wait_on_bit{,_lock}_action is NFS
which needs to use a freezer-aware schedule() call.
A comment in fs/gfs2/glock.c notes that having multiple 'action'
functions is useful as they display differently in the 'wchan'
field of 'ps'. (and /proc/$PID/wchan).
As the new bit_wait{,_io} functions are tagged "__sched", they
will not show up at all, but something higher in the stack. So
the distinction will still be visible, only with different
function names (gds2_glock_wait versus gfs2_glock_dq_wait in the
gfs2/glock.c case).
Since first version of this patch (against 3.15) two new action
functions appeared, on in NFS and one in CIFS. CIFS also now
uses an action function that makes the same freezer aware
schedule call as NFS.
Signed-off-by: NeilBrown <neilb@suse.de>
Acked-by: David Howells <dhowells@redhat.com> (fscache, keys)
Acked-by: Steven Whitehouse <swhiteho@redhat.com> (gfs2)
Acked-by: Peter Zijlstra <peterz@infradead.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Steve French <sfrench@samba.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/20140707051603.28027.72349.stgit@notabene.brown
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2014-07-07 13:16:04 +08:00
|
|
|
__wait_on_bit(wqh, &wq, bit_wait,
|
|
|
|
TASK_UNINTERRUPTIBLE);
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
2010-05-25 05:32:38 +08:00
|
|
|
}
|
2009-06-08 19:35:40 +08:00
|
|
|
}
|
|
|
|
|
2012-05-03 20:48:03 +08:00
|
|
|
/*
|
|
|
|
* Wait for writeback on an inode to complete. Caller must have inode pinned.
|
|
|
|
*/
|
|
|
|
void inode_wait_for_writeback(struct inode *inode)
|
|
|
|
{
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
__inode_wait_for_writeback(inode);
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sleep until I_SYNC is cleared. This function must be called with i_lock
|
|
|
|
* held and drops it. It is aimed for callers not holding any inode reference
|
|
|
|
* so once i_lock is dropped, inode can go away.
|
|
|
|
*/
|
|
|
|
static void inode_sleep_on_writeback(struct inode *inode)
|
|
|
|
__releases(inode->i_lock)
|
|
|
|
{
|
|
|
|
DEFINE_WAIT(wait);
|
|
|
|
wait_queue_head_t *wqh = bit_waitqueue(&inode->i_state, __I_SYNC);
|
|
|
|
int sleep;
|
|
|
|
|
|
|
|
prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
|
|
|
|
sleep = inode->i_state & I_SYNC;
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
if (sleep)
|
|
|
|
schedule();
|
|
|
|
finish_wait(wqh, &wait);
|
|
|
|
}
|
|
|
|
|
2012-05-03 20:47:58 +08:00
|
|
|
/*
|
|
|
|
* Find proper writeback list for the inode depending on its current state and
|
|
|
|
* possibly also change of its state while we were doing writeback. Here we
|
|
|
|
* handle things such as livelock prevention or fairness of writeback among
|
|
|
|
* inodes. This function can be called only by flusher thread - noone else
|
|
|
|
* processes all inodes in writeback lists and requeueing inodes behind flusher
|
|
|
|
* thread's back can have unexpected consequences.
|
|
|
|
*/
|
|
|
|
static void requeue_inode(struct inode *inode, struct bdi_writeback *wb,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
|
|
|
if (inode->i_state & I_FREEING)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sync livelock prevention. Each inode is tagged and synced in one
|
|
|
|
* shot. If still dirty, it will be redirty_tail()'ed below. Update
|
|
|
|
* the dirty time to prevent enqueue and sync it again.
|
|
|
|
*/
|
|
|
|
if ((inode->i_state & I_DIRTY) &&
|
|
|
|
(wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages))
|
|
|
|
inode->dirtied_when = jiffies;
|
|
|
|
|
2012-05-03 20:48:00 +08:00
|
|
|
if (wbc->pages_skipped) {
|
|
|
|
/*
|
|
|
|
* writeback is not making progress due to locked
|
|
|
|
* buffers. Skip this inode for now.
|
|
|
|
*/
|
|
|
|
redirty_tail(inode, wb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-03 20:47:58 +08:00
|
|
|
if (mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) {
|
|
|
|
/*
|
|
|
|
* We didn't write back all the pages. nfs_writepages()
|
|
|
|
* sometimes bales out without doing anything.
|
|
|
|
*/
|
|
|
|
if (wbc->nr_to_write <= 0) {
|
|
|
|
/* Slice used up. Queue for next turn. */
|
|
|
|
requeue_io(inode, wb);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Writeback blocked by something other than
|
|
|
|
* congestion. Delay the inode for some time to
|
|
|
|
* avoid spinning on the CPU (100% iowait)
|
|
|
|
* retrying writeback of the dirty page/inode
|
|
|
|
* that cannot be performed immediately.
|
|
|
|
*/
|
|
|
|
redirty_tail(inode, wb);
|
|
|
|
}
|
|
|
|
} else if (inode->i_state & I_DIRTY) {
|
|
|
|
/*
|
|
|
|
* Filesystems can dirty the inode during writeback operations,
|
|
|
|
* such as delayed allocation during submission or metadata
|
|
|
|
* updates after data IO completion.
|
|
|
|
*/
|
|
|
|
redirty_tail(inode, wb);
|
2015-02-02 13:37:00 +08:00
|
|
|
} else if (inode->i_state & I_DIRTY_TIME) {
|
2015-03-18 00:23:19 +08:00
|
|
|
inode->dirtied_when = jiffies;
|
2015-05-23 05:13:45 +08:00
|
|
|
inode_wb_list_move_locked(inode, wb, &wb->b_dirty_time);
|
2012-05-03 20:47:58 +08:00
|
|
|
} else {
|
|
|
|
/* The inode is clean. Remove from writeback lists. */
|
2015-05-23 05:13:45 +08:00
|
|
|
inode_wb_list_del_locked(inode, wb);
|
2012-05-03 20:47:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-08 19:35:40 +08:00
|
|
|
/*
|
2012-05-03 20:48:00 +08:00
|
|
|
* Write out an inode and its dirty pages. Do not update the writeback list
|
|
|
|
* linkage. That is left to the caller. The caller is also responsible for
|
|
|
|
* setting I_SYNC flag and calling inode_sync_complete() to clear it.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
static int
|
2012-10-09 07:33:45 +08:00
|
|
|
__writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct address_space *mapping = inode->i_mapping;
|
2010-12-02 07:33:37 +08:00
|
|
|
long nr_to_write = wbc->nr_to_write;
|
2009-06-08 19:35:40 +08:00
|
|
|
unsigned dirty;
|
2005-04-17 06:20:36 +08:00
|
|
|
int ret;
|
|
|
|
|
2012-05-03 20:48:00 +08:00
|
|
|
WARN_ON(!(inode->i_state & I_SYNC));
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2013-01-12 05:06:37 +08:00
|
|
|
trace_writeback_single_inode_start(inode, wbc, nr_to_write);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
ret = do_writepages(mapping, wbc);
|
|
|
|
|
2010-03-05 16:21:21 +08:00
|
|
|
/*
|
|
|
|
* Make sure to wait on the data before writing out the metadata.
|
|
|
|
* This is important for filesystems that modify metadata on data
|
2013-07-02 20:38:35 +08:00
|
|
|
* I/O completion. We don't do it for sync(2) writeback because it has a
|
|
|
|
* separate, external IO completion path and ->sync_fs for guaranteeing
|
|
|
|
* inode metadata is written back correctly.
|
2010-03-05 16:21:21 +08:00
|
|
|
*/
|
2013-07-02 20:38:35 +08:00
|
|
|
if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync) {
|
2010-03-05 16:21:21 +08:00
|
|
|
int err = filemap_fdatawait(mapping);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ret == 0)
|
|
|
|
ret = err;
|
|
|
|
}
|
|
|
|
|
2010-05-07 17:35:44 +08:00
|
|
|
/*
|
|
|
|
* Some filesystems may redirty the inode during the writeback
|
|
|
|
* due to delalloc, clear dirty metadata flags right before
|
|
|
|
* write_inode()
|
|
|
|
*/
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
2014-10-25 03:38:21 +08:00
|
|
|
|
2010-05-07 17:35:44 +08:00
|
|
|
dirty = inode->i_state & I_DIRTY;
|
2015-03-18 00:23:19 +08:00
|
|
|
if (inode->i_state & I_DIRTY_TIME) {
|
|
|
|
if ((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) ||
|
|
|
|
unlikely(inode->i_state & I_DIRTY_TIME_EXPIRED) ||
|
|
|
|
unlikely(time_after(jiffies,
|
|
|
|
(inode->dirtied_time_when +
|
|
|
|
dirtytime_expire_interval * HZ)))) {
|
|
|
|
dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED;
|
|
|
|
trace_writeback_lazytime(inode);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
inode->i_state &= ~I_DIRTY_TIME_EXPIRED;
|
2015-02-02 13:37:00 +08:00
|
|
|
inode->i_state &= ~dirty;
|
2014-10-25 03:38:21 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Paired with smp_mb() in __mark_inode_dirty(). This allows
|
|
|
|
* __mark_inode_dirty() to test i_state without grabbing i_lock -
|
|
|
|
* either they see the I_DIRTY bits cleared or we see the dirtied
|
|
|
|
* inode.
|
|
|
|
*
|
|
|
|
* I_DIRTY_PAGES is always cleared together above even if @mapping
|
|
|
|
* still has dirty pages. The flag is reinstated after smp_mb() if
|
|
|
|
* necessary. This guarantees that either __mark_inode_dirty()
|
|
|
|
* sees clear I_DIRTY_PAGES or we see PAGECACHE_TAG_DIRTY.
|
|
|
|
*/
|
|
|
|
smp_mb();
|
|
|
|
|
|
|
|
if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
|
|
|
|
inode->i_state |= I_DIRTY_PAGES;
|
|
|
|
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_unlock(&inode->i_lock);
|
2014-10-25 03:38:21 +08:00
|
|
|
|
2015-02-02 13:37:00 +08:00
|
|
|
if (dirty & I_DIRTY_TIME)
|
|
|
|
mark_inode_dirty_sync(inode);
|
2010-03-05 16:21:21 +08:00
|
|
|
/* Don't write the inode if only I_DIRTY_PAGES was set */
|
2015-02-02 13:37:00 +08:00
|
|
|
if (dirty & ~I_DIRTY_PAGES) {
|
2010-03-05 16:21:37 +08:00
|
|
|
int err = write_inode(inode, wbc);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ret == 0)
|
|
|
|
ret = err;
|
|
|
|
}
|
2012-05-03 20:48:00 +08:00
|
|
|
trace_writeback_single_inode(inode, wbc, nr_to_write);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write out an inode's dirty pages. Either the caller has an active reference
|
|
|
|
* on the inode or the inode has I_WILL_FREE set.
|
|
|
|
*
|
|
|
|
* This function is designed to be called for writing back one inode which
|
|
|
|
* we go e.g. from filesystem. Flusher thread uses __writeback_single_inode()
|
|
|
|
* and does more profound writeback list handling in writeback_sb_inodes().
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
if (!atomic_read(&inode->i_count))
|
|
|
|
WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING)));
|
|
|
|
else
|
|
|
|
WARN_ON(inode->i_state & I_WILL_FREE);
|
|
|
|
|
|
|
|
if (inode->i_state & I_SYNC) {
|
|
|
|
if (wbc->sync_mode != WB_SYNC_ALL)
|
|
|
|
goto out;
|
|
|
|
/*
|
2012-05-03 20:48:03 +08:00
|
|
|
* It's a data-integrity sync. We must wait. Since callers hold
|
|
|
|
* inode reference or inode has I_WILL_FREE set, it cannot go
|
|
|
|
* away under us.
|
2012-05-03 20:48:00 +08:00
|
|
|
*/
|
2012-05-03 20:48:03 +08:00
|
|
|
__inode_wait_for_writeback(inode);
|
2012-05-03 20:48:00 +08:00
|
|
|
}
|
|
|
|
WARN_ON(inode->i_state & I_SYNC);
|
|
|
|
/*
|
2013-12-14 04:21:26 +08:00
|
|
|
* Skip inode if it is clean and we have no outstanding writeback in
|
|
|
|
* WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
|
|
|
|
* function since flusher thread may be doing for example sync in
|
|
|
|
* parallel and if we move the inode, it could get skipped. So here we
|
|
|
|
* make sure inode is on some writeback list and leave it there unless
|
|
|
|
* we have completely cleaned the inode.
|
2012-05-03 20:48:00 +08:00
|
|
|
*/
|
2015-02-02 13:37:00 +08:00
|
|
|
if (!(inode->i_state & I_DIRTY_ALL) &&
|
2013-12-14 04:21:26 +08:00
|
|
|
(wbc->sync_mode != WB_SYNC_ALL ||
|
|
|
|
!mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
|
2012-05-03 20:48:00 +08:00
|
|
|
goto out;
|
|
|
|
inode->i_state |= I_SYNC;
|
2015-06-02 22:39:48 +08:00
|
|
|
wbc_attach_and_unlock_inode(wbc, inode);
|
2012-05-03 20:48:00 +08:00
|
|
|
|
2012-10-09 07:33:45 +08:00
|
|
|
ret = __writeback_single_inode(inode, wbc);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2015-06-02 22:39:48 +08:00
|
|
|
wbc_detach_inode(wbc);
|
2011-04-22 08:19:44 +08:00
|
|
|
spin_lock(&wb->list_lock);
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
2012-05-03 20:48:00 +08:00
|
|
|
/*
|
|
|
|
* If inode is clean, remove it from writeback lists. Otherwise don't
|
|
|
|
* touch it. See comment above for explanation.
|
|
|
|
*/
|
2015-02-02 13:37:00 +08:00
|
|
|
if (!(inode->i_state & I_DIRTY_ALL))
|
2015-05-23 05:13:45 +08:00
|
|
|
inode_wb_list_del_locked(inode, wb);
|
2012-05-03 20:48:00 +08:00
|
|
|
spin_unlock(&wb->list_lock);
|
2007-10-17 14:30:44 +08:00
|
|
|
inode_sync_complete(inode);
|
2012-05-03 20:48:00 +08:00
|
|
|
out:
|
|
|
|
spin_unlock(&inode->i_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
writeback: move bandwidth related fields from backing_dev_info into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bandwidth related fields from backing_dev_info into
bdi_writeback.
* The moved fields are: bw_time_stamp, dirtied_stamp, written_stamp,
write_bandwidth, avg_write_bandwidth, dirty_ratelimit,
balanced_dirty_ratelimit, completions and dirty_exceeded.
* writeback_chunk_size() and over_bground_thresh() now take @wb
instead of @bdi.
* bdi_writeout_fraction(bdi, ...) -> wb_writeout_fraction(wb, ...)
bdi_dirty_limit(bdi, ...) -> wb_dirty_limit(wb, ...)
bdi_position_ration(bdi, ...) -> wb_position_ratio(wb, ...)
bdi_update_writebandwidth(bdi, ...) -> wb_update_write_bandwidth(wb, ...)
[__]bdi_update_bandwidth(bdi, ...) -> [__]wb_update_bandwidth(wb, ...)
bdi_{max|min}_pause(bdi, ...) -> wb_{max|min}_pause(wb, ...)
bdi_dirty_limits(bdi, ...) -> wb_dirty_limits(wb, ...)
* Init/exits of the relocated fields are moved to bdi_wb_init/exit()
respectively. Note that explicit zeroing is dropped in the process
as wb's are cleared in entirety anyway.
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->stat[] are mechanically replaced with bdi->wb.stat[]
introducing no behavior changes.
v2: Typo in description fixed as suggested by Jan.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:28 +08:00
|
|
|
static long writeback_chunk_size(struct bdi_writeback *wb,
|
2010-08-30 03:28:09 +08:00
|
|
|
struct wb_writeback_work *work)
|
2011-05-05 09:54:37 +08:00
|
|
|
{
|
|
|
|
long pages;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* WB_SYNC_ALL mode does livelock avoidance by syncing dirty
|
|
|
|
* inodes/pages in one big loop. Setting wbc.nr_to_write=LONG_MAX
|
|
|
|
* here avoids calling into writeback_inodes_wb() more than once.
|
|
|
|
*
|
|
|
|
* The intended call sequence for WB_SYNC_ALL writeback is:
|
|
|
|
*
|
|
|
|
* wb_writeback()
|
|
|
|
* writeback_sb_inodes() <== called only once
|
|
|
|
* write_cache_pages() <== called once for each inode
|
|
|
|
* (quickly) tag currently dirty pages
|
|
|
|
* (maybe slowly) sync all tagged pages
|
|
|
|
*/
|
|
|
|
if (work->sync_mode == WB_SYNC_ALL || work->tagged_writepages)
|
|
|
|
pages = LONG_MAX;
|
2010-08-30 03:28:09 +08:00
|
|
|
else {
|
writeback: move bandwidth related fields from backing_dev_info into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bandwidth related fields from backing_dev_info into
bdi_writeback.
* The moved fields are: bw_time_stamp, dirtied_stamp, written_stamp,
write_bandwidth, avg_write_bandwidth, dirty_ratelimit,
balanced_dirty_ratelimit, completions and dirty_exceeded.
* writeback_chunk_size() and over_bground_thresh() now take @wb
instead of @bdi.
* bdi_writeout_fraction(bdi, ...) -> wb_writeout_fraction(wb, ...)
bdi_dirty_limit(bdi, ...) -> wb_dirty_limit(wb, ...)
bdi_position_ration(bdi, ...) -> wb_position_ratio(wb, ...)
bdi_update_writebandwidth(bdi, ...) -> wb_update_write_bandwidth(wb, ...)
[__]bdi_update_bandwidth(bdi, ...) -> [__]wb_update_bandwidth(wb, ...)
bdi_{max|min}_pause(bdi, ...) -> wb_{max|min}_pause(wb, ...)
bdi_dirty_limits(bdi, ...) -> wb_dirty_limits(wb, ...)
* Init/exits of the relocated fields are moved to bdi_wb_init/exit()
respectively. Note that explicit zeroing is dropped in the process
as wb's are cleared in entirety anyway.
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->stat[] are mechanically replaced with bdi->wb.stat[]
introducing no behavior changes.
v2: Typo in description fixed as suggested by Jan.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:28 +08:00
|
|
|
pages = min(wb->avg_write_bandwidth / 2,
|
2015-05-23 06:23:22 +08:00
|
|
|
global_wb_domain.dirty_limit / DIRTY_SCOPE);
|
2010-08-30 03:28:09 +08:00
|
|
|
pages = min(pages, work->nr_pages);
|
|
|
|
pages = round_down(pages + MIN_WRITEBACK_PAGES,
|
|
|
|
MIN_WRITEBACK_PAGES);
|
|
|
|
}
|
2011-05-05 09:54:37 +08:00
|
|
|
|
|
|
|
return pages;
|
|
|
|
}
|
|
|
|
|
2010-03-12 06:09:47 +08:00
|
|
|
/*
|
|
|
|
* Write a portion of b_io inodes which belong to @sb.
|
2010-06-10 18:07:54 +08:00
|
|
|
*
|
2011-05-05 09:54:37 +08:00
|
|
|
* Return the number of pages and/or inodes written.
|
2010-03-12 06:09:47 +08:00
|
|
|
*/
|
2011-05-05 09:54:37 +08:00
|
|
|
static long writeback_sb_inodes(struct super_block *sb,
|
|
|
|
struct bdi_writeback *wb,
|
|
|
|
struct wb_writeback_work *work)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2011-05-05 09:54:37 +08:00
|
|
|
struct writeback_control wbc = {
|
|
|
|
.sync_mode = work->sync_mode,
|
|
|
|
.tagged_writepages = work->tagged_writepages,
|
|
|
|
.for_kupdate = work->for_kupdate,
|
|
|
|
.for_background = work->for_background,
|
2013-07-02 20:38:35 +08:00
|
|
|
.for_sync = work->for_sync,
|
2011-05-05 09:54:37 +08:00
|
|
|
.range_cyclic = work->range_cyclic,
|
|
|
|
.range_start = 0,
|
|
|
|
.range_end = LLONG_MAX,
|
|
|
|
};
|
|
|
|
unsigned long start_time = jiffies;
|
|
|
|
long write_chunk;
|
|
|
|
long wrote = 0; /* count both pages and inodes */
|
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
while (!list_empty(&wb->b_io)) {
|
2010-10-21 08:49:30 +08:00
|
|
|
struct inode *inode = wb_inode(wb->b_io.prev);
|
2010-06-10 18:07:54 +08:00
|
|
|
|
|
|
|
if (inode->i_sb != sb) {
|
2011-05-05 09:54:37 +08:00
|
|
|
if (work->sb) {
|
2010-06-10 18:07:54 +08:00
|
|
|
/*
|
|
|
|
* We only want to write back data for this
|
|
|
|
* superblock, move all inodes not belonging
|
|
|
|
* to it back onto the dirty list.
|
|
|
|
*/
|
2011-04-22 08:19:44 +08:00
|
|
|
redirty_tail(inode, wb);
|
2010-06-10 18:07:54 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The inode belongs to a different superblock.
|
|
|
|
* Bounce back to the caller to unpin this and
|
|
|
|
* pin the next superblock.
|
|
|
|
*/
|
2011-05-05 09:54:37 +08:00
|
|
|
break;
|
2010-06-10 18:07:54 +08:00
|
|
|
}
|
|
|
|
|
2010-10-25 01:40:46 +08:00
|
|
|
/*
|
2012-06-09 11:10:55 +08:00
|
|
|
* Don't bother with new inodes or inodes being freed, first
|
|
|
|
* kind does not need periodic writeout yet, and for the latter
|
2010-10-25 01:40:46 +08:00
|
|
|
* kind writeout is handled by the freer.
|
|
|
|
*/
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
2010-10-25 01:40:46 +08:00
|
|
|
if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_unlock(&inode->i_lock);
|
2011-07-12 14:08:50 +08:00
|
|
|
redirty_tail(inode, wb);
|
fs: new inode i_state corruption fix
There was a report of a data corruption
http://lkml.org/lkml/2008/11/14/121. There is a script included to
reproduce the problem.
During testing, I encountered a number of strange things with ext3, so I
tried ext2 to attempt to reduce complexity of the problem. I found that
fsstress would quickly hang in wait_on_inode, waiting for I_LOCK to be
cleared, even though instrumentation showed that unlock_new_inode had
already been called for that inode. This points to memory scribble, or
synchronisation problme.
i_state of I_NEW inodes is not protected by inode_lock because other
processes are not supposed to touch them until I_LOCK (and I_NEW) is
cleared. Adding WARN_ON(inode->i_state & I_NEW) to sites where we modify
i_state revealed that generic_sync_sb_inodes is picking up new inodes from
the inode lists and passing them to __writeback_single_inode without
waiting for I_NEW. Subsequently modifying i_state causes corruption. In
my case it would look like this:
CPU0 CPU1
unlock_new_inode() __sync_single_inode()
reg <- inode->i_state
reg -> reg & ~(I_LOCK|I_NEW) reg <- inode->i_state
reg -> inode->i_state reg -> reg | I_SYNC
reg -> inode->i_state
Non-atomic RMW on CPU1 overwrites CPU0 store and sets I_LOCK|I_NEW again.
Fix for this is rather than wait for I_NEW inodes, just skip over them:
inodes concurrently being created are not subject to data integrity
operations, and should not significantly contribute to dirty memory
either.
After this change, I'm unable to reproduce any of the added warnings or
hangs after ~1hour of running. Previously, the new warnings would start
immediately and hang would happen in under 5 minutes.
I'm also testing on ext3 now, and so far no problems there either. I
don't know whether this fixes the problem reported above, but it fixes a
real problem for me.
Cc: "Jorge Boncompte [DTI2]" <jorge@dti2.net>
Reported-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Cc: Jan Kara <jack@suse.cz>
Cc: <stable@kernel.org>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-03-13 05:31:38 +08:00
|
|
|
continue;
|
|
|
|
}
|
2012-05-03 20:47:56 +08:00
|
|
|
if ((inode->i_state & I_SYNC) && wbc.sync_mode != WB_SYNC_ALL) {
|
|
|
|
/*
|
|
|
|
* If this inode is locked for writeback and we are not
|
|
|
|
* doing writeback-for-data-integrity, move it to
|
|
|
|
* b_more_io so that writeback can proceed with the
|
|
|
|
* other inodes on s_io.
|
|
|
|
*
|
|
|
|
* We'll have another go at writing back this inode
|
|
|
|
* when we completed a full scan of b_io.
|
|
|
|
*/
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
requeue_io(inode, wb);
|
|
|
|
trace_writeback_sb_inodes_requeue(inode);
|
|
|
|
continue;
|
|
|
|
}
|
2012-05-03 20:47:59 +08:00
|
|
|
spin_unlock(&wb->list_lock);
|
|
|
|
|
2012-05-03 20:48:00 +08:00
|
|
|
/*
|
|
|
|
* We already requeued the inode if it had I_SYNC set and we
|
|
|
|
* are doing WB_SYNC_NONE writeback. So this catches only the
|
|
|
|
* WB_SYNC_ALL case.
|
|
|
|
*/
|
2012-05-03 20:48:03 +08:00
|
|
|
if (inode->i_state & I_SYNC) {
|
|
|
|
/* Wait for I_SYNC. This function drops i_lock... */
|
|
|
|
inode_sleep_on_writeback(inode);
|
|
|
|
/* Inode may be gone, start again */
|
2012-06-08 23:07:36 +08:00
|
|
|
spin_lock(&wb->list_lock);
|
2012-05-03 20:48:03 +08:00
|
|
|
continue;
|
|
|
|
}
|
2012-05-03 20:48:00 +08:00
|
|
|
inode->i_state |= I_SYNC;
|
2015-06-02 22:39:48 +08:00
|
|
|
wbc_attach_and_unlock_inode(&wbc, inode);
|
2012-05-03 20:48:03 +08:00
|
|
|
|
writeback: move bandwidth related fields from backing_dev_info into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bandwidth related fields from backing_dev_info into
bdi_writeback.
* The moved fields are: bw_time_stamp, dirtied_stamp, written_stamp,
write_bandwidth, avg_write_bandwidth, dirty_ratelimit,
balanced_dirty_ratelimit, completions and dirty_exceeded.
* writeback_chunk_size() and over_bground_thresh() now take @wb
instead of @bdi.
* bdi_writeout_fraction(bdi, ...) -> wb_writeout_fraction(wb, ...)
bdi_dirty_limit(bdi, ...) -> wb_dirty_limit(wb, ...)
bdi_position_ration(bdi, ...) -> wb_position_ratio(wb, ...)
bdi_update_writebandwidth(bdi, ...) -> wb_update_write_bandwidth(wb, ...)
[__]bdi_update_bandwidth(bdi, ...) -> [__]wb_update_bandwidth(wb, ...)
bdi_{max|min}_pause(bdi, ...) -> wb_{max|min}_pause(wb, ...)
bdi_dirty_limits(bdi, ...) -> wb_dirty_limits(wb, ...)
* Init/exits of the relocated fields are moved to bdi_wb_init/exit()
respectively. Note that explicit zeroing is dropped in the process
as wb's are cleared in entirety anyway.
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->stat[] are mechanically replaced with bdi->wb.stat[]
introducing no behavior changes.
v2: Typo in description fixed as suggested by Jan.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:28 +08:00
|
|
|
write_chunk = writeback_chunk_size(wb, work);
|
2011-05-05 09:54:37 +08:00
|
|
|
wbc.nr_to_write = write_chunk;
|
|
|
|
wbc.pages_skipped = 0;
|
2011-03-22 19:23:36 +08:00
|
|
|
|
2012-05-03 20:48:03 +08:00
|
|
|
/*
|
|
|
|
* We use I_SYNC to pin the inode in memory. While it is set
|
|
|
|
* evict_inode() will wait so the inode cannot be freed.
|
|
|
|
*/
|
2012-10-09 07:33:45 +08:00
|
|
|
__writeback_single_inode(inode, &wbc);
|
2011-03-22 19:23:36 +08:00
|
|
|
|
2015-06-02 22:39:48 +08:00
|
|
|
wbc_detach_inode(&wbc);
|
2011-05-05 09:54:37 +08:00
|
|
|
work->nr_pages -= write_chunk - wbc.nr_to_write;
|
|
|
|
wrote += write_chunk - wbc.nr_to_write;
|
2012-05-03 20:48:00 +08:00
|
|
|
spin_lock(&wb->list_lock);
|
|
|
|
spin_lock(&inode->i_lock);
|
2015-02-02 13:37:00 +08:00
|
|
|
if (!(inode->i_state & I_DIRTY_ALL))
|
2011-05-05 09:54:37 +08:00
|
|
|
wrote++;
|
2012-05-03 20:48:00 +08:00
|
|
|
requeue_inode(inode, wb, &wbc);
|
|
|
|
inode_sync_complete(inode);
|
2011-03-22 19:23:43 +08:00
|
|
|
spin_unlock(&inode->i_lock);
|
2012-05-03 20:48:03 +08:00
|
|
|
cond_resched_lock(&wb->list_lock);
|
2011-05-05 09:54:37 +08:00
|
|
|
/*
|
|
|
|
* bail out to wb_writeback() often enough to check
|
|
|
|
* background threshold and other termination conditions.
|
|
|
|
*/
|
|
|
|
if (wrote) {
|
|
|
|
if (time_is_before_jiffies(start_time + HZ / 10UL))
|
|
|
|
break;
|
|
|
|
if (work->nr_pages <= 0)
|
|
|
|
break;
|
writeback: speed up writeback of big dirty files
After making dirty a 100M file, the normal behavior is to start the
writeback for all data after 30s delays. But sometimes the following
happens instead:
- after 30s: ~4M
- after 5s: ~4M
- after 5s: all remaining 92M
Some analyze shows that the internal io dispatch queues goes like this:
s_io s_more_io
-------------------------
1) 100M,1K 0
2) 1K 96M
3) 0 96M
1) initial state with a 100M file and a 1K file
2) 4M written, nr_to_write <= 0, so write more
3) 1K written, nr_to_write > 0, no more writes(BUG)
nr_to_write > 0 in (3) fools the upper layer to think that data have all
been written out. The big dirty file is actually still sitting in
s_more_io. We cannot simply splice s_more_io back to s_io as soon as s_io
becomes empty, and let the loop in generic_sync_sb_inodes() continue: this
may starve newly expired inodes in s_dirty. It is also not an option to
draw inodes from both s_more_io and s_dirty, an let the loop go on: this
might lead to live locks, and might also starve other superblocks in sync
time(well kupdate may still starve some superblocks, that's another bug).
We have to return when a full scan of s_io completes. So nr_to_write > 0
does not necessarily mean that "all data are written". This patch
introduces a flag writeback_control.more_io to indicate that more io should
be done. With it the big dirty file no longer has to wait for the next
kupdate invokation 5s later.
In sync_sb_inodes() we only set more_io on super_blocks we actually
visited. This avoids the interaction between two pdflush deamons.
Also in __sync_single_inode() we don't blindly keep requeuing the io if the
filesystem cannot progress. Failing to do so may lead to 100% iowait.
Tested-by: Mike Snitzer <snitzer@gmail.com>
Signed-off-by: Fengguang Wu <wfg@mail.ustc.edu.cn>
Cc: Michael Rubin <mrubin@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-05 14:29:36 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2011-05-05 09:54:37 +08:00
|
|
|
return wrote;
|
2010-03-12 06:09:47 +08:00
|
|
|
}
|
|
|
|
|
2011-05-05 09:54:37 +08:00
|
|
|
static long __writeback_inodes_wb(struct bdi_writeback *wb,
|
|
|
|
struct wb_writeback_work *work)
|
2010-03-12 06:09:47 +08:00
|
|
|
{
|
2011-05-05 09:54:37 +08:00
|
|
|
unsigned long start_time = jiffies;
|
|
|
|
long wrote = 0;
|
2009-01-07 06:40:25 +08:00
|
|
|
|
2010-03-12 06:09:47 +08:00
|
|
|
while (!list_empty(&wb->b_io)) {
|
2010-10-21 08:49:30 +08:00
|
|
|
struct inode *inode = wb_inode(wb->b_io.prev);
|
2010-03-12 06:09:47 +08:00
|
|
|
struct super_block *sb = inode->i_sb;
|
2009-09-24 21:25:11 +08:00
|
|
|
|
2015-02-20 01:19:35 +08:00
|
|
|
if (!trylock_super(sb)) {
|
2011-07-30 12:14:35 +08:00
|
|
|
/*
|
2015-02-20 01:19:35 +08:00
|
|
|
* trylock_super() may fail consistently due to
|
2011-07-30 12:14:35 +08:00
|
|
|
* s_umount being grabbed by someone else. Don't use
|
|
|
|
* requeue_io() to avoid busy retrying the inode/sb.
|
|
|
|
*/
|
|
|
|
redirty_tail(inode, wb);
|
2010-06-10 18:07:54 +08:00
|
|
|
continue;
|
2010-03-12 06:09:47 +08:00
|
|
|
}
|
2011-05-05 09:54:37 +08:00
|
|
|
wrote += writeback_sb_inodes(sb, wb, work);
|
2015-02-20 01:19:35 +08:00
|
|
|
up_read(&sb->s_umount);
|
2010-03-12 06:09:47 +08:00
|
|
|
|
2011-05-05 09:54:37 +08:00
|
|
|
/* refer to the same tests at the end of writeback_sb_inodes */
|
|
|
|
if (wrote) {
|
|
|
|
if (time_is_before_jiffies(start_time + HZ / 10UL))
|
|
|
|
break;
|
|
|
|
if (work->nr_pages <= 0)
|
|
|
|
break;
|
|
|
|
}
|
2010-03-12 06:09:47 +08:00
|
|
|
}
|
2009-09-02 15:19:46 +08:00
|
|
|
/* Leave any unwritten inodes on b_io */
|
2011-05-05 09:54:37 +08:00
|
|
|
return wrote;
|
2009-09-02 15:19:46 +08:00
|
|
|
}
|
|
|
|
|
2013-09-12 05:22:40 +08:00
|
|
|
static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
|
2011-10-08 11:54:10 +08:00
|
|
|
enum wb_reason reason)
|
2010-06-10 18:07:54 +08:00
|
|
|
{
|
2011-05-05 09:54:37 +08:00
|
|
|
struct wb_writeback_work work = {
|
|
|
|
.nr_pages = nr_pages,
|
|
|
|
.sync_mode = WB_SYNC_NONE,
|
|
|
|
.range_cyclic = 1,
|
2011-10-08 11:54:10 +08:00
|
|
|
.reason = reason,
|
2011-05-05 09:54:37 +08:00
|
|
|
};
|
2010-06-10 18:07:54 +08:00
|
|
|
|
2011-04-22 08:19:44 +08:00
|
|
|
spin_lock(&wb->list_lock);
|
writeback: refill b_io iff empty
There is no point to carry different refill policies between for_kupdate
and other type of works. Use a consistent "refill b_io iff empty" policy
which can guarantee fairness in an easy to understand way.
A b_io refill will setup a _fixed_ work set with all currently eligible
inodes and start a new round of walk through b_io. The "fixed" work set
means no new inodes will be added to the work set during the walk.
Only when a complete walk over b_io is done, new inodes that are
eligible at the time will be enqueued and the walk be started over.
This procedure provides fairness among the inodes because it guarantees
each inode to be synced once and only once at each round. So all inodes
will be free from starvations.
This change relies on wb_writeback() to keep retrying as long as we made
some progress on cleaning some pages and/or inodes. Without that ability,
the old logic on background works relies on aggressively queuing all
eligible inodes into b_io at every time. But that's not a guarantee.
The below test script completes a slightly faster now:
2.6.39-rc3 2.6.39-rc3-dyn-expire+
------------------------------------------------
all elapsed 256.043 252.367
stddev 24.381 12.530
tar elapsed 30.097 28.808
dd elapsed 13.214 11.782
#!/bin/zsh
cp /c/linux-2.6.38.3.tar.bz2 /dev/shm/
umount /dev/sda7
mkfs.xfs -f /dev/sda7
mount /dev/sda7 /fs
echo 3 > /proc/sys/vm/drop_caches
tic=$(cat /proc/uptime|cut -d' ' -f2)
cd /fs
time tar jxf /dev/shm/linux-2.6.38.3.tar.bz2 &
time dd if=/dev/zero of=/fs/zero bs=1M count=1000 &
wait
sync
tac=$(cat /proc/uptime|cut -d' ' -f2)
echo elapsed: $((tac - tic))
It maintains roughly the same small vs. large file writeout shares, and
offers large files better chances to be written in nice 4M chunks.
Analyzes from Dave Chinner in great details:
Let's say we have lots of inodes with 100 dirty pages being created,
and one large writeback going on. We expire 8 new inodes for every
1024 pages we write back.
With the old code, we do:
b_more_io (large inode) -> b_io (1l)
8 newly expired inodes -> b_io (1l, 8s)
writeback large inode 1024 pages -> b_more_io
b_more_io (large inode) -> b_io (8s, 1l)
8 newly expired inodes -> b_io (8s, 1l, 8s)
writeback 8 small inodes 800 pages
1 large inode 224 pages -> b_more_io
b_more_io (large inode) -> b_io (8s, 1l)
8 newly expired inodes -> b_io (8s, 1l, 8s)
.....
Your new code:
b_more_io (large inode) -> b_io (1l)
8 newly expired inodes -> b_io (1l, 8s)
writeback large inode 1024 pages -> b_more_io
(b_io == 8s)
writeback 8 small inodes 800 pages
b_io empty: (1800 pages written)
b_more_io (large inode) -> b_io (1l)
14 newly expired inodes -> b_io (1l, 14s)
writeback large inode 1024 pages -> b_more_io
(b_io == 14s)
writeback 10 small inodes 1000 pages
1 small inode 24 pages -> b_more_io (1l, 1s(24))
writeback 5 small inodes 500 pages
b_io empty: (2548 pages written)
b_more_io (large inode) -> b_io (1l, 1s(24))
20 newly expired inodes -> b_io (1l, 1s(24), 20s)
......
Rough progression of pages written at b_io refill:
Old code:
total large file % of writeback
1024 224 21.9% (fixed)
New code:
total large file % of writeback
1800 1024 ~55%
2550 1024 ~40%
3050 1024 ~33%
3500 1024 ~29%
3950 1024 ~26%
4250 1024 ~24%
4500 1024 ~22.7%
4700 1024 ~21.7%
4800 1024 ~21.3%
4800 1024 ~21.3%
(pretty much steady state from here)
Ok, so the steady state is reached with a similar percentage of
writeback to the large file as the existing code. Ok, that's good,
but providing some evidence that is doesn't change the shared of
writeback to the large should be in the commit message ;)
The other advantage to this is that we always write 1024 page chunks
to the large file, rather than smaller "whatever remains" chunks.
CC: Jan Kara <jack@suse.cz>
Acked-by: Mel Gorman <mel@csn.ul.ie>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
2010-07-22 10:11:53 +08:00
|
|
|
if (list_empty(&wb->b_io))
|
2011-10-08 11:51:56 +08:00
|
|
|
queue_io(wb, &work);
|
2011-05-05 09:54:37 +08:00
|
|
|
__writeback_inodes_wb(wb, &work);
|
2011-04-22 08:19:44 +08:00
|
|
|
spin_unlock(&wb->list_lock);
|
2010-06-10 18:07:54 +08:00
|
|
|
|
2011-05-05 09:54:37 +08:00
|
|
|
return nr_pages - work.nr_pages;
|
|
|
|
}
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Explicit flushing or periodic writeback of "old" data.
|
2009-09-02 15:19:46 +08:00
|
|
|
*
|
2009-09-09 15:08:54 +08:00
|
|
|
* Define "old": the first time one of an inode's pages is dirtied, we mark the
|
|
|
|
* dirtying-time in the inode's address_space. So this periodic writeback code
|
|
|
|
* just walks the superblock inode list, writing back any inodes which are
|
|
|
|
* older than a specific point in time.
|
2009-09-02 15:19:46 +08:00
|
|
|
*
|
2009-09-09 15:08:54 +08:00
|
|
|
* Try to run once per dirty_writeback_interval. But if a writeback event
|
|
|
|
* takes longer than a dirty_writeback_interval interval, then leave a
|
|
|
|
* one-second gap.
|
2009-09-02 15:19:46 +08:00
|
|
|
*
|
2009-09-09 15:08:54 +08:00
|
|
|
* older_than_this takes precedence over nr_to_write. So we'll only write back
|
|
|
|
* all dirty pages if they are all attached to "old" mappings.
|
2009-09-02 15:19:46 +08:00
|
|
|
*/
|
2009-09-16 21:18:25 +08:00
|
|
|
static long wb_writeback(struct bdi_writeback *wb,
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work *work)
|
2009-09-02 15:19:46 +08:00
|
|
|
{
|
2010-08-30 01:22:30 +08:00
|
|
|
unsigned long wb_start = jiffies;
|
2011-05-05 09:54:37 +08:00
|
|
|
long nr_pages = work->nr_pages;
|
2014-02-21 18:19:04 +08:00
|
|
|
unsigned long oldest_jif;
|
2009-09-17 01:22:48 +08:00
|
|
|
struct inode *inode;
|
2011-05-05 09:54:37 +08:00
|
|
|
long progress;
|
2009-09-02 15:19:46 +08:00
|
|
|
|
2014-02-21 18:19:04 +08:00
|
|
|
oldest_jif = jiffies;
|
|
|
|
work->older_than_this = &oldest_jif;
|
2009-01-07 06:40:25 +08:00
|
|
|
|
2011-04-22 02:06:32 +08:00
|
|
|
spin_lock(&wb->list_lock);
|
2009-09-09 15:08:54 +08:00
|
|
|
for (;;) {
|
|
|
|
/*
|
2009-09-23 20:33:40 +08:00
|
|
|
* Stop writeback when nr_pages has been consumed
|
2009-09-09 15:08:54 +08:00
|
|
|
*/
|
2010-07-06 14:59:53 +08:00
|
|
|
if (work->nr_pages <= 0)
|
2009-09-09 15:08:54 +08:00
|
|
|
break;
|
2009-09-02 15:19:46 +08:00
|
|
|
|
2011-01-14 07:45:47 +08:00
|
|
|
/*
|
|
|
|
* Background writeout and kupdate-style writeback may
|
|
|
|
* run forever. Stop them if there is other work to do
|
|
|
|
* so that e.g. sync can proceed. They'll be restarted
|
|
|
|
* after the other works are all done.
|
|
|
|
*/
|
|
|
|
if ((work->for_background || work->for_kupdate) &&
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
!list_empty(&wb->work_list))
|
2011-01-14 07:45:47 +08:00
|
|
|
break;
|
|
|
|
|
2009-01-07 06:40:25 +08:00
|
|
|
/*
|
2009-09-23 20:33:40 +08:00
|
|
|
* For background writeout, stop when we are below the
|
|
|
|
* background dirty threshold
|
2009-01-07 06:40:25 +08:00
|
|
|
*/
|
2015-05-23 06:23:31 +08:00
|
|
|
if (work->for_background && !wb_over_bg_thresh(wb))
|
2009-09-09 15:08:54 +08:00
|
|
|
break;
|
2009-01-07 06:40:25 +08:00
|
|
|
|
2011-10-19 17:44:41 +08:00
|
|
|
/*
|
|
|
|
* Kupdate and background works are special and we want to
|
|
|
|
* include all inodes that need writing. Livelock avoidance is
|
|
|
|
* handled by these works yielding to any other work so we are
|
|
|
|
* safe.
|
|
|
|
*/
|
2010-07-22 10:32:30 +08:00
|
|
|
if (work->for_kupdate) {
|
2014-02-21 18:19:04 +08:00
|
|
|
oldest_jif = jiffies -
|
2010-07-22 10:32:30 +08:00
|
|
|
msecs_to_jiffies(dirty_expire_interval * 10);
|
2011-10-19 17:44:41 +08:00
|
|
|
} else if (work->for_background)
|
2014-02-21 18:19:04 +08:00
|
|
|
oldest_jif = jiffies;
|
2010-07-07 11:24:07 +08:00
|
|
|
|
2011-05-05 09:54:37 +08:00
|
|
|
trace_writeback_start(wb->bdi, work);
|
2011-04-22 02:06:32 +08:00
|
|
|
if (list_empty(&wb->b_io))
|
2011-10-08 11:51:56 +08:00
|
|
|
queue_io(wb, work);
|
2010-07-06 14:59:53 +08:00
|
|
|
if (work->sb)
|
2011-05-05 09:54:37 +08:00
|
|
|
progress = writeback_sb_inodes(work->sb, wb, work);
|
2010-06-10 18:07:54 +08:00
|
|
|
else
|
2011-05-05 09:54:37 +08:00
|
|
|
progress = __writeback_inodes_wb(wb, work);
|
|
|
|
trace_writeback_written(wb->bdi, work);
|
2010-07-07 11:24:07 +08:00
|
|
|
|
2010-08-30 01:22:30 +08:00
|
|
|
wb_update_bandwidth(wb, wb_start);
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
/*
|
writeback: try more writeback as long as something was written
writeback_inodes_wb()/__writeback_inodes_sb() are not aggressive in that
they only populate possibly a subset of eligible inodes into b_io at
entrance time. When the queued set of inodes are all synced, they just
return, possibly with all queued inode pages written but still
wbc.nr_to_write > 0.
For kupdate and background writeback, there may be more eligible inodes
sitting in b_dirty when the current set of b_io inodes are completed. So
it is necessary to try another round of writeback as long as we made some
progress in this round. When there are no more eligible inodes, no more
inodes will be enqueued in queue_io(), hence nothing could/will be
synced and we may safely bail.
For example, imagine 100 inodes
i0, i1, i2, ..., i90, i91, i99
At queue_io() time, i90-i99 happen to be expired and moved to s_io for
IO. When finished successfully, if their total size is less than
MAX_WRITEBACK_PAGES, nr_to_write will be > 0. Then wb_writeback() will
quit the background work (w/o this patch) while it's still over
background threshold. This will be a fairly normal/frequent case I guess.
Now that we do tagged sync and update inode->dirtied_when after the sync,
this change won't livelock sync(1). I actually tried to write 1 page
per 1ms with this command
write-and-fsync -n10000 -S 1000 -c 4096 /fs/test
and do sync(1) at the same time. The sync completes quickly on ext4,
xfs, btrfs.
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
2010-07-23 00:23:44 +08:00
|
|
|
* Did we write something? Try for more
|
|
|
|
*
|
|
|
|
* Dirty inodes are moved to b_io for writeback in batches.
|
|
|
|
* The completion of the current batch does not necessarily
|
|
|
|
* mean the overall work is done. So we keep looping as long
|
|
|
|
* as made some progress on cleaning pages or inodes.
|
2009-09-09 15:08:54 +08:00
|
|
|
*/
|
2011-05-05 09:54:37 +08:00
|
|
|
if (progress)
|
2009-09-24 01:32:26 +08:00
|
|
|
continue;
|
|
|
|
/*
|
writeback: try more writeback as long as something was written
writeback_inodes_wb()/__writeback_inodes_sb() are not aggressive in that
they only populate possibly a subset of eligible inodes into b_io at
entrance time. When the queued set of inodes are all synced, they just
return, possibly with all queued inode pages written but still
wbc.nr_to_write > 0.
For kupdate and background writeback, there may be more eligible inodes
sitting in b_dirty when the current set of b_io inodes are completed. So
it is necessary to try another round of writeback as long as we made some
progress in this round. When there are no more eligible inodes, no more
inodes will be enqueued in queue_io(), hence nothing could/will be
synced and we may safely bail.
For example, imagine 100 inodes
i0, i1, i2, ..., i90, i91, i99
At queue_io() time, i90-i99 happen to be expired and moved to s_io for
IO. When finished successfully, if their total size is less than
MAX_WRITEBACK_PAGES, nr_to_write will be > 0. Then wb_writeback() will
quit the background work (w/o this patch) while it's still over
background threshold. This will be a fairly normal/frequent case I guess.
Now that we do tagged sync and update inode->dirtied_when after the sync,
this change won't livelock sync(1). I actually tried to write 1 page
per 1ms with this command
write-and-fsync -n10000 -S 1000 -c 4096 /fs/test
and do sync(1) at the same time. The sync completes quickly on ext4,
xfs, btrfs.
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
2010-07-23 00:23:44 +08:00
|
|
|
* No more inodes for IO, bail
|
2009-09-24 01:32:26 +08:00
|
|
|
*/
|
2010-07-22 12:19:51 +08:00
|
|
|
if (list_empty(&wb->b_more_io))
|
2009-09-09 15:08:54 +08:00
|
|
|
break;
|
2009-09-24 01:32:26 +08:00
|
|
|
/*
|
|
|
|
* Nothing written. Wait for some inode to
|
|
|
|
* become available for writeback. Otherwise
|
|
|
|
* we'll just busyloop.
|
|
|
|
*/
|
|
|
|
if (!list_empty(&wb->b_more_io)) {
|
2011-05-05 09:54:37 +08:00
|
|
|
trace_writeback_wait(wb->bdi, work);
|
2010-10-21 08:49:30 +08:00
|
|
|
inode = wb_inode(wb->b_more_io.prev);
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
2012-05-03 20:47:59 +08:00
|
|
|
spin_unlock(&wb->list_lock);
|
2012-05-03 20:48:03 +08:00
|
|
|
/* This function drops i_lock... */
|
|
|
|
inode_sleep_on_writeback(inode);
|
2012-05-03 20:47:59 +08:00
|
|
|
spin_lock(&wb->list_lock);
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-22 02:06:32 +08:00
|
|
|
spin_unlock(&wb->list_lock);
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2011-05-05 09:54:37 +08:00
|
|
|
return nr_pages - work->nr_pages;
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-07-06 14:59:53 +08:00
|
|
|
* Return the next wb_writeback_work struct that hasn't been processed yet.
|
2009-09-09 15:08:54 +08:00
|
|
|
*/
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
static struct wb_writeback_work *get_next_work_item(struct bdi_writeback *wb)
|
2009-09-09 15:08:54 +08:00
|
|
|
{
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work *work = NULL;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
spin_lock_bh(&wb->work_lock);
|
|
|
|
if (!list_empty(&wb->work_list)) {
|
|
|
|
work = list_entry(wb->work_list.next,
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work, list);
|
|
|
|
list_del_init(&work->list);
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
spin_unlock_bh(&wb->work_lock);
|
2010-07-06 14:59:53 +08:00
|
|
|
return work;
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
|
|
|
|
2010-10-30 23:55:52 +08:00
|
|
|
/*
|
|
|
|
* Add in the number of potentially dirty inodes, because each inode
|
|
|
|
* write can dirty pagecache in the underlying blockdev.
|
|
|
|
*/
|
|
|
|
static unsigned long get_nr_dirty_pages(void)
|
|
|
|
{
|
|
|
|
return global_page_state(NR_FILE_DIRTY) +
|
|
|
|
global_page_state(NR_UNSTABLE_NFS) +
|
|
|
|
get_nr_dirty_inodes();
|
|
|
|
}
|
|
|
|
|
2011-01-14 07:45:44 +08:00
|
|
|
static long wb_check_background_flush(struct bdi_writeback *wb)
|
|
|
|
{
|
2015-05-23 06:23:31 +08:00
|
|
|
if (wb_over_bg_thresh(wb)) {
|
2011-01-14 07:45:44 +08:00
|
|
|
|
|
|
|
struct wb_writeback_work work = {
|
|
|
|
.nr_pages = LONG_MAX,
|
|
|
|
.sync_mode = WB_SYNC_NONE,
|
|
|
|
.for_background = 1,
|
|
|
|
.range_cyclic = 1,
|
2011-10-08 11:54:10 +08:00
|
|
|
.reason = WB_REASON_BACKGROUND,
|
2011-01-14 07:45:44 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
return wb_writeback(wb, &work);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
static long wb_check_old_data_flush(struct bdi_writeback *wb)
|
|
|
|
{
|
|
|
|
unsigned long expired;
|
|
|
|
long nr_pages;
|
|
|
|
|
2010-05-17 18:51:03 +08:00
|
|
|
/*
|
|
|
|
* When set to zero, disable periodic writeback
|
|
|
|
*/
|
|
|
|
if (!dirty_writeback_interval)
|
|
|
|
return 0;
|
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
expired = wb->last_old_flush +
|
|
|
|
msecs_to_jiffies(dirty_writeback_interval * 10);
|
|
|
|
if (time_before(jiffies, expired))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
wb->last_old_flush = jiffies;
|
2010-10-30 23:55:52 +08:00
|
|
|
nr_pages = get_nr_dirty_pages();
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2009-09-16 21:18:25 +08:00
|
|
|
if (nr_pages) {
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work work = {
|
2009-09-16 21:18:25 +08:00
|
|
|
.nr_pages = nr_pages,
|
|
|
|
.sync_mode = WB_SYNC_NONE,
|
|
|
|
.for_kupdate = 1,
|
|
|
|
.range_cyclic = 1,
|
2011-10-08 11:54:10 +08:00
|
|
|
.reason = WB_REASON_PERIODIC,
|
2009-09-16 21:18:25 +08:00
|
|
|
};
|
|
|
|
|
2010-07-06 14:59:53 +08:00
|
|
|
return wb_writeback(wb, &work);
|
2009-09-16 21:18:25 +08:00
|
|
|
}
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve work items and do the writeback they describe
|
|
|
|
*/
|
2013-07-09 07:00:14 +08:00
|
|
|
static long wb_do_writeback(struct bdi_writeback *wb)
|
2009-09-09 15:08:54 +08:00
|
|
|
{
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work *work;
|
2009-09-16 21:18:25 +08:00
|
|
|
long wrote = 0;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2015-05-23 05:13:26 +08:00
|
|
|
set_bit(WB_writeback_running, &wb->state);
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
while ((work = get_next_work_item(wb)) != NULL) {
|
2015-05-23 05:13:58 +08:00
|
|
|
struct wb_completion *done = work->done;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
trace_writeback_exec(wb->bdi, work);
|
2010-07-07 11:24:06 +08:00
|
|
|
|
2010-07-06 14:59:53 +08:00
|
|
|
wrote += wb_writeback(wb, work);
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2015-08-19 05:54:53 +08:00
|
|
|
if (work->auto_free)
|
2010-07-06 14:59:53 +08:00
|
|
|
kfree(work);
|
2015-05-23 05:13:58 +08:00
|
|
|
if (done && atomic_dec_and_test(&done->cnt))
|
|
|
|
wake_up_all(&wb->bdi->wb_waitq);
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for periodic writeback, kupdated() style
|
|
|
|
*/
|
|
|
|
wrote += wb_check_old_data_flush(wb);
|
2011-01-14 07:45:44 +08:00
|
|
|
wrote += wb_check_background_flush(wb);
|
2015-05-23 05:13:26 +08:00
|
|
|
clear_bit(WB_writeback_running, &wb->state);
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
return wrote;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle writeback of dirty data for the device backed by this bdi. Also
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
* reschedules periodically and does kupdated style flushing.
|
2009-09-09 15:08:54 +08:00
|
|
|
*/
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
void wb_workfn(struct work_struct *work)
|
2009-09-09 15:08:54 +08:00
|
|
|
{
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
struct bdi_writeback *wb = container_of(to_delayed_work(work),
|
|
|
|
struct bdi_writeback, dwork);
|
2009-09-09 15:08:54 +08:00
|
|
|
long pages_written;
|
|
|
|
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
set_worker_desc("flush-%s", dev_name(wb->bdi->dev));
|
2010-10-27 05:22:45 +08:00
|
|
|
current->flags |= PF_SWAPWRITE;
|
2010-07-07 11:24:06 +08:00
|
|
|
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
if (likely(!current_is_workqueue_rescuer() ||
|
2015-05-23 05:13:26 +08:00
|
|
|
!test_bit(WB_registered, &wb->state))) {
|
2010-07-25 19:29:22 +08:00
|
|
|
/*
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
* The normal path. Keep writing back @wb until its
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
* work_list is empty. Note that this path is also taken
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
* if @wb is shutting down even when we're running off the
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
* rescuer as work_list needs to be drained.
|
2010-07-25 19:29:22 +08:00
|
|
|
*/
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
do {
|
2013-07-09 07:00:14 +08:00
|
|
|
pages_written = wb_do_writeback(wb);
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
trace_writeback_pages_written(pages_written);
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
} while (!list_empty(&wb->work_list));
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* bdi_wq can't get enough workers and we're running off
|
|
|
|
* the emergency worker. Don't hog it. Hopefully, 1024 is
|
|
|
|
* enough for efficient IO.
|
|
|
|
*/
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
pages_written = writeback_inodes_wb(wb, 1024,
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
WB_REASON_FORKER_THREAD);
|
2010-07-07 11:24:06 +08:00
|
|
|
trace_writeback_pages_written(pages_written);
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
|
|
|
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
if (!list_empty(&wb->work_list))
|
2014-04-04 05:46:22 +08:00
|
|
|
mod_delayed_work(bdi_wq, &wb->dwork, 0);
|
|
|
|
else if (wb_has_dirty_io(wb) && dirty_writeback_interval)
|
writeback: move backing_dev_info->wb_lock and ->worklist into bdi_writeback
Currently, a bdi (backing_dev_info) embeds single wb (bdi_writeback)
and the role of the separation is unclear. For cgroup support for
writeback IOs, a bdi will be updated to host multiple wb's where each
wb serves writeback IOs of a different cgroup on the bdi. To achieve
that, a wb should carry all states necessary for servicing writeback
IOs for a cgroup independently.
This patch moves bdi->wb_lock and ->worklist into wb.
* The lock protects bdi->worklist and bdi->wb.dwork scheduling. While
moving, rename it to wb->work_lock as wb->wb_lock is confusing.
Also, move wb->dwork downwards so that it's colocated with the new
->work_lock and ->work_list fields.
* bdi_writeback_workfn() -> wb_workfn()
bdi_wakeup_thread_delayed(bdi) -> wb_wakeup_delayed(wb)
bdi_wakeup_thread(bdi) -> wb_wakeup(wb)
bdi_queue_work(bdi, ...) -> wb_queue_work(wb, ...)
__bdi_start_writeback(bdi, ...) -> __wb_start_writeback(wb, ...)
get_next_work_item(bdi) -> get_next_work_item(wb)
* bdi_wb_shutdown() is renamed to wb_shutdown() and now takes @wb.
The function contained parts which belong to the containing bdi
rather than the wb itself - testing cap_writeback_dirty and
bdi_remove_from_list() invocation. Those are moved to
bdi_unregister().
* bdi_wb_{init|exit}() are renamed to wb_{init|exit}().
Initializations of the moved bdi->wb_lock and ->work_list are
relocated from bdi_init() to wb_init().
* As there's still only one bdi_writeback per backing_dev_info, all
uses of bdi->state are mechanically replaced with bdi->wb.state
introducing no behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:30 +08:00
|
|
|
wb_wakeup_delayed(wb);
|
2010-07-07 11:24:06 +08:00
|
|
|
|
writeback: replace custom worker pool implementation with unbound workqueue
Writeback implements its own worker pool - each bdi can be associated
with a worker thread which is created and destroyed dynamically. The
worker thread for the default bdi is always present and serves as the
"forker" thread which forks off worker threads for other bdis.
there's no reason for writeback to implement its own worker pool when
using unbound workqueue instead is much simpler and more efficient.
This patch replaces custom worker pool implementation in writeback
with an unbound workqueue.
The conversion isn't too complicated but the followings are worth
mentioning.
* bdi_writeback->last_active, task and wakeup_timer are removed.
delayed_work ->dwork is added instead. Explicit timer handling is
no longer necessary. Everything works by either queueing / modding
/ flushing / canceling the delayed_work item.
* bdi_writeback_thread() becomes bdi_writeback_workfn() which runs off
bdi_writeback->dwork. On each execution, it processes
bdi->work_list and reschedules itself if there are more things to
do.
The function also handles low-mem condition, which used to be
handled by the forker thread. If the function is running off a
rescuer thread, it only writes out limited number of pages so that
the rescuer can serve other bdis too. This preserves the flusher
creation failure behavior of the forker thread.
* INIT_LIST_HEAD(&bdi->bdi_list) is used to tell
bdi_writeback_workfn() about on-going bdi unregistration so that it
always drains work_list even if it's running off the rescuer. Note
that the original code was broken in this regard. Under memory
pressure, a bdi could finish unregistration with non-empty
work_list.
* The default bdi is no longer special. It now is treated the same as
any other bdi and bdi_cap_flush_forker() is removed.
* BDI_pending is no longer used. Removed.
* Some tracepoints become non-applicable. The following TPs are
removed - writeback_nothread, writeback_wake_thread,
writeback_wake_forker_thread, writeback_thread_start,
writeback_thread_stop.
Everything, including devices coming and going away and rescuer
operation under simulated memory pressure, seems to work fine in my
test setup.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
2013-04-02 10:08:06 +08:00
|
|
|
current->flags &= ~PF_SWAPWRITE;
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-09 00:15:07 +08:00
|
|
|
* Start writeback of `nr_pages' pages. If `nr_pages' is zero, write back
|
|
|
|
* the whole world.
|
2009-09-09 15:08:54 +08:00
|
|
|
*/
|
2011-10-08 11:54:10 +08:00
|
|
|
void wakeup_flusher_threads(long nr_pages, enum wb_reason reason)
|
2009-09-09 15:08:54 +08:00
|
|
|
{
|
2010-06-09 00:15:07 +08:00
|
|
|
struct backing_dev_info *bdi;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2013-09-12 05:22:22 +08:00
|
|
|
if (!nr_pages)
|
|
|
|
nr_pages = get_nr_dirty_pages();
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2010-06-09 00:15:07 +08:00
|
|
|
rcu_read_lock();
|
2015-05-23 05:13:55 +08:00
|
|
|
list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
|
|
|
|
struct bdi_writeback *wb;
|
|
|
|
struct wb_iter iter;
|
|
|
|
|
|
|
|
if (!bdi_has_dirty_io(bdi))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bdi_for_each_wb(wb, bdi, &iter, 0)
|
|
|
|
wb_start_writeback(wb, wb_split_bdi_pages(wb, nr_pages),
|
|
|
|
false, reason);
|
|
|
|
}
|
2009-09-14 19:12:40 +08:00
|
|
|
rcu_read_unlock();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-03-18 00:23:19 +08:00
|
|
|
/*
|
|
|
|
* Wake up bdi's periodically to make sure dirtytime inodes gets
|
|
|
|
* written back periodically. We deliberately do *not* check the
|
|
|
|
* b_dirtytime list in wb_has_dirty_io(), since this would cause the
|
|
|
|
* kernel to be constantly waking up once there are any dirtytime
|
|
|
|
* inodes on the system. So instead we define a separate delayed work
|
|
|
|
* function which gets called much more rarely. (By default, only
|
|
|
|
* once every 12 hours.)
|
|
|
|
*
|
|
|
|
* If there is any other write activity going on in the file system,
|
|
|
|
* this function won't be necessary. But if the only thing that has
|
|
|
|
* happened on the file system is a dirtytime inode caused by an atime
|
|
|
|
* update, we need this infrastructure below to make sure that inode
|
|
|
|
* eventually gets pushed out to disk.
|
|
|
|
*/
|
|
|
|
static void wakeup_dirtytime_writeback(struct work_struct *w);
|
|
|
|
static DECLARE_DELAYED_WORK(dirtytime_work, wakeup_dirtytime_writeback);
|
|
|
|
|
|
|
|
static void wakeup_dirtytime_writeback(struct work_struct *w)
|
|
|
|
{
|
|
|
|
struct backing_dev_info *bdi;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
|
2015-05-23 05:13:56 +08:00
|
|
|
struct bdi_writeback *wb;
|
|
|
|
struct wb_iter iter;
|
|
|
|
|
|
|
|
bdi_for_each_wb(wb, bdi, &iter, 0)
|
|
|
|
if (!list_empty(&bdi->wb.b_dirty_time))
|
|
|
|
wb_wakeup(&bdi->wb);
|
2015-03-18 00:23:19 +08:00
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init start_dirtytime_writeback(void)
|
|
|
|
{
|
|
|
|
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
__initcall(start_dirtytime_writeback);
|
|
|
|
|
2015-03-18 00:23:32 +08:00
|
|
|
int dirtytime_interval_handler(struct ctl_table *table, int write,
|
|
|
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
|
|
if (ret == 0 && write)
|
|
|
|
mod_delayed_work(system_wq, &dirtytime_work, 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
static noinline void block_dump___mark_inode_dirty(struct inode *inode)
|
|
|
|
{
|
|
|
|
if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
|
|
|
|
struct dentry *dentry;
|
|
|
|
const char *name = "?";
|
|
|
|
|
|
|
|
dentry = d_find_alias(inode);
|
|
|
|
if (dentry) {
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
name = (const char *) dentry->d_name.name;
|
|
|
|
}
|
|
|
|
printk(KERN_DEBUG
|
|
|
|
"%s(%d): dirtied inode %lu (%s) on %s\n",
|
|
|
|
current->comm, task_pid_nr(current), inode->i_ino,
|
|
|
|
name, inode->i_sb->s_id);
|
|
|
|
if (dentry) {
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
dput(dentry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* __mark_inode_dirty - internal function
|
|
|
|
* @inode: inode to mark
|
|
|
|
* @flags: what kind of dirty (i.e. I_DIRTY_SYNC)
|
|
|
|
* Mark an inode as dirty. Callers should use mark_inode_dirty or
|
|
|
|
* mark_inode_dirty_sync.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
2009-09-09 15:08:54 +08:00
|
|
|
* Put the inode on the super block's dirty list.
|
|
|
|
*
|
|
|
|
* CAREFUL! We mark it dirty unconditionally, but move it onto the
|
|
|
|
* dirty list only if it is hashed or if it refers to a blockdev.
|
|
|
|
* If it was not hashed, it will never be added to the dirty list
|
|
|
|
* even if it is later hashed, as it will have been marked dirty already.
|
|
|
|
*
|
|
|
|
* In short, make sure you hash any inodes _before_ you start marking
|
|
|
|
* them dirty.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
2009-09-09 15:08:54 +08:00
|
|
|
* Note that for blockdevs, inode->dirtied_when represents the dirtying time of
|
|
|
|
* the block-special inode (/dev/hda1) itself. And the ->dirtied_when field of
|
|
|
|
* the kernel-internal blockdev inode represents the dirtying time of the
|
|
|
|
* blockdev's pages. This is why for I_DIRTY_PAGES we always use
|
|
|
|
* page->mapping->host, so the page-dirtying time is recorded in the internal
|
|
|
|
* blockdev inode.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2015-02-02 13:37:00 +08:00
|
|
|
#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
|
2009-09-09 15:08:54 +08:00
|
|
|
void __mark_inode_dirty(struct inode *inode, int flags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2009-09-09 15:08:54 +08:00
|
|
|
struct super_block *sb = inode->i_sb;
|
2015-02-02 13:37:00 +08:00
|
|
|
int dirtytime;
|
|
|
|
|
|
|
|
trace_writeback_mark_inode_dirty(inode, flags);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
/*
|
|
|
|
* Don't do this for I_DIRTY_PAGES - that doesn't actually
|
|
|
|
* dirty the inode itself
|
|
|
|
*/
|
2015-02-02 13:37:00 +08:00
|
|
|
if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_TIME)) {
|
2013-01-12 05:06:37 +08:00
|
|
|
trace_writeback_dirty_inode_start(inode, flags);
|
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
if (sb->s_op->dirty_inode)
|
2011-05-27 18:53:02 +08:00
|
|
|
sb->s_op->dirty_inode(inode, flags);
|
2013-01-12 05:06:37 +08:00
|
|
|
|
|
|
|
trace_writeback_dirty_inode(inode, flags);
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
2015-02-02 13:37:00 +08:00
|
|
|
if (flags & I_DIRTY_INODE)
|
|
|
|
flags &= ~I_DIRTY_TIME;
|
|
|
|
dirtytime = flags & I_DIRTY_TIME;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
/*
|
2014-10-25 03:38:21 +08:00
|
|
|
* Paired with smp_mb() in __writeback_single_inode() for the
|
|
|
|
* following lockless i_state test. See there for details.
|
2009-09-09 15:08:54 +08:00
|
|
|
*/
|
|
|
|
smp_mb();
|
|
|
|
|
2015-02-02 13:37:00 +08:00
|
|
|
if (((inode->i_state & flags) == flags) ||
|
|
|
|
(dirtytime && (inode->i_state & I_DIRTY_INODE)))
|
2009-09-09 15:08:54 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (unlikely(block_dump))
|
|
|
|
block_dump___mark_inode_dirty(inode);
|
|
|
|
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
2015-02-02 13:37:00 +08:00
|
|
|
if (dirtytime && (inode->i_state & I_DIRTY_INODE))
|
|
|
|
goto out_unlock_inode;
|
2009-09-09 15:08:54 +08:00
|
|
|
if ((inode->i_state & flags) != flags) {
|
|
|
|
const int was_dirty = inode->i_state & I_DIRTY;
|
|
|
|
|
2015-05-23 05:13:37 +08:00
|
|
|
inode_attach_wb(inode, NULL);
|
|
|
|
|
2015-02-02 13:37:00 +08:00
|
|
|
if (flags & I_DIRTY_INODE)
|
|
|
|
inode->i_state &= ~I_DIRTY_TIME;
|
2009-09-09 15:08:54 +08:00
|
|
|
inode->i_state |= flags;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the inode is being synced, just update its dirty state.
|
|
|
|
* The unlocker will place the inode on the appropriate
|
|
|
|
* superblock list, based upon its state.
|
|
|
|
*/
|
|
|
|
if (inode->i_state & I_SYNC)
|
2011-03-22 19:23:36 +08:00
|
|
|
goto out_unlock_inode;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Only add valid (hashed) inodes to the superblock's
|
|
|
|
* dirty list. Add blockdev inodes as well.
|
|
|
|
*/
|
|
|
|
if (!S_ISBLK(inode->i_mode)) {
|
2010-10-24 03:19:20 +08:00
|
|
|
if (inode_unhashed(inode))
|
2011-03-22 19:23:36 +08:00
|
|
|
goto out_unlock_inode;
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
2010-06-03 05:38:30 +08:00
|
|
|
if (inode->i_state & I_FREEING)
|
2011-03-22 19:23:36 +08:00
|
|
|
goto out_unlock_inode;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the inode was already on b_dirty/b_io/b_more_io, don't
|
|
|
|
* reposition it (that would break b_dirty time-ordering).
|
|
|
|
*/
|
|
|
|
if (!was_dirty) {
|
2015-05-29 02:50:52 +08:00
|
|
|
struct bdi_writeback *wb;
|
2015-05-23 05:13:45 +08:00
|
|
|
struct list_head *dirty_list;
|
2011-03-22 19:23:41 +08:00
|
|
|
bool wakeup_bdi = false;
|
2010-07-25 19:29:21 +08:00
|
|
|
|
2015-05-29 02:50:52 +08:00
|
|
|
wb = locked_inode_to_wb_and_lock_list(inode);
|
2010-07-25 19:29:21 +08:00
|
|
|
|
2015-05-23 05:14:02 +08:00
|
|
|
WARN(bdi_cap_writeback_dirty(wb->bdi) &&
|
|
|
|
!test_bit(WB_registered, &wb->state),
|
|
|
|
"bdi-%s not registered\n", wb->bdi->name);
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
inode->dirtied_when = jiffies;
|
2015-03-18 00:23:19 +08:00
|
|
|
if (dirtytime)
|
|
|
|
inode->dirtied_time_when = jiffies;
|
2015-05-23 05:13:45 +08:00
|
|
|
|
2015-03-18 00:23:19 +08:00
|
|
|
if (inode->i_state & (I_DIRTY_INODE | I_DIRTY_PAGES))
|
2015-05-23 05:14:02 +08:00
|
|
|
dirty_list = &wb->b_dirty;
|
2015-03-18 00:23:19 +08:00
|
|
|
else
|
2015-05-23 05:14:02 +08:00
|
|
|
dirty_list = &wb->b_dirty_time;
|
2015-05-23 05:13:45 +08:00
|
|
|
|
2015-05-23 05:14:02 +08:00
|
|
|
wakeup_bdi = inode_wb_list_move_locked(inode, wb,
|
2015-05-23 05:13:45 +08:00
|
|
|
dirty_list);
|
|
|
|
|
2015-05-23 05:14:02 +08:00
|
|
|
spin_unlock(&wb->list_lock);
|
2015-02-02 13:37:00 +08:00
|
|
|
trace_writeback_dirty_inode_enqueue(inode);
|
2011-03-22 19:23:41 +08:00
|
|
|
|
2015-05-23 05:13:45 +08:00
|
|
|
/*
|
|
|
|
* If this is the first dirty inode for this bdi,
|
|
|
|
* we have to wake-up the corresponding bdi thread
|
|
|
|
* to make sure background write-back happens
|
|
|
|
* later.
|
|
|
|
*/
|
2015-05-23 05:14:02 +08:00
|
|
|
if (bdi_cap_writeback_dirty(wb->bdi) && wakeup_bdi)
|
|
|
|
wb_wakeup_delayed(wb);
|
2011-03-22 19:23:41 +08:00
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2011-03-22 19:23:36 +08:00
|
|
|
out_unlock_inode:
|
|
|
|
spin_unlock(&inode->i_lock);
|
2010-07-25 19:29:21 +08:00
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__mark_inode_dirty);
|
|
|
|
|
2009-09-16 21:13:54 +08:00
|
|
|
static void wait_sb_inodes(struct super_block *sb)
|
2009-09-09 15:08:54 +08:00
|
|
|
{
|
|
|
|
struct inode *inode, *old_inode = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We need to be protected against the filesystem going from
|
|
|
|
* r/o to r/w or vice versa.
|
|
|
|
*/
|
2009-09-16 21:13:54 +08:00
|
|
|
WARN_ON(!rwsem_is_locked(&sb->s_umount));
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2011-03-22 19:23:40 +08:00
|
|
|
spin_lock(&inode_sb_list_lock);
|
2009-09-09 15:08:54 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Data integrity sync. Must wait for all pages under writeback,
|
|
|
|
* because there may have been pages dirtied before our sync
|
|
|
|
* call, but which had writeout started before we write it out.
|
|
|
|
* In which case, the inode may not be on the dirty list, but
|
|
|
|
* we still have to wait for that writeout.
|
|
|
|
*/
|
2009-09-16 21:13:54 +08:00
|
|
|
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
|
2011-03-22 19:23:36 +08:00
|
|
|
struct address_space *mapping = inode->i_mapping;
|
2009-09-09 15:08:54 +08:00
|
|
|
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
|
|
|
|
(mapping->nrpages == 0)) {
|
|
|
|
spin_unlock(&inode->i_lock);
|
2009-09-09 15:08:54 +08:00
|
|
|
continue;
|
2011-03-22 19:23:36 +08:00
|
|
|
}
|
2009-09-09 15:08:54 +08:00
|
|
|
__iget(inode);
|
2011-03-22 19:23:36 +08:00
|
|
|
spin_unlock(&inode->i_lock);
|
2011-03-22 19:23:40 +08:00
|
|
|
spin_unlock(&inode_sb_list_lock);
|
|
|
|
|
2009-09-09 15:08:54 +08:00
|
|
|
/*
|
2011-03-22 19:23:40 +08:00
|
|
|
* We hold a reference to 'inode' so it couldn't have been
|
|
|
|
* removed from s_inodes list while we dropped the
|
|
|
|
* inode_sb_list_lock. We cannot iput the inode now as we can
|
|
|
|
* be holding the last reference and we cannot iput it under
|
|
|
|
* inode_sb_list_lock. So we keep the reference and iput it
|
|
|
|
* later.
|
2009-09-09 15:08:54 +08:00
|
|
|
*/
|
|
|
|
iput(old_inode);
|
|
|
|
old_inode = inode;
|
|
|
|
|
|
|
|
filemap_fdatawait(mapping);
|
|
|
|
|
|
|
|
cond_resched();
|
|
|
|
|
2011-03-22 19:23:40 +08:00
|
|
|
spin_lock(&inode_sb_list_lock);
|
2009-09-09 15:08:54 +08:00
|
|
|
}
|
2011-03-22 19:23:40 +08:00
|
|
|
spin_unlock(&inode_sb_list_lock);
|
2009-09-09 15:08:54 +08:00
|
|
|
iput(old_inode);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-05-23 05:14:00 +08:00
|
|
|
static void __writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr,
|
|
|
|
enum wb_reason reason, bool skip_if_busy)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2015-05-23 05:13:58 +08:00
|
|
|
DEFINE_WB_COMPLETION_ONSTACK(done);
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work work = {
|
2010-06-07 00:38:15 +08:00
|
|
|
.sb = sb,
|
|
|
|
.sync_mode = WB_SYNC_NONE,
|
|
|
|
.tagged_writepages = 1,
|
|
|
|
.done = &done,
|
|
|
|
.nr_pages = nr,
|
2011-10-08 11:54:10 +08:00
|
|
|
.reason = reason,
|
2010-06-09 00:14:43 +08:00
|
|
|
};
|
2015-05-23 05:13:48 +08:00
|
|
|
struct backing_dev_info *bdi = sb->s_bdi;
|
2009-09-02 18:34:32 +08:00
|
|
|
|
2015-05-23 05:13:48 +08:00
|
|
|
if (!bdi_has_dirty_io(bdi) || bdi == &noop_backing_dev_info)
|
2012-07-03 22:45:27 +08:00
|
|
|
return;
|
2010-06-09 00:14:51 +08:00
|
|
|
WARN_ON(!rwsem_is_locked(&sb->s_umount));
|
2015-05-23 05:14:00 +08:00
|
|
|
|
2015-05-23 05:14:01 +08:00
|
|
|
bdi_split_work_to_wbs(sb->s_bdi, &work, skip_if_busy);
|
2015-05-23 05:13:58 +08:00
|
|
|
wb_wait_for_completion(bdi, &done);
|
2010-05-17 18:55:07 +08:00
|
|
|
}
|
2015-05-23 05:14:00 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* writeback_inodes_sb_nr - writeback dirty inodes from given super_block
|
|
|
|
* @sb: the superblock
|
|
|
|
* @nr: the number of pages to write
|
|
|
|
* @reason: reason why some writeback work initiated
|
|
|
|
*
|
|
|
|
* Start writeback on some inodes on this super_block. No guarantees are made
|
|
|
|
* 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,
|
|
|
|
enum wb_reason reason)
|
|
|
|
{
|
|
|
|
__writeback_inodes_sb_nr(sb, nr, reason, false);
|
|
|
|
}
|
2010-10-29 23:16:17 +08:00
|
|
|
EXPORT_SYMBOL(writeback_inodes_sb_nr);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* writeback_inodes_sb - writeback dirty inodes from given super_block
|
|
|
|
* @sb: the superblock
|
2011-11-23 20:56:45 +08:00
|
|
|
* @reason: reason why some writeback work was initiated
|
2010-10-29 23:16:17 +08:00
|
|
|
*
|
|
|
|
* Start writeback on some inodes on this super_block. No guarantees are made
|
|
|
|
* on how many (if any) will be written, and this function does not wait
|
|
|
|
* for IO completion of submitted IO.
|
|
|
|
*/
|
2011-10-08 11:54:10 +08:00
|
|
|
void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason)
|
2010-10-29 23:16:17 +08:00
|
|
|
{
|
2011-10-08 11:54:10 +08:00
|
|
|
return writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason);
|
2010-10-29 23:16:17 +08:00
|
|
|
}
|
2010-06-01 17:08:43 +08:00
|
|
|
EXPORT_SYMBOL(writeback_inodes_sb);
|
2010-05-17 18:55:07 +08:00
|
|
|
|
2009-12-23 20:57:07 +08:00
|
|
|
/**
|
2013-01-10 13:47:57 +08:00
|
|
|
* try_to_writeback_inodes_sb_nr - try to start writeback if none underway
|
2009-12-23 20:57:07 +08:00
|
|
|
* @sb: the superblock
|
2013-01-10 13:47:57 +08:00
|
|
|
* @nr: the number of pages to write
|
|
|
|
* @reason: the reason of writeback
|
2009-12-23 20:57:07 +08:00
|
|
|
*
|
2013-01-10 13:47:57 +08:00
|
|
|
* Invoke writeback_inodes_sb_nr if no writeback is currently underway.
|
2009-12-23 20:57:07 +08:00
|
|
|
* Returns 1 if writeback was started, 0 if not.
|
|
|
|
*/
|
2015-05-23 05:14:00 +08:00
|
|
|
bool try_to_writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr,
|
|
|
|
enum wb_reason reason)
|
2009-12-23 20:57:07 +08:00
|
|
|
{
|
2013-01-10 13:47:57 +08:00
|
|
|
if (!down_read_trylock(&sb->s_umount))
|
2015-05-23 05:14:00 +08:00
|
|
|
return false;
|
2013-01-10 13:47:57 +08:00
|
|
|
|
2015-05-23 05:14:00 +08:00
|
|
|
__writeback_inodes_sb_nr(sb, nr, reason, true);
|
2013-01-10 13:47:57 +08:00
|
|
|
up_read(&sb->s_umount);
|
2015-05-23 05:14:00 +08:00
|
|
|
return true;
|
2009-12-23 20:57:07 +08:00
|
|
|
}
|
2013-01-10 13:47:57 +08:00
|
|
|
EXPORT_SYMBOL(try_to_writeback_inodes_sb_nr);
|
2009-12-23 20:57:07 +08:00
|
|
|
|
2010-10-29 23:16:17 +08:00
|
|
|
/**
|
2013-01-10 13:47:57 +08:00
|
|
|
* try_to_writeback_inodes_sb - try to start writeback if none underway
|
2010-10-29 23:16:17 +08:00
|
|
|
* @sb: the superblock
|
2011-11-23 20:56:45 +08:00
|
|
|
* @reason: reason why some writeback work was initiated
|
2010-10-29 23:16:17 +08:00
|
|
|
*
|
2013-01-10 13:47:57 +08:00
|
|
|
* Implement by try_to_writeback_inodes_sb_nr()
|
2010-10-29 23:16:17 +08:00
|
|
|
* Returns 1 if writeback was started, 0 if not.
|
|
|
|
*/
|
2015-05-23 05:14:00 +08:00
|
|
|
bool try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason)
|
2010-10-29 23:16:17 +08:00
|
|
|
{
|
2013-01-10 13:47:57 +08:00
|
|
|
return try_to_writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason);
|
2010-10-29 23:16:17 +08:00
|
|
|
}
|
2013-01-10 13:47:57 +08:00
|
|
|
EXPORT_SYMBOL(try_to_writeback_inodes_sb);
|
2010-10-29 23:16:17 +08:00
|
|
|
|
2009-09-02 18:34:32 +08:00
|
|
|
/**
|
|
|
|
* sync_inodes_sb - sync sb inode pages
|
2014-02-21 18:19:04 +08:00
|
|
|
* @sb: the superblock
|
2009-09-02 18:34:32 +08:00
|
|
|
*
|
|
|
|
* This function writes and waits on any dirty inode belonging to this
|
2014-02-21 18:19:04 +08:00
|
|
|
* super_block.
|
2009-09-02 18:34:32 +08:00
|
|
|
*/
|
2014-02-21 18:19:04 +08:00
|
|
|
void sync_inodes_sb(struct super_block *sb)
|
2009-09-02 18:34:32 +08:00
|
|
|
{
|
2015-05-23 05:13:58 +08:00
|
|
|
DEFINE_WB_COMPLETION_ONSTACK(done);
|
2010-07-06 14:59:53 +08:00
|
|
|
struct wb_writeback_work work = {
|
2010-06-09 00:14:43 +08:00
|
|
|
.sb = sb,
|
|
|
|
.sync_mode = WB_SYNC_ALL,
|
|
|
|
.nr_pages = LONG_MAX,
|
|
|
|
.range_cyclic = 0,
|
2010-07-06 14:59:53 +08:00
|
|
|
.done = &done,
|
2011-10-08 11:54:10 +08:00
|
|
|
.reason = WB_REASON_SYNC,
|
2013-07-02 20:38:35 +08:00
|
|
|
.for_sync = 1,
|
2010-06-09 00:14:43 +08:00
|
|
|
};
|
2015-05-23 05:13:48 +08:00
|
|
|
struct backing_dev_info *bdi = sb->s_bdi;
|
2010-06-09 00:14:43 +08:00
|
|
|
|
2012-07-03 22:45:27 +08:00
|
|
|
/* Nothing to do? */
|
2015-05-23 05:13:48 +08:00
|
|
|
if (!bdi_has_dirty_io(bdi) || bdi == &noop_backing_dev_info)
|
2012-07-03 22:45:27 +08:00
|
|
|
return;
|
2010-06-09 00:14:51 +08:00
|
|
|
WARN_ON(!rwsem_is_locked(&sb->s_umount));
|
|
|
|
|
2015-05-23 05:14:01 +08:00
|
|
|
bdi_split_work_to_wbs(bdi, &work, false);
|
2015-05-23 05:13:58 +08:00
|
|
|
wb_wait_for_completion(bdi, &done);
|
2010-07-06 14:59:53 +08:00
|
|
|
|
2009-09-16 21:13:54 +08:00
|
|
|
wait_sb_inodes(sb);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2009-09-02 18:34:32 +08:00
|
|
|
EXPORT_SYMBOL(sync_inodes_sb);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/**
|
[PATCH] fix nr_unused accounting, and avoid recursing in iput with I_WILL_FREE set
list_move(&inode->i_list, &inode_in_use);
} else {
list_move(&inode->i_list, &inode_unused);
+ inodes_stat.nr_unused++;
}
}
wake_up_inode(inode);
Are you sure the above diff is correct? It was added somewhere between
2.6.5 and 2.6.8. I think it's wrong.
The only way I can imagine the i_count to be zero in the above path, is
that I_WILL_FREE is set. And if I_WILL_FREE is set, then we must not
increase nr_unused. So I believe the above change is buggy and it will
definitely overstate the number of unused inodes and it should be backed
out.
Note that __writeback_single_inode before calling __sync_single_inode, can
drop the spinlock and we can have both the dirty and locked bitflags clear
here:
spin_unlock(&inode_lock);
__wait_on_inode(inode);
iput(inode);
XXXXXXX
spin_lock(&inode_lock);
}
use inode again here
a construct like the above makes zero sense from a reference counting
standpoint.
Either we don't ever use the inode again after the iput, or the
inode_lock should be taken _before_ executing the iput (i.e. a __iput
would be required). Taking the inode_lock after iput means the iget was
useless if we keep using the inode after the iput.
So the only chance the 2.6 was safe to call __writeback_single_inode
with the i_count == 0, is that I_WILL_FREE is set (I_WILL_FREE will
prevent the VM to free the inode in XXXXX).
Potentially calling the above iput with I_WILL_FREE was also wrong
because it would recurse in iput_final (the second mainline bug).
The below (untested) patch fixes the nr_unused accounting, avoids recursing
in iput when I_WILL_FREE is set and makes sure (with the BUG_ON) that we
don't corrupt memory and that all holders that don't set I_WILL_FREE, keeps
a reference on the inode!
Signed-off-by: Andrea Arcangeli <andrea@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-10-31 07:03:05 +08:00
|
|
|
* write_inode_now - write an inode to disk
|
|
|
|
* @inode: inode to write to disk
|
|
|
|
* @sync: whether the write should be synchronous or not
|
|
|
|
*
|
|
|
|
* This function commits an inode to disk immediately if it is dirty. This is
|
|
|
|
* primarily needed by knfsd.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
[PATCH] fix nr_unused accounting, and avoid recursing in iput with I_WILL_FREE set
list_move(&inode->i_list, &inode_in_use);
} else {
list_move(&inode->i_list, &inode_unused);
+ inodes_stat.nr_unused++;
}
}
wake_up_inode(inode);
Are you sure the above diff is correct? It was added somewhere between
2.6.5 and 2.6.8. I think it's wrong.
The only way I can imagine the i_count to be zero in the above path, is
that I_WILL_FREE is set. And if I_WILL_FREE is set, then we must not
increase nr_unused. So I believe the above change is buggy and it will
definitely overstate the number of unused inodes and it should be backed
out.
Note that __writeback_single_inode before calling __sync_single_inode, can
drop the spinlock and we can have both the dirty and locked bitflags clear
here:
spin_unlock(&inode_lock);
__wait_on_inode(inode);
iput(inode);
XXXXXXX
spin_lock(&inode_lock);
}
use inode again here
a construct like the above makes zero sense from a reference counting
standpoint.
Either we don't ever use the inode again after the iput, or the
inode_lock should be taken _before_ executing the iput (i.e. a __iput
would be required). Taking the inode_lock after iput means the iget was
useless if we keep using the inode after the iput.
So the only chance the 2.6 was safe to call __writeback_single_inode
with the i_count == 0, is that I_WILL_FREE is set (I_WILL_FREE will
prevent the VM to free the inode in XXXXX).
Potentially calling the above iput with I_WILL_FREE was also wrong
because it would recurse in iput_final (the second mainline bug).
The below (untested) patch fixes the nr_unused accounting, avoids recursing
in iput when I_WILL_FREE is set and makes sure (with the BUG_ON) that we
don't corrupt memory and that all holders that don't set I_WILL_FREE, keeps
a reference on the inode!
Signed-off-by: Andrea Arcangeli <andrea@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-10-31 07:03:05 +08:00
|
|
|
* The caller must either have a ref on the inode or must have set I_WILL_FREE.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
int write_inode_now(struct inode *inode, int sync)
|
|
|
|
{
|
2011-04-22 08:19:44 +08:00
|
|
|
struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct writeback_control wbc = {
|
|
|
|
.nr_to_write = LONG_MAX,
|
2008-02-08 20:20:23 +08:00
|
|
|
.sync_mode = sync ? WB_SYNC_ALL : WB_SYNC_NONE,
|
[PATCH] writeback: fix range handling
When a writeback_control's `start' and `end' fields are used to
indicate a one-byte-range starting at file offset zero, the required
values of .start=0,.end=0 mean that the ->writepages() implementation
has no way of telling that it is being asked to perform a range
request. Because we're currently overloading (start == 0 && end == 0)
to mean "this is not a write-a-range request".
To make all this sane, the patch changes range of writeback_control.
So caller does: If it is calling ->writepages() to write pages, it
sets range (range_start/end or range_cyclic) always.
And if range_cyclic is true, ->writepages() thinks the range is
cyclic, otherwise it just uses range_start and range_end.
This patch does,
- Add LLONG_MAX, LLONG_MIN, ULLONG_MAX to include/linux/kernel.h
-1 is usually ok for range_end (type is long long). But, if someone did,
range_end += val; range_end is "val - 1"
u64val = range_end >> bits; u64val is "~(0ULL)"
or something, they are wrong. So, this adds LLONG_MAX to avoid nasty
things, and uses LLONG_MAX for range_end.
- All callers of ->writepages() sets range_start/end or range_cyclic.
- Fix updates of ->writeback_index. It seems already bit strange.
If it starts at 0 and ended by check of nr_to_write, this last
index may reduce chance to scan end of file. So, this updates
->writeback_index only if range_cyclic is true or whole-file is
scanned.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Nathan Scott <nathans@sgi.com>
Cc: Anton Altaparmakov <aia21@cantab.net>
Cc: Steven French <sfrench@us.ibm.com>
Cc: "Vladimir V. Saveliev" <vs@namesys.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-23 17:03:26 +08:00
|
|
|
.range_start = 0,
|
|
|
|
.range_end = LLONG_MAX,
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
if (!mapping_cap_writeback_dirty(inode->i_mapping))
|
2005-11-07 16:59:15 +08:00
|
|
|
wbc.nr_to_write = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
might_sleep();
|
2012-05-03 20:48:00 +08:00
|
|
|
return writeback_single_inode(inode, wb, &wbc);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(write_inode_now);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sync_inode - write an inode and its pages to disk.
|
|
|
|
* @inode: the inode to sync
|
|
|
|
* @wbc: controls the writeback mode
|
|
|
|
*
|
|
|
|
* sync_inode() will write an inode and its pages to disk. It will also
|
|
|
|
* correctly update the inode on its superblock's dirty inode lists and will
|
|
|
|
* update inode->i_state.
|
|
|
|
*
|
|
|
|
* The caller must have a ref on the inode.
|
|
|
|
*/
|
|
|
|
int sync_inode(struct inode *inode, struct writeback_control *wbc)
|
|
|
|
{
|
2012-05-03 20:48:00 +08:00
|
|
|
return writeback_single_inode(inode, &inode_to_bdi(inode)->wb, wbc);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(sync_inode);
|
2010-10-06 16:48:20 +08:00
|
|
|
|
|
|
|
/**
|
2011-01-14 07:45:48 +08:00
|
|
|
* sync_inode_metadata - write an inode to disk
|
2010-10-06 16:48:20 +08:00
|
|
|
* @inode: the inode to sync
|
|
|
|
* @wait: wait for I/O to complete.
|
|
|
|
*
|
2011-01-14 07:45:48 +08:00
|
|
|
* Write an inode to disk and adjust its dirty state after completion.
|
2010-10-06 16:48:20 +08:00
|
|
|
*
|
|
|
|
* Note: only writes the actual inode, no associated data or other metadata.
|
|
|
|
*/
|
|
|
|
int sync_inode_metadata(struct inode *inode, int wait)
|
|
|
|
{
|
|
|
|
struct writeback_control wbc = {
|
|
|
|
.sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_NONE,
|
|
|
|
.nr_to_write = 0, /* metadata-only */
|
|
|
|
};
|
|
|
|
|
|
|
|
return sync_inode(inode, &wbc);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(sync_inode_metadata);
|