From owner-freebsd-bugs@FreeBSD.ORG Thu Apr 15 10:50:19 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3EB2716A4CE for ; Thu, 15 Apr 2004 10:50:19 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2130743D46 for ; Thu, 15 Apr 2004 10:50:16 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i3FHoGbv090998 for ; Thu, 15 Apr 2004 10:50:16 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i3FHoFhN090997; Thu, 15 Apr 2004 10:50:15 -0700 (PDT) (envelope-from gnats) Date: Thu, 15 Apr 2004 10:50:15 -0700 (PDT) Message-Id: <200404151750.i3FHoFhN090997@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: "Dorr H. Clark" Subject: ports fix not kern (was Re: kern/61909: 5.2-Current fails to notice change of CD in drive) X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: "Dorr H. Clark" List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Apr 2004 17:50:19 -0000 The following reply was made to PR kern/61909; it has been noted by GNATS. From: "Dorr H. Clark" 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