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

Linux compat 4.18: check_disk_size_change() #7611

Merged
merged 1 commit into from Jun 15, 2018

Conversation

behlendorf
Copy link
Contributor

@behlendorf behlendorf commented Jun 7, 2018

Description

Added support for the bops->check_events() interface which was added in the 2.6.38 kernel to replace bops->media_changed(). Fully implementing this functionality allows the volume resize code to rely on revalidate_disk(), which is the preferred mechanism, and removes the need to use check_disk_size_change().

In order for bops->check_events() to lookup the zvol_state_t stored in the disk->private_data the zvol_state_lock needs to be held. Since the check events interface may poll the mutex has been converted to a rwlock for better concurrency. The rwlock need only be taken as a writer in the zvol_free() path when disk->private_data is set to NULL.

The configure checks for the block_device_operations structure were consolidated in a single kernel-block-device-operations.m4 file.

The ZFS_AC_KERNEL_BDEV_BLOCK_DEVICE_OPERATIONS configure checks and assoicated dead code was removed. This interface was added to the 2.6.28 kernel which predates the oldest supported 2.6.32 kernel and will therefore always be available.

Updated maximum Linux version in META file. The 4.17 kernel was released on 2018-06-03 and ZoL is compatible with the finalized kernel.

Motivation and Context

Maintain compatibility with the latest kernels.

How Has This Been Tested?

Locally built and manually tested that change events are being generated for resized volumes. Relying on the bots to verify functionality for populate kernel versions. Locally, all basic zvol tests pass.

$ ./scripts/zfs-tests.sh -T zvol 
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos (run as root) [00:03] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev (run as root) [00:16] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode (run as root) [00:47] [PASS]                                                
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil (run as root) [00:09] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/setup (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos (run as root) [00:00] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos (run as root) [00:01] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos (run as root) [00:05] [PASS]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos (run as root) [00:00] [SKIP]
Test: /home/behlendo/src/git/zfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup (run as root) [00:00] [PASS]

Results Summary
SKIP	   8
PASS	  19

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)
  • Documentation (a change to man pages or other documentation)

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.

@behlendorf behlendorf requested a review from shartse June 7, 2018 18:35
@behlendorf behlendorf added the Status: Work in Progress Not yet ready for general review label Jun 8, 2018
@behlendorf behlendorf force-pushed the check_events branch 2 times, most recently from 929e87f to 72f512c Compare June 12, 2018 22:53
@behlendorf
Copy link
Contributor Author

@bprotopopov would you mind reviewing this change, and if possible stress testing it for possible new locking issues introduced by the check_events handler.

@behlendorf behlendorf removed the Status: Work in Progress Not yet ready for general review label Jun 13, 2018
@shartse
Copy link
Contributor

shartse commented Jun 13, 2018

This seems reasonable to me after an initial pass, though I'll keep looking. Have you been able to verify that udev "change" events are generated when expected? When are they expected? I could do some tests with hot-expand if that would be helpful

@behlendorf
Copy link
Contributor Author

@shartse thanks for looking at this. I manually verified that the "change" events were being generated based on the console detected capacity change log message and by inspecting the output of udevadm monitor -p when resizing a zvol. Additionally, #7629 builds on this change to support the autoexpend property which also consumes these events.

@bprotopopov
Copy link
Contributor

Yes, I’ll take a look, @behlendorf

Copy link
Contributor

@bprotopopov bprotopopov left a comment

Choose a reason for hiding this comment

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

LGTM modulo the comments.

ASSERT(!MUTEX_HELD(&zvol_state_lock));

mutex_enter(&zvol_state_lock);
rw_enter(&zvol_state_lock, RW_READER);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we assert that zvol_state_lock is not held here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this was converted to a krwlock it's now possible that another thread is holding the lock as a reader. The best we can do is assert that we're not holding it a writer but that wasn't really useful so I dropped it entirely.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, it makes sense, thanks.

ASSERT(!MUTEX_HELD(&zvol_state_lock));

mutex_enter(&zvol_state_lock);
rw_enter(&zvol_state_lock, RW_READER);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we assert that zvol_state_lock is not held here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as above.

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it.


zvol_state_t *zv = disk->private_data;
if (zv != NULL) {
boolean_t locked = MUTEX_HELD(&zv->zv_state_lock);
Copy link
Contributor

Choose a reason for hiding this comment

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

For this function, as well as zvol_media_changed() and zvol_revalidate_disk(), I am not sure why we don't know if we are holding the zv_state_lock(). Can some comments be added here as to the possible locking states of the calling thread and the context for those states to take place?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, will do.

Added support for the bops->check_events() interface which was
added in the 2.6.38 kernel to replace bops->media_changed().
Fully implementing this functionality allows the volume resize
code to rely on revalidate_disk(), which is the preferred
mechanism, and removes the need to use check_disk_size_change().

In order for bops->check_events() to lookup the zvol_state_t
stored in the disk->private_data the zvol_state_lock needs to
be held.  Since the check events interface may poll the mutex
has been converted to a rwlock for better concurrently.  The
rwlock need only be taken as a writer in the zvol_free() path
when disk->private_data is set to NULL.

The configure checks for the block_device_operations structure
were consolidated in a single kernel-block-device-operations.m4
file.

The ZFS_AC_KERNEL_BDEV_BLOCK_DEVICE_OPERATIONS configure checks
and assoicated dead code was removed.  This interface was added
to the 2.6.28 kernel which predates the oldest supported 2.6.32
kernel and will therefore always be available.

Updated maximum Linux version in META file.  The 4.17 kernel
was released on 2018-06-03 and ZoL is compatible with the
finalized kernel.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
@behlendorf
Copy link
Contributor Author

@bprotopopov @shartse refreshed.

I've removed the locked check in the zvol_check_events(), zvol_media_changed(), and zvol_revalidate_disk() functions. It was originally added to handle the case where revalidate_disk() was called under the zv->zv_state_lock, however that wasn't sufficient and a lock inversion was still possible with the bdev->bd_mutex. Both issues were resolved by pulling the revalidate_disk() call outside the locks.


set_capacity(zv->zv_disk, volsize >> 9);
zv->zv_volsize = volsize;
check_disk_size_change(zv->zv_disk, bdev);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there anything we're losing from no longer using check_disk_size_change?

It looks like there's kernel logging:
printk(KERN_INFO, "%s: detected capacity change from %lld to %lld\n", disk->disk_name, bdev_size, disk_size);

and updates to the inode:
i_size_write(bdev->bd_inode, disk_size);

I'm not sure if the inode is meaningful to us in this case, I don't fully understand how it relates to azvol. I also don't know if kernel logging makes sense as a level of abstraction for a zvol but maybe we can get the size change logged in zfs_dbgmsg?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@shartse good question. The short answer is we shouldn't be losing anything since revalidate_disk() will internally call check_disk_size_change(). In fact, revalidate_disk() is the interface we should have been using all along, and check_disk_size_change() was un-exported because it wasn't originally intended to be called by drivers.

As for logging the size change that's an interesting thought, what would be the use case for this?
In practice my feeling is it wouldn't be too useful, and we would already have some log information from the zpool history log entry.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool - thanks for the clarification. I think having the information in zpool history is sufficient

Copy link
Contributor

@bprotopopov bprotopopov left a comment

Choose a reason for hiding this comment

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

LGTM

@codecov
Copy link

codecov bot commented Jun 15, 2018

Codecov Report

Merging #7611 into master will decrease coverage by <.01%.
The diff coverage is 88.88%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #7611      +/-   ##
==========================================
- Coverage   77.45%   77.44%   -0.01%     
==========================================
  Files         363      363              
  Lines      110514   110517       +3     
==========================================
- Hits        85595    85592       -3     
- Misses      24919    24925       +6
Flag Coverage Δ
#kernel 78.39% <88.88%> (+0.21%) ⬆️
#user 66.23% <ø> (-0.15%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 29445fe...6d464db. Read the comment docs.

@behlendorf behlendorf merged commit 7b98f0d into openzfs:master Jun 15, 2018
@tonyhutter tonyhutter added this to To do in 0.7.10 Aug 7, 2018
ryao pushed a commit to ryao/zfs that referenced this pull request Aug 13, 2018
Added support for the bops->check_events() interface which was
added in the 2.6.38 kernel to replace bops->media_changed().
Fully implementing this functionality allows the volume resize
code to rely on revalidate_disk(), which is the preferred
mechanism, and removes the need to use check_disk_size_change().

In order for bops->check_events() to lookup the zvol_state_t
stored in the disk->private_data the zvol_state_lock needs to
be held.  Since the check events interface may poll the mutex
has been converted to a rwlock for better concurrently.  The
rwlock need only be taken as a writer in the zvol_free() path
when disk->private_data is set to NULL.

The configure checks for the block_device_operations structure
were consolidated in a single kernel-block-device-operations.m4
file.

The ZFS_AC_KERNEL_BDEV_BLOCK_DEVICE_OPERATIONS configure checks
and assoicated dead code was removed.  This interface was added
to the 2.6.28 kernel which predates the oldest supported 2.6.32
kernel and will therefore always be available.

Updated maximum Linux version in META file.  The 4.17 kernel
was released on 2018-06-03 and ZoL is compatible with the
finalized kernel.

Reviewed-by: Boris Protopopov <boris.protopopov@actifio.com>
Reviewed-by: Sara Hartse <sara.hartse@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#7611
Backported-by: Richard Yao <ryao@gentoo.org>
@tonyhutter tonyhutter moved this from To do to In progress in 0.7.10 Aug 14, 2018
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request Aug 15, 2018
Added support for the bops->check_events() interface which was
added in the 2.6.38 kernel to replace bops->media_changed().
Fully implementing this functionality allows the volume resize
code to rely on revalidate_disk(), which is the preferred
mechanism, and removes the need to use check_disk_size_change().

In order for bops->check_events() to lookup the zvol_state_t
stored in the disk->private_data the zvol_state_lock needs to
be held.  Since the check events interface may poll the mutex
has been converted to a rwlock for better concurrently.  The
rwlock need only be taken as a writer in the zvol_free() path
when disk->private_data is set to NULL.

The configure checks for the block_device_operations structure
were consolidated in a single kernel-block-device-operations.m4
file.

The ZFS_AC_KERNEL_BDEV_BLOCK_DEVICE_OPERATIONS configure checks
and assoicated dead code was removed.  This interface was added
to the 2.6.28 kernel which predates the oldest supported 2.6.32
kernel and will therefore always be available.

Updated maximum Linux version in META file.  The 4.17 kernel
was released on 2018-06-03 and ZoL is compatible with the
finalized kernel.

Reviewed-by: Boris Protopopov <boris.protopopov@actifio.com>
Reviewed-by: Sara Hartse <sara.hartse@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#7611
Backported-by: Richard Yao <ryao@gentoo.org>
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request Aug 23, 2018
Added support for the bops->check_events() interface which was
added in the 2.6.38 kernel to replace bops->media_changed().
Fully implementing this functionality allows the volume resize
code to rely on revalidate_disk(), which is the preferred
mechanism, and removes the need to use check_disk_size_change().

In order for bops->check_events() to lookup the zvol_state_t
stored in the disk->private_data the zvol_state_lock needs to
be held.  Since the check events interface may poll the mutex
has been converted to a rwlock for better concurrently.  The
rwlock need only be taken as a writer in the zvol_free() path
when disk->private_data is set to NULL.

The configure checks for the block_device_operations structure
were consolidated in a single kernel-block-device-operations.m4
file.

The ZFS_AC_KERNEL_BDEV_BLOCK_DEVICE_OPERATIONS configure checks
and assoicated dead code was removed.  This interface was added
to the 2.6.28 kernel which predates the oldest supported 2.6.32
kernel and will therefore always be available.

Updated maximum Linux version in META file.  The 4.17 kernel
was released on 2018-06-03 and ZoL is compatible with the
finalized kernel.

Reviewed-by: Boris Protopopov <boris.protopopov@actifio.com>
Reviewed-by: Sara Hartse <sara.hartse@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#7611
@tonyhutter tonyhutter moved this from In progress to Done in 0.7.10 Aug 30, 2018
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request Sep 5, 2018
Added support for the bops->check_events() interface which was
added in the 2.6.38 kernel to replace bops->media_changed().
Fully implementing this functionality allows the volume resize
code to rely on revalidate_disk(), which is the preferred
mechanism, and removes the need to use check_disk_size_change().

In order for bops->check_events() to lookup the zvol_state_t
stored in the disk->private_data the zvol_state_lock needs to
be held.  Since the check events interface may poll the mutex
has been converted to a rwlock for better concurrently.  The
rwlock need only be taken as a writer in the zvol_free() path
when disk->private_data is set to NULL.

The configure checks for the block_device_operations structure
were consolidated in a single kernel-block-device-operations.m4
file.

The ZFS_AC_KERNEL_BDEV_BLOCK_DEVICE_OPERATIONS configure checks
and assoicated dead code was removed.  This interface was added
to the 2.6.28 kernel which predates the oldest supported 2.6.32
kernel and will therefore always be available.

Updated maximum Linux version in META file.  The 4.17 kernel
was released on 2018-06-03 and ZoL is compatible with the
finalized kernel.

Reviewed-by: Boris Protopopov <boris.protopopov@actifio.com>
Reviewed-by: Sara Hartse <sara.hartse@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#7611
@behlendorf behlendorf deleted the check_events branch April 19, 2021 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
0.7.10
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants