Fix multiple problems around LUN disable under load.

- Move private data about ATIOs/INOTs from per-LUN to per-channel data.
This allows active commands to continue operation after LUN destruction.
This also simplifies lookup of the data by tag in some situations.
 - Unify three restart_queue processing implementations.
 - Complete all ATIOs from restart_queue on LUN disable.
 - Delete ATIO private data when command completed or aborted, not depending
on the ATIO being requeued, that was ugly hack and could never happen.  CAM
should always call ether XPT_CONT_TARGET_IO with status or XPT_ABORT.
 - Implement XPT_ABORT for queued ATIOs/INOTs to allow CAM do graceful
shutdown, not depending on LUN disable, as it is done in ahd(4)/targ(4).
 - Unify isp_endcmd() arguments to make it more usable in generic code.
 - Remove never really used LUN state reference counter.

MFC after:	2 weeks
This commit is contained in:
Alexander Motin 2017-02-22 06:43:49 +00:00
parent b28a6ab3bd
commit 8290ea90be
3 changed files with 307 additions and 456 deletions

File diff suppressed because it is too large Load Diff

View File

@ -100,7 +100,7 @@ typedef struct atio_private_data {
uint32_t bytes_xfered;
uint32_t bytes_in_transit;
uint32_t tag; /* typically f/w RX_ID */
uint32_t lun;
lun_id_t lun;
uint32_t nphdl;
uint32_t sid;
uint32_t portid;
@ -139,14 +139,12 @@ typedef struct atio_private_data {
#define ATPD_GET_SEQNO(hdrp) (((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_MASK)
#define ATPD_GET_NCAM(hdrp) ((((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0)
typedef union inot_private_data inot_private_data_t;
union inot_private_data {
inot_private_data_t *next;
struct {
isp_notify_t nt; /* must be first! */
uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
uint32_t tag_id, seq_id;
} rd;
typedef struct inot_private_data inot_private_data_t;
struct inot_private_data {
STAILQ_ENTRY(inot_private_data) next;
isp_notify_t nt;
uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
uint32_t tag_id, seq_id;
};
typedef struct isp_timed_notify_ack {
void *isp;
@ -155,21 +153,15 @@ typedef struct isp_timed_notify_ack {
struct callout timer;
} isp_tna_t;
STAILQ_HEAD(ntpdlist, inot_private_data);
typedef struct tstate {
SLIST_ENTRY(tstate) next;
lun_id_t ts_lun;
struct cam_path *owner;
struct ccb_hdr_slist atios;
struct ccb_hdr_slist inots;
uint32_t hold;
SLIST_ENTRY(tstate) next;
lun_id_t ts_lun;
struct ccb_hdr_slist atios;
struct ccb_hdr_slist inots;
struct ntpdlist restart_queue;
uint16_t atio_count;
uint16_t inot_count;
inot_private_data_t * restart_queue;
inot_private_data_t * ntfree;
inot_private_data_t ntpool[ATPDPSIZE];
LIST_HEAD(, atio_private_data) atfree;
LIST_HEAD(, atio_private_data) atused[ATPDPHASHSIZE];
atio_private_data_t atpool[ATPDPSIZE];
} tstate_t;
#define LUN_HASH_SIZE 32
@ -211,6 +203,7 @@ struct isp_nexus {
*/
SLIST_HEAD(tslist, tstate);
TAILQ_HEAD(isp_ccbq, ccb_hdr);
LIST_HEAD(atpdlist, atio_private_data);
struct isp_fc {
struct cam_sim *sim;
@ -242,6 +235,11 @@ struct isp_fc {
#ifdef ISP_TARGET_MODE
struct tslist lun_hash[LUN_HASH_SIZE];
struct isp_ccbq waitq; /* waiting CCBs */
struct ntpdlist ntfree;
inot_private_data_t ntpool[ATPDPSIZE];
struct atpdlist atfree;
struct atpdlist atused[ATPDPHASHSIZE];
atio_private_data_t atpool[ATPDPSIZE];
#if defined(DEBUG)
unsigned int inject_lost_data_frame;
#endif
@ -258,6 +256,11 @@ struct isp_spi {
#ifdef ISP_TARGET_MODE
struct tslist lun_hash[LUN_HASH_SIZE];
struct isp_ccbq waitq; /* waiting CCBs */
struct ntpdlist ntfree;
inot_private_data_t ntpool[ATPDPSIZE];
struct atpdlist atfree;
struct atpdlist atused[ATPDPHASHSIZE];
atio_private_data_t atpool[ATPDPSIZE];
#endif
int num_threads;
};

View File

@ -503,11 +503,11 @@ isp_endcmd(ispsoftc_t *isp, ...)
ct7_entry_t _ctio7;
} un;
va_list ap;
int vpidx, nphdl;
ISP_MEMZERO(&un, sizeof un);
if (IS_24XX(isp)) {
int vpidx, nphdl;
at7_entry_t *aep;
ct7_entry_t *cto = &un._ctio7;
@ -573,6 +573,9 @@ isp_endcmd(ispsoftc_t *isp, ...)
va_start(ap, isp);
aep = va_arg(ap, at2_entry_t *);
/* nphdl and vpidx are unused here. */
nphdl = va_arg(ap, int);
vpidx = va_arg(ap, int);
code = va_arg(ap, uint32_t);
hdl = va_arg(ap, uint32_t);
va_end(ap);