scsi_ses.c fixes

Matthew Jacob mj at feral.com
Fri Feb 22 05:58:51 UTC 2008



On Wed, 20 Feb 2008, Scott Long wrote:

> Matthew Jacob wrote:
>> 
>> Well, no need to be embarassed. It's embarassing to not hear anything about 
>> for months- and this for something which as a driver configures with just 
>> about every backplane and storage unit out there. Nobody apparently 
>> installs and runs the examples ses code - probably they should be promoted 
>> to real modules.
>> 
>
> Yeah, I thought that I had tested against the example ses code at one 
> point, but apparently not.  While we're here, note the comment about 
> dropping the lock multiple times to do copyout.  That can probably be 
> easily fixed by allocating a temporary buffer to copy everything into 
> first, but I was hoping to find a more elegant solution.  If you have 
> any ideas, feel free to try them out.

You don't really need to lock the peripheral for some of the cases- the 
data is stable as long as periph doesn't go away, which it shouldn't as 
long as the user app had the device open. This plus u_int ->uint.

Index: scsi_ses.c
===================================================================
RCS file: /home/ncvs/src/sys/cam/scsi/scsi_ses.c,v
retrieving revision 1.36
diff -u -r1.36 scsi_ses.c
--- scsi_ses.c	20 Feb 2008 19:49:46 -0000	1.36
+++ scsi_ses.c	22 Feb 2008 05:56:32 -0000
@@ -144,9 +144,9 @@
  	encvec		ses_vec;	/* vector to handlers */
  	void *		ses_private;	/* per-type private data */
  	encobj *	ses_objmap;	/* objects */
-	u_int32_t	ses_nobjects;	/* number of objects */
+	uint32_t	ses_nobjects;	/* number of objects */
  	ses_encstat	ses_encstat;	/* overall status */
-	u_int8_t	ses_flags;
+	uint8_t		ses_flags;
  	union ccb	ses_saved_ccb;
  	struct cdev *ses_dev;
  	struct cam_periph *periph;
@@ -166,9 +166,9 @@
  static  periph_dtor_t   sescleanup;
  static  periph_start_t  sesstart;

-static void sesasync(void *, u_int32_t, struct cam_path *, void *);
+static void sesasync(void *, uint32_t, struct cam_path *, void *);
  static void sesdone(struct cam_periph *, union ccb *);
-static int seserror(union ccb *, u_int32_t, u_int32_t);
+static int seserror(union ccb *, uint32_t, uint32_t);

  static struct periph_driver sesdriver = {
  	sesinit, "ses",
@@ -234,7 +234,7 @@
  }

  static void
-sesasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
+sesasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
  {
  	struct cam_periph *periph;

@@ -303,7 +303,7 @@
  		return (CAM_REQ_CMP_ERR);
  	}

-	softc = malloc(sizeof (struct ses_softc), M_SCSISES, M_NOWAIT);
+	softc = SES_MALLOC(sizeof (struct ses_softc));
  	if (softc == NULL) {
  		printf("sesregister: Unable to probe new device. "
  		       "Unable to allocate softc\n"); 
@@ -472,7 +472,7 @@
  }

  static int
-seserror(union ccb *ccb, u_int32_t cflags, u_int32_t sflags)
+seserror(union ccb *ccb, uint32_t cflags, uint32_t sflags)
  {
  	struct ses_softc *softc;
  	struct cam_periph *periph;
@@ -489,7 +489,7 @@
  	struct cam_periph *periph;
  	ses_encstat tmp;
  	ses_objstat objs;
-	ses_object obj, *uobj;
+	ses_object *uobj;
  	struct ses_softc *ssc;
  	void *addr;
  	int error, i;
@@ -511,6 +511,9 @@

  	/*
  	 * Now check to see whether we're initialized or not.
+	 * This actually should never fail as we're not supposed
+	 * to get past ses_open w/o successfully initializing
+	 * things.
  	 */
  	if ((ssc->ses_flags & SES_FLAG_INITIALIZED) == 0) {
  		cam_periph_unlock(periph);
@@ -526,6 +529,14 @@
  	/*
  	 * If this command can change the device's state,
  	 * we must have the device open for writing.
+	 *
+	 * For commands that get information about the
+	 * device- we don't need to lock the peripheral
+	 * if we aren't running a command. The number
+	 * of objects and the contents will stay stable
+	 * after the first open that does initialization.
+	 * The periph also can't go away while a user
+	 * process has it open.
  	 */
  	switch (cmd) {
  	case SESIOC_GETNOBJ:
@@ -546,23 +557,16 @@
  		break;

  	case SESIOC_GETOBJMAP:
-		/*
-		 * XXX Dropping the lock while copying multiple segments is
-		 * bogus.
-		 */
-		cam_periph_lock(periph);
-		for (uobj = addr, i = 0; i != ssc->ses_nobjects; i++, uobj++) {
-			obj.obj_id = i;
-			obj.subencid = ssc->ses_objmap[i].subenclosure;
-			obj.object_type = ssc->ses_objmap[i].enctype;
-			cam_periph_unlock(periph);
-			error = copyout(&obj, uobj, sizeof (ses_object));
-			cam_periph_lock(periph);
+		for (uobj = addr, i = 0; i != ssc->ses_nobjects; i++) {
+			ses_object kobj;
+			kobj.obj_id = i;
+			kobj.subencid = ssc->ses_objmap[i].subenclosure;
+			kobj.object_type = ssc->ses_objmap[i].enctype;
+			error = copyout(&kobj, &uobj[i], sizeof (ses_object));
  			if (error) {
  				break;
  			}
  		}
-		cam_periph_unlock(periph);
  		break;

  	case SESIOC_GETENCSTAT:


More information about the freebsd-scsi mailing list