ibdm shouldn't abuse ddi_get_time(9f)
ddi_get_time() returns a Unix timestamp based on the current TOD. If the TOD setting changes for whatever reason (daylight saving time adjustments, NTP), the value returned by ddi_get_time() may change non-monotonically. This makes it unsuitable for calculating timeouts and wait times.
We ran into this issue at Nexenta. The installer first asks for timezone information, and then proceeds to run 'devfsadm -c disk'. devfsadm gets blocked for a long time (hours).
What happens is: the ibdm kmod stashes a ddi_get_time() timestamp of when the HCA attached. Then, devfsadm blocks on a mt_config_thread trying to configure the IB nexus:
swtch+0x141 cv_timedwait_hires+0xec cv_reltimedwait+0x51 ibdm`ibdm_ibnex_port_settle_wait+0x5f ib`ibnex_bus_config+0x1e8 devi_config_common+0xa5 mt_config_thread+0x58 thread_start+8
The function of interest here is ibdm_ibnex_port_settle(). It calls ibdm_get_waittime() to get a delay to feed to cv_reltimedwait(). The delay is (more or less) calculated as: ddi_get_time() - hca_attach_time. This works fine as long as ddi_get_time() continues incrementing at a constant rate (1 sec/sec).
In our case, we end up with the driver attaching, then we change the timezone setting via rtc(1m), and then ibdm_get_waittime() tries to calculate a delay that ends up hours long because ddi_get_time() went back.
Switching to gethrtime(9f) or ddi_get_lbolt(9f) solves this.
Updated by Electric Monk almost 5 years ago
- % Done changed from 80 to 100
- Status changed from New to Closed
commit e1d3217b9afde782c4d3e946fda0e6ef36a61306 Author: Josef 'Jeff' Sipek <firstname.lastname@example.org> Date: 2014-05-14T23:36:50.000Z 4777 ibdm shouldn't abuse ddi_get_time(9f) Reviewed by: Rob Gittins <email@example.com> Reviewed by: Albert Lee <firstname.lastname@example.org> Reviewed by: Robert Mustacchi <email@example.com> Reviewed by: Hans Rosenfeld <firstname.lastname@example.org> Approved by: Richard Lowe <email@example.com>