From: Gleb C. <lna...@ya...> - 2023-05-10 07:32:21
|
Commit: 92db6a9 GitHub URL: https://github.com/SCST-project/scst/commit/92db6a9fc58d55a0810499e273c796a97b04061b Author: Brian Meagher Date: 2023-05-10T10:31:51+03:00 Log Message: ----------- scst_pres,scst_dlm: Fix broken UNIT ATTENTION for remote PR registrants Previously, when scst_pr_send_ua_reg attempted to deliver a UNIT ATTENTION to a registrant that was on another node in a dlm-based HA cluster, the unit attention was dropped. Rectify by adding a pr_reg_queue_rem_ua function to struct scst_cl_ops and calling it from scst_pr_send_ua_reg. Each registrant will maintain an incoming 'queue' of unit attentions by adding next_rem_ua_idx to the registrant data maintained in the DLM. This will tell the other nodes which PR_REG_UA_LOCK lock to create in the lockspace in order to 'send' a unit attention to the registrant. Further, each node will also maintain two lists (pending and sent) for the outgoing unit attentions from this node to a registrant. When the recipient has read all the sent unit attentions (and cleared next_rem_ua_idx), then the sent list may be cleared. Modified Paths: -------------- scst/include/scst.h | 24 + scst/src/scst_dlm.c | 339 ++++++++++++++- scst/src/scst_dlm.h | 21 + scst/src/scst_no_dlm.c | 7 + scst/src/scst_pres.c | 4 +- scst/src/scst_pres.h | 3 + 6 files changed, 388 insertions(+), 10 deletions(-) =================================================================== diff --git a/scst/include/scst.h b/scst/include/scst.h index 0e9d299..0723d75 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2637,6 +2637,26 @@ struct scst_dev_registrant { int dlm_idx; struct scst_lksb lksb; char lvb[PR_DLM_LVB_LEN]; + uint32_t registered_by_nodeid; + + /* List of UNIT ATTENTIONs to be sent by this node to this registrant on a remote node */ + struct list_head pending_rem_ua_list; + + /* + * List of UNIT ATTENTIONs already sent by this node to this registrant on a remote node + * + * Once the remote node clears next_rem_ua_idx, we can discard the entries. + */ + struct list_head sent_rem_ua_list; + + /* + * Index to indicate the tail of a 'queue' of incoming UNIT ATTENTIONs from remote nodes + * to this node, implemented as PR_REG_UA_LOCK locks. + * + * It will be incremented by the sender of each UA, and cleared by the recipiant node when + * it reads all the UNIT ATTENTIONs directed to it. + */ + uint16_t next_rem_ua_idx; }; /** @@ -2657,6 +2677,7 @@ struct scst_dev_registrant { * reservation on @dev. * @reserve: Apply an SPC-2 reservation for session @sess on @dev if * @sess != NULL or clear that reservation if @ses == NULL. + * @pr_reg_queue_rem_ua Queue a UNIT ATTENTION to a remote registrant. */ struct scst_cl_ops { int (*pr_init)(struct scst_device *dev, const char *cl_dev_id); @@ -2679,6 +2700,9 @@ struct scst_cl_ops { bool (*is_not_rsv_holder)(struct scst_device *dev, struct scst_session *sess); void (*reserve)(struct scst_device *dev, struct scst_session *sess); + void (*pr_reg_queue_rem_ua)(struct scst_device *dev, + struct scst_dev_registrant *reg, + int key, int asc, int ascq); }; /* diff --git a/scst/src/scst_dlm.c b/scst/src/scst_dlm.c index 109dc83..c3fb411 100644 --- a/scst/src/scst_dlm.c +++ b/scst/src/scst_dlm.c @@ -33,17 +33,48 @@ #if (defined(CONFIG_DLM) || defined(CONFIG_DLM_MODULE)) && \ !defined(CONFIG_SCST_NO_DLM) +/* + * UNIT ATTENTION that is to be delivered thru DLM to another (remote) node. + */ +struct scst_dlm_rem_ua { + int key; + int asc; + int ascq; + + struct scst_lksb lksb; + char lvb[PR_DLM_LVB_LEN]; + + /* + * Keep the list entry name generic as expect to reuse the struct + * definition in multiple contexts, e.g. pending_rem_ua_list and + * sent_rem_ua_list in struct scst_dev_registrant + */ + struct list_head rem_ua_list_entry; +}; + static void scst_pr_dlm_cleanup(struct scst_device *dev); static void scst_dlm_pre_bast(void *bastarg, int mode); static void scst_dlm_post_bast(void *bastarg, int mode); static void scst_dlm_post_ast(void *astarg); +static struct scst_dlm_rem_ua *scst_dlm_alloc_rem_ua(void); +static void scst_dlm_free_rem_ua(struct scst_dlm_rem_ua *ua); +static void scst_dlm_pr_reg_release_rem_ua(struct scst_dlm_rem_ua *ua); +static void scst_dlm_pr_reg_send_rem_ua(struct scst_device *dev, + dlm_lockspace_t *ls, + struct scst_dev_registrant *reg, + struct scst_dlm_rem_ua *ua); +static void scst_dlm_rm_rem_ua_ls(dlm_lockspace_t *ls, struct scst_dlm_rem_ua *ua); +static struct scst_dlm_rem_ua *scst_dlm_pr_reg_recv_rem_ua(struct scst_device *dev, + dlm_lockspace_t *ls, + struct scst_dev_registrant *reg, + int index); static inline void compile_time_size_checks(void) { BUILD_BUG_ON(sizeof(struct pr_lvb) > PR_DLM_LVB_LEN); BUILD_BUG_ON(sizeof(struct pr_lvb) != 20); BUILD_BUG_ON(sizeof(struct pr_reg_lvb) > PR_DLM_LVB_LEN); - BUILD_BUG_ON(sizeof(struct pr_reg_lvb) != 240); + BUILD_BUG_ON(sizeof(struct pr_reg_lvb) != 248); } static void scst_dlm_ast(void *astarg) @@ -157,13 +188,33 @@ static void scst_dlm_pr_init_reg(struct scst_device *dev, reg->lksb.lksb.sb_lvbptr = (void *)reg->lvb; reg->lksb.lksb.sb_lkid = 0; reg->dlm_idx = -1; + reg->registered_by_nodeid = -1; + INIT_LIST_HEAD(®->pending_rem_ua_list); + INIT_LIST_HEAD(®->sent_rem_ua_list); } static void scst_dlm_pr_rm_reg_ls(dlm_lockspace_t *ls, - struct scst_dev_registrant *reg) + struct scst_dev_registrant *reg, + bool include_rem_ua) { int res; + if (include_rem_ua) { + struct scst_dlm_rem_ua *ua, *tmp; + + /* Drop the items on the pending list */ + list_for_each_entry_safe(ua, tmp, ®->pending_rem_ua_list, rem_ua_list_entry) { + scst_dlm_pr_reg_release_rem_ua(ua); + } + reg->next_rem_ua_idx = 0; + + /* Drop the items on the sent list */ + list_for_each_entry_safe(ua, tmp, ®->sent_rem_ua_list, rem_ua_list_entry) { + scst_dlm_rm_rem_ua_ls(ls, ua); + scst_dlm_pr_reg_release_rem_ua(ua); + } + } + if (!reg->lksb.lksb.sb_lkid) return; res = scst_dlm_unlock_wait(ls, ®->lksb); @@ -178,7 +229,7 @@ static void scst_dlm_pr_rm_reg(struct scst_device *dev, struct scst_dev_registrant *reg) { lockdep_assert_pr_write_lock_held(dev); - scst_dlm_pr_rm_reg_ls(dev->pr_dlm->ls, reg); + scst_dlm_pr_rm_reg_ls(dev->pr_dlm->ls, reg, true); } /* Copy SPC-2 reservation state from the DLM LVB into @dev. */ @@ -306,7 +357,7 @@ static int scst_copy_from_dlm(struct scst_device *dev, dlm_lockspace_t *ls, list_for_each_entry(reg, &dev->dev_registrants_list, dev_registrants_list_entry) - scst_dlm_pr_rm_reg_ls(ls, reg); + scst_dlm_pr_rm_reg_ls(ls, reg, false); for (i = 0; i < nr_registrants; i++) { struct pr_reg_lvb *reg_lvb; @@ -330,10 +381,12 @@ static int scst_copy_from_dlm(struct scst_device *dev, dlm_lockspace_t *ls, rel_tgt_id, reg_lvb->key, false); if (reg) { - scst_dlm_pr_rm_reg_ls(ls, reg); + scst_dlm_pr_rm_reg_ls(ls, reg, false); reg->lksb.lksb.sb_lkid = reg_lksb[i].lksb.sb_lkid; reg->dlm_idx = i; - memcpy(reg->lvb, reg_lvb_content, sizeof(reg->lvb)); + reg->registered_by_nodeid = be32_to_cpu(reg_lvb->registered_by_nodeid); + reg->next_rem_ua_idx = be16_to_cpu(reg_lvb->next_rem_ua_idx); + memcpy(reg->lvb, reg_lvb, sizeof(reg->lvb)); if (reg_lvb->is_holder) { if (dev->pr_is_set) scst_pr_clear_holder(dev); @@ -346,6 +399,29 @@ static int scst_copy_from_dlm(struct scst_device *dev, dlm_lockspace_t *ls, scst_dlm_unlock_wait(ls, ®_lksb[i]); continue; } + + /* Does the registrant have UAs that need to be delivered here? */ + if (unlikely((reg->registered_by_nodeid == pr_dlm->local_nodeid) && + (reg->next_rem_ua_idx))) { + struct scst_dlm_rem_ua *ua; + int j; + + for (j = 0; j < reg->next_rem_ua_idx; j++) { + ua = scst_dlm_pr_reg_recv_rem_ua(dev, ls, reg, j); + if (ua) { + if (reg->tgt_dev) + scst_pr_send_ua_reg(dev, reg, ua->key, + ua->asc, ua->ascq); + scst_dlm_free_rem_ua(ua); + } + } + /* Reset the incoming queue and tell other nodes to re-read */ + reg->next_rem_ua_idx = 0; + reg_lvb->next_rem_ua_idx = cpu_to_be16(reg->next_rem_ua_idx); + memcpy(reg->lvb, reg_lvb, sizeof(reg->lvb)); + *modified_lvb = true; + } + scst_dlm_lock_wait(ls, DLM_LOCK_CR, ®->lksb, DLM_LKF_CONVERT | DLM_LKF_VALBLK, NULL, NULL); @@ -422,6 +498,7 @@ static void scst_copy_to_dlm(struct scst_device *dev, dlm_lockspace_t *ls) struct pr_lvb *lvb = (void *)pr_dlm->lvb; struct pr_reg_lvb *reg_lvb; struct scst_dev_registrant *reg; + struct scst_dlm_rem_ua *ua; int i; char reg_name[32]; uint32_t nr_registrants, tid_size; @@ -444,14 +521,17 @@ static void scst_copy_to_dlm(struct scst_device *dev, dlm_lockspace_t *ls) list_for_each_entry(reg, &dev->dev_registrants_list, dev_registrants_list_entry) { if (reg->dlm_idx >= nr_registrants) - scst_dlm_pr_rm_reg_ls(ls, reg); + scst_dlm_pr_rm_reg_ls(ls, reg, false); if (reg->dlm_idx < 0) { i = scst_get_available_dlm_idx(dev); snprintf(reg_name, sizeof(reg_name), PR_REG_LOCK, i); if (scst_dlm_lock_wait(ls, DLM_LOCK_NL, ®->lksb, 0, reg_name, NULL) - >= 0) + >= 0) { reg->dlm_idx = i; + reg->registered_by_nodeid = pr_dlm->local_nodeid; + reg->next_rem_ua_idx = 0; + } } } @@ -469,6 +549,8 @@ static void scst_copy_to_dlm(struct scst_device *dev, dlm_lockspace_t *ls) reg_lvb->rel_tgt_id = cpu_to_be16(reg->rel_tgt_id); reg_lvb->version = 1; reg_lvb->is_holder = dev->pr_holder == reg; + reg_lvb->registered_by_nodeid = cpu_to_be32(reg->registered_by_nodeid); + reg_lvb->next_rem_ua_idx = cpu_to_be16(reg->next_rem_ua_idx); tid_size = scst_tid_size(reg->transport_id); #if 0 PRINT_INFO("Copying transport ID into %s." PR_REG_LOCK @@ -482,6 +564,45 @@ static void scst_copy_to_dlm(struct scst_device *dev, dlm_lockspace_t *ls) sizeof(reg_lvb->tid))) tid_size = sizeof(reg_lvb->tid); memcpy(reg_lvb->tid, reg->transport_id, tid_size); + + /* + * If the destination has consumed all the UAs, then + * remove any that we sent and recorded. + */ + if (reg->next_rem_ua_idx == 0) { + while (!list_empty(®->sent_rem_ua_list)) { + ua = list_first_entry(®->sent_rem_ua_list, + struct scst_dlm_rem_ua, + rem_ua_list_entry); + scst_dlm_rm_rem_ua_ls(ls, ua); + scst_dlm_pr_reg_release_rem_ua(ua); + } + } + + /* + * Do we have UA's to deliver for this registrant? + * + * If so, generate a lock and keep a record of it. + */ + while (!list_empty(®->pending_rem_ua_list)) { + ua = list_first_entry(®->pending_rem_ua_list, + struct scst_dlm_rem_ua, rem_ua_list_entry); + + list_del_init(&ua->rem_ua_list_entry); + + /* + * Create new lock, add the entry to sent_rem_ua_list and increment + * next_rem_ua_idx. + */ + scst_dlm_pr_reg_send_rem_ua(dev, ls, reg, ua); + } + + /* + * We may have just increased next_rem_ua_idx in the above loop + * (scst_dlm_pr_reg_send_rem_ua) + */ + reg_lvb->next_rem_ua_idx = cpu_to_be16(reg->next_rem_ua_idx); + scst_dlm_lock_wait(ls, DLM_LOCK_CR, ®->lksb, DLM_LKF_CONVERT | DLM_LKF_VALBLK, reg_name, NULL); @@ -720,7 +841,7 @@ static void scst_dlm_remove_locks(struct scst_pr_dlm_data *pr_dlm, scst_pr_write_lock(dev); list_for_each_entry(reg, &dev->dev_registrants_list, dev_registrants_list_entry) - scst_dlm_pr_rm_reg_ls(ls, reg); + scst_dlm_pr_rm_reg_ls(ls, reg, true); scst_pr_write_unlock(dev); scst_dlm_remove_lock(ls, &pr_dlm->pre_join_lksb, NULL); @@ -1494,6 +1615,205 @@ static void scst_pr_dlm_cleanup(struct scst_device *dev) dev->pr_dlm = NULL; } +static struct scst_dlm_rem_ua *scst_dlm_alloc_rem_ua(void) +{ + struct scst_dlm_rem_ua *ua = NULL; + + ua = kzalloc(sizeof(struct scst_dlm_rem_ua), GFP_KERNEL); + if (ua == NULL) { + PRINT_ERROR("Unable to allocate unit attention"); + goto out; + } + + TRACE_MEM("Allocated dlm ua %p", ua); + + ua->lksb.lksb.sb_lvbptr = (void *)ua->lvb; + ua->lksb.lksb.sb_lkid = 0; + +out: + return ua; +} + +static void scst_dlm_free_rem_ua(struct scst_dlm_rem_ua *ua) +{ + TRACE_MEM("Freeing dlm ua %p", ua); + kfree(ua); +} + +/* + * scst_dlm_pr_reg_queue_rem_ua - queue a remote unit attention for transmition to the remote node + */ +static void scst_dlm_pr_reg_queue_rem_ua(struct scst_device *dev, + struct scst_dev_registrant *reg, + int key, int asc, int ascq) +{ + struct scst_dlm_rem_ua *ua = NULL; + struct scst_pr_dlm_data *const pr_dlm = dev->pr_dlm; + + TRACE_ENTRY(); + + ua = scst_dlm_alloc_rem_ua(); + if (ua == NULL) { + PRINT_ERROR("Unable to allocate unit attention for dlm registrant"); + return; + } + + ua->key = key; + ua->asc = asc; + ua->ascq = ascq; + + /* + * Lock to ensure we are not currently doing a scst_copy_to_dlm or + * scst_copy_from_dlm. + */ + mutex_lock(&pr_dlm->ls_mutex); + list_add_tail(&ua->rem_ua_list_entry, ®->pending_rem_ua_list); + mutex_unlock(&pr_dlm->ls_mutex); + + TRACE_EXIT(); +} + +/* + * scst_dlm_pr_reg_release_rem_ua - remove from list and free remote unit attention data structure + */ +static void scst_dlm_pr_reg_release_rem_ua(struct scst_dlm_rem_ua *ua) +{ + TRACE_ENTRY(); + + TRACE_DBG("Releasing dlm ua %p", ua); + list_del(&ua->rem_ua_list_entry); + scst_dlm_free_rem_ua(ua); + + TRACE_EXIT(); +} + +/* + * scst_dlm_pr_reg_send_rem_ua - send a unit attention to the registrant on a remote node + * + * This will create a lock containing the necessary UA information, increment next_rem_ua_idx and + * add the struct scst_dlm_rem_ua to the registrant's sent_rem_ua_list. + */ +static void scst_dlm_pr_reg_send_rem_ua(struct scst_device *dev, dlm_lockspace_t *ls, + struct scst_dev_registrant *reg, struct scst_dlm_rem_ua *ua) +{ + char reg_ua_name[32]; + struct dlm_ua_lvb *ua_lvb; + + TRACE_ENTRY(); + + snprintf(reg_ua_name, sizeof(reg_ua_name), PR_REG_UA_LOCK, reg->dlm_idx, + reg->next_rem_ua_idx); + + /* Always create a new lock. */ + if (scst_dlm_lock_wait(ls, DLM_LOCK_NL, &ua->lksb, 0, reg_ua_name, NULL) < 0) { + PRINT_ERROR("Failed to lock (NL) %s.%s", dev->virt_name, reg_ua_name); + goto out; + } + + if (scst_dlm_lock_wait(ls, DLM_LOCK_PW, &ua->lksb, + DLM_LKF_VALBLK | DLM_LKF_CONVERT, + reg_ua_name, NULL) < 0) { + PRINT_ERROR("Failed to lock %s.%s", dev->virt_name, reg_ua_name); + goto out; + } + + ua_lvb = (void *)ua->lksb.lksb.sb_lvbptr; + + memset(ua->lvb, 0, sizeof(ua->lvb)); + ua_lvb->version = 1; + ua_lvb->key = ua->key; + ua_lvb->asc = ua->asc; + ua_lvb->ascq = ua->ascq; + + scst_dlm_lock_wait(ls, DLM_LOCK_CR, &ua->lksb, + DLM_LKF_CONVERT | DLM_LKF_VALBLK, + reg_ua_name, NULL); + reg->next_rem_ua_idx++; + list_add_tail(&ua->rem_ua_list_entry, ®->sent_rem_ua_list); + +out: + TRACE_EXIT(); +} + +/* + * scst_dlm_rm_rem_ua_ls - Unlock the lock associated with a remote unit attention + */ +static void scst_dlm_rm_rem_ua_ls(dlm_lockspace_t *ls, struct scst_dlm_rem_ua *ua) +{ + int res; + + if (!ua->lksb.lksb.sb_lkid) + return; + res = scst_dlm_unlock_wait(ls, &ua->lksb); + WARN(res < 0, "scst_dlm_unlock_wait(%08x) failed (%d)", + ua->lksb.lksb.sb_lkid, res); + ua->lksb.lksb.sb_lkid = 0; +} + +/* + * scst_dlm_pr_reg_recv_rem_ua - receive a remotely generated UNIT ATTENTION for this registrant + * + * This will read unit attention that was 'published' by another node as a lock. The resultant + * struct scst_dlm_rem_ua will NOT be inserted into a list on this node. + */ +static struct scst_dlm_rem_ua *scst_dlm_pr_reg_recv_rem_ua(struct scst_device *dev, + dlm_lockspace_t *ls, + struct scst_dev_registrant *reg, + int index) +{ + char reg_ua_name[32]; + struct scst_dlm_rem_ua *ua; + struct dlm_ua_lvb *ua_lvb; + int res; + + ua = scst_dlm_alloc_rem_ua(); + if (!ua) + return NULL; + + ua_lvb = (void *)ua->lksb.lksb.sb_lvbptr; + snprintf(reg_ua_name, sizeof(reg_ua_name), PR_REG_UA_LOCK, reg->dlm_idx, index); + + res = scst_dlm_lock_wait(ls, DLM_LOCK_PW, &ua->lksb, + DLM_LKF_VALBLK, reg_ua_name, NULL); + if (res < 0) { + res = -EFAULT; + PRINT_ERROR("locking %s.%s failed", dev->virt_name, + reg_ua_name); + goto cancel; + } else if (ua->lksb.lksb.sb_flags & DLM_SBF_VALNOTVALID) { + res = -EINVAL; + PRINT_WARNING("%s.%s has an invalid lock value block", + dev->virt_name, reg_ua_name); + goto unlock_cancel; + } else if (ua_lvb->version != 1) { + res = -EPROTONOSUPPORT; + PRINT_ERROR("%s.%s.version = %d instead of 1", + dev->virt_name, reg_ua_name, + ua_lvb->version); + goto unlock_cancel; + } + + ua->key = ua_lvb->key; + ua->asc = ua_lvb->asc; + ua->ascq = ua_lvb->ascq; + + /* + * Now unlock again, we're done reading this from the DLM and have no + * further interest in this lock object. + */ + scst_dlm_rm_rem_ua_ls(ls, ua); + + return ua; + +unlock_cancel: + if (ua->lksb.lksb.sb_lkid) + scst_dlm_unlock_wait(ls, &ua->lksb); + +cancel: + scst_dlm_free_rem_ua(ua); + return NULL; +} + const struct scst_cl_ops scst_dlm_cl_ops = { .pr_init = scst_pr_dlm_init, .pr_cleanup = scst_pr_dlm_cleanup, @@ -1508,6 +1828,7 @@ const struct scst_cl_ops scst_dlm_cl_ops = { .is_rsv_holder = scst_dlm_is_rsv_holder, .is_not_rsv_holder = scst_dlm_is_not_rsv_holder, .reserve = scst_dlm_reserve, + .pr_reg_queue_rem_ua = scst_dlm_pr_reg_queue_rem_ua, }; char *scst_dlm_cluster_name; diff --git a/scst/src/scst_dlm.h b/scst/src/scst_dlm.h index 4d9a926..863d3e3 100644 --- a/scst/src/scst_dlm.h +++ b/scst/src/scst_dlm.h @@ -34,6 +34,7 @@ #define PR_PRE_UPDATE_LOCK "pr_pre_%d" #define PR_POST_UPDATE_LOCK "pr_post_%d" #define PR_REG_LOCK "pr_reg_%02d" +#define PR_REG_UA_LOCK "pr_reg_%02d_ua_%02d" /* * Data members needed for managing PR data via the DLM. @@ -142,6 +143,10 @@ struct pr_lvb { * @version: version of this structure * @is_holder: whether or not holding the reservation * @tid: transport ID - up to 228 bytes for iSCSI + * @registered_by_nodeid: Corosync node ID of the node holding that + * made the registration. + * @next_rem_ua_idx: Index to be used when publishing the next UA + * @pad: Ensure this struct is a multiple of 8 bytes */ struct pr_reg_lvb { __be64 key; @@ -149,6 +154,22 @@ struct pr_reg_lvb { u8 version; u8 is_holder; u8 tid[228]; + __be32 registered_by_nodeid; + __be16 next_rem_ua_idx; + u8 pad[2]; +}; + +/** + * struct dlm_ua_lvb - PR_REG_UA_LOCK LVB data format + * @key: sense key + * @asc: additional sense code + * @ascq: additional sense code qualifier + */ +struct dlm_ua_lvb { + u8 version; + u8 key; + u8 asc; + u8 ascq; }; #endif /* __SCST_PRES_DLM_H */ diff --git a/scst/src/scst_no_dlm.c b/scst/src/scst_no_dlm.c index 54f8bb2..d8dceec 100644 --- a/scst/src/scst_no_dlm.c +++ b/scst/src/scst_no_dlm.c @@ -101,6 +101,12 @@ static void scst_no_dlm_reserve(struct scst_device *dev, dev->reserved_by = sess; } +static void scst_no_dlm_pr_reg_queue_rem_ua(struct scst_device *dev, + struct scst_dev_registrant *reg, + int key, int asc, int ascq) +{ +} + const struct scst_cl_ops scst_no_dlm_cl_ops = { .pr_init = scst_no_dlm_pr_init, .pr_cleanup = scst_no_dlm_pr_cleanup, @@ -115,4 +121,5 @@ const struct scst_cl_ops scst_no_dlm_cl_ops = { .is_rsv_holder = scst_no_dlm_is_rsv_holder, .is_not_rsv_holder = scst_no_dlm_is_not_rsv_holder, .reserve = scst_no_dlm_reserve, + .pr_reg_queue_rem_ua = scst_no_dlm_pr_reg_queue_rem_ua, }; diff --git a/scst/src/scst_pres.c b/scst/src/scst_pres.c index ce86068..b9c330a 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -539,7 +539,7 @@ static void scst_pr_remove_registrants(struct scst_device *dev) } /* Must be called under dev_pr_mutex */ -static void scst_pr_send_ua_reg(struct scst_device *dev, +void scst_pr_send_ua_reg(struct scst_device *dev, struct scst_dev_registrant *reg, int key, int asc, int ascq) { @@ -558,6 +558,8 @@ static void scst_pr_send_ua_reg(struct scst_device *dev, if (reg->tgt_dev) scst_check_set_UA(reg->tgt_dev, ua, sizeof(ua), 0); + else + dev->cl_ops->pr_reg_queue_rem_ua(dev, reg, key, asc, ascq); TRACE_EXIT(); return; diff --git a/scst/src/scst_pres.h b/scst/src/scst_pres.h index 1ab2f6e..3d68dbf 100644 --- a/scst/src/scst_pres.h +++ b/scst/src/scst_pres.h @@ -142,6 +142,9 @@ struct scst_dev_registrant *scst_pr_add_registrant(struct scst_device *dev, bool dev_lock_locked); void scst_pr_remove_registrant(struct scst_device *dev, struct scst_dev_registrant *reg); +void scst_pr_send_ua_reg(struct scst_device *dev, + struct scst_dev_registrant *reg, + int key, int asc, int ascq); void scst_pr_set_holder(struct scst_device *dev, struct scst_dev_registrant *holder, uint8_t scope, uint8_t type); |