Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:Update
drbd.28197
fix-potential-double-call-of-drbd_backing_devic...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fix-potential-double-call-of-drbd_backing_devic.patch of Package drbd.28197
From 3f30589d3c31fc4e89b75d8321db2672925ecc55 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg <lars.ellenberg@linbit.com> Date: Fri, 26 Apr 2019 15:46:50 +0200 Subject: [PATCH] drbd: fix potential double call of drbd_backing_device_free During down/detach, we schedule "DESTROY_DISK" on the DRBD resource worker. But we also schedule a generic work drbd_device_finalize_work_fn() from the drbd_destroy_device() destructor. Both call drbd_backing_dev_free(device, device->ldev); device->ldev = NULL; If due to some race both run at "exactly" the same time, we get a "double free", two calls to bd_unlink_disk_holder(), and | kernfs: can not remove 'dm-0', no directory | WARNING: CPU: 0 PID: 4468 at fs/kernfs/dir.c:1504 kernfs_remove_by_name_ns So we better call that only once. The backing device life time is unrelated to device life time, so the correct place is when detaching from the backing device, not during device destruction. But we need to wait for the worker to actually process the DESTROY_DISK. Once (interruptible) from adm_detach(), so a not interrupted administrative detach will only return after the backing device was in fact released. And once in adm_del_minor(), before unregistering the device object, because otherwise with a quick "detach, del_minor" (aka: "down") we have a race[*] where the worker might not find the device object anymore that was scheduled to have its backing device detached. This wait needs to be uninterruptible. [*] that race would lead to drbd_backing_device_free() never being called, and | vgchange -an scratch | /sys/block/drbd100/dev: fopen failed: No such file or directory | /dev/scratch/s0_00: failed to find associated device structure for holder /dev/drbd100. | Logical volume scratch/s0_00 is used by another device. | Can't deactivate volume group "scratch" with 1 open logical volume(s) --- drbd/drbd_main.c | 5 +---- drbd/drbd_nl.c | 8 +++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drbd/drbd_main.c b/drbd/drbd_main.c index 69e1d15b..e57ea696 100644 --- a/drbd/drbd_main.c +++ b/drbd/drbd_main.c @@ -2943,13 +2943,10 @@ static void drbd_device_finalize_work_fn(struct work_struct *work) { struct drbd_device *device = container_of(work, struct drbd_device, finalize_work); struct drbd_resource *resource = device->resource; - + if (device->this_bdev) bdput(device->this_bdev); - drbd_backing_dev_free(device, device->ldev); - device->ldev = NULL; - if (device->bitmap) { drbd_bm_free(device->bitmap); device->bitmap = NULL; diff --git a/drbd/drbd_nl.c b/drbd/drbd_nl.c index a77f9297..bccc6de2 100644 --- a/drbd/drbd_nl.c +++ b/drbd/drbd_nl.c @@ -3124,8 +3124,11 @@ static enum drbd_state_rv adm_detach(struct drbd_device *device, bool force, boo drbd_resume_io(device); ret = wait_event_interruptible(device->misc_wait, get_disk_state(device) != D_DETACHING); - if (retcode >= SS_SUCCESS) + if (retcode >= SS_SUCCESS) { + /* wait for completion of drbd_ldev_destroy() */ + wait_event_interruptible(device->misc_wait, !test_bit(GOING_DISKLESS, &device->flags)); drbd_cleanup_device(device); + } else device->device_conf.intentional_diskless = false; if (retcode == SS_IS_DISKLESS) @@ -5856,6 +5859,9 @@ static enum drbd_ret_code adm_del_minor(struct drbd_device *device) stable_change_repl_state(peer_device, L_OFF, CS_VERBOSE | CS_WAIT_COMPLETE); + /* If the worker still has to find it to call drbd_ldev_destroy(), + * we must not unregister the device yet. */ + wait_event(device->misc_wait, !test_bit(GOING_DISKLESS, &device->flags)); /* * Flush the resource work queue to make sure that no more events like * state change notifications for this device are queued: we want the -- 2.16.4
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor