Mercurial > illumos > illumos-gate
changeset 14069:13ecd3583387
3775 Upstreaming of ALUA use-after-free fixes from Nexenta
Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com>
Reviewed by: T Nguyen <truongqnguien@gmail.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
author | Dan McDonald <danmcd@nexenta.com> |
---|---|
date | Thu, 27 Jun 2013 13:54:16 -0400 |
parents | 2547a41b1162 |
children | d4c9f8eba8fa |
files | usr/src/uts/common/io/comstar/port/pppt/pppt.c usr/src/uts/common/io/comstar/port/pppt/pppt.h usr/src/uts/common/io/comstar/port/pppt/pppt_msg.c |
diffstat | 3 files changed, 23 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/comstar/port/pppt/pppt.c Mon Jun 24 09:23:31 2013 +0200 +++ b/usr/src/uts/common/io/comstar/port/pppt/pppt.c Thu Jun 27 13:54:16 2013 -0400 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013, Nexenta Systems, Inc. All rights reserved. */ #include <sys/cpuvar.h> @@ -131,8 +132,6 @@ static pppt_status_t pppt_task_try_abort(pppt_task_t *ptask); -static pppt_status_t pppt_task_hold(pppt_task_t *ptask); - static void pppt_task_rele(pppt_task_t *ptask); static void pppt_task_update_state(pppt_task_t *ptask, @@ -801,7 +800,7 @@ pppt_task_t *ptask = task->task_port_private; pppt_sess_t *ps = ptask->pt_sess; - pppt_task_free(ptask); + pppt_task_rele(ptask); pppt_sess_rele(ps); } @@ -1209,7 +1208,7 @@ ptask->pt_state = PTS_INIT; ptask->pt_read_buf = NULL; ptask->pt_read_xfer_msgid = 0; - cv_init(&ptask->pt_cv, NULL, CV_DRIVER, NULL); + ptask->pt_refcnt = 0; mutex_init(&ptask->pt_mutex, NULL, MUTEX_DRIVER, NULL); immed_pbuf = (pppt_buf_t *)(ptask + 1); bzero(immed_pbuf, sizeof (*immed_pbuf)); @@ -1232,8 +1231,8 @@ pppt_task_free(pppt_task_t *ptask) { mutex_enter(&ptask->pt_mutex); + ASSERT(ptask->pt_refcnt == 0); mutex_destroy(&ptask->pt_mutex); - cv_destroy(&ptask->pt_cv); kmem_free(ptask, sizeof (pppt_task_t) + sizeof (pppt_buf_t) + sizeof (stmf_data_buf_t)); } @@ -1249,6 +1248,8 @@ mutex_enter(&ptask->pt_mutex); if (avl_find(&ptask->pt_sess->ps_task_list, ptask, &where) == NULL) { pppt_task_update_state(ptask, PTS_ACTIVE); + /* Manually increment refcnt, sincd we hold the mutex... */ + ptask->pt_refcnt++; avl_insert(&ptask->pt_sess->ps_task_list, ptask, where); mutex_exit(&ptask->pt_mutex); mutex_exit(&ptask->pt_sess->ps_mutex); @@ -1289,6 +1290,8 @@ mutex_enter(&ptask->pt_sess->ps_mutex); avl_remove(&ptask->pt_sess->ps_task_list, ptask); mutex_exit(&ptask->pt_sess->ps_mutex); + /* Out of the AVL tree, so drop a reference. */ + pppt_task_rele(ptask); } return (pppt_status); @@ -1401,12 +1404,14 @@ mutex_enter(&ptask->pt_sess->ps_mutex); avl_remove(&ptask->pt_sess->ps_task_list, ptask); mutex_exit(&ptask->pt_sess->ps_mutex); + /* Out of the AVL tree, so drop a reference. */ + pppt_task_rele(ptask); } return (pppt_status); } -static pppt_status_t +pppt_status_t pppt_task_hold(pppt_task_t *ptask) { pppt_status_t pppt_status = PPPT_STATUS_SUCCESS; @@ -1425,10 +1430,14 @@ static void pppt_task_rele(pppt_task_t *ptask) { + boolean_t freeit; + mutex_enter(&ptask->pt_mutex); ptask->pt_refcnt--; - cv_signal(&ptask->pt_cv); + freeit = (ptask->pt_refcnt == 0); mutex_exit(&ptask->pt_mutex); + if (freeit) + pppt_task_free(ptask); } static void @@ -1440,5 +1449,4 @@ ASSERT(mutex_owned(&ptask->pt_mutex)); ptask->pt_state = new_state; - cv_signal(&ptask->pt_cv); }
--- a/usr/src/uts/common/io/comstar/port/pppt/pppt.h Mon Jun 24 09:23:31 2013 +0200 +++ b/usr/src/uts/common/io/comstar/port/pppt/pppt.h Thu Jun 27 13:54:16 2013 -0400 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013, Nexenta Systems, Inc. All rights reserved. */ #ifndef _PPPT_H #define _PPPT_H @@ -168,7 +169,6 @@ avl_node_t pt_sess_ln; int pt_refcnt; kmutex_t pt_mutex; - kcondvar_t pt_cv; stmf_ic_msgid_t pt_task_id; uint8_t pt_lun_id[16]; pppt_task_state_t pt_state; @@ -296,6 +296,8 @@ void pppt_tgt_sm_ctl(stmf_local_port_t *lport, int cmd, void *arg); +pppt_status_t pppt_task_hold(pppt_task_t *); + #ifdef __cplusplus } #endif
--- a/usr/src/uts/common/io/comstar/port/pppt/pppt_msg.c Mon Jun 24 09:23:31 2013 +0200 +++ b/usr/src/uts/common/io/comstar/port/pppt/pppt_msg.c Thu Jun 27 13:54:16 2013 -0400 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013, Nexenta Systems, Inc. All rights reserved. */ #include <sys/cpuvar.h> @@ -316,8 +317,8 @@ scmd->icsc_task_lun_no, scmd->icsc_task_cdb_length, 0); if (ptask->pt_stmf_task == NULL) { + /* NOTE: pppt_task_done() will free ptask. */ (void) pppt_task_done(ptask); - pppt_task_free(ptask); pppt_sess_rele(pppt_sess); pppt_msg_tx_status(msg, STMF_ALLOC_FAILURE); stmf_ic_msg_free(msg); @@ -326,6 +327,8 @@ } task = ptask->pt_stmf_task; + /* task_port_private reference is a real reference. */ + (void) pppt_task_hold(ptask); task->task_port_private = ptask; task->task_flags = scmd->icsc_task_flags; task->task_additional_flags = 0;