drbd: get_one_status(): Iterate over resource->devices instead of connection->peer_de...
[deliverable/linux.git] / drivers / block / drbd / drbd_nl.c
index ddff39182a23784ded047107f3a13fc22a71aa8f..6f11d85792631223264d03e5252afe7b6e00af2d 100644 (file)
@@ -104,6 +104,7 @@ static struct drbd_config_context {
        struct drbd_genlmsghdr *reply_dh;
        /* resolved from attributes, if possible */
        struct drbd_device *device;
+       struct drbd_resource *resource;
        struct drbd_connection *connection;
 } adm_ctx;
 
@@ -213,13 +214,19 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
 
        adm_ctx.minor = d_in->minor;
        adm_ctx.device = minor_to_device(d_in->minor);
-       adm_ctx.connection = conn_get_by_name(adm_ctx.resource_name);
+       if (adm_ctx.resource_name) {
+               adm_ctx.resource = drbd_find_resource(adm_ctx.resource_name);
+               if (adm_ctx.resource) {
+                       adm_ctx.connection = first_connection(adm_ctx.resource);
+                       kref_get(&adm_ctx.connection->kref);
+               }
+       }
 
        if (!adm_ctx.device && (flags & DRBD_ADM_NEED_MINOR)) {
                drbd_msg_put_info("unknown minor");
                return ERR_MINOR_INVALID;
        }
-       if (!adm_ctx.connection && (flags & DRBD_ADM_NEED_RESOURCE)) {
+       if (!adm_ctx.resource && (flags & DRBD_ADM_NEED_RESOURCE)) {
                drbd_msg_put_info("unknown resource");
                if (adm_ctx.resource_name)
                        return ERR_RES_NOT_KNOWN;
@@ -247,11 +254,11 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
        }
 
        /* some more paranoia, if the request was over-determined */
-       if (adm_ctx.device && adm_ctx.connection &&
-           first_peer_device(adm_ctx.device)->connection != adm_ctx.connection) {
-               pr_warning("request: minor=%u, resource=%s; but that minor belongs to connection %s\n",
-                               adm_ctx.minor, adm_ctx.resource_name,
-                               first_peer_device(adm_ctx.device)->connection->resource->name);
+       if (adm_ctx.device && adm_ctx.resource &&
+           adm_ctx.device->resource != adm_ctx.resource) {
+               pr_warning("request: minor=%u, resource=%s; but that minor belongs to resource %s\n",
+                               adm_ctx.minor, adm_ctx.resource->name,
+                               adm_ctx.device->resource->name);
                drbd_msg_put_info("minor exists in different resource");
                return ERR_INVALID_REQUEST;
        }
@@ -261,7 +268,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
                pr_warning("request: minor=%u, volume=%u; but that minor is volume %u in %s\n",
                                adm_ctx.minor, adm_ctx.volume,
                                adm_ctx.device->vnr,
-                               first_peer_device(adm_ctx.device)->connection->resource->name);
+                               adm_ctx.device->resource->name);
                drbd_msg_put_info("minor exists as different volume");
                return ERR_INVALID_REQUEST;
        }
@@ -280,6 +287,10 @@ static int drbd_adm_finish(struct genl_info *info, int retcode)
                kref_put(&adm_ctx.connection->kref, drbd_destroy_connection);
                adm_ctx.connection = NULL;
        }
+       if (adm_ctx.resource) {
+               kref_put(&adm_ctx.resource->kref, drbd_destroy_resource);
+               adm_ctx.resource = NULL;
+       }
 
        if (!adm_ctx.reply_skb)
                return -ENOMEM;
@@ -340,17 +351,17 @@ int drbd_khelper(struct drbd_device *device, char *cmd)
         * write out any unsynced meta data changes now */
        drbd_md_sync(device);
 
