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