Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Dec 1998 10:00:40 -0800 (PST)
From:      Kenneth Merry <ken@FreeBSD.ORG>
To:        cvs-committers@FreeBSD.ORG, cvs-all@FreeBSD.ORG
Subject:   cvs commit: src/sys/cam cam_periph.c
Message-ID:  <199812161800.KAA28535@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
ken         1998/12/16 10:00:40 PST

  Modified files:
    sys/cam              cam_periph.c 
  Log:
  Probable fix for the "cdda2wav" panics that various people have been
  reporting since this past summer.  (I think Daniel O'Conner was the first.)
  
  The problem appears to have been something like this:
  
   - cdda2wav by default passes in a buffer that is close to the 128K MAXPHYS
     limit.
   - many times, the buffer is not page aligned
   - vmapbuf() truncates the address, so that it is page aligned
   - that causes the total size of the buffer to be greater than MAXPHYS,
     which of course is a bad thing.
  
  Here's a quote from the PR (kern/9067):
  
  ==================
  In particular, note bp->b_bufsize = 0x0001f950 and bp->b_data = 0xf2219960
  (which does not start on a page boundary).  vunmapbuf() loops through all
  the pages without any difficulty until addr reaches 0xf2239000, and then
  the panic occurs.  This seems to indicate that we are exceeding MAXPHYS
  since we actually started from the middle of a page (the data is being
  transfered to a non page aligned location).
  
  To complete the description, note that the system call originates from
  ReadCddaMMC12() (in scsi_cmds.c of cdda2wav) with a request to read 55
  audio sectors of 2352 bytes (which is calculated to fall under MAXPHYS).
  This in turn ends up calling scsi_send() (in scsi-bsd.c) which calls
  cam_fill_csio() and cam_send_ccb().  This results in a CAMIOCOMMAND ioctl
  with a ccb function code of XPT_SCSI_IO.
  ==================
  
  The fix is to change the size check in cam_periph_mapmem() so that it is
  like the one in minphys().  In particular, it is something like:
  
  if ((buffer_length + (buf_ptr & PAGE_MASK)) > MAXPHYS)
  	buffer is too big
  
  My fix is based on the one in the PR, but I cleaned up a fair number of
  things in cam_periph_mapmem().  The checks for each buffer to be mapped
  are now in a separate loop from the actual mapping operation.  With the new
  arrangement, we don't have to bother with unmapping any previously mapped
  buffers if one of the checks fails.
  
  Many thanks to James Liu for tracking this down.  I'd appreciate it if some
  vm-savvy folks would look this over.  I believe this fix is correct, but I
  could be wrong.
  
  PR:		kern/9067 (also, kern/8112)
  Reviewed by:	gibbs
  Submitted by:	"James T. Liu" <jtliu@phlebas.rockefeller.edu>
  
  Revision  Changes    Path
  1.7       +39 -47    src/sys/cam/cam_periph.c

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message



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