diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-02-22 02:07:03 -0500 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2011-10-14 10:48:00 -0400 |
commit | 774b305518a68a50df4f479bcf79da2add724e6e (patch) | |
tree | 19b0322feebe2aed18cee0eb7ffa3f5e0ad3addc /drivers/block/drbd/drbd_nl.c | |
parent | 80883197da071239ed9e76bd3b9d8c9c5e19e4e6 (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.c | 106 |
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 | ||
446 | static 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 | |||
480 | static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | 446 | static 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 | ||
2147 | static 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 | |||
2163 | static 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 | |||
2181 | static 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 | |||
2195 | static 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 | |||
2187 | enum cn_handler_type { | 2208 | enum 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 | |||
2194 | struct cn_handler_struct { | 2214 | struct 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 | ||
2240 | static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms *nsp) | 2264 | static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms *nsp) |