diff options
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 87925e97e613..29e5c70e4e26 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -870,6 +870,11 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
870 | retcode = ERR_DISK_CONFIGURED; | 870 | retcode = ERR_DISK_CONFIGURED; |
871 | goto fail; | 871 | goto fail; |
872 | } | 872 | } |
873 | /* It may just now have detached because of IO error. Make sure | ||
874 | * drbd_ldev_destroy is done already, we may end up here very fast, | ||
875 | * e.g. if someone calls attach from the on-io-error handler, | ||
876 | * to realize a "hot spare" feature (not that I'd recommend that) */ | ||
877 | wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); | ||
873 | 878 | ||
874 | /* allocation not in the IO path, cqueue thread context */ | 879 | /* allocation not in the IO path, cqueue thread context */ |
875 | nbc = kzalloc(sizeof(struct drbd_backing_dev), GFP_KERNEL); | 880 | nbc = kzalloc(sizeof(struct drbd_backing_dev), GFP_KERNEL); |
@@ -1098,9 +1103,9 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
1098 | /* Reset the "barriers don't work" bits here, then force meta data to | 1103 | /* Reset the "barriers don't work" bits here, then force meta data to |
1099 | * be written, to ensure we determine if barriers are supported. */ | 1104 | * be written, to ensure we determine if barriers are supported. */ |
1100 | if (nbc->dc.no_md_flush) | 1105 | if (nbc->dc.no_md_flush) |
1101 | set_bit(MD_NO_BARRIER, &mdev->flags); | 1106 | set_bit(MD_NO_FUA, &mdev->flags); |
1102 | else | 1107 | else |
1103 | clear_bit(MD_NO_BARRIER, &mdev->flags); | 1108 | clear_bit(MD_NO_FUA, &mdev->flags); |
1104 | 1109 | ||
1105 | /* Point of no return reached. | 1110 | /* Point of no return reached. |
1106 | * Devices and memory are no longer released by error cleanup below. | 1111 | * Devices and memory are no longer released by error cleanup below. |
@@ -1112,8 +1117,8 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
1112 | nbc = NULL; | 1117 | nbc = NULL; |
1113 | resync_lru = NULL; | 1118 | resync_lru = NULL; |
1114 | 1119 | ||
1115 | mdev->write_ordering = WO_bio_barrier; | 1120 | mdev->write_ordering = WO_bdev_flush; |
1116 | drbd_bump_write_ordering(mdev, WO_bio_barrier); | 1121 | drbd_bump_write_ordering(mdev, WO_bdev_flush); |
1117 | 1122 | ||
1118 | if (drbd_md_test_flag(mdev->ldev, MDF_CRASHED_PRIMARY)) | 1123 | if (drbd_md_test_flag(mdev->ldev, MDF_CRASHED_PRIMARY)) |
1119 | set_bit(CRASHED_PRIMARY, &mdev->flags); | 1124 | set_bit(CRASHED_PRIMARY, &mdev->flags); |
@@ -1262,7 +1267,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
1262 | force_diskless_dec: | 1267 | force_diskless_dec: |
1263 | put_ldev(mdev); | 1268 | put_ldev(mdev); |
1264 | force_diskless: | 1269 | force_diskless: |
1265 | drbd_force_state(mdev, NS(disk, D_DISKLESS)); | 1270 | drbd_force_state(mdev, NS(disk, D_FAILED)); |
1266 | drbd_md_sync(mdev); | 1271 | drbd_md_sync(mdev); |
1267 | release_bdev2_fail: | 1272 | release_bdev2_fail: |
1268 | if (nbc) | 1273 | if (nbc) |
@@ -1285,10 +1290,19 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
1285 | return 0; | 1290 | return 0; |
1286 | } | 1291 | } |
1287 | 1292 | ||
1293 | /* Detaching the disk is a process in multiple stages. First we need to lock | ||
1294 | * out application IO, in-flight IO, IO stuck in drbd_al_begin_io. | ||
1295 | * Then we transition to D_DISKLESS, and wait for put_ldev() to return all | ||
1296 | * internal references as well. | ||
1297 | * Only then we have finally detached. */ | ||
1288 | static int drbd_nl_detach(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | 1298 | static int drbd_nl_detach(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, |
1289 | struct drbd_nl_cfg_reply *reply) | 1299 | struct drbd_nl_cfg_reply *reply) |
1290 | { | 1300 | { |
1301 | drbd_suspend_io(mdev); /* so no-one is stuck in drbd_al_begin_io */ | ||
1291 | reply->ret_code = drbd_request_state(mdev, NS(disk, D_DISKLESS)); | 1302 | reply->ret_code = drbd_request_state(mdev, NS(disk, D_DISKLESS)); |
1303 | if (mdev->state.disk == D_DISKLESS) | ||
1304 | wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); | ||
1305 | drbd_resume_io(mdev); | ||
1292 | return 0; | 1306 | return 0; |
1293 | } | 1307 | } |
1294 | 1308 | ||
@@ -1953,7 +1967,6 @@ static int drbd_nl_resume_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
1953 | if (test_bit(NEW_CUR_UUID, &mdev->flags)) { | 1967 | if (test_bit(NEW_CUR_UUID, &mdev->flags)) { |
1954 | drbd_uuid_new_current(mdev); | 1968 | drbd_uuid_new_current(mdev); |
1955 | clear_bit(NEW_CUR_UUID, &mdev->flags); | 1969 | clear_bit(NEW_CUR_UUID, &mdev->flags); |
1956 | drbd_md_sync(mdev); | ||
1957 | } | 1970 | } |
1958 | drbd_suspend_io(mdev); | 1971 | drbd_suspend_io(mdev); |
1959 | reply->ret_code = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0)); | 1972 | reply->ret_code = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0)); |