On Tue, Feb 21, 2012 at 03:15:29PM +0200, Alexey Vatchenko wrote: > Reading 512 bytes from raw device with 2048 sector size fails. If i read > 512 bytes from block device the problem is not reproduced. > > How to reproduce. > 1. I plugged my iPod Nano (2nd generation) into PC. > Then use the following code to reproduce the issue. > > #include <sys/types.h> > > #include <fcntl.h> > #include <stdio.h> > #include <unistd.h> > > int > main(void) > { > char buf[512]; > ssize_t sz; > int fd; > > fd = open("/dev/rsd0j", O_RDONLY); > if (fd == -1) > err(1, "open"); > sz = read(fd, buf, sizeof(buf)); > if (sz == -1) > err(1, "read"); > close(fd); > return (0); > } > > 2. Another way to reproduce and actually why i spot this problem is fsck. > `fsck /dev/sd0j` on msdos device launches `fsck_msdos /dev/rsd0j`. > If i run fsck_msdos on /dev/sd0j the problem is not reproduced. > > The problem goes into kernel in file sys/kern/subr_disk.c function > bounds_check_with_label(): > > /* Ensure transfer is a whole number of aligned sectors. */ > if ((bp->b_blkno % DL_BLKSPERSEC(lp)) != 0 || > (bp->b_bcount % lp->d_secsize) != 0) > goto bad; >
This is intentional. You cannot read from a raw device fewer bytes at a time than the minimum the device provides per i/o. On block devices the buffer cache does the correct size i/o and extracts just the number of bytes you requested. The fsck behaviour is more interesting. .... Ken