aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_nl.c
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-02-22 02:07:03 -0500
committerPhilipp Reisner <philipp.reisner@linbit.com>2011-10-14 10:48:00 -0400
commit774b305518a68a50df4f479bcf79da2add724e6e (patch)
tree19b0322feebe2aed18cee0eb7ffa3f5e0ad3addc /drivers/block/drbd/drbd_nl.c
parent80883197da071239ed9e76bd3b9d8c9c5e19e4e6 (diff)
drbd: Implemented new commands to create/delete connections/minors
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r--drivers/block/drbd/drbd_nl.c106
1 files changed, 65 insertions, 41 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 455a51dd364d..f2739fd188a0 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -443,40 +443,6 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
443 return rv; 443 return rv;
444} 444}
445 445
446static struct drbd_conf *ensure_mdev(int minor, int create)
447{
448 struct drbd_conf *mdev;
449
450 if (minor >= minor_count)
451 return NULL;
452
453 mdev = minor_to_mdev(minor);
454
455 if (!mdev && create) {
456 struct gendisk *disk = NULL;
457 mdev = drbd_new_device(minor);
458
459 spin_lock_irq(&drbd_pp_lock);
460 if (minor_table[minor] == NULL) {
461 minor_table[minor] = mdev;
462 disk = mdev->vdisk;
463 mdev = NULL;
464 } /* else: we lost the race */
465 spin_unlock_irq(&drbd_pp_lock);
466
467 if (disk) /* we won the race above */
468 /* in case we ever add a drbd_delete_device(),
469 * don't forget the del_gendisk! */
470 add_disk(disk);
471 else /* we lost the race above */
472 drbd_free_mdev(mdev);
473
474 mdev = minor_to_mdev(minor);
475 }
476
477 return mdev;
478}
479
480static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, 446static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
481 struct drbd_nl_cfg_reply *reply) 447 struct drbd_nl_cfg_reply *reply)
482{ 448{
@@ -1789,12 +1755,6 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
1789 if (!expect(sc.al_extents <= DRBD_AL_EXTENTS_MAX)) 1755 if (!expect(sc.al_extents <= DRBD_AL_EXTENTS_MAX))
1790 sc.al_extents = DRBD_AL_EXTENTS_MAX; 1756 sc.al_extents = DRBD_AL_EXTENTS_MAX;
1791 1757
1792 /* to avoid spurious errors when configuring minors before configuring
1793 * the minors they depend on: if necessary, first create the minor we
1794 * depend on */
1795 if (sc.after >= 0)
1796 ensure_mdev(sc.after, 1);
1797
1798 /* most sanity checks done, try to assign the new sync-after 1758 /* most sanity checks done, try to assign the new sync-after
1799 * dependency. need to hold the global lock in there, 1759 * dependency. need to hold the global lock in there,
1800 * to avoid a race in the dependency loop check. */ 1760 * to avoid a race in the dependency loop check. */
@@ -2184,13 +2144,73 @@ out:
2184 return 0; 2144 return 0;
2185} 2145}
2186 2146
2147static int drbd_nl_new_conn(struct drbd_nl_cfg_req *nlp, struct drbd_nl_cfg_reply *reply)
2148{
2149 struct new_connection args;
2150
2151 if (!new_connection_from_tags(nlp->tag_list, &args)) {
2152 reply->ret_code = ERR_MANDATORY_TAG;
2153 return 0;
2154 }
2155
2156 reply->ret_code = NO_ERROR;
2157 if (!drbd_new_tconn(args.name))
2158 reply->ret_code = ERR_NOMEM;
2159
2160 return 0;
2161}
2162
2163static int drbd_nl_new_minor(struct drbd_tconn *tconn,
2164 struct drbd_nl_cfg_req *nlp, struct drbd_nl_cfg_reply *reply)
2165{
2166 struct new_minor args;
2167
2168 args.vol_nr = 0;
2169 args.minor = 0;
2170
2171 if (!new_minor_from_tags(nlp->tag_list, &args)) {
2172 reply->ret_code = ERR_MANDATORY_TAG;
2173 return 0;
2174 }
2175
2176 reply->ret_code = conn_new_minor(tconn, args.minor, args.vol_nr);
2177
2178 return 0;
2179}
2180
2181static int drbd_nl_del_minor(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
2182 struct drbd_nl_cfg_reply *reply)
2183{
2184 if (mdev->state.disk == D_DISKLESS &&
2185 mdev->state.conn == C_STANDALONE &&
2186 mdev->state.role == R_SECONDARY) {
2187 drbd_delete_device(mdev_to_minor(mdev));
2188 reply->ret_code = NO_ERROR;
2189 } else {
2190 reply->ret_code = ERR_MINOR_CONFIGURED;
2191 }
2192 return 0;
2193}
2194
2195static int drbd_nl_del_conn(struct drbd_tconn *tconn,
2196 struct drbd_nl_cfg_req *nlp, struct drbd_nl_cfg_reply *reply)
2197{
2198 if (conn_lowest_minor(tconn) < 0) {
2199 drbd_free_tconn(tconn);
2200 reply->ret_code = NO_ERROR;
2201 } else {
2202 reply->ret_code = ERR_CONN_IN_USE;
2203 }
2204
2205 return 0;
2206}
2207
2187enum cn_handler_type { 2208enum cn_handler_type {
2188 CHT_MINOR, 2209 CHT_MINOR,
2189 CHT_CONN, 2210 CHT_CONN,
2190 CHT_CTOR, 2211 CHT_CTOR,
2191 /* CHT_RES, later */ 2212 /* CHT_RES, later */
2192}; 2213};
2193
2194struct cn_handler_struct { 2214struct cn_handler_struct {
2195 enum cn_handler_type type; 2215 enum cn_handler_type type;
2196 union { 2216 union {
@@ -2235,6 +2255,10 @@ static struct cn_handler_struct cnd_table[] = {
2235 sizeof(struct get_timeout_flag_tag_len_struct)}, 2255 sizeof(struct get_timeout_flag_tag_len_struct)},
2236 [ P_start_ov ] = { CHT_MINOR, { &drbd_nl_start_ov }, 0 }, 2256 [ P_start_ov ] = { CHT_MINOR, { &drbd_nl_start_ov }, 0 },
2237 [ P_new_c_uuid ] = { CHT_MINOR, { &drbd_nl_new_c_uuid }, 0 }, 2257 [ P_new_c_uuid ] = { CHT_MINOR, { &drbd_nl_new_c_uuid }, 0 },
2258 [ P_new_connection ] = { CHT_CTOR, { .constructor = &drbd_nl_new_conn }, 0 },
2259 [ P_new_minor ] = { CHT_CONN, { .conn_based = &drbd_nl_new_minor }, 0 },
2260 [ P_del_minor ] = { CHT_MINOR, { &drbd_nl_del_minor }, 0 },
2261 [ P_del_connection ] = { CHT_CONN, { .conn_based = &drbd_nl_del_conn }, 0 },
2238}; 2262};
2239 2263
2240static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms *nsp) 2264static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms *nsp)