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

Issue 6065 - Adding ZVol as log device of seprate pool causes deadlock #6134

Closed
wants to merge 2 commits into from

Conversation

bprotopopov
Copy link
Contributor

Introduced zv_state_lock to protect internal state of zvol_state_t.
Reverted commit 1ee159f
Fix lock order inversion with zvol_open()...

Description

Introduced zv_state_lock to protect internal state of zvol_state_t and to avoid taking spa_namespace_lock (e.g. in dmu_objset_own() code path) while holding zvol_stat_lock. Refactore the code accordingly.

Reverted commit 1ee159f
Fix lock order inversion with zvol_open()...
as it did not account for use of zvols as vdevs. The latter use cases resulted in the lock order inversion deadlocks that involved spa_namespace_lock and bdev->bd_mutex.

Motivation and Context

This is needed to allow use of zvols as vdevs (logs, caches, regular vdevs).

How Has This Been Tested?

Tested use of zvols as regular vdevs, logs, and caches. Added and removed devices, exported, and re-imported pools. Performed basic I/O testing. Ran full suit of zfs-test (did not enable additional relevant test cases at this time).

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)

Checklist:

  • My code follows the ZFS on Linux code style requirements.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • All commit messages are properly formatted and contain Signed-off-by.
  • Change has been approved by a ZFS on Linux member.

@mention-bot
Copy link

@bprotopopov, thanks for your PR! By analyzing the history of the files in this pull request, we identified @behlendorf, @tuxoko and @fajarnugraha to be potential reviewers.

@bprotopopov
Copy link
Contributor Author

Addressed commit message style issues:
error: commit subject over 50 characters
error: missing "Signed-off-by"

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.

Nice. The timing is good for this, I happened to recently be looking at enabling additional test cases which require this so I'll pull this locally and test it out.

* devices on top of zvols. In particular, management of device minor number
* operations - create, remove, rename, and set_snapdev - involves access to
* these structures. The zvol_state_lock is primarily used to protect the
* zvol_state_list, while the zv_state_lock is used to protect the contents
Copy link
Contributor

Choose a reason for hiding this comment

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

The names zvol_state_lock and zv_state_lock are so close how about adding zv-> here to make it clear it's a member of the structure. And I think we can break this in to two sentences.

- * zvol_state_list,  while the zv_state_lock is used to protect the contents
+ * zvol_state_list.  The zv->zv_state_lock is used to protect the contents

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, will change.

* operations - create, remove, rename, and set_snapdev - involves access to
* these structures. The zvol_state_lock is primarily used to protect the
* zvol_state_list, while the zv_state_lock is used to protect the contents
* of the zvol_state_t structures, as well as to make sure that when it the
Copy link
Contributor

Choose a reason for hiding this comment

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

s/when it the/when the/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do.

return (SET_ERROR(error));
if (zv != NULL)
mutex_exit(&zv->zv_state_lock);
return (SET_ERROR(ENXIO));
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you find an issue here returning error instead of ENXIO unconditionally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it looks like an oversight, will fix.

for (zv = list_head(&free_list); zv != NULL; zv = zv_next) {
zv_next = list_next(&free_list, zv);
zvol_free(zv);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

How about using the while/list_head/list_remove idiom here.

while ((zv = list_head(&free_list)) != NULL) {
        list_remove(&free_list, zv);
        zvol_free(zv);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, seems reasonable to me.

@bprotopopov
Copy link
Contributor Author

Forced-pushed the changes.

The lock is designed to protect internal state of zvol_state_t and
to avoid taking spa_namespace_lock (e.g. in dmu_objset_own() code path)
while holding zvol_stat_lock. Refactor the code accordingly.

Signed-off-by: Boris Protopopov <boris.protopopov@actifio.com>
Revert commit 1ee159f
    Fix lock order inversion with zvol_open()...
as it did not account for use of zvols as vdevs. The latter
use cases resulted in the lock order inversion deadlocks
that involved spa_namespace_lock and bdev->bd_mutex.

Signed-off-by: Boris Protopopov <boris.protopopov@actifio.com>
@bprotopopov
Copy link
Contributor Author

Noticed a small typo in the commit message, re-pushed.

@behlendorf
Copy link
Contributor

Thanks for updating this.

I've updated #6128 to include your original version of this patch. That PR additionally enables most of the test cases which depend on this functionality. Pushed to the bots for testing, everything worked as expected for me locally.

@bprotopopov
Copy link
Contributor Author

awesome, @behlendorf, nice to hear

@behlendorf
Copy link
Contributor

The test failures were unrelated and I haven't observed any issues with this change locally. I'm merging it to master and we'll get the test cases which depend on it enabled soon to avoid regressing. @bprotopopov thanks for sorting this out!

behlendorf pushed a commit that referenced this pull request May 16, 2017
Fix lock order inversion with zvol_open() as it did not account
for use of zvols as vdevs. The latter use cases resulted in the
lock order inversion deadlocks that involved spa_namespace_lock
and bdev->bd_mutex.

Signed-off-by: Boris Protopopov <boris.protopopov@actifio.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #6065
Issue #6134
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants