Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix hangs with parallel pool import #16178

Closed
wants to merge 3 commits into from

Conversation

asomers
Copy link
Contributor

@asomers asomers commented May 8, 2024

Motivation and Context

The parallel pool import feature (#16093) can greatly increase the number of threads used by /sbin/zpool . If it reaches the OS-imposed per-process limit and then tries to import an additional pool, the command will hang. This PR fixes such hangs.

Description

The PR consists of four distinct commits:

  • Ensure that tpool_dispatch returns an error if it cannot start at least 1 worker. Previously it would silently fail.
  • If tpool_dispatch fails while mounting file systems, make libzfs fall back to serial execution. This fixes the bug, though with inconsistent performance.
  • Allow /sbin/zpool to control the threadpool size used by libzfs when mounting file systems. This improves the performance of the solution in the previous commit. However, it changes the libzfs ABI.
  • Add an ATF test for tpool_dispatch to ensure correct behavior if it cannot start even one worker. Due to lack of test infrastructure within the OpenZFS repository, this commit is not actually included in this PR. Instead, I plan to commit it directly to FreeBSD.

How Has This Been Tested?

In addition to the aforementioned libtpool test, I have tested this change by importing 6 pools in parallel, each with 1501 file systems. Before my changes, that would fail on 7 out of 8 attempts. Now it always succeeds, with consistent performance.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

Fixes #16172

asomers added 2 commits May 8, 2024 14:06
Sponsored by:	Axcient
Signed-off-by:	Alan Somers <[email protected]>
During parallel zpool import, /sbin/zpool will create a separate thread
pool for each pool, used to mount that pool's datasets.  If the total
thread count exceed's the system's limit on threads per process, then
tpool_dispatch may fail.  If it does, directly execute the mount
operation instead.

Sponsored by:	Axcient
Signed-off-by:	Alan Somers <[email protected]>
Fixes openzfs#16172
@behlendorf behlendorf added the Status: Code Review Needed Ready for review and testing label May 9, 2024
Copy link
Contributor

@behlendorf behlendorf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, it changes the libzfs ABI.

Thanks for calling this out. The original parallel import code has ended up in tagged release yet so this isn't a major problem.

Add an ATF test for tpool_dispatch to ensure correct behavior if it cannot start even one worker. Due to lack of test infrastructure within the OpenZFS repository, this commit is not actually included in this PR. Instead, I plan to commit it directly to FreeBSD.

Good.

@grwilson can you review this.

@asomers
Copy link
Contributor Author

asomers commented May 9, 2024

@behlendorf if it's ok to change the libzfs abi, could you please tell me how to update the libzfs.abi file? It looks like it's automatically generated somehow.

@behlendorf
Copy link
Contributor

@asomers you can download an updated abi file from the artifacts for this PR (at the bottom). You'll just need to replace the current abi file in this PR with the new once after inspecting the differences, then force update the PR.

https://github.com/openzfs/zfs/actions/runs/9007873783?pr=16178

Ever since a10d50f, ZFS has mounted file systems in parallel when
importing a pool.  It uses a fixed size of 512 for the thread pool.  But
since c183d16, it has also imported pools in parallel.  So the total
number of threads at one time is 513 * npools + 1.  That can easily
exceed the system's limit on the number of threads per process, which
will cause one or more pools to be unable to allocate any worker
threads, forcing them to fallback to slow serial mounting .  To
forestall that, manage the threadpool size in /sbin/zpool, not libzfs.
Use the same size (512), but divided by the number of pools.

This is a backwards-incompatible change to the libzfs abi.

Sponsored by:	Axcient
Signed-off-by:	Alan Somers <[email protected]>
@asomers
Copy link
Contributor Author

asomers commented May 9, 2024

@asomers you can download an updated abi file from the artifacts for this PR (at the bottom). You'll just need to replace the current abi file in this PR with the new once after inspecting the differences, then force update the PR.

Ahh, that's easy. Done!

@grwilson grwilson self-requested a review May 10, 2024 14:05
@behlendorf behlendorf added Status: Accepted Ready to integrate (reviewed, tested) and removed Status: Code Review Needed Ready for review and testing labels May 13, 2024
behlendorf pushed a commit that referenced this pull request May 14, 2024
During parallel zpool import, /sbin/zpool will create a separate thread
pool for each pool, used to mount that pool's datasets.  If the total
thread count exceed's the system's limit on threads per process, then
tpool_dispatch may fail.  If it does, directly execute the mount
operation instead.

Sponsored by: Axcient
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: George Wilson <[email protected]>
Signed-off-by: Alan Somers <[email protected]>
Closes #16178
Fixes #16172
behlendorf pushed a commit that referenced this pull request May 14, 2024
Ever since a10d50f, ZFS has mounted file systems in parallel when
importing a pool.  It uses a fixed size of 512 for the thread pool.  But
since c183d16, it has also imported pools in parallel.  So the total
number of threads at one time is 513 * npools + 1.  That can easily
exceed the system's limit on the number of threads per process, which
will cause one or more pools to be unable to allocate any worker
threads, forcing them to fallback to slow serial mounting .  To
forestall that, manage the threadpool size in /sbin/zpool, not libzfs.
Use the same size (512), but divided by the number of pools.

This is a backwards-incompatible change to the libzfs abi.

Sponsored by: Axcient
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: George Wilson <[email protected]>
Signed-off-by: Alan Somers <[email protected]>
Closes #16178
@asomers asomers deleted the libtpool-hang branch May 14, 2024 16:48
@asomers
Copy link
Contributor Author

asomers commented Jun 13, 2024

Now that this PR has been merged downstream into FreeBSD, here is a review for the libtpool ATF test. https://reviews.freebsd.org/D45587

lundman pushed a commit to openzfsonwindows/openzfs that referenced this pull request Sep 4, 2024
Sponsored by: Axcient
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: George Wilson <[email protected]>
Signed-off-by: Alan Somers <[email protected]>
Closes openzfs#16178
lundman pushed a commit to openzfsonwindows/openzfs that referenced this pull request Sep 4, 2024
During parallel zpool import, /sbin/zpool will create a separate thread
pool for each pool, used to mount that pool's datasets.  If the total
thread count exceed's the system's limit on threads per process, then
tpool_dispatch may fail.  If it does, directly execute the mount
operation instead.

Sponsored by: Axcient
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: George Wilson <[email protected]>
Signed-off-by: Alan Somers <[email protected]>
Closes openzfs#16178
Fixes openzfs#16172
lundman pushed a commit to openzfsonwindows/openzfs that referenced this pull request Sep 4, 2024
Ever since a10d50f, ZFS has mounted file systems in parallel when
importing a pool.  It uses a fixed size of 512 for the thread pool.  But
since c183d16, it has also imported pools in parallel.  So the total
number of threads at one time is 513 * npools + 1.  That can easily
exceed the system's limit on the number of threads per process, which
will cause one or more pools to be unable to allocate any worker
threads, forcing them to fallback to slow serial mounting .  To
forestall that, manage the threadpool size in /sbin/zpool, not libzfs.
Use the same size (512), but divided by the number of pools.

This is a backwards-incompatible change to the libzfs abi.

Sponsored by: Axcient
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: George Wilson <[email protected]>
Signed-off-by: Alan Somers <[email protected]>
Closes openzfs#16178
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Accepted Ready to integrate (reviewed, tested)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Parallel zpool import hangs
3 participants