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 }
|