| From a6bc8274c3ed2f0f3c4ba7564b988ec977a5547d Mon Sep 17 00:00:00 2001 |
| From: Kaike Wan <kaike.wan@intel.com> |
| Date: Mon, 10 Feb 2020 08:10:26 -0500 |
| Subject: [PATCH] IB/hfi1: Acquire lock to release TID entries when user file |
| is closed |
| |
| commit a70ed0f2e6262e723ae8d70accb984ba309eacc2 upstream. |
| |
| Each user context is allocated a certain number of RcvArray (TID) |
| entries and these entries are managed through TID groups. These groups |
| are put into one of three lists in each user context: tid_group_list, |
| tid_used_list, and tid_full_list, depending on the number of used TID |
| entries within each group. When TID packets are expected, one or more |
| TID groups will be allocated. After the packets are received, the TID |
| groups will be freed. Since multiple user threads may access the TID |
| groups simultaneously, a mutex exp_mutex is used to synchronize the |
| access. However, when the user file is closed, it tries to release |
| all TID groups without acquiring the mutex first, which risks a race |
| condition with another thread that may be releasing its TID groups, |
| leading to data corruption. |
| |
| This patch addresses the issue by acquiring the mutex first before |
| releasing the TID groups when the file is closed. |
| |
| Fixes: 3abb33ac6521 ("staging/hfi1: Add TID cache receive init and free funcs") |
| Link: https://lore.kernel.org/r/20200210131026.87408.86853.stgit@awfm-01.aw.intel.com |
| Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com> |
| Signed-off-by: Kaike Wan <kaike.wan@intel.com> |
| Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> |
| Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.c b/drivers/infiniband/hw/hfi1/user_exp_rcv.c |
| index 3592a9ec155e..10e6da739db4 100644 |
| --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c |
| +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c |
| @@ -165,10 +165,12 @@ void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd) |
| if (fd->handler) { |
| hfi1_mmu_rb_unregister(fd->handler); |
| } else { |
| + mutex_lock(&uctxt->exp_mutex); |
| if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list)) |
| unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd); |
| if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list)) |
| unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd); |
| + mutex_unlock(&uctxt->exp_mutex); |
| } |
| |
| kfree(fd->invalid_tids); |
| -- |
| 2.7.4 |
| |