drbd: Iterate over all connections
[deliverable/linux.git] / drivers / block / drbd / drbd_main.c
index cc3b451d465faa3647bac61e1194d8e710665958..54df98fa288183f7d9e35d0bcfbbada55ce58c61 100644 (file)
@@ -117,8 +117,8 @@ module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0
 /* in 2.6.x, our device mapping and config info contains our virtual gendisks
  * as member "struct gendisk *vdisk;"
  */
-struct idr minors;
-struct list_head drbd_tconns;  /* list of struct drbd_tconn */
+struct idr drbd_devices;
+struct list_head drbd_resources;
 
 struct kmem_cache *drbd_request_cache;
 struct kmem_cache *drbd_ee_cache;      /* peer requests */
@@ -182,7 +182,7 @@ int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins)
 
 /**
  * tl_release() - mark as BARRIER_ACKED all requests in the corresponding transfer log epoch
- * @tconn:     DRBD connection.
+ * @connection:        DRBD connection.
  * @barrier_nr:        Expected identifier of the DRBD write barrier packet.
  * @set_size:  Expected number of requests before that barrier.
  *
@@ -190,7 +190,7 @@ int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins)
  * epoch of not yet barrier-acked requests, this function will cause a
  * termination of the connection.
  */
-void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
+void tl_release(struct drbd_connection *connection, unsigned int barrier_nr,
                unsigned int set_size)
 {
        struct drbd_request *r;
@@ -198,11 +198,11 @@ void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
        int expect_epoch = 0;
        int expect_size = 0;
 
-       spin_lock_irq(&tconn->req_lock);
+       spin_lock_irq(&connection->req_lock);
 
        /* find oldest not yet barrier-acked write request,
         * count writes in its epoch. */
-       list_for_each_entry(r, &tconn->transfer_log, tl_requests) {
+       list_for_each_entry(r, &connection->transfer_log, tl_requests) {
                const unsigned s = r->rq_state;
                if (!req) {
                        if (!(s & RQ_WRITE))
@@ -227,18 +227,18 @@ void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
 
        /* first some paranoia code */
        if (req == NULL) {
-               conn_err(tconn, "BAD! BarrierAck #%u received, but no epoch in tl!?\n",
+               drbd_err(connection, "BAD! BarrierAck #%u received, but no epoch in tl!?\n",
                         barrier_nr);
                goto bail;
        }
        if (expect_epoch != barrier_nr) {
-               conn_err(tconn, "BAD! BarrierAck #%u received, expected #%u!\n",
+               drbd_err(connection, "BAD! BarrierAck #%u received, expected #%u!\n",
                         barrier_nr, expect_epoch);
                goto bail;
        }
 
        if (expect_size != set_size) {
-               conn_err(tconn, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
+               drbd_err(connection, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
                         barrier_nr, set_size, expect_size);
                goto bail;
        }
@@ -247,21 +247,21 @@ void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
        /* this extra list walk restart is paranoia,
         * to catch requests being barrier-acked "unexpectedly".
         * It usually should find the same req again, or some READ preceding it. */
-       list_for_each_entry(req, &tconn->transfer_log, tl_requests)
+       list_for_each_entry(req, &connection->transfer_log, tl_requests)
                if (req->epoch == expect_epoch)
                        break;
-       list_for_each_entry_safe_from(req, r, &tconn->transfer_log, tl_requests) {
+       list_for_each_entry_safe_from(req, r, &connection->transfer_log, tl_requests) {
                if (req->epoch != expect_epoch)
                        break;
                _req_mod(req, BARRIER_ACKED);
        }
-       spin_unlock_irq(&tconn->req_lock);
+       spin_unlock_irq(&connection->req_lock);
 
        return;
 
 bail:
-       spin_unlock_irq(&tconn->req_lock);
-       conn_request_state(tconn, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
+       spin_unlock_irq(&connection->req_lock);
+       conn_request_state(connection, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
 }
 
 
@@ -274,19 +274,19 @@ bail:
  * RESTART_FROZEN_DISK_IO.
  */
 /* must hold resource->req_lock */
-void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what)
+void _tl_restart(struct drbd_connection *connection, enum drbd_req_event what)
 {
        struct drbd_request *req, *r;
 
-       list_for_each_entry_safe(req, r, &tconn->transfer_log, tl_requests)
+       list_for_each_entry_safe(req, r, &connection->transfer_log, tl_requests)
                _req_mod(req, what);
 }
 
-void tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what)
+void tl_restart(struct drbd_connection *connection, enum drbd_req_event what)
 {
-       spin_lock_irq(&tconn->req_lock);
-       _tl_restart(tconn, what);
-       spin_unlock_irq(&tconn->req_lock);
+       spin_lock_irq(&connection->req_lock);
+       _tl_restart(connection, what);
+       spin_unlock_irq(&connection->req_lock);
 }
 
 /**
@@ -297,9 +297,9 @@ void tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what)
  * by the requests on the transfer gets marked as our of sync. Called from the
  * receiver thread and the worker thread.
  */
-void tl_clear(struct drbd_tconn *tconn)
+void tl_clear(struct drbd_connection *connection)
 {
-       tl_restart(tconn, CONNECTION_LOST_WHILE_PENDING);
+       tl_restart(connection, CONNECTION_LOST_WHILE_PENDING);
 }
 
 /**
@@ -308,29 +308,30 @@ void tl_clear(struct drbd_tconn *tconn)
  */
 void tl_abort_disk_io(struct drbd_device *device)
 {
-       struct drbd_tconn *tconn = device->tconn;
+       struct drbd_connection *connection = first_peer_device(device)->connection;
        struct drbd_request *req, *r;
 
-       spin_lock_irq(&tconn->req_lock);
-       list_for_each_entry_safe(req, r, &tconn->transfer_log, tl_requests) {
+       spin_lock_irq(&connection->req_lock);
+       list_for_each_entry_safe(req, r, &connection->transfer_log, tl_requests) {
                if (!(req->rq_state & RQ_LOCAL_PENDING))
                        continue;
                if (req->w.device != device)
                        continue;
                _req_mod(req, ABORT_DISK_IO);
        }
-       spin_unlock_irq(&tconn->req_lock);
+       spin_unlock_irq(&connection->req_lock);
 }
 
 static int drbd_thread_setup(void *arg)
 {
        struct drbd_thread *thi = (struct drbd_thread *) arg;
-       struct drbd_tconn *tconn = thi->tconn;
+       struct drbd_connection *connection = thi->connection;
        unsigned long flags;
        int retval;
 
        snprintf(current->comm, sizeof(current->comm), "drbd_%c_%s",
-                thi->name[0], thi->tconn->name);
+                thi->name[0],
+                thi->connection->resource->name);
 
 restart:
        retval = thi->function(thi);
@@ -348,7 +349,7 @@ restart:
         */
 
        if (thi->t_state == RESTARTING) {
-               conn_info(tconn, "Restarting %s thread\n", thi->name);
+               drbd_info(connection, "Restarting %s thread\n", thi->name);
                thi->t_state = RUNNING;
                spin_unlock_irqrestore(&thi->t_lock, flags);
                goto restart;
@@ -360,29 +361,29 @@ restart:
        complete_all(&thi->stop);
        spin_unlock_irqrestore(&thi->t_lock, flags);
 
-       conn_info(tconn, "Terminating %s\n", current->comm);
+       drbd_info(connection, "Terminating %s\n", current->comm);
 
        /* Release mod reference taken when thread was started */
 
-       kref_put(&tconn->kref, &conn_destroy);
+       kref_put(&connection->kref, drbd_destroy_connection);
        module_put(THIS_MODULE);
        return retval;
 }
 
-static void drbd_thread_init(struct drbd_tconn *tconn, struct drbd_thread *thi,
+static void drbd_thread_init(struct drbd_connection *connection, struct drbd_thread *thi,
                             int (*func) (struct drbd_thread *), char *name)
 {
        spin_lock_init(&thi->t_lock);
        thi->task    = NULL;
        thi->t_state = NONE;
        thi->function = func;
-       thi->tconn = tconn;
+       thi->connection = connection;
        strncpy(thi->name, name, ARRAY_SIZE(thi->name));
 }
 
 int drbd_thread_start(struct drbd_thread *thi)
 {
-       struct drbd_tconn *tconn = thi->tconn;
+       struct drbd_connection *connection = thi->connection;
        struct task_struct *nt;
        unsigned long flags;
 
@@ -392,17 +393,17 @@ int drbd_thread_start(struct drbd_thread *thi)
 
        switch (thi->t_state) {
        case NONE:
-               conn_info(tconn, "Starting %s thread (from %s [%d])\n",
+               drbd_info(connection, "Starting %s thread (from %s [%d])\n",
                         thi->name, current->comm, current->pid);
 
                /* Get ref on module for thread - this is released when thread exits */
                if (!try_module_get(THIS_MODULE)) {
-                       conn_err(tconn, "Failed to get module reference in drbd_thread_start\n");
+                       drbd_err(connection, "Failed to get module reference in drbd_thread_start\n");
                        spin_unlock_irqrestore(&thi->t_lock, flags);
                        return false;
                }
 
-               kref_get(&thi->tconn->kref);
+               kref_get(&thi->connection->kref);
 
                init_completion(&thi->stop);
                thi->reset_cpu_mask = 1;
@@ -411,12 +412,12 @@ int drbd_thread_start(struct drbd_thread *thi)
                flush_signals(current); /* otherw. may get -ERESTARTNOINTR */
 
                nt = kthread_create(drbd_thread_setup, (void *) thi,
-                                   "drbd_%c_%s", thi->name[0], thi->tconn->name);
+                                   "drbd_%c_%s", thi->name[0], thi->connection->resource->name);
 
                if (IS_ERR(nt)) {
-                       conn_err(tconn, "Couldn't start thread\n");
+                       drbd_err(connection, "Couldn't start thread\n");
 
-                       kref_put(&tconn->kref, &conn_destroy);
+                       kref_put(&connection->kref, drbd_destroy_connection);
                        module_put(THIS_MODULE);
                        return false;
                }
@@ -428,7 +429,7 @@ int drbd_thread_start(struct drbd_thread *thi)
                break;
        case EXITING:
                thi->t_state = RESTARTING;
-               conn_info(tconn, "Restarting %s thread (from %s [%d])\n",
+               drbd_info(connection, "Restarting %s thread (from %s [%d])\n",
                                thi->name, current->comm, current->pid);
                /* fall through */
        case RUNNING:
@@ -477,33 +478,34 @@ void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait)
                wait_for_completion(&thi->stop);
 }
 
-static struct drbd_thread *drbd_task_to_thread(struct drbd_tconn *tconn, struct task_struct *task)
+static struct drbd_thread *drbd_task_to_thread(struct drbd_connection *connection, struct task_struct *task)
 {
        struct drbd_thread *thi =
-               task == tconn->receiver.task ? &tconn->receiver :
-               task == tconn->asender.task  ? &tconn->asender :
-               task == tconn->worker.task   ? &tconn->worker : NULL;
+               task == connection->receiver.task ? &connection->receiver :
+               task == connection->asender.task  ? &connection->asender :
+               task == connection->worker.task   ? &connection->worker : NULL;
 
        return thi;
 }
 
-char *drbd_task_to_thread_name(struct drbd_tconn *tconn, struct task_struct *task)
+char *drbd_task_to_thread_name(struct drbd_connection *connection, struct task_struct *task)
 {
-       struct drbd_thread *thi = drbd_task_to_thread(tconn, task);
+       struct drbd_thread *thi = drbd_task_to_thread(connection, task);
        return thi ? thi->name : task->comm;
 }
 
-int conn_lowest_minor(struct drbd_tconn *tconn)
+int conn_lowest_minor(struct drbd_connection *connection)
 {
-       struct drbd_device *device;
-       int vnr = 0, m;
+       struct drbd_peer_device *peer_device;
+       int vnr = 0, minor = -1;
 
        rcu_read_lock();
-       device = idr_get_next(&tconn->volumes, &vnr);
-       m = device ? device_to_minor(device) : -1;
+       peer_device = idr_get_next(&connection->peer_devices, &vnr);
+       if (peer_device)
+               minor = device_to_minor(peer_device->device);
        rcu_read_unlock();
 
-       return m;
+       return minor;
 }
 
 #ifdef CONFIG_SMP
@@ -514,23 +516,23 @@ int conn_lowest_minor(struct drbd_tconn *tconn)
  * Forces all threads of a device onto the same CPU. This is beneficial for
  * DRBD's performance. May be overwritten by user's configuration.
  */
-void drbd_calc_cpu_mask(struct drbd_tconn *tconn)
+void drbd_calc_cpu_mask(struct drbd_connection *connection)
 {
        int ord, cpu;
 
        /* user override. */
-       if (cpumask_weight(tconn->cpu_mask))
+       if (cpumask_weight(connection->cpu_mask))
                return;
 
-       ord = conn_lowest_minor(tconn) % cpumask_weight(cpu_online_mask);
+       ord = conn_lowest_minor(connection) % cpumask_weight(cpu_online_mask);
        for_each_online_cpu(cpu) {
                if (ord-- == 0) {
-                       cpumask_set_cpu(cpu, tconn->cpu_mask);
+                       cpumask_set_cpu(cpu, connection->cpu_mask);
                        return;
                }
        }
        /* should not be reached */
-       cpumask_setall(tconn->cpu_mask);
+       cpumask_setall(connection->cpu_mask);
 }
 
 /**
@@ -548,7 +550,7 @@ void drbd_thread_current_set_cpu(struct drbd_thread *thi)
        if (!thi->reset_cpu_mask)
                return;
        thi->reset_cpu_mask = 0;
-       set_cpus_allowed_ptr(p, thi->tconn->cpu_mask);
+       set_cpus_allowed_ptr(p, thi->connection->cpu_mask);
 }
 #endif
 
@@ -559,9 +561,9 @@ void drbd_thread_current_set_cpu(struct drbd_thread *thi)
  * word aligned on 64-bit architectures.  (The bitmap send and receive code
  * relies on this.)
  */
-unsigned int drbd_header_size(struct drbd_tconn *tconn)
+unsigned int drbd_header_size(struct drbd_connection *connection)
 {
-       if (tconn->agreed_pro_version >= 100) {
+       if (connection->agreed_pro_version >= 100) {
                BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header100), 8));
                return sizeof(struct p_header100);
        } else {
@@ -599,32 +601,32 @@ static unsigned int prepare_header100(struct p_header100 *h, enum drbd_packet cm
        return sizeof(struct p_header100);
 }
 
-static unsigned int prepare_header(struct drbd_tconn *tconn, int vnr,
+static unsigned int prepare_header(struct drbd_connection *connection, int vnr,
                                   void *buffer, enum drbd_packet cmd, int size)
 {
-       if (tconn->agreed_pro_version >= 100)
+       if (connection->agreed_pro_version >= 100)
                return prepare_header100(buffer, cmd, size, vnr);
-       else if (tconn->agreed_pro_version >= 95 &&
+       else if (connection->agreed_pro_version >= 95 &&
                 size > DRBD_MAX_SIZE_H80_PACKET)
                return prepare_header95(buffer, cmd, size);
        else
                return prepare_header80(buffer, cmd, size);
 }
 
-static void *__conn_prepare_command(struct drbd_tconn *tconn,
+static void *__conn_prepare_command(struct drbd_connection *connection,
                                    struct drbd_socket *sock)
 {
        if (!sock->socket)
                return NULL;
-       return sock->sbuf + drbd_header_size(tconn);
+       return sock->sbuf + drbd_header_size(connection);
 }
 
-void *conn_prepare_command(struct drbd_tconn *tconn, struct drbd_socket *sock)
+void *conn_prepare_command(struct drbd_connection *connection, struct drbd_socket *sock)
 {
        void *p;
 
        mutex_lock(&sock->mutex);
-       p = __conn_prepare_command(tconn, sock);
+       p = __conn_prepare_command(connection, sock);
        if (!p)
                mutex_unlock(&sock->mutex);
 
@@ -633,10 +635,10 @@ void *conn_prepare_command(struct drbd_tconn *tconn, struct drbd_socket *sock)
 
 void *drbd_prepare_command(struct drbd_device *device, struct drbd_socket *sock)
 {
-       return conn_prepare_command(device->tconn, sock);
+       return conn_prepare_command(first_peer_device(device)->connection, sock);
 }
 
-static int __send_command(struct drbd_tconn *tconn, int vnr,
+static int __send_command(struct drbd_connection *connection, int vnr,
                          struct drbd_socket *sock, enum drbd_packet cmd,
                          unsigned int header_size, void *data,
                          unsigned int size)
@@ -653,29 +655,29 @@ static int __send_command(struct drbd_tconn *tconn, int vnr,
         */
        msg_flags = data ? MSG_MORE : 0;
 
-       header_size += prepare_header(tconn, vnr, sock->sbuf, cmd,
+       header_size += prepare_header(connection, vnr, sock->sbuf, cmd,
                                      header_size + size);
-       err = drbd_send_all(tconn, sock->socket, sock->sbuf, header_size,
+       err = drbd_send_all(connection, sock->socket, sock->sbuf, header_size,
                            msg_flags);
        if (data && !err)
-               err = drbd_send_all(tconn, sock->socket, data, size, 0);
+               err = drbd_send_all(connection, sock->socket, data, size, 0);
        return err;
 }
 
-static int __conn_send_command(struct drbd_tconn *tconn, struct drbd_socket *sock,
+static int __conn_send_command(struct drbd_connection *connection, struct drbd_socket *sock,
                               enum drbd_packet cmd, unsigned int header_size,
                               void *data, unsigned int size)
 {
-       return __send_command(tconn, 0, sock, cmd, header_size, data, size);
+       return __send_command(connection, 0, sock, cmd, header_size, data, size);
 }
 
-int conn_send_command(struct drbd_tconn *tconn, struct drbd_socket *sock,
+int conn_send_command(struct drbd_connection *connection, struct drbd_socket *sock,
                      enum drbd_packet cmd, unsigned int header_size,
                      void *data, unsigned int size)
 {
        int err;
 
-       err = __conn_send_command(tconn, sock, cmd, header_size, data, size);
+       err = __conn_send_command(connection, sock, cmd, header_size, data, size);
        mutex_unlock(&sock->mutex);
        return err;
 }
@@ -686,30 +688,30 @@ int drbd_send_command(struct drbd_device *device, struct drbd_socket *sock,
 {
        int err;
 
-       err = __send_command(device->tconn, device->vnr, sock, cmd, header_size,
+       err = __send_command(first_peer_device(device)->connection, device->vnr, sock, cmd, header_size,
                             data, size);
        mutex_unlock(&sock->mutex);
        return err;
 }
 
-int drbd_send_ping(struct drbd_tconn *tconn)
+int drbd_send_ping(struct drbd_connection *connection)
 {
        struct drbd_socket *sock;
 
-       sock = &tconn->meta;
-       if (!conn_prepare_command(tconn, sock))
+       sock = &connection->meta;
+       if (!conn_prepare_command(connection, sock))
                return -EIO;
-       return conn_send_command(tconn, sock, P_PING, 0, NULL, 0);
+       return conn_send_command(connection, sock, P_PING, 0, NULL, 0);
 }
 
-int drbd_send_ping_ack(struct drbd_tconn *tconn)
+int drbd_send_ping_ack(struct drbd_connection *connection)
 {
        struct drbd_socket *sock;
 
-       sock = &tconn->meta;
-       if (!conn_prepare_command(tconn, sock))
+       sock = &connection->meta;
+       if (!conn_prepare_command(connection, sock))
                return -EIO;
-       return conn_send_command(tconn, sock, P_PING_ACK, 0, NULL, 0);
+       return conn_send_command(connection, sock, P_PING_ACK, 0, NULL, 0);
 }
 
 int drbd_send_sync_param(struct drbd_device *device)
@@ -717,18 +719,18 @@ int drbd_send_sync_param(struct drbd_device *device)
        struct drbd_socket *sock;
        struct p_rs_param_95 *p;
        int size;
-       const int apv = device->tconn->agreed_pro_version;
+       const int apv = first_peer_device(device)->connection->agreed_pro_version;
        enum drbd_packet cmd;
        struct net_conf *nc;
        struct disk_conf *dc;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
 
        rcu_read_lock();
-       nc = rcu_dereference(device->tconn->net_conf);
+       nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 
        size = apv <= 87 ? sizeof(struct p_rs_param)
                : apv == 88 ? sizeof(struct p_rs_param)
@@ -766,30 +768,30 @@ int drbd_send_sync_param(struct drbd_device *device)
        return drbd_send_command(device, sock, cmd, size, NULL, 0);
 }
 
-int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd)
+int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cmd)
 {
        struct drbd_socket *sock;
        struct p_protocol *p;
        struct net_conf *nc;
        int size, cf;
 
-       sock = &tconn->data;
-       p = __conn_prepare_command(tconn, sock);
+       sock = &connection->data;
+       p = __conn_prepare_command(connection, sock);
        if (!p)
                return -EIO;
 
        rcu_read_lock();
-       nc = rcu_dereference(tconn->net_conf);
+       nc = rcu_dereference(connection->net_conf);
 
-       if (nc->tentative && tconn->agreed_pro_version < 92) {
+       if (nc->tentative && connection->agreed_pro_version < 92) {
                rcu_read_unlock();
                mutex_unlock(&sock->mutex);
-               conn_err(tconn, "--dry-run is not supported by peer");
+               drbd_err(connection, "--dry-run is not supported by peer");
                return -EOPNOTSUPP;
        }
 
        size = sizeof(*p);
-       if (tconn->agreed_pro_version >= 87)
+       if (connection->agreed_pro_version >= 87)
                size += strlen(nc->integrity_alg) + 1;
 
        p->protocol      = cpu_to_be32(nc->wire_protocol);
@@ -804,20 +806,20 @@ int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd)
                cf |= CF_DRY_RUN;
        p->conn_flags    = cpu_to_be32(cf);
 
-       if (tconn->agreed_pro_version >= 87)
+       if (connection->agreed_pro_version >= 87)
                strcpy(p->integrity_alg, nc->integrity_alg);
        rcu_read_unlock();
 
-       return __conn_send_command(tconn, sock, cmd, size, NULL, 0);
+       return __conn_send_command(connection, sock, cmd, size, NULL, 0);
 }
 
-int drbd_send_protocol(struct drbd_tconn *tconn)
+int drbd_send_protocol(struct drbd_connection *connection)
 {
        int err;
 
-       mutex_lock(&tconn->data.mutex);
-       err = __drbd_send_protocol(tconn, P_PROTOCOL);
-       mutex_unlock(&tconn->data.mutex);
+       mutex_lock(&connection->data.mutex);
+       err = __drbd_send_protocol(connection, P_PROTOCOL);
+       mutex_unlock(&connection->data.mutex);
 
        return err;
 }
@@ -831,7 +833,7 @@ static int _drbd_send_uuids(struct drbd_device *device, u64 uuid_flags)
        if (!get_ldev_if_state(device, D_NEGOTIATING))
                return 0;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p) {
                put_ldev(device);
@@ -845,7 +847,7 @@ static int _drbd_send_uuids(struct drbd_device *device, u64 uuid_flags)
        device->comm_bm_set = drbd_bm_total_weight(device);
        p->uuid[UI_SIZE] = cpu_to_be64(device->comm_bm_set);
        rcu_read_lock();
-       uuid_flags |= rcu_dereference(device->tconn->net_conf)->discard_my_data ? 1 : 0;
+       uuid_flags |= rcu_dereference(first_peer_device(device)->connection->net_conf)->discard_my_data ? 1 : 0;
        rcu_read_unlock();
        uuid_flags |= test_bit(CRASHED_PRIMARY, &device->flags) ? 2 : 0;
        uuid_flags |= device->new_state_tmp.disk == D_INCONSISTENT ? 4 : 0;
@@ -869,7 +871,7 @@ void drbd_print_uuids(struct drbd_device *device, const char *text)
 {
        if (get_ldev_if_state(device, D_NEGOTIATING)) {
                u64 *uuid = device->ldev->md.uuid;
-               dev_info(DEV, "%s %016llX:%016llX:%016llX:%016llX\n",
+               drbd_info(device, "%s %016llX:%016llX:%016llX:%016llX\n",
                     text,
                     (unsigned long long)uuid[UI_CURRENT],
                     (unsigned long long)uuid[UI_BITMAP],
@@ -877,7 +879,7 @@ void drbd_print_uuids(struct drbd_device *device, const char *text)
                     (unsigned long long)uuid[UI_HISTORY_END]);
                put_ldev(device);
        } else {
-               dev_info(DEV, "%s effective data uuid: %016llX\n",
+               drbd_info(device, "%s effective data uuid: %016llX\n",
                                text,
                                (unsigned long long)device->ed_uuid);
        }
@@ -889,7 +891,7 @@ void drbd_gen_and_send_sync_uuid(struct drbd_device *device)
        struct p_rs_uuid *p;
        u64 uuid;
 
-       D_ASSERT(device->state.disk == D_UP_TO_DATE);
+       D_ASSERT(device, device->state.disk == D_UP_TO_DATE);
 
        uuid = device->ldev->md.uuid[UI_BITMAP];
        if (uuid && uuid != UUID_JUST_CREATED)
@@ -900,7 +902,7 @@ void drbd_gen_and_send_sync_uuid(struct drbd_device *device)
        drbd_print_uuids(device, "updated sync UUID");
        drbd_md_sync(device);
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (p) {
                p->uuid = cpu_to_be64(uuid);
@@ -917,7 +919,7 @@ int drbd_send_sizes(struct drbd_device *device, int trigger_reply, enum dds_flag
        unsigned int max_bio_size;
 
        if (get_ldev_if_state(device, D_NEGOTIATING)) {
-               D_ASSERT(device->ldev->backing_bdev);
+               D_ASSERT(device, device->ldev->backing_bdev);
                d_size = drbd_get_max_capacity(device->ldev);
                rcu_read_lock();
                u_size = rcu_dereference(device->ldev->disk_conf)->disk_size;
@@ -933,14 +935,14 @@ int drbd_send_sizes(struct drbd_device *device, int trigger_reply, enum dds_flag
                max_bio_size = DRBD_MAX_BIO_SIZE; /* ... multiple BIOs per peer_request */
        }
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
 
-       if (device->tconn->agreed_pro_version <= 94)
+       if (first_peer_device(device)->connection->agreed_pro_version <= 94)
                max_bio_size = min(max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
-       else if (device->tconn->agreed_pro_version < 100)
+       else if (first_peer_device(device)->connection->agreed_pro_version < 100)
                max_bio_size = min(max_bio_size, DRBD_MAX_BIO_SIZE_P95);
 
        p->d_size = cpu_to_be64(d_size);
@@ -961,7 +963,7 @@ int drbd_send_current_state(struct drbd_device *device)
        struct drbd_socket *sock;
        struct p_state *p;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -984,7 +986,7 @@ int drbd_send_state(struct drbd_device *device, union drbd_state state)
        struct drbd_socket *sock;
        struct p_state *p;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -997,7 +999,7 @@ int drbd_send_state_req(struct drbd_device *device, union drbd_state mask, union
        struct drbd_socket *sock;
        struct p_req_state *p;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -1006,20 +1008,20 @@ int drbd_send_state_req(struct drbd_device *device, union drbd_state mask, union
        return drbd_send_command(device, sock, P_STATE_CHG_REQ, sizeof(*p), NULL, 0);
 }
 
-int conn_send_state_req(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val)
+int conn_send_state_req(struct drbd_connection *connection, union drbd_state mask, union drbd_state val)
 {
        enum drbd_packet cmd;
        struct drbd_socket *sock;
        struct p_req_state *p;
 
-       cmd = tconn->agreed_pro_version < 100 ? P_STATE_CHG_REQ : P_CONN_ST_CHG_REQ;
-       sock = &tconn->data;
-       p = conn_prepare_command(tconn, sock);
+       cmd = connection->agreed_pro_version < 100 ? P_STATE_CHG_REQ : P_CONN_ST_CHG_REQ;
+       sock = &connection->data;
+       p = conn_prepare_command(connection, sock);
        if (!p)
                return -EIO;
        p->mask = cpu_to_be32(mask.i);
        p->val = cpu_to_be32(val.i);
-       return conn_send_command(tconn, sock, cmd, sizeof(*p), NULL, 0);
+       return conn_send_command(connection, sock, cmd, sizeof(*p), NULL, 0);
 }
 
 void drbd_send_sr_reply(struct drbd_device *device, enum drbd_state_rv retcode)
@@ -1027,7 +1029,7 @@ void drbd_send_sr_reply(struct drbd_device *device, enum drbd_state_rv retcode)
        struct drbd_socket *sock;
        struct p_req_state_reply *p;
 
-       sock = &device->tconn->meta;
+       sock = &first_peer_device(device)->connection->meta;
        p = drbd_prepare_command(device, sock);
        if (p) {
                p->retcode = cpu_to_be32(retcode);
@@ -1035,17 +1037,17 @@ void drbd_send_sr_reply(struct drbd_device *device, enum drbd_state_rv retcode)
        }
 }
 
-void conn_send_sr_reply(struct drbd_tconn *tconn, enum drbd_state_rv retcode)
+void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode)
 {
        struct drbd_socket *sock;
        struct p_req_state_reply *p;
-       enum drbd_packet cmd = tconn->agreed_pro_version < 100 ? P_STATE_CHG_REPLY : P_CONN_ST_CHG_REPLY;
+       enum drbd_packet cmd = connection->agreed_pro_version < 100 ? P_STATE_CHG_REPLY : P_CONN_ST_CHG_REPLY;
 
-       sock = &tconn->meta;
-       p = conn_prepare_command(tconn, sock);
+       sock = &connection->meta;
+       p = conn_prepare_command(connection, sock);
        if (p) {
                p->retcode = cpu_to_be32(retcode);
-               conn_send_command(tconn, sock, cmd, sizeof(*p), NULL, 0);
+               conn_send_command(connection, sock, cmd, sizeof(*p), NULL, 0);
        }
 }
 
@@ -1081,9 +1083,9 @@ static int fill_bitmap_rle_bits(struct drbd_device *device,
 
        /* may we use this feature? */
        rcu_read_lock();
-       use_rle = rcu_dereference(device->tconn->net_conf)->use_rle;
+       use_rle = rcu_dereference(first_peer_device(device)->connection->net_conf)->use_rle;
        rcu_read_unlock();
-       if (!use_rle || device->tconn->agreed_pro_version < 90)
+       if (!use_rle || first_peer_device(device)->connection->agreed_pro_version < 90)
                return 0;
 
        if (c->bit_offset >= c->bm_bits)
@@ -1124,7 +1126,7 @@ static int fill_bitmap_rle_bits(struct drbd_device *device,
                /* paranoia: catch zero runlength.
                 * can only happen if bitmap is modified while we scan it. */
                if (rl == 0) {
-                       dev_err(DEV, "unexpected zero runlength while encoding bitmap "
+                       drbd_err(device, "unexpected zero runlength while encoding bitmap "
                            "t:%u bo:%lu\n", toggle, c->bit_offset);
                        return -1;
                }
@@ -1133,7 +1135,7 @@ static int fill_bitmap_rle_bits(struct drbd_device *device,
                if (bits == -ENOBUFS) /* buffer full */
                        break;
                if (bits <= 0) {
-                       dev_err(DEV, "error while encoding bitmap: %d\n", bits);
+                       drbd_err(device, "error while encoding bitmap: %d\n", bits);
                        return 0;
                }
 
@@ -1172,8 +1174,8 @@ static int fill_bitmap_rle_bits(struct drbd_device *device,
 static int
 send_bitmap_rle_or_plain(struct drbd_device *device, struct bm_xfer_ctx *c)
 {
-       struct drbd_socket *sock = &device->tconn->data;
-       unsigned int header_size = drbd_header_size(device->tconn);
+       struct drbd_socket *sock = &first_peer_device(device)->connection->data;
+       unsigned int header_size = drbd_header_size(first_peer_device(device)->connection);
        struct p_compressed_bm *p = sock->sbuf + header_size;
        int len, err;
 
@@ -1184,7 +1186,7 @@ send_bitmap_rle_or_plain(struct drbd_device *device, struct bm_xfer_ctx *c)
 
        if (len) {
                dcbp_set_code(p, RLE_VLI_Bits);
-               err = __send_command(device->tconn, device->vnr, sock,
+               err = __send_command(first_peer_device(device)->connection, device->vnr, sock,
                                     P_COMPRESSED_BITMAP, sizeof(*p) + len,
                                     NULL, 0);
                c->packets[0]++;
@@ -1205,7 +1207,7 @@ send_bitmap_rle_or_plain(struct drbd_device *device, struct bm_xfer_ctx *c)
                len = num_words * sizeof(*p);
                if (len)
                        drbd_bm_get_lel(device, c->word_offset, num_words, p);
-               err = __send_command(device->tconn, device->vnr, sock, P_BITMAP, len, NULL, 0);
+               err = __send_command(first_peer_device(device)->connection, device->vnr, sock, P_BITMAP, len, NULL, 0);
                c->word_offset += num_words;
                c->bit_offset = c->word_offset * BITS_PER_LONG;
 
@@ -1236,13 +1238,13 @@ static int _drbd_send_bitmap(struct drbd_device *device)
 
        if (get_ldev(device)) {
                if (drbd_md_test_flag(device->ldev, MDF_FULL_SYNC)) {
-                       dev_info(DEV, "Writing the whole bitmap, MDF_FullSync was set.\n");
+                       drbd_info(device, "Writing the whole bitmap, MDF_FullSync was set.\n");
                        drbd_bm_set_all(device);
                        if (drbd_bm_write(device)) {
                                /* write_bm did fail! Leave full sync flag set in Meta P_DATA
                                 * but otherwise process as per normal - need to tell other
                                 * side that a full resync is required! */
-                               dev_err(DEV, "Failed to write bitmap to disk!\n");
+                               drbd_err(device, "Failed to write bitmap to disk!\n");
                        } else {
                                drbd_md_clear_flag(device, MDF_FULL_SYNC);
                                drbd_md_sync(device);
@@ -1265,7 +1267,7 @@ static int _drbd_send_bitmap(struct drbd_device *device)
 
 int drbd_send_bitmap(struct drbd_device *device)
 {
-       struct drbd_socket *sock = &device->tconn->data;
+       struct drbd_socket *sock = &first_peer_device(device)->connection->data;
        int err = -1;
 
        mutex_lock(&sock->mutex);
@@ -1275,21 +1277,21 @@ int drbd_send_bitmap(struct drbd_device *device)
        return err;
 }
 
-void drbd_send_b_ack(struct drbd_tconn *tconn, u32 barrier_nr, u32 set_size)
+void drbd_send_b_ack(struct drbd_connection *connection, u32 barrier_nr, u32 set_size)
 {
        struct drbd_socket *sock;
        struct p_barrier_ack *p;
 
-       if (tconn->cstate < C_WF_REPORT_PARAMS)
+       if (connection->cstate < C_WF_REPORT_PARAMS)
                return;
 
-       sock = &tconn->meta;
-       p = conn_prepare_command(tconn, sock);
+       sock = &connection->meta;
+       p = conn_prepare_command(connection, sock);
        if (!p)
                return;
        p->barrier = barrier_nr;
        p->set_size = cpu_to_be32(set_size);
-       conn_send_command(tconn, sock, P_BARRIER_ACK, sizeof(*p), NULL, 0);
+       conn_send_command(connection, sock, P_BARRIER_ACK, sizeof(*p), NULL, 0);
 }
 
 /**
@@ -1309,7 +1311,7 @@ static int _drbd_send_ack(struct drbd_device *device, enum drbd_packet cmd,
        if (device->state.conn < C_CONNECTED)
                return -EIO;
 
-       sock = &device->tconn->meta;
+       sock = &first_peer_device(device)->connection->meta;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -1326,8 +1328,8 @@ static int _drbd_send_ack(struct drbd_device *device, enum drbd_packet cmd,
 void drbd_send_ack_dp(struct drbd_device *device, enum drbd_packet cmd,
                      struct p_data *dp, int data_size)
 {
-       if (device->tconn->peer_integrity_tfm)
-               data_size -= crypto_hash_digestsize(device->tconn->peer_integrity_tfm);
+       if (first_peer_device(device)->connection->peer_integrity_tfm)
+               data_size -= crypto_hash_digestsize(first_peer_device(device)->connection->peer_integrity_tfm);
        _drbd_send_ack(device, cmd, dp->sector, cpu_to_be32(data_size),
                       dp->block_id);
 }
@@ -1370,7 +1372,7 @@ int drbd_send_drequest(struct drbd_device *device, int cmd,
        struct drbd_socket *sock;
        struct p_block_req *p;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -1388,7 +1390,7 @@ int drbd_send_drequest_csum(struct drbd_device *device, sector_t sector, int siz
 
        /* FIXME: Put the digest into the preallocated socket buffer.  */
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -1404,7 +1406,7 @@ int drbd_send_ov_request(struct drbd_device *device, sector_t sector, int size)
        struct drbd_socket *sock;
        struct p_block_req *p;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -1418,34 +1420,34 @@ int drbd_send_ov_request(struct drbd_device *device, sector_t sector, int size)
  * returns false if we should retry,
  * true if we think connection is dead
  */
-static int we_should_drop_the_connection(struct drbd_tconn *tconn, struct socket *sock)
+static int we_should_drop_the_connection(struct drbd_connection *connection, struct socket *sock)
 {
        int drop_it;
        /* long elapsed = (long)(jiffies - device->last_received); */
 
-       drop_it =   tconn->meta.socket == sock
-               || !tconn->asender.task
-               || get_t_state(&tconn->asender) != RUNNING
-               || tconn->cstate < C_WF_REPORT_PARAMS;
+       drop_it =   connection->meta.socket == sock
+               || !connection->asender.task
+               || get_t_state(&connection->asender) != RUNNING
+               || connection->cstate < C_WF_REPORT_PARAMS;
 
        if (drop_it)
                return true;
 
-       drop_it = !--tconn->ko_count;
+       drop_it = !--connection->ko_count;
        if (!drop_it) {
-               conn_err(tconn, "[%s/%d] sock_sendmsg time expired, ko = %u\n",
-                        current->comm, current->pid, tconn->ko_count);
-               request_ping(tconn);
+               drbd_err(connection, "[%s/%d] sock_sendmsg time expired, ko = %u\n",
+                        current->comm, current->pid, connection->ko_count);
+               request_ping(connection);
        }
 
        return drop_it; /* && (device->state == R_PRIMARY) */;
 }
 
-static void drbd_update_congested(struct drbd_tconn *tconn)
+static void drbd_update_congested(struct drbd_connection *connection)
 {
-       struct sock *sk = tconn->data.socket->sk;
+       struct sock *sk = connection->data.socket->sk;
        if (sk->sk_wmem_queued > sk->sk_sndbuf * 4 / 5)
-               set_bit(NET_CONGESTED, &tconn->flags);
+               set_bit(NET_CONGESTED, &connection->flags);
 }
 
 /* The idea of sendpage seems to be to put some kind of reference
@@ -1476,9 +1478,9 @@ static int _drbd_no_send_page(struct drbd_device *device, struct page *page,
        void *addr;
        int err;
 
-       socket = device->tconn->data.socket;
+       socket = first_peer_device(device)->connection->data.socket;
        addr = kmap(page) + offset;
-       err = drbd_send_all(device->tconn, socket, addr, size, msg_flags);
+       err = drbd_send_all(first_peer_device(device)->connection, socket, addr, size, msg_flags);
        kunmap(page);
        if (!err)
                device->send_cnt += size >> 9;
@@ -1488,7 +1490,7 @@ static int _drbd_no_send_page(struct drbd_device *device, struct page *page,
 static int _drbd_send_page(struct drbd_device *device, struct page *page,
                    int offset, size_t size, unsigned msg_flags)
 {
-       struct socket *socket = device->tconn->data.socket;
+       struct socket *socket = first_peer_device(device)->connection->data.socket;
        mm_segment_t oldfs = get_fs();
        int len = size;
        int err = -EIO;
@@ -1503,7 +1505,7 @@ static int _drbd_send_page(struct drbd_device *device, struct page *page,
                return _drbd_no_send_page(device, page, offset, size, msg_flags);
 
        msg_flags |= MSG_NOSIGNAL;
-       drbd_update_congested(device->tconn);
+       drbd_update_congested(first_peer_device(device)->connection);
        set_fs(KERNEL_DS);
        do {
                int sent;
@@ -1511,11 +1513,11 @@ static int _drbd_send_page(struct drbd_device *device, struct page *page,
                sent = socket->ops->sendpage(socket, page, offset, len, msg_flags);
                if (sent <= 0) {
                        if (sent == -EAGAIN) {
-                               if (we_should_drop_the_connection(device->tconn, socket))
+                               if (we_should_drop_the_connection(first_peer_device(device)->connection, socket))
                                        break;
                                continue;
                        }
-                       dev_warn(DEV, "%s: size=%d len=%d sent=%d\n",
+                       drbd_warn(device, "%s: size=%d len=%d sent=%d\n",
                             __func__, (int)size, len, sent);
                        if (sent < 0)
                                err = sent;
@@ -1525,7 +1527,7 @@ static int _drbd_send_page(struct drbd_device *device, struct page *page,
                offset += sent;
        } while (len > 0 /* THINK && device->cstate >= C_CONNECTED*/);
        set_fs(oldfs);
-       clear_bit(NET_CONGESTED, &device->tconn->flags);
+       clear_bit(NET_CONGESTED, &first_peer_device(device)->connection->flags);
 
        if (len == 0) {
                err = 0;
@@ -1593,7 +1595,7 @@ static int _drbd_send_zc_ee(struct drbd_device *device,
 
 static u32 bio_flags_to_wire(struct drbd_device *device, unsigned long bi_rw)
 {
-       if (device->tconn->agreed_pro_version >= 95)
+       if (first_peer_device(device)->connection->agreed_pro_version >= 95)
                return  (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
                        (bi_rw & REQ_FUA ? DP_FUA : 0) |
                        (bi_rw & REQ_FLUSH ? DP_FLUSH : 0) |
@@ -1613,9 +1615,10 @@ int drbd_send_dblock(struct drbd_device *device, struct drbd_request *req)
        int dgs;
        int err;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
-       dgs = device->tconn->integrity_tfm ? crypto_hash_digestsize(device->tconn->integrity_tfm) : 0;
+       dgs = first_peer_device(device)->connection->integrity_tfm ?
+             crypto_hash_digestsize(first_peer_device(device)->connection->integrity_tfm) : 0;
 
        if (!p)
                return -EIO;
@@ -1626,7 +1629,7 @@ int drbd_send_dblock(struct drbd_device *device, struct drbd_request *req)
        if (device->state.conn >= C_SYNC_SOURCE &&
            device->state.conn <= C_PAUSED_SYNC_T)
                dp_flags |= DP_MAY_SET_IN_SYNC;
-       if (device->tconn->agreed_pro_version >= 100) {
+       if (first_peer_device(device)->connection->agreed_pro_version >= 100) {
                if (req->rq_state & RQ_EXP_RECEIVE_ACK)
                        dp_flags |= DP_SEND_RECEIVE_ACK;
                if (req->rq_state & RQ_EXP_WRITE_ACK)
@@ -1634,8 +1637,8 @@ int drbd_send_dblock(struct drbd_device *device, struct drbd_request *req)
        }
        p->dp_flags = cpu_to_be32(dp_flags);
        if (dgs)
-               drbd_csum_bio(device, device->tconn->integrity_tfm, req->master_bio, p + 1);
-       err = __send_command(device->tconn, device->vnr, sock, P_DATA, sizeof(*p) + dgs, NULL, req->i.size);
+               drbd_csum_bio(device, first_peer_device(device)->connection->integrity_tfm, req->master_bio, p + 1);
+       err = __send_command(first_peer_device(device)->connection, device->vnr, sock, P_DATA, sizeof(*p) + dgs, NULL, req->i.size);
        if (!err) {
                /* For protocol A, we have to memcpy the payload into
                 * socket buffers, as we may complete right away
@@ -1658,9 +1661,9 @@ int drbd_send_dblock(struct drbd_device *device, struct drbd_request *req)
                        /* 64 byte, 512 bit, is the largest digest size
                         * currently supported in kernel crypto. */
                        unsigned char digest[64];
-                       drbd_csum_bio(device, device->tconn->integrity_tfm, req->master_bio, digest);
+                       drbd_csum_bio(device, first_peer_device(device)->connection->integrity_tfm, req->master_bio, digest);
                        if (memcmp(p + 1, digest, dgs)) {
-                               dev_warn(DEV,
+                               drbd_warn(device,
                                        "Digest mismatch, buffer modified by upper layers during write: %llus +%u\n",
                                        (unsigned long long)req->i.sector, req->i.size);
                        }
@@ -1685,10 +1688,11 @@ int drbd_send_block(struct drbd_device *device, enum drbd_packet cmd,
        int err;
        int dgs;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
 
-       dgs = device->tconn->integrity_tfm ? crypto_hash_digestsize(device->tconn->integrity_tfm) : 0;
+       dgs = first_peer_device(device)->connection->integrity_tfm ?
+             crypto_hash_digestsize(first_peer_device(device)->connection->integrity_tfm) : 0;
 
        if (!p)
                return -EIO;
@@ -1697,8 +1701,8 @@ int drbd_send_block(struct drbd_device *device, enum drbd_packet cmd,
        p->seq_num = 0;  /* unused */
        p->dp_flags = 0;
        if (dgs)
-               drbd_csum_ee(device, device->tconn->integrity_tfm, peer_req, p + 1);
-       err = __send_command(device->tconn, device->vnr, sock, cmd, sizeof(*p) + dgs, NULL, peer_req->i.size);
+               drbd_csum_ee(device, first_peer_device(device)->connection->integrity_tfm, peer_req, p + 1);
+       err = __send_command(first_peer_device(device)->connection, device->vnr, sock, cmd, sizeof(*p) + dgs, NULL, peer_req->i.size);
        if (!err)
                err = _drbd_send_zc_ee(device, peer_req);
        mutex_unlock(&sock->mutex);  /* locked by drbd_prepare_command() */
@@ -1711,7 +1715,7 @@ int drbd_send_out_of_sync(struct drbd_device *device, struct drbd_request *req)
        struct drbd_socket *sock;
        struct p_block_desc *p;
 
-       sock = &device->tconn->data;
+       sock = &first_peer_device(device)->connection->data;
        p = drbd_prepare_command(device, sock);
        if (!p)
                return -EIO;
@@ -1736,7 +1740,7 @@ int drbd_send_out_of_sync(struct drbd_device *device, struct drbd_request *req)
 /*
  * you must have down()ed the appropriate [m]sock_mutex elsewhere!
  */
-int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
+int drbd_send(struct drbd_connection *connection, struct socket *sock,
              void *buf, size_t size, unsigned msg_flags)
 {
        struct kvec iov;
@@ -1757,11 +1761,11 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
        msg.msg_controllen = 0;
        msg.msg_flags      = msg_flags | MSG_NOSIGNAL;
 
-       if (sock == tconn->data.socket) {
+       if (sock == connection->data.socket) {
                rcu_read_lock();
-               tconn->ko_count = rcu_dereference(tconn->net_conf)->ko_count;
+               connection->ko_count = rcu_dereference(connection->net_conf)->ko_count;
                rcu_read_unlock();
-               drbd_update_congested(tconn);
+               drbd_update_congested(connection);
        }
        do {
                /* STRANGE
@@ -1775,7 +1779,7 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
  */
                rv = kernel_sendmsg(sock, &msg, &iov, 1, size);
                if (rv == -EAGAIN) {
-                       if (we_should_drop_the_connection(tconn, sock))
+                       if (we_should_drop_the_connection(connection, sock))
                                break;
                        else
                                continue;
@@ -1791,17 +1795,17 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
                iov.iov_len  -= rv;
        } while (sent < size);
 
-       if (sock == tconn->data.socket)
-               clear_bit(NET_CONGESTED, &tconn->flags);
+       if (sock == connection->data.socket)
+               clear_bit(NET_CONGESTED, &connection->flags);
 
        if (rv <= 0) {
                if (rv != -EAGAIN) {
-                       conn_err(tconn, "%s_sendmsg returned %d\n",
-                                sock == tconn->meta.socket ? "msock" : "sock",
+                       drbd_err(connection, "%s_sendmsg returned %d\n",
+                                sock == connection->meta.socket ? "msock" : "sock",
                                 rv);
-                       conn_request_state(tconn, NS(conn, C_BROKEN_PIPE), CS_HARD);
+                       conn_request_state(connection, NS(conn, C_BROKEN_PIPE), CS_HARD);
                } else
-                       conn_request_state(tconn, NS(conn, C_TIMEOUT), CS_HARD);
+                       conn_request_state(connection, NS(conn, C_TIMEOUT), CS_HARD);
        }
 
        return sent;
@@ -1812,12 +1816,12 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
  *
  * Returns 0 upon success and a negative error value otherwise.
  */
-int drbd_send_all(struct drbd_tconn *tconn, struct socket *sock, void *buffer,
+int drbd_send_all(struct drbd_connection *connection, struct socket *sock, void *buffer,
                  size_t size, unsigned msg_flags)
 {
        int err;
 
-       err = drbd_send(tconn, sock, buffer, size, msg_flags);
+       err = drbd_send(connection, sock, buffer, size, msg_flags);
        if (err < 0)
                return err;
        if (err != size)
@@ -1832,7 +1836,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
        int rv = 0;
 
        mutex_lock(&drbd_main_mutex);
-       spin_lock_irqsave(&device->tconn->req_lock, flags);
+       spin_lock_irqsave(&first_peer_device(device)->connection->req_lock, flags);
        /* to have a stable device->state.role
         * and no race with updating open_cnt */
 
@@ -1845,7 +1849,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
 
        if (!rv)
                device->open_cnt++;
-       spin_unlock_irqrestore(&device->tconn->req_lock, flags);
+       spin_unlock_irqrestore(&first_peer_device(device)->connection->req_lock, flags);
        mutex_unlock(&drbd_main_mutex);
 
        return rv;
@@ -1950,9 +1954,9 @@ void drbd_init_set_defaults(struct drbd_device *device)
 void drbd_device_cleanup(struct drbd_device *device)
 {
        int i;
-       if (device->tconn->receiver.t_state != NONE)
-               dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
-                               device->tconn->receiver.t_state);
+       if (first_peer_device(device)->connection->receiver.t_state != NONE)
+               drbd_err(device, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
+                               first_peer_device(device)->connection->receiver.t_state);
 
        device->al_writ_cnt  =
        device->bm_writ_cnt  =
@@ -1970,7 +1974,7 @@ void drbd_device_cleanup(struct drbd_device *device)
                device->rs_mark_left[i] = 0;
                device->rs_mark_time[i] = 0;
        }
-       D_ASSERT(device->tconn->net_conf == NULL);
+       D_ASSERT(device, first_peer_device(device)->connection->net_conf == NULL);
 
        drbd_set_my_capacity(device, 0);
        if (device->bitmap) {
@@ -1984,16 +1988,16 @@ void drbd_device_cleanup(struct drbd_device *device)
 
        clear_bit(AL_SUSPENDED, &device->flags);
 
-       D_ASSERT(list_empty(&device->active_ee));
-       D_ASSERT(list_empty(&device->sync_ee));
-       D_ASSERT(list_empty(&device->done_ee));
-       D_ASSERT(list_empty(&device->read_ee));
-       D_ASSERT(list_empty(&device->net_ee));
-       D_ASSERT(list_empty(&device->resync_reads));
-       D_ASSERT(list_empty(&device->tconn->sender_work.q));
-       D_ASSERT(list_empty(&device->resync_work.list));
-       D_ASSERT(list_empty(&device->unplug_work.list));
-       D_ASSERT(list_empty(&device->go_diskless.list));
+       D_ASSERT(device, list_empty(&device->active_ee));
+       D_ASSERT(device, list_empty(&device->sync_ee));
+       D_ASSERT(device, list_empty(&device->done_ee));
+       D_ASSERT(device, list_empty(&device->read_ee));
+       D_ASSERT(device, list_empty(&device->net_ee));
+       D_ASSERT(device, list_empty(&device->resync_reads));
+       D_ASSERT(device, list_empty(&first_peer_device(device)->connection->sender_work.q));
+       D_ASSERT(device, list_empty(&device->resync_work.list));
+       D_ASSERT(device, list_empty(&device->unplug_work.list));
+       D_ASSERT(device, list_empty(&device->go_diskless.list));
 
        drbd_set_defaults(device);
 }
@@ -2010,7 +2014,7 @@ static void drbd_destroy_mempools(void)
                drbd_pp_vacant--;
        }
 
-       /* D_ASSERT(atomic_read(&drbd_pp_vacant)==0); */
+       /* D_ASSERT(device, atomic_read(&drbd_pp_vacant)==0); */
 
        if (drbd_md_io_bio_set)
                bioset_free(drbd_md_io_bio_set);
@@ -2136,35 +2140,36 @@ static void drbd_release_all_peer_reqs(struct drbd_device *device)
 
        rr = drbd_free_peer_reqs(device, &device->active_ee);
        if (rr)
-               dev_err(DEV, "%d EEs in active list found!\n", rr);
+               drbd_err(device, "%d EEs in active list found!\n", rr);
 
        rr = drbd_free_peer_reqs(device, &device->sync_ee);
        if (rr)
-               dev_err(DEV, "%d EEs in sync list found!\n", rr);
+               drbd_err(device, "%d EEs in sync list found!\n", rr);
 
        rr = drbd_free_peer_reqs(device, &device->read_ee);
        if (rr)
-               dev_err(DEV, "%d EEs in read list found!\n", rr);
+               drbd_err(device, "%d EEs in read list found!\n", rr);
 
        rr = drbd_free_peer_reqs(device, &device->done_ee);
        if (rr)
-               dev_err(DEV, "%d EEs in done list found!\n", rr);
+               drbd_err(device, "%d EEs in done list found!\n", rr);
 
        rr = drbd_free_peer_reqs(device, &device->net_ee);
        if (rr)
-               dev_err(DEV, "%d EEs in net list found!\n", rr);
+               drbd_err(device, "%d EEs in net list found!\n", rr);
 }
 
 /* caution. no locking. */
-void drbd_minor_destroy(struct kref *kref)
+void drbd_destroy_device(struct kref *kref)
 {
        struct drbd_device *device = container_of(kref, struct drbd_device, kref);
-       struct drbd_tconn *tconn = device->tconn;
+       struct drbd_resource *resource = device->resource;
+       struct drbd_connection *connection;
 
        del_timer_sync(&device->request_timer);
 
        /* paranoia asserts */
-       D_ASSERT(device->open_cnt == 0);
+       D_ASSERT(device, device->open_cnt == 0);
        /* end paranoia asserts */
 
        /* cleanup stuff that may have been allocated during
@@ -2190,9 +2195,12 @@ void drbd_minor_destroy(struct kref *kref)
        put_disk(device->vdisk);
        blk_cleanup_queue(device->rq_queue);
        kfree(device->rs_plan_s);
+       kfree(first_peer_device(device));
        kfree(device);
 
-       kref_put(&tconn->kref, &conn_destroy);
+       for_each_connection(connection, resource)
+               kref_put(&connection->kref, drbd_destroy_connection);
+       kref_put(&resource->kref, drbd_destroy_resource);
 }
 
 /* One global retry thread, if we need to push back some bio and have it
@@ -2229,7 +2237,7 @@ static void do_retry(struct work_struct *ws)
                                (req->rq_state & RQ_LOCAL_ABORTED) != 0);
 
                if (!expected)
-                       dev_err(DEV, "req=%p completion_ref=%d rq_state=%x\n",
+                       drbd_err(device, "req=%p completion_ref=%d rq_state=%x\n",
                                req, atomic_read(&req->completion_ref),
                                req->rq_state);
 
@@ -2273,12 +2281,32 @@ void drbd_restart_request(struct drbd_request *req)
        queue_work(retry.wq, &retry.worker);
 }
 
+void drbd_destroy_resource(struct kref *kref)
+{
+       struct drbd_resource *resource =
+               container_of(kref, struct drbd_resource, kref);
+
+       idr_destroy(&resource->devices);
+       kfree(resource->name);
+       kfree(resource);
+}
+
+void drbd_free_resource(struct drbd_resource *resource)
+{
+       struct drbd_connection *connection, *tmp;
+
+       for_each_connection_safe(connection, tmp, resource) {
+               list_del(&connection->connections);
+               kref_put(&connection->kref, drbd_destroy_connection);
+       }
+       kref_put(&resource->kref, drbd_destroy_resource);
+}
 
 static void drbd_cleanup(void)
 {
        unsigned int i;
        struct drbd_device *device;
-       struct drbd_tconn *tconn, *tmp;
+       struct drbd_resource *resource, *tmp;
 
        unregister_reboot_notifier(&drbd_notifier);
 
@@ -2298,26 +2326,19 @@ static void drbd_cleanup(void)
 
        drbd_genl_unregister();
 
-       idr_for_each_entry(&minors, device, i) {
-               idr_remove(&minors, device_to_minor(device));
-               idr_remove(&device->tconn->volumes, device->vnr);
-               destroy_workqueue(device->submit.wq);
-               del_gendisk(device->vdisk);
-               /* synchronize_rcu(); No other threads running at this point */
-               kref_put(&device->kref, &drbd_minor_destroy);
-       }
+       idr_for_each_entry(&drbd_devices, device, i)
+               drbd_delete_device(device);
 
        /* not _rcu since, no other updater anymore. Genl already unregistered */
-       list_for_each_entry_safe(tconn, tmp, &drbd_tconns, all_tconn) {
-               list_del(&tconn->all_tconn); /* not _rcu no proc, not other threads */
-               /* synchronize_rcu(); */
-               kref_put(&tconn->kref, &conn_destroy);
+       for_each_resource_safe(resource, tmp, &drbd_resources) {
+               list_del(&resource->resources);
+               drbd_free_resource(resource);
        }
 
        drbd_destroy_mempools();
        unregister_blkdev(DRBD_MAJOR, "drbd");
 
-       idr_destroy(&minors);
+       idr_destroy(&drbd_devices);
 
        printk(KERN_INFO "drbd: module cleanup done.\n");
 }
@@ -2343,7 +2364,7 @@ static int drbd_congested(void *congested_data, int bdi_bits)
                goto out;
        }
 
-       if (test_bit(CALLBACK_PENDING, &device->tconn->flags)) {
+       if (test_bit(CALLBACK_PENDING, &first_peer_device(device)->connection->flags)) {
                r |= (1 << BDI_async_congested);
                /* Without good local data, we would need to read from remote,
                 * and that would need the worker thread as well, which is
@@ -2367,7 +2388,8 @@ static int drbd_congested(void *congested_data, int bdi_bits)
                        reason = 'b';
        }
 
-       if (bdi_bits & (1 << BDI_async_congested) && test_bit(NET_CONGESTED, &device->tconn->flags)) {
+       if (bdi_bits & (1 << BDI_async_congested) &&
+           test_bit(NET_CONGESTED, &first_peer_device(device)->connection->flags)) {
                r |= (1 << BDI_async_congested);
                reason = reason == 'b' ? 'a' : 'n';
        }
@@ -2384,45 +2406,48 @@ static void drbd_init_workqueue(struct drbd_work_queue* wq)
        init_waitqueue_head(&wq->q_wait);
 }
 
-struct drbd_tconn *conn_get_by_name(const char *name)
+struct drbd_resource *drbd_find_resource(const char *name)
 {
-       struct drbd_tconn *tconn;
+       struct drbd_resource *resource;
 
        if (!name || !name[0])
                return NULL;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(tconn, &drbd_tconns, all_tconn) {
-               if (!strcmp(tconn->name, name)) {
-                       kref_get(&tconn->kref);
+       for_each_resource_rcu(resource, &drbd_resources) {
+               if (!strcmp(resource->name, name)) {
+                       kref_get(&resource->kref);
                        goto found;
                }
        }
-       tconn = NULL;
+       resource = NULL;
 found:
        rcu_read_unlock();
-       return tconn;
+       return resource;
 }
 
-struct drbd_tconn *conn_get_by_addrs(void *my_addr, int my_addr_len,
+struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
                                     void *peer_addr, int peer_addr_len)
 {
-       struct drbd_tconn *tconn;
+       struct drbd_resource *resource;
+       struct drbd_connection *connection;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(tconn, &drbd_tconns, all_tconn) {
-               if (tconn->my_addr_len == my_addr_len &&
-                   tconn->peer_addr_len == peer_addr_len &&
-                   !memcmp(&tconn->my_addr, my_addr, my_addr_len) &&
-                   !memcmp(&tconn->peer_addr, peer_addr, peer_addr_len)) {
-                       kref_get(&tconn->kref);
-                       goto found;
+       for_each_resource_rcu(resource, &drbd_resources) {
+               for_each_connection_rcu(connection, resource) {
+                       if (connection->my_addr_len == my_addr_len &&
+                           connection->peer_addr_len == peer_addr_len &&
+                           !memcmp(&connection->my_addr, my_addr, my_addr_len) &&
+                           !memcmp(&connection->peer_addr, peer_addr, peer_addr_len)) {
+                               kref_get(&connection->kref);
+                               goto found;
+                       }
                }
        }
-       tconn = NULL;
+       connection = NULL;
 found:
        rcu_read_unlock();
-       return tconn;
+       return connection;
 }
 
 static int drbd_alloc_socket(struct drbd_socket *socket)
@@ -2442,29 +2467,30 @@ static void drbd_free_socket(struct drbd_socket *socket)
        free_page((unsigned long) socket->rbuf);
 }
 
-void conn_free_crypto(struct drbd_tconn *tconn)
+void conn_free_crypto(struct drbd_connection *connection)
 {
-       drbd_free_sock(tconn);
+       drbd_free_sock(connection);
 
-       crypto_free_hash(tconn->csums_tfm);
-       crypto_free_hash(tconn->verify_tfm);
-       crypto_free_hash(tconn->cram_hmac_tfm);
-       crypto_free_hash(tconn->integrity_tfm);
-       crypto_free_hash(tconn->peer_integrity_tfm);
-       kfree(tconn->int_dig_in);
-       kfree(tconn->int_dig_vv);
+       crypto_free_hash(connection->csums_tfm);
+       crypto_free_hash(connection->verify_tfm);
+       crypto_free_hash(connection->cram_hmac_tfm);
+       crypto_free_hash(connection->integrity_tfm);
+       crypto_free_hash(connection->peer_integrity_tfm);
+       kfree(connection->int_dig_in);
+       kfree(connection->int_dig_vv);
 
-       tconn->csums_tfm = NULL;
-       tconn->verify_tfm = NULL;
-       tconn->cram_hmac_tfm = NULL;
-       tconn->integrity_tfm = NULL;
-       tconn->peer_integrity_tfm = NULL;
-       tconn->int_dig_in = NULL;
-       tconn->int_dig_vv = NULL;
+       connection->csums_tfm = NULL;
+       connection->verify_tfm = NULL;
+       connection->cram_hmac_tfm = NULL;
+       connection->integrity_tfm = NULL;
+       connection->peer_integrity_tfm = NULL;
+       connection->int_dig_in = NULL;
+       connection->int_dig_vv = NULL;
 }
 
-int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts)
+int set_resource_options(struct drbd_resource *resource, struct res_opts *res_opts)
 {
+       struct drbd_connection *connection;
        cpumask_var_t new_cpu_mask;
        int err;
 
@@ -2481,18 +2507,20 @@ int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts)
                err = bitmap_parse(res_opts->cpu_mask, 32,
                                   cpumask_bits(new_cpu_mask), nr_cpu_ids);
                if (err) {
-                       conn_warn(tconn, "bitmap_parse() failed with %d\n", err);
+                       drbd_warn(resource, "bitmap_parse() failed with %d\n", err);
                        /* retcode = ERR_CPU_MASK_PARSE; */
                        goto fail;
                }
        }
-       tconn->res_opts = *res_opts;
-       if (!cpumask_equal(tconn->cpu_mask, new_cpu_mask)) {
-               cpumask_copy(tconn->cpu_mask, new_cpu_mask);
-               drbd_calc_cpu_mask(tconn);
-               tconn->receiver.reset_cpu_mask = 1;
-               tconn->asender.reset_cpu_mask = 1;
-               tconn->worker.reset_cpu_mask = 1;
+       resource->res_opts = *res_opts;
+       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->asender.reset_cpu_mask = 1;
+                       connection->worker.reset_cpu_mask = 1;
+               }
        }
        err = 0;
 
@@ -2502,93 +2530,118 @@ fail:
 
 }
 
-/* caller must be under genl_lock() */
-struct drbd_tconn *conn_create(const char *name, struct res_opts *res_opts)
+struct drbd_resource *drbd_create_resource(const char *name)
 {
-       struct drbd_tconn *tconn;
+       struct drbd_resource *resource;
 
-       tconn = kzalloc(sizeof(struct drbd_tconn), GFP_KERNEL);
-       if (!tconn)
+       resource = kmalloc(sizeof(struct drbd_resource), GFP_KERNEL);
+       if (!resource)
+               return NULL;
+       resource->name = kstrdup(name, GFP_KERNEL);
+       if (!resource->name) {
+               kfree(resource);
                return NULL;
+       }
+       kref_init(&resource->kref);
+       idr_init(&resource->devices);
+       INIT_LIST_HEAD(&resource->connections);
+       list_add_tail_rcu(&resource->resources, &drbd_resources);
+       return resource;
+}
 
-       tconn->name = kstrdup(name, GFP_KERNEL);
-       if (!tconn->name)
-               goto fail;
+/* caller must be under genl_lock() */
+struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
+{
+       struct drbd_resource *resource;
+       struct drbd_connection *connection;
+
+       connection = kzalloc(sizeof(struct drbd_connection), GFP_KERNEL);
+       if (!connection)
+               return NULL;
 
-       if (drbd_alloc_socket(&tconn->data))
+       if (drbd_alloc_socket(&connection->data))
                goto fail;
-       if (drbd_alloc_socket(&tconn->meta))
+       if (drbd_alloc_socket(&connection->meta))
                goto fail;
 
-       if (!zalloc_cpumask_var(&tconn->cpu_mask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&connection->cpu_mask, GFP_KERNEL))
                goto fail;
 
-       if (set_resource_options(tconn, res_opts))
+       connection->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
+       if (!connection->current_epoch)
                goto fail;
 
-       tconn->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
-       if (!tconn->current_epoch)
-               goto fail;
+       INIT_LIST_HEAD(&connection->transfer_log);
+
+       INIT_LIST_HEAD(&connection->current_epoch->list);
+       connection->epochs = 1;
+       spin_lock_init(&connection->epoch_lock);
+       connection->write_ordering = WO_bdev_flush;
 
-       INIT_LIST_HEAD(&tconn->transfer_log);
+       connection->send.seen_any_write_yet = false;
+       connection->send.current_epoch_nr = 0;
+       connection->send.current_epoch_writes = 0;
 
-       INIT_LIST_HEAD(&tconn->current_epoch->list);
-       tconn->epochs = 1;
-       spin_lock_init(&tconn->epoch_lock);
-       tconn->write_ordering = WO_bdev_flush;
+       resource = drbd_create_resource(name);
+       if (!resource)
+               goto fail;
 
-       tconn->send.seen_any_write_yet = false;
-       tconn->send.current_epoch_nr = 0;
-       tconn->send.current_epoch_writes = 0;
+       connection->cstate = C_STANDALONE;
+       mutex_init(&connection->cstate_mutex);
+       spin_lock_init(&connection->req_lock);
+       mutex_init(&connection->conf_update);
+       init_waitqueue_head(&connection->ping_wait);
+       idr_init(&connection->peer_devices);
 
-       tconn->cstate = C_STANDALONE;
-       mutex_init(&tconn->cstate_mutex);
-       spin_lock_init(&tconn->req_lock);
-       mutex_init(&tconn->conf_update);
-       init_waitqueue_head(&tconn->ping_wait);
-       idr_init(&tconn->volumes);
+       drbd_init_workqueue(&connection->sender_work);
+       mutex_init(&connection->data.mutex);
+       mutex_init(&connection->meta.mutex);
 
-       drbd_init_workqueue(&tconn->sender_work);
-       mutex_init(&tconn->data.mutex);
-       mutex_init(&tconn->meta.mutex);
+       drbd_thread_init(connection, &connection->receiver, drbdd_init, "receiver");
+       drbd_thread_init(connection, &connection->worker, drbd_worker, "worker");
+       drbd_thread_init(connection, &connection->asender, drbd_asender, "asender");
 
-       drbd_thread_init(tconn, &tconn->receiver, drbdd_init, "receiver");
-       drbd_thread_init(tconn, &tconn->worker, drbd_worker, "worker");
-       drbd_thread_init(tconn, &tconn->asender, drbd_asender, "asender");
+       kref_init(&connection->kref);
 
-       kref_init(&tconn->kref);
-       list_add_tail_rcu(&tconn->all_tconn, &drbd_tconns);
+       connection->resource = resource;
 
-       return tconn;
+       if (set_resource_options(resource, res_opts))
+               goto fail_resource;
 
-fail:
-       kfree(tconn->current_epoch);
-       free_cpumask_var(tconn->cpu_mask);
-       drbd_free_socket(&tconn->meta);
-       drbd_free_socket(&tconn->data);
-       kfree(tconn->name);
-       kfree(tconn);
+       kref_get(&resource->kref);
+       list_add_tail_rcu(&connection->connections, &resource->connections);
+       return connection;
 
+fail_resource:
+       list_del(&resource->resources);
+       drbd_free_resource(resource);
+fail:
+       kfree(connection->current_epoch);
+       free_cpumask_var(connection->cpu_mask);
+       drbd_free_socket(&connection->meta);
+       drbd_free_socket(&connection->data);
+       kfree(connection);
        return NULL;
 }
 
-void conn_destroy(struct kref *kref)
+void drbd_destroy_connection(struct kref *kref)
 {
-       struct drbd_tconn *tconn = container_of(kref, struct drbd_tconn, kref);
+       struct drbd_connection *connection = container_of(kref, struct drbd_connection, kref);
+       struct drbd_resource *resource = connection->resource;
 
-       if (atomic_read(&tconn->current_epoch->epoch_size) !=  0)
-               conn_err(tconn, "epoch_size:%d\n", atomic_read(&tconn->current_epoch->epoch_size));
-       kfree(tconn->current_epoch);
+       if (atomic_read(&connection->current_epoch->epoch_size) !=  0)
+               drbd_err(connection, "epoch_size:%d\n", atomic_read(&connection->current_epoch->epoch_size));
+       kfree(connection->current_epoch);
 
-       idr_destroy(&tconn->volumes);
+       idr_destroy(&connection->peer_devices);
 
-       free_cpumask_var(tconn->cpu_mask);
-       drbd_free_socket(&tconn->meta);
-       drbd_free_socket(&tconn->data);
-       kfree(tconn->name);
-       kfree(tconn->int_dig_in);
-       kfree(tconn->int_dig_vv);
-       kfree(tconn);
+       free_cpumask_var(connection->cpu_mask);
+       drbd_free_socket(&connection->meta);
+       drbd_free_socket(&connection->data);
+       kfree(connection->int_dig_in);
+       kfree(connection->int_dig_vv);
+       kfree(connection);
+       kref_put(&resource->kref, drbd_destroy_resource);
 }
 
 static int init_submitter(struct drbd_device *device)
@@ -2606,13 +2659,14 @@ static int init_submitter(struct drbd_device *device)
        return 0;
 }
 
-enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, int vnr)
+enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned int minor, int vnr)
 {
+       struct drbd_connection *connection;
        struct drbd_device *device;
+       struct drbd_peer_device *peer_device, *tmp_peer_device;
        struct gendisk *disk;
        struct request_queue *q;
-       int vnr_got = vnr;
-       int minor_got = minor;
+       int id;
        enum drbd_ret_code err = ERR_NOMEM;
 
        device = minor_to_device(minor);
@@ -2623,10 +2677,10 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
        device = kzalloc(sizeof(struct drbd_device), GFP_KERNEL);
        if (!device)
                return ERR_NOMEM;
+       kref_init(&device->kref);
 
-       kref_get(&tconn->kref);
-       device->tconn = tconn;
-
+       kref_get(&resource->kref);
+       device->resource = resource;
        device->minor = minor;
        device->vnr = vnr;
 
@@ -2666,7 +2720,7 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
        blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
        blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
        blk_queue_merge_bvec(q, drbd_merge_bvec);
-       q->queue_lock = &device->tconn->req_lock; /* needed since we use */
+       q->queue_lock = &connection->req_lock;
 
        device->md_io_page = alloc_page(GFP_KERNEL);
        if (!device->md_io_page)
@@ -2677,23 +2731,47 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
        device->read_requests = RB_ROOT;
        device->write_requests = RB_ROOT;
 
-       minor_got = idr_alloc(&minors, device, minor, minor + 1, GFP_KERNEL);
-       if (minor_got < 0) {
-               if (minor_got == -ENOSPC) {
+       id = idr_alloc(&drbd_devices, device, minor, minor + 1, GFP_KERNEL);
+       if (id < 0) {
+               if (id == -ENOSPC) {
                        err = ERR_MINOR_EXISTS;
                        drbd_msg_put_info("requested minor exists already");
                }
                goto out_no_minor_idr;
        }
+       kref_get(&device->kref);
 
-       vnr_got = idr_alloc(&tconn->volumes, device, vnr, vnr + 1, GFP_KERNEL);
-       if (vnr_got < 0) {
-               if (vnr_got == -ENOSPC) {
-                       err = ERR_INVALID_REQUEST;
-                       drbd_msg_put_info("requested volume exists already");
+       id = idr_alloc(&resource->devices, device, vnr, vnr + 1, GFP_KERNEL);
+       if (id < 0) {
+               if (id == -ENOSPC) {
+                       err = ERR_MINOR_EXISTS;
+                       drbd_msg_put_info("requested minor exists already");
                }
                goto out_idr_remove_minor;
        }
+       kref_get(&device->kref);
+
+       INIT_LIST_HEAD(&device->peer_devices);
+       for_each_connection(connection, resource) {
+               peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL);
+               if (!peer_device)
+                       goto out_idr_remove_from_resource;
+               peer_device->connection = connection;
+               peer_device->device = device;
+
+               list_add(&peer_device->peer_devices, &device->peer_devices);
+               kref_get(&device->kref);
+
+               id = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL);
+               if (id < 0) {
+                       if (id == -ENOSPC) {
+                               err = ERR_INVALID_REQUEST;
+                               drbd_msg_put_info("requested volume exists already");
+                       }
+                       goto out_idr_remove_from_resource;
+               }
+               kref_get(&connection->kref);
+       }
 
        if (init_submitter(device)) {
                err = ERR_NOMEM;
@@ -2702,19 +2780,31 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
        }
 
        add_disk(disk);
-       kref_init(&device->kref); /* one ref for both idrs and the the add_disk */
 
        /* inherit the connection state */
-       device->state.conn = tconn->cstate;
+       device->state.conn = first_connection(resource)->cstate;
        if (device->state.conn == C_WF_REPORT_PARAMS)
                drbd_connected(device);
 
        return NO_ERROR;
 
 out_idr_remove_vol:
-       idr_remove(&tconn->volumes, vnr_got);
+       idr_remove(&connection->peer_devices, vnr);
+out_idr_remove_from_resource:
+       for_each_connection(connection, resource) {
+               peer_device = idr_find(&connection->peer_devices, vnr);
+               if (peer_device) {
+                       idr_remove(&connection->peer_devices, vnr);
+                       kref_put(&connection->kref, drbd_destroy_connection);
+               }
+       }
+       for_each_peer_device_safe(peer_device, tmp_peer_device, device) {
+               list_del(&peer_device->peer_devices);
+               kfree(peer_device);
+       }
+       idr_remove(&resource->devices, vnr);
 out_idr_remove_minor:
-       idr_remove(&minors, minor_got);
+       idr_remove(&drbd_devices, minor);
        synchronize_rcu();
 out_no_minor_idr:
        drbd_bm_cleanup(device);
@@ -2725,11 +2815,28 @@ out_no_io_page:
 out_no_disk:
        blk_cleanup_queue(q);
 out_no_q:
+       kref_put(&resource->kref, drbd_destroy_resource);
        kfree(device);
-       kref_put(&tconn->kref, &conn_destroy);
        return err;
 }
 
+void drbd_delete_device(struct drbd_device *device)
+{
+       struct drbd_resource *resource = device->resource;
+       struct drbd_connection *connection;
+       int refs = 3;
+
+       for_each_connection(connection, resource) {
+               idr_remove(&connection->peer_devices, device->vnr);
+               refs++;
+       }
+       idr_remove(&resource->devices, device->vnr);
+       idr_remove(&drbd_devices, device_to_minor(device));
+       del_gendisk(device->vdisk);
+       synchronize_rcu();
+       kref_sub(&device->kref, refs, drbd_destroy_device);
+}
+
 int __init drbd_init(void)
 {
        int err;
@@ -2760,10 +2867,10 @@ int __init drbd_init(void)
        init_waitqueue_head(&drbd_pp_wait);
 
        drbd_proc = NULL; /* play safe for drbd_cleanup */
-       idr_init(&minors);
+       idr_init(&drbd_devices);
 
        rwlock_init(&global_state_lock);
-       INIT_LIST_HEAD(&drbd_tconns);
+       INIT_LIST_HEAD(&drbd_resources);
 
        err = drbd_genl_register();
        if (err) {
@@ -2821,37 +2928,39 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
        kfree(ldev);
 }
 
-void drbd_free_sock(struct drbd_tconn *tconn)
+void drbd_free_sock(struct drbd_connection *connection)
 {
-       if (tconn->data.socket) {
-               mutex_lock(&tconn->data.mutex);
-               kernel_sock_shutdown(tconn->data.socket, SHUT_RDWR);
-               sock_release(tconn->data.socket);
-               tconn->data.socket = NULL;
-               mutex_unlock(&tconn->data.mutex);
+       if (connection->data.socket) {
+               mutex_lock(&connection->data.mutex);
+               kernel_sock_shutdown(connection->data.socket, SHUT_RDWR);
+               sock_release(connection->data.socket);
+               connection->data.socket = NULL;
+               mutex_unlock(&connection->data.mutex);
        }
-       if (tconn->meta.socket) {
-               mutex_lock(&tconn->meta.mutex);
-               kernel_sock_shutdown(tconn->meta.socket, SHUT_RDWR);
-               sock_release(tconn->meta.socket);
-               tconn->meta.socket = NULL;
-               mutex_unlock(&tconn->meta.mutex);
+       if (connection->meta.socket) {
+               mutex_lock(&connection->meta.mutex);
+               kernel_sock_shutdown(connection->meta.socket, SHUT_RDWR);
+               sock_release(connection->meta.socket);
+               connection->meta.socket = NULL;
+               mutex_unlock(&connection->meta.mutex);
        }
 }
 
 /* meta data management */
 
-void conn_md_sync(struct drbd_tconn *tconn)
+void conn_md_sync(struct drbd_connection *connection)
 {
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        int vnr;
 
        rcu_read_lock();
-       idr_for_each_entry(&tconn->volumes, device, vnr) {
+       idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+               struct drbd_device *device = peer_device->device;
+
                kref_get(&device->kref);
                rcu_read_unlock();
                drbd_md_sync(device);
-               kref_put(&device->kref, &drbd_minor_destroy);
+               kref_put(&device->kref, drbd_destroy_device);
                rcu_read_lock();
        }
        rcu_read_unlock();
@@ -2908,12 +3017,12 @@ void drbd_md_write(struct drbd_device *device, void *b)
        buffer->al_stripes = cpu_to_be32(device->ldev->md.al_stripes);
        buffer->al_stripe_size_4k = cpu_to_be32(device->ldev->md.al_stripe_size_4k);
 
-       D_ASSERT(drbd_md_ss(device->ldev) == device->ldev->md.md_offset);
+       D_ASSERT(device, drbd_md_ss(device->ldev) == device->ldev->md.md_offset);
        sector = device->ldev->md.md_offset;
 
        if (drbd_md_sync_page_io(device, device->ldev, sector, WRITE)) {
                /* this was a try anyways ... */
-               dev_err(DEV, "meta data update failed!\n");
+               drbd_err(device, "meta data update failed!\n");
                drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
        }
 }
@@ -2995,7 +3104,7 @@ static int check_activity_log_stripe_size(struct drbd_device *device,
 
        return 0;
 err:
-       dev_err(DEV, "invalid activity log striping: al_stripes=%u, al_stripe_size_4k=%u\n",
+       drbd_err(device, "invalid activity log striping: al_stripes=%u, al_stripe_size_4k=%u\n",
                        al_stripes, al_stripe_size_4k);
        return -EINVAL;
 }
@@ -3067,7 +3176,7 @@ static int check_offsets_and_sizes(struct drbd_device *device, struct drbd_backi
        return 0;
 
 err:
-       dev_err(DEV, "meta data offsets don't make sense: idx=%d "
+       drbd_err(device, "meta data offsets don't make sense: idx=%d "
                        "al_s=%u, al_sz4k=%u, al_offset=%d, bm_offset=%d, "
                        "md_size_sect=%u, la_size=%llu, md_capacity=%llu\n",
                        in_core->meta_dev_idx,
@@ -3112,7 +3221,7 @@ int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev)
        if (drbd_md_sync_page_io(device, bdev, bdev->md.md_offset, READ)) {
                /* NOTE: can't do normal error processing here as this is
                   called BEFORE disk is attached */
-               dev_err(DEV, "Error while reading metadata.\n");
+               drbd_err(device, "Error while reading metadata.\n");
                rv = ERR_IO_MD_DISK;
                goto err;
        }
@@ -3122,7 +3231,7 @@ int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev)
        if (magic == DRBD_MD_MAGIC_84_UNCLEAN ||
            (magic == DRBD_MD_MAGIC_08 && !(flags & MDF_AL_CLEAN))) {
                        /* btw: that's Activity Log clean, not "all" clean. */
-               dev_err(DEV, "Found unclean meta data. Did you \"drbdadm apply-al\"?\n");
+               drbd_err(device, "Found unclean meta data. Did you \"drbdadm apply-al\"?\n");
                rv = ERR_MD_UNCLEAN;
                goto err;
        }
@@ -3130,14 +3239,14 @@ int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev)
        rv = ERR_MD_INVALID;
        if (magic != DRBD_MD_MAGIC_08) {
                if (magic == DRBD_MD_MAGIC_07)
-                       dev_err(DEV, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
+                       drbd_err(device, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
                else
-                       dev_err(DEV, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
+                       drbd_err(device, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
                goto err;
        }
 
        if (be32_to_cpu(buffer->bm_bytes_per_bit) != BM_BLOCK_SIZE) {
-               dev_err(DEV, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
+               drbd_err(device, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
                    be32_to_cpu(buffer->bm_bytes_per_bit), BM_BLOCK_SIZE);
                goto err;
        }
@@ -3160,26 +3269,26 @@ int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev)
                goto err;
 
        if (be32_to_cpu(buffer->bm_offset) != bdev->md.bm_offset) {
-               dev_err(DEV, "unexpected bm_offset: %d (expected %d)\n",
+               drbd_err(device, "unexpected bm_offset: %d (expected %d)\n",
                    be32_to_cpu(buffer->bm_offset), bdev->md.bm_offset);
                goto err;
        }
        if (be32_to_cpu(buffer->md_size_sect) != bdev->md.md_size_sect) {
-               dev_err(DEV, "unexpected md_size: %u (expected %u)\n",
+               drbd_err(device, "unexpected md_size: %u (expected %u)\n",
                    be32_to_cpu(buffer->md_size_sect), bdev->md.md_size_sect);
                goto err;
        }
 
        rv = NO_ERROR;
 
-       spin_lock_irq(&device->tconn->req_lock);
+       spin_lock_irq(&first_peer_device(device)->connection->req_lock);
        if (device->state.conn < C_CONNECTED) {
                unsigned int peer;
                peer = be32_to_cpu(buffer->la_peer_max_bio_size);
                peer = max(peer, DRBD_MAX_BIO_SIZE_SAFE);
                device->peer_max_bio_size = peer;
        }
-       spin_unlock_irq(&device->tconn->req_lock);
+       spin_unlock_irq(&first_peer_device(device)->connection->req_lock);
 
  err:
        drbd_md_put_buffer(device);
@@ -3273,7 +3382,7 @@ void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
        bm_uuid = device->ldev->md.uuid[UI_BITMAP];
 
        if (bm_uuid)
-               dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
+               drbd_warn(device, "bm UUID was already set: %llX\n", bm_uuid);
 
        device->ldev->md.uuid[UI_BITMAP] = device->ldev->md.uuid[UI_CURRENT];
        __drbd_uuid_set(device, UI_CURRENT, val);
@@ -3298,7 +3407,7 @@ void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
        } else {
                unsigned long long bm_uuid = device->ldev->md.uuid[UI_BITMAP];
                if (bm_uuid)
-                       dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
+                       drbd_warn(device, "bm UUID was already set: %llX\n", bm_uuid);
 
                device->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
        }
@@ -3361,7 +3470,7 @@ static int w_bitmap_io(struct drbd_work *w, int unused)
        struct drbd_device *device = w->device;
        int rv = -EIO;
 
-       D_ASSERT(atomic_read(&device->ap_bio_cnt) == 0);
+       D_ASSERT(device, atomic_read(&device->ap_bio_cnt) == 0);
 
        if (get_ldev(device)) {
                drbd_bm_lock(device, work->why, work->flags);
@@ -3400,7 +3509,7 @@ static int w_go_diskless(struct drbd_work *w, int unused)
 {
        struct drbd_device *device = w->device;
 
-       D_ASSERT(device->state.disk == D_FAILED);
+       D_ASSERT(device, device->state.disk == D_FAILED);
        /* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
         * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
         * the protected members anymore, though, so once put_ldev reaches zero
@@ -3454,13 +3563,13 @@ void drbd_queue_bitmap_io(struct drbd_device *device,
                          void (*done)(struct drbd_device *, int),
                          char *why, enum bm_flag flags)
 {
-       D_ASSERT(current == device->tconn->worker.task);
+       D_ASSERT(device, current == first_peer_device(device)->connection->worker.task);
 
-       D_ASSERT(!test_bit(BITMAP_IO_QUEUED, &device->flags));
-       D_ASSERT(!test_bit(BITMAP_IO, &device->flags));
-       D_ASSERT(list_empty(&device->bm_io_work.w.list));
+       D_ASSERT(device, !test_bit(BITMAP_IO_QUEUED, &device->flags));
+       D_ASSERT(device, !test_bit(BITMAP_IO, &device->flags));
+       D_ASSERT(device, list_empty(&device->bm_io_work.w.list));
        if (device->bm_io_work.why)
-               dev_err(DEV, "FIXME going to queue '%s' but '%s' still pending?\n",
+               drbd_err(device, "FIXME going to queue '%s' but '%s' still pending?\n",
                        why, device->bm_io_work.why);
 
        device->bm_io_work.io_fn = io_fn;
@@ -3468,13 +3577,13 @@ void drbd_queue_bitmap_io(struct drbd_device *device,
        device->bm_io_work.why = why;
        device->bm_io_work.flags = flags;
 
-       spin_lock_irq(&device->tconn->req_lock);
+       spin_lock_irq(&first_peer_device(device)->connection->req_lock);
        set_bit(BITMAP_IO, &device->flags);
        if (atomic_read(&device->ap_bio_cnt) == 0) {
                if (!test_and_set_bit(BITMAP_IO_QUEUED, &device->flags))
-                       drbd_queue_work(&device->tconn->sender_work, &device->bm_io_work.w);
+                       drbd_queue_work(&first_peer_device(device)->connection->sender_work, &device->bm_io_work.w);
        }
-       spin_unlock_irq(&device->tconn->req_lock);
+       spin_unlock_irq(&first_peer_device(device)->connection->req_lock);
 }
 
 /**
@@ -3491,7 +3600,7 @@ int drbd_bitmap_io(struct drbd_device *device, int (*io_fn)(struct drbd_device *
 {
        int rv;
 
-       D_ASSERT(current != device->tconn->worker.task);
+       D_ASSERT(device, current != first_peer_device(device)->connection->worker.task);
 
        if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
                drbd_suspend_io(device);
@@ -3532,16 +3641,16 @@ static void md_sync_timer_fn(unsigned long data)
 
        /* must not double-queue! */
        if (list_empty(&device->md_sync_work.list))
-               drbd_queue_work_front(&device->tconn->sender_work, &device->md_sync_work);
+               drbd_queue_work_front(&first_peer_device(device)->connection->sender_work, &device->md_sync_work);
 }
 
 static int w_md_sync(struct drbd_work *w, int unused)
 {
        struct drbd_device *device = w->device;
 
-       dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
+       drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
 #ifdef DEBUG
-       dev_warn(DEV, "last md_mark_dirty: %s:%u\n",
+       drbd_warn(device, "last md_mark_dirty: %s:%u\n",
                device->last_md_mark_dirty.func, device->last_md_mark_dirty.line);
 #endif
        drbd_md_sync(device);
@@ -3631,7 +3740,7 @@ int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i)
        long timeout;
 
        rcu_read_lock();
-       nc = rcu_dereference(device->tconn->net_conf);
+       nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
        if (!nc) {
                rcu_read_unlock();
                return -ETIMEDOUT;
@@ -3642,10 +3751,10 @@ int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i)
        /* Indicate to wake up device->misc_wait on progress.  */
        i->waiting = true;
        prepare_to_wait(&device->misc_wait, &wait, TASK_INTERRUPTIBLE);
-       spin_unlock_irq(&device->tconn->req_lock);
+       spin_unlock_irq(&first_peer_device(device)->connection->req_lock);
        timeout = schedule_timeout(timeout);
        finish_wait(&device->misc_wait, &wait);
-       spin_lock_irq(&device->tconn->req_lock);
+       spin_lock_irq(&first_peer_device(device)->connection->req_lock);
        if (!timeout || device->state.conn < C_CONNECTED)
                return -ETIMEDOUT;
        if (signal_pending(current))
@@ -3715,7 +3824,7 @@ _drbd_insert_fault(struct drbd_device *device, unsigned int type)
                fault_count++;
 
                if (__ratelimit(&drbd_ratelimit_state))
-                       dev_warn(DEV, "***Simulating %s failure\n",
+                       drbd_warn(device, "***Simulating %s failure\n",
                                _drbd_fault_str(type));
        }
 
This page took 0.062723 seconds and 5 git commands to generate.