On 12/01/2011 12:20 PM, OGAWA Hirofumi wrote: > Kai Meyer<kai@xxxxxxxxxx> writes: > >>> The i_pos means directory entry (contains inode information in unix-fs) >>> position, >>> >>> block number == i_pos / (logical-blocksize / 32) >>> offset == i_pos& (logical-blocksize / 32) >>> >>> the above position's directory entry contains information for >>> problematic file. This is how to use i_pos information. >>> >>> FWIW, in this error case, the cluster chain in FAT table which is >>> pointed by that entry, it has invalid cluster value. >>> >>> Thanks. >> If you would verify my math for me, I would appreciate it. >> >> In this case, my logical block size is 4096, because byte 13 of the 8Gb >> file system is 8, and I take that to be 8 * 512, which is 4096. So: >> >> block_number = 523791 / (4096 / 32) = 4092 >> offset = 523791 % (4096 / 32) = 15 // I assume you meant modulo in your >> original post, and not binary AND. > Whoops, you are right. (I forgot "-1") > >> So if the block_number is 4092, I would multiply that by 8 (sectors per >> logical block) to get the sector number: >> 32736 > Right. > >> Does the error indicate that sector contains the corrupted data? > No. > >> Or is it the sector that contains the information that points to the >> corrupted data? > Right. > > The i_pos is pointing a directory entry (include/linux/msdos_fs.h: > struct msdos_dir_entry). > > And starthi (if FAT32) and start contain the pointer to next cluster > number. That message was outputted when walking in cluster chain. > > If you want to see actual corrupted data, you can check the cluster > chain by pointing from that directory entry. > > Thanks. Thanks for the helpful response. I'm not entirely sure I understand the next part though. I hacked a dirty entry dumper tool: #include <stdio.h> #include <linux/msdos_fs.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> int main(int argc, char** argv) { off_t pos = atoi(argv[2]); unsigned long block; off_t sector; unsigned int offset; int fd = open(argv[1], O_RDONLY); char buf[512]; struct msdos_dir_entry dirent; block = pos / (4096 / 32); sector = block * 8; offset = pos % (4096 / 32); printf("block %lu, sector %lu, offset %u\n", block, sector, offset); lseek(fd, sector * 512, SEEK_SET); if (read(fd, buf, 512) < 0) { fprintf(stderr, "Unable to read from device %s\n", argv[1]); return -1; } memcpy(&dirent, buf + offset, sizeof(dirent)); printf("name %s\n", dirent.name); printf("attr %u\n", dirent.attr); printf("lcase %u\n", dirent.lcase); printf("ctime_cs %u\n", dirent.ctime_cs); printf("ctime %u\n", dirent.ctime); printf("cdate %u\n", dirent.cdate); printf("adate %u\n", dirent.adate); printf("starthi %u\n", dirent.starthi); printf("time %u\n", dirent.time); printf("date %u\n", dirent.date); printf("start %u\n", dirent.start); printf("size %u\n", dirent.size); } Here's what it outputs: ./vfat_entry /dev/sblsnap0 523793 block 4092, sector 32736, offset 17 name attr 255 lcase 255 ctime_cs 255 ctime 12799 cdate 12670 adate 8224 starthi 8224 time 23072 date 21061 start 32 size 2171155456 So, I take starthi, and shift 16 bits left, then and in the start value. That should give me the byte address of the first cluster of the file, correct? Then I need to follow the cluster chain until I get a bad value. Thanks _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies