History

scsi: target: tcmu: Add new feature KEEP_BUF

When running command pipelining for WRITE direction commands (e.g. tape device write), userspace sends cmd completion to cmd ring before processing write data. In that case userspace has to copy data before sending completion, because cmd completion also implicitly releases the data buffer in data area. The new feature KEEP_BUF allows userspace to optionally keep the buffer after completion by setting new bit TCMU_UFLAG_KEEP_BUF in tcmu_cmd_entry_hdr->uflags. In that case buffer has to be released explicitly by writing the cmd_id to new action item free_kept_buf. All kept buffers are released during reset_ring and if userspace closes uio device (tcmu_release).

Bodo Stroesser committed 5 years ago

Commit 018c1491 parent c11a1ae2 files · +141 −11Browse files

Unified · Split

2 files
  1. drivers/target/target_core_user.c +139 −11
  2. include/uapi/linux/target_core_user.h +2 −0
drivers/target/target_core_user.c+139−11
@@ -191,6 +191,7 @@ struct tcmu_cmd { · 190 unmodified lines
191191 unsigned long deadline;
192192
193193 #define TCMU_CMD_BIT_EXPIRED 0
194+#define TCMU_CMD_BIT_KEEP_BUF 1
194195 unsigned long flags;
195196 };
196197
@@ -1315,11 +1316,13 @@ unlock: · 1118 unmodified lines
13151316 mutex_unlock(&udev->cmdr_lock);
13161317 }
13171318
1318−static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *entry)
1319+static bool tcmu_handle_completion(struct tcmu_cmd *cmd,
1320+ struct tcmu_cmd_entry *entry, bool keep_buf)
13191321 {
13201322 struct se_cmd *se_cmd = cmd->se_cmd;
13211323 struct tcmu_dev *udev = cmd->tcmu_dev;
13221324 bool read_len_valid = false;
1325+ bool ret = true;
13231326 uint32_t read_len;
13241327
13251328 /*
@@ -1330,6 +1333,13 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry * · 4 unmodified lines
13301333 WARN_ON_ONCE(se_cmd);
13311334 goto out;
13321335 }
1336+ if (test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
1337+ pr_err("cmd_id %u already completed with KEEP_BUF, ring is broken\n",
1338+ entry->hdr.cmd_id);
1339+ set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags);
1340+ ret = false;
1341+ goto out;
1342+ }
13331343
13341344 list_del_init(&cmd->queue_entry);
13351345
@@ -1379,8 +1389,22 @@ done: · 43 unmodified lines
13791389 target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status);
13801390
13811391 out:
1382− tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
1383− tcmu_free_cmd(cmd);
1392+ if (!keep_buf) {
1393+ tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
1394+ tcmu_free_cmd(cmd);
1395+ } else {
1396+ /*
1397+ * Keep this command after completion, since userspace still
1398+ * needs the data buffer. Mark it with TCMU_CMD_BIT_KEEP_BUF
1399+ * and reset potential TCMU_CMD_BIT_EXPIRED, so we don't accept
1400+ * a second completion later.
1401+ * Userspace can free the buffer later by writing the cmd_id
1402+ * to new action attribute free_kept_buf.
1403+ */
1404+ clear_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
1405+ set_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags);
1406+ }
1407+ return ret;
13841408 }
13851409
13861410 static int tcmu_run_tmr_queue(struct tcmu_dev *udev)
@@ -1432,6 +1456,7 @@ static bool tcmu_handle_completions(struct tcmu_dev *udev) · 45 unmodified lines
14321456 while (udev->cmdr_last_cleaned != READ_ONCE(mb->cmd_tail)) {
14331457
14341458 struct tcmu_cmd_entry *entry = udev->cmdr + udev->cmdr_last_cleaned;
1459+ bool keep_buf;
14351460
14361461 /*
14371462 * Flush max. up to end of cmd ring since current entry might
@@ -1453,7 +1478,11 @@ static bool tcmu_handle_completions(struct tcmu_dev *udev) · 15 unmodified lines
14531478 }
14541479 WARN_ON(tcmu_hdr_get_op(entry->hdr.len_op) != TCMU_OP_CMD);
14551480
1456− cmd = xa_erase(&udev->commands, entry->hdr.cmd_id);
1481+ keep_buf = !!(entry->hdr.uflags & TCMU_UFLAG_KEEP_BUF);
1482+ if (keep_buf)
1483+ cmd = xa_load(&udev->commands, entry->hdr.cmd_id);
1484+ else
1485+ cmd = xa_erase(&udev->commands, entry->hdr.cmd_id);
14571486 if (!cmd) {
14581487 pr_err("cmd_id %u not found, ring is broken\n",
14591488 entry->hdr.cmd_id);
@@ -1461,7 +1490,8 @@ static bool tcmu_handle_completions(struct tcmu_dev *udev) · 1 unmodified line
14611490 return false;
14621491 }
14631492
1464− tcmu_handle_completion(cmd, entry);
1493+ if (!tcmu_handle_completion(cmd, entry, keep_buf))
1494+ break;
14651495
14661496 UPDATE_HEAD(udev->cmdr_last_cleaned,
14671497 tcmu_hdr_get_len(entry->hdr.len_op),
@@ -1619,7 +1649,8 @@ static void tcmu_dev_call_rcu(struct rcu_head *p) · 151 unmodified lines
16191649
16201650 static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd)
16211651 {
1622− if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
1652+ if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) ||
1653+ test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
16231654 kmem_cache_free(tcmu_cmd_cache, cmd);
16241655 return 0;
16251656 }
@@ -1903,6 +1934,38 @@ static int tcmu_open(struct uio_info *info, struct inode *inode) · 277 unmodified lines
19031934 static int tcmu_release(struct uio_info *info, struct inode *inode)
19041935 {
19051936 struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info);
1937+ struct tcmu_cmd *cmd;
1938+ unsigned long i;
1939+ bool freed = false;
1940+
1941+ mutex_lock(&udev->cmdr_lock);
1942+
1943+ xa_for_each(&udev->commands, i, cmd) {
1944+ /* Cmds with KEEP_BUF set are no longer on the ring, but
1945+ * userspace still holds the data buffer. If userspace closes
1946+ * we implicitly free these cmds and buffers, since after new
1947+ * open the (new ?) userspace cannot find the cmd in the ring
1948+ * and thus never will release the buffer by writing cmd_id to
1949+ * free_kept_buf action attribute.
1950+ */
1951+ if (!test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags))
1952+ continue;
1953+ pr_debug("removing KEEP_BUF cmd %u on dev %s from ring\n",
1954+ cmd->cmd_id, udev->name);
1955+ freed = true;
1956+
1957+ xa_erase(&udev->commands, i);
1958+ tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
1959+ tcmu_free_cmd(cmd);
1960+ }
1961+ /*
1962+ * We only freed data space, not ring space. Therefore we dont call
1963+ * run_tmr_queue, but call run_qfull_queue if tmr_list is empty.
1964+ */
1965+ if (freed && list_empty(&udev->tmr_queue))
1966+ run_qfull_queue(udev, false);
1967+
1968+ mutex_unlock(&udev->cmdr_lock);
19061969
19071970 clear_bit(TCMU_DEV_BIT_OPEN, &udev->flags);
19081971
@@ -2147,7 +2210,8 @@ static int tcmu_configure_device(struct se_device *dev) · 238 unmodified lines
21472210 mb->version = TCMU_MAILBOX_VERSION;
21482211 mb->flags = TCMU_MAILBOX_FLAG_CAP_OOOC |
21492212 TCMU_MAILBOX_FLAG_CAP_READ_LEN |
2150− TCMU_MAILBOX_FLAG_CAP_TMR;
2213+ TCMU_MAILBOX_FLAG_CAP_TMR |
2214+ TCMU_MAILBOX_FLAG_CAP_KEEP_BUF;
21512215 mb->cmdr_off = CMDR_OFF;
21522216 mb->cmdr_size = udev->cmdr_size;
21532217
@@ -2279,12 +2343,16 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level) · 125 unmodified lines
22792343 mutex_lock(&udev->cmdr_lock);
22802344
22812345 xa_for_each(&udev->commands, i, cmd) {
2282− pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n",
2283− cmd->cmd_id, udev->name,
2284− test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags));
2346+ pr_debug("removing cmd %u on dev %s from ring %s\n",
2347+ cmd->cmd_id, udev->name,
2348+ test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) ?
2349+ "(is expired)" :
2350+ (test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags) ?
2351+ "(is keep buffer)" : ""));
22852352
22862353 xa_erase(&udev->commands, i);
2287− if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
2354+ if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) &&
2355+ !test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
22882356 WARN_ON(!cmd->se_cmd);
22892357 list_del_init(&cmd->queue_entry);
22902358 cmd->se_cmd->priv = NULL;
@@ -2933,6 +3001,65 @@ static ssize_t tcmu_reset_ring_store(struct config_item *item, const char *page, · 642 unmodified lines
29333001 }
29343002 CONFIGFS_ATTR_WO(tcmu_, reset_ring);
29353003
3004+static ssize_t tcmu_free_kept_buf_store(struct config_item *item, const char *page,
3005+ size_t count)
3006+{
3007+ struct se_device *se_dev = container_of(to_config_group(item),
3008+ struct se_device,
3009+ dev_action_group);
3010+ struct tcmu_dev *udev = TCMU_DEV(se_dev);
3011+ struct tcmu_cmd *cmd;
3012+ u16 cmd_id;
3013+ int ret;
3014+
3015+ if (!target_dev_configured(&udev->se_dev)) {
3016+ pr_err("Device is not configured.\n");
3017+ return -EINVAL;
3018+ }
3019+
3020+ ret = kstrtou16(page, 0, &cmd_id);
3021+ if (ret < 0)
3022+ return ret;
3023+
3024+ mutex_lock(&udev->cmdr_lock);
3025+
3026+ {
3027+ XA_STATE(xas, &udev->commands, cmd_id);
3028+
3029+ xas_lock(&xas);
3030+ cmd = xas_load(&xas);
3031+ if (!cmd) {
3032+ pr_err("free_kept_buf: cmd_id %d not found\n", cmd_id);
3033+ count = -EINVAL;
3034+ xas_unlock(&xas);
3035+ goto out_unlock;
3036+ }
3037+ if (!test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
3038+ pr_err("free_kept_buf: cmd_id %d was not completed with KEEP_BUF\n",
3039+ cmd_id);
3040+ count = -EINVAL;
3041+ xas_unlock(&xas);
3042+ goto out_unlock;
3043+ }
3044+ xas_store(&xas, NULL);
3045+ xas_unlock(&xas);
3046+ }
3047+
3048+ tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
3049+ tcmu_free_cmd(cmd);
3050+ /*
3051+ * We only freed data space, not ring space. Therefore we dont call
3052+ * run_tmr_queue, but call run_qfull_queue if tmr_list is empty.
3053+ */
3054+ if (list_empty(&udev->tmr_queue))
3055+ run_qfull_queue(udev, false);
3056+
3057+out_unlock:
3058+ mutex_unlock(&udev->cmdr_lock);
3059+ return count;
3060+}
3061+CONFIGFS_ATTR_WO(tcmu_, free_kept_buf);
3062+
29363063 static struct configfs_attribute *tcmu_attrib_attrs[] = {
29373064 &tcmu_attr_cmd_time_out,
29383065 &tcmu_attr_qfull_time_out,
@@ -2951,6 +3078,7 @@ static struct configfs_attribute **tcmu_attrs; · 12 unmodified lines
29513078 static struct configfs_attribute *tcmu_action_attrs[] = {
29523079 &tcmu_attr_block_dev,
29533080 &tcmu_attr_reset_ring,
3081+ &tcmu_attr_free_kept_buf,
29543082 NULL,
29553083 };
29563084
include/uapi/linux/target_core_user.h+2−0
@@ -46,6 +46,7 @@ · 45 unmodified lines
4646 #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0) /* Out-of-order completions */
4747 #define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1) /* Read data length */
4848 #define TCMU_MAILBOX_FLAG_CAP_TMR (1 << 2) /* TMR notifications */
49+#define TCMU_MAILBOX_FLAG_CAP_KEEP_BUF (1<<3) /* Keep buf after cmd completion */
4950
5051 struct tcmu_mailbox {
5152 __u16 version;
@@ -75,6 +76,7 @@ struct tcmu_cmd_entry_hdr { · 23 unmodified lines
7576 __u8 kflags;
7677 #define TCMU_UFLAG_UNKNOWN_OP 0x1
7778 #define TCMU_UFLAG_READ_LEN 0x2
79+#define TCMU_UFLAG_KEEP_BUF 0x4
7880 __u8 uflags;
7981
8082 } __packed;