cd(4) M_WAITOK allocations with periph lock held
Scott Long
scottl at samsco.org
Tue Dec 1 21:30:40 UTC 2009
How about the attached match instead. It refactors the code so that
unlocks aren't needed.
Scott
On Tue, 1 Dec 2009, Jaakko Heinonen wrote:
>
> Hi,
>
> There are some M_WAITOK malloc invocations with periph lock held in
> cd(4). Below is a link to a patch which drops the periph lock while
> doing those allocations. Comments/review?
>
> ---
>
> Drop periph lock while allocating memory with M_WAITOK flag in
> cdreportkey(), cdsendkey() and cdreaddvdstructure().
>
> PR: kern/130735
> Tested by: Eygene Ryabinkin
>
> The patch against head:
>
> http://people.freebsd.org/~jh/patches/scsi_cd-M_WAITOK-fixes.diff
>
> --
> Jaakko
> _______________________________________________
> freebsd-scsi at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-scsi
> To unsubscribe, send any mail to "freebsd-scsi-unsubscribe at freebsd.org"
>
-------------- next part --------------
Index: scsi_cd.c
===================================================================
RCS file: /usr1/ncvs/src/sys/cam/scsi/scsi_cd.c,v
retrieving revision 1.112
diff -u -r1.112 scsi_cd.c
--- scsi_cd.c 14 Nov 2009 20:13:38 -0000 1.112
+++ scsi_cd.c 1 Dec 2009 21:28:00 -0000
@@ -2673,12 +2673,10 @@
authinfo = (struct dvd_authinfo *)addr;
- cam_periph_lock(periph);
if (cmd == DVDIOCREPORTKEY)
error = cdreportkey(periph, authinfo);
else
error = cdsendkey(periph, authinfo);
- cam_periph_unlock(periph);
break;
}
case DVDIOCREADSTRUCTURE: {
@@ -2686,9 +2684,7 @@
dvdstruct = (struct dvd_struct *)addr;
- cam_periph_lock(periph);
error = cdreaddvdstructure(periph, dvdstruct);
- cam_periph_unlock(periph);
break;
}
@@ -3732,8 +3728,6 @@
databuf = NULL;
lba = 0;
- ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
-
switch (authinfo->format) {
case DVD_REPORT_AGID:
length = sizeof(struct scsi_report_key_data_agid);
@@ -3759,9 +3753,7 @@
length = 0;
break;
default:
- error = EINVAL;
- goto bailout;
- break; /* NOTREACHED */
+ return (EINVAL);
}
if (length != 0) {
@@ -3769,6 +3761,8 @@
} else
databuf = NULL;
+ cam_periph_lock(periph);
+ ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
scsi_report_key(&ccb->csio,
/* retries */ 1,
@@ -3870,11 +3864,12 @@
break; /* NOTREACHED */
}
bailout:
+ xpt_release_ccb(ccb);
+ cam_periph_unlock(periph);
+
if (databuf != NULL)
free(databuf, M_DEVBUF);
- xpt_release_ccb(ccb);
-
return(error);
}
@@ -3889,8 +3884,6 @@
error = 0;
databuf = NULL;
- ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
-
switch(authinfo->format) {
case DVD_SEND_CHALLENGE: {
struct scsi_report_key_data_challenge *challenge_data;
@@ -3942,11 +3935,12 @@
break;
}
default:
- error = EINVAL;
- goto bailout;
- break; /* NOTREACHED */
+ return (EINVAL);
}
+ cam_periph_lock(periph);
+ ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
+
scsi_send_key(&ccb->csio,
/* retries */ 1,
/* cbfcnp */ cddone,
@@ -3963,11 +3957,12 @@
bailout:
+ xpt_release_ccb(ccb);
+ cam_periph_unlock(periph);
+
if (databuf != NULL)
free(databuf, M_DEVBUF);
- xpt_release_ccb(ccb);
-
return(error);
}
@@ -3985,8 +3980,6 @@
/* The address is reserved for many of the formats */
address = 0;
- ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
-
switch(dvdstruct->format) {
case DVD_STRUCT_PHYSICAL:
length = sizeof(struct scsi_read_dvd_struct_data_physical);
@@ -4004,13 +3997,7 @@
length = sizeof(struct scsi_read_dvd_struct_data_manufacturer);
break;
case DVD_STRUCT_CMI:
- error = ENODEV;
- goto bailout;
-#ifdef notyet
- length = sizeof(struct scsi_read_dvd_struct_data_copy_manage);
- address = dvdstruct->address;
-#endif
- break; /* NOTREACHED */
+ return (ENODEV);
case DVD_STRUCT_PROTDISCID:
length = sizeof(struct scsi_read_dvd_struct_data_prot_discid);
break;
@@ -4027,21 +4014,9 @@
length = sizeof(struct scsi_read_dvd_struct_data_spare_area);
break;
case DVD_STRUCT_RMD_LAST:
- error = ENODEV;
- goto bailout;
-#ifdef notyet
- length = sizeof(struct scsi_read_dvd_struct_data_rmd_borderout);
- address = dvdstruct->address;
-#endif
- break; /* NOTREACHED */
+ return (ENODEV);
case DVD_STRUCT_RMD_RMA:
- error = ENODEV;
- goto bailout;
-#ifdef notyet
- length = sizeof(struct scsi_read_dvd_struct_data_rmd);
- address = dvdstruct->address;
-#endif
- break; /* NOTREACHED */
+ return (ENODEV);
case DVD_STRUCT_PRERECORDED:
length = sizeof(struct scsi_read_dvd_struct_data_leadin);
break;
@@ -4049,13 +4024,7 @@
length = sizeof(struct scsi_read_dvd_struct_data_disc_id);
break;
case DVD_STRUCT_DCB:
- error = ENODEV;
- goto bailout;
-#ifdef notyet
- length = sizeof(struct scsi_read_dvd_struct_data_dcb);
- address = dvdstruct->address;
-#endif
- break; /* NOTREACHED */
+ return (ENODEV);
case DVD_STRUCT_LIST:
/*
* This is the maximum allocation length for the READ DVD
@@ -4067,9 +4036,7 @@
length = 65535;
break;
default:
- error = EINVAL;
- goto bailout;
- break; /* NOTREACHED */
+ return (EINVAL);
}
if (length != 0) {
@@ -4077,6 +4044,9 @@
} else
databuf = NULL;
+ cam_periph_lock(periph);
+ ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
+
scsi_read_dvd_structure(&ccb->csio,
/* retries */ 1,
/* cbfcnp */ cddone,
@@ -4166,11 +4136,12 @@
}
bailout:
+ xpt_release_ccb(ccb);
+ cam_periph_unlock(periph);
+
if (databuf != NULL)
free(databuf, M_DEVBUF);
- xpt_release_ccb(ccb);
-
return(error);
}
More information about the freebsd-scsi
mailing list