Code to mostly prevent this deadlock in kernel has already been
committed as 701b3696; this userland code provides earlier, better
error messages for this problem.
Do not keep UFS suspended while writing new cylinder groups.
Since the new cylinder groups are outside the existing filesystem, UFS
does not need to be suspended while writing them. We can write the
new cylinder groups first, before editing the existing filesystem.
THis has two benefits: Most of the writes (and potential I/O errors)
are done before editing the existing filesystem, and it limits the
maximum suspended time to one cylinder group's worth of I/O. This is
quite significant for filesystems that have a lot of new cylinder
groups to write.
Unfortunately, to get write access to the filesystem's volume, we
still need to suspend UFS via the /dev/ufssuspend interface, even for
blocks beyond the existing filesystem. Do it repeatedly for each
cylinder group. This means the accumulated suspended time remains
the same, or maybe even grows, if filesystem reloads are costly.
Kernel changes in ufssuspend will be needed to remove this lmitations.
Inmprove growfs/ufssuspend to write new blocks without suspending UFS
Like the old code, this prevents unmounts while growfs is running;
this is now technically only required at the very end when growfs
rewrites what used to be the last cg and the superblock, but it
provides a better UX if unmounts are attempted during growfs.
This work is forward and backward compatible: a new growfs will work
with an unchanged kernel, and vice versa.