Commit 625a6ba2 authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Philipp Reisner

drbd: Move cpu_mask from connection to resource

Also fix drbd_calc_cpu_mask() to spread resources equally over all online cpus
independent of device minor numbers.
Signed-off-by: default avatarAndreas Gruenbacher <agruen@linbit.com>
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
parent f44d0436
...@@ -584,6 +584,8 @@ struct drbd_resource { ...@@ -584,6 +584,8 @@ struct drbd_resource {
unsigned susp:1; /* IO suspended by user */ unsigned susp:1; /* IO suspended by user */
unsigned susp_nod:1; /* IO suspended because no data */ unsigned susp_nod:1; /* IO suspended because no data */
unsigned susp_fen:1; /* IO suspended because fence peer handler runs */ unsigned susp_fen:1; /* IO suspended because fence peer handler runs */
cpumask_var_t cpu_mask;
}; };
struct drbd_connection { struct drbd_connection {
...@@ -632,7 +634,6 @@ struct drbd_connection { ...@@ -632,7 +634,6 @@ struct drbd_connection {
struct drbd_thread receiver; struct drbd_thread receiver;
struct drbd_thread worker; struct drbd_thread worker;
struct drbd_thread asender; struct drbd_thread asender;
cpumask_var_t cpu_mask;
/* sender side */ /* sender side */
struct drbd_work_queue sender_work; struct drbd_work_queue sender_work;
...@@ -880,10 +881,8 @@ extern void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait); ...@@ -880,10 +881,8 @@ extern void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait);
extern char *drbd_task_to_thread_name(struct drbd_connection *connection, struct task_struct *task); extern char *drbd_task_to_thread_name(struct drbd_connection *connection, struct task_struct *task);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern void drbd_thread_current_set_cpu(struct drbd_thread *thi); extern void drbd_thread_current_set_cpu(struct drbd_thread *thi);
extern void drbd_calc_cpu_mask(struct drbd_connection *connection);
#else #else
#define drbd_thread_current_set_cpu(A) ({}) #define drbd_thread_current_set_cpu(A) ({})
#define drbd_calc_cpu_mask(A) ({})
#endif #endif
extern void tl_release(struct drbd_connection *, unsigned int barrier_nr, extern void tl_release(struct drbd_connection *, unsigned int barrier_nr,
unsigned int set_size); unsigned int set_size);
......
...@@ -511,28 +511,38 @@ int conn_lowest_minor(struct drbd_connection *connection) ...@@ -511,28 +511,38 @@ int conn_lowest_minor(struct drbd_connection *connection)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/** /**
* drbd_calc_cpu_mask() - Generate CPU masks, spread over all CPUs * drbd_calc_cpu_mask() - Generate CPU masks, spread over all CPUs
* @device: DRBD device.
* *
* Forces all threads of a device onto the same CPU. This is beneficial for * Forces all threads of a resource onto the same CPU. This is beneficial for
* DRBD's performance. May be overwritten by user's configuration. * DRBD's performance. May be overwritten by user's configuration.
*/ */
void drbd_calc_cpu_mask(struct drbd_connection *connection) static void drbd_calc_cpu_mask(cpumask_var_t *cpu_mask)
{ {
int ord, cpu; unsigned int *resources_per_cpu, min_index = ~0;
/* user override. */ resources_per_cpu = kzalloc(nr_cpu_ids * sizeof(*resources_per_cpu), GFP_KERNEL);
if (cpumask_weight(connection->cpu_mask)) if (resources_per_cpu) {
return; struct drbd_resource *resource;
unsigned int cpu, min = ~0;
ord = conn_lowest_minor(connection) % cpumask_weight(cpu_online_mask); rcu_read_lock();
for_each_resource_rcu(resource, &drbd_resources) {
for_each_cpu(cpu, resource->cpu_mask)
resources_per_cpu[cpu]++;
}
rcu_read_unlock();
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
if (ord-- == 0) { if (resources_per_cpu[cpu] < min) {
cpumask_set_cpu(cpu, connection->cpu_mask); min = resources_per_cpu[cpu];
return; min_index = cpu;
}
} }
kfree(resources_per_cpu);
} }
/* should not be reached */ if (min_index == ~0) {
cpumask_setall(connection->cpu_mask); cpumask_setall(*cpu_mask);
return;
}
cpumask_set_cpu(min_index, *cpu_mask);
} }
/** /**
...@@ -550,8 +560,10 @@ void drbd_thread_current_set_cpu(struct drbd_thread *thi) ...@@ -550,8 +560,10 @@ void drbd_thread_current_set_cpu(struct drbd_thread *thi)
if (!thi->reset_cpu_mask) if (!thi->reset_cpu_mask)
return; return;
thi->reset_cpu_mask = 0; thi->reset_cpu_mask = 0;
set_cpus_allowed_ptr(p, thi->connection->cpu_mask); set_cpus_allowed_ptr(p, thi->connection->resource->cpu_mask);
} }
#else
#define drbd_calc_cpu_mask(A) ({})
#endif #endif
/** /**
...@@ -2287,6 +2299,7 @@ void drbd_destroy_resource(struct kref *kref) ...@@ -2287,6 +2299,7 @@ void drbd_destroy_resource(struct kref *kref)
container_of(kref, struct drbd_resource, kref); container_of(kref, struct drbd_resource, kref);
idr_destroy(&resource->devices); idr_destroy(&resource->devices);
free_cpumask_var(resource->cpu_mask);
kfree(resource->name); kfree(resource->name);
kfree(resource); kfree(resource);
} }
...@@ -2512,10 +2525,11 @@ int set_resource_options(struct drbd_resource *resource, struct res_opts *res_op ...@@ -2512,10 +2525,11 @@ int set_resource_options(struct drbd_resource *resource, struct res_opts *res_op
} }
} }
resource->res_opts = *res_opts; resource->res_opts = *res_opts;
if (cpumask_empty(new_cpu_mask))
drbd_calc_cpu_mask(&new_cpu_mask);
if (!cpumask_equal(resource->cpu_mask, new_cpu_mask)) {
cpumask_copy(resource->cpu_mask, new_cpu_mask);
for_each_connection_rcu(connection, resource) { for_each_connection_rcu(connection, resource) {
if (!cpumask_equal(connection->cpu_mask, new_cpu_mask)) {
cpumask_copy(connection->cpu_mask, new_cpu_mask);
drbd_calc_cpu_mask(connection);
connection->receiver.reset_cpu_mask = 1; connection->receiver.reset_cpu_mask = 1;
connection->asender.reset_cpu_mask = 1; connection->asender.reset_cpu_mask = 1;
connection->worker.reset_cpu_mask = 1; connection->worker.reset_cpu_mask = 1;
...@@ -2535,12 +2549,12 @@ struct drbd_resource *drbd_create_resource(const char *name) ...@@ -2535,12 +2549,12 @@ struct drbd_resource *drbd_create_resource(const char *name)
resource = kzalloc(sizeof(struct drbd_resource), GFP_KERNEL); resource = kzalloc(sizeof(struct drbd_resource), GFP_KERNEL);
if (!resource) if (!resource)
return NULL; goto fail;
resource->name = kstrdup(name, GFP_KERNEL); resource->name = kstrdup(name, GFP_KERNEL);
if (!resource->name) { if (!resource->name)
kfree(resource); goto fail_free_resource;
return NULL; if (!zalloc_cpumask_var(&resource->cpu_mask, GFP_KERNEL))
} goto fail_free_name;
kref_init(&resource->kref); kref_init(&resource->kref);
idr_init(&resource->devices); idr_init(&resource->devices);
INIT_LIST_HEAD(&resource->connections); INIT_LIST_HEAD(&resource->connections);
...@@ -2548,6 +2562,13 @@ struct drbd_resource *drbd_create_resource(const char *name) ...@@ -2548,6 +2562,13 @@ struct drbd_resource *drbd_create_resource(const char *name)
mutex_init(&resource->conf_update); mutex_init(&resource->conf_update);
spin_lock_init(&resource->req_lock); spin_lock_init(&resource->req_lock);
return resource; return resource;
fail_free_name:
kfree(resource->name);
fail_free_resource:
kfree(resource);
fail:
return NULL;
} }
/* caller must be under genl_lock() */ /* caller must be under genl_lock() */
...@@ -2565,9 +2586,6 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts) ...@@ -2565,9 +2586,6 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
if (drbd_alloc_socket(&connection->meta)) if (drbd_alloc_socket(&connection->meta))
goto fail; goto fail;
if (!zalloc_cpumask_var(&connection->cpu_mask, GFP_KERNEL))
goto fail;
connection->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL); connection->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
if (!connection->current_epoch) if (!connection->current_epoch)
goto fail; goto fail;
...@@ -2616,7 +2634,6 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts) ...@@ -2616,7 +2634,6 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
drbd_free_resource(resource); drbd_free_resource(resource);
fail: fail:
kfree(connection->current_epoch); kfree(connection->current_epoch);
free_cpumask_var(connection->cpu_mask);
drbd_free_socket(&connection->meta); drbd_free_socket(&connection->meta);
drbd_free_socket(&connection->data); drbd_free_socket(&connection->data);
kfree(connection); kfree(connection);
...@@ -2634,7 +2651,6 @@ void drbd_destroy_connection(struct kref *kref) ...@@ -2634,7 +2651,6 @@ void drbd_destroy_connection(struct kref *kref)
idr_destroy(&connection->peer_devices); idr_destroy(&connection->peer_devices);
free_cpumask_var(connection->cpu_mask);
drbd_free_socket(&connection->meta); drbd_free_socket(&connection->meta);
drbd_free_socket(&connection->data); drbd_free_socket(&connection->data);
kfree(connection->int_dig_in); kfree(connection->int_dig_in);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment