Print this page
4781 sd shouldn't abuse ddi_get_time(9f)
Reviewed by: Richard Elling <richard.elling@gmail.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>


   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 /*
  26  * Copyright (c) 2011 Bayard G. Bell.  All rights reserved.
  27  * Copyright (c) 2012 by Delphix. All rights reserved.
  28  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  29  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
  30  */
  31 /*
  32  * Copyright 2011 cyril.galibern@opensvc.com
  33  */
  34 
  35 /*
  36  * SCSI disk target driver.
  37  */
  38 #include <sys/scsi/scsi.h>
  39 #include <sys/dkbad.h>
  40 #include <sys/dklabel.h>
  41 #include <sys/dkio.h>
  42 #include <sys/fdio.h>
  43 #include <sys/cdio.h>
  44 #include <sys/mhd.h>
  45 #include <sys/vtoc.h>
  46 #include <sys/dktp/fdisk.h>
  47 #include <sys/kstat.h>
  48 #include <sys/vtrace.h>


6524  *    Function: sd_pm_idletimeout_handler
6525  *
6526  * Description: A timer routine that's active only while a device is busy.
6527  *              The purpose is to extend slightly the pm framework's busy
6528  *              view of the device to prevent busy/idle thrashing for
6529  *              back-to-back commands. Do this by comparing the current time
6530  *              to the time at which the last command completed and when the
6531  *              difference is greater than sd_pm_idletime, call
6532  *              pm_idle_component. In addition to indicating idle to the pm
6533  *              framework, update the chain type to again use the internal pm
6534  *              layers of the driver.
6535  *
6536  *   Arguments: arg - driver soft state (unit) structure
6537  *
6538  *     Context: Executes in a timeout(9F) thread context
6539  */
6540 
6541 static void
6542 sd_pm_idletimeout_handler(void *arg)
6543 {

6544         struct sd_lun *un = arg;
6545 
6546         time_t  now;
6547 
6548         mutex_enter(&sd_detach_mutex);
6549         if (un->un_detach_count != 0) {
6550                 /* Abort if the instance is detaching */
6551                 mutex_exit(&sd_detach_mutex);
6552                 return;
6553         }
6554         mutex_exit(&sd_detach_mutex);
6555 
6556         now = ddi_get_time();
6557         /*
6558          * Grab both mutexes, in the proper order, since we're accessing
6559          * both PM and softstate variables.
6560          */
6561         mutex_enter(SD_MUTEX(un));
6562         mutex_enter(&un->un_pm_mutex);
6563         if (((now - un->un_pm_idle_time) > sd_pm_idletime) &&
6564             (un->un_ncmds_in_driver == 0) && (un->un_pm_count == 0)) {
6565                 /*
6566                  * Update the chain types.
6567                  * This takes affect on the next new command received.
6568                  */
6569                 if (un->un_f_non_devbsize_supported) {
6570                         un->un_buf_chain_type = SD_CHAIN_INFO_RMMEDIA;
6571                 } else {
6572                         un->un_buf_chain_type = SD_CHAIN_INFO_DISK;
6573                 }
6574                 un->un_uscsi_chain_type = SD_CHAIN_INFO_USCSI_CMD;
6575 
6576                 SD_TRACE(SD_LOG_IO_PM, un,
6577                     "sd_pm_idletimeout_handler: idling device\n");
6578                 (void) pm_idle_component(SD_DEVINFO(un), 0);
6579                 un->un_pm_idle_timeid = NULL;
6580         } else {
6581                 un->un_pm_idle_timeid =
6582                     timeout(sd_pm_idletimeout_handler, un,
6583                     (drv_usectohz((clock_t)300000))); /* 300 ms. */


12444         ASSERT(un != NULL);
12445         ASSERT(bp != NULL);
12446         ASSERT(!mutex_owned(SD_MUTEX(un)));
12447 
12448         SD_TRACE(SD_LOG_IO_CORE, un, "sd_buf_iodone: entry.\n");
12449 
12450         xp = SD_GET_XBUF(bp);
12451         ASSERT(xp != NULL);
12452 
12453         /* xbuf is gone after this */
12454         if (ddi_xbuf_done(bp, un->un_xbuf_attr)) {
12455                 mutex_enter(SD_MUTEX(un));
12456 
12457                 /*
12458                  * Grab time when the cmd completed.
12459                  * This is used for determining if the system has been
12460                  * idle long enough to make it idle to the PM framework.
12461                  * This is for lowering the overhead, and therefore improving
12462                  * performance per I/O operation.
12463                  */
12464                 un->un_pm_idle_time = ddi_get_time();
12465 
12466                 un->un_ncmds_in_driver--;
12467                 ASSERT(un->un_ncmds_in_driver >= 0);
12468                 SD_INFO(SD_LOG_IO, un,
12469                     "sd_buf_iodone: un_ncmds_in_driver = %ld\n",
12470                     un->un_ncmds_in_driver);
12471 
12472                 mutex_exit(SD_MUTEX(un));
12473         }
12474 
12475         biodone(bp);                            /* bp is gone after this */
12476 
12477         SD_TRACE(SD_LOG_IO_CORE, un, "sd_buf_iodone: exit.\n");
12478 }
12479 
12480 
12481 /*
12482  *    Function: sd_uscsi_iodone
12483  *
12484  * Description: Frees the sd_xbuf & returns the buf to its originator.


12494         ASSERT(un != NULL);
12495         ASSERT(bp != NULL);
12496 
12497         xp = SD_GET_XBUF(bp);
12498         ASSERT(xp != NULL);
12499         ASSERT(!mutex_owned(SD_MUTEX(un)));
12500 
12501         SD_INFO(SD_LOG_IO, un, "sd_uscsi_iodone: entry.\n");
12502 
12503         bp->b_private = xp->xb_private;
12504 
12505         mutex_enter(SD_MUTEX(un));
12506 
12507         /*
12508          * Grab time when the cmd completed.
12509          * This is used for determining if the system has been
12510          * idle long enough to make it idle to the PM framework.
12511          * This is for lowering the overhead, and therefore improving
12512          * performance per I/O operation.
12513          */
12514         un->un_pm_idle_time = ddi_get_time();
12515 
12516         un->un_ncmds_in_driver--;
12517         ASSERT(un->un_ncmds_in_driver >= 0);
12518         SD_INFO(SD_LOG_IO, un, "sd_uscsi_iodone: un_ncmds_in_driver = %ld\n",
12519             un->un_ncmds_in_driver);
12520 
12521         mutex_exit(SD_MUTEX(un));
12522 
12523         if (((struct uscsi_cmd *)(xp->xb_pktinfo))->uscsi_rqlen >
12524             SENSE_LENGTH) {
12525                 kmem_free(xp, sizeof (struct sd_xbuf) - SENSE_LENGTH +
12526                     MAX_SENSE_LENGTH);
12527         } else {
12528                 kmem_free(xp, sizeof (struct sd_xbuf));
12529         }
12530 
12531         biodone(bp);
12532 
12533         SD_INFO(SD_LOG_IO, un, "sd_uscsi_iodone: exit.\n");
12534 }




   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 /*
  26  * Copyright (c) 2011 Bayard G. Bell.  All rights reserved.
  27  * Copyright (c) 2012 by Delphix. All rights reserved.
  28  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  29  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
  30  */
  31 /*
  32  * Copyright 2011 cyril.galibern@opensvc.com
  33  */
  34 
  35 /*
  36  * SCSI disk target driver.
  37  */
  38 #include <sys/scsi/scsi.h>
  39 #include <sys/dkbad.h>
  40 #include <sys/dklabel.h>
  41 #include <sys/dkio.h>
  42 #include <sys/fdio.h>
  43 #include <sys/cdio.h>
  44 #include <sys/mhd.h>
  45 #include <sys/vtoc.h>
  46 #include <sys/dktp/fdisk.h>
  47 #include <sys/kstat.h>
  48 #include <sys/vtrace.h>


