-
Notifications
You must be signed in to change notification settings - Fork 32
Add udev semaphore synchronization for uevent-generating commands #774
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
Conversation
2a1bd12
to
1cc7d09
Compare
e44f5c3
to
f5e10b3
Compare
@bmr-cymru Plz put up a stratisd PR that uses these changes in the manner intended. You can just edit that PRs Cargo.toml to point the devicemapper-rs dependency at this PR. Sort of like stratis-storage/stratisd#2907, although that is tremendously obsolete now. |
Pulling this back into draft for now to fix some problems I found while testing with stratis. |
d12e103
to
6d114a9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still working...one minor comment.
6d114a9
to
6bf146c
Compare
Good point. I'll update the commit to drop that mention at least - I can test removing the allowlist although in some ways I think it's desirable even with the fix for the |
I think it's best to keep the allow listing - this avoids conflicts between the types in the generated bindings that result from the same types being exposed in both the device-mapper and SysV semaphore headers:
I'll edit the commit message accordingly. |
6bf146c
to
18882d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last batch of minor suggestions.
@bmr-cymru Ok! It looks like we're good to go. Let me know when you've squashed all the commits that need to be squashed, and then I'll merge the PR and make a new release. |
cc2a352
to
b5ac771
Compare
Add the log crate for the logging facade macros and enable the Rust env_logger in the testing module. Related: stratis-storage#768
Add simple debug!() logging statements to each device-mapper operation in the dm module. Resolves: stratis-storage#768
The udev primary source flag will be set automatically by DM::do_ioctl() when issuing a device-mapper ioctl command that generates uevents: remove the setting of the flag from the thindev new, setup, and snapshot methods.
A device-mapper cookie is a 32-bit value comprising 16 device-mapper udev rule control flags in the upper sixteen bits and a randomly generated base value in the lower 16 bits: +----------------+----------------+ | udev flags | random base | +----------------+----------------+ The devicemapper-rs DmCookie type is mis-named since it represents the possible values of the udev flags in the upper bits of a cookie value: re-name the type as DmUdevFlags to make the distinction more clear.
Avoid manually re-defining the constants from libdevmapper (for e.g. the udev flag values) by incorporating these definitions into the bindings generated for devicemapper-rs-sys. An allowlist is used to control the visibility of types and constants in the bindings to prevent including unwanted interfaces included from the libdevmapper headers: this avoids conflicts when the same types are defined in the SysV semaphore interface. Use the symbolic names for device-mapper udev flags from the devicemapper-rs-sys bindings rather than hard coding the literal flag values and make the type a plain u32 rather than dmi::__u32. Resolves: stratis-storage#730
Add bindings for the SysV semaphore interface to provide constants and structs currently missing from the libc bindings for some target environments and expose these definitions in a new core::sysvsem sub-module.
Add a new sub-module to encapsulate creating, destroying, and waiting on device-mapper Udev synchronisation semaphores. The module contains the low-level wrappers to the unsafe SysV semaphore bindings provided by the libc crate as well as higher level UdevSync interface for use by other sub-modules: UdevSync::begin() UdevSync::end() UdevSync::cancel() This provides the necessary primitives to implement the ioctl-issuing side of the DM cookie protocol. Completion of DM cookie semaphores is not implemented as this is always carried out by the dmsetup program via udev rule callbacks. This simplifies integrating udev synchronization with the other DM methods and avoids the need to expose the low-level semaphore operations outside the dm_udev_sync module. Since it is possible for the kernel to be compiled without semaphore support or for the administrator to dynamically disable their use via sysctl, runtime semaphore limits are checked in a new helper function, dm_udev_sync::sysv_sem_supported(). Testing the maxid value returned by semctl(0, 0, SEM_INFO, ...) as is done by libdevmapper is not sufficient to determine whether semaphores can be used. It is possible for the administrator to disable them completely via sysctl without causing the maxid value to be less than zero: # echo 0 0 0 0 > /proc/sys/kernel/sem Check that the following values in the returned seminfo struct are greater than zero: semmsl - Maximum number of semaphores in a set semmni - Maximum number of semaphore sets semmns - Maximum number of semaphores in all semaphore sets Additionally log a warning if the value of any of these settings is less than 1000 which is an exceptional situation based on typical modern distribution defaults for these settings. Related: stratis-storage#774
Add udev synchronization to device-mapper ioctl operations that generate uevents by calling UdevSync::begin(), sync.cancel() and sync.end() directly from DM::do_ioctl(). This simplifies and unifies error handling and udev sync clean up vs. implementing synchronization in specific device_*() methods that require it. DM::do_ioctl() decodes the ioctl command to determine whether or not to set the DM_UDEV_PRIMARY_SOURCE_FLAG, which also determines whether or not udev synchronisation should be used for the operation. Related: stratis-storage#774
Allow up to five attempts to remove a device-mapper device when the ioctl returns EBUSY: this implements the same scheme as libdevmapper but with a lower maximum retry count (5 vs. 25): this has been found to be adequate in testing devicemapper-rs. Related: stratis-storage#774
…cache_dev Allowing udev time to interact with the devices invalidates some of the assumptions in loop_test_minimal_cache_dev regarding the state of the cache since udev probes will issue reads to the device to determine its content, meaning that the cache is no longer completely pristine. Remove the following assertions: assert_eq!(usage.used_cache, DataBlocks(0)); assert_eq!(performance.read_hits, 0); assert_eq!(performance.read_misses, 0); assert_eq!(performance.promotions, 0); The alternative would be to expose the DmOptions used to create the cache device stack to users of the CacheDev, allowing device-mapper udev flags to be used to suppress udev rule processing however this would be a quite invasive change solely for the use of the test suite.
Prevent xfs_admin -U from racing with udev inotify disarm while processing the previous (mkfs.xfs) generated uevent by calling udev_settle() after invoking any process that opens a block device for writing.
@mulkieran I've squashed all the fixup commits into their parents and tidied the branch up a little. It's still 12 commits but I think it makes a logical sequence of changes. Let me know if you'd like me to squash more aggressively. |
This branch adds support for udev synchronization using SysV semaphores and the device-mapper ioctl/uevent "cookie" mechanism.
The branch adds a new sub-module,
dm_udev_sync
that wraps the low-level semaphore operations and provides an interface tocore::dm
.All udev synchronization is carried out insde
DM::do_ioctl()
. This centralises and simplifies handling ioctl errors (which require the udev semaphore to be cleaned up before propagating the error) and minimises the changes needed to synchronize with uevents.This branch also adds basic logging infrastructure to the crate, using the log facade and the env_logger crate: this was helpful in developing and debugging the udev interactions and may be useful for debugging other problems involving device-mapper.