need some debugging help

Kenneth D. Merry ken at kdm.org
Fri Aug 29 21:04:00 PDT 2003


I've been working on a set of patches to remove the sysctl variable creation
from interrupt context in the cd(4) and da(4) drivers.

To fix the problem, I've created a new taskqueue that runs in a thread
context, instead of inside a software interrupt like the current task
queues.  (The eventual fix will involve moving the CAM probe inside a
thread; this will provide a more temporary solution that will hopefully
also work on -stable, until we can change the CAM probe code.)

I think I have everything setup correctly, but I keep getting panics inside
the GEOM code with these patches.  (Memory modified after free.)  I don't
know whether I've just exposed some race condition, or whether I've done
something wrong.

I've seen several different panics, all with the same root cause (memory
modified after free), and with two different previous memory pools -- geom
and devbuf.

==========================================================================
SMP: AP CPU #1 Launched!
Memory modified after free 0xcbd4f800(124)
panic: Most recently used by GEOM

cpuid = 0; lapic.id = 00000000
Debugger("panic")
Stopped at      Debugger+0x55:  xchgl   %ebx,in_Debugger.0
db> trace
Debugger(c03e974d,0,c03fb4d8,e5e45934,100) at Debugger+0x55
panic(c03fb4d8,c03e55db,7c,c083ac14,c083ac00) at panic+0x15f
mtrash_ctor(cbd4f800,80,0,57a,cbd4f800) at mtrash_ctor+0x5d
uma_zalloc_arg(c083ac00,0,102,e5e4599c,e5e4599c) at uma_zalloc_arg+0x1e4
malloc(5b,c042fae0,102,1,c02756e4) at malloc+0xd3
g_new_providerf(cbda62c0,cbd7b130,e5e45a3c,1,1) at g_new_providerf+0xa3
g_slice_config(cbda62c0,2,1,0,0) at g_slice_config+0x259
g_bsd_modify(cbda62c0,cbd7712c,e5e45c8c,10,cbd77000) at g_bsd_modify+0x382
g_bsd_taste(c0470480,cbda5780,0,159,cbda5700) at g_bsd_taste+0x2c4
g_new_provider_event(cbda5780,0,c03e52b7,b3,66666667) at g_new_provider_event+0xad
one_event(e5e45d0c,c021cd85,c0485fb4,0,4c) at one_event+0x218
g_run_events(c0485fb4,0,4c,c03d7a28,a) at g_run_events+0x15
g_event_procbody(0,e5e45d48,c03e738b,314,34df1a6d) at g_event_procbody+0x45
fork_exit(c021cd40,0,e5e45d48) at fork_exit+0xcf
fork_trampoline() at fork_trampoline+0x8
--- trap 0x1, eip = 0, esp = 0xe5e45d7c, ebp = 0 ---
db> panic

==========================================================================
SMP: AP CPU #1 Launched!
Memory modified after free 0xcbd4f600(124)
panic: Most recently used by devbuf

cpuid = 0; lapic.id = 00000000
Debugger("panic")
Stopped at      Debugger+0x55:  xchgl   %ebx,in_Debugger.0
db> trace
Debugger(c03e974d,0,c03fb4d8,e5e45af0,100) at Debugger+0x55
panic(c03fb4d8,c03e7f50,7c,c083ac14,c083ac00) at panic+0x15f
mtrash_ctor(cbd4f600,80,0,57a,cbd4f600) at mtrash_ctor+0x5d
uma_zalloc_arg(c083ac00,0,102,e5e45b58,e5e45b58) at uma_zalloc_arg+0x1e4
malloc(5a,c042fae0,102,1,c02756e4) at malloc+0xd3
g_new_providerf(cbda74c0,cb9b0d90,e5e45bf8,1,1) at g_new_providerf+0xa3
g_slice_config(cbda74c0,0,1,7e00,0) at g_slice_config+0x259
g_mbr_modify(cbda74c0,cb9d3800,cbd5b200,123,0) at g_mbr_modify+0x247
g_mbr_taste(c0470560,cbd4ee80,0,159,cbd4f580) at g_mbr_taste+0x1be
g_new_provider_event(cbd4ee80,0,c03e52b7,b3,66666667) at g_new_provider_event+0xad
one_event(e5e45d0c,c021cd85,c0485fb4,0,4c) at one_event+0x218
g_run_events(c0485fb4,0,4c,c03d7a28,a) at g_run_events+0x15
g_event_procbody(0,e5e45d48,c03e738b,314,34df1a6d) at g_event_procbody+0x45
fork_exit(c021cd40,0,e5e45d48) at fork_exit+0xcf
fork_trampoline() at fork_trampoline+0x8
--- trap 0x1, eip = 0, esp = 0xe5e45d7c, ebp = 0 ---
db> panic
==========================================================================

