diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-05-03 09:00:55 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:55:43 -0500 |
commit | daeda1cca91d58bb6c8e45f6734f021bab9c28b7 (patch) | |
tree | 002ba940efd64307f0805d6418634e2559f71363 /drivers/block/drbd/drbd_nl.c | |
parent | 563e4cf25ec804eb02cd30a41baa2fcc6c06679b (diff) |
drbd: RCU for disk_conf
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 144 |
1 files changed, 96 insertions, 48 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index b8ea4807c981..ea62838e0794 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -384,7 +384,8 @@ static enum drbd_fencing_p highest_fencing_policy(struct drbd_tconn *tconn) | |||
384 | rcu_read_lock(); | 384 | rcu_read_lock(); |
385 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { | 385 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { |
386 | if (get_ldev_if_state(mdev, D_CONSISTENT)) { | 386 | if (get_ldev_if_state(mdev, D_CONSISTENT)) { |
387 | fp = max_t(enum drbd_fencing_p, fp, mdev->ldev->dc.fencing); | 387 | fp = max_t(enum drbd_fencing_p, fp, |
388 | rcu_dereference(mdev->ldev->disk_conf)->fencing); | ||
388 | put_ldev(mdev); | 389 | put_ldev(mdev); |
389 | } | 390 | } |
390 | } | 391 | } |
@@ -678,7 +679,12 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev, | |||
678 | struct drbd_backing_dev *bdev) | 679 | struct drbd_backing_dev *bdev) |
679 | { | 680 | { |
680 | sector_t md_size_sect = 0; | 681 | sector_t md_size_sect = 0; |
681 | switch (bdev->dc.meta_dev_idx) { | 682 | int meta_dev_idx; |
683 | |||
684 | rcu_read_lock(); | ||
685 | meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx; | ||
686 | |||
687 | switch (meta_dev_idx) { | ||
682 | default: | 688 | default: |
683 | /* v07 style fixed size indexed meta data */ | 689 | /* v07 style fixed size indexed meta data */ |
684 | bdev->md.md_size_sect = MD_RESERVED_SECT; | 690 | bdev->md.md_size_sect = MD_RESERVED_SECT; |
@@ -713,6 +719,7 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev, | |||
713 | bdev->md.bm_offset = -md_size_sect + MD_AL_OFFSET; | 719 | bdev->md.bm_offset = -md_size_sect + MD_AL_OFFSET; |
714 | break; | 720 | break; |
715 | } | 721 | } |
722 | rcu_read_unlock(); | ||
716 | } | 723 | } |
717 | 724 | ||
718 | /* input size is expected to be in KB */ | 725 | /* input size is expected to be in KB */ |
@@ -803,7 +810,9 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds | |||
803 | /* TODO: should only be some assert here, not (re)init... */ | 810 | /* TODO: should only be some assert here, not (re)init... */ |
804 | drbd_md_set_sector_offsets(mdev, mdev->ldev); | 811 | drbd_md_set_sector_offsets(mdev, mdev->ldev); |
805 | 812 | ||
806 | u_size = mdev->ldev->dc.disk_size; | 813 | rcu_read_lock(); |
814 | u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size; | ||
815 | rcu_read_unlock(); | ||
807 | size = drbd_new_dev_size(mdev, mdev->ldev, u_size, flags & DDSF_FORCED); | 816 | size = drbd_new_dev_size(mdev, mdev->ldev, u_size, flags & DDSF_FORCED); |
808 | 817 | ||
809 | if (drbd_get_capacity(mdev->this_bdev) != size || | 818 | if (drbd_get_capacity(mdev->this_bdev) != size || |
@@ -979,7 +988,9 @@ static void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_ | |||
979 | struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; | 988 | struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; |
980 | 989 | ||
981 | max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9); | 990 | max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9); |
982 | max_segments = mdev->ldev->dc.max_bio_bvecs; | 991 | rcu_read_lock(); |
992 | max_segments = rcu_dereference(mdev->ldev->disk_conf)->max_bio_bvecs; | ||
993 | rcu_read_unlock(); | ||
983 | put_ldev(mdev); | 994 | put_ldev(mdev); |
984 | } | 995 | } |
985 | 996 | ||
@@ -1095,7 +1106,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | |||
1095 | { | 1106 | { |
1096 | enum drbd_ret_code retcode; | 1107 | enum drbd_ret_code retcode; |
1097 | struct drbd_conf *mdev; | 1108 | struct drbd_conf *mdev; |
1098 | struct disk_conf *new_disk_conf; | 1109 | struct disk_conf *new_disk_conf, *old_disk_conf; |
1099 | int err, fifo_size; | 1110 | int err, fifo_size; |
1100 | int *rs_plan_s = NULL; | 1111 | int *rs_plan_s = NULL; |
1101 | 1112 | ||
@@ -1114,19 +1125,15 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | |||
1114 | goto out; | 1125 | goto out; |
1115 | } | 1126 | } |
1116 | 1127 | ||
1117 | /* FIXME freeze IO, cluster wide. | 1128 | new_disk_conf = kmalloc(sizeof(struct disk_conf), GFP_KERNEL); |
1118 | * | ||
1119 | * We should make sure no-one uses | ||
1120 | * some half-updated struct when we | ||
1121 | * assign it later. */ | ||
1122 | |||
1123 | new_disk_conf = kmalloc(sizeof(*new_disk_conf), GFP_KERNEL); | ||
1124 | if (!new_disk_conf) { | 1129 | if (!new_disk_conf) { |
1125 | retcode = ERR_NOMEM; | 1130 | retcode = ERR_NOMEM; |
1126 | goto fail; | 1131 | goto fail; |
1127 | } | 1132 | } |
1128 | 1133 | ||
1129 | memcpy(new_disk_conf, &mdev->ldev->dc, sizeof(*new_disk_conf)); | 1134 | mutex_lock(&mdev->tconn->conf_update); |
1135 | old_disk_conf = mdev->ldev->disk_conf; | ||
1136 | *new_disk_conf = *old_disk_conf; | ||
1130 | if (should_set_defaults(info)) | 1137 | if (should_set_defaults(info)) |
1131 | set_disk_conf_defaults(new_disk_conf); | 1138 | set_disk_conf_defaults(new_disk_conf); |
1132 | 1139 | ||
@@ -1151,7 +1158,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | |||
1151 | if (!rs_plan_s) { | 1158 | if (!rs_plan_s) { |
1152 | dev_err(DEV, "kmalloc of fifo_buffer failed"); | 1159 | dev_err(DEV, "kmalloc of fifo_buffer failed"); |
1153 | retcode = ERR_NOMEM; | 1160 | retcode = ERR_NOMEM; |
1154 | goto fail; | 1161 | goto fail_unlock; |
1155 | } | 1162 | } |
1156 | } | 1163 | } |
1157 | 1164 | ||
@@ -1171,31 +1178,37 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | |||
1171 | 1178 | ||
1172 | if (err) { | 1179 | if (err) { |
1173 | retcode = ERR_NOMEM; | 1180 | retcode = ERR_NOMEM; |
1174 | goto fail; | 1181 | goto fail_unlock; |
1175 | } | 1182 | } |
1176 | 1183 | ||
1177 | /* FIXME | ||
1178 | * To avoid someone looking at a half-updated struct, we probably | ||
1179 | * should have a rw-semaphor on net_conf and disk_conf. | ||
1180 | */ | ||
1181 | write_lock_irq(&global_state_lock); | 1184 | write_lock_irq(&global_state_lock); |
1182 | retcode = drbd_sync_after_valid(mdev, new_disk_conf->resync_after); | 1185 | retcode = drbd_sync_after_valid(mdev, new_disk_conf->resync_after); |
1183 | if (retcode == NO_ERROR) { | 1186 | if (retcode == NO_ERROR) { |
1184 | mdev->ldev->dc = *new_disk_conf; | 1187 | rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf); |
1185 | drbd_sync_after_changed(mdev); | 1188 | drbd_sync_after_changed(mdev); |
1186 | } | 1189 | } |
1187 | write_unlock_irq(&global_state_lock); | 1190 | write_unlock_irq(&global_state_lock); |
1188 | 1191 | ||
1189 | drbd_md_sync(mdev); | 1192 | if (retcode != NO_ERROR) |
1193 | goto fail_unlock; | ||
1190 | 1194 | ||
1195 | drbd_md_sync(mdev); | ||
1191 | 1196 | ||
1192 | if (mdev->state.conn >= C_CONNECTED) | 1197 | if (mdev->state.conn >= C_CONNECTED) |
1193 | drbd_send_sync_param(mdev); | 1198 | drbd_send_sync_param(mdev); |
1194 | 1199 | ||
1200 | mutex_unlock(&mdev->tconn->conf_update); | ||
1201 | synchronize_rcu(); | ||
1202 | kfree(old_disk_conf); | ||
1203 | goto success; | ||
1204 | |||
1205 | fail_unlock: | ||
1206 | mutex_unlock(&mdev->tconn->conf_update); | ||
1195 | fail: | 1207 | fail: |
1196 | put_ldev(mdev); | ||
1197 | kfree(new_disk_conf); | 1208 | kfree(new_disk_conf); |
1198 | kfree(rs_plan_s); | 1209 | kfree(rs_plan_s); |
1210 | success: | ||
1211 | put_ldev(mdev); | ||
1199 | out: | 1212 | out: |
1200 | drbd_adm_finish(info, retcode); | 1213 | drbd_adm_finish(info, retcode); |
1201 | return 0; | 1214 | return 0; |
@@ -1210,6 +1223,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1210 | sector_t max_possible_sectors; | 1223 | sector_t max_possible_sectors; |
1211 | sector_t min_md_device_sectors; | 1224 | sector_t min_md_device_sectors; |
1212 | struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */ | 1225 | struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */ |
1226 | struct disk_conf *new_disk_conf = NULL; | ||
1213 | struct block_device *bdev; | 1227 | struct block_device *bdev; |
1214 | struct lru_cache *resync_lru = NULL; | 1228 | struct lru_cache *resync_lru = NULL; |
1215 | union drbd_state ns, os; | 1229 | union drbd_state ns, os; |
@@ -1243,17 +1257,22 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1243 | retcode = ERR_NOMEM; | 1257 | retcode = ERR_NOMEM; |
1244 | goto fail; | 1258 | goto fail; |
1245 | } | 1259 | } |
1260 | new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL); | ||
1261 | if (!new_disk_conf) { | ||
1262 | retcode = ERR_NOMEM; | ||
1263 | goto fail; | ||
1264 | } | ||
1265 | nbc->disk_conf = new_disk_conf; | ||
1246 | 1266 | ||
1247 | set_disk_conf_defaults(&nbc->dc); | 1267 | set_disk_conf_defaults(new_disk_conf); |
1248 | 1268 | err = disk_conf_from_attrs(new_disk_conf, info); | |
1249 | err = disk_conf_from_attrs(&nbc->dc, info); | ||
1250 | if (err) { | 1269 | if (err) { |
1251 | retcode = ERR_MANDATORY_TAG; | 1270 | retcode = ERR_MANDATORY_TAG; |
1252 | drbd_msg_put_info(from_attrs_err_to_txt(err)); | 1271 | drbd_msg_put_info(from_attrs_err_to_txt(err)); |
1253 | goto fail; | 1272 | goto fail; |
1254 | } | 1273 | } |
1255 | 1274 | ||
1256 | if (nbc->dc.meta_dev_idx < DRBD_MD_INDEX_FLEX_INT) { | 1275 | if (new_disk_conf->meta_dev_idx < DRBD_MD_INDEX_FLEX_INT) { |
1257 | retcode = ERR_MD_IDX_INVALID; | 1276 | retcode = ERR_MD_IDX_INVALID; |
1258 | goto fail; | 1277 | goto fail; |
1259 | } | 1278 | } |
@@ -1261,7 +1280,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1261 | rcu_read_lock(); | 1280 | rcu_read_lock(); |
1262 | nc = rcu_dereference(mdev->tconn->net_conf); | 1281 | nc = rcu_dereference(mdev->tconn->net_conf); |
1263 | if (nc) { | 1282 | if (nc) { |
1264 | if (nbc->dc.fencing == FP_STONITH && nc->wire_protocol == DRBD_PROT_A) { | 1283 | if (new_disk_conf->fencing == FP_STONITH && nc->wire_protocol == DRBD_PROT_A) { |
1265 | rcu_read_unlock(); | 1284 | rcu_read_unlock(); |
1266 | retcode = ERR_STONITH_AND_PROT_A; | 1285 | retcode = ERR_STONITH_AND_PROT_A; |
1267 | goto fail; | 1286 | goto fail; |
@@ -1269,10 +1288,10 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1269 | } | 1288 | } |
1270 | rcu_read_unlock(); | 1289 | rcu_read_unlock(); |
1271 | 1290 | ||
1272 | bdev = blkdev_get_by_path(nbc->dc.backing_dev, | 1291 | bdev = blkdev_get_by_path(new_disk_conf->backing_dev, |
1273 | FMODE_READ | FMODE_WRITE | FMODE_EXCL, mdev); | 1292 | FMODE_READ | FMODE_WRITE | FMODE_EXCL, mdev); |
1274 | if (IS_ERR(bdev)) { | 1293 | if (IS_ERR(bdev)) { |
1275 | dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev, | 1294 | dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->backing_dev, |
1276 | PTR_ERR(bdev)); | 1295 | PTR_ERR(bdev)); |
1277 | retcode = ERR_OPEN_DISK; | 1296 | retcode = ERR_OPEN_DISK; |
1278 | goto fail; | 1297 | goto fail; |
@@ -1287,12 +1306,12 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1287 | * should check it for you already; but if you don't, or | 1306 | * should check it for you already; but if you don't, or |
1288 | * someone fooled it, we need to double check here) | 1307 | * someone fooled it, we need to double check here) |
1289 | */ | 1308 | */ |
1290 | bdev = blkdev_get_by_path(nbc->dc.meta_dev, | 1309 | bdev = blkdev_get_by_path(new_disk_conf->meta_dev, |
1291 | FMODE_READ | FMODE_WRITE | FMODE_EXCL, | 1310 | FMODE_READ | FMODE_WRITE | FMODE_EXCL, |
1292 | (nbc->dc.meta_dev_idx < 0) ? | 1311 | (new_disk_conf->meta_dev_idx < 0) ? |
1293 | (void *)mdev : (void *)drbd_m_holder); | 1312 | (void *)mdev : (void *)drbd_m_holder); |
1294 | if (IS_ERR(bdev)) { | 1313 | if (IS_ERR(bdev)) { |
1295 | dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.meta_dev, | 1314 | dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->meta_dev, |
1296 | PTR_ERR(bdev)); | 1315 | PTR_ERR(bdev)); |
1297 | retcode = ERR_OPEN_MD_DISK; | 1316 | retcode = ERR_OPEN_MD_DISK; |
1298 | goto fail; | 1317 | goto fail; |
@@ -1300,8 +1319,8 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1300 | nbc->md_bdev = bdev; | 1319 | nbc->md_bdev = bdev; |
1301 | 1320 | ||
1302 | if ((nbc->backing_bdev == nbc->md_bdev) != | 1321 | if ((nbc->backing_bdev == nbc->md_bdev) != |
1303 | (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL || | 1322 | (new_disk_conf->meta_dev_idx == DRBD_MD_INDEX_INTERNAL || |
1304 | nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) { | 1323 | new_disk_conf->meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) { |
1305 | retcode = ERR_MD_IDX_INVALID; | 1324 | retcode = ERR_MD_IDX_INVALID; |
1306 | goto fail; | 1325 | goto fail; |
1307 | } | 1326 | } |
@@ -1317,21 +1336,21 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1317 | /* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */ | 1336 | /* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */ |
1318 | drbd_md_set_sector_offsets(mdev, nbc); | 1337 | drbd_md_set_sector_offsets(mdev, nbc); |
1319 | 1338 | ||
1320 | if (drbd_get_max_capacity(nbc) < nbc->dc.disk_size) { | 1339 | if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) { |
1321 | dev_err(DEV, "max capacity %llu smaller than disk size %llu\n", | 1340 | dev_err(DEV, "max capacity %llu smaller than disk size %llu\n", |
1322 | (unsigned long long) drbd_get_max_capacity(nbc), | 1341 | (unsigned long long) drbd_get_max_capacity(nbc), |
1323 | (unsigned long long) nbc->dc.disk_size); | 1342 | (unsigned long long) new_disk_conf->disk_size); |
1324 | retcode = ERR_DISK_TO_SMALL; | 1343 | retcode = ERR_DISK_TO_SMALL; |
1325 | goto fail; | 1344 | goto fail; |
1326 | } | 1345 | } |
1327 | 1346 | ||
1328 | if (nbc->dc.meta_dev_idx < 0) { | 1347 | if (new_disk_conf->meta_dev_idx < 0) { |
1329 | max_possible_sectors = DRBD_MAX_SECTORS_FLEX; | 1348 | max_possible_sectors = DRBD_MAX_SECTORS_FLEX; |
1330 | /* at least one MB, otherwise it does not make sense */ | 1349 | /* at least one MB, otherwise it does not make sense */ |
1331 | min_md_device_sectors = (2<<10); | 1350 | min_md_device_sectors = (2<<10); |
1332 | } else { | 1351 | } else { |
1333 | max_possible_sectors = DRBD_MAX_SECTORS; | 1352 | max_possible_sectors = DRBD_MAX_SECTORS; |
1334 | min_md_device_sectors = MD_RESERVED_SECT * (nbc->dc.meta_dev_idx + 1); | 1353 | min_md_device_sectors = MD_RESERVED_SECT * (new_disk_conf->meta_dev_idx + 1); |
1335 | } | 1354 | } |
1336 | 1355 | ||
1337 | if (drbd_get_capacity(nbc->md_bdev) < min_md_device_sectors) { | 1356 | if (drbd_get_capacity(nbc->md_bdev) < min_md_device_sectors) { |
@@ -1356,7 +1375,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1356 | dev_warn(DEV, "==> truncating very big lower level device " | 1375 | dev_warn(DEV, "==> truncating very big lower level device " |
1357 | "to currently maximum possible %llu sectors <==\n", | 1376 | "to currently maximum possible %llu sectors <==\n", |
1358 | (unsigned long long) max_possible_sectors); | 1377 | (unsigned long long) max_possible_sectors); |
1359 | if (nbc->dc.meta_dev_idx >= 0) | 1378 | if (new_disk_conf->meta_dev_idx >= 0) |
1360 | dev_warn(DEV, "==>> using internal or flexible " | 1379 | dev_warn(DEV, "==>> using internal or flexible " |
1361 | "meta data may help <<==\n"); | 1380 | "meta data may help <<==\n"); |
1362 | } | 1381 | } |
@@ -1399,14 +1418,14 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1399 | } | 1418 | } |
1400 | 1419 | ||
1401 | /* Since we are diskless, fix the activity log first... */ | 1420 | /* Since we are diskless, fix the activity log first... */ |
1402 | if (drbd_check_al_size(mdev, &nbc->dc)) { | 1421 | if (drbd_check_al_size(mdev, new_disk_conf)) { |
1403 | retcode = ERR_NOMEM; | 1422 | retcode = ERR_NOMEM; |
1404 | goto force_diskless_dec; | 1423 | goto force_diskless_dec; |
1405 | } | 1424 | } |
1406 | 1425 | ||
1407 | /* Prevent shrinking of consistent devices ! */ | 1426 | /* Prevent shrinking of consistent devices ! */ |
1408 | if (drbd_md_test_flag(nbc, MDF_CONSISTENT) && | 1427 | if (drbd_md_test_flag(nbc, MDF_CONSISTENT) && |
1409 | drbd_new_dev_size(mdev, nbc, nbc->dc.disk_size, 0) < nbc->md.la_size_sect) { | 1428 | drbd_new_dev_size(mdev, nbc, nbc->disk_conf->disk_size, 0) < nbc->md.la_size_sect) { |
1410 | dev_warn(DEV, "refusing to truncate a consistent device\n"); | 1429 | dev_warn(DEV, "refusing to truncate a consistent device\n"); |
1411 | retcode = ERR_DISK_TO_SMALL; | 1430 | retcode = ERR_DISK_TO_SMALL; |
1412 | goto force_diskless_dec; | 1431 | goto force_diskless_dec; |
@@ -1419,11 +1438,13 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1419 | 1438 | ||
1420 | /* Reset the "barriers don't work" bits here, then force meta data to | 1439 | /* Reset the "barriers don't work" bits here, then force meta data to |
1421 | * be written, to ensure we determine if barriers are supported. */ | 1440 | * be written, to ensure we determine if barriers are supported. */ |
1422 | if (nbc->dc.no_md_flush) | 1441 | if (new_disk_conf->no_md_flush) |
1423 | set_bit(MD_NO_FUA, &mdev->flags); | 1442 | set_bit(MD_NO_FUA, &mdev->flags); |
1424 | else | 1443 | else |
1425 | clear_bit(MD_NO_FUA, &mdev->flags); | 1444 | clear_bit(MD_NO_FUA, &mdev->flags); |
1426 | 1445 | ||
1446 | /* FIXME Missing stuff: rs_plan_s, clip al range */ | ||
1447 | |||
1427 | /* Point of no return reached. | 1448 | /* Point of no return reached. |
1428 | * Devices and memory are no longer released by error cleanup below. | 1449 | * Devices and memory are no longer released by error cleanup below. |
1429 | * now mdev takes over responsibility, and the state engine should | 1450 | * now mdev takes over responsibility, and the state engine should |
@@ -1433,6 +1454,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1433 | mdev->resync = resync_lru; | 1454 | mdev->resync = resync_lru; |
1434 | nbc = NULL; | 1455 | nbc = NULL; |
1435 | resync_lru = NULL; | 1456 | resync_lru = NULL; |
1457 | new_disk_conf = NULL; | ||
1436 | 1458 | ||
1437 | mdev->write_ordering = WO_bdev_flush; | 1459 | mdev->write_ordering = WO_bdev_flush; |
1438 | drbd_bump_write_ordering(mdev, WO_bdev_flush); | 1460 | drbd_bump_write_ordering(mdev, WO_bdev_flush); |
@@ -1530,9 +1552,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1530 | if (drbd_md_test_flag(mdev->ldev, MDF_PEER_OUT_DATED)) | 1552 | if (drbd_md_test_flag(mdev->ldev, MDF_PEER_OUT_DATED)) |
1531 | ns.pdsk = D_OUTDATED; | 1553 | ns.pdsk = D_OUTDATED; |
1532 | 1554 | ||
1533 | if ( ns.disk == D_CONSISTENT && | 1555 | rcu_read_lock(); |
1534 | (ns.pdsk == D_OUTDATED || mdev->ldev->dc.fencing == FP_DONT_CARE)) | 1556 | if (ns.disk == D_CONSISTENT && |
1557 | (ns.pdsk == D_OUTDATED || rcu_dereference(mdev->ldev->disk_conf)->fencing == FP_DONT_CARE)) | ||
1535 | ns.disk = D_UP_TO_DATE; | 1558 | ns.disk = D_UP_TO_DATE; |
1559 | rcu_read_unlock(); | ||
1536 | 1560 | ||
1537 | /* All tests on MDF_PRIMARY_IND, MDF_CONNECTED_IND, | 1561 | /* All tests on MDF_PRIMARY_IND, MDF_CONNECTED_IND, |
1538 | MDF_CONSISTENT and MDF_WAS_UP_TO_DATE must happen before | 1562 | MDF_CONSISTENT and MDF_WAS_UP_TO_DATE must happen before |
@@ -1589,6 +1613,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1589 | FMODE_READ | FMODE_WRITE | FMODE_EXCL); | 1613 | FMODE_READ | FMODE_WRITE | FMODE_EXCL); |
1590 | kfree(nbc); | 1614 | kfree(nbc); |
1591 | } | 1615 | } |
1616 | kfree(new_disk_conf); | ||
1592 | lc_destroy(resync_lru); | 1617 | lc_destroy(resync_lru); |
1593 | 1618 | ||
1594 | finish: | 1619 | finish: |
@@ -1691,7 +1716,7 @@ _check_net_options(struct drbd_tconn *tconn, struct net_conf *old_conf, struct n | |||
1691 | 1716 | ||
1692 | idr_for_each_entry(&tconn->volumes, mdev, i) { | 1717 | idr_for_each_entry(&tconn->volumes, mdev, i) { |
1693 | if (get_ldev(mdev)) { | 1718 | if (get_ldev(mdev)) { |
1694 | enum drbd_fencing_p fp = mdev->ldev->dc.fencing; | 1719 | enum drbd_fencing_p fp = rcu_dereference(mdev->ldev->disk_conf)->fencing; |
1695 | put_ldev(mdev); | 1720 | put_ldev(mdev); |
1696 | if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) | 1721 | if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) |
1697 | return ERR_STONITH_AND_PROT_A; | 1722 | return ERR_STONITH_AND_PROT_A; |
@@ -2159,11 +2184,13 @@ void resync_after_online_grow(struct drbd_conf *mdev) | |||
2159 | 2184 | ||
2160 | int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) | 2185 | int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) |
2161 | { | 2186 | { |
2187 | struct disk_conf *old_disk_conf, *new_disk_conf = NULL; | ||
2162 | struct resize_parms rs; | 2188 | struct resize_parms rs; |
2163 | struct drbd_conf *mdev; | 2189 | struct drbd_conf *mdev; |
2164 | enum drbd_ret_code retcode; | 2190 | enum drbd_ret_code retcode; |
2165 | enum determine_dev_size dd; | 2191 | enum determine_dev_size dd; |
2166 | enum dds_flags ddsf; | 2192 | enum dds_flags ddsf; |
2193 | sector_t u_size; | ||
2167 | int err; | 2194 | int err; |
2168 | 2195 | ||
2169 | retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR); | 2196 | retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR); |
@@ -2204,10 +2231,31 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) | |||
2204 | goto fail; | 2231 | goto fail; |
2205 | } | 2232 | } |
2206 | 2233 | ||
2234 | rcu_read_lock(); | ||
2235 | u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size; | ||
2236 | rcu_read_unlock(); | ||
2237 | if (u_size != (sector_t)rs.resize_size) { | ||
2238 | new_disk_conf = kmalloc(sizeof(struct disk_conf), GFP_KERNEL); | ||
2239 | if (!new_disk_conf) { | ||
2240 | retcode = ERR_NOMEM; | ||
2241 | goto fail; | ||
2242 | } | ||
2243 | } | ||
2244 | |||
2207 | if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) | 2245 | if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) |
2208 | mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev); | 2246 | mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev); |
2209 | 2247 | ||
2210 | mdev->ldev->dc.disk_size = (sector_t)rs.resize_size; | 2248 | if (new_disk_conf) { |
2249 | mutex_lock(&mdev->tconn->conf_update); | ||
2250 | old_disk_conf = mdev->ldev->disk_conf; | ||
2251 | *new_disk_conf = *old_disk_conf; | ||
2252 | new_disk_conf->disk_size = (sector_t)rs.resize_size; | ||
2253 | rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf); | ||
2254 | mutex_unlock(&mdev->tconn->conf_update); | ||
2255 | synchronize_rcu(); | ||
2256 | kfree(old_disk_conf); | ||
2257 | } | ||
2258 | |||
2211 | ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0); | 2259 | ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0); |
2212 | dd = drbd_determine_dev_size(mdev, ddsf); | 2260 | dd = drbd_determine_dev_size(mdev, ddsf); |
2213 | drbd_md_sync(mdev); | 2261 | drbd_md_sync(mdev); |
@@ -2501,11 +2549,11 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev, | |||
2501 | if (res_opts_to_skb(skb, &mdev->tconn->res_opts, exclude_sensitive)) | 2549 | if (res_opts_to_skb(skb, &mdev->tconn->res_opts, exclude_sensitive)) |
2502 | goto nla_put_failure; | 2550 | goto nla_put_failure; |
2503 | 2551 | ||
2552 | rcu_read_lock(); | ||
2504 | if (got_ldev) | 2553 | if (got_ldev) |
2505 | if (disk_conf_to_skb(skb, &mdev->ldev->dc, exclude_sensitive)) | 2554 | if (disk_conf_to_skb(skb, rcu_dereference(mdev->ldev->disk_conf), exclude_sensitive)) |
2506 | goto nla_put_failure; | 2555 | goto nla_put_failure; |
2507 | 2556 | ||
2508 | rcu_read_lock(); | ||
2509 | nc = rcu_dereference(mdev->tconn->net_conf); | 2557 | nc = rcu_dereference(mdev->tconn->net_conf); |
2510 | if (nc) | 2558 | if (nc) |
2511 | err = net_conf_to_skb(skb, nc, exclude_sensitive); | 2559 | err = net_conf_to_skb(skb, nc, exclude_sensitive); |