Otherwise the thread1 may be blocked during the transaction start
in tgt_client_data_update() with 'ted_lcd_lock' held because another
thread2 may be blocked by such lock in tgt_txn_stop_cb() but with
transaction handle started. That is deadlock.
Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: Id623d171e43beaa54ae4a9718fb4dc52c474df01
Reviewed-on: http://review.whamcloud.com/23129
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Tested-by: Jenkins
Reviewed-by: Mike Pershin <mike.pershin@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
RETURN(PTR_ERR(th));
tti_buf_lcd(tti);
RETURN(PTR_ERR(th));
tti_buf_lcd(tti);
- mutex_lock(&ted->ted_lcd_lock);
rc = dt_declare_record_write(env, tgt->lut_last_rcvd,
&tti->tti_buf,
ted->ted_lr_off, th);
rc = dt_declare_record_write(env, tgt->lut_last_rcvd,
&tti->tti_buf,
ted->ted_lr_off, th);
rc = dt_trans_start_local(env, tgt->lut_bottom, th);
if (rc)
GOTO(out, rc);
rc = dt_trans_start_local(env, tgt->lut_bottom, th);
if (rc)
GOTO(out, rc);
+
+ mutex_lock(&ted->ted_lcd_lock);
+
/*
* Until this operations will be committed the sync is needed
* for this export. This should be done _after_ starting the
/*
* Until this operations will be committed the sync is needed
* for this export. This should be done _after_ starting the
tti->tti_off = ted->ted_lr_off;
rc = tgt_client_data_write(env, tgt, ted->ted_lcd, &tti->tti_off, th);
tti->tti_off = ted->ted_lr_off;
rc = tgt_client_data_write(env, tgt, ted->ted_lcd, &tti->tti_off, th);
+
+ mutex_unlock(&ted->ted_lcd_lock);
+
- mutex_unlock(&ted->ted_lcd_lock);
dt_trans_stop(env, tgt->lut_bottom, th);
CDEBUG(D_INFO, "%s: update last_rcvd client data for UUID = %s, "
"last_transno = %llu: rc = %d\n", tgt->lut_obd->obd_name,
dt_trans_stop(env, tgt->lut_bottom, th);
CDEBUG(D_INFO, "%s: update last_rcvd client data for UUID = %s, "
"last_transno = %llu: rc = %d\n", tgt->lut_obd->obd_name,