Memory modified after free 0xcbd4f600(124)
panic: Most recently used by devbuf

cpuid = 0; lapic.id = 00000000
Debugger("panic")
Stopped at      Debugger+0x55:  xchgl   %ebx,in_Debugger.0
db> trace
Debugger(c03e974d,0,c03fb4d8,e5e45bbc,100) at Debugger+0x55
panic(c03fb4d8,c03e7f50,7c,c083ac14,c083ac00) at panic+0x15f
mtrash_ctor(cbd4f600,80,0,57a,cbd4f600) at mtrash_ctor+0x5d
uma_zalloc_arg(c083ac00,0,102,fe,cbd6b800) at uma_zalloc_arg+0x1e4
malloc(60,c042fae0,102,cbd59240,c0470560) at malloc+0xd3
g_slice_alloc(4,214,cbd4f4d4,1c2,e5e45c9c) at g_slice_alloc+0x7e
g_slice_new(c0470560,4,cbd4f480,e5e45c98,e5e45c9c) at g_slice_new+0x6f
g_mbr_taste(c0470560,cbd4f480,0,159,cbd4f580) at g_mbr_taste+0x90
g_new_provider_event(cbd4f480,0,c03e52b7,b3,66666667) at g_new_provider_event+0xad
one_event(e5e45d0c,c021cd85,c0485fb4,0,4c) at one_event+0x218
g_run_events(c0485fb4,0,4c,c03d7a28,a) at g_run_events+0x15
g_event_procbody(0,e5e45d48,c03e738b,314,34df1a6d) at g_event_procbody+0x45
fork_exit(c021cd40,0,e5e45d48) at fork_exit+0xcf
fork_trampoline() at fork_trampoline+0x8
--- trap 0x1, eip = 0, esp = 0xe5e45d7c, ebp = 0 ---
db> 
==========================================================================
SMP: AP CPU #1 Launched!
Memory modified after free 0xcbd4f600(124)
panic: Most recently used by devbuf

cpuid = 0; lapic.id = 00000000
Debugger("panic")
Stopped at      Debugger+0x55:  xchgl   %ebx,in_Debugger.0
db> trace
Debugger(c03e974d,0,c03fb4d8,e5e45aa8,100) at Debugger+0x55
panic(c03fb4d8,c03e7f50,7c,c083ac14,c083ac00) at panic+0x15f
mtrash_ctor(cbd4f600,80,0,57a,cbd4f600) at mtrash_ctor+0x5d
uma_zalloc_arg(c083ac00,0,102,5c,cbd4f900) at uma_zalloc_arg+0x1e4
malloc(64,c042fae0,102,cbd4f900,2) at malloc+0xd3
g_post_event_x(c021ea70,cbd4f900,2,0,e5e45b6c) at g_post_event_x+0x54
g_post_event(c021ea70,cbd4f900,2,cbd4f900,0) at g_post_event+0x45
g_new_providerf(cbda3540,cb9b0b20,e5e45bf8,1,1) at g_new_providerf+0x151
g_slice_config(cbda3540,0,1,7e00,0) at g_slice_config+0x259
g_mbr_modify(cbda3540,cbd6c400,cbd73000,123,0) at g_mbr_modify+0x247
g_mbr_taste(c0470560,cbd4f700,0,159,cbd4f780) at g_mbr_taste+0x1be
g_new_provider_event(cbd4f700,0,c03e52b7,b3,66666667) at g_new_provider_event+0xad
one_event(e5e45d0c,c021cd85,c0485fb4,0,4c) at one_event+0x218
g_run_events(c0485fb4,0,4c,c03d7a28,a) at g_run_events+0x15
g_event_procbody(0,e5e45d48,c03e738b,314,34df1a6d) at g_event_procbody+0x45
fork_exit(c021cd40,0,e5e45d48) at fork_exit+0xcf
fork_trampoline() at fork_trampoline+0x8
--- trap 0x1, eip = 0, esp = 0xe5e45d7c, ebp = 0 ---

