Module Name: src Committed By: martin Date: Mon Dec 18 14:15:58 UTC 2023
Modified Files: src/sys/dev/iscsi [netbsd-10]: iscsi.h iscsi_globals.h iscsi_ioctl.c iscsi_send.c iscsi_text.c iscsi_utils.c Log Message: Pull up following revision(s) (requested by mlelstv in ticket #505): sys/dev/iscsi/iscsi_utils.c: revision 1.29 sys/dev/iscsi/iscsi.h: revision 1.5 sys/dev/iscsi/iscsi_ioctl.c: revision 1.34 sys/dev/iscsi/iscsi_globals.h: revision 1.28 sys/dev/iscsi/iscsi_text.c: revision 1.14 sys/dev/iscsi/iscsi_send.c: revision 1.40 Adapt to bignum representation of target. Fix negotiation for mutual authentication. Prepare for more CHAP types. Fix crashes for invalid socket descriptors passed to kernel. Protect usecount with connection mutex, avoids race on connection close. Minor cosmetics. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.4.50.1 src/sys/dev/iscsi/iscsi.h cvs rdiff -u -r1.27 -r1.27.4.1 src/sys/dev/iscsi/iscsi_globals.h cvs rdiff -u -r1.33 -r1.33.4.1 src/sys/dev/iscsi/iscsi_ioctl.c cvs rdiff -u -r1.39 -r1.39.4.1 src/sys/dev/iscsi/iscsi_send.c cvs rdiff -u -r1.13 -r1.13.28.1 src/sys/dev/iscsi/iscsi_text.c cvs rdiff -u -r1.28 -r1.28.4.1 src/sys/dev/iscsi/iscsi_utils.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/iscsi/iscsi.h diff -u src/sys/dev/iscsi/iscsi.h:1.4 src/sys/dev/iscsi/iscsi.h:1.4.50.1 --- src/sys/dev/iscsi/iscsi.h:1.4 Wed Jun 15 04:30:30 2016 +++ src/sys/dev/iscsi/iscsi.h Mon Dec 18 14:15:58 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi.h,v 1.4 2016/06/15 04:30:30 mlelstv Exp $ */ +/* $NetBSD: iscsi.h,v 1.4.50.1 2023/12/18 14:15:58 martin Exp $ */ /*- * Copyright (c) 2004,2006,2011 The NetBSD Foundation, Inc. @@ -54,6 +54,13 @@ typedef enum { Indicates SRP authentication (for future use). */ +typedef enum { + ISCSI_CHAP_MD5 = 5, + ISCSI_CHAP_SHA1 = 6, + ISCSI_CHAP_SHA256 = 7, + ISCSI_CHAP_SHA3_256 = 8 +} iscsi_chap_types_t; + typedef struct { unsigned int mutual_auth:1; unsigned int is_secure:1; Index: src/sys/dev/iscsi/iscsi_globals.h diff -u src/sys/dev/iscsi/iscsi_globals.h:1.27 src/sys/dev/iscsi/iscsi_globals.h:1.27.4.1 --- src/sys/dev/iscsi/iscsi_globals.h:1.27 Tue Sep 13 13:09:16 2022 +++ src/sys/dev/iscsi/iscsi_globals.h Mon Dec 18 14:15:58 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_globals.h,v 1.27 2022/09/13 13:09:16 mlelstv Exp $ */ +/* $NetBSD: iscsi_globals.h,v 1.27.4.1 2023/12/18 14:15:58 martin Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -135,11 +135,10 @@ /* Connection state */ typedef enum { - /* first three correspond to CSG/NSG coding */ ST_SEC_NEG = 0, /* security negotiation phase */ - ST_OP_NEG = 1, /* operational negotiation phase */ + ST_SEC_FIN = 1, /* switch from SEC after mutual CHAP */ + ST_OP_NEG = 2, /* operational negotiation phase */ ST_FULL_FEATURE = 3, /* full feature phase */ - /* rest is internal */ ST_WINDING_DOWN = 4, /* connection termination initiated, logging out */ ST_LOGOUT_SENT = 5, /* logout has been sent */ ST_SETTLING = 6, /* waiting for things to settle down */ Index: src/sys/dev/iscsi/iscsi_ioctl.c diff -u src/sys/dev/iscsi/iscsi_ioctl.c:1.33 src/sys/dev/iscsi/iscsi_ioctl.c:1.33.4.1 --- src/sys/dev/iscsi/iscsi_ioctl.c:1.33 Tue Sep 13 13:09:16 2022 +++ src/sys/dev/iscsi/iscsi_ioctl.c Mon Dec 18 14:15:58 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_ioctl.c,v 1.33 2022/09/13 13:09:16 mlelstv Exp $ */ +/* $NetBSD: iscsi_ioctl.c,v 1.33.4.1 2023/12/18 14:15:58 martin Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -728,18 +728,11 @@ create_connection(iscsi_login_parameters } rc = get_socket(par->socket, &conn->c_sock); - fd_close(par->socket); + if (rc != EBADF) + fd_close(par->socket); if (rc) { DEBOUT(("Invalid socket %d\n", par->socket)); - - callout_destroy(&conn->c_timeout); - rw_destroy(&conn->c_sock_rw); - cv_destroy(&conn->c_idle_cv); - cv_destroy(&conn->c_ccb_cv); - cv_destroy(&conn->c_pdu_cv); - cv_destroy(&conn->c_conn_cv); - mutex_destroy(&conn->c_lock); free(conn, M_DEVBUF); par->status = ISCSI_STATUS_INVALID_SOCKET; return rc; @@ -901,11 +894,13 @@ recreate_connection(iscsi_login_paramete DEBOUT(("Too many connections (max = %d, curr = %d)\n", sess->s_MaxConnections, sess->s_active_connections)); - /* Always close the desecriptor */ - fd_close(par->socket); + /* Close the desecriptor */ + rc = EIO; + if (fd_getfile(par->socket) != NULL) + rc = fd_close(par->socket); par->status = ISCSI_STATUS_MAXED_CONNECTIONS; - return EIO; + return rc; } rw_enter(&conn->c_sock_rw, RW_WRITER); @@ -915,7 +910,8 @@ recreate_connection(iscsi_login_paramete } rc = get_socket(par->socket, &conn->c_sock); rw_exit(&conn->c_sock_rw); - fd_close(par->socket); + if (rc != EBADF) + fd_close(par->socket); if (rc) { DEBOUT(("Invalid socket %d\n", par->socket)); @@ -1739,19 +1735,23 @@ iscsi_cleanup_thread(void *par) * the send/recv threads have been killed */ DEBC(conn, 5, ("Cleanup: Waiting for threads to exit\n")); + + mutex_enter(&conn->c_lock); while (conn->c_sendproc || conn->c_rcvproc) - kpause("threads", false, hz, NULL); + kpause("threads", false, hz, &conn->c_lock); for (s=1; conn->c_usecount > 0 && s < 3; ++s) - kpause("usecount", false, hz, NULL); + kpause("usecount", false, hz, &conn->c_lock); if (conn->c_usecount > 0) { DEBC(conn, 5, ("Cleanup: %d CCBs busy\n", conn->c_usecount)); + mutex_exit(&conn->c_lock); /* retry later */ mutex_enter(&iscsi_cleanup_mtx); TAILQ_INSERT_HEAD(&iscsi_cleanupc_list, conn, c_connections); continue; } + mutex_exit(&conn->c_lock); KASSERT(!conn->c_in_session); @@ -1838,7 +1838,7 @@ iscsi_cleanup_thread(void *par) conn->c_timedout = TOUT_NONE; } - /* Go to sleep, but wake up every 30 seconds to + /* Go to sleep, but wake up every 120 seconds to * check for dead event handlers */ rc = cv_timedwait(&iscsi_cleanup_cv, &iscsi_cleanup_mtx, (TAILQ_FIRST(&event_handlers)) ? 120 * hz : 0); Index: src/sys/dev/iscsi/iscsi_send.c diff -u src/sys/dev/iscsi/iscsi_send.c:1.39 src/sys/dev/iscsi/iscsi_send.c:1.39.4.1 --- src/sys/dev/iscsi/iscsi_send.c:1.39 Tue Sep 13 13:09:16 2022 +++ src/sys/dev/iscsi/iscsi_send.c Mon Dec 18 14:15:58 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_send.c,v 1.39 2022/09/13 13:09:16 mlelstv Exp $ */ +/* $NetBSD: iscsi_send.c,v 1.39.4.1 2023/12/18 14:15:58 martin Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -34,7 +34,6 @@ #include <sys/filedesc.h> #include <sys/socket.h> #include <sys/socketvar.h> -#include <sys/atomic.h> /*#define LUN_1 1 */ @@ -242,10 +241,6 @@ reassign_tasks(connection_t *oldconn) /* reset timeouts */ ccb->ccb_num_timeouts = 0; - /* fixup reference counts */ - oldconn->c_usecount--; - atomic_inc_uint(&conn->c_usecount); - DEBC(conn, 1, ("CCB %p: Copied PDU %p to %p\n", ccb, opdu, pdu)); @@ -255,9 +250,17 @@ reassign_tasks(connection_t *oldconn) /* and free the old PDU */ free_pdu(opdu); - /* put ready CCB into waiting list of new connection */ mutex_enter(&conn->c_lock); + + /* fixup reference counts */ + mutex_enter(&oldconn->c_lock); + oldconn->c_usecount--; + conn->c_usecount++; + mutex_exit(&oldconn->c_lock); + + /* put ready CCB into waiting list of new connection */ suspend_ccb(ccb, TRUE); + mutex_exit(&conn->c_lock); } @@ -683,6 +686,11 @@ init_login_pdu(connection_t *conn, ccb_t NEXT_PHASE(c_phase); } + DEB(99, ("InitLoginPdu: Flags=%x Phase=%x->%x\n", + hpdu->pduh_Flags, + (hpdu->pduh_Flags >> CSG_SHIFT) & SG_MASK, + hpdu->pduh_Flags & SG_MASK)); + memcpy(isid, &iscsi_InitiatorISID, 6); isid->TSIH = conn->c_session->s_TSIH; @@ -748,6 +756,27 @@ negotiate_login(connection_t *conn, pdu_ break; case SG_LOGIN_OPERATIONAL_NEGOTIATION: + + if (conn->c_state == ST_SEC_FIN) { + + /* + * Both sides announced to continue with + * operational negotation, but this is the + * last target packet from mutual CHAP + * that needs to be validated. + */ + rc = assemble_security_parameters(conn, tx_ccb, rx_pdu, tx_pdu); + if (rc) + break; + + /* + * Response was valid, drop (security) parameters + * so that we start negotiating operational + * parameters. + */ + rx_pdu->pdu_temp_data = NULL; + } + rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu); break; @@ -1699,13 +1728,22 @@ ccb_timeout(ccb_t *ccb) DEBC(conn, 0, ("ccb_timeout: num=%d total=%d disp=%d\n", ccb->ccb_num_timeouts+1, ccb->ccb_total_tries, ccb->ccb_disp)); + /* + * XXX can we time out after connection is closed ? + */ + if (conn == NULL) { + wake_ccb(ccb, ISCSI_STATUS_TIMEOUT); + return; + } + if (++ccb->ccb_num_timeouts > MAX_CCB_TIMEOUTS || ccb->ccb_total_tries > MAX_CCB_TRIES || ccb->ccb_disp <= CCBDISP_FREE || !ccb->ccb_session->s_ErrorRecoveryLevel) { wake_ccb(ccb, ISCSI_STATUS_TIMEOUT); - handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION); + handle_connection_error(conn, + ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION); } else { if (ccb->ccb_data_in && ccb->ccb_xfer_len < ccb->ccb_data_len) { /* request resend of all missing data */ Index: src/sys/dev/iscsi/iscsi_text.c diff -u src/sys/dev/iscsi/iscsi_text.c:1.13 src/sys/dev/iscsi/iscsi_text.c:1.13.28.1 --- src/sys/dev/iscsi/iscsi_text.c:1.13 Sun Apr 21 11:45:08 2019 +++ src/sys/dev/iscsi/iscsi_text.c Mon Dec 18 14:15:58 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_text.c,v 1.13 2019/04/21 11:45:08 maya Exp $ */ +/* $NetBSD: iscsi_text.c,v 1.13.28.1 2023/12/18 14:15:58 martin Exp $ */ /*- * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc. @@ -133,7 +133,7 @@ typedef struct STATIC key_entry_t entries[] = { {"AuthMethod", T_AUTH, 0}, - {"CHAP_A", T_NUM, 5}, + {"CHAP_A", T_NUM, ISCSI_CHAP_MD5}, {"CHAP_C", T_BIGNUM, 0}, {"CHAP_I", T_NUM, 0}, {"CHAP_N", T_STRING, 0}, @@ -170,14 +170,14 @@ STATIC key_entry_t entries[] = { /* a negotiation parameter: key and values (there may be more than 1 for lists) */ typedef struct { - text_key_t key; /* the key */ - int list_num; /* number of elements in list, doubles as */ - bool hex_bignums; /* whether to encode in hex or base64 */ - /* data size for large numeric values */ + text_key_t key; /* the key */ + int list_num; /* number of elements in list, doubles as */ + /* data size for large numeric values */ + bool hex_bignums; /* whether to encode in hex or base64 */ union { - uint32_t nval[MAX_LIST]; /* numeric or enumeration values */ - uint8_t *sval; /* string or data pointer */ + uint32_t nval[MAX_LIST];/* numeric or enumeration values */ + uint8_t *sval; /* string or data pointer */ } val; } negotiation_parameter_t; @@ -220,7 +220,6 @@ typedef struct /*****************************************************************************/ - STATIC void chap_md5_response(uint8_t *buffer, uint8_t identifier, uint8_t *secret, uint8_t *challenge, int challenge_size) @@ -234,7 +233,6 @@ chap_md5_response(uint8_t *buffer, uint8 MD5Final(buffer, &md5); } - /*****************************************************************************/ /* @@ -322,6 +320,7 @@ get_bignumval(uint8_t *buf, negotiation_ } buf++; par->list_num = dp - par->val.sval; + par->hex_bignums = true; } else if (buf[0] == '0' && (buf[1] == 'b' || buf[1] == 'B')) { buf = base64_decode(&buf[2], par->val.sval, &par->list_num); } else { @@ -340,12 +339,13 @@ get_bignumval(uint8_t *buf, negotiation_ * Parameter: * buf The buffer pointer * pval The pointer to the result. + * sep Separator to next value. * * Returns: The pointer to the next parameter, NULL on error. */ STATIC uint8_t * -get_numval(uint8_t *buf, uint32_t *pval) +get_numval(uint8_t *buf, uint32_t *pval, const uint8_t sep) { uint32_t val = 0; char c; @@ -389,11 +389,11 @@ STATIC uint8_t * get_range(uint8_t *buf, uint32_t *pval1, uint32_t *pval2) { - if ((buf = get_numval(buf, pval1)) == NULL) + if ((buf = get_numval(buf, pval1, '~')) == NULL) return NULL; if (!*buf) return NULL; - if ((buf = get_numval(buf, pval2)) == NULL) + if ((buf = get_numval(buf, pval2, '~')) == NULL) return NULL; return buf; } @@ -539,6 +539,7 @@ get_parameter(uint8_t *buf, negotiation_ par->key = i; par->list_num = 1; + par->hex_bignums = false; /* set by get_bignumval */ if (i > MAX_KEY) { DEBOUT(("get_parameter: unrecognized key <%s>\n", buf)); @@ -556,7 +557,7 @@ get_parameter(uint8_t *buf, negotiation_ switch (entries[i].val) { case T_NUM: - bp = get_numval(bp, &par->val.nval[0]); + bp = get_numval(bp, &par->val.nval[0], '\0'); break; case T_BIGNUM: @@ -927,6 +928,12 @@ complete_pars(negotiation_state_t *state DEB(10, ("complete_pars: n=%d, len=%d\n", state->num_pars, len)); + if (len == 0) { + pdu->pdu_temp_data = NULL; + pdu->pdu_temp_data_len = 0; + return 0; + } + if ((bp = malloc(len, M_TEMP, M_WAITOK)) == NULL) { DEBOUT(("*** Out of memory in complete_pars\n")); return ISCSI_STATUS_NO_RESOURCES; @@ -1313,7 +1320,6 @@ assemble_login_parameters(connection_t * return (next) ? 0 : -1; } - /* * assemble_security_parameters: * Assemble the security negotiation parameters. @@ -1342,6 +1348,7 @@ assemble_security_parameters(connection_ int challenge_size = 0; uint8_t *response = NULL; int response_size = 0; + bool challenge_hex = iscsi_hex_bignums; state->num_pars = 0; next = 0; @@ -1385,7 +1392,7 @@ assemble_security_parameters(connection_ case K_Auth_CHAP_Algorithm: if (state->auth_state != AUTH_CHAP_ALG_SENT || - rxp.val.nval[0] != 5) { + rxp.val.nval[0] != ISCSI_CHAP_MD5) { DEBOUT(("Bad algorithm, auth_state = %d, alg %d\n", state->auth_state, rxp.val.nval[0])); return ISCSI_STATUS_NEGOTIATION_ERROR; @@ -1400,6 +1407,8 @@ assemble_security_parameters(connection_ } challenge = rxp.val.sval; challenge_size = rxp.list_num; + /* respond in the same format as the challenge */ + challenge_hex = rxp.hex_bignums; break; case K_Auth_CHAP_Identifier: @@ -1428,8 +1437,11 @@ assemble_security_parameters(connection_ } response = rxp.val.sval; response_size = rxp.list_num; - if (response_size != CHAP_MD5_SIZE) + if (response_size != CHAP_MD5_SIZE) { + DEBOUT(("CHAP Response, bad size %d\n", + response_size)); return ISCSI_STATUS_NEGOTIATION_ERROR; + } break; default: @@ -1446,7 +1458,7 @@ assemble_security_parameters(connection_ return ISCSI_STATUS_NEGOTIATION_ERROR; case AUTH_METHOD_SELECTED: - set_key_n(state, K_Auth_CHAP_Algorithm, 5); + set_key_n(state, K_Auth_CHAP_Algorithm, ISCSI_CHAP_MD5); state->auth_state = AUTH_CHAP_ALG_SENT; next = -1; break; @@ -1461,12 +1473,15 @@ assemble_security_parameters(connection_ set_key_s(state, K_Auth_CHAP_Name, state->user_name); - chap_md5_response(state->temp_buf, identifier, state->password, - challenge, challenge_size); + chap_md5_response(state->temp_buf, identifier, + state->password, challenge, challenge_size); cpar = set_key_s(state, K_Auth_CHAP_Response, state->temp_buf); - if (cpar != NULL) + if (cpar != NULL) { cpar->list_num = CHAP_MD5_SIZE; + /* respond in same format as challenge */ + cpar->hex_bignums = challenge_hex; + } if (par->auth_info.mutual_auth) { if (!state->target_password[0]) { @@ -1481,9 +1496,14 @@ assemble_security_parameters(connection_ state->temp_buf[CHAP_MD5_SIZE]); cpar = set_key_s(state, K_Auth_CHAP_Challenge, &state->temp_buf[CHAP_MD5_SIZE + 1]); - if (cpar != NULL) + if (cpar != NULL) { cpar->list_num = CHAP_CHALLENGE_LEN; - next = -1; + /* use same format as target challenge */ + cpar->hex_bignums = challenge_hex; + } + + /* transitional state */ + conn->c_state = ST_SEC_FIN; } state->auth_state = AUTH_CHAP_RSP_SENT; break; @@ -1496,12 +1516,13 @@ assemble_security_parameters(connection_ } chap_md5_response(state->temp_buf, - state->temp_buf[CHAP_MD5_SIZE], - state->password, - &state->temp_buf[CHAP_MD5_SIZE + 1], - CHAP_CHALLENGE_LEN); + state->temp_buf[CHAP_MD5_SIZE], + state->target_password, + &state->temp_buf[CHAP_MD5_SIZE + 1], + CHAP_CHALLENGE_LEN); - if (memcmp(state->temp_buf, response, response_size)) { + if (response_size > sizeof(state->temp_buf) || + memcmp(state->temp_buf, response, response_size)) { DEBOUT(("Mutual authentication mismatch\n")); return ISCSI_STATUS_AUTHENTICATION_FAILED; } @@ -1533,9 +1554,9 @@ set_first_opnegs(connection_t *conn, neg iscsi_login_parameters_t *lpar = conn->c_login_par; negotiation_parameter_t *cpar; - /* Digests - suggest None,CRC32C unless the user forces a value */ + /* Digests - suggest None,CRC32C unless the user forces a value */ cpar = set_key_n(state, K_HeaderDigest, - (lpar->is_present.HeaderDigest) ? lpar->HeaderDigest : 0); + (lpar->is_present.HeaderDigest) ? lpar->HeaderDigest : 0); if (cpar != NULL && !lpar->is_present.HeaderDigest) { cpar->list_num = 2; cpar->val.nval[1] = 1; @@ -1557,16 +1578,19 @@ set_first_opnegs(connection_t *conn, neg /* First connection only */ if (!conn->c_session->s_TSIH) { state->ErrorRecoveryLevel = - (lpar->is_present.ErrorRecoveryLevel) ? lpar->ErrorRecoveryLevel - : 2; + (lpar->is_present.ErrorRecoveryLevel) ? + lpar->ErrorRecoveryLevel : 2; /* - Negotiate InitialR2T to FALSE and ImmediateData to TRUE, should - be slightly more efficient than the default InitialR2T=TRUE. + * Negotiate InitialR2T to FALSE and ImmediateData to + * TRUE, should be slightly more efficient than the + * default InitialR2T=TRUE. */ state->InitialR2T = FALSE; state->ImmediateData = TRUE; - /* We don't really care about this, so don't negotiate by default */ + /* We don't really care about this, so don't negotiate + * by default + */ state->MaxBurstLength = entries[K_MaxBurstLength].defval; state->FirstBurstLength = entries[K_FirstBurstLength].defval; state->MaxOutstandingR2T = entries[K_MaxOutstandingR2T].defval; @@ -1625,7 +1649,7 @@ assemble_negotiation_parameters(connecti DEBC(conn, 10, ("AsmNegParams: connState=%d, MRDSL=%d\n", conn->c_state, state->MaxRecvDataSegmentLength)); - if (conn->c_state == ST_SEC_NEG) { + if (conn->c_state == ST_SEC_NEG || conn->c_state == ST_SEC_FIN) { conn->c_state = ST_OP_NEG; set_first_opnegs(conn, state); } @@ -1709,6 +1733,7 @@ assemble_send_targets(pdu_t *pdu, uint8_ par.key = K_SendTargets; par.list_num = 1; par.val.sval = val; + par.hex_bignums = false; len = parameter_size(&par); @@ -1719,8 +1744,10 @@ assemble_send_targets(pdu_t *pdu, uint8_ pdu->pdu_temp_data = buf; pdu->pdu_temp_data_len = len; - if (put_parameter(buf, len, &par) == 0) + if (put_parameter(buf, len, &par) == 0) { + DEBOUT(("trying to put zero sized buffer\n")); return ISCSI_STATUS_PARAMETER_INVALID; + } return 0; } Index: src/sys/dev/iscsi/iscsi_utils.c diff -u src/sys/dev/iscsi/iscsi_utils.c:1.28 src/sys/dev/iscsi/iscsi_utils.c:1.28.4.1 --- src/sys/dev/iscsi/iscsi_utils.c:1.28 Tue Sep 13 13:09:16 2022 +++ src/sys/dev/iscsi/iscsi_utils.c Mon Dec 18 14:15:58 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_utils.c,v 1.28 2022/09/13 13:09:16 mlelstv Exp $ */ +/* $NetBSD: iscsi_utils.c,v 1.28.4.1 2023/12/18 14:15:58 martin Exp $ */ /*- * Copyright (c) 2004,2005,2006,2008 The NetBSD Foundation, Inc. @@ -235,7 +235,9 @@ get_ccb(connection_t *conn, bool waitok) ccb->ccb_disp = CCBDISP_NOWAIT; ccb->ccb_connection = conn; ccb->ccb_num_timeouts = 0; - atomic_inc_uint(&conn->c_usecount); + mutex_enter(&conn->c_lock); + conn->c_usecount++; + mutex_exit(&conn->c_lock); DEBC(conn, 15, ( "get_ccb: ccb = %p, usecount = %d\n", @@ -264,8 +266,10 @@ free_ccb(ccb_t *ccb) KASSERT((ccb->ccb_flags & CCBF_WAITQUEUE) == 0); - atomic_dec_uint(&conn->c_usecount); ccb->ccb_connection = NULL; + mutex_enter(&conn->c_lock); + conn->c_usecount--; + mutex_exit(&conn->c_lock); if (ccb->ccb_disp > CCBDISP_NOWAIT) { DEBOUT(("Freeing CCB with disp %d\n",ccb->ccb_disp));