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

Reply via email to