aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_main.c
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@linbit.com>2011-06-08 16:17:38 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2014-02-17 10:44:53 -0500
commit77c556f663b7ac066268c94c18670ce93dec60c0 (patch)
treec05d7b93806b46528e4007ca2bf83ecfb2ec0671 /drivers/block/drbd/drbd_main.c
parent05a10ec7900dbdba008a24bf56b3490c4b568d2c (diff)
drbd: Add struct drbd_resource
In a first step, each resource has exactly one connection, and both objects are allocated at the same time. The final result will be one resource and zero or more connections. Only allow to delete a resource if all its connections are C_STANDALONE. Stop the worker threads of all connections early enough. Signed-off-by: Andreas Gruenbacher <agruen@linbit.com> Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_main.c')
-rw-r--r--drivers/block/drbd/drbd_main.c96
1 files changed, 71 insertions, 25 deletions
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) {