这个在编程的时候常用。 一定搞清楚他们之间的关系。
struct page * buffer_page ;
unsigned long buffer_virt ;
buffer_virt = get_zeroed_page ( GFP_ATOMIC ) ) ) {
buffer_page = virt_to_page ( buffer_virt ) ;
unsigned long get_zeroed_page ( unsigned int gfp_mask )
{
struct page * page ;
page = alloc_pages ( gfp_mask , 0 ) ;
if ( page ) {
void * address = page_address ( page ) ;
clear_page ( address ) ;
return ( unsigned long ) address ;
}
return 0 ;
}
/*
* Common helper functions.
*/
unsigned long __get_free_pages ( unsigned int gfp_mask , unsigned int order )
{
struct page * page ;
page = alloc_pages ( gfp_mask , order ) ;
if ( ! page )
return 0 ;
return ( unsigned long ) page_address ( page ) ;
}
# define TryLockPage ( page ) test_and_set_bit ( PG_locked , & ( page ) - > flags )
# define PageChecked ( page ) test_bit ( PG_checked , & ( page ) - > flags )
# define SetPageChecked ( page ) set_bit ( PG_checked , & ( page ) - > flags )
# define PageLaunder ( page ) test_bit ( PG_launder , & ( page ) - > flags )
# define SetPageLaunder ( page ) set_bit ( PG_launder , & ( page ) - > flags )
# define ClearPageLaunder ( page ) clear_bit ( PG_launder , & ( page ) - > flags )
//关于调用wait函数的代码
/*
* Calling wait_on_buffer() for a zero-ref buffer is illegal, so we call into
* __wait_on_buffer() just to trip a debug check. Because debug code in inline
* functions is bloaty.
*/
static inline void wait_on_buffer ( struct buffer_head * bh )
{
might_sleep ( ) ;
if ( buffer_locked ( bh ) | | atomic_read ( & bh - > b_count ) = = 0 )
/* if a block is locked , it says kernel is transfering data into it
* so we must wait for the bit has been cleared successfully
* bob
*/
__wait_on_buffer ( bh ) ;
}
/*
* Note that the real wait_on_buffer() is an inline function that checks
* that the buffer is locked before calling this, so that unnecessary disk
* unplugging does not occur.
*/
void __wait_on_buffer ( struct buffer_head * bh )
{
struct task_struct * tsk = current ;
DECLARE_WAITQUEUE ( wait , tsk ) ;
get_bh ( bh ) ;
add_wait_queue ( & bh - > b_wait , & wait ) ;
/* in fact , here we use do {} while(condition) is better than for(;;)
* because ,after "schedule()" ,maybe condition(buffer_locked()) has been applied
* then the loop can directly break
* --bob
*/
do {
run_task_queue ( & tq_disk ) ;
set_task_state ( tsk , TASK_UNINTERRUPTIBLE ) ;
if ( ! buffer_locked ( bh ) )
break ;
schedule ( ) ;
} while ( buffer_locked ( bh ) ) ;
tsk - > state = TASK_RUNNING ;
remove_wait_queue ( & bh - > b_wait , & wait ) ;
put_bh ( bh ) ;
}
struct page * buffer_page ;
unsigned long buffer_virt ;
buffer_virt = get_zeroed_page ( GFP_ATOMIC ) ) ) {
buffer_page = virt_to_page ( buffer_virt ) ;
unsigned long get_zeroed_page ( unsigned int gfp_mask )
{
struct page * page ;
page = alloc_pages ( gfp_mask , 0 ) ;
if ( page ) {
void * address = page_address ( page ) ;
clear_page ( address ) ;
return ( unsigned long ) address ;
}
return 0 ;
}
/*
* Common helper functions.
*/
unsigned long __get_free_pages ( unsigned int gfp_mask , unsigned int order )
{
struct page * page ;
page = alloc_pages ( gfp_mask , order ) ;
if ( ! page )
return 0 ;
return ( unsigned long ) page_address ( page ) ;
}
# define TryLockPage ( page ) test_and_set_bit ( PG_locked , & ( page ) - > flags )
# define PageChecked ( page ) test_bit ( PG_checked , & ( page ) - > flags )
# define SetPageChecked ( page ) set_bit ( PG_checked , & ( page ) - > flags )
# define PageLaunder ( page ) test_bit ( PG_launder , & ( page ) - > flags )
# define SetPageLaunder ( page ) set_bit ( PG_launder , & ( page ) - > flags )
# define ClearPageLaunder ( page ) clear_bit ( PG_launder , & ( page ) - > flags )
//关于调用wait函数的代码
/*
* Calling wait_on_buffer() for a zero-ref buffer is illegal, so we call into
* __wait_on_buffer() just to trip a debug check. Because debug code in inline
* functions is bloaty.
*/
static inline void wait_on_buffer ( struct buffer_head * bh )
{
might_sleep ( ) ;
if ( buffer_locked ( bh ) | | atomic_read ( & bh - > b_count ) = = 0 )
/* if a block is locked , it says kernel is transfering data into it
* so we must wait for the bit has been cleared successfully
* bob
*/
__wait_on_buffer ( bh ) ;
}
/*
* Note that the real wait_on_buffer() is an inline function that checks
* that the buffer is locked before calling this, so that unnecessary disk
* unplugging does not occur.
*/
void __wait_on_buffer ( struct buffer_head * bh )
{
struct task_struct * tsk = current ;
DECLARE_WAITQUEUE ( wait , tsk ) ;
get_bh ( bh ) ;
add_wait_queue ( & bh - > b_wait , & wait ) ;
/* in fact , here we use do {} while(condition) is better than for(;;)
* because ,after "schedule()" ,maybe condition(buffer_locked()) has been applied
* then the loop can directly break
* --bob
*/
do {
run_task_queue ( & tq_disk ) ;
set_task_state ( tsk , TASK_UNINTERRUPTIBLE ) ;
if ( ! buffer_locked ( bh ) )
break ;
schedule ( ) ;
} while ( buffer_locked ( bh ) ) ;
tsk - > state = TASK_RUNNING ;
remove_wait_queue ( & bh - > b_wait , & wait ) ;
put_bh ( bh ) ;
}