| Summary: | Incorrect handling of end-of-media in atapi cdrom driver | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | daveg <daveg> | ||||
| Component: | kern | Assignee: | Søren Schmidt <sos> | ||||
| Status: | Closed FIXED | ||||||
| Severity: | Affects Only Me | ||||||
| Priority: | Normal | ||||||
| Version: | Unspecified | ||||||
| Hardware: | Any | ||||||
| OS: | Any | ||||||
| Attachments: |
|
||||||
State Changed From-To: open->analyzed Hmm, well, the _real_ problem is the size put in volinfo, this is unfortunately not done equal by all drives, some gives the number of blocks offset 1 some offset 0, so the fix in the PR is just as wrong as the current code. I guess there is no real solution to this, other than trying the last block and see what gives, the drive could hide the error and let the rest of the system live happily... Responsible Changed From-To: freebsd-bugs->sos sos is Mr ATA State Changed From-To: analyzed->closed This is belived to be fixed in -current some time ago |
The atapi cdrom driver incorrecly handles the end-of-media (EOM) condition. It can attempt to read one block past the EOM when it is reading the last file on the CD. Fix: this is a classic off-by-one error on the EOM detection code in acd_start() *** atapi-cd.c 2000/05/08 23:00:21 1.1 --- atapi-cd.c 2000/10/23 16:52:57 *************** How-To-Repeat: 1. create a cd with one file on it that is 1343775 bytes long dd if=/dev/zero of=/tmp/f bs=1343775 count=1 mkisofs -A "cd" -D -l -J -v -r -o /tmp/cdimage.raw /tmp/f cdrecord dev=0,0,0 speed=4 -multi -v /tmp/cdimage.raw 2. copy to file from the cd using /bin/cp (and cp must be compiled with -DVM_AND_BUFFER_CACHE_SYNCHRONIZED, which 4.0 is) the cp command will fail because: - since the file is less than 8meg, cp mmaps the file, which causes the the vnode pager to page in the file. - the block size of the cd is 2k and the page size is 4k. the file ends in the first 2k of the last page. the last page in of the file will result in two reads. - the first one works fine (it is the last block on the cd and it contains 287 bytes of file data). the next one attempts to read past the EOM. it should just return EOF, but instead a read command is issued to the controller. the read gets an error and the following is printed in the console: acd0: READ_BIG - ILLEGAL REQUEST asc=64 ascq=00 error=01 - the error is passed up to the vnode pager in the struct buf. this causes the page in to fail and the vnode pager prints the following on the console: vm_fault: pager read error, pid 292 (cp) - since the page in fails, the cp fails. Using dd or the like will not detect this problem since they do not attempt to read past the EOM like the vnode pager can.