diff options
Diffstat (limited to 'mm/backing-dev.c')
| -rw-r--r-- | mm/backing-dev.c | 84 | 
1 files changed, 25 insertions, 59 deletions
| diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 4a9d4e27d0d9..1eead4761011 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -2,8 +2,9 @@  #include <linux/wait.h>  #include <linux/rbtree.h> -#include <linux/backing-dev.h>  #include <linux/kthread.h> +#include <linux/backing-dev.h> +#include <linux/blk-cgroup.h>  #include <linux/freezer.h>  #include <linux/fs.h>  #include <linux/pagemap.h> @@ -291,8 +292,6 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,  	memset(wb, 0, sizeof(*wb)); -	if (wb != &bdi->wb) -		bdi_get(bdi);  	wb->bdi = bdi;  	wb->last_old_flush = jiffies;  	INIT_LIST_HEAD(&wb->b_dirty); @@ -316,7 +315,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,  	err = fprop_local_init_percpu(&wb->completions, gfp);  	if (err) -		goto out_put_bdi; +		return err;  	for (i = 0; i < NR_WB_STAT_ITEMS; i++) {  		err = percpu_counter_init(&wb->stat[i], 0, gfp); @@ -330,9 +329,6 @@ out_destroy_stat:  	while (i--)  		percpu_counter_destroy(&wb->stat[i]);  	fprop_local_destroy_percpu(&wb->completions); -out_put_bdi: -	if (wb != &bdi->wb) -		bdi_put(bdi);  	return err;  } @@ -373,8 +369,6 @@ static void wb_exit(struct bdi_writeback *wb)  		percpu_counter_destroy(&wb->stat[i]);  	fprop_local_destroy_percpu(&wb->completions); -	if (wb != &wb->bdi->wb) -		bdi_put(wb->bdi);  }  #ifdef CONFIG_CGROUP_WRITEBACK @@ -397,6 +391,7 @@ static void cgwb_release_workfn(struct work_struct *work)  	struct bdi_writeback *wb = container_of(work, struct bdi_writeback,  						release_work);  	struct blkcg *blkcg = css_to_blkcg(wb->blkcg_css); +	struct backing_dev_info *bdi = wb->bdi;  	mutex_lock(&wb->bdi->cgwb_release_mutex);  	wb_shutdown(wb); @@ -416,6 +411,7 @@ static void cgwb_release_workfn(struct work_struct *work)  	percpu_ref_exit(&wb->refcnt);  	wb_exit(wb); +	bdi_put(bdi);  	WARN_ON_ONCE(!list_empty(&wb->b_attached));  	kfree_rcu(wb, rcu);  } @@ -497,6 +493,7 @@ static int cgwb_create(struct backing_dev_info *bdi,  	INIT_LIST_HEAD(&wb->b_attached);  	INIT_WORK(&wb->release_work, cgwb_release_workfn);  	set_bit(WB_registered, &wb->state); +	bdi_get(bdi);  	/*  	 * The root wb determines the registered state of the whole bdi and @@ -528,6 +525,7 @@ static int cgwb_create(struct backing_dev_info *bdi,  	goto out_put;  err_fprop_exit: +	bdi_put(bdi);  	fprop_local_destroy_percpu(&wb->memcg_completions);  err_ref_exit:  	percpu_ref_exit(&wb->refcnt); @@ -958,14 +956,14 @@ void bdi_unregister(struct backing_dev_info *bdi)  		bdi->owner = NULL;  	}  } +EXPORT_SYMBOL(bdi_unregister);  static void release_bdi(struct kref *ref)  {  	struct backing_dev_info *bdi =  			container_of(ref, struct backing_dev_info, refcnt); -	if (test_bit(WB_registered, &bdi->wb.state)) -		bdi_unregister(bdi); +	WARN_ON_ONCE(test_bit(WB_registered, &bdi->wb.state));  	WARN_ON_ONCE(bdi->dev);  	wb_exit(&bdi->wb);  	kfree(bdi); @@ -977,6 +975,22 @@ void bdi_put(struct backing_dev_info *bdi)  }  EXPORT_SYMBOL(bdi_put); +struct backing_dev_info *inode_to_bdi(struct inode *inode) +{ +	struct super_block *sb; + +	if (!inode) +		return &noop_backing_dev_info; + +	sb = inode->i_sb; +#ifdef CONFIG_BLOCK +	if (sb_is_blkdev_sb(sb)) +		return I_BDEV(inode)->bd_disk->bdi; +#endif +	return sb->s_bdi; +} +EXPORT_SYMBOL(inode_to_bdi); +  const char *bdi_dev_name(struct backing_dev_info *bdi)  {  	if (!bdi || !bdi->dev) @@ -1041,51 +1055,3 @@ long congestion_wait(int sync, long timeout)  	return ret;  }  EXPORT_SYMBOL(congestion_wait); - -/** - * wait_iff_congested - Conditionally wait for a backing_dev to become uncongested or a pgdat to complete writes - * @sync: SYNC or ASYNC IO - * @timeout: timeout in jiffies - * - * In the event of a congested backing_dev (any backing_dev) this waits - * for up to @timeout jiffies for either a BDI to exit congestion of the - * given @sync queue or a write to complete. - * - * The return value is 0 if the sleep is for the full timeout. Otherwise, - * it is the number of jiffies that were still remaining when the function - * returned. return_value == timeout implies the function did not sleep. - */ -long wait_iff_congested(int sync, long timeout) -{ -	long ret; -	unsigned long start = jiffies; -	DEFINE_WAIT(wait); -	wait_queue_head_t *wqh = &congestion_wqh[sync]; - -	/* -	 * If there is no congestion, yield if necessary instead -	 * of sleeping on the congestion queue -	 */ -	if (atomic_read(&nr_wb_congested[sync]) == 0) { -		cond_resched(); - -		/* In case we scheduled, work out time remaining */ -		ret = timeout - (jiffies - start); -		if (ret < 0) -			ret = 0; - -		goto out; -	} - -	/* Sleep until uncongested or a write happens */ -	prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); -	ret = io_schedule_timeout(timeout); -	finish_wait(wqh, &wait); - -out: -	trace_writeback_wait_iff_congested(jiffies_to_usecs(timeout), -					jiffies_to_usecs(jiffies - start)); - -	return ret; -} -EXPORT_SYMBOL(wait_iff_congested); |