virtual drive errors

Andriy Gapon avg at icyb.net.ua
Wed Apr 7 21:50:49 UTC 2010


on 07/04/2010 19:58 Pavel Sukhoy said the following:
> Hi All,
> 
> I tried to ask this question in <freebsd-usb at FreeBSD.org> mailing list,
> but maybe it's a right place to ask about this problem?


I see that there were some followups on usb@ that must have directed you here
and I think that this is indeed the right list for this issue.
See my analysis below the report.

> My server is based on intel S5000PAL motherboard and have dedicated "Intel
> remote
> management module 2". 
> 
> If I try to boot from remotely mounted installation drive/iso (FreeBSD
> 8.0-RELEASE) it goes fine until I
> choose installation media - in messages I see a read error.
> 
> If I try to mount remote drive on working FreeBSD (also 8.0-RELEASE and
> 7.3-RELEASE) - I
> see that virtual
> device recognized fine, but gets error when trying to mount:
> 
> 
> Remotely connecting iso:
> 
> 12:53:33 kernel: umass3: <Intel(R) Multidevice, class 0/0, rev 
> 2.00/0.01, addr 2> on usbus4
> 12:53:33 kernel: umass3:  SCSI over Bulk-Only; quirks = 0x0000
> 12:53:34 kernel: umass3:3:3:-1: Attached to scbus3
> 12:53:35 kernel: (probe0:umass-sim3:3:0:0): TEST UNIT READY. CDB: 
> 0 0 0 0 0 0
> 12:53:35 kernel: (probe0:umass-sim3:3:0:0): CAM Status: SCSI 
> Status Error
> 12:53:35 kernel: (probe0:umass-sim3:3:0:0): SCSI Status: Check 
> Condition
> 12:53:35 kernel: (probe0:umass-sim3:3:0:0): UNIT ATTENTION 
> asc:29,0
> 12:53:35 kernel: (probe0:umass-sim3:3:0:0): Power on, reset, or 
> bus device reset occurred
> 12:53:35 kernel: (probe0:umass-sim3:3:0:0): Retrying Command (per 
> Sense Data)
> 12:53:35 kernel: cd3 at umass-sim3 bus 3 target 0 lun 0
> 12:53:35 kernel: cd3: <Intel(R) RMM2 VDrive 4 0.01> Removable CD-
> ROM SCSI-3 device
> 12:53:35 kernel: cd3: 40.000MB/s transfers
> 12:53:35 kernel: cd3: cd present [1058112 x 2048 byte records]
> 
> And now I trying to mount it:
> 
> 12:54:20 kernel: g_vfs_done():cd3[READ(offset=32768, 
> length=2048)]error = 5 
> 
> This error repeats on any virtual iso/drives.
> 
> Maybe anyone else seen similar problems and know some solution? 
> 
> Thanks in advance for any help.

Having spent the past couple of month examining various code paths in VFS, GEOM
and CAM, I think that I see what's going on here.

First, let me show off, ehm, double-check my understanding.
I think that error 5, i.e. EIO, is returned from g_io_check(), namely from the
following clause:
                if (bp->bio_offset > pp->mediasize)
                        return (EIO);
I think that this happens because pp->mediasize is zero in this case.

*Idea*: g_io_check() could return a different (more appropriate?) error code for
the case of pp->mediasize being zero.

Now, let's see why pp->mediasize is zero here.
Consider the following call chain that takes place before any reading of media
in this case:
iso_mountfs -> g_vfs_open -> g_access -> g_disk_access -> d_open=cdopen ->
cdcheckmedia

cdcheckmedia is supposed to set d_mediasize of the corresponding geom disk and
g_disk_access passes that value to mediasize of the corresponding geom provider.
So, it looks that in this case d_mediasize remains zero instead of being set to
actual media size.

Looking at cdcheckmedia and at the logged READ TOC (0x43) SCSI command errors
(as reported by Markus) I see the following problem.  Even if cdsize() call at
the beginning of cdcheckmedia() succeeds, a subsequent failure of cdreadtoc()
throws us to 'bailout' label which is past the code that sets d_mediasize.

I think that the following patch should help with this situation (and possibly
other cases with READ TOC problems):

--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -2769,16 +2769,20 @@ cdcheckmedia(struct cam_periph *periph)
 	 * Get the disc size and block size.  If we can't get it, we don't
 	 * have media, most likely.
 	 */
 	if ((error = cdsize(periph, &size)) != 0) {
 		softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC);
 		cdprevent(periph, PR_ALLOW);
 		return (error);
-	} else
+	} else {
 		softc->flags |= CD_FLAG_VALID_MEDIA;
+		softc->disk->d_sectorsize = softc->params.blksize;
+		softc->disk->d_mediasize =
+		    (off_t)softc->params.blksize * softc->params.disksize;
+	}

 	/*
 	 * Now we check the table of contents.  This (currently) is only
 	 * used for the CDIOCPLAYTRACKS ioctl.  It may be used later to do
 	 * things like present a separate entry in /dev for each track,
 	 * like that acd(4) driver does.
 	 */
@@ -2859,17 +2863,14 @@ cdcheckmedia(struct cam_periph *periph)
 		for (cdindex = 0; cdindex < num_entries - 1; cdindex++) {
 			softc->toc.entries[cdindex].track =
 				bcd2bin(softc->toc.entries[cdindex].track);
 		}
 	}

 	softc->flags |= CD_FLAG_VALID_TOC;
-	softc->disk->d_sectorsize = softc->params.blksize;
-	softc->disk->d_mediasize =
-	    (off_t)softc->params.blksize * softc->params.disksize;

 bailout:

 	/*
 	 * We unconditionally (re)set the blocksize each time the
 	 * CD device is opened.  This is because the CD can change,
 	 * and therefore the blocksize might change.

Or alternatively, the assignments could be moved past the bailout label.
Will you be able to test this patch using your scenario with already installed
FreeBSD?  Or perhaps by creating your own bootable/live FreeBSD CD?

-- 
Andriy Gapon


More information about the freebsd-hackers mailing list