Re: [PATCH 4/4] target/user: Don't free expired command when time out

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Looks good, would just need to be updated if cmd->data_bitmap is inlined, see previous patch's comments.

Reviewed-by: Andy Grover <agrover@xxxxxxxxxx>

On 02/24/2016 04:27 PM, Sheng Yang wrote:
Which would result in NPE after when userspace connected again.

Expired command would be freed either when handling command(by userspace),
or when device was tearing down

Signed-off-by: Sheng Yang <sheng@xxxxxxxxxx>
---
  drivers/target/target_core_user.c | 30 +++++++++++++++++++-----------
  1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index f039d48..07cdfe4 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -572,9 +572,14 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
  	struct tcmu_dev *udev = cmd->tcmu_dev;

  	if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
-		/* cmd has been completed already from timeout, just reclaim data
-		   ring space */
+		/*
+		 * cmd has been completed already from timeout, just reclaim
+		 * data ring space and free cmd
+		 */
  		free_data_area(udev, cmd);
+
+		kfree(cmd->data_bitmap);
+		kmem_cache_free(tcmu_cmd_cache, cmd);
  		return;
  	}

@@ -692,9 +697,6 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
  	target_complete_cmd(cmd->se_cmd, SAM_STAT_CHECK_CONDITION);
  	cmd->se_cmd = NULL;

-	kfree(cmd->data_bitmap);
-	kmem_cache_free(tcmu_cmd_cache, cmd);
-
  	return 0;
  }

@@ -999,12 +1001,13 @@ err_vzalloc:
  	return ret;
  }

-static int tcmu_check_pending_cmd(int id, void *p, void *data)
+static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd)
  {
-	struct tcmu_cmd *cmd = p;
-
-	if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
+	if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+		kfree(cmd->data_bitmap);
+		kmem_cache_free(tcmu_cmd_cache, cmd);
  		return 0;
+	}
  	return -EINVAL;
  }

@@ -1019,6 +1022,8 @@ static void tcmu_dev_call_rcu(struct rcu_head *p)
  static void tcmu_free_device(struct se_device *dev)
  {
  	struct tcmu_dev *udev = TCMU_DEV(dev);
+	struct tcmu_cmd *cmd;
+	bool all_expired = true;
  	int i;

  	del_timer_sync(&udev->timeout);
@@ -1028,10 +1033,13 @@ static void tcmu_free_device(struct se_device *dev)

  	/* Upper layer should drain all requests before calling this */
  	spin_lock_irq(&udev->commands_lock);
-	i = idr_for_each(&udev->commands, tcmu_check_pending_cmd, NULL);
+	idr_for_each_entry(&udev->commands, cmd, i) {
+		if (tcmu_check_and_free_pending_cmd(cmd) != 0)
+			all_expired = false;
+	}
  	idr_destroy(&udev->commands);
  	spin_unlock_irq(&udev->commands_lock);
-	WARN_ON(i);
+	WARN_ON(!all_expired);

  	/* Device was configured */
  	if (udev->uio_info.uio_dev) {


--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux