Hi, I think softraid is leaking vnodes. When taking a device offline with bioctl -O /dev/sd0a sd2, then wiping the disk with dd (including the disklabel), I cannot change sd0's disklabel as it would say "open part- ition would change/shrink". This is because on assembly (and rebuild) the device is VOP_OPEN()d, but never closed.
With this diff, whenever a disk goes offline (I/O error or bioctl -O), we actively close the vnode. One thing I wonder is, this still works when the backing device has already detached (USB drive being pulled). Opinions? Patrick diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index dcc4db16864..e43594e48b6 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -4354,6 +4354,18 @@ die: sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state; sd->sd_set_vol_state(sd); + if (new_state == BIOC_SDOFFLINE) { + sd->sd_vol.sv_chunks[c]->src_dev_mm = NODEV; + if (sd->sd_vol.sv_chunks[c]->src_vn) { + vn_lock(sd->sd_vol.sv_chunks[c]->src_vn, + LK_EXCLUSIVE | LK_RETRY, curproc); + VOP_CLOSE(sd->sd_vol.sv_chunks[c]->src_vn, + FREAD | FWRITE, NOCRED, curproc); + vput(sd->sd_vol.sv_chunks[c]->src_vn); + sd->sd_vol.sv_chunks[c]->src_vn = NULL; + } + } + sd->sd_must_flush = 1; task_add(systq, &sd->sd_meta_save_task); done: diff --git a/sys/dev/softraid_raid1.c b/sys/dev/softraid_raid1.c index 055b8868dfa..5106054129c 100644 --- a/sys/dev/softraid_raid1.c +++ b/sys/dev/softraid_raid1.c @@ -28,6 +28,8 @@ #include <sys/rwlock.h> #include <sys/queue.h> #include <sys/fcntl.h> +#include <sys/vnode.h> +#include <sys/lock.h> #include <sys/mount.h> #include <sys/sensors.h> #include <sys/stat.h> @@ -184,6 +186,18 @@ die: sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state; sd->sd_set_vol_state(sd); + if (new_state == BIOC_SDOFFLINE) { + sd->sd_vol.sv_chunks[c]->src_dev_mm = NODEV; + if (sd->sd_vol.sv_chunks[c]->src_vn) { + vn_lock(sd->sd_vol.sv_chunks[c]->src_vn, + LK_EXCLUSIVE | LK_RETRY, curproc); + VOP_CLOSE(sd->sd_vol.sv_chunks[c]->src_vn, + FREAD | FWRITE, NOCRED, curproc); + vput(sd->sd_vol.sv_chunks[c]->src_vn); + sd->sd_vol.sv_chunks[c]->src_vn = NULL; + } + } + sd->sd_must_flush = 1; task_add(systq, &sd->sd_meta_save_task); done: diff --git a/sys/dev/softraid_raid5.c b/sys/dev/softraid_raid5.c index a3425842808..d2c36fe577d 100644 --- a/sys/dev/softraid_raid5.c +++ b/sys/dev/softraid_raid5.c @@ -30,6 +30,8 @@ #include <sys/rwlock.h> #include <sys/queue.h> #include <sys/fcntl.h> +#include <sys/vnode.h> +#include <sys/lock.h> #include <sys/mount.h> #include <sys/sensors.h> #include <sys/stat.h> @@ -212,6 +214,18 @@ die: sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state; sd->sd_set_vol_state(sd); + if (new_state == BIOC_SDOFFLINE) { + sd->sd_vol.sv_chunks[c]->src_dev_mm = NODEV; + if (sd->sd_vol.sv_chunks[c]->src_vn) { + vn_lock(sd->sd_vol.sv_chunks[c]->src_vn, + LK_EXCLUSIVE | LK_RETRY, curproc); + VOP_CLOSE(sd->sd_vol.sv_chunks[c]->src_vn, + FREAD | FWRITE, NOCRED, curproc); + vput(sd->sd_vol.sv_chunks[c]->src_vn); + sd->sd_vol.sv_chunks[c]->src_vn = NULL; + } + } + sd->sd_must_flush = 1; task_add(systq, &sd->sd_meta_save_task); done: diff --git a/sys/dev/softraid_raid6.c b/sys/dev/softraid_raid6.c index 14eb9f98369..aee93eae6f5 100644 --- a/sys/dev/softraid_raid6.c +++ b/sys/dev/softraid_raid6.c @@ -29,6 +29,8 @@ #include <sys/rwlock.h> #include <sys/queue.h> #include <sys/fcntl.h> +#include <sys/vnode.h> +#include <sys/lock.h> #include <sys/mount.h> #include <sys/sensors.h> #include <sys/stat.h> @@ -230,6 +232,18 @@ die: sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state; sd->sd_set_vol_state(sd); + if (new_state == BIOC_SDOFFLINE) { + sd->sd_vol.sv_chunks[c]->src_dev_mm = NODEV; + if (sd->sd_vol.sv_chunks[c]->src_vn) { + vn_lock(sd->sd_vol.sv_chunks[c]->src_vn, + LK_EXCLUSIVE | LK_RETRY, curproc); + VOP_CLOSE(sd->sd_vol.sv_chunks[c]->src_vn, + FREAD | FWRITE, NOCRED, curproc); + vput(sd->sd_vol.sv_chunks[c]->src_vn); + sd->sd_vol.sv_chunks[c]->src_vn = NULL; + } + } + sd->sd_must_flush = 1; task_add(systq, &sd->sd_meta_save_task); done: