Split cluster sync function to two parts: 1. Read cluster data. 2. Apply cluster data. Signed-off-by: Dmitry Bogdanov <d.bogdanov@xxxxxxxxx> --- drivers/target/target_cluster_dlm.c | 117 ++++++++++++++++++---------- 1 file changed, 74 insertions(+), 43 deletions(-) diff --git a/drivers/target/target_cluster_dlm.c b/drivers/target/target_cluster_dlm.c index 546e28062b8f..ff0c207be141 100644 --- a/drivers/target/target_cluster_dlm.c +++ b/drivers/target/target_cluster_dlm.c @@ -565,61 +565,53 @@ static void target_allocate_pr_ua(struct se_device *dev, u8 asc) } } -static void target_pr_sync_cb(void *arg) +static int target_dlm_read_cluster_data( + struct se_device *dev, + struct pr_lvb *pr_data, + struct pr_reg_lvb **pr_reg_datap) { - struct se_device *dev = arg; struct target_cluster_data *cluster_data = dev->cluster_data; - struct t10_pr_registration *pr_reg, *pr_reg_tmp; - struct t10_pr_registration *pr_reg_res_holder = NULL; - struct t10_pr_registration *pr_prev_res_holder = NULL; struct pr_reg_lvb *pr_reg_data = NULL; - LIST_HEAD(to_be_deleted_list); - LIST_HEAD(preempt_and_abort_list); struct async_group grp; - struct pr_lvb pr_data; - bool res_to_delete = false; - struct se_node_acl *pr_reg_nacl; - u64 pr_res_mapped_lun; - bool reg_deleted = false; - bool was_held; - u8 was_type; - u8 was_scope; - bool found; + int res = 0; int i = 0; - int res; - res = dlm_ckv_get(cluster_data->pr_data, (char *)&pr_data, sizeof(pr_data)); + res = dlm_ckv_get(cluster_data->pr_data, (char *)pr_data, + sizeof(struct pr_lvb)); if (res) goto done; - if (!pr_data.version) { + if (!pr_data->version) { pr_info("TARGET_CORE[%d]: PR data from cluster is invalid\n", dev->dev_index); goto done; } - pr_reg_data = kzalloc(sizeof(struct pr_reg_lvb) * pr_data.nr_registrants, + if (pr_data->nr_registrants == 0) + goto done; + + *pr_reg_datap = kzalloc(sizeof(struct pr_reg_lvb) * pr_data->nr_registrants, GFP_KERNEL); + pr_reg_data = *pr_reg_datap; if (!pr_reg_data) { res = -ENOMEM; goto done; } - res = pr_reg_realloc(cluster_data, pr_data.nr_registrants); + res = pr_reg_realloc(cluster_data, pr_data->nr_registrants); if (res) goto done; - if (pr_data.nr_registrants == 0) - goto skip_pr_reg; - refcount_set(&grp.pending, 1); /* 1 for a loop */ atomic_set(&grp.status, 0); init_completion(&grp.compl); - for (i = 0; i < pr_data.nr_registrants; ++i) { + for (i = 0; i < pr_data->nr_registrants; ++i) { refcount_inc(&grp.pending); - res = dlm_ckv_get_async(cluster_data->pr_reg_kv[i], (char *)(pr_reg_data + i), - sizeof(struct pr_reg_lvb), group_compl_cb, &grp); + res = dlm_ckv_get_async(cluster_data->pr_reg_kv[i], + (char *)(pr_reg_data + i), + sizeof(struct pr_reg_lvb), + group_compl_cb, &grp); if (res) { refcount_dec(&grp.pending); break; @@ -639,7 +631,33 @@ static void target_pr_sync_cb(void *arg) goto done; } -skip_pr_reg: +done: + if (res) + kfree(pr_reg_data); + return res; +} + +static void target_dlm_apply_cluster_data( + struct se_device *dev, + struct pr_lvb *pr_data, + struct pr_reg_lvb *pr_reg_data) +{ + struct target_cluster_data *cluster_data = dev->cluster_data; + struct t10_pr_registration *pr_reg, *pr_reg_tmp; + struct t10_pr_registration *pr_reg_res_holder = NULL; + struct t10_pr_registration *pr_prev_res_holder = NULL; + LIST_HEAD(to_be_deleted_list); + LIST_HEAD(preempt_and_abort_list); + bool res_to_delete = false; + struct se_node_acl *pr_reg_nacl; + u64 pr_res_mapped_lun; + bool reg_deleted = false; + bool was_held; + u8 was_type; + u8 was_scope; + bool found; + int i = 0; + /* * Update existing registrations */ @@ -656,7 +674,7 @@ static void target_pr_sync_cb(void *arg) pr_reg_list) { found = false; - for (i = 0; i < pr_data.nr_registrants; ++i) { + for (i = 0; i < pr_data->nr_registrants; ++i) { if (!pr_reg_data[i].version) continue; @@ -665,7 +683,7 @@ static void target_pr_sync_cb(void *arg) found = true; /* mark existing registrants */ pr_reg_data[i].version = 0; - target_update_pr_reg(dev, pr_reg, &pr_data, + target_update_pr_reg(dev, pr_reg, pr_data, &pr_reg_data[i], &pr_reg_res_holder); break; @@ -685,12 +703,12 @@ static void target_pr_sync_cb(void *arg) if (dev->dev_pr_res_holder != pr_reg) __core_scsi3_free_registration(dev, pr_reg, - (pr_data.pro_sa == PRO_PREEMPT_AND_ABORT) ? + (pr_data->pro_sa == PRO_PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, 0); else res_to_delete = true; - switch (pr_data.pro_sa) { + switch (pr_data->pro_sa) { case PRO_CLEAR: /* * establish a unit attention condition for the initiator @@ -720,12 +738,12 @@ static void target_pr_sync_cb(void *arg) spin_unlock(&dev->t10_pr.registration_lock); /* register new entries */ - for (i = 0; i < pr_data.nr_registrants; ++i) { + for (i = 0; i < pr_data->nr_registrants; ++i) { /* skip existing registrants */ if (!pr_reg_data[i].version) continue; - pr_reg = target_create_pr_reg(dev, &pr_data, &pr_reg_data[i]); + pr_reg = target_create_pr_reg(dev, pr_data, &pr_reg_data[i]); if (!pr_reg) pr_err("TARGET_CORE[%d]: can not create new registration\n", dev->dev_index); @@ -733,7 +751,7 @@ static void target_pr_sync_cb(void *arg) pr_reg_res_holder = pr_reg; } - switch (pr_data.pro_sa) { + switch (pr_data->pro_sa) { case PRO_REGISTER_AND_IGNORE_EXISTING_KEY: case PRO_REGISTER: /* @@ -793,11 +811,11 @@ static void target_pr_sync_cb(void *arg) } /* update general data */ - atomic_set(&dev->t10_pr.pr_generation, pr_data.pr_generation); - dev->t10_pr.pr_aptpl_active = pr_data.pr_aptpl; + atomic_set(&dev->t10_pr.pr_generation, pr_data->pr_generation); + dev->t10_pr.pr_aptpl_active = pr_data->pr_aptpl; /* update SPC-2 reservation */ - cluster_data->reserved_node_id = pr_data.reserved_by_nodeid; + cluster_data->reserved_node_id = pr_data->reserved_by_nodeid; spin_lock(&dev->dev_reservation_lock); if (cluster_data->reserved_node_id == cluster_data->local_nodeid && dev->reservation_holder == NULL) { @@ -826,18 +844,18 @@ static void target_pr_sync_cb(void *arg) if (pr_reg_res_holder) __core_scsi3_set_reservation(dev, pr_reg_res_holder, - pr_data.pr_scope, pr_data.pr_type); + pr_data->pr_scope, pr_data->pr_type); spin_unlock(&dev->dev_reservation_lock); if (res_to_delete) { spin_lock(&dev->t10_pr.registration_lock); __core_scsi3_free_registration(dev, pr_prev_res_holder, - (pr_data.pro_sa == PRO_PREEMPT_AND_ABORT) ? + (pr_data->pro_sa == PRO_PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, 0); spin_unlock(&dev->t10_pr.registration_lock); } - if (pr_data.pro_sa == PRO_PREEMPT_AND_ABORT) { + if (pr_data->pro_sa == PRO_PREEMPT_AND_ABORT) { core_local_lun_reset(dev, NULL, &preempt_and_abort_list, NULL); core_scsi3_release_preempt_and_abort( @@ -845,7 +863,7 @@ static void target_pr_sync_cb(void *arg) pr_reg_res_holder); } - if (pr_data.pro_sa == PR_SYNC_REASON_RESET) { + if (pr_data->pro_sa == PR_SYNC_REASON_RESET) { core_local_lun_reset(dev, NULL, NULL, NULL); target_dev_ua_allocate(dev, 0x29, @@ -856,10 +874,23 @@ static void target_pr_sync_cb(void *arg) core_scsi3_update_and_write_aptpl(dev, dev->t10_pr.pr_aptpl_active); -done: kfree(pr_reg_data); } +static void target_pr_sync_cb(void *arg) +{ + struct pr_reg_lvb *pr_reg_data = NULL; + struct se_device *dev = arg; + struct pr_lvb pr_data; + int res; + + res = target_dlm_read_cluster_data(dev, &pr_data, &pr_reg_data); + if (res) + return; + + target_dlm_apply_cluster_data(dev, &pr_data, pr_reg_data); +} + static void target_spc2_reserve(struct se_device *dev, struct se_session *sess) { -- 2.25.1