Commit 4ef2a4f4 authored by Lars Ellenberg's avatar Lars Ellenberg Committed by Jens Axboe
Browse files

drbd: fix confusing error message during attach



If we attach a (consistent) backing device,
which knows about a last-agreed effective size,
and that effective size is *larger* than the currently requested size,
we refused to attach with ERR_DISK_TOO_SMALL
  Failure: (111) Low.dev. smaller than requested DRBD-dev. size.
which is confusing to say the least.

This patch changes the error code in that case to ERR_IMPLICIT_SHRINK
  Failure: (170) Implicit device shrinking not allowed. See kernel log.
  additional info from kernel:
  To-be-attached device has last effective > current size, and is consistent
  (9999 > 7777 sectors). Refusing to attach.

It also allows to attach with an explicit size.

Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent b17b5960
Loading
Loading
Loading
Loading
+44 −5
Original line number Diff line number Diff line
@@ -127,6 +127,35 @@ static int drbd_msg_put_info(struct sk_buff *skb, const char *info)
	return 0;
}

__printf(2, 3)
static int drbd_msg_sprintf_info(struct sk_buff *skb, const char *fmt, ...)
{
	va_list args;
	struct nlattr *nla, *txt;
	int err = -EMSGSIZE;
	int len;

	nla = nla_nest_start(skb, DRBD_NLA_CFG_REPLY);
	if (!nla)
		return err;

	txt = nla_reserve(skb, T_info_text, 256);
	if (!txt) {
		nla_nest_cancel(skb, nla);
		return err;
	}
	va_start(args, fmt);
	len = vscnprintf(nla_data(txt), 256, fmt, args);
	va_end(args);

	/* maybe: retry with larger reserve, if truncated */
	txt->nla_len = nla_attr_size(len+1);
	nlmsg_trim(skb, (char*)txt + NLA_ALIGN(txt->nla_len));
	nla_nest_end(skb, nla);

	return 0;
}

/* This would be a good candidate for a "pre_doit" hook,
 * and per-family private info->pointers.
 * But we need to stay compatible with older kernels.
@@ -1947,12 +1976,22 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
	}

	/* Prevent shrinking of consistent devices ! */
	if (drbd_md_test_flag(nbc, MDF_CONSISTENT) &&
	    drbd_new_dev_size(device, nbc, nbc->disk_conf->disk_size, 0) < nbc->md.la_size_sect) {
		drbd_warn(device, "refusing to truncate a consistent device\n");
		retcode = ERR_DISK_TOO_SMALL;
	{
	unsigned long long nsz = drbd_new_dev_size(device, nbc, nbc->disk_conf->disk_size, 0);
	unsigned long long eff = nbc->md.la_size_sect;
	if (drbd_md_test_flag(nbc, MDF_CONSISTENT) && nsz < eff) {
		if (nsz == nbc->disk_conf->disk_size) {
			drbd_warn(device, "truncating a consistent device during attach (%llu < %llu)\n", nsz, eff);
		} else {
			drbd_warn(device, "refusing to truncate a consistent device (%llu < %llu)\n", nsz, eff);
			drbd_msg_sprintf_info(adm_ctx.reply_skb,
				"To-be-attached device has last effective > current size, and is consistent\n"
				"(%llu > %llu sectors). Refusing to attach.", eff, nsz);
			retcode = ERR_IMPLICIT_SHRINK;
			goto force_diskless_dec;
		}
	}
	}

	lock_all_resources();
	retcode = drbd_resync_after_valid(device, new_disk_conf->resync_after);