[gparted] Flush device after wiping a file system (#688882)
- From: Curtis Gedak <gedakc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gparted] Flush device after wiping a file system (#688882)
- Date: Mon, 25 Mar 2013 16:58:34 +0000 (UTC)
commit 797f0b8eeb61f81da1791c3cf048b5c0abf9a550
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date: Tue Jan 15 13:51:04 2013 +0000
Flush device after wiping a file system (#688882)
When just formatting an existing partition to "cleared", GParted just
uses wipefs to clear the file system signatures. Afterwards parted/
libparted still detect the file system and GParted shows errors from the
file system specific tools reporting the file system doesn't exist.
# wipefs /dev/sda7
offset type
----------------------------------------------------------------
0x0 xfs [filesystem]
UUID: 28399a74-83a5-4ed7-aaf8-c76ac449fb57
# wipefs -a /dev/sda7
4 bytes were erased at offset 0x0 (xfs)
they were: 58 46 53 42
# parted /dev/sda print
Model: ATA SAMSUNG HM500JI (scsi)
Disk /dev/sda: 500GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 538MB 537MB primary ext4 boot
2 538MB 5907MB 5369MB primary linux-swap(v1)
3 5907MB 32.8GB 26.8GB primary ext4
4 32.8GB 500GB 467GB extended
5 32.8GB 355GB 322GB logical ext3
6 355GB 356GB 1074MB logical
7 356GB 357GB 1074MB logical xfs
# xfs_db -c 'sb 0' -c 'print blocksize' -c 'print dblocks' -c 'print fdblocks' -r /dev/sda7
xfs_db: /dev/sda7 is not a valid XFS filesystem (unexpected SB magic number 0x00000000)
Wipefs was run on the partition specific block device (/dev/sda7) where
as libparted reads the disk using the whole disk device (/dev/sda).
However as the Linux buffer cache does not provide cache coherency, the
xfs file system can still be found in the cache of /dev/sda.
Fix this by calling ped_device_sync() after wipefs as it guarantees
cache coherency.
(As documented in erase_filesystem_signatures() there are cases when
calling ped_device_sync() isn't necessary, but testing shows that the
whole processes takes at most 0.15 seconds. As this is in the middle of
applying an operation, uses won't notice this extra time so just always
call ped_device_sync()).
Bug #688882 - Improve clearing of file system signatures
src/GParted_Core.cc | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
---
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index fe5bd5a..e15d5c3 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -3147,6 +3147,41 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope
od .set_status( exit_status == 0 ? STATUS_SUCCES : STATUS_N_A ) ;
}
+ //Linux kernel doesn't maintain buffer cache coherency between the whole disk
+ // device and partition devices. So even though the file system signatures
+ // have been overwritten on the disk via a partition device, libparted reading
+ // via the whole disk device will read the old data and report the file system
+ // as still existing.
+ //
+ // Libparted >= 2.0 works around this by calling ioctl(fd, BLKFLSBUF) to flush
+ // the cache when opening the whole disk device, but only for kernels before
+ // 2.6.0.
+ // Ref: parted v3.1-52-g1c659d5 ./libparted/arch/linux.c linux_open()
+ // 1657 /* With kernels < 2.6 flush cache for cache coherence issues */
+ // 1658 if (!_have_kern26())
+ // 1659 _flush_cache (dev);
+ //
+ // Calling ped_device_sync() to flush the cache is required when the partition is
+ // just being cleared. However the sync can be skipped when the wipe is being
+ // performed as part of writing a new file system as the partition type is also
+ // changed, which modified the partition table so GParted calls
+ // ped_disk_commit_to_os(). This instructs the kernel to remove all non-busy
+ // partitions on the disk and re-adds them, thus effectively flushing the cache
+ // of the disk.
+ //
+ // Opening the device and calling ped_device_sync() took 0.15 seconds or less on
+ // a 5400 RPM laptop hard drive. For now just always call ped_device_sync() as
+ // it doesn't add much time to the overall operation.
+ PedDevice * lp_device = ped_device_get( partition .device_path .c_str() ) ;
+ if ( lp_device != NULL )
+ {
+ if ( ped_device_open( lp_device ) )
+ {
+ ped_device_sync( lp_device ) ;
+ ped_device_close( lp_device ) ;
+ }
+ ped_device_destroy( lp_device ) ;
+ }
return true ;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]