// Copyright (C) 2005, 2006 IBM Corp. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version /*********************************************************** * Trace the following activities of scsi layer: * * 1. I/O Entry * * 2. Issuing I/O to LLD * * 3. I/O done by LLD * * 4. I/O Complete * * * ***********************************************************/ %{ #include #include #include #include #include #include %} probe addevent.scsi = addevent.scsi.ioentry, addevent.scsi.iodispatching, addevent.scsi.iodone, addevent.scsi.iocompleted {} /* mid-layer prepare a IO request */ probe addevent.scsi.ioentry += _addevent.scsi.ioentry { update_record() } probe _addevent.scsi.ioentry = scsi.ioentry { log_scsi_ioentry(disk_major, disk_minor, device_state, req_addr) } /* Dispatch a command to the low-level driver. */ probe addevent.scsi.iodispatching += _addevent.scsi.iodispatching { update_record() } probe _addevent.scsi.iodispatching = scsi.iodispatching { log_scsi_dispatch(host_no, channel, lun, dev_id, device_state, data_direction, request_buffer, request_bufflen, req_addr) } /* I/O is done by low-level driver*/ probe addevent.scsi.iodone += _addevent.scsi.iodone { update_record() } probe _addevent.scsi.iodone = scsi.iodone { /* scsi timer check. We should record the hook only * when the timer is inactive. But there's a gap between * the checking and the actual calling of scsi_delete_timer. */ if( scsi_timer_pending == 1) { log_scsi_iodone_extra(host_no, channel, lun, dev_id, device_state, data_direction, req_addr) } } /* mid-layer processes the completed IO */ probe addevent.scsi.iocompleted += _addevent.scsi.iocompleted { update_record() } probe _addevent.scsi.iocompleted = scsi.iocompleted { log_scsi_iocompleted(host_no, channel, lun, dev_id, device_state, data_direction, req_addr, goodbytes) } /* log the info about scsi io entry */ function log_scsi_ioentry(major:long, minor:long, dev_state:long, req_addr:long) %{ /* major|minor|scsi_device_state|request_addr */ _lket_trace(_GROUP_SCSI, _HOOKID_SCSI_IOENTRY, "%1b%1b%1b%8b", THIS->major, THIS->minor, THIS->dev_state, THIS->req_addr); %} /* log the info about scsi_dispatching_cmd */ function log_scsi_dispatch(host_no:long, channel:long, lun:long, dev_id:long, device_state:long, data_direction:long, request_buffer:long, request_bufflen:long, req_addr:long) %{ _lket_trace(_GROUP_SCSI, _HOOKID_SCSI_IO_TO_LLD, "%1b%1b%1b%1b%1b%1b%8b%4b%8b", THIS->host_no, THIS->channel, THIS->lun, THIS->dev_id, THIS->device_state, THIS->data_direction, THIS->request_buffer, THIS->request_bufflen, THIS->req_addr); %} /* log the info about scsi_done */ function log_scsi_iodone_extra(host_no:long, channel:long, lun:long, dev_id:long, device_state:long, data_direction:long, req_addr:long) %{ _lket_trace(_GROUP_SCSI, _HOOKID_SCSI_IODONE_BY_LLD, "%1b%1b%1b%1b%1b%1b%8b", THIS->host_no, THIS->channel, THIS->lun, THIS->dev_id, THIS->device_state, THIS->data_direction, THIS->req_addr); %} /* log the info about scsi_dispatching_cmd */ function log_scsi_iocompleted(host_no:long, channel:long, lun:long, dev_id:long, device_state:long, data_direction:long, req_addr:long, goodbytes:long) %{ _lket_trace(_GROUP_SCSI, _HOOKID_SCSI_IOCOMP_BY_MIDLEVEL, "%1b%1b%1b%1b%1b%1b%8b%4b", THIS->host_no, THIS->channel, THIS->lun, THIS->dev_id, THIS->device_state, THIS->data_direction, THIS->req_addr, THIS->goodbytes); %} probe never { printf("%d\n", GROUP_SCSI) }