==========================================================================

Since the panics involved either M_DEVBUF or M_GEOM, I removed all M_DEVBUF
mallocs from the cd(4) and da(4) drivers.  (None of the other affected code
used M_DEVBUF; I created new malloc types for the cd(4) and da(4) drivers.)

The problem didn't change.  (Other than the exact place in GEOM that
triggered the malloc that caught the problem.)

Anyway, I've attached the patch in question.  If someone could tell me what
(if anything) I'm doing wrong, I'd appreciate it!

Thanks,

Ken
-- 
Kenneth Merry
ken at kdm.org
-------------- next part --------------
==== //depot/FreeBSD-ken/src/sys/cam/scsi/scsi_cd.c#39 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_cd.c ====
*** /tmp/tmp.285.0	Fri Aug 29 21:34:15 2003
--- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_cd.c	Fri Aug 29 21:16:37 2003
***************
*** 62,67 ****
--- 62,68 ----
  #include <sys/dvdio.h>
  #include <sys/devicestat.h>
  #include <sys/sysctl.h>
+ #include <sys/taskqueue.h>
  
  #include <cam/cam.h>
  #include <cam/cam_ccb.h>
***************
*** 154,159 ****
--- 155,161 ----
  	eventhandler_tag	clonetag;
  	int			minimum_command_size;
  	int			outstanding_cmds;
+ 	struct task		sysctl_task;
  	struct sysctl_ctx_list	sysctl_ctx;
  	struct sysctl_oid	*sysctl_tree;
  	STAILQ_HEAD(, cd_mode_params)	mode_queue;
***************
*** 311,316 ****
--- 313,320 ----
  #define CHANGER_MAX_BUSY_SECONDS	15
  #endif
  
+ MALLOC_DEFINE(M_CAM_CD, "cdbuffers", "Buffers for cd(4)");
+ 
  static int changer_min_busy_seconds = CHANGER_MIN_BUSY_SECONDS;
  static int changer_max_busy_seconds = CHANGER_MAX_BUSY_SECONDS;
  
***************
*** 524,536 ****
  			      changer_links);
  		xpt_print_path(periph->path);
  		printf("removing changer entry\n");
! 		free(softc->changer, M_DEVBUF);
  		num_changers--;
  	}
  	devstat_remove_entry(softc->device_stats);
  	destroy_dev(softc->dev);
  	EVENTHANDLER_DEREGISTER(dev_clone, softc->clonetag);
! 	free(softc, M_DEVBUF);
  	splx(s);
  }
  
--- 528,540 ----
  			      changer_links);
  		xpt_print_path(periph->path);
  		printf("removing changer entry\n");
! 		free(softc->changer, M_CAM_CD);
  		num_changers--;
  	}
  	devstat_remove_entry(softc->device_stats);
  	destroy_dev(softc->dev);
  	EVENTHANDLER_DEREGISTER(dev_clone, softc->clonetag);
! 	free(softc, M_CAM_CD);
  	splx(s);
  }
  
***************
*** 598,603 ****
--- 602,644 ----
  	}
  }
  
+ static void
+ cdsysctlinit(void *context, int pending)
+ {
+ 	struct cam_periph *periph;
+ 	struct cd_softc *softc;
+ 	char tmpstr[80], tmpstr2[80];
+ 
+ 	periph = (struct cam_periph *)context;
+ 	softc = (struct cd_softc *)periph->softc;
+ 
+ 	snprintf(tmpstr, sizeof(tmpstr), "CAM CD unit %d", periph->unit_number);
+ 	snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
+ 
+ 	mtx_lock(&Giant);
+ 
+ 	sysctl_ctx_init(&softc->sysctl_ctx);
+ 	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
+ 		SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO,
+ 		tmpstr2, CTLFLAG_RD, 0, tmpstr);
+ 
+ 	if (softc->sysctl_tree == NULL) {
+ 		printf("cdsysctlinit: unable to allocate sysctl tree\n");
+ 		return;
+ 	}
+ 
+ 	/*
+ 	 * Now register the sysctl handler, so the user can the value on
+ 	 * the fly.
+ 	 */
+ 	SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
+ 		OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
+ 		&softc->minimum_command_size, 0, cdcmdsizesysctl, "I",
+ 		"Minimum CDB size");
+ 
+ 	mtx_unlock(&Giant);
+ }
+ 
  /*
   * We have a handler function for this so we can check the values when the
   * user sets them, instead of every time we look at them.
***************
*** 642,648 ****
  	struct ccb_setasync csa;
  	struct ccb_pathinq cpi;
  	struct ccb_getdev *cgd;
! 	char tmpstr[80], tmpstr2[80];
  	caddr_t match;
  
  	cgd = (struct ccb_getdev *)arg;
--- 683,689 ----
  	struct ccb_setasync csa;
  	struct ccb_pathinq cpi;
  	struct ccb_getdev *cgd;
! 	char tmpstr[80];
  	caddr_t match;
  
  	cgd = (struct ccb_getdev *)arg;
***************
*** 655,661 ****
  		return(CAM_REQ_CMP_ERR);
  	}
  
! 	softc = (struct cd_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT);
  
  	if (softc == NULL) {
  		printf("cdregister: Unable to probe new device. "
--- 696,702 ----
  		return(CAM_REQ_CMP_ERR);
  	}
  
! 	softc = (struct cd_softc *)malloc(sizeof(*softc),M_CAM_CD,M_NOWAIT);
  
  	if (softc == NULL) {
  		printf("cdregister: Unable to probe new device. "
***************
*** 696,712 ****
  	if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
  		softc->quirks |= CD_Q_10_BYTE_ONLY;
  
! 	snprintf(tmpstr, sizeof(tmpstr), "CAM CD unit %d", periph->unit_number);
! 	snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
! 	sysctl_ctx_init(&softc->sysctl_ctx);
! 	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
! 		SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO,
! 		tmpstr2, CTLFLAG_RD, 0, tmpstr);
! 	if (softc->sysctl_tree == NULL) {
! 		printf("cdregister: unable to allocate sysctl tree\n");
! 		free(softc, M_DEVBUF);
! 		return (CAM_REQ_CMP_ERR);
! 	}
  
  	/* The default is 6 byte commands, unless quirked otherwise */
  	if (softc->quirks & CD_Q_10_BYTE_ONLY)
--- 737,743 ----
  	if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
  		softc->quirks |= CD_Q_10_BYTE_ONLY;
  
! 	TASK_INIT(&softc->sysctl_task, 0, cdsysctlinit, periph);
  
  	/* The default is 6 byte commands, unless quirked otherwise */
  	if (softc->quirks & CD_Q_10_BYTE_ONLY)
