Skip to content

pool is imported on host '<unknown>' (hostid=0). #18823

Closed

Description

@pzwahlen

System information

Type Version/Name
Distribution Name Rocky Linux
Distribution Version 9.8
Kernel Version 5.14.0-687.26.1.el9_8
Architecture x86_64
OpenZFS Version 2.4.3

Describe the problem you're observing

We are running a shared jbob zfs cluster. Our dev/test environement is running under VMware using shared disks (thick provisioning, independant, multi-writer). This has been working fine in the past and today we use it to validate an upgrade from 2.3.4 to 2.4.3. 'multihost' is enabled and we have unique /etc/hostid.

Under 2.4.3 the pool cannot be moved from one node to the other anymore (note: pacemaker/corosync have been disabled and we are testing everything manually). Pool is properly exported on one node and we get the following error while importing on the other node:

cannot import 'p02': pool is imported on host '<unknown>' (hostid=0).
Export the pool on the other system, then run 'zpool import'.

Disabling multihost/mmp makes it possible to move the pool from one node to the other. Re-enabling multihost brings the issue back when trying to move the pool to another node.

Also, import systematically triggers an activity check, which ends with (note: the pool 'p02' was properly exported before this):

NOTICE: pool 'p02' activity check required, 34 seconds remaining
WARNING: pool 'p02' activity detected, aborted import during claim

This pool is made of a pair of mirrors (2x2 disks) and contains a 'hole' vdev due to a previous mirror removal test. Could this be part of the issue ?

Activity

  1. pzwahlen commented on Jul 19, 2026

    @pzwahlen
    Author

    I am able to replicate this issue:

    • Create a pool with 2 mirrors of 2 disks each
    • Test export on node 1 and import on node 2 -> OK
    • Add a mirrored log
    • Test export on node 2 and import on node 1 -> OK
    • Remove log mirror (leaves 'hole')
    • Test export on node 1 and import on node 2 -> FAIL (activity detected)
  2. mkhllr commented on Jul 20, 2026

    @mkhllr
    Contributor

    I was able to reproduce this and bisect it. @pzwahlen's narrowing to the log
    removal is exactly right: the trigger is the hole that zpool remove leaves
    in the vdev config.

    Reproduction

    This is on a plain QEMU VM with file vdevs and a single node, simulating the
    second host by changing the hostid between export and import, so none of your
    VMware or shared-disk setup is needed to hit it.

    zpool create -f p mirror d1 d2 mirror d3 d4
    zpool set multihost=on p
    zpool add p log mirror d5 d6
    zpool remove p mirror-2          # leaves type: 'hole' in the config
    zpool export p
    zgenhostid -f feedface           # pretend we are the other node
    zpool import -d . p
      cannot import 'p': pool is imported on host '<unknown>' (hostid=0).
    

    A control run that never adds or removes a log imports cleanly through the same
    export/hostid-change/import sequence, which is what points at the hole rather
    than at multihost itself.

    Bisect

    Each step below was built with --enable-debug and I checked that the loaded
    module's srcversion matched the freshly built one, so none of these are stale
    module results.

    zfs-2.3.4   GOOD
    zfs-2.4.0   GOOD
    zfs-2.4.1   BAD
    zfs-2.4.2   BAD
    master      BAD
    

    git bisect run over the 85 commits in zfs-2.4.0..zfs-2.4.1 lands on

    c710f879236a94bb10a051b1e88648ad0475b76e  mmp: claim sequence id before final import
    

    and I re-tested its parent 96ffe5100 explicitly to confirm it is GOOD.

    Worth noting for anyone else hitting this: 2.4.0 is unaffected, so the exposure
    starts at 2.4.1.

    Mechanism

    In mmp_claim_uberblock_sync() the new activity check walks the vdev tree
    accumulating req_writes, then requires that many good writes:

    if (cvd->vdev_islog || cvd->vdev_isspare || cvd->vdev_isl2cache)
            continue;
    
    if (cvd->vdev_top == cvd) {
            ...
            *req_writes += MIN(MAX(cvd->vdev_children, 1), 2);
    }

    A hole is a top-level vdev and is none of log/spare/l2cache, so it survives that
    filter and adds 1 to req_writes. It is not writeable, so the function returns
    at the vdev_writeable() check before issuing any write and good_writes never
    accounts for it. good_writes can then never reach req_writes, the check
    concludes the pool is active elsewhere, and the import fails with hostid 0
    because the hole has no label to read a hostid from.

    That also explains why it only shows up after a log device is removed, and why a
    pool that never had one is fine.

    Candidate fix

    Skipping holes alongside the other vdev types resolves it here. vdev_label.c
    already guards vdev_ishole in the equivalent places (lines 769 and 820), so
    this matches existing practice:

    if (cvd->vdev_islog || cvd->vdev_isspare ||
        cvd->vdev_isl2cache || cvd->vdev_ishole)
            continue;

    With that applied to master the same reproduction imports cleanly, with the hole
    still present in the config.

    The mmp test group still passes with it applied, 17/17 on Ubuntu 24.04 /
    kernel 6.8, including mmp_active_import, mmp_concurrent_import and
    mmp_exported_import, so the activity check itself still behaves for the cases
    it is meant to catch.

    I have not tried to judge whether skipping holes is the right shape of fix
    compared with, say, deriving req_writes from writeable leaves. Happy to open a
    PR if that is useful, or leave it with you.

  3. added a commit that references this issue on Jul 21, 2026
    ef1715b
  4. added a commit that references this issue on Jul 22, 2026
    1ac3f27
  5. added 5 commits that reference this issue on Aug 12, 2026
    7ef6ff9
    9623afd
    bbf0b24
    3faeb65
    9c1b3a4
  6. added a commit that references this issue on Aug 26, 2026
    af3cb94
  7. added a commit that references this issue on Sep 26, 2026
    9e39617
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: DefectIncorrect behavior (e.g. crash, hang)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions