Skip to content

Commit

Permalink
Merged in DW-1381-remove-device-io-bsod (pull request #394)
Browse files Browse the repository at this point in the history
DW-1381 fix BSOD when volume is removed during IO.
  • Loading branch information
sungeun-kim committed Jan 23, 2017
2 parents d236498 + 7705b82 commit 3c9d460
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 12 deletions.
10 changes: 5 additions & 5 deletions wdrbd9/disp.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ mvolCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
if (VolumeExtension->Active)
{
// DW-1300: get device and get reference.
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension);
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension, TRUE);
// DW-1300: prevent mounting volume when device went diskless.
if (device && ((R_PRIMARY != device->resource->role[NOW]) || (device->resource->bPreDismountLock == TRUE) || device->disk_state[NOW] == D_DISKLESS)) // V9
{
Expand Down Expand Up @@ -476,7 +476,7 @@ mvolFlush(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

if (g_mj_flush_buffers_filter && VolumeExtension->Active) {
// DW-1300: get device and get reference.
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension);
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension, TRUE);
if (device) {
PMVOL_THREAD pThreadInfo;
pThreadInfo = &VolumeExtension->WorkThreadInfo;
Expand Down Expand Up @@ -520,7 +520,7 @@ mvolSystemControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
if (VolumeExtension->Active)
{
// DW-1300: get device and get reference.
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension);
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension, TRUE);
// DW-1300: prevent mounting volume when device is failed or below.
if (device && device->resource->bTempAllowMount == FALSE && ((R_PRIMARY != device->resource->role[NOW]) || (device->resource->bPreDismountLock == TRUE) || device->disk_state[NOW] <= D_FAILED)) // V9
{
Expand Down Expand Up @@ -565,7 +565,7 @@ mvolRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
if (VolumeExtension->Active)
{
// DW-1300: get device and get reference.
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension);
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension, TRUE);
// DW-1363: prevent mounting volume when device is failed or below.
if (device && ((R_PRIMARY == device->resource->role[0]) && (device->resource->bPreDismountLock == FALSE) && device->disk_state[NOW] > D_FAILED || device->resource->bTempAllowMount == TRUE))
{
Expand Down Expand Up @@ -640,7 +640,7 @@ mvolWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

if (VolumeExtension->Active) {
// DW-1300: get device and get reference.
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension);
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension, TRUE);
// DW-1363: prevent writing when device is failed or below.
if (device && device->resource && (device->resource->role[NOW] == R_PRIMARY) && (device->resource->bPreSecondaryLock == FALSE) && (device->disk_state[NOW] > D_FAILED)) {

Expand Down
28 changes: 26 additions & 2 deletions wdrbd9/drbd_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -2237,7 +2237,7 @@ void query_targetdev(PVOLUME_EXTENSION pvext)
!RtlEqualUnicodeString(&pvext->MountPoint, &new_name, TRUE))
{
// DW-1300: get device and get reference.
struct drbd_device *device = get_device_with_vol_ext(pvext);
struct drbd_device *device = get_device_with_vol_ext(pvext, TRUE);
if (device &&
get_ldev_if_state(device, D_NEGOTIATING))
{
Expand Down Expand Up @@ -2518,6 +2518,9 @@ void delete_drbd_block_device(struct kref *kref)
ObDereferenceObject(bdev->bd_disk->pDeviceExtension->DeviceObject);
bdev->bd_disk->pDeviceExtension->DeviceObject = NULL;

// DW-1381: set dev as NULL not to access from this volume extension since it's being deleted.
bdev->bd_disk->pDeviceExtension->dev = NULL;

blk_cleanup_queue(bdev->bd_disk->queue);

put_disk(bdev->bd_disk);
Expand All @@ -2527,14 +2530,32 @@ void delete_drbd_block_device(struct kref *kref)
}

// get device with volume extension in safe, user should put ref when no longer use device.
struct drbd_device *get_device_with_vol_ext(PVOLUME_EXTENSION pvext)
struct drbd_device *get_device_with_vol_ext(PVOLUME_EXTENSION pvext, bool bCheckRemoveLock)
{
unsigned char oldIRQL = 0;
struct drbd_device *device = NULL;

if (KeGetCurrentIrql() > DISPATCH_LEVEL)
return NULL;

// DW-1381: dev is set as NULL when block device is destroyed.
if (!pvext->dev)
{
WDRBD_ERROR("failed to get drbd device since pvext->dev is NULL\n");
return NULL;
}

// DW-1381: check if device is removed already.
if (bCheckRemoveLock)
{
NTSTATUS status = IoAcquireRemoveLock(&pvext->RemoveLock, NULL);
if (!NT_SUCCESS(status))
{
WDRBD_INFO("failed to acquire remove lock with status:0x%x, return NULL\n", status);
return NULL;
}
}

oldIRQL = ExAcquireSpinLockShared(&pvext->dev->bd_disk->drbd_device_ref_lock);
device = pvext->dev->bd_disk->drbd_device;
if (device)
Expand All @@ -2548,6 +2569,9 @@ struct drbd_device *get_device_with_vol_ext(PVOLUME_EXTENSION pvext)
}
ExReleaseSpinLockShared(&pvext->dev->bd_disk->drbd_device_ref_lock, oldIRQL);

if (bCheckRemoveLock)
IoReleaseRemoveLock(&pvext->RemoveLock, NULL);

return device;
}

Expand Down
2 changes: 1 addition & 1 deletion wdrbd9/drbd_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,7 @@ extern void NTAPI NetlinkServerThread(PVOID p);
extern struct block_device * create_drbd_block_device(IN OUT PVOLUME_EXTENSION pvext);
extern void delete_drbd_block_device(struct kref *kref);
// DW-1300
extern struct drbd_device *get_device_with_vol_ext(PVOLUME_EXTENSION pvext);
extern struct drbd_device *get_device_with_vol_ext(PVOLUME_EXTENSION pvext, bool bCheckRemoveLock);
extern BOOLEAN do_add_minor(unsigned int minor);
extern void drbdFreeDev(PVOLUME_EXTENSION pDeviceExtension);
extern void query_targetdev(PVOLUME_EXTENSION pvext);
Expand Down
2 changes: 1 addition & 1 deletion wdrbd9/ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ IOCTL_MountVolume(PDEVICE_OBJECT DeviceObject, PIRP Irp, PULONG ReturnLength)
}

