2006-10-20 10:28:16 +04:00
# include <linux/wait.h>
# include <linux/backing-dev.h>
# include <linux/fs.h>
# include <linux/sched.h>
# include <linux/module.h>
2007-10-17 10:25:47 +04:00
int bdi_init ( struct backing_dev_info * bdi )
{
int i , j ;
int err ;
for ( i = 0 ; i < NR_BDI_STAT_ITEMS ; i + + ) {
err = percpu_counter_init_irq ( & bdi - > bdi_stat [ i ] , 0 ) ;
2007-10-17 10:25:50 +04:00
if ( err )
goto err ;
}
bdi - > dirty_exceeded = 0 ;
err = prop_local_init_percpu ( & bdi - > completions ) ;
if ( err ) {
err :
for ( j = 0 ; j < i ; j + + )
percpu_counter_destroy ( & bdi - > bdi_stat [ i ] ) ;
2007-10-17 10:25:47 +04:00
}
return err ;
}
EXPORT_SYMBOL ( bdi_init ) ;
void bdi_destroy ( struct backing_dev_info * bdi )
{
int i ;
for ( i = 0 ; i < NR_BDI_STAT_ITEMS ; i + + )
percpu_counter_destroy ( & bdi - > bdi_stat [ i ] ) ;
2007-10-17 10:25:50 +04:00
prop_local_destroy_percpu ( & bdi - > completions ) ;
2007-10-17 10:25:47 +04:00
}
EXPORT_SYMBOL ( bdi_destroy ) ;
2006-10-20 10:28:16 +04:00
static wait_queue_head_t congestion_wqh [ 2 ] = {
__WAIT_QUEUE_HEAD_INITIALIZER ( congestion_wqh [ 0 ] ) ,
__WAIT_QUEUE_HEAD_INITIALIZER ( congestion_wqh [ 1 ] )
} ;
void clear_bdi_congested ( struct backing_dev_info * bdi , int rw )
{
enum bdi_state bit ;
wait_queue_head_t * wqh = & congestion_wqh [ rw ] ;
bit = ( rw = = WRITE ) ? BDI_write_congested : BDI_read_congested ;
clear_bit ( bit , & bdi - > state ) ;
smp_mb__after_clear_bit ( ) ;
if ( waitqueue_active ( wqh ) )
wake_up ( wqh ) ;
}
EXPORT_SYMBOL ( clear_bdi_congested ) ;
void set_bdi_congested ( struct backing_dev_info * bdi , int rw )
{
enum bdi_state bit ;
bit = ( rw = = WRITE ) ? BDI_write_congested : BDI_read_congested ;
set_bit ( bit , & bdi - > state ) ;
}
EXPORT_SYMBOL ( set_bdi_congested ) ;
/**
* congestion_wait - wait for a backing_dev to become uncongested
* @ rw : READ or WRITE
* @ timeout : timeout in jiffies
*
* Waits for up to @ timeout jiffies for a backing_dev ( any backing_dev ) to exit
* write congestion . If no backing_devs are congested then just wait for the
* next write to be completed .
*/
long congestion_wait ( int rw , long timeout )
{
long ret ;
DEFINE_WAIT ( wait ) ;
wait_queue_head_t * wqh = & congestion_wqh [ rw ] ;
prepare_to_wait ( wqh , & wait , TASK_UNINTERRUPTIBLE ) ;
ret = io_schedule_timeout ( timeout ) ;
finish_wait ( wqh , & wait ) ;
return ret ;
}
EXPORT_SYMBOL ( congestion_wait ) ;
2007-10-17 10:25:50 +04:00