aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2010-09-01 08:39:30 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-10-14 12:38:28 -0400
commitef50a3e34f93a067ada541346be3175e924331a2 (patch)
tree455fd4a7d4b11ead24b7e297f25b02afabc36c76 /drivers/block
parent3f3a9b849d2b703934c07fa17f5eac2dc37c1f6b (diff)
drbd: implicitly create unconfigured devices on sync-after dependencies
If pacemaker (for example) decided to initialize minor devices not in the exact sync-after dependency order, the configuration partially failed with an error "The sync-after minor number is invalid". (Bugz. #322) We can avoid that by implicitly creating unconfigured minor devices, if others depend on them. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_nl.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index d066190f997a..e0061a906ba8 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -413,6 +413,39 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
413 return r; 413 return r;
414} 414}
415 415
416static struct drbd_conf *ensure_mdev(int minor, int create)
417{
418 struct drbd_conf *mdev;
419
420 if (minor >= minor_count)
421 return NULL;
422
423 mdev = minor_to_mdev(minor);
424
425 if (!mdev && create) {
426 struct gendisk *disk = NULL;
427 mdev = drbd_new_device(minor);
428
429 spin_lock_irq(&drbd_pp_lock);
430 if (minor_table[minor] == NULL) {
431 minor_table[minor] = mdev;
432 disk = mdev->vdisk;
433 mdev = NULL;
434 } /* else: we lost the race */
435 spin_unlock_irq(&drbd_pp_lock);
436
437 if (disk) /* we won the race above */
438 /* in case we ever add a drbd_delete_device(),
439 * don't forget the del_gendisk! */
440 add_disk(disk);
441 else /* we lost the race above */
442 drbd_free_mdev(mdev);
443
444 mdev = minor_to_mdev(minor);
445 }
446
447 return mdev;
448}
416 449
417static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, 450static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
418 struct drbd_nl_cfg_reply *reply) 451 struct drbd_nl_cfg_reply *reply)
@@ -1713,6 +1746,12 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
1713 } 1746 }
1714#undef AL_MAX 1747#undef AL_MAX
1715 1748
1749 /* to avoid spurious errors when configuring minors before configuring
1750 * the minors they depend on: if necessary, first create the minor we
1751 * depend on */
1752 if (sc.after >= 0)
1753 ensure_mdev(sc.after, 1);
1754
1716 /* most sanity checks done, try to assign the new sync-after 1755 /* most sanity checks done, try to assign the new sync-after
1717 * dependency. need to hold the global lock in there, 1756 * dependency. need to hold the global lock in there,
1718 * to avoid a race in the dependency loop check. */ 1757 * to avoid a race in the dependency loop check. */
@@ -2080,40 +2119,6 @@ out:
2080 return 0; 2119 return 0;
2081} 2120}
2082 2121
2083static struct drbd_conf *ensure_mdev(struct drbd_nl_cfg_req *nlp)
2084{
2085 struct drbd_conf *mdev;
2086
2087 if (nlp->drbd_minor >= minor_count)
2088 return NULL;
2089
2090 mdev = minor_to_mdev(nlp->drbd_minor);
2091
2092 if (!mdev && (nlp->flags & DRBD_NL_CREATE_DEVICE)) {
2093 struct gendisk *disk = NULL;
2094 mdev = drbd_new_device(nlp->drbd_minor);
2095
2096 spin_lock_irq(&drbd_pp_lock);
2097 if (minor_table[nlp->drbd_minor] == NULL) {
2098 minor_table[nlp->drbd_minor] = mdev;
2099 disk = mdev->vdisk;
2100 mdev = NULL;
2101 } /* else: we lost the race */
2102 spin_unlock_irq(&drbd_pp_lock);
2103
2104 if (disk) /* we won the race above */
2105 /* in case we ever add a drbd_delete_device(),
2106 * don't forget the del_gendisk! */
2107 add_disk(disk);
2108 else /* we lost the race above */
2109 drbd_free_mdev(mdev);
2110
2111 mdev = minor_to_mdev(nlp->drbd_minor);
2112 }
2113
2114 return mdev;
2115}
2116
2117struct cn_handler_struct { 2122struct cn_handler_struct {
2118 int (*function)(struct drbd_conf *, 2123 int (*function)(struct drbd_conf *,
2119 struct drbd_nl_cfg_req *, 2124 struct drbd_nl_cfg_req *,
@@ -2174,7 +2179,8 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms
2174 goto fail; 2179 goto fail;
2175 } 2180 }
2176 2181
2177 mdev = ensure_mdev(nlp); 2182 mdev = ensure_mdev(nlp->drbd_minor,
2183 (nlp->flags & DRBD_NL_CREATE_DEVICE));
2178 if (!mdev) { 2184 if (!mdev) {
2179 retcode = ERR_MINOR_INVALID; 2185 retcode = ERR_MINOR_INVALID;
2180 goto fail; 2186 goto fail;