block: Consolidate phys_segment and hw_segment limits
[linux-2.6.git] / drivers / block / drbd / drbd_nl.c
index 73c55cc..4df3b40 100644 (file)
@@ -510,7 +510,7 @@ void drbd_resume_io(struct drbd_conf *mdev)
  * Returns 0 on success, negative return values indicate errors.
  * You should call drbd_md_sync() after calling this function.
  */
-enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_hold(local)
+enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force) __must_hold(local)
 {
        sector_t prev_first_sect, prev_size; /* previous meta location */
        sector_t la_size;
@@ -541,7 +541,7 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_ho
        /* TODO: should only be some assert here, not (re)init... */
        drbd_md_set_sector_offsets(mdev, mdev->ldev);
 
-       size = drbd_new_dev_size(mdev, mdev->ldev);
+       size = drbd_new_dev_size(mdev, mdev->ldev, force);
 
        if (drbd_get_capacity(mdev->this_bdev) != size ||
            drbd_bm_capacity(mdev) != size) {
@@ -596,7 +596,7 @@ out:
 }
 
 sector_t
-drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
+drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, int assume_peer_has_space)
 {
        sector_t p_size = mdev->p_size;   /* partner's disk size. */
        sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */
@@ -606,6 +606,11 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 
        m_size = drbd_get_max_capacity(bdev);
 
+       if (mdev->state.conn < C_CONNECTED && assume_peer_has_space) {
+               dev_warn(DEV, "Resize while not connected was forced by the user!\n");
+               p_size = m_size;
+       }
+
        if (p_size && m_size) {
                size = min_t(sector_t, p_size, m_size);
        } else {
@@ -704,9 +709,8 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu
 
        max_seg_s = min(queue_max_sectors(b) * queue_logical_block_size(b), max_seg_s);
 
-       blk_queue_max_sectors(q, max_seg_s >> 9);
-       blk_queue_max_phys_segments(q, max_segments ? max_segments : MAX_PHYS_SEGMENTS);
-       blk_queue_max_hw_segments(q, max_segments ? max_segments : MAX_HW_SEGMENTS);
+       blk_queue_max_hw_sectors(q, max_seg_s >> 9);
+       blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
        blk_queue_max_segment_size(q, max_seg_s);
        blk_queue_logical_block_size(q, 512);
        blk_queue_segment_boundary(q, PAGE_SIZE-1);
@@ -733,7 +737,7 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu
  */
 static void drbd_reconfig_start(struct drbd_conf *mdev)
 {
-       wait_event(mdev->state_wait, test_and_set_bit(CONFIG_PENDING, &mdev->flags));
+       wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags));
        wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags));
        drbd_thread_start(&mdev->worker);
 }
@@ -894,11 +898,6 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
                min_md_device_sectors = MD_RESERVED_SECT * (nbc->dc.meta_dev_idx + 1);
        }
 
-       if (drbd_get_capacity(nbc->md_bdev) > max_possible_sectors)
-               dev_warn(DEV, "truncating very big lower level device "
-                    "to currently maximum possible %llu sectors\n",
-                    (unsigned long long) max_possible_sectors);
-
        if (drbd_get_capacity(nbc->md_bdev) < min_md_device_sectors) {
                retcode = ERR_MD_DISK_TO_SMALL;
                dev_warn(DEV, "refusing attach: md-device too small, "
@@ -917,6 +916,15 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 
        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 "
+                       "to currently maximum possible %llu sectors <==\n",
+                       (unsigned long long) max_possible_sectors);
+               if (nbc->dc.meta_dev_idx >= 0)
+                       dev_warn(DEV, "==>> using internal or flexible "
+                                     "meta data may help <<==\n");
+       }
+
        drbd_suspend_io(mdev);
        /* also wait for the last barrier ack. */
        wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt));
@@ -961,7 +969,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 
        /* Prevent shrinking of consistent devices ! */
        if (drbd_md_test_flag(nbc, MDF_CONSISTENT) &&
-          drbd_new_dev_size(mdev, nbc) < nbc->md.la_size_sect) {
+           drbd_new_dev_size(mdev, nbc, 0) < nbc->md.la_size_sect) {
                dev_warn(DEV, "refusing to truncate a consistent device\n");
                retcode = ERR_DISK_TO_SMALL;
                goto force_diskless_dec;
@@ -1048,7 +1056,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
            !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND))
                set_bit(USE_DEGR_WFC_T, &mdev->flags);
 
-       dd = drbd_determin_dev_size(mdev);
+       dd = drbd_determin_dev_size(mdev, 0);
        if (dd == dev_size_error) {
                retcode = ERR_NOMEM_BITMAP;
                goto force_diskless_dec;
@@ -1267,8 +1275,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
                        goto fail;
                }
 
-               if (crypto_tfm_alg_type(crypto_hash_tfm(tfm))
-                                               != CRYPTO_ALG_TYPE_HASH) {
+               if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) {
                        retcode = ERR_AUTH_ALG_ND;
                        goto fail;
                }
@@ -1501,7 +1508,7 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
        }
 
        mdev->ldev->dc.disk_size = (sector_t)rs.resize_size;
-       dd = drbd_determin_dev_size(mdev);
+       dd = drbd_determin_dev_size(mdev, rs.resize_force);
        drbd_md_sync(mdev);
        put_ldev(mdev);
        if (dd == dev_size_error) {
@@ -2000,7 +2007,7 @@ static struct cn_handler_struct cnd_table[] = {
        [ P_new_c_uuid ]        = { &drbd_nl_new_c_uuid,        0 },
 };
 
-static void drbd_connector_callback(struct cn_msg *req)
+static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms *nsp)
 {
        struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req *)req->data;
        struct cn_handler_struct *cm;
@@ -2017,6 +2024,11 @@ static void drbd_connector_callback(struct cn_msg *req)
                return;
        }
 
+       if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
+               retcode = ERR_PERM;
+               goto fail;
+       }
+
        mdev = ensure_mdev(nlp);
        if (!mdev) {
                retcode = ERR_MINOR_INVALID;