6524  *    Function: sd_pm_idletimeout_handler
6525  *
6526  * Description: A timer routine that's active only while a device is busy.
6527  *              The purpose is to extend slightly the pm framework's busy
6528  *              view of the device to prevent busy/idle thrashing for
6529  *              back-to-back commands. Do this by comparing the current time
6530  *              to the time at which the last command completed and when the
6531  *              difference is greater than sd_pm_idletime, call
6532  *              pm_idle_component. In addition to indicating idle to the pm
6533  *              framework, update the chain type to again use the internal pm
6534  *              layers of the driver.
6535  *
6536  *   Arguments: arg - driver soft state (unit) structure
6537  *
6538  *     Context: Executes in a timeout(9F) thread context
6539  */
6540 
6541 static void
6542 sd_pm_idletimeout_handler(void *arg)
6543 {
6544         const hrtime_t idletime = sd_pm_idletime * NANOSEC;
6545         struct sd_lun *un = arg;
6546 


6547         mutex_enter(&sd_detach_mutex);
6548         if (un->un_detach_count != 0) {
6549                 /* Abort if the instance is detaching */
6550                 mutex_exit(&sd_detach_mutex);
6551                 return;
6552         }
6553         mutex_exit(&sd_detach_mutex);
6554 

6555         /*
6556          * Grab both mutexes, in the proper order, since we're accessing
6557          * both PM and softstate variables.
6558          */
6559         mutex_enter(SD_MUTEX(un));
6560         mutex_enter(&un->un_pm_mutex);
6561         if (((gethrtime() - un->un_pm_idle_time) > idletime) &&
6562             (un->un_ncmds_in_driver == 0) && (un->un_pm_count == 0)) {
6563                 /*
6564                  * Update the chain types.
6565                  * This takes affect on the next new command received.
6566                  */
6567                 if (un->un_f_non_devbsize_supported) {
6568                         un->un_buf_chain_type = SD_CHAIN_INFO_RMMEDIA;
6569                 } else {
6570                         un->un_buf_chain_type = SD_CHAIN_INFO_DISK;
6571                 }
6572                 un->un_uscsi_chain_type = SD_CHAIN_INFO_USCSI_CMD;
6573 
6574                 SD_TRACE(SD_LOG_IO_PM, un,
6575                     "sd_pm_idletimeout_handler: idling device\n");
6576                 (void) pm_idle_component(SD_DEVINFO(un), 0);
6577                 un->un_pm_idle_timeid = NULL;
6578         } else {
6579                 un->un_pm_idle_timeid =
6580                     timeout(sd_pm_idletimeout_handler, un,
6581                     (drv_usectohz((clock_t)300000))); /* 300 ms. */


12442         ASSERT(un != NULL);
12443         ASSERT(bp != NULL);
12444         ASSERT(!mutex_owned(SD_MUTEX(un)));
12445 
12446         SD_TRACE(SD_LOG_IO_CORE, un, "sd_buf_iodone: entry.\n");
12447 
12448         xp = SD_GET_XBUF(bp);
12449         ASSERT(xp != NULL);
12450 
12451         /* xbuf is gone after this */
12452         if (ddi_xbuf_done(bp, un->un_xbuf_attr)) {
12453                 mutex_enter(SD_MUTEX(un));
12454 
12455                 /*
12456                  * Grab time when the cmd completed.
12457                  * This is used for determining if the system has been
12458                  * idle long enough to make it idle to the PM framework.
12459                  * This is for lowering the overhead, and therefore improving
12460                  * performance per I/O operation.
12461                  */
12462                 un->un_pm_idle_time = gethrtime();
12463 
12464                 un->un_ncmds_in_driver--;
12465                 ASSERT(un->un_ncmds_in_driver >= 0);
12466                 SD_INFO(SD_LOG_IO, un,
12467                     "sd_buf_iodone: un_ncmds_in_driver = %ld\n",
12468                     un->un_ncmds_in_driver);
12469 
12470                 mutex_exit(SD_MUTEX(un));
12471         }
12472 
12473         biodone(bp);                            /* bp is gone after this */
12474 
12475         SD_TRACE(SD_LOG_IO_CORE, un, "sd_buf_iodone: exit.\n");
12476 }
12477 
12478 
12479 /*
12480  *    Function: sd_uscsi_iodone
12481  *
12482  * Description: Frees the sd_xbuf & returns the buf to its originator.


12492         ASSERT(un != NULL);
12493         ASSERT(bp != NULL);
12494 
12495         xp = SD_GET_XBUF(bp);
12496         ASSERT(xp != NULL);
12497         ASSERT(!mutex_owned(SD_MUTEX(un)));
12498 
12499         SD_INFO(SD_LOG_IO, un, "sd_uscsi_iodone: entry.\n");
12500 
12501         bp->b_private = xp->xb_private;
12502 
12503         mutex_enter(SD_MUTEX(un));
12504 
12505         /*
12506          * Grab time when the cmd completed.
12507          * This is used for determining if the system has been
12508          * idle long enough to make it idle to the PM framework.
12509          * This is for lowering the overhead, and therefore improving
12510          * performance per I/O operation.
12511          */
12512         un->un_pm_idle_time = gethrtime();
12513 
12514         un->un_ncmds_in_driver--;
12515         ASSERT(un->un_ncmds_in_driver >= 0);
12516         SD_INFO(SD_LOG_IO, un, "sd_uscsi_iodone: un_ncmds_in_driver = %ld\n",
12517             un->un_ncmds_in_driver);
12518 
12519         mutex_exit(SD_MUTEX(un));
12520 
12521         if (((struct uscsi_cmd *)(xp->xb_pktinfo))->uscsi_rqlen >
12522             SENSE_LENGTH) {
12523                 kmem_free(xp, sizeof (struct sd_xbuf) - SENSE_LENGTH +
12524                     MAX_SENSE_LENGTH);
12525         } else {
12526                 kmem_free(xp, sizeof (struct sd_xbuf));
12527         }
12528 
12529         biodone(bp);
12530 
12531         SD_INFO(SD_LOG_IO, un, "sd_uscsi_iodone: exit.\n");
12532 }