***************
*** 728,742 ****
  		softc->minimum_command_size = 10;
  
  	/*
- 	 * Now register the sysctl handler, so the user can the value on
- 	 * the fly.
- 	 */
- 	SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
- 		OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
- 		&softc->minimum_command_size, 0, cdcmdsizesysctl, "I",
- 		"Minimum CDB size");
- 
- 	/*
  	 * We need to register the statistics structure for this device,
  	 * but we don't have the blocksize yet for it.  So, we register
  	 * the structure and indicate that we don't have the blocksize
--- 759,764 ----
***************
*** 889,895 ****
  		 */
  		else {
  			nchanger = malloc(sizeof(struct cdchanger),
! 				M_DEVBUF, M_NOWAIT);
  
  			if (nchanger == NULL) {
  				softc->flags &= ~CD_FLAG_CHANGER;
--- 911,917 ----
  		 */
  		else {
  			nchanger = malloc(sizeof(struct cdchanger),
! 				M_CAM_CD, M_NOWAIT);
  
  			if (nchanger == NULL) {
  				softc->flags &= ~CD_FLAG_CHANGER;
***************
*** 1847,1852 ****
--- 1869,1879 ----
  			xpt_announce_periph(periph, announce_buf);
  			if (softc->flags & CD_FLAG_CHANGER)
  				cdchangerschedule(softc);
+ 			/*
+ 			 * Create our sysctl variables, now that we know
+ 			 * we have successfully attached.
+ 			 */
+ 			taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
  		}
  		softc->state = CD_STATE_NORMAL;		
  		/*
***************
*** 3716,3722 ****
  	}
  
  	if (length != 0) {
! 		databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
  	} else
  		databuf = NULL;
  
--- 3743,3749 ----
  	}
  
  	if (length != 0) {
! 		databuf = malloc(length, M_CAM_CD, M_WAITOK | M_ZERO);
  	} else
  		databuf = NULL;
  
***************
*** 3823,3829 ****
  	}
  bailout:
  	if (databuf != NULL)
! 		free(databuf, M_DEVBUF);
  
  	xpt_release_ccb(ccb);
  
--- 3850,3856 ----
  	}
  bailout:
  	if (databuf != NULL)
! 		free(databuf, M_CAM_CD);
  
  	xpt_release_ccb(ccb);
  
***************
*** 3849,3855 ****
  
  		length = sizeof(*challenge_data);
  
! 		challenge_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
  
  		databuf = (u_int8_t *)challenge_data;
  
--- 3876,3882 ----
  
  		length = sizeof(*challenge_data);
  
! 		challenge_data = malloc(length, M_CAM_CD, M_WAITOK | M_ZERO);
  
  		databuf = (u_int8_t *)challenge_data;
  
***************
*** 3866,3872 ****
  
  		length = sizeof(*key2_data);
  
! 		key2_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
  
  		databuf = (u_int8_t *)key2_data;
  
--- 3893,3899 ----
  
  		length = sizeof(*key2_data);
  
! 		key2_data = malloc(length, M_CAM_CD, M_WAITOK | M_ZERO);
  
  		databuf = (u_int8_t *)key2_data;
  
***************
*** 3883,3889 ****
  
  		length = sizeof(*rpc_data);
  
! 		rpc_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
  
  		databuf = (u_int8_t *)rpc_data;
  
--- 3910,3916 ----
  
  		length = sizeof(*rpc_data);
  
! 		rpc_data = malloc(length, M_CAM_CD, M_WAITOK | M_ZERO);
  
  		databuf = (u_int8_t *)rpc_data;
  
***************
*** 3916,3922 ****
  bailout:
  
  	if (databuf != NULL)
! 		free(databuf, M_DEVBUF);
  
  	xpt_release_ccb(ccb);
  
--- 3943,3949 ----
  bailout:
  
  	if (databuf != NULL)
! 		free(databuf, M_CAM_CD);
  
  	xpt_release_ccb(ccb);
  
***************
*** 4025,4031 ****
  	}
  
  	if (length != 0) {
! 		databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
  	} else
  		databuf = NULL;
  
--- 4052,4058 ----
  	}
  
  	if (length != 0) {
! 		databuf = malloc(length, M_CAM_CD, M_WAITOK | M_ZERO);
  	} else
  		databuf = NULL;
  
***************
*** 4119,4125 ****
  bailout:
  
  	if (databuf != NULL)
! 		free(databuf, M_DEVBUF);
  
  	xpt_release_ccb(ccb);
  
--- 4146,4152 ----
  bailout:
  
  	if (databuf != NULL)
! 		free(databuf, M_CAM_CD);
  
  	xpt_release_ccb(ccb);
  
==== //depot/FreeBSD-ken/src/sys/cam/scsi/scsi_da.c#59 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_da.c ====
*** /tmp/tmp.285.1	Fri Aug 29 21:34:15 2003
--- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_da.c	Fri Aug 29 21:22:33 2003
***************
*** 48,53 ****
--- 48,54 ----
  #include <sys/eventhandler.h>
  #include <sys/malloc.h>
  #include <sys/cons.h>
+ #include <sys/taskqueue.h>
  
  #include <machine/md_var.h>
  
***************
*** 133,138 ****
--- 134,140 ----
  	struct	 disk_params params;
  	struct	 disk disk;
  	union	 ccb saved_ccb;
+ 	struct task		sysctl_task;
  	struct sysctl_ctx_list	sysctl_ctx;
  	struct sysctl_oid	*sysctl_tree;
  };
***************
*** 388,393 ****
--- 390,396 ----
  static	periph_init_t	dainit;
  static	void		daasync(void *callback_arg, u_int32_t code,
  				struct cam_path *path, void *arg);
+ static	void		dasysctlinit(void *context, int pending);
  static	int		dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
  static	periph_ctor_t	daregister;
  static	periph_dtor_t	dacleanup;
***************
*** 412,417 ****
--- 415,422 ----
  #define	DA_DEFAULT_RETRY	4
  #endif
  
+ MALLOC_DEFINE(M_CAM_DA, "dabuffers", "Buffers for da(4)");
+ 
  static int da_retry_count = DA_DEFAULT_RETRY;
  static int da_default_timeout = DA_DEFAULT_TIMEOUT;
  
***************
*** 848,854 ****
  		printf("can't remove sysctl context\n");
  	}
  	disk_destroy(&softc->disk);
! 	free(softc, M_DEVBUF);
  }
  
  static void
--- 853,859 ----
  		printf("can't remove sysctl context\n");
  	}
  	disk_destroy(&softc->disk);
! 	free(softc, M_CAM_DA);
  }
  
  static void
***************
*** 915,920 ****
--- 920,960 ----
  	}
  }
  
+ static void
+ dasysctlinit(void *context, int pending)
+ {
+ 	struct cam_periph *periph;
+ 	struct da_softc *softc;
+ 	char tmpstr[80], tmpstr2[80];
+ 
+ 	periph = (struct cam_periph *)context;
+ 	softc = (struct da_softc *)periph;
+ 
+ 	snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
+ 	snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
+ 
+ 	mtx_lock(&Giant);
+ 	sysctl_ctx_init(&softc->sysctl_ctx);
+ 	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
+ 		SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
+ 		CTLFLAG_RD, 0, tmpstr);
+ 	if (softc->sysctl_tree == NULL) {
+ 		printf("dasysctlinit: unable to allocate sysctl tree\n");
+ 		return;
+ 	}
+ 
+ 	/*
+ 	 * Now register the sysctl handler, so the user can the value on
+ 	 * the fly.
+ 	 */
+ 	SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
+ 		OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
+ 		&softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
+ 		"Minimum CDB size");
+ 
+ 	mtx_unlock(&Giant);
+ }
+ 
  static int
  dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
  {
***************
*** 955,961 ****
  	struct ccb_setasync csa;
  	struct ccb_pathinq cpi;
  	struct ccb_getdev *cgd;
! 	char tmpstr[80], tmpstr2[80];
  	caddr_t match;
  
  	cgd = (struct ccb_getdev *)arg;
--- 995,1001 ----
  	struct ccb_setasync csa;
  	struct ccb_pathinq cpi;
  	struct ccb_getdev *cgd;
! 	char tmpstr[80];
  	caddr_t match;
  
  	cgd = (struct ccb_getdev *)arg;
***************
*** 969,975 ****
  		return(CAM_REQ_CMP_ERR);
  	}
  
! 	softc = (struct da_softc *)malloc(sizeof(*softc), M_DEVBUF,
  	    M_NOWAIT|M_ZERO);
  
  	if (softc == NULL) {
--- 1009,1015 ----
  		return(CAM_REQ_CMP_ERR);
  	}
  
! 	softc = (struct da_softc *)malloc(sizeof(*softc), M_CAM_DA,
  	    M_NOWAIT|M_ZERO);
  
  	if (softc == NULL) {
***************
*** 1008,1024 ****
  	if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
  		softc->quirks |= DA_Q_NO_6_BYTE;
  
! 	snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
! 	snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
! 	sysctl_ctx_init(&softc->sysctl_ctx);
! 	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
! 		SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
! 		CTLFLAG_RD, 0, tmpstr);
! 	if (softc->sysctl_tree == NULL) {
! 		printf("daregister: unable to allocate sysctl tree\n");
! 		free(softc, M_DEVBUF);
! 		return (CAM_REQ_CMP_ERR);
! 	}
  
  	/*
  	 * RBC devices don't have to support READ(6), only READ(10).
--- 1048,1054 ----
  	if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
  		softc->quirks |= DA_Q_NO_6_BYTE;
  
! 	TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph);
  
  	/*
  	 * RBC devices don't have to support READ(6), only READ(10).
***************
*** 1050,1064 ****
  		softc->minimum_cmd_size = 16;
  
  	/*
- 	 * Now register the sysctl handler, so the user can the value on
- 	 * the fly.
- 	 */
- 	SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
- 		OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
- 		&softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
- 		"Minimum CDB size");
- 
- 	/*
  	 * Block our timeout handler while we
  	 * add this softc to the dev list.
  	 */
