/** * DOC: Userspace I/O * Userspace I/O * ------------- * * Define a shared-memory interface for LIO to pass SCSI commands and * data to userspace for processing. This is to allow backends that * are too complex for in-kernel support to be possible. * * It uses the UIO framework to do a lot of the device-creation and * introspection work for us. * * See the .h file for how the ring is laid out. Note that while the * command ring is defined, the particulars of the data area are * not. Offset values in the command entry point to other locations * internal to the mmap-ed area. There is separate space outside the * command ring for data buffers. This leaves maximum flexibility for * moving buffer allocations, or even page flipping or other * allocation techniques, without altering the command ring layout. * * SECURITY: * The user process must be assumed to be malicious. There's no way to * prevent it breaking the command ring protocol if it wants, but in * order to prevent other issues we must only ever read *data* from * the shared memory area, not offsets or sizes. This applies to * command ring entries as well as the mailbox. Extra code needed for * this may have a 'UAM' comment.
*/
#define TCMU_TIME_OUT (30 * MSEC_PER_SEC)
/* For mailbox plus cmd ring, the size is fixed 8MB */ #define MB_CMDR_SIZE_DEF (8 * 1024 * 1024) /* Offset of cmd ring is size of mailbox */ #define CMDR_OFF ((__u32)sizeof(struct tcmu_mailbox)) #define CMDR_SIZE_DEF (MB_CMDR_SIZE_DEF - CMDR_OFF)
/* * For data area, the default block size is PAGE_SIZE and * the default total size is 256K * PAGE_SIZE.
*/ #define DATA_PAGES_PER_BLK_DEF 1 #define DATA_AREA_PAGES_DEF (256 * 1024)
struct tcmu_nl_cmd { /* wake up thread waiting for reply */ struct completion complete; struct list_head nl_list; struct tcmu_dev *udev; int cmd; int status;
};
struct tcmu_mailbox *mb_addr; void *cmdr;
u32 cmdr_size;
u32 cmdr_last_cleaned; /* Offset of data area from start of mb */ /* Must add data_off and mb_addr to get the address */
size_t data_off; int data_area_mb;
uint32_t max_blocks;
size_t mmap_pages;
/* Can't use se_cmd when cleaning up expired cmds, because if
cmd has been completed then accessing se_cmd is off limits */
uint32_t dbi_cnt;
uint32_t dbi_bidi_cnt;
uint32_t dbi_cur;
uint32_t *dbi;
module_param_cb(global_max_data_area_mb, &tcmu_global_max_data_area_op, NULL,
S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(global_max_data_area_mb, "Max MBs allowed to be allocated to all the tcmu device's " "data areas.");
if (!udev) {
pr_err("tcmu nl cmd %u/%d completion could not find device with dev id %u.\n",
completed_cmd, rc, dev_id);
ret = -ENODEV; goto unlock;
}
list_del(&nl_cmd->nl_list);
if (nl_cmd->cmd != completed_cmd) {
pr_err("Mismatched commands on %s (Expecting reply for %d. Current %d).\n",
udev->name, completed_cmd, nl_cmd->cmd);
ret = -EINVAL; goto unlock;
}
for (i = 0; i < len; i++)
clear_bit(tcmu_cmd->dbi[i], udev->data_bitmap);
}
staticinlineint tcmu_get_empty_block(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, int prev_dbi, int length, int *iov_cnt)
{
XA_STATE(xas, &udev->data_pages, 0); struct page *page; int i, cnt, dbi, dpi; int page_cnt = DIV_ROUND_UP(length, PAGE_SIZE);
dbi = find_first_zero_bit(udev->data_bitmap, udev->dbi_thresh); if (dbi == udev->dbi_thresh) return -1;
dpi = dbi * udev->data_pages_per_blk; /* Count the number of already allocated pages */
xas_set(&xas, dpi);
rcu_read_lock(); for (cnt = 0; xas_next(&xas) && cnt < page_cnt;)
cnt++;
rcu_read_unlock();
for (i = cnt; i < page_cnt; i++) { /* try to get new zeroed page from the mm */
page = alloc_page(GFP_NOIO | __GFP_ZERO); if (!page) break;
if (xa_store(&udev->data_pages, dpi + i, page, GFP_NOIO)) {
__free_page(page); break;
}
} if (atomic_add_return(i - cnt, &global_page_count) >
tcmu_global_max_pages)
schedule_delayed_work(&tcmu_unmap_work, 0);
if (i && dbi > udev->dbi_max)
udev->dbi_max = dbi;
staticint tcmu_get_empty_blocks(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, int length)
{ /* start value of dbi + 1 must not be a valid dbi */ int dbi = -2; int blk_data_len, iov_cnt = 0;
uint32_t blk_size = udev->data_blk_size;
if (se_cmd->se_cmd_flags & SCF_BIDI) {
BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); for (i = 0, len = 0; i < se_cmd->t_bidi_data_nents; i++)
len += se_cmd->t_bidi_data_sg[i].length;
cmd->dbi_bidi_cnt = DIV_ROUND_UP(len, blk_size);
cmd->dbi_cnt += cmd->dbi_bidi_cnt;
cmd->data_len_bidi = len;
}
}
staticint new_block_to_iov(struct tcmu_dev *udev, struct tcmu_cmd *cmd, struct iovec **iov, int prev_dbi, int len)
{ /* Get the next dbi */ int dbi = tcmu_cmd_get_dbi(cmd);
/* Do not add more than udev->data_blk_size to iov */
len = min_t(int, len, udev->data_blk_size);
/* * The following code will gather and map the blocks to the same iovec * when the blocks are all next to each other.
*/ if (dbi != prev_dbi + 1) { /* dbi is not next to previous dbi, so start new iov */ if (prev_dbi >= 0)
(*iov)++; /* write offset relative to mb_addr */
(*iov)->iov_base = (void __user *)
(udev->data_off + dbi * udev->data_blk_size);
}
(*iov)->iov_len += len;
return dbi;
}
staticvoid tcmu_setup_iovs(struct tcmu_dev *udev, struct tcmu_cmd *cmd, struct iovec **iov, int data_length)
{ /* start value of dbi + 1 must not be a valid dbi */ int dbi = -2;
/* We prepare the IOVs for DMA_FROM_DEVICE transfer direction */ for (; data_length > 0; data_length -= udev->data_blk_size)
dbi = new_block_to_iov(udev, cmd, iov, dbi, data_length);
}
/* * Some ring helper functions. We don't assume size is a power of 2 so * we can't use circ_buf.h.
*/ staticinline size_t spc_used(size_t head, size_t tail, size_t size)
{ int diff = head - tail;
while (page_remaining && data_len) { if (!sg_miter_next(&sg_iter)) { /* set length to 0 to abort outer loop */
data_len = 0;
pr_debug("%s: aborting data copy due to exhausted sg_list\n",
__func__); break;
}
cp_len = min3(sg_iter.length, page_remaining,
data_len);
if (!bidi) {
data_sg = se_cmd->t_data_sg;
data_nents = se_cmd->t_data_nents;
} else { /* * For bidi case, the first count blocks are for Data-Out * buffer blocks, and before gathering the Data-In buffer * the Data-Out buffer blocks should be skipped.
*/
tcmu_cmd_set_dbi_cur(tcmu_cmd,
tcmu_cmd->dbi_cnt - tcmu_cmd->dbi_bidi_cnt);
/* * We can't queue a command until we have space available on the cmd ring. * * Called with ring lock held.
*/ staticbool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size)
{ struct tcmu_mailbox *mb = udev->mb_addr;
size_t space, cmd_needed;
u32 cmd_head;
/* * If cmd end-of-ring space is too small then we need space for a NOP plus * original cmd - cmds are internally contiguous.
*/ if (head_to_end(cmd_head, udev->cmdr_size) >= cmd_size)
cmd_needed = cmd_size; else
cmd_needed = cmd_size + head_to_end(cmd_head, udev->cmdr_size);
/* * We have to allocate data buffers before we can queue a command. * Returns -1 on error (not enough space) or number of needed iovs on success * * Called with ring lock held.
*/ staticint tcmu_alloc_data_space(struct tcmu_dev *udev, struct tcmu_cmd *cmd, int *iov_bidi_cnt)
{ int space, iov_cnt = 0, ret = 0;
if (!cmd->dbi_cnt) goto wr_iov_cnts;
/* try to check and get the data blocks as needed */
space = spc_bitmap_free(udev->data_bitmap, udev->dbi_thresh); if (space < cmd->dbi_cnt) { unsignedlong blocks_left =
(udev->max_blocks - udev->dbi_thresh) + space;
if (blocks_left < cmd->dbi_cnt) {
pr_debug("no data space: only %lu available, but ask for %u\n",
blocks_left * udev->data_blk_size,
cmd->dbi_cnt * udev->data_blk_size); return -1;
}
/* * For backwards compat if qfull_time_out is not set use * cmd_time_out and if that's not set use the default time out.
*/ if (!udev->qfull_time_out) return -ETIMEDOUT; elseif (udev->qfull_time_out > 0)
tmo = udev->qfull_time_out; elseif (udev->cmd_time_out)
tmo = udev->cmd_time_out; else
tmo = TCMU_TIME_OUT;
list_add_tail(&tcmu_cmd->queue_entry, &udev->qfull_queue);
pr_debug("adding cmd %p on dev %s to ring space wait queue\n",
tcmu_cmd, udev->name); return 0;
}
/* Insert a PAD if end-of-ring space is too small */ if (head_to_end(cmd_head, udev->cmdr_size) < cmd_size) {
size_t pad_size = head_to_end(cmd_head, udev->cmdr_size);
hdr = udev->cmdr + cmd_head;
tcmu_hdr_set_op(&hdr->len_op, TCMU_OP_PAD);
tcmu_hdr_set_len(&hdr->len_op, pad_size);
hdr->cmd_id = 0; /* not used for PAD */
hdr->kflags = 0;
hdr->uflags = 0;
tcmu_flush_dcache_range(hdr, sizeof(*hdr));
if (!test_and_set_bit(TCMU_DEV_BIT_PLUGGED, &udev->flags)) return &udev->se_plug;
return NULL;
}
/** * queue_cmd_ring - queue cmd to ring or internally * @tcmu_cmd: cmd to queue * @scsi_err: TCM error code if failure (-1) returned. * * Returns: * -1 we cannot queue internally or to the ring. * 0 success * 1 internally queued to wait for ring memory to free.
*/ staticint queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
{ struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
size_t base_command_size, command_size; struct tcmu_mailbox *mb = udev->mb_addr; struct tcmu_cmd_entry *entry; struct iovec *iov; int iov_cnt, iov_bidi_cnt;
uint32_t cmd_id, cmd_head;
uint64_t cdb_off;
uint32_t blk_size = udev->data_blk_size; /* size of data buffer needed */
size_t data_length = (size_t)tcmu_cmd->dbi_cnt * blk_size;
*scsi_err = TCM_NO_SENSE;
if (test_bit(TCMU_DEV_BIT_BLOCKED, &udev->flags)) {
*scsi_err = TCM_LUN_BUSY; return -1;
}
if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) {
*scsi_err = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -1;
}
if (!list_empty(&udev->qfull_queue)) goto queue;
if (data_length > (size_t)udev->max_blocks * blk_size) {
pr_warn("TCMU: Request of size %zu is too big for %zu data area\n",
data_length, (size_t)udev->max_blocks * blk_size);
*scsi_err = TCM_INVALID_CDB_FIELD; return -1;
}
/* * Must be a certain minimum size for response sense info, but * also may be larger if the iov array is large.
*/
base_command_size = tcmu_cmd_get_base_cmd_size(iov_cnt);
command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size);
if (command_size > (udev->cmdr_size / 2)) {
pr_warn("TCMU: Request of size %zu is too big for %u cmd ring\n",
command_size, udev->cmdr_size);
tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cur);
*scsi_err = TCM_INVALID_CDB_FIELD; return -1;
}
if (!is_ring_space_avail(udev, command_size)) /* * Don't leave commands partially setup because the unmap * thread might need the blocks to make forward progress.
*/ goto free_and_queue;
if (xa_alloc(&udev->commands, &cmd_id, tcmu_cmd, XA_LIMIT(1, 0xffff),
GFP_NOWAIT) < 0) {
pr_err("tcmu: Could not allocate cmd id.\n");
queue: if (add_to_qfull_queue(tcmu_cmd)) {
*scsi_err = TCM_OUT_OF_RESOURCES; return -1;
}
return 1;
}
/** * queue_tmr_ring - queue tmr info to ring or internally * @udev: related tcmu_dev * @tmr: tcmu_tmr containing tmr info to queue * * Returns: * 0 success * 1 internally queued to wait for ring memory to free.
*/ staticint
queue_tmr_ring(struct tcmu_dev *udev, struct tcmu_tmr *tmr)
{ struct tcmu_tmr_entry *entry; int cmd_size; int id_list_sz; struct tcmu_mailbox *mb = udev->mb_addr;
uint32_t cmd_head;
if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) goto out_free;
if (!list_empty(&udev->tmr_queue) ||
!is_ring_space_avail(udev, cmd_size)) {
list_add_tail(&tmr->queue_entry, &udev->tmr_queue);
pr_debug("adding tmr %p on dev %s to TMR ring space wait queue\n",
tmr, udev->name); return 1;
}
/* First we check for aborted commands in qfull_queue */
list_for_each_entry(se_cmd, cmd_list, state_list) {
i++; if (!se_cmd->priv) continue;
cmd = se_cmd->priv; /* Commands on qfull queue have no id yet */ if (cmd->cmd_id) {
cmd_cnt++; continue;
}
pr_debug("Removing aborted command %p from queue on dev %s.\n",
cmd, udev->name);
/* * cmd has been completed already from timeout, just reclaim * data area space and free cmd
*/ if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
WARN_ON_ONCE(se_cmd); goto out;
} if (test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
pr_err("cmd_id %u already completed with KEEP_BUF, ring is broken\n",
entry->hdr.cmd_id);
set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags);
ret = false; goto out;
}
list_del_init(&cmd->queue_entry);
tcmu_cmd_reset_dbi_cur(cmd);
if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
pr_warn("TCMU: Userspace set UNKNOWN_OP flag on se_cmd %p\n",
cmd->se_cmd);
entry->rsp.scsi_status = SAM_STAT_CHECK_CONDITION; goto done;
}
out: if (!keep_buf) {
tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
tcmu_free_cmd(cmd);
} else { /* * Keep this command after completion, since userspace still * needs the data buffer. Mark it with TCMU_CMD_BIT_KEEP_BUF * and reset potential TCMU_CMD_BIT_EXPIRED, so we don't accept * a second completion later. * Userspace can free the buffer later by writing the cmd_id * to new action attribute free_kept_buf.
*/
clear_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
set_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags);
} return ret;
}
pr_debug("removing tmr %p on dev %s from queue\n",
tmr, udev->name);
if (queue_tmr_ring(udev, tmr)) {
pr_debug("ran out of space during tmr queue run\n"); /* * tmr was requeued, so just put all tmrs back in * the queue
*/
list_splice_tail(&tmrs, &udev->tmr_queue); return 0;
}
}
/* * Flush max. up to end of cmd ring since current entry might * be a padding that is shorter than sizeof(*entry)
*/
size_t ring_left = head_to_end(udev->cmdr_last_cleaned,
udev->cmdr_size);
tcmu_flush_dcache_range(entry, ring_left < sizeof(*entry) ?
ring_left : sizeof(*entry));
keep_buf = !!(entry->hdr.uflags & TCMU_UFLAG_KEEP_BUF); if (keep_buf)
cmd = xa_load(&udev->commands, entry->hdr.cmd_id); else
cmd = xa_erase(&udev->commands, entry->hdr.cmd_id); if (!cmd) {
pr_err("cmd_id %u not found, ring is broken\n",
entry->hdr.cmd_id);
set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags); returnfalse;
}
if (!tcmu_handle_completion(cmd, entry, keep_buf)) break;
UPDATE_HEAD(udev->cmdr_last_cleaned,
tcmu_hdr_get_len(entry->hdr.len_op),
udev->cmdr_size);
} if (free_space)
free_space = tcmu_run_tmr_queue(udev);
if (atomic_read(&global_page_count) > tcmu_global_max_pages &&
xa_empty(&udev->commands) && list_empty(&udev->qfull_queue)) { /* * Allocated blocks exceeded global block limit, currently no * more pending or waiting commands so try to reclaim blocks.
*/
schedule_delayed_work(&tcmu_unmap_work, 0);
} if (udev->cmd_time_out)
tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
first = first * udev->data_pages_per_blk;
last = (last + 1) * udev->data_pages_per_blk - 1;
xa_for_each_range(&udev->data_pages, dpi, page, first, last) {
xa_erase(&udev->data_pages, dpi); /* * While reaching here there may be page faults occurring on * the to-be-released pages. A race condition may occur if * unmap_mapping_range() is called before page faults on these * pages have completed; a valid but stale map is created. * * If another command subsequently runs and needs to extend * dbi_thresh, it may reuse the slot corresponding to the * previous page in data_bitmap. Though we will allocate a new * page for the slot in data_area, no page fault will happen * because we have a valid map. Therefore the command's data * will be lost. * * We lock and unlock pages that are to be released to ensure * all page faults have completed. This way * unmap_mapping_range() can ensure stale maps are cleanly * removed.
*/
lock_page(page);
unlock_page(page);
__free_page(page);
pages_freed++;
}
spin_lock_bh(&timed_out_udevs_lock); if (!list_empty(&udev->timedout_entry))
list_del(&udev->timedout_entry);
spin_unlock_bh(&timed_out_udevs_lock);
/* Upper layer should drain all requests before calling this */
mutex_lock(&udev->cmdr_lock);
xa_for_each(&udev->commands, i, cmd) { if (tcmu_check_and_free_pending_cmd(cmd) != 0)
all_expired = false;
} /* There can be left over TMR cmds. Remove them. */
tcmu_remove_all_queued_tmr(udev); if (!list_empty(&udev->qfull_queue))
all_expired = false;
xa_destroy(&udev->commands);
WARN_ON(!all_expired);
pr_debug("removing cmd %p on dev %s from queue\n",
tcmu_cmd, udev->name);
if (fail) { /* * We were not able to even start the command, so * fail with busy to allow a retry in case runner * was only temporarily down. If the device is being * removed then LIO core will do the right thing and * fail the retry.
*/
tcmu_cmd->se_cmd->priv = NULL;
target_complete_cmd(tcmu_cmd->se_cmd, SAM_STAT_BUSY);
tcmu_free_cmd(tcmu_cmd); continue;
}
ret = queue_cmd_ring(tcmu_cmd, &scsi_ret); if (ret < 0) {
pr_debug("cmd %p on dev %s failed with %u\n",
tcmu_cmd, udev->name, scsi_ret); /* * Ignore scsi_ret for now. target_complete_cmd * drops it.
*/
tcmu_cmd->se_cmd->priv = NULL;
target_complete_cmd(tcmu_cmd->se_cmd,
SAM_STAT_CHECK_CONDITION);
tcmu_free_cmd(tcmu_cmd);
} elseif (ret > 0) {
pr_debug("ran out of space during cmdr queue run\n"); /* * cmd was requeued, so just put all cmds back in * the queue
*/
list_splice_tail(&cmds, &udev->qfull_queue); break;
}
}
mutex_lock(&udev->cmdr_lock); if (tcmu_handle_completions(udev))
run_qfull_queue(udev, false);
mutex_unlock(&udev->cmdr_lock);
return 0;
}
/* * mmap code from uio.c. Copied here because we want to hook mmap() * and this stuff must come along.
*/ staticint tcmu_find_mem_index(struct vm_area_struct *vma)
{ struct tcmu_dev *udev = vma->vm_private_data; struct uio_info *info = &udev->uio_info;
if (vma->vm_pgoff < MAX_UIO_MAPS) { if (info->mem[vma->vm_pgoff].size == 0) return -1; return (int)vma->vm_pgoff;
} return -1;
}
/* * Userspace messed up and passed in a address not in the * data iov passed to it.
*/
pr_err("Invalid addr to data page mapping (dpi %u) on device %s\n",
dpi, udev->name);
mutex_unlock(&udev->cmdr_lock);
int mi = tcmu_find_mem_index(vmf->vma); if (mi < 0) return VM_FAULT_SIGBUS;
/* * We need to subtract mi because userspace uses offset = N*PAGE_SIZE * to use mem[N].
*/
offset = (vmf->pgoff - mi) << PAGE_SHIFT;
if (offset < udev->data_off) { /* For the vmalloc()ed cmd area pages */
addr = (void *)(unsignedlong)info->mem[mi].addr + offset;
page = vmalloc_to_page(addr);
get_page(page);
} else {
uint32_t dpi;
/* For the dynamically growing data area pages */
dpi = (offset - udev->data_off) / PAGE_SIZE;
page = tcmu_try_get_data_page(udev, dpi); if (!page) return VM_FAULT_SIGBUS;
ret = VM_FAULT_LOCKED;
}
xa_for_each(&udev->commands, i, cmd) { /* Cmds with KEEP_BUF set are no longer on the ring, but * userspace still holds the data buffer. If userspace closes * we implicitly free these cmds and buffers, since after new * open the (new ?) userspace cannot find the cmd in the ring * and thus never will release the buffer by writing cmd_id to * free_kept_buf action attribute.
*/ if (!test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) continue;
pr_debug("removing KEEP_BUF cmd %u on dev %s from ring\n",
cmd->cmd_id, udev->name);
freed = true;
xa_erase(&udev->commands, i);
tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
tcmu_free_cmd(cmd);
} /* * We only freed data space, not ring space. Therefore we dont call * run_tmr_queue, but call run_qfull_queue if tmr_list is empty.
*/ if (freed && list_empty(&udev->tmr_queue))
run_qfull_queue(udev, false);
ret = tcmu_init_genl_cmd_reply(udev, cmd); if (ret) {
nlmsg_free(skb); return ret;
}
ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0,
TCMU_MCGRP_CONFIG);
/* Wait during an add as the listener may not be up yet */ if (ret == 0 ||
(ret == -ESRCH && cmd == TCMU_CMD_ADDED_DEVICE)) return tcmu_wait_genl_cmd_reply(udev); else
tcmu_destroy_genl_cmd_reply(udev);
return ret;
}
staticint tcmu_send_dev_add_event(struct tcmu_dev *udev)
{ struct sk_buff *skb = NULL; void *msg_header = NULL; int ret = 0;
ret = tcmu_netlink_event_init(udev, TCMU_CMD_ADDED_DEVICE, &skb,
&msg_header); if (ret < 0) return ret; return tcmu_netlink_event_send(udev, TCMU_CMD_ADDED_DEVICE, skb,
msg_header);
}
staticint tcmu_send_dev_remove_event(struct tcmu_dev *udev)
{ struct sk_buff *skb = NULL; void *msg_header = NULL; int ret = 0;
ret = tcmu_netlink_event_init(udev, TCMU_CMD_REMOVED_DEVICE,
&skb, &msg_header); if (ret < 0) return ret; return tcmu_netlink_event_send(udev, TCMU_CMD_REMOVED_DEVICE,
skb, msg_header);
}
ret = uio_register_device(tcmu_root_device, info); if (ret) goto err_register;
/* User can set hw_block_size before enable the device */ if (dev->dev_attrib.hw_block_size == 0)
dev->dev_attrib.hw_block_size = 512; /* Other attributes can be configured in userspace */ if (!dev->dev_attrib.hw_max_sectors)
dev->dev_attrib.hw_max_sectors = 128; if (!dev->dev_attrib.emulate_write_cache)
dev->dev_attrib.emulate_write_cache = 0;
dev->dev_attrib.hw_queue_depth = 128;
/* If user didn't explicitly disable netlink reply support, use * module scope setting.
*/ if (udev->nl_reply_supported >= 0)
udev->nl_reply_supported = tcmu_kern_cmd_reply_supported;
/* * Get a ref incase userspace does a close on the uio device before * LIO has initiated tcmu_free_device.
*/
kref_get(&udev->kref);
ret = tcmu_send_dev_add_event(udev); if (ret) goto err_netlink;
xa_for_each(&udev->commands, i, cmd) {
pr_debug("removing cmd %u on dev %s from ring %s\n",
cmd->cmd_id, udev->name,
test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) ? "(is expired)" :
(test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags) ? "(is keep buffer)" : ""));
xa_erase(&udev->commands, i); if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) &&
!test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
WARN_ON(!cmd->se_cmd);
list_del_init(&cmd->queue_entry);
cmd->se_cmd->priv = NULL; if (err_level == 1) { /* * Userspace was not able to start the * command or it is retryable.
*/
target_complete_cmd(cmd->se_cmd, SAM_STAT_BUSY);
} else { /* hard failure */
target_complete_cmd(cmd->se_cmd,
SAM_STAT_CHECK_CONDITION);
}
}
tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
tcmu_free_cmd(cmd);
}
mb = udev->mb_addr;
tcmu_flush_dcache_range(mb, sizeof(*mb));
pr_debug("mb last %u head %u tail %u\n", udev->cmdr_last_cleaned,
mb->cmd_tail, mb->cmd_head);
/* * ring is empty and qfull queue never contains aborted commands. * So TMRs in tmr queue do not contain relevant cmd_ids. * After a ring reset userspace should do a fresh start, so * even LUN RESET message is no longer relevant. * Therefore remove all TMRs from qfull queue
*/
tcmu_remove_all_queued_tmr(udev);
ret = match_int(arg, &val); if (ret < 0) {
pr_err("match_int() failed for max_data_area_mb=. Error %d.\n",
ret); return ret;
} if (val <= 0) {
pr_err("Invalid max_data_area %d.\n", val); return -EINVAL;
} if (val > TCMU_PAGES_TO_MBS(tcmu_global_max_pages)) {
pr_err("%d is too large. Adjusting max_data_area_mb to global limit of %u\n",
val, TCMU_PAGES_TO_MBS(tcmu_global_max_pages));
val = TCMU_PAGES_TO_MBS(tcmu_global_max_pages);
} if (TCMU_MBS_TO_PAGES(val) < pages_per_blk) {
pr_err("Invalid max_data_area %d (%zu pages): smaller than data_pages_per_blk (%u pages).\n",
val, TCMU_MBS_TO_PAGES(val), pages_per_blk); return -EINVAL;
}
mutex_lock(&udev->cmdr_lock); if (udev->data_bitmap) {
pr_err("Cannot set max_data_area_mb after it has been enabled.\n");
ret = -EINVAL; goto unlock;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.