From: Lars Ellenberg Date: Tue, 8 Mar 2011 15:11:16 +0000 (+0100) Subject: drbd: allow holes in minor and volume id allocation X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=8432b31457bee1f32cd2ede82e4a68b1af1d5225;p=deliverable%2Flinux.git drbd: allow holes in minor and volume id allocation s/idr_get_new/idr_get_new_above/ Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 429fd8da6b71..ea638ce48e8b 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1509,6 +1509,7 @@ extern int is_valid_ar_handle(struct drbd_request *, sector_t); /* drbd_nl.c */ +extern int drbd_msg_put_info(const char *info); extern void drbd_suspend_io(struct drbd_conf *mdev); extern void drbd_resume_io(struct drbd_conf *mdev); extern char *ppsize(char *buf, unsigned long long size); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9697ab872098..24c712b91fb1 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2322,6 +2322,7 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, struct request_queue *q; int vnr_got = vnr; int minor_got = minor; + enum drbd_ret_code err = ERR_NOMEM; mdev = minor_to_mdev(minor); if (mdev) @@ -2389,35 +2390,35 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, INIT_LIST_HEAD(&mdev->current_epoch->list); mdev->epochs = 1; - if (!idr_pre_get(&tconn->volumes, GFP_KERNEL)) - goto out_no_vol_idr; - if (idr_get_new(&tconn->volumes, mdev, &vnr_got)) - goto out_no_vol_idr; - if (vnr_got != vnr) { - dev_err(DEV, "vnr_got (%d) != vnr (%d)\n", vnr_got, vnr); - goto out_idr_remove_vol; - } - if (!idr_pre_get(&minors, GFP_KERNEL)) - goto out_idr_remove_vol; - if (idr_get_new(&minors, mdev, &minor_got)) - goto out_idr_remove_vol; + goto out_no_minor_idr; + if (idr_get_new_above(&minors, mdev, minor, &minor_got)) + goto out_no_minor_idr; if (minor_got != minor) { - /* minor exists, or other idr strangeness? */ - dev_err(DEV, "available minor (%d) != requested minor (%d)\n", - minor_got, minor); + err = ERR_MINOR_EXISTS; + drbd_msg_put_info("requested minor exists already"); goto out_idr_remove_minor; } + + if (!idr_pre_get(&tconn->volumes, GFP_KERNEL)) + goto out_idr_remove_minor; + if (idr_get_new_above(&tconn->volumes, mdev, vnr, &vnr_got)) + goto out_idr_remove_minor; + if (vnr_got != vnr) { + err = ERR_INVALID_REQUEST; + drbd_msg_put_info("requested volume exists already"); + goto out_idr_remove_vol; + } add_disk(disk); return NO_ERROR; -out_idr_remove_minor: - idr_remove(&minors, minor_got); out_idr_remove_vol: idr_remove(&tconn->volumes, vnr_got); +out_idr_remove_minor: + idr_remove(&minors, minor_got); synchronize_rcu(); -out_no_vol_idr: +out_no_minor_idr: kfree(mdev->current_epoch); out_no_epoch: drbd_bm_cleanup(mdev); @@ -2429,7 +2430,7 @@ out_no_disk: blk_cleanup_queue(q); out_no_q: kfree(mdev); - return ERR_NOMEM; + return err; } /* counterpart of drbd_new_device. diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index f9be14248e33..f54d512ffce5 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -109,7 +109,7 @@ static void drbd_adm_send_reply(struct sk_buff *skb, struct genl_info *info) /* Used on a fresh "drbd_adm_prepare"d reply_skb, this cannot fail: The only * reason it could fail was no space in skb, and there are 4k available. */ -static int drbd_msg_put_info(const char *info) +int drbd_msg_put_info(const char *info) { struct sk_buff *skb = adm_ctx.reply_skb; struct nlattr *nla;