ports fix not kern (was Re: kern/61909: 5.2-Current fails to notice
change of CD in drive)
Dorr H. Clark
dclark at applmath.scu.edu
Thu Apr 15 10:50:19 PDT 2004
The following reply was made to PR kern/61909; it has been noted by GNATS.
From: "Dorr H. Clark" <dclark at applmath.scu.edu>
To: freebsd-gnats-submit at FreeBSD.org, timon at memphis.mephi.ru
Cc:
Subject: ports fix not kern (was Re: kern/61909: 5.2-Current fails to notice
change of CD in drive)
Date: Thu, 15 Apr 2004 10:48:57 -0700
Proposed fix:
--- /usr/ports/audio/dagrab/work/dagrab-0.3.5/dagrab.c Wed Mar 3
21:50:08 2004
+++ dagrab.c Tue Mar 16 15:09:04 2004
@@ -243,6 +243,38 @@
return ioctl(cdrom_fd,CDIOREADTOCENTRY,Te);
}
+int force_read_check(struct cd_trk_list *tl)
+{
+ int num = opt_blocks;
+ int lba = tl->min;
+ int buf[opt_ibufsize];
+ int *p = buf;
+
+#if defined (__FreeBSD__) && (__FreeBSD_version >= 501106)
+ int bsize = CD_FRAMESIZE_RAW;
+ if(ioctl(cdrom_fd,CDRIOCSETBLOCKSIZE,&bsize) == -1) {
+ fprintf(stderr, "setblocksize");
+ return -1;
+ }
+
+ if (pread(cdrom_fd, (char *)p, num*bsize, lba*bsize) !=
num*bsize){
+ printf("Could not read media\n");
+#else
+ struct ioc_read_audio ra;
+
+ ra.address.lba=lba;
+ ra.address_format=CD_LBA_FORMAT;
+ ra.nframes=num;
+ ra.buffer=buf;
+ if(ioctl(cdrom_fd,CDIOCREADAUDIO,&ra)){
+ fprintf(stderr, "Could not read media\n");
+#endif
+ return -1;
+ }
+
+return 1;
+}
+
void cd_read_audio(int lba,int num,char *buf)
/* reads num CD_FRAMESIZE_RAW sized
sectors in buf, starting from lba*/
@@ -251,7 +283,7 @@
{
/* CDIOCREADAUDIO has been removed in FreeBSD 5.1-CURRENT */
#if defined (__FreeBSD__) && (__FreeBSD_version >= 501106)
- int bsize = 2352;
+ int bsize = CD_FRAMESIZE_RAW;
if(ioctl(cdrom_fd,CDRIOCSETBLOCKSIZE,&bsize) == -1) {
fprintf(stderr, "setblocksize");
exit(1);
@@ -699,6 +730,12 @@
}
tl->starts[tl->max-tl->min+1]=ntohl(Te.entry.addr.lba);
tl->types[tl->max-tl->min+1]=Te.entry.control&CDROM_DATA_TRACK;
+
+ if(force_read_check(tl) == -1) {
+ fprintf(stderr,"%s: error reading from device
%s\n",progname,cd
_dev);
+ exit(1);
+ }
+
i=cddb_main(tl);
if(i==-1) {
{ NOTE: this patch presumes the FreeBSD patch has already been applied,
it does not directly apply to the original dagrab-0.3.5/dagrab.c }
Problem Definition:
The bug report describes the problem being that when a cd is
removed
from the cdrom drive, the cd track information still exists until
another disk
is entered into the drive. This can confuse programs, such as dagrab,
because some operations only look at the track information and will
incorrectly report information about the contents of the cd drive.
Problem Analysis:
The program dagrab was written for linux and ported to FreeBSD.
Although the two operating systems are very similar with respect
to cdrom I/O, there are some subtle differences between the two.
FreeBSD only updates cd track information when a new cd is entered
in the drive, an ioctl() call to obtain track information with no cd
will return the contents of the file system cache. In particular, when
the cd is removed, the track listings /dev/acd0?t* remain intact
and will not be replaced until a new cd is entered into the drive.
Linux also caches the cd track information, but only for as long
as the cd is actually in the drive. Once the cd is removed, any call
to ioctl() will result in an IO failure unless a new cd has been
entered.
Based on the FreeBSD philosophy that the file system should
cache
this information, this bug has been improperly filed against the kernel
and should be moved to the ports section.
Solution:
The only method I have found to determine if the cd is actually
in the drive without getting a ghost image from the filesystem cache is
to invoke a read operation on the cdrom drive. Other types of access
will return a result with an undetermined origin as they can be
satisfied
by the cache. Similar programs, such as cdparanoia, also catch this
condition (although based on their implementation, it may be
coincidence)
by the same method of invoking a read operation on the cd. The problem
with this strategy of defeating the normal filesystem cache behavior
is that it invalidates the cache performance gain because an actual
read operation is a very slow operation. However, by reading a small
section of the disk as opposed to the whole table of contents this
minimizes the performance degradation.
Daniel Weeks, engineer
Dorr H. Clark, advisor
Graduate School of Engineering
Santa Clara University
More information about the freebsd-bugs
mailing list