lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Wed, 20 Aug 2008 16:26:22 +0800
From:	"Trotski Liu" <trotski.liu@...il.com>
To:	linux-kernel@...r.kernel.org
Subject: how to maintain the coherence between PG_Dirty and BH_Dirty

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 as TAG_DIRTY in Radix Tree


  3) why create_empty_buffers will  set BH_Dirty if PG_Dirty, but
grow_buffers will not ?
      if a block device page is mapped to user space, and is marked
dirty, we attach clean buffer_heads to it will guarantee the file
system will not be corrupted, but it also imply that  the dirty data
in the blocks will be lost.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