这个在编程的时候常用。 一定搞清楚他们之间的关系。
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);
}