Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Apr 2004 10:50:15 -0700 (PDT)
From:      "Dorr H. Clark" <dclark@applmath.scu.edu>
To:        freebsd-bugs@FreeBSD.org
Subject:   ports fix not kern (was Re: kern/61909: 5.2-Current fails to notice change of CD in drive)
Message-ID:  <200404151750.i3FHoFhN090997@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/61909; it has been noted by GNATS.

From: "Dorr H. Clark" <dclark@applmath.scu.edu>
To: freebsd-gnats-submit@FreeBSD.org, timon@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200404151750.i3FHoFhN090997>