diff options
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 47 |
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 | ||
1144 | static void enforce_disk_conf_limits(struct disk_conf *dc) | 1144 | static 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 | ||
1155 | int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | 1172 | int 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), |