* Set a vdev's state. If this is during an open, we don't update the parent * state, because we're in the process of opening children depth-first. * Otherwise, we propagate the change to the parent. * * If this routine places a device in a faulted state, an appropriate ereport is * generated. */
| 4763 | * generated. |
| 4764 | */ |
| 4765 | void |
| 4766 | vdev_set_state(vdev_t *vd, boolean_t isopen, vdev_state_t state, vdev_aux_t aux) |
| 4767 | { |
| 4768 | uint64_t save_state; |
| 4769 | spa_t *spa = vd->vdev_spa; |
| 4770 | |
| 4771 | if (state == vd->vdev_state) { |
| 4772 | /* |
| 4773 | * Since vdev_offline() code path is already in an offline |
| 4774 | * state we can miss a statechange event to OFFLINE. Check |
| 4775 | * the previous state to catch this condition. |
| 4776 | */ |
| 4777 | if (vd->vdev_ops->vdev_op_leaf && |
| 4778 | (state == VDEV_STATE_OFFLINE) && |
| 4779 | (vd->vdev_prevstate >= VDEV_STATE_FAULTED)) { |
| 4780 | /* post an offline state change */ |
| 4781 | zfs_post_state_change(spa, vd, vd->vdev_prevstate); |
| 4782 | } |
| 4783 | vd->vdev_stat.vs_aux = aux; |
| 4784 | return; |
| 4785 | } |
| 4786 | |
| 4787 | save_state = vd->vdev_state; |
| 4788 | |
| 4789 | vd->vdev_state = state; |
| 4790 | vd->vdev_stat.vs_aux = aux; |
| 4791 | |
| 4792 | /* |
| 4793 | * If we are setting the vdev state to anything but an open state, then |
| 4794 | * always close the underlying device unless the device has requested |
| 4795 | * a delayed close (i.e. we're about to remove or fault the device). |
| 4796 | * Otherwise, we keep accessible but invalid devices open forever. |
| 4797 | * We don't call vdev_close() itself, because that implies some extra |
| 4798 | * checks (offline, etc) that we don't want here. This is limited to |
| 4799 | * leaf devices, because otherwise closing the device will affect other |
| 4800 | * children. |
| 4801 | */ |
| 4802 | if (!vd->vdev_delayed_close && vdev_is_dead(vd) && |
| 4803 | vd->vdev_ops->vdev_op_leaf) |
| 4804 | vd->vdev_ops->vdev_op_close(vd); |
| 4805 | |
| 4806 | if (vd->vdev_removed && |
| 4807 | state == VDEV_STATE_CANT_OPEN && |
| 4808 | (aux == VDEV_AUX_OPEN_FAILED || vd->vdev_checkremove)) { |
| 4809 | /* |
| 4810 | * If the previous state is set to VDEV_STATE_REMOVED, then this |
| 4811 | * device was previously marked removed and someone attempted to |
| 4812 | * reopen it. If this failed due to a nonexistent device, then |
| 4813 | * keep the device in the REMOVED state. We also let this be if |
| 4814 | * it is one of our special test online cases, which is only |
| 4815 | * attempting to online the device and shouldn't generate an FMA |
| 4816 | * fault. |
| 4817 | */ |
| 4818 | vd->vdev_state = VDEV_STATE_REMOVED; |
| 4819 | vd->vdev_stat.vs_aux = VDEV_AUX_NONE; |
| 4820 | } else if (state == VDEV_STATE_REMOVED) { |
| 4821 | vd->vdev_removed = B_TRUE; |
| 4822 | } else if (state == VDEV_STATE_CANT_OPEN) { |
no test coverage detected