aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/drbd/drbd_int.h45
-rw-r--r--drivers/block/drbd/drbd_main.c96
-rw-r--r--drivers/block/drbd/drbd_nl.c116
3 files changed, 179 insertions, 78 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index b324314768fd..b51ecdbdd30c 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -105,7 +105,7 @@ struct drbd_connection;
105#define DEV (disk_to_dev(device->vdisk)) 105#define DEV (disk_to_dev(device->vdisk))
106 106
107#define conn_printk(LEVEL, TCONN, FMT, ARGS...) \ 107#define conn_printk(LEVEL, TCONN, FMT, ARGS...) \
108 printk(LEVEL "d-con %s: " FMT, TCONN->name , ## ARGS) 108 printk(LEVEL "d-con %s: " FMT, TCONN->resource->name , ## ARGS)
109#define conn_alert(TCONN, FMT, ARGS...) conn_printk(KERN_ALERT, TCONN, FMT, ## ARGS) 109#define conn_alert(TCONN, FMT, ARGS...) conn_printk(KERN_ALERT, TCONN, FMT, ## ARGS)
110#define conn_crit(TCONN, FMT, ARGS...) conn_printk(KERN_CRIT, TCONN, FMT, ## ARGS) 110#define conn_crit(TCONN, FMT, ARGS...) conn_printk(KERN_CRIT, TCONN, FMT, ## ARGS)
111#define conn_err(TCONN, FMT, ARGS...) conn_printk(KERN_ERR, TCONN, FMT, ## ARGS) 111#define conn_err(TCONN, FMT, ARGS...) conn_printk(KERN_ERR, TCONN, FMT, ## ARGS)
@@ -167,7 +167,7 @@ drbd_insert_fault(struct drbd_device *device, unsigned int type) {
167 167
168extern struct ratelimit_state drbd_ratelimit_state; 168extern struct ratelimit_state drbd_ratelimit_state;
169extern struct idr drbd_devices; /* RCU, updates: genl_lock() */ 169extern struct idr drbd_devices; /* RCU, updates: genl_lock() */
170extern struct list_head drbd_connections; /* RCU, updates: genl_lock() */ 170extern struct list_head drbd_resources; /* RCU, updates: genl_lock() */
171 171
172extern const char *cmdname(enum drbd_packet cmd); 172extern const char *cmdname(enum drbd_packet cmd);
173 173
@@ -536,9 +536,16 @@ enum {
536 DISCONNECT_SENT, 536 DISCONNECT_SENT,
537}; 537};
538 538
539struct drbd_connection { /* is a resource from the config file */ 539struct drbd_resource {
540 char *name; /* Resource name */ 540 char *name;
541 struct list_head connections; /* linked on global drbd_connections */ 541 struct kref kref;
542 struct list_head connections;
543 struct list_head resources;
544};
545
546struct drbd_connection {
547 struct list_head connections;
548 struct drbd_resource *resource;
542 struct kref kref; 549 struct kref kref;
543 struct idr volumes; /* <connection, vnr> to device mapping */ 550 struct idr volumes; /* <connection, vnr> to device mapping */
544 enum drbd_conns cstate; /* Only C_STANDALONE to C_WF_REPORT_PARAMS */ 551 enum drbd_conns cstate; /* Only C_STANDALONE to C_WF_REPORT_PARAMS */
@@ -779,6 +786,24 @@ static inline struct drbd_peer_device *first_peer_device(struct drbd_device *dev
779 return list_first_entry(&device->peer_devices, struct drbd_peer_device, peer_devices); 786 return list_first_entry(&device->peer_devices, struct drbd_peer_device, peer_devices);
780} 787}
781 788
789#define for_each_resource(resource, _resources) \
790 list_for_each_entry(resource, _resources, resources)
791
792#define for_each_resource_rcu(resource, _resources) \
793 list_for_each_entry_rcu(resource, _resources, resources)
794
795#define for_each_resource_safe(resource, tmp, _resources) \
796 list_for_each_entry_safe(resource, tmp, _resources, resources)
797
798#define for_each_connection(connection, resource) \
799 list_for_each_entry(connection, &resource->connections, connections)
800
801#define for_each_connection_rcu(connection, resource) \
802 list_for_each_entry_rcu(connection, &resource->connections, connections)
803
804#define for_each_connection_safe(connection, tmp, resource) \
805 list_for_each_entry_safe(connection, tmp, &resource->connections, connections)
806
782#define for_each_peer_device(peer_device, device) \ 807#define for_each_peer_device(peer_device, device) \
783 list_for_each_entry(peer_device, &device->peer_devices, peer_devices) 808 list_for_each_entry(peer_device, &device->peer_devices, peer_devices)
784 809
@@ -1177,12 +1202,16 @@ extern int conn_lowest_minor(struct drbd_connection *connection);
1177enum drbd_ret_code drbd_create_minor(struct drbd_connection *connection, unsigned int minor, int vnr); 1202enum drbd_ret_code drbd_create_minor(struct drbd_connection *connection, unsigned int minor, int vnr);
1178extern void drbd_destroy_device(struct kref *kref); 1203extern void drbd_destroy_device(struct kref *kref);
1179 1204
1205extern struct drbd_resource *drbd_create_resource(const char *name);
1206extern void drbd_free_resource(struct drbd_resource *resource);
1207
1180extern int set_resource_options(struct drbd_connection *connection, struct res_opts *res_opts); 1208extern int set_resource_options(struct drbd_connection *connection, struct res_opts *res_opts);
1181extern struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts); 1209extern struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts);
1182extern void drbd_destroy_connection(struct kref *kref); 1210extern void drbd_destroy_connection(struct kref *kref);
1183struct drbd_connection *conn_get_by_name(const char *name); 1211struct drbd_connection *conn_get_by_name(const char *name);
1184extern struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len, 1212extern struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
1185 void *peer_addr, int peer_addr_len); 1213 void *peer_addr, int peer_addr_len);
1214extern void drbd_destroy_resource(struct kref *kref);
1186extern void conn_free_crypto(struct drbd_connection *connection); 1215extern void conn_free_crypto(struct drbd_connection *connection);
1187 1216
1188extern int proc_details; 1217extern int proc_details;
@@ -2082,4 +2111,10 @@ static inline void drbd_md_flush(struct drbd_device *device)
2082 } 2111 }
2083} 2112}
2084 2113
2114static inline struct drbd_connection *first_connection(struct drbd_resource *resource)
2115{
2116 return list_first_entry(&resource->connections,
2117 struct drbd_connection, connections);
2118}
2119
2085#endif 2120#endif
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 4da017d22f4b..f13d836e76a6 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -118,7 +118,7 @@ module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0
118 * as member "struct gendisk *vdisk;" 118 * as member "struct gendisk *vdisk;"
119 */ 119 */
120struct idr drbd_devices; 120struct idr drbd_devices;
121struct list_head drbd_connections; /* list of struct drbd_connection */ 121struct list_head drbd_resources;
122 122
123struct kmem_cache *drbd_request_cache; 123struct kmem_cache *drbd_request_cache;
124struct kmem_cache *drbd_ee_cache; /* peer requests */ 124struct kmem_cache *drbd_ee_cache; /* peer requests */
@@ -330,7 +330,8 @@ static int drbd_thread_setup(void *arg)
330 int retval; 330 int retval;
331 331
332 snprintf(current->comm, sizeof(current->comm), "drbd_%c_%s", 332 snprintf(current->comm, sizeof(current->comm), "drbd_%c_%s",
333 thi->name[0], thi->connection->name); 333 thi->name[0],
334 thi->connection->resource->name);
334 335
335restart: 336restart:
336 retval = thi->function(thi); 337 retval = thi->function(thi);
@@ -411,7 +412,7 @@ int drbd_thread_start(struct drbd_thread *thi)
411 flush_signals(current); /* otherw. may get -ERESTARTNOINTR */ 412 flush_signals(current); /* otherw. may get -ERESTARTNOINTR */
412 413
413 nt = kthread_create(drbd_thread_setup, (void *) thi, 414 nt = kthread_create(drbd_thread_setup, (void *) thi,
414 "drbd_%c_%s", thi->name[0], thi->connection->name); 415 "drbd_%c_%s", thi->name[0], thi->connection->resource->name);
415 416
416 if (IS_ERR(nt)) { 417 if (IS_ERR(nt)) {
417 conn_err(connection, "Couldn't start thread\n"); 418 conn_err(connection, "Couldn't start thread\n");
@@ -2276,12 +2277,31 @@ void drbd_restart_request(struct drbd_request *req)
2276 queue_work(retry.wq, &retry.worker); 2277 queue_work(retry.wq, &retry.worker);
2277} 2278}
2278 2279
2280void drbd_destroy_resource(struct kref *kref)
2281{
2282 struct drbd_resource *resource =
2283 container_of(kref, struct drbd_resource, kref);
2284
2285 kfree(resource->name);
2286 kfree(resource);
2287}
2288
2289void drbd_free_resource(struct drbd_resource *resource)
2290{
2291 struct drbd_connection *connection, *tmp;
2292
2293 for_each_connection_safe(connection, tmp, resource) {
2294 list_del(&connection->connections);
2295 kref_put(&connection->kref, drbd_destroy_connection);
2296 }
2297 kref_put(&resource->kref, drbd_destroy_resource);
2298}
2279 2299
2280static void drbd_cleanup(void) 2300static void drbd_cleanup(void)
2281{ 2301{
2282 unsigned int i; 2302 unsigned int i;
2283 struct drbd_device *device; 2303 struct drbd_device *device;
2284 struct drbd_connection *connection, *tmp; 2304 struct drbd_resource *resource, *tmp;
2285 2305
2286 unregister_reboot_notifier(&drbd_notifier); 2306 unregister_reboot_notifier(&drbd_notifier);
2287 2307
@@ -2311,10 +2331,9 @@ static void drbd_cleanup(void)
2311 } 2331 }
2312 2332
2313 /* not _rcu since, no other updater anymore. Genl already unregistered */ 2333 /* not _rcu since, no other updater anymore. Genl already unregistered */
2314 list_for_each_entry_safe(connection, tmp, &drbd_connections, connections) { 2334 for_each_resource_safe(resource, tmp, &drbd_resources) {
2315 list_del(&connection->connections); /* not _rcu no proc, not other threads */ 2335 list_del(&resource->resources);
2316 /* synchronize_rcu(); */ 2336 drbd_free_resource(resource);
2317 kref_put(&connection->kref, drbd_destroy_connection);
2318 } 2337 }
2319 2338
2320 drbd_destroy_mempools(); 2339 drbd_destroy_mempools();
@@ -2391,13 +2410,15 @@ static void drbd_init_workqueue(struct drbd_work_queue* wq)
2391struct drbd_connection *conn_get_by_name(const char *name) 2410struct drbd_connection *conn_get_by_name(const char *name)
2392{ 2411{
2393 struct drbd_connection *connection; 2412 struct drbd_connection *connection;
2413 struct drbd_resource *resource;
2394 2414
2395 if (!name || !name[0]) 2415 if (!name || !name[0])
2396 return NULL; 2416 return NULL;
2397 2417
2398 rcu_read_lock(); 2418 rcu_read_lock();
2399 list_for_each_entry_rcu(connection, &drbd_connections, connections) { 2419 for_each_resource_rcu(resource, &drbd_resources) {
2400 if (!strcmp(connection->name, name)) { 2420 if (!strcmp(resource->name, name)) {
2421 connection = first_connection(resource);
2401 kref_get(&connection->kref); 2422 kref_get(&connection->kref);
2402 goto found; 2423 goto found;
2403 } 2424 }
@@ -2411,16 +2432,19 @@ found:
2411struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len, 2432struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
2412 void *peer_addr, int peer_addr_len) 2433 void *peer_addr, int peer_addr_len)
2413{ 2434{
2435 struct drbd_resource *resource;
2414 struct drbd_connection *connection; 2436 struct drbd_connection *connection;
2415 2437
2416 rcu_read_lock(); 2438 rcu_read_lock();
2417 list_for_each_entry_rcu(connection, &drbd_connections, connections) { 2439 for_each_resource_rcu(resource, &drbd_resources) {
2418 if (connection->my_addr_len == my_addr_len && 2440 for_each_connection_rcu(connection, resource) {
2419 connection->peer_addr_len == peer_addr_len && 2441 if (connection->my_addr_len == my_addr_len &&
2420 !memcmp(&connection->my_addr, my_addr, my_addr_len) && 2442 connection->peer_addr_len == peer_addr_len &&
2421 !memcmp(&connection->peer_addr, peer_addr, peer_addr_len)) { 2443 !memcmp(&connection->my_addr, my_addr, my_addr_len) &&
2422 kref_get(&connection->kref); 2444 !memcmp(&connection->peer_addr, peer_addr, peer_addr_len)) {
2423 goto found; 2445 kref_get(&connection->kref);
2446 goto found;
2447 }
2424 } 2448 }
2425 } 2449 }
2426 connection = NULL; 2450 connection = NULL;
@@ -2506,19 +2530,34 @@ fail:
2506 2530
2507} 2531}
2508 2532
2533struct drbd_resource *drbd_create_resource(const char *name)
2534{
2535 struct drbd_resource *resource;
2536
2537 resource = kmalloc(sizeof(struct drbd_resource), GFP_KERNEL);
2538 if (!resource)
2539 return NULL;
2540 resource->name = kstrdup(name, GFP_KERNEL);
2541 if (!resource->name) {
2542 kfree(resource);
2543 return NULL;
2544 }
2545 kref_init(&resource->kref);
2546 INIT_LIST_HEAD(&resource->connections);
2547 list_add_tail_rcu(&resource->resources, &drbd_resources);
2548 return resource;
2549}
2550
2509/* caller must be under genl_lock() */ 2551/* caller must be under genl_lock() */
2510struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts) 2552struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
2511{ 2553{
2554 struct drbd_resource *resource;
2512 struct drbd_connection *connection; 2555 struct drbd_connection *connection;
2513 2556
2514 connection = kzalloc(sizeof(struct drbd_connection), GFP_KERNEL); 2557 connection = kzalloc(sizeof(struct drbd_connection), GFP_KERNEL);
2515 if (!connection) 2558 if (!connection)
2516 return NULL; 2559 return NULL;
2517 2560
2518 connection->name = kstrdup(name, GFP_KERNEL);
2519 if (!connection->name)
2520 goto fail;
2521
2522 if (drbd_alloc_socket(&connection->data)) 2561 if (drbd_alloc_socket(&connection->data))
2523 goto fail; 2562 goto fail;
2524 if (drbd_alloc_socket(&connection->meta)) 2563 if (drbd_alloc_socket(&connection->meta))
@@ -2545,6 +2584,10 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
2545 connection->send.current_epoch_nr = 0; 2584 connection->send.current_epoch_nr = 0;
2546 connection->send.current_epoch_writes = 0; 2585 connection->send.current_epoch_writes = 0;
2547 2586
2587 resource = drbd_create_resource(name);
2588 if (!resource)
2589 goto fail;
2590
2548 connection->cstate = C_STANDALONE; 2591 connection->cstate = C_STANDALONE;
2549 mutex_init(&connection->cstate_mutex); 2592 mutex_init(&connection->cstate_mutex);
2550 spin_lock_init(&connection->req_lock); 2593 spin_lock_init(&connection->req_lock);
@@ -2561,7 +2604,10 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
2561 drbd_thread_init(connection, &connection->asender, drbd_asender, "asender"); 2604 drbd_thread_init(connection, &connection->asender, drbd_asender, "asender");
2562 2605
2563 kref_init(&connection->kref); 2606 kref_init(&connection->kref);
2564 list_add_tail_rcu(&connection->connections, &drbd_connections); 2607
2608 kref_get(&resource->kref);
2609 connection->resource = resource;
2610 list_add_tail_rcu(&connection->connections, &resource->connections);
2565 2611
2566 return connection; 2612 return connection;
2567 2613
@@ -2570,7 +2616,6 @@ fail:
2570 free_cpumask_var(connection->cpu_mask); 2616 free_cpumask_var(connection->cpu_mask);
2571 drbd_free_socket(&connection->meta); 2617 drbd_free_socket(&connection->meta);
2572 drbd_free_socket(&connection->data); 2618 drbd_free_socket(&connection->data);
2573 kfree(connection->name);
2574 kfree(connection); 2619 kfree(connection);
2575 2620
2576 return NULL; 2621 return NULL;
@@ -2579,6 +2624,7 @@ fail:
2579void drbd_destroy_connection(struct kref *kref) 2624void drbd_destroy_connection(struct kref *kref)
2580{ 2625{
2581 struct drbd_connection *connection = container_of(kref, struct drbd_connection, kref); 2626 struct drbd_connection *connection = container_of(kref, struct drbd_connection, kref);
2627 struct drbd_resource *resource = connection->resource;
2582 2628
2583 if (atomic_read(&connection->current_epoch->epoch_size) != 0) 2629 if (atomic_read(&connection->current_epoch->epoch_size) != 0)
2584 conn_err(connection, "epoch_size:%d\n", atomic_read(&connection->current_epoch->epoch_size)); 2630 conn_err(connection, "epoch_size:%d\n", atomic_read(&connection->current_epoch->epoch_size));
@@ -2589,10 +2635,10 @@ void drbd_destroy_connection(struct kref *kref)
2589 free_cpumask_var(connection->cpu_mask); 2635 free_cpumask_var(connection->cpu_mask);
2590 drbd_free_socket(&connection->meta); 2636 drbd_free_socket(&connection->meta);
2591 drbd_free_socket(&connection->data); 2637 drbd_free_socket(&connection->data);
2592 kfree(connection->name);
2593 kfree(connection->int_dig_in); 2638 kfree(connection->int_dig_in);
2594 kfree(connection->int_dig_vv); 2639 kfree(connection->int_dig_vv);
2595 kfree(connection); 2640 kfree(connection);
2641 kref_put(&resource->kref, drbd_destroy_resource);
2596} 2642}
2597 2643
2598static int init_submitter(struct drbd_device *device) 2644static int init_submitter(struct drbd_device *device)
@@ -2775,7 +2821,7 @@ int __init drbd_init(void)
2775 idr_init(&drbd_devices); 2821 idr_init(&drbd_devices);
2776 2822
2777 rwlock_init(&global_state_lock); 2823 rwlock_init(&global_state_lock);
2778 INIT_LIST_HEAD(&drbd_connections); 2824 INIT_LIST_HEAD(&drbd_resources);
2779 2825
2780 err = drbd_genl_register(); 2826 err = drbd_genl_register();
2781 if (err) { 2827 if (err) {
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 83d8c18fb84c..b8eacccbdc5c 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -249,7 +249,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
249 first_peer_device(adm_ctx.device)->connection != adm_ctx.connection) { 249 first_peer_device(adm_ctx.device)->connection != adm_ctx.connection) {
250 pr_warning("request: minor=%u, resource=%s; but that minor belongs to connection %s\n", 250 pr_warning("request: minor=%u, resource=%s; but that minor belongs to connection %s\n",
251 adm_ctx.minor, adm_ctx.resource_name, 251 adm_ctx.minor, adm_ctx.resource_name,
252 first_peer_device(adm_ctx.device)->connection->name); 252 first_peer_device(adm_ctx.device)->connection->resource->name);
253 drbd_msg_put_info("minor exists in different resource"); 253 drbd_msg_put_info("minor exists in different resource");
254 return ERR_INVALID_REQUEST; 254 return ERR_INVALID_REQUEST;
255 } 255 }
@@ -258,7 +258,8 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
258 adm_ctx.volume != adm_ctx.device->vnr) { 258 adm_ctx.volume != adm_ctx.device->vnr) {
259 pr_warning("request: minor=%u, volume=%u; but that minor is volume %u in %s\n", 259 pr_warning("request: minor=%u, volume=%u; but that minor is volume %u in %s\n",
260 adm_ctx.minor, adm_ctx.volume, 260 adm_ctx.minor, adm_ctx.volume,
261 adm_ctx.device->vnr, first_peer_device(adm_ctx.device)->connection->name); 261 adm_ctx.device->vnr,
262 first_peer_device(adm_ctx.device)->connection->resource->name);
262 drbd_msg_put_info("minor exists as different volume"); 263 drbd_msg_put_info("minor exists as different volume");
263 return ERR_INVALID_REQUEST; 264 return ERR_INVALID_REQUEST;
264 } 265 }
@@ -371,23 +372,24 @@ static int conn_khelper(struct drbd_connection *connection, char *cmd)
371 (char[20]) { }, /* address family */ 372 (char[20]) { }, /* address family */
372 (char[60]) { }, /* address */ 373 (char[60]) { }, /* address */
373 NULL }; 374 NULL };
374 char *argv[] = {usermode_helper, cmd, connection->name, NULL }; 375 char *resource_name = connection->resource->name;
376 char *argv[] = {usermode_helper, cmd, resource_name, NULL };
375 int ret; 377 int ret;
376 378
377 setup_khelper_env(connection, envp); 379 setup_khelper_env(connection, envp);
378 conn_md_sync(connection); 380 conn_md_sync(connection);
379 381
380 conn_info(connection, "helper command: %s %s %s\n", usermode_helper, cmd, connection->name); 382 conn_info(connection, "helper command: %s %s %s\n", usermode_helper, cmd, resource_name);
381 /* TODO: conn_bcast_event() ?? */ 383 /* TODO: conn_bcast_event() ?? */
382 384
383 ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC); 385 ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC);
384 if (ret) 386 if (ret)
385 conn_warn(connection, "helper command: %s %s %s exit code %u (0x%x)\n", 387 conn_warn(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
386 usermode_helper, cmd, connection->name, 388 usermode_helper, cmd, resource_name,
387 (ret >> 8) & 0xff, ret); 389 (ret >> 8) & 0xff, ret);
388 else 390 else
389 conn_info(connection, "helper command: %s %s %s exit code %u (0x%x)\n", 391 conn_info(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
390 usermode_helper, cmd, connection->name, 392 usermode_helper, cmd, resource_name,
391 (ret >> 8) & 0xff, ret); 393 (ret >> 8) & 0xff, ret);
392 /* TODO: conn_bcast_event() ?? */ 394 /* TODO: conn_bcast_event() ?? */
393 395
@@ -2143,6 +2145,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
2143 struct drbd_device *device; 2145 struct drbd_device *device;
2144 struct net_conf *old_conf, *new_conf = NULL; 2146 struct net_conf *old_conf, *new_conf = NULL;
2145 struct crypto crypto = { }; 2147 struct crypto crypto = { };
2148 struct drbd_resource *resource;
2146 struct drbd_connection *connection; 2149 struct drbd_connection *connection;
2147 enum drbd_ret_code retcode; 2150 enum drbd_ret_code retcode;
2148 int i; 2151 int i;
@@ -2163,17 +2166,21 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
2163 /* No need for _rcu here. All reconfiguration is 2166 /* No need for _rcu here. All reconfiguration is
2164 * strictly serialized on genl_lock(). We are protected against 2167 * strictly serialized on genl_lock(). We are protected against
2165 * concurrent reconfiguration/addition/deletion */ 2168 * concurrent reconfiguration/addition/deletion */
2166 list_for_each_entry(connection, &drbd_connections, connections) { 2169 for_each_resource(resource, &drbd_resources) {
2167 if (nla_len(adm_ctx.my_addr) == connection->my_addr_len && 2170 for_each_connection(connection, resource) {
2168 !memcmp(nla_data(adm_ctx.my_addr), &connection->my_addr, connection->my_addr_len)) { 2171 if (nla_len(adm_ctx.my_addr) == connection->my_addr_len &&
2169 retcode = ERR_LOCAL_ADDR; 2172 !memcmp(nla_data(adm_ctx.my_addr), &connection->my_addr,
2170 goto out; 2173 connection->my_addr_len)) {
2171 } 2174 retcode = ERR_LOCAL_ADDR;
2175 goto out;
2176 }
2172 2177
2173 if (nla_len(adm_ctx.peer_addr) == connection->peer_addr_len && 2178 if (nla_len(adm_ctx.peer_addr) == connection->peer_addr_len &&
2174 !memcmp(nla_data(adm_ctx.peer_addr), &connection->peer_addr, connection->peer_addr_len)) { 2179 !memcmp(nla_data(adm_ctx.peer_addr), &connection->peer_addr,
2175 retcode = ERR_PEER_ADDR; 2180 connection->peer_addr_len)) {
2176 goto out; 2181 retcode = ERR_PEER_ADDR;
2182 goto out;
2183 }
2177 } 2184 }
2178 } 2185 }
2179 2186
@@ -2736,7 +2743,7 @@ static int nla_put_drbd_cfg_context(struct sk_buff *skb, struct drbd_connection
2736 if (vnr != VOLUME_UNSPECIFIED && 2743 if (vnr != VOLUME_UNSPECIFIED &&
2737 nla_put_u32(skb, T_ctx_volume, vnr)) 2744 nla_put_u32(skb, T_ctx_volume, vnr))
2738 goto nla_put_failure; 2745 goto nla_put_failure;
2739 if (nla_put_string(skb, T_ctx_resource_name, connection->name)) 2746 if (nla_put_string(skb, T_ctx_resource_name, connection->resource->name))
2740 goto nla_put_failure; 2747 goto nla_put_failure;
2741 if (connection->my_addr_len && 2748 if (connection->my_addr_len &&
2742 nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr)) 2749 nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr))
@@ -2899,18 +2906,20 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
2899{ 2906{
2900 struct drbd_device *device; 2907 struct drbd_device *device;
2901 struct drbd_genlmsghdr *dh; 2908 struct drbd_genlmsghdr *dh;
2902 struct drbd_connection *pos = (struct drbd_connection *)cb->args[0]; 2909 struct drbd_resource *pos = (struct drbd_resource *)cb->args[0];
2903 struct drbd_connection *connection = NULL; 2910 struct drbd_resource *resource = NULL;
2904 struct drbd_connection *tmp; 2911 struct drbd_connection *connection;
2912 struct drbd_resource *tmp;
2905 unsigned volume = cb->args[1]; 2913 unsigned volume = cb->args[1];
2906 2914
2907 /* Open coded, deferred, iteration: 2915 /* Open coded, deferred, iteration:
2908 * list_for_each_entry_safe(connection, tmp, &drbd_connections, connections) { 2916 * for_each_resource_safe(resource, tmp, &drbd_resources) {
2917 * connection = "first connection of resource";
2909 * idr_for_each_entry(&connection->volumes, device, i) { 2918 * idr_for_each_entry(&connection->volumes, device, i) {
2910 * ... 2919 * ...
2911 * } 2920 * }
2912 * } 2921 * }
2913 * where connection is cb->args[0]; 2922 * where resource is cb->args[0];
2914 * and i is cb->args[1]; 2923 * and i is cb->args[1];
2915 * 2924 *
2916 * cb->args[2] indicates if we shall loop over all resources, 2925 * cb->args[2] indicates if we shall loop over all resources,
@@ -2927,36 +2936,37 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
2927 /* synchronize with conn_create()/drbd_destroy_connection() */ 2936 /* synchronize with conn_create()/drbd_destroy_connection() */
2928 rcu_read_lock(); 2937 rcu_read_lock();
2929 /* revalidate iterator position */ 2938 /* revalidate iterator position */
2930 list_for_each_entry_rcu(tmp, &drbd_connections, connections) { 2939 for_each_resource_rcu(tmp, &drbd_resources) {
2931 if (pos == NULL) { 2940 if (pos == NULL) {
2932 /* first iteration */ 2941 /* first iteration */
2933 pos = tmp; 2942 pos = tmp;
2934 connection = pos; 2943 resource = pos;
2935 break; 2944 break;
2936 } 2945 }
2937 if (tmp == pos) { 2946 if (tmp == pos) {
2938 connection = pos; 2947 resource = pos;
2939 break; 2948 break;
2940 } 2949 }
2941 } 2950 }
2942 if (connection) { 2951 if (resource) {
2943next_connection: 2952next_resource:
2953 connection = first_connection(resource);
2944 device = idr_get_next(&connection->volumes, &volume); 2954 device = idr_get_next(&connection->volumes, &volume);
2945 if (!device) { 2955 if (!device) {
2946 /* No more volumes to dump on this connection. 2956 /* No more volumes to dump on this resource.
2947 * Advance connection iterator. */ 2957 * Advance resource iterator. */
2948 pos = list_entry_rcu(connection->connections.next, 2958 pos = list_entry_rcu(resource->resources.next,
2949 struct drbd_connection, connections); 2959 struct drbd_resource, resources);
2950 /* Did we dump any volume on this connection yet? */ 2960 /* Did we dump any volume of this resource yet? */
2951 if (volume != 0) { 2961 if (volume != 0) {
2952 /* If we reached the end of the list, 2962 /* If we reached the end of the list,
2953 * or only a single resource dump was requested, 2963 * or only a single resource dump was requested,
2954 * we are done. */ 2964 * we are done. */
2955 if (&pos->connections == &drbd_connections || cb->args[2]) 2965 if (&pos->resources == &drbd_resources || cb->args[2])
2956 goto out; 2966 goto out;
2957 volume = 0; 2967 volume = 0;
2958 connection = pos; 2968 resource = pos;
2959 goto next_connection; 2969 goto next_resource;
2960 } 2970 }
2961 } 2971 }
2962 2972
@@ -3000,9 +3010,9 @@ out:
3000 rcu_read_unlock(); 3010 rcu_read_unlock();
3001 /* where to start the next iteration */ 3011 /* where to start the next iteration */
3002 cb->args[0] = (long)pos; 3012 cb->args[0] = (long)pos;
3003 cb->args[1] = (pos == connection) ? volume + 1 : 0; 3013 cb->args[1] = (pos == resource) ? volume + 1 : 0;
3004 3014
3005 /* No more connections/volumes/minors found results in an empty skb. 3015 /* No more resources/volumes/minors found results in an empty skb.
3006 * Which will terminate the dump. */ 3016 * Which will terminate the dump. */
3007 return skb->len; 3017 return skb->len;
3008} 3018}
@@ -3399,9 +3409,11 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
3399 3409
3400 /* delete connection */ 3410 /* delete connection */
3401 if (conn_lowest_minor(adm_ctx.connection) < 0) { 3411 if (conn_lowest_minor(adm_ctx.connection) < 0) {
3402 list_del_rcu(&adm_ctx.connection->connections); 3412 struct drbd_resource *resource = adm_ctx.connection->resource;
3413
3414 list_del_rcu(&resource->resources);
3403 synchronize_rcu(); 3415 synchronize_rcu();
3404 kref_put(&adm_ctx.connection->kref, drbd_destroy_connection); 3416 drbd_free_resource(resource);
3405 3417
3406 retcode = NO_ERROR; 3418 retcode = NO_ERROR;
3407 } else { 3419 } else {
@@ -3417,6 +3429,8 @@ out:
3417 3429
3418int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info) 3430int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
3419{ 3431{
3432 struct drbd_resource *resource;
3433 struct drbd_connection *connection;
3420 enum drbd_ret_code retcode; 3434 enum drbd_ret_code retcode;
3421 3435
3422 retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE); 3436 retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
@@ -3425,18 +3439,24 @@ int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
3425 if (retcode != NO_ERROR) 3439 if (retcode != NO_ERROR)
3426 goto out; 3440 goto out;
3427 3441
3428 if (conn_lowest_minor(adm_ctx.connection) < 0) { 3442 resource = adm_ctx.resource;
3429 list_del_rcu(&adm_ctx.connection->connections); 3443 for_each_connection(connection, resource) {
3430 synchronize_rcu(); 3444 if (connection->cstate > C_STANDALONE) {
3431 kref_put(&adm_ctx.connection->kref, drbd_destroy_connection); 3445 retcode = ERR_NET_CONFIGURED;
3432 3446 goto out;
3433 retcode = NO_ERROR; 3447 }
3434 } else { 3448 }
3449 if (!idr_is_empty(&resource->devices)) {
3435 retcode = ERR_RES_IN_USE; 3450 retcode = ERR_RES_IN_USE;
3451 goto out;
3436 } 3452 }
3437 3453
3438 if (retcode == NO_ERROR) 3454 list_del_rcu(&resource->resources);
3439 drbd_thread_stop(&adm_ctx.connection->worker); 3455 for_each_connection(connection, resource)
3456 drbd_thread_stop(&connection->worker);
3457 synchronize_rcu();
3458 drbd_free_resource(resource);
3459 retcode = NO_ERROR;
3440out: 3460out:
3441 drbd_adm_finish(info, retcode); 3461 drbd_adm_finish(info, retcode);
3442 return 0; 3462 return 0;