how to maintain the coherence between PG_Dirty and BH_Dirty

Previous thread: [PATCH] [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl() by Zev Weiss on Wednesday, August 20, 2008 - 3:47 am. (11 messages)

Next thread: [PATCH] x86: Use X86_CR4_PGE in x86/power/hibernate_asm_32.S by Uros Bizjak on Wednesday, August 20, 2008 - 4:44 am. (4 messages)
To: <linux-kernel@...>
Date: Wednesday, August 20, 2008 - 4:26 am

Sorry for my rash mail, but I really have some questions which have
bothered me for a long time.

1) Since clear_page_dirty_for_io move the dirty bit from pte to page
structure, and dirty all the buffer_head associated with the page
structure, what is the purpose of set_page_dirty in do_wp_page /
do_linear_fault ?
The dirty state is recorded in the pte, and even if we do not
call the set_page_dirty, each clear_page_dirty_for_io will set
PG_Dirty correctly according to the pte.
We only need to call set_page_dirty when the dirty pte will be
unmapped, and as long as the pte is not unmapped, the _PAGE_DIRTY in
pte will reflect the lastest dirty state of the page, isn't it?

2) in some circumstance(e.g. do_wp_page,do_linear_fault), we call
set_page_dirty without holding PG_Lock. is it possible that the page
isn't associated with any buffer_head, and set_page_dirty works like
this:
CPU 1 : spin_lock ( private_lock )
CPU 1 : nothing to do because none buffer_head is attached
CPU 1 : spin_unlock ( private_lock )
CPU 2 ( or preempt ) : create_empty_buffers {
: lock_page
: spin_lock ( private_lock )
: attached clean buffers to the page
because CPU 1 is not set PG_Dirty yet
: spin_unlock ( private_lock )
: unlock_page }
CPU 1 : Set_Bit ( PG_Dirty )
the result is dirty page with clean buffer_head, and data will lost.
then try_to_free_buffers maybe call cancel_dirty_page since all the
buffer_heads attached is clean. thus,the set_page_dirty have none
effect on the dirty state, and all PG_dirty and BH_Dirty are cleaned.
is this concurrency possible? is it better to implement
set_page_dirty like this:
> spin_lock ( private_lock)
> mark buffer_head as BH_Dirty
> ret = test_and_set (PG_Dirty)
> spin_unlock ( private_lock )
> if (!ret)
> mark page ...

Previous thread: [PATCH] [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl() by Zev Weiss on Wednesday, August 20, 2008 - 3:47 am. (11 messages)

Next thread: [PATCH] x86: Use X86_CR4_PGE in x86/power/hibernate_asm_32.S by Uros Bizjak on Wednesday, August 20, 2008 - 4:44 am. (4 messages)