Nice finding, as I was able to reproduce this effect on my system, too. At my site it happens on /dev/hda, so it is no SCSI issue.
# uname -a
Linux X.X.X 2.6.26-2-686 #1 SMP Tue Mar 9 17:35:51 UTC 2010 i686 GNU/Linux
I think whitequark
is right that it is a cache issue. Here is my interpretation what happened on your site (note that I am not sure that my explanation is correct, though):
/dev/sda1 is in use. So "sync" updates the superblock every time the journal is flushed (or similar). So the disk /dev/sda1 is changed.
However the kernel does not use a combined cache for /dev/sda and /dev/sda1, instead both "files" are cache on it's own. Updating /dev/sda1 (sync) therefor does not invalidate the cache of /dev/sda. Hence reading from /dev/sda shows the old cache value (so the cache is out of sync with the harddrive) while /dev/sda1 shows the correct (new) values.
Here is the situation seen on my side. I came here having done some dumps before on /dev/hda, so it had already cached some old data:
# od -tx1z -N 10k /dev/hda2 > NOW1
# dd ibs=512 skip=1975995 if=/dev/hda | od -tx1z -N 10k > MAIN1
# diff NOW1 MAIN1
3,4c3,4
< 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 be 1a 39 00 >..1.W.a..}....9.<
< 0002020 4e ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >N.!.............<
---
> 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 4e 1b 39 00 >..1.W.a..}..N.9.<
> 0002020 52 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >R.!.............<
# od -tx1z -N 10k /dev/hda2 > NOW1
# diff NOW1 MAIN1
3,4c3,4
< 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 be 1a 39 00 >..1.W.a..}....9.<
< 0002020 4e ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >N.!.............<
---
> 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 4e 1b 39 00 >..1.W.a..}..N.9.<
> 0002020 52 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >R.!.............<
# od -tx1z -N 10k /dev/hda2 > NOW2
# dd ibs=512 skip=1975995 if=/dev/hda | od -tx1z -N 10k > MAIN2
# diff MAIN1 MAIN2
# diff NOW2 MAIN2
3,4c3,4
< 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 f0 19 39 00 >..1.W.a..}....9.<
< 0002020 41 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >A.!.............<
---
> 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 4e 1b 39 00 >..1.W.a..}..N.9.<
> 0002020 52 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >R.!.............<
106c106
< 0012440 00 80 14 00 01 80 14 00 02 80 14 00 00 00 01 00 >................<
---
> 0012440 00 80 14 00 01 80 14 00 02 80 14 00 00 00 00 00 >................<
334c334
< 0021540 00 80 4d 00 01 80 4d 00 02 80 4d 00 02 00 63 3e >..M...M...M...c><
---
> 0021540 00 80 4d 00 01 80 4d 00 02 80 4d 00 02 00 64 3e >..M...M...M...d><
While /dev/hda does not show any update, /dev/hda2 shows some changes.
But when I flush the caches and try again, everything shows to be the same:
# hdparm -f /dev/hda
/dev/hda:
# dd ibs=512 skip=1975995 if=/dev/hda | od -tx1z -N 10k > MAIN2
# diff MAIN1 MAIN2
3,4c3,4
< 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 4e 1b 39 00 >..1.W.a..}..N.9.<
< 0002020 52 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >R.!.............<
---
> 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 dc 1a 39 00 >..1.W.a..}....9.<
> 0002020 96 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >..!.............<
36,37c36,37
< 0010300 00 00 03 00 01 00 03 00 02 00 03 00 00 00 bb 3b >...............;<
< 0010320 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
---
> 0010300 00 00 03 00 01 00 03 00 02 00 03 00 00 00 bc 3b >...............;<
> 0010320 7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
48c48
< 0010600 00 00 06 00 01 00 06 00 02 00 06 00 03 00 18 3f >...............?<
---
> 0010600 00 00 06 00 01 00 06 00 02 00 06 00 04 00 18 3f >...............?<
106c106
< 0012440 00 80 14 00 01 80 14 00 02 80 14 00 00 00 00 00 >................<
---
> 0012440 00 80 14 00 01 80 14 00 02 80 14 00 00 00 01 00 >................<
# od -tx1z -N 10k /dev/hda2 > NOW2
# diff NOW2 MAIN2
# diff MAIN1 MAIN2
3,4c3,4
< 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 4e 1b 39 00 >..1.W.a..}..N.9.<
< 0002020 52 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >R.!.............<
---
> 0002000 00 00 31 01 57 c4 61 02 04 7d 1e 00 dc 1a 39 00 >..1.W.a..}....9.<
> 0002020 96 ea 21 01 00 00 00 00 02 00 00 00 02 00 00 00 >..!.............<
36,37c36,37
< 0010300 00 00 03 00 01 00 03 00 02 00 03 00 00 00 bb 3b >...............;<
< 0010320 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
---
> 0010300 00 00 03 00 01 00 03 00 02 00 03 00 00 00 bc 3b >...............;<
> 0010320 7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
48c48
< 0010600 00 00 06 00 01 00 06 00 02 00 06 00 03 00 18 3f >...............?<
---
> 0010600 00 00 06 00 01 00 06 00 02 00 06 00 04 00 18 3f >...............?<
106c106
< 0012440 00 80 14 00 01 80 14 00 02 80 14 00 00 00 00 00 >................<
---
> 0012440 00 80 14 00 01 80 14 00 02 80 14 00 00 00 01 00 >................<
Short note on how to reproduce:
- Make sure your system is idle and has plenty of RAM for caching.
- run
fdisk -u -l
to find where the partition starts. At my side it is 1975995
- Choose a mounted partition and the complete drive.
- Then do the both dumps (NOW1, MAIN1) and compare them. They shall compare equal.
- Change a bit on the partition, sync.
- Leave it more time.
- Change a bit, sync again.
- Do dump NOW2, it shall differ from NOW1
- Do a dump MAIN2, it should not differ from MAIN1!
- Execute the
hdparm
line for your drive
- Do dump MAIN2 again, now it will differ from MAIN1.
- If you are quick enough, NOW2 and MAIN2 will compare equal.
After some brief testing and only with TestDisk and sfdisk in a virtual environment (I can't confirm that creating a new partition table in something like fdisk or gparted would leave it in tact) I'm inclined to say no, writing a partition table won't affect anything other than the first 512 bytes.
Below are the test steps...
I created a 100MB hard drive and partitioned it as follows:
I then mounted and added files to each of the partitions before wiping the first 512 bytes
sudo dd if=/dev/zero bs=1 count=512 conv=notrunc of=/dev/sdb
A quick check with fdisk has shown that this has been wiped
richard@mint14 ~/Disktests $ sudo fdisk -lu /dev/sdb
Disk /dev/sdb: 104 MB, 104857600 bytes
255 heads, 63 sectors/track, 12 cylinders, total 204800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/sdb doesn't contain a valid partition table
So I ran TestDisk against it which successfully found the partitions by scanning the drive and I wrote them to the disk.
After this I dumped the partition table out using sfdisk
richard@mint14 ~/Disktests $ sudo sfdisk -d /dev/sdb > sdb_partitions.out
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
richard@mint14 ~/Disktests $ cat sdb_partitions.out
# partition table of /dev/sdb
unit: sectors
/dev/sdb1 : start= 2048, size= 20480, Id=83, bootable
/dev/sdb2 : start= 22528, size= 61440, Id=83
/dev/sdb3 : start= 83968, size= 61440, Id= 5
/dev/sdb4 : start= 145408, size= 59392, Id= 7
/dev/sdb5 : start= 86016, size= 59392, Id=83
I made a copy of this file and edited it manually to create a single 20MB partition, so one that overlaps the second partition and then wrote it back to the drive
richard@mint14 ~/Disktests $ sudo sfdisk /dev/sdb < sdb_partitions.out_modified
Checking that no-one is using this disk right now ...
OK
Disk /dev/sdb: 12 cylinders, 255 heads, 63 sectors/track
sfdisk: ERROR: sector 0 does not have an MSDOS signature
/dev/sdb: unrecognised partition table type
Old situation:
No partitions found
New situation:
Warning: The partition table looks like it was made
for C/H/S=*/173/42 (instead of 12/255/63).
For this listing I'll assume that geometry.
Units = sectors of 512 bytes, counting from 0
Device Boot Start End #sectors Id System
/dev/sdb1 * 2048 43007 40960 83 Linux
start: (c,h,s) expected (0,48,33) found (0,32,33)
end: (c,h,s) expected (5,158,42) found (2,172,42)
/dev/sdb2 0 - 0 0 Empty
/dev/sdb3 0 - 0 0 Empty
/dev/sdb4 0 - 0 0 Empty
Warning: partition 1 does not end at a cylinder boundary
Successfully wrote the new partition table
Re-reading the partition table ...
Another quick check with fdisk shows that it's successfully written this partition table to disk
richard@mint14 ~/Disktests $ sudo fdisk -lu /dev/sdb
Disk /dev/sdb: 104 MB, 104857600 bytes
173 heads, 42 sectors/track, 28 cylinders, total 204800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Device Boot Start End Blocks Id System
/dev/sdb1 * 2048 43007 20480 83 Linux
Finally using sfdisk to replace the original partition table
richard@mint14 ~/Disktests $ sudo sfdisk --force /dev/sdb < sdb_partitions.out
Checking that no-one is using this disk right now ...
OK
Disk /dev/sdb: 12 cylinders, 255 heads, 63 sectors/track
sfdisk: ERROR: sector 0 does not have an MSDOS signature
/dev/sdb: unrecognised partition table type
Old situation:
No partitions found
New situation:
Units = sectors of 512 bytes, counting from 0
Device Boot Start End #sectors Id System
/dev/sdb1 * 2048 22527 20480 83 Linux
/dev/sdb2 22528 83967 61440 83 Linux
/dev/sdb3 83968 145407 61440 5 Extended
/dev/sdb4 145408 204799 59392 7 HPFS/NTFS/exFAT
/dev/sdb5 86016 145407 59392 83 Linux
I then mounted each of these again and verified that the files were there and in tact.
Best Answer
If you need the partition size, you should be fine with the command you already mentioned:
If you need the total file system size, you can use the total numbers given by
df
:Note that if you sum up used and available space given by
df
, it will be less than the given total space. This is due to file system overhead, e.g. the journal.If you want to modify or just have a look on your file system setup consider the
tune2fs
anddumpe2fs
manpages.