Power down the server, swap out the drive, reboot.
# zpool replace tank <failed drive id> <replacement drive id>gave a Device not in pool error.
Googling suggested exporting then reimporting the pool, but all
# zpool export -r tankgot me was "Pool busy", even though there were no processes accessing it according to fuser and lsof, and zpool iostat showed 0 reads or writes.
Eventually I hit upon this issue in the ZFSonlinux bug tracker:https://github.com/zfsonlinux/zfs/issues/976
Finally a solution to my original problem. I needed full paths to the device names.
# zpool replace tank /dev/disk/by-id/<failed drive id> /dev/disk/by-id/<replacement drive id>did the trick:
# zpool status pool: tank state: DEGRADED status: One or more devices is currently being resilvered. The pool will continue to function, possibly in a degraded state. action: Wait for the resilver to complete. scan: resilver in progress since Fri Sep 28 00:02:04 2012 12.3G scanned out of 205G at 24.5M/s, 2h14m to go 3.07G resilvered, 5.98% done config: NAME STATE READ WRITE CKSUM tank DEGRADED 0 0 0 raidz1-0 DEGRADED 0 0 0 ata-VB0250EAVER_Z2ATRS75 ONLINE 0 0 0 ata-WDC_WD2500AAJS-22RYA0_WD-WCAR00411237 ONLINE 0 0 0 ata-WDC_WD2500JS-75NCB3_WD-WCANK8544801 ONLINE 0 0 0 replacing-3 UNAVAIL 0 0 0 ata-WDC_WD2500JS-75NCB3_WD-WCANKC570943 UNAVAIL 0 0 0 ata-SAMSUNG_SP2504C_S09QJ1SP156094 ONLINE 0 0 0 (resilvering) errors: No known data errors
Success! Still don't know what was causing the "pool busy" error when trying to export.
I expect this should work in ZFS on Linux for all zpool operations that refer to individual vdevs or disks, like zpool add, zpool remove, etc.