summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-03-05 20:14:42 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2013-03-05 22:21:27 +0000
commit97231876f92481697532dc999577f997624cfecd (patch)
treee964e79a071c0cec843dd70a57bdda30268679bf /usr/src/uts
parentdf8e9ae2b126b7dc626ed694e6b79e0e941149e4 (diff)
parent41610d101ac089e52e33b0a671581e0c80d256c0 (diff)
downloadillumos-joyent-97231876f92481697532dc999577f997624cfecd.tar.gz
Merge /root/git/illumos-gate
* /root/git/illumos-gate: commit 41610d101ac089e52e33b0a671581e0c80d256c0 3530 ::smbsess prints wrong IP addresses in verbose mode, has no idea about IPv6 commit d04756377ddd1cf28ebcf652541094e17b03c889 3603 panic from bpobj_enqueue_subobj() 3604 zdb should print bpobjs more verbosely commit df49e4e49391204d49b62e99bfae86101a20c690 3551 hvm_sd module missing dependencies on scsi and cmlb commit 0689f76c08c5e553ff25ac43a852b56c430bb61e 3582 zfs_delay() should support a variable resolution 3584 DTrace sdt probes for ZFS txg states Conflicts: usr/src/uts/common/fs/zfs/dsl_dir.c usr/src/uts/common/fs/zfs/dsl_pool.c
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/common/conf/param.c8
-rw-r--r--usr/src/uts/common/fs/zfs/bpobj.c8
-rw-r--r--usr/src/uts/common/fs/zfs/dmu.c2
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dir.c2
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_pool.c17
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_scan.c8
-rw-r--r--usr/src/uts/common/fs/zfs/spa_misc.c6
-rw-r--r--usr/src/uts/common/fs/zfs/sys/txg.h9
-rw-r--r--usr/src/uts/common/fs/zfs/sys/txg_impl.h12
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_zone.h2
-rw-r--r--usr/src/uts/common/fs/zfs/txg.c27
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_zone.c16
-rw-r--r--usr/src/uts/common/os/condvar.c2
-rw-r--r--usr/src/uts/common/sys/condvar.h2
-rw-r--r--usr/src/uts/common/sys/time.h3
-rw-r--r--usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile7
16 files changed, 78 insertions, 53 deletions
diff --git a/usr/src/uts/common/conf/param.c b/usr/src/uts/common/conf/param.c
index 06e7810f07..34e2d3324d 100644
--- a/usr/src/uts/common/conf/param.c
+++ b/usr/src/uts/common/conf/param.c
@@ -697,10 +697,10 @@ param_init(void)
* should re-evaluate their usage and specify the appropriate
* resolution.
*/
- time_res[TR_NANOSEC] = SEC;
- time_res[TR_MICROSEC] = MILLISEC;
- time_res[TR_MILLISEC] = MICROSEC;
- time_res[TR_SEC] = NANOSEC;
+ time_res[TR_NANOSEC] = NANOSEC / NANOSEC;
+ time_res[TR_MICROSEC] = NANOSEC / MICROSEC;
+ time_res[TR_MILLISEC] = NANOSEC / MILLISEC;
+ time_res[TR_SEC] = NANOSEC / SEC;
time_res[TR_CLOCK_TICK] = nsec_per_tick;
}
diff --git a/usr/src/uts/common/fs/zfs/bpobj.c b/usr/src/uts/common/fs/zfs/bpobj.c
index bcb5f331f0..1b9baa779d 100644
--- a/usr/src/uts/common/fs/zfs/bpobj.c
+++ b/usr/src/uts/common/fs/zfs/bpobj.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/bpobj.h>
@@ -418,6 +418,12 @@ bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx)
VERIFY3U(0, ==, dmu_buf_hold(bpo->bpo_os, subsubobjs,
0, FTAG, &subdb, 0));
+ /*
+ * Make sure that we are not asking dmu_write()
+ * to write more data than we have in our buffer.
+ */
+ VERIFY3U(subdb->db_size, >=,
+ numsubsub * sizeof (subobj));
dmu_write(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs,
bpo->bpo_phys->bpo_num_subobjs * sizeof (subobj),
numsubsub * sizeof (subobj), subdb->db_data, tx);
diff --git a/usr/src/uts/common/fs/zfs/dmu.c b/usr/src/uts/common/fs/zfs/dmu.c
index 8567ca0e4e..3a1ea02726 100644
--- a/usr/src/uts/common/fs/zfs/dmu.c
+++ b/usr/src/uts/common/fs/zfs/dmu.c
@@ -1699,7 +1699,7 @@ dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi)
doi->doi_checksum = dn->dn_checksum;
doi->doi_compress = dn->dn_compress;
doi->doi_physical_blocks_512 = (DN_USED_BYTES(dnp) + 256) >> 9;
- doi->doi_max_offset = (dnp->dn_maxblkid + 1) * dn->dn_datablksz;
+ doi->doi_max_offset = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
doi->doi_fill_count = 0;
for (int i = 0; i < dnp->dn_nblkptr; i++)
doi->doi_fill_count += dnp->dn_blkptr[i].blk_fill;
diff --git a/usr/src/uts/common/fs/zfs/dsl_dir.c b/usr/src/uts/common/fs/zfs/dsl_dir.c
index cfb20b4ff5..d43f386d2e 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dir.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dir.c
@@ -740,7 +740,7 @@ dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t lsize, uint64_t asize,
} else {
if (err == EAGAIN) {
txg_delay(dd->dd_pool, tx->tx_txg,
- zfs_zone_txg_delay());
+ zfs_zone_txg_delay(), MSEC2NSEC(10));
err = ERESTART;
}
dsl_pool_memory_pressure(dd->dd_pool);
diff --git a/usr/src/uts/common/fs/zfs/dsl_pool.c b/usr/src/uts/common/fs/zfs/dsl_pool.c
index f341b38957..b498902967 100644
--- a/usr/src/uts/common/fs/zfs/dsl_pool.c
+++ b/usr/src/uts/common/fs/zfs/dsl_pool.c
@@ -59,6 +59,8 @@ kmutex_t zfs_write_limit_lock;
static pgcnt_t old_physmem = 0;
+hrtime_t zfs_throttle_resolution = MSEC2NSEC(10);
+
int
dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **ddp)
{
@@ -512,12 +514,13 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
* Weight the throughput calculation towards the current value:
* thru = 3/4 old_thru + 1/4 new_thru
*
- * Note: write_time is in nanosecs, so write_time/MICROSEC
- * yields millisecs
+ * Note: write_time is in nanosecs while dp_throughput is expressed in
+ * bytes per millisecond.
*/
ASSERT(zfs_write_limit_min > 0);
- if (data_written > zfs_write_limit_min / 8 && write_time > MICROSEC) {
- uint64_t throughput = data_written / (write_time / MICROSEC);
+ if (data_written > zfs_write_limit_min / 8 &&
+ write_time > MSEC2NSEC(1)) {
+ uint64_t throughput = data_written / NSEC2MSEC(write_time);
if (dp->dp_throughput)
dp->dp_throughput = throughput / 4 +
@@ -615,8 +618,10 @@ dsl_pool_tempreserve_space(dsl_pool_t *dp, uint64_t space, dmu_tx_t *tx)
* the caller some number of clock ticks. This will slow down the
* "fill" rate until the sync process can catch up with us.
*/
- if (reserved && reserved > (write_limit - (write_limit >> 3)))
- txg_delay(dp, tx->tx_txg, zfs_zone_txg_delay());
+ if (reserved && reserved > (write_limit - (write_limit >> 3))) {
+ txg_delay(dp, tx->tx_txg, zfs_zone_txg_delay(),
+ zfs_throttle_resolution);
+ }
return (0);
}
diff --git a/usr/src/uts/common/fs/zfs/dsl_scan.c b/usr/src/uts/common/fs/zfs/dsl_scan.c
index 3de3c6e4d7..167f3825e5 100644
--- a/usr/src/uts/common/fs/zfs/dsl_scan.c
+++ b/usr/src/uts/common/fs/zfs/dsl_scan.c
@@ -403,7 +403,7 @@ dsl_scan_check_pause(dsl_scan_t *scn, const zbookmark_t *zb)
zfs_resilver_min_time_ms : zfs_scan_min_time_ms;
elapsed_nanosecs = gethrtime() - scn->scn_sync_start_time;
if (elapsed_nanosecs / NANOSEC > zfs_txg_timeout ||
- (elapsed_nanosecs / MICROSEC > mintime &&
+ (NSEC2MSEC(elapsed_nanosecs) > mintime &&
txg_sync_waiting(scn->scn_dp)) ||
spa_shutting_down(scn->scn_dp->dp_spa)) {
if (zb) {
@@ -1308,7 +1308,7 @@ dsl_scan_free_should_pause(dsl_scan_t *scn)
elapsed_nanosecs = gethrtime() - scn->scn_sync_start_time;
return (elapsed_nanosecs / NANOSEC > zfs_txg_timeout ||
- (elapsed_nanosecs / MICROSEC > zfs_free_min_time_ms &&
+ (NSEC2MSEC(elapsed_nanosecs) > zfs_free_min_time_ms &&
txg_sync_waiting(scn->scn_dp)) ||
spa_shutting_down(scn->scn_dp->dp_spa));
}
@@ -1433,7 +1433,7 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
"free_bpobj/bptree txg %llu",
(longlong_t)scn->scn_visited_this_txg,
(longlong_t)
- (gethrtime() - scn->scn_sync_start_time) / MICROSEC,
+ NSEC2MSEC(gethrtime() - scn->scn_sync_start_time),
(longlong_t)tx->tx_txg);
scn->scn_visited_this_txg = 0;
/*
@@ -1481,7 +1481,7 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
zfs_dbgmsg("visited %llu blocks in %llums",
(longlong_t)scn->scn_visited_this_txg,
- (longlong_t)(gethrtime() - scn->scn_sync_start_time) / MICROSEC);
+ (longlong_t)NSEC2MSEC(gethrtime() - scn->scn_sync_start_time));
if (!scn->scn_pausing) {
/* finished with scan. */
diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c
index 733d2609e5..1663abbb5e 100644
--- a/usr/src/uts/common/fs/zfs/spa_misc.c
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c
@@ -499,8 +499,8 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
hdlr.cyh_arg = spa;
hdlr.cyh_level = CY_LOW_LEVEL;
- spa->spa_deadman_synctime = zfs_deadman_synctime *
- zfs_txg_synctime_ms * MICROSEC;
+ spa->spa_deadman_synctime = MSEC2NSEC(zfs_deadman_synctime *
+ zfs_txg_synctime_ms);
/*
* This determines how often we need to check for hung I/Os after
@@ -508,7 +508,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
* an expensive operation we don't want to check too frequently.
* Instead wait for 5 synctimes before checking again.
*/
- when.cyt_interval = 5ULL * zfs_txg_synctime_ms * MICROSEC;
+ when.cyt_interval = MSEC2NSEC(5 * zfs_txg_synctime_ms);
when.cyt_when = CY_INFINITY;
mutex_enter(&cpu_lock);
spa->spa_deadman_cycid = cyclic_add(&hdlr, &when);
diff --git a/usr/src/uts/common/fs/zfs/sys/txg.h b/usr/src/uts/common/fs/zfs/sys/txg.h
index 2df33f0fb0..1529e5ac6d 100644
--- a/usr/src/uts/common/fs/zfs/sys/txg.h
+++ b/usr/src/uts/common/fs/zfs/sys/txg.h
@@ -74,13 +74,8 @@ extern void txg_rele_to_quiesce(txg_handle_t *txghp);
extern void txg_rele_to_sync(txg_handle_t *txghp);
extern void txg_register_callbacks(txg_handle_t *txghp, list_t *tx_callbacks);
-/*
- * Delay the caller by the specified number of ticks or until
- * the txg closes (whichever comes first). This is intended
- * to be used to throttle writers when the system nears its
- * capacity.
- */
-extern void txg_delay(struct dsl_pool *dp, uint64_t txg, int ticks);
+extern void txg_delay(struct dsl_pool *dp, uint64_t txg, hrtime_t delta,
+ hrtime_t resolution);
/*
* Wait until the given transaction group has finished syncing.
diff --git a/usr/src/uts/common/fs/zfs/sys/txg_impl.h b/usr/src/uts/common/fs/zfs/sys/txg_impl.h
index 7b356eac12..8f1b21b3d4 100644
--- a/usr/src/uts/common/fs/zfs/sys/txg_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/txg_impl.h
@@ -23,6 +23,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#ifndef _SYS_TXG_IMPL_H
#define _SYS_TXG_IMPL_H
@@ -36,14 +40,14 @@ extern "C" {
struct tx_cpu {
kmutex_t tc_lock;
kcondvar_t tc_cv[TXG_SIZE];
- uint64_t tc_count[TXG_SIZE];
+ uint64_t tc_count[TXG_SIZE]; /* tx hold count on each txg */
list_t tc_callbacks[TXG_SIZE]; /* commit cb list */
- char tc_pad[16];
+ char tc_pad[16]; /* pad to fill 3 cache lines */
};
typedef struct tx_state {
- tx_cpu_t *tx_cpu; /* protects right to enter txg */
- kmutex_t tx_sync_lock; /* protects tx_state_t */
+ tx_cpu_t *tx_cpu; /* protects access to tx_open_txg */
+ kmutex_t tx_sync_lock; /* protects the rest of this struct */
uint64_t tx_open_txg; /* currently open txg id */
uint64_t tx_quiesced_txg; /* quiesced txg waiting for sync */
uint64_t tx_syncing_txg; /* currently syncing txg id */
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_zone.h b/usr/src/uts/common/fs/zfs/sys/zfs_zone.h
index 069ec004f3..b3e90c187e 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_zone.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_zone.h
@@ -50,7 +50,7 @@ extern void zfs_zone_zio_done(zio_t *);
extern void zfs_zone_zio_dequeue(zio_t *);
extern void zfs_zone_zio_enqueue(zio_t *);
extern void zfs_zone_report_txg_sync(void *);
-extern int zfs_zone_txg_delay();
+extern hrtime_t zfs_zone_txg_delay();
#ifdef _KERNEL
extern zio_t *zfs_zone_schedule(vdev_queue_t *);
#endif
diff --git a/usr/src/uts/common/fs/zfs/txg.c b/usr/src/uts/common/fs/zfs/txg.c
index 51fdd48ac8..471e365eb5 100644
--- a/usr/src/uts/common/fs/zfs/txg.c
+++ b/usr/src/uts/common/fs/zfs/txg.c
@@ -233,7 +233,7 @@ txg_thread_exit(tx_state_t *tx, callb_cpr_t *cpr, kthread_t **tpp)
}
static void
-txg_thread_wait(tx_state_t *tx, callb_cpr_t *cpr, kcondvar_t *cv, uint64_t time)
+txg_thread_wait(tx_state_t *tx, callb_cpr_t *cpr, kcondvar_t *cv, clock_t time)
{
CALLB_CPR_SAFE_BEGIN(cpr);
@@ -354,6 +354,9 @@ txg_quiesce(dsl_pool_t *dp, uint64_t txg)
ASSERT(txg == tx->tx_open_txg);
tx->tx_open_txg++;
+ DTRACE_PROBE2(txg__quiescing, dsl_pool_t *, dp, uint64_t, txg);
+ DTRACE_PROBE2(txg__opened, dsl_pool_t *, dp, uint64_t, tx->tx_open_txg);
+
/*
* Now that we've incremented tx_open_txg, we can let threads
* enter the next transaction group.
@@ -476,6 +479,7 @@ txg_sync_thread(dsl_pool_t *dp)
txg = tx->tx_quiesced_txg;
tx->tx_quiesced_txg = 0;
tx->tx_syncing_txg = txg;
+ DTRACE_PROBE2(txg__syncing, dsl_pool_t *, dp, uint64_t, txg);
cv_broadcast(&tx->tx_quiesce_more_cv);
dprintf("txg=%llu quiesce_txg=%llu sync_txg=%llu\n",
@@ -491,6 +495,7 @@ txg_sync_thread(dsl_pool_t *dp)
mutex_enter(&tx->tx_sync_lock);
tx->tx_synced_txg = txg;
tx->tx_syncing_txg = 0;
+ DTRACE_PROBE2(txg__synced, dsl_pool_t *, dp, uint64_t, txg);
cv_broadcast(&tx->tx_sync_done_cv);
/*
@@ -539,21 +544,22 @@ txg_quiesce_thread(dsl_pool_t *dp)
*/
dprintf("quiesce done, handing off txg %llu\n", txg);
tx->tx_quiesced_txg = txg;
+ DTRACE_PROBE2(txg__quiesced, dsl_pool_t *, dp, uint64_t, txg);
cv_broadcast(&tx->tx_sync_more_cv);
cv_broadcast(&tx->tx_quiesce_done_cv);
}
}
/*
- * Delay this thread by 'ticks' if we are still in the open transaction
- * group and there is already a waiting txg quiesing or quiesced. Abort
- * the delay if this txg stalls or enters the quiesing state.
+ * Delay this thread by delay nanoseconds if we are still in the open
+ * transaction group and there is already a waiting txg quiesing or quiesced.
+ * Abort the delay if this txg stalls or enters the quiesing state.
*/
void
-txg_delay(dsl_pool_t *dp, uint64_t txg, int ticks)
+txg_delay(dsl_pool_t *dp, uint64_t txg, hrtime_t delay, hrtime_t resolution)
{
tx_state_t *tx = &dp->dp_tx;
- clock_t timeout = ddi_get_lbolt() + ticks;
+ hrtime_t start = gethrtime();
/* don't delay if this txg could transition to quiesing immediately */
if (tx->tx_open_txg > txg ||
@@ -566,10 +572,11 @@ txg_delay(dsl_pool_t *dp, uint64_t txg, int ticks)
return;
}
- while (ddi_get_lbolt() < timeout &&
- tx->tx_syncing_txg < txg-1 && !txg_stalled(dp))
- (void) cv_timedwait(&tx->tx_quiesce_more_cv, &tx->tx_sync_lock,
- timeout);
+ while (gethrtime() - start < delay &&
+ tx->tx_syncing_txg < txg-1 && !txg_stalled(dp)) {
+ (void) cv_timedwait_hires(&tx->tx_quiesce_more_cv,
+ &tx->tx_sync_lock, delay, resolution, 0);
+ }
mutex_exit(&tx->tx_sync_lock);
}
diff --git a/usr/src/uts/common/fs/zfs/zfs_zone.c b/usr/src/uts/common/fs/zfs/zfs_zone.c
index 08f4f38e04..6e0864c799 100644
--- a/usr/src/uts/common/fs/zfs/zfs_zone.c
+++ b/usr/src/uts/common/fs/zfs/zfs_zone.c
@@ -68,10 +68,10 @@ zfs_zone_report_txg_sync(void *dp)
{
}
-int
+hrtime_t
zfs_zone_txg_delay()
{
- return (1);
+ return (MSEC2NSEC(10));
}
#else
@@ -195,7 +195,7 @@ int zfs_zone_schedule_thresh = 5;
* Tunables for delay throttling when TxG flush is occurring.
*/
int zfs_zone_txg_throttle_scale = 2;
-int zfs_zone_txg_delay_ticks = 2;
+hrtime_t zfs_zone_txg_delay_nsec = MSEC2NSEC(20);
typedef struct {
int zq_qdepth;
@@ -970,19 +970,19 @@ zfs_zone_report_txg_sync(void *dp)
}
}
-int
+hrtime_t
zfs_zone_txg_delay()
{
zone_t *zonep = curzone;
- int delay = 1;
+ hrtime_t delay = MSEC2NSEC(10);
if (zonep->zone_io_util_above_avg)
- delay = zfs_zone_txg_delay_ticks;
+ delay = zfs_zone_txg_delay_nsec;
- extern void __dtrace_probe_zfs__zone__txg__delay(uintptr_t, uintptr_t);
+ extern void __dtrace_probe_zfs__zone__txg__delay(uintptr_t, hrtime_t);
__dtrace_probe_zfs__zone__txg__delay((uintptr_t)(zonep->zone_id),
- (uintptr_t)delay);
+ (hrtime_t)delay);
return (delay);
}
diff --git a/usr/src/uts/common/os/condvar.c b/usr/src/uts/common/os/condvar.c
index 60ff344d82..e9c418ffbd 100644
--- a/usr/src/uts/common/os/condvar.c
+++ b/usr/src/uts/common/os/condvar.c
@@ -43,8 +43,6 @@
#include <sys/sdt.h>
#include <sys/callo.h>
-clock_t cv_timedwait_hires(kcondvar_t *, kmutex_t *, hrtime_t, hrtime_t, int);
-
/*
* CV_MAX_WAITERS is the maximum number of waiters we track; once
* the number becomes higher than that, we look at the sleepq to
diff --git a/usr/src/uts/common/sys/condvar.h b/usr/src/uts/common/sys/condvar.h
index 56e660e5e2..ef72c3c567 100644
--- a/usr/src/uts/common/sys/condvar.h
+++ b/usr/src/uts/common/sys/condvar.h
@@ -94,6 +94,8 @@ extern void cv_destroy(kcondvar_t *);
extern void cv_wait(kcondvar_t *, kmutex_t *);
extern void cv_wait_stop(kcondvar_t *, kmutex_t *, int);
extern clock_t cv_timedwait(kcondvar_t *, kmutex_t *, clock_t);
+extern clock_t cv_timedwait_hires(kcondvar_t *, kmutex_t *, hrtime_t, hrtime_t,
+ int);
extern clock_t cv_reltimedwait(kcondvar_t *, kmutex_t *, clock_t, time_res_t);
extern int cv_wait_sig(kcondvar_t *, kmutex_t *);
extern clock_t cv_timedwait_sig(kcondvar_t *, kmutex_t *, clock_t);
diff --git a/usr/src/uts/common/sys/time.h b/usr/src/uts/common/sys/time.h
index fcb9a290fe..9fc4704860 100644
--- a/usr/src/uts/common/sys/time.h
+++ b/usr/src/uts/common/sys/time.h
@@ -236,6 +236,9 @@ struct itimerval32 {
#define MICROSEC 1000000
#define NANOSEC 1000000000
+#define MSEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / MILLISEC))
+#define NSEC2MSEC(n) ((n) / (NANOSEC / MILLISEC))
+
#endif /* !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__) */
#ifndef _ASM
diff --git a/usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile b/usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile
index 681f4849ae..aba7418b0a 100644
--- a/usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile
+++ b/usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile
@@ -38,7 +38,7 @@ UTSBASE = ../../..
# Define the module and object file sets.
#
# Normally when compiling sd there are .conf file definitions and
-# definitions for warlock, but we don't both with those here.
+# definitions for warlock, but we don't bother with those here.
#
MODULE = hvm_sd
OBJECTS = $(HVM_SD_OBJS:%=$(OBJS_DIR)/%)
@@ -78,6 +78,11 @@ CERRWARN += -_gcc=-Wno-uninitialized
CERRWARN += -_gcc=-Wno-unused-value
#
+# Depends on scsi and cmlb
+#
+LDFLAGS += -dy -N misc/scsi -N misc/cmlb
+
+#
# Default build targets.
#
.KEEP_STATE: