/*
* 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.
*
* 10Apr2002 Andrew Morton
* Split out of fs/inode.c
* Additions for address_space-based writeback
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
#include <linux/buffer_head.h>
#include "internal.h"
#define inode_to_bdi(inode) ((inode)->i_mapping->backing_dev_info)
/*
* We don't actually have pdflush, but this one is exported though /proc...
*/
int nr_pdflush_threads;
/*
* Passed into wb_writeback(), essentially a subset of writeback_control
*/
struct wb_writeback_args {
long nr_pages;
struct super_block *sb;
enum writeback_sync_modes sync_mode;
int for_kupdate;
int range_cyclic;
};
/*
* Work items for the bdi_writeback threads
*/
struct bdi_work {
struct list_head list; /* pending work list */
struct rcu_head rcu_head; /* for RCU free/clear of work */
unsigned long seen; /* threads that have seen this work */
atomic_t pending; /* number of threads still to do work */
struct wb_writeback_args args; /* writeback arguments */
unsigned long state; /* flag bits, see WS_* */
};
enum {
WS_USED_B = 0,
WS_ONSTACK_B,
};
#define WS_USED (1 << WS_USED_B)
#define WS_ONSTACK (1 << WS_ONSTACK_B)
static inline bool bdi_work_on_stack(struct bdi_work *work)
{
return test_bit(WS_ONSTACK_B, &work->state);
}
static inline void bdi_work_init(struct bdi_work *work,
struct wb_writeback_args *args)
{
INIT_RCU_HEAD(&work->rcu_head);
work->args = *args;
work->state = WS_USED;
}
/**
* writeback_in_progress - determine whether there is writeback in progress
* @bdi: the device's backing_dev_info structure.
*
* Determine whether there is writeback waiting to be handled against a
* backing device.
*/
int writeback_in_progress(struct backing_dev_info *bdi)
{
return !list_empty(&bdi->work_list);
}
static void bdi_work_clear(struct bdi_work *work)
{
clear_bit(WS_USED_B, &work->state);
smp_mb__after_clear_bit();
wake_up_bit(&work->state, WS_USED_B);
}
static void bdi_work_free(struct rcu_head *head)
{
struct bdi_work *work = container_of(head, struct bdi_work, rcu_head);
if (!bdi_work_on_stack(work))
kfree(work);
else
bdi_work_clear(work);
}
static void wb_work_complete(struct bdi_work *work)
{
const enum writeback_sync_modes sync_mode = work->args.sync_mode;
/*
* For allocated work, we can clear the done/seen bit right here.
* For on-stack work, we need to postpone both the clear and free
* to after the RCU grace period, since the stack could be invalidated
* as soon as bdi_work_clear() has done the wakeup.
*/
if (!bdi_work_on_stack(work))
bdi_work_clear(work);
if (sync_mode == WB_SYNC_NONE || bdi_work_on_stack(work))
call_rcu(&work->rcu_head, bdi_work_free);
}
static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work)
{
/*
* The caller has retrieved the work arguments from this work,
* drop our reference. If this is the last ref, delete and free it
*/
if (atomic_dec_and_test(&work->pending)) {