// DW-1300: get device and get reference.
device = get_device_with_vol_ext(pvext);
device = get_device_with_vol_ext(pvext, TRUE);
if (pvext->WorkThreadInfo.Active && device)
{
sprintf(Message, "%wZ volume is handling by drbd. Failed to mount",
Expand Down
5 changes: 2 additions & 3 deletions wdrbd9/sub.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ mvolRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

if (VolumeExtension->dev) {
// DW-1300: get device and get reference.
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension);
struct drbd_device *device = get_device_with_vol_ext(VolumeExtension, FALSE);
if (device)
{
if (get_disk_state2(device) >= D_INCONSISTENT)
Expand All @@ -180,7 +180,6 @@ mvolRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
// DW-1109: put ref count that's been set as 1 when initialized, in add device routine.
// deleting block device can be defered if drbd device is using.
blkdev_put(VolumeExtension->dev, 0);
VolumeExtension->dev = NULL;
}

// DW-1277: check volume type we marked when drbd attaches.
Expand Down Expand Up @@ -317,7 +316,7 @@ mvolReadWriteDevice(PVOLUME_EXTENSION VolumeExtension, PIRP Irp, ULONG Io)
}

// DW-1300: get device and get reference.
device = get_device_with_vol_ext(VolumeExtension);
device = get_device_with_vol_ext(VolumeExtension, TRUE);
if (device/* && (mdev->state.role == R_PRIMARY)*/) {
struct splitInfo *splitInfo = 0;
ULONG io_id = 0;
Expand Down

0 comments on commit 3c9d460

Please sign in to comment.