aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
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),