static int vdev_disk_off_notify(ldi_handle_t lh, ldi_ev_cookie_t ecookie, void *arg, void *ev_data) { vdev_t *vd = (vdev_t *)arg; vdev_disk_t *dvd = vd->vdev_tsd; /* * Ignore events other than offline. */ if (strcmp(ldi_ev_get_type(ecookie), LDI_EV_OFFLINE) != 0) return (LDI_EV_SUCCESS); /* * All LDI handles must be closed for the state change to succeed, so * call on vdev_disk_close() to do this. * * We inform vdev_disk_close that it is being called from offline * notify context so it will defer cleanup of LDI event callbacks and * freeing of vd->vdev_tsd to the offline finalize or a reopen. */ dvd->vd_ldi_offline = B_TRUE; vdev_disk_close(vd); /* * Now that the device is closed, request that the spa_async_thread * mark the device as REMOVED and notify FMA of the removal. */ zfs_post_remove(vd->vdev_spa, vd); vd->vdev_remove_wanted = B_TRUE; spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE); return (LDI_EV_SUCCESS); }
/* * Unfortunately the notify thread that posts the termination event to us * is inside IOkit locked loop, so we have to issue the vnode_close() * async, or vn_close()/dkclose() will wait on notify to release the lock */ static void vdev_close_thread(void *arg) { vdev_t *vd = (vdev_t *)arg; vdev_disk_t *dvd = (vdev_disk_t *)vd->vdev_tsd; if (dvd) dvd->vd_offline = B_TRUE; vdev_disk_close(vd); thread_exit(); }