-       dev_info(DEV, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
+       drbd_info(device, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
        sib.sib_reason = SIB_HELPER_PRE;
        sib.helper_name = cmd;
        drbd_bcast_event(device, &sib);
        ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC);
        if (ret)
-               dev_warn(DEV, "helper command: %s %s %s exit code %u (0x%x)\n",
+               drbd_warn(device, "helper command: %s %s %s exit code %u (0x%x)\n",
                                usermode_helper, cmd, mb,
                                (ret >> 8) & 0xff, ret);
        else
-               dev_info(DEV, "helper command: %s %s %s exit code %u (0x%x)\n",
+               drbd_info(device, "helper command: %s %s %s exit code %u (0x%x)\n",
                                usermode_helper, cmd, mb,
                                (ret >> 8) & 0xff, ret);
        sib.sib_reason = SIB_HELPER_POST;
@@ -381,16 +392,16 @@ static int conn_khelper(struct drbd_connection *connection, char *cmd)
        setup_khelper_env(connection, envp);
        conn_md_sync(connection);
 
-       conn_info(connection, "helper command: %s %s %s\n", usermode_helper, cmd, resource_name);
+       drbd_info(connection, "helper command: %s %s %s\n", usermode_helper, cmd, resource_name);
        /* TODO: conn_bcast_event() ?? */
 
        ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC);
        if (ret)
-               conn_warn(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
+               drbd_warn(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
                          usermode_helper, cmd, resource_name,
                          (ret >> 8) & 0xff, ret);
        else
-               conn_info(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
+               drbd_info(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
                          usermode_helper, cmd, resource_name,
                          (ret >> 8) & 0xff, ret);
        /* TODO: conn_bcast_event() ?? */
@@ -404,14 +415,16 @@ static int conn_khelper(struct drbd_connection *connection, char *cmd)
 static enum drbd_fencing_p highest_fencing_policy(struct drbd_connection *connection)
 {
        enum drbd_fencing_p fp = FP_NOT_AVAIL;
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        int vnr;
 
        rcu_read_lock();
-       idr_for_each_entry(&connection->volumes, device, vnr) {
+       idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+               struct drbd_device *device = peer_device->device;
                if (get_ldev_if_state(device, D_CONSISTENT)) {
-                       fp = max_t(enum drbd_fencing_p, fp,
-                                  rcu_dereference(device->ldev->disk_conf)->fencing);
+                       struct disk_conf *disk_conf =
+                               rcu_dereference(peer_device->device->ldev->disk_conf);
+                       fp = max_t(enum drbd_fencing_p, fp, disk_conf->fencing);
                        put_ldev(device);
                }
        }
@@ -430,7 +443,7 @@ bool conn_try_outdate_peer(struct drbd_connection *connection)
        int r;
 
        if (connection->cstate >= C_WF_REPORT_PARAMS) {
-               conn_err(connection, "Expected cstate < C_WF_REPORT_PARAMS\n");
+               drbd_err(connection, "Expected cstate < C_WF_REPORT_PARAMS\n");
                return false;
        }
 
@@ -441,7 +454,7 @@ bool conn_try_outdate_peer(struct drbd_connection *connection)
        fp = highest_fencing_policy(connection);
        switch (fp) {
        case FP_NOT_AVAIL:
-               conn_warn(connection, "Not fencing peer, I'm not even Consistent myself.\n");
+               drbd_warn(connection, "Not fencing peer, I'm not even Consistent myself.\n");
                goto out;
        case FP_DONT_CARE:
                return true;
@@ -475,24 +488,24 @@ bool conn_try_outdate_peer(struct drbd_connection *connection)
                 * This is useful when an unconnected R_SECONDARY is asked to
                 * become R_PRIMARY, but finds the other peer being active. */
                ex_to_string = "peer is active";
-               conn_warn(connection, "Peer is primary, outdating myself.\n");
+               drbd_warn(connection, "Peer is primary, outdating myself.\n");
                mask.disk = D_MASK;
                val.disk = D_OUTDATED;
                break;
        case 7:
                if (fp != FP_STONITH)
-                       conn_err(connection, "fence-peer() = 7 && fencing != Stonith !!!\n");
+                       drbd_err(connection, "fence-peer() = 7 && fencing != Stonith !!!\n");
                ex_to_string = "peer was stonithed";
                mask.pdsk = D_MASK;
                val.pdsk = D_OUTDATED;
                break;
        default:
                /* The script is broken ... */
-               conn_err(connection, "fence-peer helper broken, returned %d\n", (r>>8)&0xff);
+               drbd_err(connection, "fence-peer helper broken, returned %d\n", (r>>8)&0xff);
                return false; /* Eventually leave IO frozen */
        }
 
-       conn_info(connection, "fence-peer helper returned %d (%s)\n",
+       drbd_info(connection, "fence-peer helper returned %d (%s)\n",
                  (r>>8) & 0xff, ex_to_string);
 
  out:
@@ -506,7 +519,7 @@ bool conn_try_outdate_peer(struct drbd_connection *connection)
                if (connection->connect_cnt != connect_cnt)
                        /* In case the connection was established and droped
                           while the fence-peer handler was running, ignore it */
-                       conn_info(connection, "Ignoring fence-peer exit code\n");
+                       drbd_info(connection, "Ignoring fence-peer exit code\n");
                else
                        _conn_request_state(connection, mask, val, CS_VERBOSE);
        }
@@ -532,7 +545,7 @@ void conn_try_outdate_peer_async(struct drbd_connection *connection)
        kref_get(&connection->kref);
        opa = kthread_run(_try_outdate_peer_async, connection, "drbd_async_h");
        if (IS_ERR(opa)) {
-               conn_err(connection, "out of mem, failed to invoke fence-peer helper\n");
+               drbd_err(connection, "out of mem, failed to invoke fence-peer helper\n");
                kref_put(&connection->kref, drbd_destroy_connection);
        }
 }
@@ -577,7 +590,7 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
 
                if (rv == SS_NO_UP_TO_DATE_DISK &&
                    device->state.disk == D_CONSISTENT && mask.pdsk == 0) {
-                       D_ASSERT(device->state.pdsk == D_UNKNOWN);
+                       D_ASSERT(device, device->state.pdsk == D_UNKNOWN);
 
                        if (conn_try_outdate_peer(first_peer_device(device)->connection)) {
                                val.disk = D_UP_TO_DATE;
@@ -590,7 +603,7 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
                        goto out;
                if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) {
                        if (!conn_try_outdate_peer(first_peer_device(device)->connection) && force) {
-                               dev_warn(DEV, "Forced into split brain situation!\n");
+                               drbd_warn(device, "Forced into split brain situation!\n");
                                mask.pdsk = D_MASK;
                                val.pdsk  = D_OUTDATED;
 
@@ -623,7 +636,7 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
                goto out;
 
        if (forced)
-               dev_warn(DEV, "Forced to consider local data as UpToDate!\n");
+               drbd_warn(device, "Forced to consider local data as UpToDate!\n");
 
        /* Wait until nothing is on the fly :) */
        wait_event(device->misc_wait, atomic_read(&device->ap_pending_cnt) == 0);
@@ -892,7 +905,7 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct
                if (rs && u_size == 0) {
                        /* Remove "rs &&" later. This check should always be active, but
                           right now the receiver expects the permissive behavior */
-                       dev_warn(DEV, "Implicit shrink not allowed. "
+                       drbd_warn(device, "Implicit shrink not allowed. "
                                 "Use --size=%llus for explicit shrink.\n",
                                 (unsigned long long)size);
                        rv = DS_ERROR_SHRINK;
@@ -911,10 +924,10 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct
                        /* currently there is only one error: ENOMEM! */
                        size = drbd_bm_capacity(device)>>1;
                        if (size == 0) {
-                               dev_err(DEV, "OUT OF MEMORY! "
+                               drbd_err(device, "OUT OF MEMORY! "
                                    "Could not allocate bitmap!\n");
                        } else {
-                               dev_err(DEV, "BM resizing failed. "
+                               drbd_err(device, "BM resizing failed. "
                                    "Leaving size unchanged at size = %lu KB\n",
                                    (unsigned long)size);
                        }
@@ -923,7 +936,7 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct
                /* racy, see comments above. */
                drbd_set_my_capacity(device, size);
                device->ldev->md.la_size_sect = size;
-               dev_info(DEV, "size = %s (%llu KB)\n", ppsize(ppb, size>>1),
+               drbd_info(device, "size = %s (%llu KB)\n", ppsize(ppb, size>>1),
                     (unsigned long long)size>>1);
        }
        if (rv <= DS_ERROR)
@@ -943,7 +956,7 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct
                md->flags &= ~MDF_PRIMARY_IND;
                drbd_md_write(device, buffer);
 
-               dev_info(DEV, "Writing the whole bitmap, %s\n",
+               drbd_info(device, "Writing the whole bitmap, %s\n",
                         la_size_changed && md_moved ? "size changed and md moved" :
                         la_size_changed ? "size changed" : "md moved");
                /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */
@@ -955,8 +968,8 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct
                drbd_md_write(device, buffer);
 
                if (rs)
-                       dev_info(DEV, "Changed AL layout to al-stripes = %d, al-stripe-size-kB = %d\n",
-                                md->al_stripes, md->al_stripe_size_4k * 4);
+                       drbd_info(device, "Changed AL layout to al-stripes = %d, al-stripe-size-kB = %d\n",
+                                 md->al_stripes, md->al_stripe_size_4k * 4);
        }
 
        if (size > la_size_sect)
@@ -994,7 +1007,7 @@ drbd_new_dev_size(struct drbd_device *device, struct drbd_backing_dev *bdev,
        m_size = drbd_get_max_capacity(bdev);
 
        if (device->state.conn < C_CONNECTED && assume_peer_has_space) {
-               dev_warn(DEV, "Resize while not connected was forced by the user!\n");
+               drbd_warn(device, "Resize while not connected was forced by the user!\n");
                p_size = m_size;
        }
 
@@ -1016,11 +1029,11 @@ drbd_new_dev_size(struct drbd_device *device, struct drbd_backing_dev *bdev,
        }
 
        if (size == 0)
-               dev_err(DEV, "Both nodes diskless!\n");
+               drbd_err(device, "Both nodes diskless!\n");
 
        if (u_size) {
                if (u_size > size)
-                       dev_err(DEV, "Requested disk size is too big (%lu > %lu)\n",
+                       drbd_err(device, "Requested disk size is too big (%lu > %lu)\n",
                            (unsigned long)u_size>>1, (unsigned long)size>>1);
                else
                        size = u_size;
@@ -1054,7 +1067,7 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
                dc->al_extents, sizeof(struct lc_element), 0);
 
        if (n == NULL) {
-               dev_err(DEV, "Cannot allocate act_log lru!\n");
+               drbd_err(device, "Cannot allocate act_log lru!\n");
                return -ENOMEM;
        }
        spin_lock_irq(&device->al_lock);
@@ -1062,7 +1075,7 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
                for (i = 0; i < t->nr_elements; i++) {
                        e = lc_element_by_index(t, i);
                        if (e->refcnt)
-                               dev_err(DEV, "refcnt(%d)==%d\n",
+                               drbd_err(device, "refcnt(%d)==%d\n",
                                    e->lc_number, e->refcnt);
                        in_use += e->refcnt;
                }
@@ -1071,7 +1084,7 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
                device->act_log = n;
        spin_unlock_irq(&device->al_lock);
        if (in_use) {
-               dev_err(DEV, "Activity log still in use!\n");
+               drbd_err(device, "Activity log still in use!\n");
                lc_destroy(n);
                return -EBUSY;
        } else {
@@ -1110,7 +1123,7 @@ static void drbd_setup_queue_param(struct drbd_device *device, unsigned int max_
                blk_queue_stack_limits(q, b);
 
                if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
-                       dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
+                       drbd_info(device, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
                                 q->backing_dev_info.ra_pages,
                                 b->backing_dev_info.ra_pages);
                        q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages;
@@ -1152,10 +1165,10 @@ void drbd_reconsider_max_bio_size(struct drbd_device *device)
        new = min(local, peer);
 
        if (device->state.role == R_PRIMARY && new < now)
-               dev_err(DEV, "ASSERT FAILED new < now; (%u < %u)\n", new, now);
+               drbd_err(device, "ASSERT FAILED new < now; (%u < %u)\n", new, now);
 
        if (new != now)
-               dev_info(DEV, "max BIO size = %u\n", new);
+               drbd_info(device, "max BIO size = %u\n", new);
 
        drbd_setup_queue_param(device, new);
 }
@@ -1189,7 +1202,7 @@ static void drbd_suspend_al(struct drbd_device *device)
        int s = 0;
 
        if (!lc_try_lock(device->act_log)) {
-               dev_warn(DEV, "Failed to lock al in drbd_suspend_al()\n");
+               drbd_warn(device, "Failed to lock al in drbd_suspend_al()\n");
                return;
        }
 
@@ -1201,7 +1214,7 @@ static void drbd_suspend_al(struct drbd_device *device)
        lc_unlock(device->act_log);
 
        if (s)
-               dev_info(DEV, "Suspended AL updates\n");
+               drbd_info(device, "Suspended AL updates\n");
 }
 
 
@@ -1296,7 +1309,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
        if (fifo_size != device->rs_plan_s->size) {
                new_plan = fifo_alloc(fifo_size);
                if (!new_plan) {
-                       dev_err(DEV, "kmalloc of fifo_buffer failed");
+                       drbd_err(device, "kmalloc of fifo_buffer failed");
                        retcode = ERR_NOMEM;
                        goto fail_unlock;
                }
@@ -1472,7 +1485,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
        bdev = blkdev_get_by_path(new_disk_conf->backing_dev,
                                  FMODE_READ | FMODE_WRITE | FMODE_EXCL, device);
        if (IS_ERR(bdev)) {
-               dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->backing_dev,
+               drbd_err(device, "open(\"%s\") failed with %ld\n", new_disk_conf->backing_dev,
                        PTR_ERR(bdev));
                retcode = ERR_OPEN_DISK;
                goto fail;
@@ -1492,7 +1505,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
                                  (new_disk_conf->meta_dev_idx < 0) ?
                                  (void *)device : (void *)drbd_m_holder);
        if (IS_ERR(bdev)) {
-               dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->meta_dev,
+               drbd_err(device, "open(\"%s\") failed with %ld\n", new_disk_conf->meta_dev,
                        PTR_ERR(bdev));
                retcode = ERR_OPEN_MD_DISK;
                goto fail;
@@ -1526,7 +1539,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
                new_disk_conf->al_extents = drbd_al_extents_max(nbc);
 
        if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) {
-               dev_err(DEV, "max capacity %llu smaller than disk size %llu\n",
+               drbd_err(device, "max capacity %llu smaller than disk size %llu\n",
                        (unsigned long long) drbd_get_max_capacity(nbc),
                        (unsigned long long) new_disk_conf->disk_size);
                retcode = ERR_DISK_TOO_SMALL;
@@ -1544,7 +1557,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 
        if (drbd_get_capacity(nbc->md_bdev) < min_md_device_sectors) {
                retcode = ERR_MD_DISK_TOO_SMALL;
-               dev_warn(DEV, "refusing attach: md-device too small, "
+               drbd_warn(device, "refusing attach: md-device too small, "
                     "at least %llu sectors needed for this meta-disk type\n",
                     (unsigned long long) min_md_device_sectors);
                goto fail;
@@ -1561,11 +1574,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
        nbc->known_size = drbd_get_capacity(nbc->backing_bdev);
 
        if (nbc->known_size > max_possible_sectors) {
-               dev_warn(DEV, "==> truncating very big lower level device "
+               drbd_warn(device, "==> truncating very big lower level device "
                        "to currently maximum possible %llu sectors <==\n",
                        (unsigned long long) max_possible_sectors);
                if (new_disk_conf->meta_dev_idx >= 0)
-                       dev_warn(DEV, "==>> using internal or flexible "
+                       drbd_warn(device, "==>> using internal or flexible "
                                      "meta data may help <<==\n");
        }
 
@@ -1600,7 +1613,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
        if (device->state.conn < C_CONNECTED &&
            device->state.role == R_PRIMARY &&
            (device->ed_uuid & ~((u64)1)) != (nbc->md.uuid[UI_CURRENT] & ~((u64)1))) {
-               dev_err(DEV, "Can only attach to data with current UUID=%016llX\n",
+               drbd_err(device, "Can only attach to data with current UUID=%016llX\n",
                    (unsigned long long)device->ed_uuid);
                retcode = ERR_DATA_NOT_CURRENT;
                goto force_diskless_dec;
@@ -1615,7 +1628,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
        /* Prevent shrinking of consistent devices ! */
        if (drbd_md_test_flag(nbc, MDF_CONSISTENT) &&
            drbd_new_dev_size(device, nbc, nbc->disk_conf->disk_size, 0) < nbc->md.la_size_sect) {
-               dev_warn(DEV, "refusing to truncate a consistent device\n");
+               drbd_warn(device, "refusing to truncate a consistent device\n");
                retcode = ERR_DISK_TOO_SMALL;
                goto force_diskless_dec;
        }
@@ -1631,7 +1644,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
         * Devices and memory are no longer released by error cleanup below.
         * now device takes over responsibility, and the state engine should
         * clean it up somewhere.  */
-       D_ASSERT(device->ldev == NULL);
+       D_ASSERT(device, device->ldev == NULL);
        device->ldev = nbc;
        device->resync = resync_lru;
        device->rs_plan_s = new_plan;
@@ -1689,7 +1702,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
        if (drbd_md_test_flag(device->ldev, MDF_FULL_SYNC) ||
            (test_bit(CRASHED_PRIMARY, &device->flags) &&
             drbd_md_test_flag(device->ldev, MDF_AL_DISABLED))) {
-               dev_info(DEV, "Assuming that all blocks are out of sync "
+               drbd_info(device, "Assuming that all blocks are out of sync "
                     "(aka FullSync)\n");
                if (drbd_bitmap_io(device, &drbd_bmio_set_n_write,
                        "set_n_write from attaching", BM_LOCKED_MASK)) {
@@ -1867,12 +1880,13 @@ out:
 
 static bool conn_resync_running(struct drbd_connection *connection)
 {
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        bool rv = false;
        int vnr;
 
        rcu_read_lock();
-       idr_for_each_entry(&connection->volumes, device, vnr) {
+       idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+               struct drbd_device *device = peer_device->device;
                if (device->state.conn == C_SYNC_SOURCE ||
                    device->state.conn == C_SYNC_TARGET ||
                    device->state.conn == C_PAUSED_SYNC_S ||
@@ -1888,12 +1902,13 @@ static bool conn_resync_running(struct drbd_connection *connection)
 
 static bool conn_ov_running(struct drbd_connection *connection)
 {
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        bool rv = false;
        int vnr;
 
        rcu_read_lock();
-       idr_for_each_entry(&connection->volumes, device, vnr) {
+       idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+               struct drbd_device *device = peer_device->device;
                if (device->state.conn == C_VERIFY_S ||
                    device->state.conn == C_VERIFY_T) {
                        rv = true;
@@ -1908,7 +1923,7 @@ static bool conn_ov_running(struct drbd_connection *connection)
 static enum drbd_ret_code
 _check_net_options(struct drbd_connection *connection, struct net_conf *old_conf, struct net_conf *new_conf)
 {
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        int i;
 
        if (old_conf && connection->cstate == C_WF_REPORT_PARAMS && connection->agreed_pro_version < 100) {
@@ -1931,7 +1946,8 @@ _check_net_options(struct drbd_connection *connection, struct net_conf *old_conf
            (new_conf->wire_protocol != DRBD_PROT_C))
                return ERR_NOT_PROTO_C;
 
-       idr_for_each_entry(&connection->volumes, device, i) {
+       idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+               struct drbd_device *device = peer_device->device;
                if (get_ldev(device)) {
                        enum drbd_fencing_p fp = rcu_dereference(device->ldev->disk_conf)->fencing;
                        put_ldev(device);
@@ -1952,7 +1968,7 @@ static enum drbd_ret_code
 check_net_options(struct drbd_connection *connection, struct net_conf *new_conf)
 {
        static enum drbd_ret_code rv;
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        int i;
 
        rcu_read_lock();
@@ -1960,7 +1976,8 @@ check_net_options(struct drbd_connection *connection, struct net_conf *new_conf)
        rcu_read_unlock();
 
        /* connection->volumes protected by genl_lock() here */
-       idr_for_each_entry(&connection->volumes, device, i) {
+       idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+               struct drbd_device *device = peer_device->device;
                if (!device->bitmap) {
                        if (drbd_bm_init(device))
                                return ERR_NOMEM;
@@ -2144,7 +2161,7 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
 
 int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
 {
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        struct net_conf *old_conf, *new_conf = NULL;
        struct crypto crypto = { };
        struct drbd_resource *resource;
@@ -2245,7 +2262,8 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
        mutex_unlock(&connection->conf_update);
 
        rcu_read_lock();
-       idr_for_each_entry(&connection->volumes, device, i) {
+       idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+               struct drbd_device *device = peer_device->device;
                device->send_cnt = 0;
                device->recv_cnt = 0;
        }
@@ -2306,7 +2324,7 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_connection *connection
                 * The state handling only uses drbd_thread_stop_nowait(),
                 * we want to really wait here until the receiver is no more.
                 */
-               drbd_thread_stop(&adm_ctx.connection->receiver);
+               drbd_thread_stop(&connection->receiver);
 
                /* Race breaker.  This additional state change request may be
                 * necessary, if this was a forced disconnect during a receiver
@@ -2317,7 +2335,7 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_connection *connection
                rv2 = conn_request_state(connection, NS(conn, C_STANDALONE),
                                CS_VERBOSE | CS_HARD);
                if (rv2 < SS_SUCCESS)
-                       conn_err(connection,
+                       drbd_err(connection,
                                "unexpected rv2=%d in conn_try_disconnect()\n",
                                rv2);
        }
@@ -2363,7 +2381,7 @@ void resync_after_online_grow(struct drbd_device *device)
 {
        int iass; /* I am sync source */
 
-       dev_info(DEV, "Resync of new storage after online grow\n");
+       drbd_info(device, "Resync of new storage after online grow\n");
        if (device->state.role != device->state.peer)
                iass = (device->state.role == R_PRIMARY);
        else
@@ -2509,7 +2527,6 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info)
 {
        enum drbd_ret_code retcode;
-       struct drbd_connection *connection;
        struct res_opts res_opts;
        int err;
 
@@ -2518,9 +2535,8 @@ int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info)
                return retcode;
        if (retcode != NO_ERROR)
                goto fail;
-       connection = adm_ctx.connection;
 
-       res_opts = connection->res_opts;
+       res_opts = adm_ctx.resource->res_opts;
        if (should_set_defaults(info))
                set_res_opts_defaults(&res_opts);
 
@@ -2531,7 +2547,7 @@ int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info)
                goto fail;
        }
 
-       err = set_resource_options(connection, &res_opts);
+       err = set_resource_options(adm_ctx.resource, &res_opts);
        if (err) {
                retcode = ERR_INVALID_REQUEST;
                if (err == -ENOMEM)
@@ -2736,23 +2752,28 @@ int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info)
        return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED));
 }
 
-static int nla_put_drbd_cfg_context(struct sk_buff *skb, struct drbd_connection *connection, unsigned vnr)
+static int nla_put_drbd_cfg_context(struct sk_buff *skb,
+                                   struct drbd_resource *resource,
+                                   struct drbd_connection *connection,
+                                   struct drbd_device *device)
 {
        struct nlattr *nla;
        nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT);
        if (!nla)
                goto nla_put_failure;
-       if (vnr != VOLUME_UNSPECIFIED &&
-           nla_put_u32(skb, T_ctx_volume, vnr))
+       if (device &&
+           nla_put_u32(skb, T_ctx_volume, device->vnr))
                goto nla_put_failure;
        if (nla_put_string(skb, T_ctx_resource_name, connection->resource->name))
                goto nla_put_failure;
-       if (connection->my_addr_len &&
-           nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr))
-               goto nla_put_failure;
-       if (connection->peer_addr_len &&
-           nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr))
-               goto nla_put_failure;
+       if (connection) {
+               if (connection->my_addr_len &&
+                   nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr))
+                       goto nla_put_failure;
+               if (connection->peer_addr_len &&
+                   nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr))
+                       goto nla_put_failure;
+       }
        nla_nest_end(skb, nla);
        return 0;
 
@@ -2762,9 +2783,22 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
+/*
+ * Return the connection of @resource if @resource has exactly one connection.
+ */
+static struct drbd_connection *the_only_connection(struct drbd_resource *resource)
+{
+       struct list_head *connections = &resource->connections;
+
+       if (list_empty(connections) || connections->next->next != connections)
+               return NULL;
+       return list_first_entry(&resource->connections, struct drbd_connection, connections);
+}
+
+int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
                const struct sib_info *sib)
 {
+       struct drbd_resource *resource = device->resource;
        struct state_info *si = NULL; /* for sizeof(si->member); */
        struct nlattr *nla;
        int got_ldev;
@@ -2788,10 +2822,10 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
 
        /* We need to add connection name and volume number information still.
         * Minor number is in drbd_genlmsghdr. */
-       if (nla_put_drbd_cfg_context(skb, first_peer_device(device)->connection, device->vnr))
+       if (nla_put_drbd_cfg_context(skb, resource, the_only_connection(resource), device))
                goto nla_put_failure;
 
-       if (res_opts_to_skb(skb, &first_peer_device(device)->connection->res_opts, exclude_sensitive))
+       if (res_opts_to_skb(skb, &device->resource->res_opts, exclude_sensitive))
                goto nla_put_failure;
 
        rcu_read_lock();
@@ -2910,14 +2944,13 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
        struct drbd_genlmsghdr *dh;
        struct drbd_resource *pos = (struct drbd_resource *)cb->args[0];
        struct drbd_resource *resource = NULL;
-       struct drbd_connection *connection;
        struct drbd_resource *tmp;
        unsigned volume = cb->args[1];
 
        /* Open coded, deferred, iteration:
         * for_each_resource_safe(resource, tmp, &drbd_resources) {
-        *      connection = "first connection of resource";
-        *      idr_for_each_entry(&connection->volumes, device, i) {
+        *      connection = "first connection of resource or undefined";
+        *      idr_for_each_entry(&resource->devices, device, i) {
         *        ...
         *      }
         * }
@@ -2952,8 +2985,7 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
        }
        if (resource) {
 next_resource:
-               connection = first_connection(resource);
-               device = idr_get_next(&connection->volumes, &volume);
+               device = idr_get_next(&resource->devices, &volume);
                if (!device) {
                        /* No more volumes to dump on this resource.
                         * Advance resource iterator. */
@@ -2982,19 +3014,25 @@ next_resource:
                        /* This is a connection without a single volume.
                         * Suprisingly enough, it may have a network
                         * configuration. */
-                       struct net_conf *nc;
+                       struct drbd_connection *connection;
+
                        dh->minor = -1U;
                        dh->ret_code = NO_ERROR;
-                       if (nla_put_drbd_cfg_context(skb, connection, VOLUME_UNSPECIFIED))
-                               goto cancel;
-                       nc = rcu_dereference(connection->net_conf);
-                       if (nc && net_conf_to_skb(skb, nc, 1) != 0)
+                       connection = the_only_connection(resource);
+                       if (nla_put_drbd_cfg_context(skb, resource, connection, NULL))
                                goto cancel;
+                       if (connection) {
+                               struct net_conf *nc;
+
+                               nc = rcu_dereference(connection->net_conf);
+                               if (nc && net_conf_to_skb(skb, nc, 1) != 0)
+                                       goto cancel;
+                       }
                        goto done;
                }
 
-               D_ASSERT(device->vnr == volume);
-               D_ASSERT(first_peer_device(device)->connection == connection);
+               D_ASSERT(device, device->vnr == volume);
+               D_ASSERT(device, device->resource == resource);
 
                dh->minor = device_to_minor(device);
                dh->ret_code = NO_ERROR;
@@ -3034,7 +3072,7 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
        const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ;
        struct nlattr *nla;
        const char *resource_name;
-       struct drbd_connection *connection;
+       struct drbd_resource *resource;
        int maxtype;
 
        /* Is this a followup call? */
@@ -3063,18 +3101,19 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
        if (!nla)
                return -EINVAL;
        resource_name = nla_data(nla);
-       connection = conn_get_by_name(resource_name);
-
-       if (!connection)
+       if (!*resource_name)
+               return -ENODEV;
+       resource = drbd_find_resource(resource_name);
+       if (!resource)
                return -ENODEV;
 
-       kref_put(&connection->kref, drbd_destroy_connection); /* get_one_status() (re)validates connection by itself */
+       kref_put(&resource->kref, drbd_destroy_resource); /* get_one_status() revalidates the resource */
 
        /* prime iterators, and set "filter" mode mark:
         * only dump this connection. */
-       cb->args[0] = (long)connection;
+       cb->args[0] = (long)resource;
        /* cb->args[1] = 0; passed in this way. */
-       cb->args[2] = (long)connection;
+       cb->args[2] = (long)resource;
 
 dump:
        return get_one_status(skb, cb);
@@ -3184,7 +3223,7 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info)
        if (device->state.conn == C_CONNECTED &&
            first_peer_device(device)->connection->agreed_pro_version >= 90 &&
            device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && args.clear_bm) {
-               dev_info(DEV, "Preparing to skip initial sync\n");
+               drbd_info(device, "Preparing to skip initial sync\n");
                skip_initial_sync = 1;
        } else if (device->state.conn != C_STANDALONE) {
                retcode = ERR_CONNECTED;
@@ -3198,7 +3237,7 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info)
                err = drbd_bitmap_io(device, &drbd_bmio_clear_n_write,
                        "clear_n_write from new_c_uuid", BM_LOCKED_MASK);
                if (err) {
-                       dev_err(DEV, "Writing bitmap failed with %d\n",err);
+                       drbd_err(device, "Writing bitmap failed with %d\n", err);
                        retcode = ERR_IO_MD_DISK;
                }
                if (skip_initial_sync) {
@@ -3309,7 +3348,7 @@ int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       retcode = drbd_create_minor(adm_ctx.connection, dh->minor, adm_ctx.volume);
+       retcode = drbd_create_device(adm_ctx.connection, dh->minor, adm_ctx.volume);
 out:
        drbd_adm_finish(info, retcode);
        return 0;
@@ -3324,12 +3363,7 @@ static enum drbd_ret_code adm_del_minor(struct drbd_device *device)
            device->state.role == R_SECONDARY) {
                _drbd_request_state(device, NS(conn, C_WF_REPORT_PARAMS),
                                    CS_VERBOSE + CS_WAIT_COMPLETE);
-               idr_remove(&first_peer_device(device)->connection->volumes, device->vnr);
-               idr_remove(&drbd_devices, device_to_minor(device));
-               destroy_workqueue(device->submit.wq);
-               del_gendisk(device->vdisk);
-               synchronize_rcu();
-               kref_put(&device->kref, drbd_destroy_device);
+               drbd_delete_device(device);
                return NO_ERROR;
        } else
                return ERR_MINOR_CONFIGURED;
@@ -3354,7 +3388,7 @@ out:
 int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
 {
        int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
-       struct drbd_device *device;
+       struct drbd_peer_device *peer_device;
        unsigned i;
 
        retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
@@ -3364,8 +3398,8 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
                goto out;
 
        /* demote */
-       idr_for_each_entry(&adm_ctx.connection->volumes, device, i) {
-               retcode = drbd_set_role(device, R_SECONDARY, 0);
+       idr_for_each_entry(&adm_ctx.connection->peer_devices, peer_device, i) {
+               retcode = drbd_set_role(peer_device->device, R_SECONDARY, 0);
                if (retcode < SS_SUCCESS) {
                        drbd_msg_put_info("failed to demote");
                        goto out;
@@ -3379,8 +3413,8 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
        }
 
        /* detach */
-       idr_for_each_entry(&adm_ctx.connection->volumes, device, i) {
-               retcode = adm_detach(device, 0);
+       idr_for_each_entry(&adm_ctx.connection->peer_devices, peer_device, i) {
+               retcode = adm_detach(peer_device->device, 0);
                if (retcode < SS_SUCCESS || retcode > NO_ERROR) {
                        drbd_msg_put_info("failed to detach");
                        goto out;
@@ -3395,8 +3429,8 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
        /* Now, nothing can fail anymore */
 
        /* delete volumes */
-       idr_for_each_entry(&adm_ctx.connection->volumes, device, i) {
-               retcode = adm_del_minor(device);
+       idr_for_each_entry(&adm_ctx.connection->peer_devices, peer_device, i) {
+               retcode = adm_del_minor(peer_device->device);
                if (retcode != NO_ERROR) {
                        /* "can not happen" */
                        drbd_msg_put_info("failed to delete volume");
@@ -3499,7 +3533,7 @@ void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib)
 nla_put_failure:
        nlmsg_free(msg);
 failed:
-       dev_err(DEV, "Error %d while broadcasting event. "
+       drbd_err(device, "Error %d while broadcasting event. "
                        "Event seq:%u sib_reason:%u\n",
                        err, seq, sib->sib_reason);
 }
This page took 0.038932 seconds and 5 git commands to generate.