aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2013-03-19 13:16:59 -0400
committerJens Axboe <axboe@kernel.dk>2013-03-23 00:18:09 -0400
commit5bbcf5e6abe97485748b51ea0713cc3012b4a8f0 (patch)
tree577851f75cfe5de3138c8c1c387883cf47f24005 /drivers/block/drbd
parent45ad07b3ac1e3062188fb760fe71cafb4a100215 (diff)
drbd: adjust upper limit for activity log extents
Now that the on-disk activity-log ring buffer size is adjustable, the maximum active set can become larger, and is now limited by the use of 16bit "labels". This increases the maximum working set from 6433 to 65534 extents, each of which covers an area of 4MiB. Which means that if you use the maximum, you'd have to resync more than 250 GiB after an unclean Primary shutdown. With capable backend storage and replication links, this is entirely feasible. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_nl.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index bcf900bcd142..42fda4ae2f87 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1141,15 +1141,32 @@ static bool should_set_defaults(struct genl_info *info)
1141 return 0 != (flags & DRBD_GENL_F_SET_DEFAULTS); 1141 return 0 != (flags & DRBD_GENL_F_SET_DEFAULTS);
1142} 1142}
1143 1143
1144static void enforce_disk_conf_limits(struct disk_conf *dc) 1144static unsigned int drbd_al_extents_max(struct drbd_backing_dev *bdev)
1145{ 1145{
1146 if (dc->al_extents < DRBD_AL_EXTENTS_MIN) 1146 /* This is limited by 16 bit "slot" numbers,
1147 dc->al_extents = DRBD_AL_EXTENTS_MIN; 1147 * and by available on-disk context storage.
1148 if (dc->al_extents > DRBD_AL_EXTENTS_MAX) 1148 *
1149 dc->al_extents = DRBD_AL_EXTENTS_MAX; 1149 * Also (u16)~0 is special (denotes a "free" extent).
1150 *
1151 * One transaction occupies one 4kB on-disk block,
1152 * we have n such blocks in the on disk ring buffer,
1153 * the "current" transaction may fail (n-1),
1154 * and there is 919 slot numbers context information per transaction.
1155 *
1156 * 72 transaction blocks amounts to more than 2**16 context slots,
1157 * so cap there first.
1158 */
1159 const unsigned int max_al_nr = DRBD_AL_EXTENTS_MAX;
1160 const unsigned int sufficient_on_disk =
1161 (max_al_nr + AL_CONTEXT_PER_TRANSACTION -1)
1162 /AL_CONTEXT_PER_TRANSACTION;
1150 1163
1151 if (dc->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX) 1164 unsigned int al_size_4k = bdev->md.al_size_4k;
1152 dc->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX; 1165
1166 if (al_size_4k > sufficient_on_disk)
1167 return max_al_nr;
1168
1169 return (al_size_4k - 1) * AL_CONTEXT_PER_TRANSACTION;
1153} 1170}
1154 1171
1155int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) 1172int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
@@ -1196,7 +1213,13 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
1196 if (!expect(new_disk_conf->resync_rate >= 1)) 1213 if (!expect(new_disk_conf->resync_rate >= 1))
1197 new_disk_conf->resync_rate = 1; 1214 new_disk_conf->resync_rate = 1;
1198 1215
1199 enforce_disk_conf_limits(new_disk_conf); 1216 if (new_disk_conf->al_extents < DRBD_AL_EXTENTS_MIN)
1217 new_disk_conf->al_extents = DRBD_AL_EXTENTS_MIN;
1218 if (new_disk_conf->al_extents > drbd_al_extents_max(mdev->ldev))
1219 new_disk_conf->al_extents = drbd_al_extents_max(mdev->ldev);
1220
1221 if (new_disk_conf->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX)
1222 new_disk_conf->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX;
1200 1223
1201 fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ; 1224 fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
1202 if (fifo_size != mdev->rs_plan_s->size) { 1225 if (fifo_size != mdev->rs_plan_s->size) {
@@ -1344,7 +1367,8 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
1344 goto fail; 1367 goto fail;
1345 } 1368 }
1346 1369
1347 enforce_disk_conf_limits(new_disk_conf); 1370 if (new_disk_conf->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX)
1371 new_disk_conf->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX;
1348 1372
1349 new_plan = fifo_alloc((new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ); 1373 new_plan = fifo_alloc((new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ);
1350 if (!new_plan) { 1374 if (!new_plan) {
@@ -1419,6 +1443,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
1419 if (retcode != NO_ERROR) 1443 if (retcode != NO_ERROR)
1420 goto fail; 1444 goto fail;
1421 1445
1446 if (new_disk_conf->al_extents < DRBD_AL_EXTENTS_MIN)
1447 new_disk_conf->al_extents = DRBD_AL_EXTENTS_MIN;
1448 if (new_disk_conf->al_extents > drbd_al_extents_max(nbc))
1449 new_disk_conf->al_extents = drbd_al_extents_max(nbc);
1450
1422 if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) { 1451 if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) {
1423 dev_err(DEV, "max capacity %llu smaller than disk size %llu\n", 1452 dev_err(DEV, "max capacity %llu smaller than disk size %llu\n",
1424 (unsigned long long) drbd_get_max_capacity(nbc), 1453 (unsigned long long) drbd_get_max_capacity(nbc),