From: short <> Date: Tue, 6 Aug 2002 14:30:49 +0000 (+0000) Subject: +README/"Linux kernel flaw" and its handling (last sector failed reads) X-Git-Url: http://git.jankratochvil.net/?p=badblock-guess.git;a=commitdiff_plain;h=6b440e700542984772b723f222f2d6d3426210b9;hp=bf17104b55bd5232d6564047ecd6dc8cbb397328 +README/"Linux kernel flaw" and its handling (last sector failed reads) --- diff --git a/README b/README index fee9795..b02fc61 100644 --- a/README +++ b/README @@ -91,6 +91,21 @@ performance about 90KB/s (approx. 7.5GB/24hours if no badblocks read retrying is needed). YMMV. +Linux kernel flaw +----------------- + +Linux kernels have internal blocksize 1KB but the partitions can be sized by +512 sectors and thus the last odd partition sector gets inaccessible. +This isn't a problem for a the disk devices as AFAIK all the disks have always +even number of sectors. + +This program is aware of this flaw and it will not report last such sector as +BAD - just the appropriate warning is supplied (to stderr). This may be visible +for example while recovering NTFS partition with odd cylinder number (=>odd +sector count) as NTFS uses the last partition sector for its superblock backup. +Fortunately CHKDSK will fix it back, of course. + + Compilation ----------- diff --git a/badblock-guess.c b/badblock-guess.c index f715cd1..e7dacd2 100644 --- a/badblock-guess.c +++ b/badblock-guess.c @@ -274,6 +274,13 @@ ext2_loff_t gotext2_loff; exit(EXIT_FAILURE); } if (len!=(gotssize=write(dst_fd,buf,len))) { + /* see README/"Linux kernel flaw" */ + /* no "start==src_len-1" checking here, we may write larger blocks! */ + if (gotssize==((src_len&~1)-start)*BLOCK + /* -1 instead of 0 is given when no bytes were written */ + || (gotssize==-1 && start==src_len-1 && end==src_len)) + return; /* suppress error message */ + fprintf(stderr,"write(\"%s\",@%llu-@%llu=%llu=%lluB)=%lld: %m\n",dst_name, (unsigned long long)start, (unsigned long long)end, @@ -284,11 +291,29 @@ ext2_loff_t gotext2_loff; } } +static void range_zero(ext2_loff_t start,ext2_loff_t end) +{ +static const unsigned char buf_zero[BUF_ZERO_BLOCKS*BLOCK]; + + g_return_if_fail(startBUF_ZERO_BLOCKS ? start+BUF_ZERO_BLOCKS : end); + g_assert(mid>=start); + g_assert(mid<=end); + + write_dst(start,mid,buf_zero); + + start=mid; + } +} + static void process(ext2_loff_t start,ext2_loff_t end) { unsigned char block_buf[BLOCK]; ext2_loff_t bads; ext2_loff_t gotext2_loff; +ssize_t gotssize; g_return_if_fail(start=end) /* finished */ return; @@ -337,23 +371,6 @@ ext2_loff_t mid=(start+end)/2; } } -static void range_zero(ext2_loff_t start,ext2_loff_t end) -{ -static const unsigned char buf_zero[BUF_ZERO_BLOCKS*BLOCK]; - - g_return_if_fail(startBUF_ZERO_BLOCKS ? start+BUF_ZERO_BLOCKS : end); - g_assert(mid>=start); - g_assert(mid<=end); - - write_dst(start,mid,buf_zero); - - start=mid; - } -} - static void finish(void) { struct range *todo_linear=tree_linearize(todo_tree),*todol;