--- 1080,1085 ----
***************
*** 1539,1546 ****
  			}
  		}
  		free(csio->data_ptr, M_TEMP);
! 		if (announce_buf[0] != '\0')
  			xpt_announce_periph(periph, announce_buf);
  		softc->state = DA_STATE_NORMAL;	
  		/*
  		 * Since our peripheral may be invalidated by an error
--- 1560,1573 ----
  			}
  		}
  		free(csio->data_ptr, M_TEMP);
! 		if (announce_buf[0] != '\0') {
  			xpt_announce_periph(periph, announce_buf);
+ 			/*
+ 			 * Create our sysctl variables, now that we know
+ 			 * we have successfully attached.
+ 			 */
+ 			taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
+ 		}
  		softc->state = DA_STATE_NORMAL;	
  		/*
  		 * Since our peripheral may be invalidated by an error
==== //depot/FreeBSD-ken/src/sys/kern/subr_taskqueue.c#12 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/kern/subr_taskqueue.c ====
*** /tmp/tmp.285.2	Fri Aug 29 21:34:15 2003
--- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/kern/subr_taskqueue.c	Fri Aug 29 18:47:53 2003
***************
*** 36,41 ****
--- 36,43 ----
  #include <sys/malloc.h>
  #include <sys/mutex.h>
  #include <sys/taskqueue.h>
+ #include <sys/kthread.h>
+ #include <sys/unistd.h>
  
  static MALLOC_DEFINE(M_TASKQUEUE, "taskqueue", "Task Queues");
  
***************
*** 44,49 ****
--- 46,52 ----
  static void	*taskqueue_ih;
  static void	*taskqueue_giant_ih;
  static struct mtx taskqueue_queues_mutex;
+ static struct proc *taskqueue_thread_proc;
  
  struct taskqueue {
  	STAILQ_ENTRY(taskqueue)	tq_link;
***************
*** 233,238 ****
--- 236,266 ----
  	taskqueue_run(taskqueue_swi_giant);
  }
  
+ static void
+ taskqueue_kthread(void *arg)
+ {
+ 	struct mtx kthread_mutex;
+ 
+ 	bzero(&kthread_mutex, sizeof(kthread_mutex));
+ 
+ 	mtx_init(&kthread_mutex, "taskqueue kthread", NULL, MTX_DEF);
+ 
+ 	mtx_lock(&kthread_mutex);
+ 
+ 	for (;;) {
+ 		mtx_unlock(&kthread_mutex);
+ 		taskqueue_run(taskqueue_thread);
+ 		mtx_lock(&kthread_mutex);
+ 		msleep(&taskqueue_thread, &kthread_mutex, PWAIT, "tqthr", 0); 
+ 	}
+ }
+ 
+ static void
+ taskqueue_thread_enqueue(void *context)
+ {
+ 	wakeup(&taskqueue_thread);
+ }
+ 
  TASKQUEUE_DEFINE(swi, taskqueue_swi_enqueue, 0,
  		 swi_add(NULL, "task queue", taskqueue_swi_run, NULL, SWI_TQ,
  		     INTR_MPSAFE, &taskqueue_ih)); 
***************
*** 240,242 ****
--- 268,274 ----
  TASKQUEUE_DEFINE(swi_giant, taskqueue_swi_giant_enqueue, 0,
  		 swi_add(NULL, "Giant task queue", taskqueue_swi_giant_run,
  		     NULL, SWI_TQ_GIANT, 0, &taskqueue_giant_ih)); 
+ 
+ TASKQUEUE_DEFINE(thread, taskqueue_thread_enqueue, 0,
+ 		 kthread_create(taskqueue_kthread, NULL,
+ 		 &taskqueue_thread_proc, RFNOWAIT, 0, "taskqueue"));
==== //depot/FreeBSD-ken/src/sys/sys/taskqueue.h#4 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/sys/taskqueue.h ====
*** /tmp/tmp.285.3	Fri Aug 29 21:34:15 2003
--- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/sys/taskqueue.h	Wed Aug 27 22:06:06 2003
***************
*** 112,116 ****
--- 112,117 ----
   */
  TASKQUEUE_DECLARE(swi_giant);
  TASKQUEUE_DECLARE(swi);
+ TASKQUEUE_DECLARE(thread);
  
  #endif /* !_SYS_TASKQUEUE_H_ */


More information about the freebsd-current mailing list