diff options
49 files changed, 2845 insertions, 3989 deletions
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index cf23c46185b2..c09d41b1a2ff 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c | |||
| @@ -1269,7 +1269,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) | |||
| 1269 | return ioctx; | 1269 | return ioctx; |
| 1270 | 1270 | ||
| 1271 | BUG_ON(ioctx->ch != ch); | 1271 | BUG_ON(ioctx->ch != ch); |
| 1272 | kref_init(&ioctx->kref); | ||
| 1273 | spin_lock_init(&ioctx->spinlock); | 1272 | spin_lock_init(&ioctx->spinlock); |
| 1274 | ioctx->state = SRPT_STATE_NEW; | 1273 | ioctx->state = SRPT_STATE_NEW; |
| 1275 | ioctx->n_rbuf = 0; | 1274 | ioctx->n_rbuf = 0; |
| @@ -1291,39 +1290,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) | |||
| 1291 | } | 1290 | } |
| 1292 | 1291 | ||
| 1293 | /** | 1292 | /** |
| 1294 | * srpt_put_send_ioctx() - Free up resources. | ||
| 1295 | */ | ||
| 1296 | static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx) | ||
| 1297 | { | ||
| 1298 | struct srpt_rdma_ch *ch; | ||
| 1299 | unsigned long flags; | ||
| 1300 | |||
| 1301 | BUG_ON(!ioctx); | ||
| 1302 | ch = ioctx->ch; | ||
| 1303 | BUG_ON(!ch); | ||
| 1304 | |||
| 1305 | WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE); | ||
| 1306 | |||
| 1307 | srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx); | ||
| 1308 | transport_generic_free_cmd(&ioctx->cmd, 0); | ||
| 1309 | |||
| 1310 | if (ioctx->n_rbuf > 1) { | ||
| 1311 | kfree(ioctx->rbufs); | ||
| 1312 | ioctx->rbufs = NULL; | ||
| 1313 | ioctx->n_rbuf = 0; | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | spin_lock_irqsave(&ch->spinlock, flags); | ||
| 1317 | list_add(&ioctx->free_list, &ch->free_list); | ||
| 1318 | spin_unlock_irqrestore(&ch->spinlock, flags); | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | static void srpt_put_send_ioctx_kref(struct kref *kref) | ||
| 1322 | { | ||
| 1323 | srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref)); | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | /** | ||
| 1327 | * srpt_abort_cmd() - Abort a SCSI command. | 1293 | * srpt_abort_cmd() - Abort a SCSI command. |
| 1328 | * @ioctx: I/O context associated with the SCSI command. | 1294 | * @ioctx: I/O context associated with the SCSI command. |
| 1329 | * @context: Preferred execution context. | 1295 | * @context: Preferred execution context. |
| @@ -1359,8 +1325,14 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) | |||
| 1359 | } | 1325 | } |
| 1360 | spin_unlock_irqrestore(&ioctx->spinlock, flags); | 1326 | spin_unlock_irqrestore(&ioctx->spinlock, flags); |
| 1361 | 1327 | ||
| 1362 | if (state == SRPT_STATE_DONE) | 1328 | if (state == SRPT_STATE_DONE) { |
| 1329 | struct srpt_rdma_ch *ch = ioctx->ch; | ||
| 1330 | |||
| 1331 | BUG_ON(ch->sess == NULL); | ||
| 1332 | |||
| 1333 | target_put_sess_cmd(ch->sess, &ioctx->cmd); | ||
| 1363 | goto out; | 1334 | goto out; |
| 1335 | } | ||
| 1364 | 1336 | ||
| 1365 | pr_debug("Aborting cmd with state %d and tag %lld\n", state, | 1337 | pr_debug("Aborting cmd with state %d and tag %lld\n", state, |
| 1366 | ioctx->tag); | 1338 | ioctx->tag); |
| @@ -1395,11 +1367,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) | |||
| 1395 | spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags); | 1367 | spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags); |
| 1396 | ioctx->cmd.transport_state |= CMD_T_LUN_STOP; | 1368 | ioctx->cmd.transport_state |= CMD_T_LUN_STOP; |
| 1397 | spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags); | 1369 | spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags); |
| 1398 | kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); | 1370 | target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); |
| 1399 | break; | 1371 | break; |
| 1400 | case SRPT_STATE_MGMT_RSP_SENT: | 1372 | case SRPT_STATE_MGMT_RSP_SENT: |
| 1401 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); | 1373 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); |
| 1402 | kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); | 1374 | target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); |
| 1403 | break; | 1375 | break; |
| 1404 | default: | 1376 | default: |
| 1405 | WARN_ON("ERROR: unexpected command state"); | 1377 | WARN_ON("ERROR: unexpected command state"); |
| @@ -1457,11 +1429,13 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, | |||
| 1457 | && state != SRPT_STATE_DONE)) | 1429 | && state != SRPT_STATE_DONE)) |
| 1458 | pr_debug("state = %d\n", state); | 1430 | pr_debug("state = %d\n", state); |
| 1459 | 1431 | ||
| 1460 | if (state != SRPT_STATE_DONE) | 1432 | if (state != SRPT_STATE_DONE) { |
| 1461 | kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); | 1433 | srpt_unmap_sg_to_ib_sge(ch, ioctx); |
| 1462 | else | 1434 | transport_generic_free_cmd(&ioctx->cmd, 0); |
| 1435 | } else { | ||
| 1463 | printk(KERN_ERR "IB completion has been received too late for" | 1436 | printk(KERN_ERR "IB completion has been received too late for" |
| 1464 | " wr_id = %u.\n", ioctx->ioctx.index); | 1437 | " wr_id = %u.\n", ioctx->ioctx.index); |
| 1438 | } | ||
| 1465 | } | 1439 | } |
| 1466 | 1440 | ||
| 1467 | /** | 1441 | /** |
| @@ -1712,10 +1686,10 @@ out_err: | |||
| 1712 | 1686 | ||
| 1713 | static int srpt_check_stop_free(struct se_cmd *cmd) | 1687 | static int srpt_check_stop_free(struct se_cmd *cmd) |
| 1714 | { | 1688 | { |
| 1715 | struct srpt_send_ioctx *ioctx; | 1689 | struct srpt_send_ioctx *ioctx = container_of(cmd, |
| 1690 | struct srpt_send_ioctx, cmd); | ||
| 1716 | 1691 | ||
| 1717 | ioctx = container_of(cmd, struct srpt_send_ioctx, cmd); | 1692 | return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); |
| 1718 | return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); | ||
| 1719 | } | 1693 | } |
| 1720 | 1694 | ||
| 1721 | /** | 1695 | /** |
| @@ -1730,12 +1704,12 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, | |||
| 1730 | uint64_t unpacked_lun; | 1704 | uint64_t unpacked_lun; |
| 1731 | u64 data_len; | 1705 | u64 data_len; |
| 1732 | enum dma_data_direction dir; | 1706 | enum dma_data_direction dir; |
| 1733 | int ret; | 1707 | sense_reason_t ret; |
| 1708 | int rc; | ||
| 1734 | 1709 | ||
| 1735 | BUG_ON(!send_ioctx); | 1710 | BUG_ON(!send_ioctx); |
| 1736 | 1711 | ||
| 1737 | srp_cmd = recv_ioctx->ioctx.buf; | 1712 | srp_cmd = recv_ioctx->ioctx.buf; |
| 1738 | kref_get(&send_ioctx->kref); | ||
| 1739 | cmd = &send_ioctx->cmd; | 1713 | cmd = &send_ioctx->cmd; |
| 1740 | send_ioctx->tag = srp_cmd->tag; | 1714 | send_ioctx->tag = srp_cmd->tag; |
| 1741 | 1715 | ||
| @@ -1755,40 +1729,26 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, | |||
| 1755 | break; | 1729 | break; |
| 1756 | } | 1730 | } |
| 1757 | 1731 | ||
| 1758 | ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len); | 1732 | if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) { |
| 1759 | if (ret) { | ||
| 1760 | printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", | 1733 | printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", |
| 1761 | srp_cmd->tag); | 1734 | srp_cmd->tag); |
| 1762 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 1735 | ret = TCM_INVALID_CDB_FIELD; |
| 1763 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 1764 | kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); | ||
| 1765 | goto send_sense; | 1736 | goto send_sense; |
| 1766 | } | 1737 | } |
| 1767 | 1738 | ||
| 1768 | cmd->data_length = data_len; | ||
| 1769 | cmd->data_direction = dir; | ||
| 1770 | unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, | 1739 | unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, |
| 1771 | sizeof(srp_cmd->lun)); | 1740 | sizeof(srp_cmd->lun)); |
| 1772 | if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) { | 1741 | rc = target_submit_cmd(cmd, ch->sess, srp_cmd->cdb, |
| 1773 | kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); | 1742 | &send_ioctx->sense_data[0], unpacked_lun, data_len, |
| 1743 | MSG_SIMPLE_TAG, dir, TARGET_SCF_ACK_KREF); | ||
| 1744 | if (rc != 0) { | ||
| 1745 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1774 | goto send_sense; | 1746 | goto send_sense; |
| 1775 | } | 1747 | } |
| 1776 | ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb); | ||
| 1777 | if (ret < 0) { | ||
| 1778 | kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); | ||
| 1779 | if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) { | ||
| 1780 | srpt_queue_status(cmd); | ||
| 1781 | return 0; | ||
| 1782 | } else | ||
| 1783 | goto send_sense; | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | transport_handle_cdb_direct(cmd); | ||
| 1787 | return 0; | 1748 | return 0; |
| 1788 | 1749 | ||
| 1789 | send_sense: | 1750 | send_sense: |
| 1790 | transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason, | 1751 | transport_send_check_condition_and_sense(cmd, ret, 0); |
| 1791 | 0); | ||
| 1792 | return -1; | 1752 | return -1; |
| 1793 | } | 1753 | } |
| 1794 | 1754 | ||
| @@ -1865,9 +1825,11 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, | |||
| 1865 | { | 1825 | { |
| 1866 | struct srp_tsk_mgmt *srp_tsk; | 1826 | struct srp_tsk_mgmt *srp_tsk; |
| 1867 | struct se_cmd *cmd; | 1827 | struct se_cmd *cmd; |
| 1828 | struct se_session *sess = ch->sess; | ||
| 1868 | uint64_t unpacked_lun; | 1829 | uint64_t unpacked_lun; |
| 1830 | uint32_t tag = 0; | ||
| 1869 | int tcm_tmr; | 1831 | int tcm_tmr; |
| 1870 | int res; | 1832 | int rc; |
| 1871 | 1833 | ||
| 1872 | BUG_ON(!send_ioctx); | 1834 | BUG_ON(!send_ioctx); |
| 1873 | 1835 | ||
| @@ -1882,39 +1844,32 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, | |||
| 1882 | send_ioctx->tag = srp_tsk->tag; | 1844 | send_ioctx->tag = srp_tsk->tag; |
| 1883 | tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); | 1845 | tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); |
| 1884 | if (tcm_tmr < 0) { | 1846 | if (tcm_tmr < 0) { |
| 1885 | send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1886 | send_ioctx->cmd.se_tmr_req->response = | 1847 | send_ioctx->cmd.se_tmr_req->response = |
| 1887 | TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; | 1848 | TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; |
| 1888 | goto process_tmr; | 1849 | goto fail; |
| 1889 | } | ||
| 1890 | res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL); | ||
| 1891 | if (res < 0) { | ||
| 1892 | send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1893 | send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; | ||
| 1894 | goto process_tmr; | ||
| 1895 | } | 1850 | } |
| 1896 | |||
| 1897 | unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, | 1851 | unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, |
| 1898 | sizeof(srp_tsk->lun)); | 1852 | sizeof(srp_tsk->lun)); |
| 1899 | res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun); | ||
| 1900 | if (res) { | ||
| 1901 | pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun); | ||
| 1902 | send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1903 | send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; | ||
| 1904 | goto process_tmr; | ||
| 1905 | } | ||
| 1906 | |||
| 1907 | if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) | ||
| 1908 | srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); | ||
| 1909 | |||
| 1910 | process_tmr: | ||
| 1911 | kref_get(&send_ioctx->kref); | ||
| 1912 | if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) | ||
| 1913 | transport_generic_handle_tmr(&send_ioctx->cmd); | ||
| 1914 | else | ||
| 1915 | transport_send_check_condition_and_sense(cmd, | ||
| 1916 | cmd->scsi_sense_reason, 0); | ||
| 1917 | 1853 | ||
| 1854 | if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) { | ||
| 1855 | rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); | ||
| 1856 | if (rc < 0) { | ||
| 1857 | send_ioctx->cmd.se_tmr_req->response = | ||
| 1858 | TMR_TASK_DOES_NOT_EXIST; | ||
| 1859 | goto fail; | ||
| 1860 | } | ||
| 1861 | tag = srp_tsk->task_tag; | ||
| 1862 | } | ||
| 1863 | rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun, | ||
| 1864 | srp_tsk, tcm_tmr, GFP_KERNEL, tag, | ||
| 1865 | TARGET_SCF_ACK_KREF); | ||
| 1866 | if (rc != 0) { | ||
| 1867 | send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; | ||
| 1868 | goto fail; | ||
| 1869 | } | ||
| 1870 | return; | ||
| 1871 | fail: | ||
| 1872 | transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: | ||
| 1918 | } | 1873 | } |
| 1919 | 1874 | ||
| 1920 | /** | 1875 | /** |
| @@ -1956,10 +1911,6 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch, | |||
| 1956 | } | 1911 | } |
| 1957 | } | 1912 | } |
| 1958 | 1913 | ||
| 1959 | transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess, | ||
| 1960 | 0, DMA_NONE, MSG_SIMPLE_TAG, | ||
| 1961 | send_ioctx->sense_data); | ||
| 1962 | |||
| 1963 | switch (srp_cmd->opcode) { | 1914 | switch (srp_cmd->opcode) { |
| 1964 | case SRP_CMD: | 1915 | case SRP_CMD: |
| 1965 | srpt_handle_cmd(ch, recv_ioctx, send_ioctx); | 1916 | srpt_handle_cmd(ch, recv_ioctx, send_ioctx); |
| @@ -2365,6 +2316,7 @@ static void srpt_release_channel_work(struct work_struct *w) | |||
| 2365 | { | 2316 | { |
| 2366 | struct srpt_rdma_ch *ch; | 2317 | struct srpt_rdma_ch *ch; |
| 2367 | struct srpt_device *sdev; | 2318 | struct srpt_device *sdev; |
| 2319 | struct se_session *se_sess; | ||
| 2368 | 2320 | ||
| 2369 | ch = container_of(w, struct srpt_rdma_ch, release_work); | 2321 | ch = container_of(w, struct srpt_rdma_ch, release_work); |
| 2370 | pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess, | 2322 | pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess, |
| @@ -2373,8 +2325,13 @@ static void srpt_release_channel_work(struct work_struct *w) | |||
| 2373 | sdev = ch->sport->sdev; | 2325 | sdev = ch->sport->sdev; |
| 2374 | BUG_ON(!sdev); | 2326 | BUG_ON(!sdev); |
| 2375 | 2327 | ||
| 2376 | transport_deregister_session_configfs(ch->sess); | 2328 | se_sess = ch->sess; |
| 2377 | transport_deregister_session(ch->sess); | 2329 | BUG_ON(!se_sess); |
| 2330 | |||
| 2331 | target_wait_for_sess_cmds(se_sess, 0); | ||
| 2332 | |||
| 2333 | transport_deregister_session_configfs(se_sess); | ||
| 2334 | transport_deregister_session(se_sess); | ||
| 2378 | ch->sess = NULL; | 2335 | ch->sess = NULL; |
| 2379 | 2336 | ||
| 2380 | srpt_destroy_ch_ib(ch); | 2337 | srpt_destroy_ch_ib(ch); |
| @@ -3099,7 +3056,7 @@ static int srpt_queue_response(struct se_cmd *cmd) | |||
| 3099 | ioctx->tag); | 3056 | ioctx->tag); |
| 3100 | srpt_unmap_sg_to_ib_sge(ch, ioctx); | 3057 | srpt_unmap_sg_to_ib_sge(ch, ioctx); |
| 3101 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); | 3058 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); |
| 3102 | kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); | 3059 | target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); |
| 3103 | } | 3060 | } |
| 3104 | 3061 | ||
| 3105 | out: | 3062 | out: |
| @@ -3490,6 +3447,23 @@ static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg) | |||
| 3490 | 3447 | ||
| 3491 | static void srpt_release_cmd(struct se_cmd *se_cmd) | 3448 | static void srpt_release_cmd(struct se_cmd *se_cmd) |
| 3492 | { | 3449 | { |
| 3450 | struct srpt_send_ioctx *ioctx = container_of(se_cmd, | ||
| 3451 | struct srpt_send_ioctx, cmd); | ||
| 3452 | struct srpt_rdma_ch *ch = ioctx->ch; | ||
| 3453 | unsigned long flags; | ||
| 3454 | |||
| 3455 | WARN_ON(ioctx->state != SRPT_STATE_DONE); | ||
| 3456 | WARN_ON(ioctx->mapped_sg_count != 0); | ||
| 3457 | |||
| 3458 | if (ioctx->n_rbuf > 1) { | ||
| 3459 | kfree(ioctx->rbufs); | ||
| 3460 | ioctx->rbufs = NULL; | ||
| 3461 | ioctx->n_rbuf = 0; | ||
| 3462 | } | ||
| 3463 | |||
| 3464 | spin_lock_irqsave(&ch->spinlock, flags); | ||
| 3465 | list_add(&ioctx->free_list, &ch->free_list); | ||
| 3466 | spin_unlock_irqrestore(&ch->spinlock, flags); | ||
| 3493 | } | 3467 | } |
| 3494 | 3468 | ||
| 3495 | /** | 3469 | /** |
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index 61e52b830816..4caf55cda7b1 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h | |||
| @@ -228,7 +228,6 @@ struct srpt_recv_ioctx { | |||
| 228 | struct srpt_send_ioctx { | 228 | struct srpt_send_ioctx { |
| 229 | struct srpt_ioctx ioctx; | 229 | struct srpt_ioctx ioctx; |
| 230 | struct srpt_rdma_ch *ch; | 230 | struct srpt_rdma_ch *ch; |
| 231 | struct kref kref; | ||
| 232 | struct rdma_iu *rdma_ius; | 231 | struct rdma_iu *rdma_ius; |
| 233 | struct srp_direct_buf *rbufs; | 232 | struct srp_direct_buf *rbufs; |
| 234 | struct srp_direct_buf single_rbuf; | 233 | struct srp_direct_buf single_rbuf; |
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index ad1dc14bacce..80f4b849e2b0 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
| @@ -1264,8 +1264,27 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, | |||
| 1264 | struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) | 1264 | struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) |
| 1265 | { | 1265 | { |
| 1266 | struct qla_hw_data *ha = vha->hw; | 1266 | struct qla_hw_data *ha = vha->hw; |
| 1267 | struct se_session *se_sess = sess->se_sess; | ||
| 1267 | struct qla_tgt_mgmt_cmd *mcmd; | 1268 | struct qla_tgt_mgmt_cmd *mcmd; |
| 1269 | struct se_cmd *se_cmd; | ||
| 1270 | u32 lun = 0; | ||
| 1268 | int rc; | 1271 | int rc; |
| 1272 | bool found_lun = false; | ||
| 1273 | |||
| 1274 | spin_lock(&se_sess->sess_cmd_lock); | ||
| 1275 | list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { | ||
| 1276 | struct qla_tgt_cmd *cmd = | ||
| 1277 | container_of(se_cmd, struct qla_tgt_cmd, se_cmd); | ||
| 1278 | if (cmd->tag == abts->exchange_addr_to_abort) { | ||
| 1279 | lun = cmd->unpacked_lun; | ||
| 1280 | found_lun = true; | ||
| 1281 | break; | ||
| 1282 | } | ||
| 1283 | } | ||
| 1284 | spin_unlock(&se_sess->sess_cmd_lock); | ||
| 1285 | |||
| 1286 | if (!found_lun) | ||
| 1287 | return -ENOENT; | ||
| 1269 | 1288 | ||
| 1270 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, | 1289 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, |
| 1271 | "qla_target(%d): task abort (tag=%d)\n", | 1290 | "qla_target(%d): task abort (tag=%d)\n", |
| @@ -1283,7 +1302,7 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, | |||
| 1283 | mcmd->sess = sess; | 1302 | mcmd->sess = sess; |
| 1284 | memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); | 1303 | memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); |
| 1285 | 1304 | ||
| 1286 | rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK, | 1305 | rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, TMR_ABORT_TASK, |
| 1287 | abts->exchange_addr_to_abort); | 1306 | abts->exchange_addr_to_abort); |
| 1288 | if (rc != 0) { | 1307 | if (rc != 0) { |
| 1289 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, | 1308 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 4372e32bc95f..d182c96e17ea 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
| @@ -620,8 +620,8 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work) | |||
| 620 | return; | 620 | return; |
| 621 | } | 621 | } |
| 622 | 622 | ||
| 623 | cmd->se_cmd.scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD; | 623 | transport_generic_request_failure(&cmd->se_cmd, |
| 624 | transport_generic_request_failure(&cmd->se_cmd); | 624 | TCM_CHECK_CONDITION_ABORT_CMD); |
| 625 | return; | 625 | return; |
| 626 | } | 626 | } |
| 627 | 627 | ||
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 035c2c762537..339f97f7085b 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
| @@ -735,7 +735,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn) | |||
| 735 | list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { | 735 | list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { |
| 736 | spin_lock(&cmd->istate_lock); | 736 | spin_lock(&cmd->istate_lock); |
| 737 | if ((cmd->i_state == ISTATE_SENT_STATUS) && | 737 | if ((cmd->i_state == ISTATE_SENT_STATUS) && |
| 738 | (cmd->stat_sn < exp_statsn)) { | 738 | iscsi_sna_lt(cmd->stat_sn, exp_statsn)) { |
| 739 | cmd->i_state = ISTATE_REMOVE; | 739 | cmd->i_state = ISTATE_REMOVE; |
| 740 | spin_unlock(&cmd->istate_lock); | 740 | spin_unlock(&cmd->istate_lock); |
| 741 | iscsit_add_cmd_to_immediate_queue(cmd, conn, | 741 | iscsit_add_cmd_to_immediate_queue(cmd, conn, |
| @@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd( | |||
| 767 | struct iscsi_conn *conn, | 767 | struct iscsi_conn *conn, |
| 768 | unsigned char *buf) | 768 | unsigned char *buf) |
| 769 | { | 769 | { |
| 770 | int data_direction, cmdsn_ret = 0, immed_ret, ret, transport_ret; | 770 | int data_direction, payload_length, cmdsn_ret = 0, immed_ret; |
| 771 | int dump_immediate_data = 0, send_check_condition = 0, payload_length; | 771 | struct iscsi_cmd *cmd = NULL; |
| 772 | struct iscsi_cmd *cmd = NULL; | ||
| 773 | struct iscsi_scsi_req *hdr; | 772 | struct iscsi_scsi_req *hdr; |
| 774 | int iscsi_task_attr; | 773 | int iscsi_task_attr; |
| 775 | int sam_task_attr; | 774 | int sam_task_attr; |
| @@ -956,38 +955,26 @@ done: | |||
| 956 | " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, | 955 | " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, |
| 957 | hdr->cmdsn, hdr->data_length, payload_length, conn->cid); | 956 | hdr->cmdsn, hdr->data_length, payload_length, conn->cid); |
| 958 | 957 | ||
| 959 | /* | 958 | cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, |
| 960 | * The CDB is going to an se_device_t. | 959 | scsilun_to_int(&hdr->lun)); |
| 961 | */ | 960 | if (cmd->sense_reason) |
| 962 | ret = transport_lookup_cmd_lun(&cmd->se_cmd, | 961 | goto attach_cmd; |
| 963 | scsilun_to_int(&hdr->lun)); | 962 | |
| 964 | if (ret < 0) { | 963 | cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); |
| 965 | if (cmd->se_cmd.scsi_sense_reason == TCM_NON_EXISTENT_LUN) { | 964 | if (cmd->sense_reason) { |
| 966 | pr_debug("Responding to non-acl'ed," | 965 | if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { |
| 967 | " non-existent or non-exported iSCSI LUN:" | 966 | return iscsit_add_reject_from_cmd( |
| 968 | " 0x%016Lx\n", get_unaligned_le64(&hdr->lun)); | 967 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, |
| 968 | 1, 1, buf, cmd); | ||
| 969 | } | 969 | } |
| 970 | send_check_condition = 1; | 970 | |
| 971 | goto attach_cmd; | 971 | goto attach_cmd; |
| 972 | } | 972 | } |
| 973 | 973 | ||
| 974 | transport_ret = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); | 974 | if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { |
| 975 | if (transport_ret == -ENOMEM) { | ||
| 976 | return iscsit_add_reject_from_cmd( | 975 | return iscsit_add_reject_from_cmd( |
| 977 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 976 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, |
| 978 | 1, 1, buf, cmd); | 977 | 1, 1, buf, cmd); |
| 979 | } else if (transport_ret < 0) { | ||
| 980 | /* | ||
| 981 | * Unsupported SAM Opcode. CHECK_CONDITION will be sent | ||
| 982 | * in iscsit_execute_cmd() during the CmdSN OOO Execution | ||
| 983 | * Mechinism. | ||
| 984 | */ | ||
| 985 | send_check_condition = 1; | ||
| 986 | } else { | ||
| 987 | if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) | ||
| 988 | return iscsit_add_reject_from_cmd( | ||
| 989 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | ||
| 990 | 1, 1, buf, cmd); | ||
| 991 | } | 978 | } |
| 992 | 979 | ||
| 993 | attach_cmd: | 980 | attach_cmd: |
| @@ -1000,11 +987,12 @@ attach_cmd: | |||
| 1000 | */ | 987 | */ |
| 1001 | core_alua_check_nonop_delay(&cmd->se_cmd); | 988 | core_alua_check_nonop_delay(&cmd->se_cmd); |
| 1002 | 989 | ||
| 1003 | ret = iscsit_allocate_iovecs(cmd); | 990 | if (iscsit_allocate_iovecs(cmd) < 0) { |
| 1004 | if (ret < 0) | ||
| 1005 | return iscsit_add_reject_from_cmd( | 991 | return iscsit_add_reject_from_cmd( |
| 1006 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 992 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, |
| 1007 | 1, 0, buf, cmd); | 993 | 1, 0, buf, cmd); |
| 994 | } | ||
| 995 | |||
| 1008 | /* | 996 | /* |
| 1009 | * Check the CmdSN against ExpCmdSN/MaxCmdSN here if | 997 | * Check the CmdSN against ExpCmdSN/MaxCmdSN here if |
| 1010 | * the Immediate Bit is not set, and no Immediate | 998 | * the Immediate Bit is not set, and no Immediate |
| @@ -1031,10 +1019,7 @@ attach_cmd: | |||
| 1031 | * If no Immediate Data is attached, it's OK to return now. | 1019 | * If no Immediate Data is attached, it's OK to return now. |
| 1032 | */ | 1020 | */ |
| 1033 | if (!cmd->immediate_data) { | 1021 | if (!cmd->immediate_data) { |
| 1034 | if (send_check_condition) | 1022 | if (!cmd->sense_reason && cmd->unsolicited_data) { |
| 1035 | return 0; | ||
| 1036 | |||
| 1037 | if (cmd->unsolicited_data) { | ||
| 1038 | iscsit_set_dataout_sequence_values(cmd); | 1023 | iscsit_set_dataout_sequence_values(cmd); |
| 1039 | 1024 | ||
| 1040 | spin_lock_bh(&cmd->dataout_timeout_lock); | 1025 | spin_lock_bh(&cmd->dataout_timeout_lock); |
| @@ -1050,19 +1035,17 @@ attach_cmd: | |||
| 1050 | * thread. They are processed in CmdSN order by | 1035 | * thread. They are processed in CmdSN order by |
| 1051 | * iscsit_check_received_cmdsn() below. | 1036 | * iscsit_check_received_cmdsn() below. |
| 1052 | */ | 1037 | */ |
| 1053 | if (send_check_condition) { | 1038 | if (cmd->sense_reason) { |
| 1054 | immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; | 1039 | immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; |
| 1055 | dump_immediate_data = 1; | ||
| 1056 | goto after_immediate_data; | 1040 | goto after_immediate_data; |
| 1057 | } | 1041 | } |
| 1058 | /* | 1042 | /* |
| 1059 | * Call directly into transport_generic_new_cmd() to perform | 1043 | * Call directly into transport_generic_new_cmd() to perform |
| 1060 | * the backend memory allocation. | 1044 | * the backend memory allocation. |
| 1061 | */ | 1045 | */ |
| 1062 | ret = transport_generic_new_cmd(&cmd->se_cmd); | 1046 | cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); |
| 1063 | if (ret < 0) { | 1047 | if (cmd->sense_reason) { |
| 1064 | immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; | 1048 | immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; |
| 1065 | dump_immediate_data = 1; | ||
| 1066 | goto after_immediate_data; | 1049 | goto after_immediate_data; |
| 1067 | } | 1050 | } |
| 1068 | 1051 | ||
| @@ -1079,7 +1062,7 @@ after_immediate_data: | |||
| 1079 | * Special case for Unsupported SAM WRITE Opcodes | 1062 | * Special case for Unsupported SAM WRITE Opcodes |
| 1080 | * and ImmediateData=Yes. | 1063 | * and ImmediateData=Yes. |
| 1081 | */ | 1064 | */ |
| 1082 | if (dump_immediate_data) { | 1065 | if (cmd->sense_reason) { |
| 1083 | if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) | 1066 | if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) |
| 1084 | return -1; | 1067 | return -1; |
| 1085 | } else if (cmd->unsolicited_data) { | 1068 | } else if (cmd->unsolicited_data) { |
| @@ -1272,8 +1255,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) | |||
| 1272 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | 1255 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
| 1273 | 1256 | ||
| 1274 | spin_lock_irqsave(&se_cmd->t_state_lock, flags); | 1257 | spin_lock_irqsave(&se_cmd->t_state_lock, flags); |
| 1275 | if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) || | 1258 | if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE)) |
| 1276 | (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) | ||
| 1277 | dump_unsolicited_data = 1; | 1259 | dump_unsolicited_data = 1; |
| 1278 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | 1260 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
| 1279 | 1261 | ||
| @@ -1742,7 +1724,6 @@ static int iscsit_handle_task_mgt_cmd( | |||
| 1742 | ret = transport_lookup_tmr_lun(&cmd->se_cmd, | 1724 | ret = transport_lookup_tmr_lun(&cmd->se_cmd, |
| 1743 | scsilun_to_int(&hdr->lun)); | 1725 | scsilun_to_int(&hdr->lun)); |
| 1744 | if (ret < 0) { | 1726 | if (ret < 0) { |
| 1745 | cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1746 | se_tmr->response = ISCSI_TMF_RSP_NO_LUN; | 1727 | se_tmr->response = ISCSI_TMF_RSP_NO_LUN; |
| 1747 | goto attach; | 1728 | goto attach; |
| 1748 | } | 1729 | } |
| @@ -1751,10 +1732,8 @@ static int iscsit_handle_task_mgt_cmd( | |||
| 1751 | switch (function) { | 1732 | switch (function) { |
| 1752 | case ISCSI_TM_FUNC_ABORT_TASK: | 1733 | case ISCSI_TM_FUNC_ABORT_TASK: |
| 1753 | se_tmr->response = iscsit_tmr_abort_task(cmd, buf); | 1734 | se_tmr->response = iscsit_tmr_abort_task(cmd, buf); |
| 1754 | if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) { | 1735 | if (se_tmr->response) |
| 1755 | cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1756 | goto attach; | 1736 | goto attach; |
| 1757 | } | ||
| 1758 | break; | 1737 | break; |
| 1759 | case ISCSI_TM_FUNC_ABORT_TASK_SET: | 1738 | case ISCSI_TM_FUNC_ABORT_TASK_SET: |
| 1760 | case ISCSI_TM_FUNC_CLEAR_ACA: | 1739 | case ISCSI_TM_FUNC_CLEAR_ACA: |
| @@ -1763,14 +1742,12 @@ static int iscsit_handle_task_mgt_cmd( | |||
| 1763 | break; | 1742 | break; |
| 1764 | case ISCSI_TM_FUNC_TARGET_WARM_RESET: | 1743 | case ISCSI_TM_FUNC_TARGET_WARM_RESET: |
| 1765 | if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) { | 1744 | if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) { |
| 1766 | cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1767 | se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; | 1745 | se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; |
| 1768 | goto attach; | 1746 | goto attach; |
| 1769 | } | 1747 | } |
| 1770 | break; | 1748 | break; |
| 1771 | case ISCSI_TM_FUNC_TARGET_COLD_RESET: | 1749 | case ISCSI_TM_FUNC_TARGET_COLD_RESET: |
| 1772 | if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) { | 1750 | if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) { |
| 1773 | cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1774 | se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; | 1751 | se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; |
| 1775 | goto attach; | 1752 | goto attach; |
| 1776 | } | 1753 | } |
| @@ -1781,7 +1758,7 @@ static int iscsit_handle_task_mgt_cmd( | |||
| 1781 | * Perform sanity checks on the ExpDataSN only if the | 1758 | * Perform sanity checks on the ExpDataSN only if the |
| 1782 | * TASK_REASSIGN was successful. | 1759 | * TASK_REASSIGN was successful. |
| 1783 | */ | 1760 | */ |
| 1784 | if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) | 1761 | if (se_tmr->response) |
| 1785 | break; | 1762 | break; |
| 1786 | 1763 | ||
| 1787 | if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) | 1764 | if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) |
| @@ -1792,7 +1769,6 @@ static int iscsit_handle_task_mgt_cmd( | |||
| 1792 | default: | 1769 | default: |
| 1793 | pr_err("Unknown TMR function: 0x%02x, protocol" | 1770 | pr_err("Unknown TMR function: 0x%02x, protocol" |
| 1794 | " error.\n", function); | 1771 | " error.\n", function); |
| 1795 | cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1796 | se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED; | 1772 | se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED; |
| 1797 | goto attach; | 1773 | goto attach; |
| 1798 | } | 1774 | } |
| @@ -2360,7 +2336,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) | |||
| 2360 | if (!conn_p) | 2336 | if (!conn_p) |
| 2361 | return; | 2337 | return; |
| 2362 | 2338 | ||
| 2363 | cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL); | 2339 | cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); |
| 2364 | if (!cmd) { | 2340 | if (!cmd) { |
| 2365 | iscsit_dec_conn_usage_count(conn_p); | 2341 | iscsit_dec_conn_usage_count(conn_p); |
| 2366 | return; | 2342 | return; |
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 0f03b7919d7c..78d75c8567d0 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c | |||
| @@ -754,9 +754,33 @@ static ssize_t lio_target_nacl_store_cmdsn_depth( | |||
| 754 | 754 | ||
| 755 | TF_NACL_BASE_ATTR(lio_target, cmdsn_depth, S_IRUGO | S_IWUSR); | 755 | TF_NACL_BASE_ATTR(lio_target, cmdsn_depth, S_IRUGO | S_IWUSR); |
| 756 | 756 | ||
| 757 | static ssize_t lio_target_nacl_show_tag( | ||
| 758 | struct se_node_acl *se_nacl, | ||
| 759 | char *page) | ||
| 760 | { | ||
| 761 | return snprintf(page, PAGE_SIZE, "%s", se_nacl->acl_tag); | ||
| 762 | } | ||
| 763 | |||
| 764 | static ssize_t lio_target_nacl_store_tag( | ||
| 765 | struct se_node_acl *se_nacl, | ||
| 766 | const char *page, | ||
| 767 | size_t count) | ||
| 768 | { | ||
| 769 | int ret; | ||
| 770 | |||
| 771 | ret = core_tpg_set_initiator_node_tag(se_nacl->se_tpg, se_nacl, page); | ||
| 772 | |||
| 773 | if (ret < 0) | ||
| 774 | return ret; | ||
| 775 | return count; | ||
| 776 | } | ||
| 777 | |||
| 778 | TF_NACL_BASE_ATTR(lio_target, tag, S_IRUGO | S_IWUSR); | ||
| 779 | |||
| 757 | static struct configfs_attribute *lio_target_initiator_attrs[] = { | 780 | static struct configfs_attribute *lio_target_initiator_attrs[] = { |
| 758 | &lio_target_nacl_info.attr, | 781 | &lio_target_nacl_info.attr, |
| 759 | &lio_target_nacl_cmdsn_depth.attr, | 782 | &lio_target_nacl_cmdsn_depth.attr, |
| 783 | &lio_target_nacl_tag.attr, | ||
| 760 | NULL, | 784 | NULL, |
| 761 | }; | 785 | }; |
| 762 | 786 | ||
| @@ -803,7 +827,7 @@ static struct se_node_acl *lio_target_make_nodeacl( | |||
| 803 | acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl); | 827 | acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl); |
| 804 | stats_cg = &se_nacl->acl_fabric_stat_group; | 828 | stats_cg = &se_nacl->acl_fabric_stat_group; |
| 805 | 829 | ||
| 806 | stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 830 | stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
| 807 | GFP_KERNEL); | 831 | GFP_KERNEL); |
| 808 | if (!stats_cg->default_groups) { | 832 | if (!stats_cg->default_groups) { |
| 809 | pr_err("Unable to allocate memory for" | 833 | pr_err("Unable to allocate memory for" |
| @@ -1268,7 +1292,7 @@ static struct se_wwn *lio_target_call_coreaddtiqn( | |||
| 1268 | */ | 1292 | */ |
| 1269 | stats_cg = &tiqn->tiqn_wwn.fabric_stat_group; | 1293 | stats_cg = &tiqn->tiqn_wwn.fabric_stat_group; |
| 1270 | 1294 | ||
| 1271 | stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 6, | 1295 | stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6, |
| 1272 | GFP_KERNEL); | 1296 | GFP_KERNEL); |
| 1273 | if (!stats_cg->default_groups) { | 1297 | if (!stats_cg->default_groups) { |
| 1274 | pr_err("Unable to allocate memory for" | 1298 | pr_err("Unable to allocate memory for" |
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 21048dbf7d13..7a333d28d9a2 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h | |||
| @@ -474,7 +474,7 @@ struct iscsi_cmd { | |||
| 474 | struct scatterlist *first_data_sg; | 474 | struct scatterlist *first_data_sg; |
| 475 | u32 first_data_sg_off; | 475 | u32 first_data_sg_off; |
| 476 | u32 kmapped_nents; | 476 | u32 kmapped_nents; |
| 477 | 477 | sense_reason_t sense_reason; | |
| 478 | } ____cacheline_aligned; | 478 | } ____cacheline_aligned; |
| 479 | 479 | ||
| 480 | struct iscsi_tmr_req { | 480 | struct iscsi_tmr_req { |
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 21f29d91a8cb..0b52a2371305 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c | |||
| @@ -929,11 +929,10 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) | |||
| 929 | case ISCSI_OP_SCSI_CMD: | 929 | case ISCSI_OP_SCSI_CMD: |
| 930 | /* | 930 | /* |
| 931 | * Go ahead and send the CHECK_CONDITION status for | 931 | * Go ahead and send the CHECK_CONDITION status for |
| 932 | * any SCSI CDB exceptions that may have occurred, also | 932 | * any SCSI CDB exceptions that may have occurred. |
| 933 | * handle the SCF_SCSI_RESERVATION_CONFLICT case here as well. | ||
| 934 | */ | 933 | */ |
| 935 | if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { | 934 | if (cmd->sense_reason) { |
| 936 | if (se_cmd->scsi_sense_reason == TCM_RESERVATION_CONFLICT) { | 935 | if (cmd->sense_reason == TCM_RESERVATION_CONFLICT) { |
| 937 | cmd->i_state = ISTATE_SEND_STATUS; | 936 | cmd->i_state = ISTATE_SEND_STATUS; |
| 938 | spin_unlock_bh(&cmd->istate_lock); | 937 | spin_unlock_bh(&cmd->istate_lock); |
| 939 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, | 938 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, |
| @@ -956,7 +955,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) | |||
| 956 | * exception | 955 | * exception |
| 957 | */ | 956 | */ |
| 958 | return transport_send_check_condition_and_sense(se_cmd, | 957 | return transport_send_check_condition_and_sense(se_cmd, |
| 959 | se_cmd->scsi_sense_reason, 0); | 958 | cmd->sense_reason, 0); |
| 960 | } | 959 | } |
| 961 | /* | 960 | /* |
| 962 | * Special case for delayed CmdSN with Immediate | 961 | * Special case for delayed CmdSN with Immediate |
| @@ -1013,7 +1012,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) | |||
| 1013 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); | 1012 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); |
| 1014 | break; | 1013 | break; |
| 1015 | case ISCSI_OP_SCSI_TMFUNC: | 1014 | case ISCSI_OP_SCSI_TMFUNC: |
| 1016 | if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { | 1015 | if (cmd->se_cmd.se_tmr_req->response) { |
| 1017 | spin_unlock_bh(&cmd->istate_lock); | 1016 | spin_unlock_bh(&cmd->istate_lock); |
| 1018 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, | 1017 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, |
| 1019 | cmd->i_state); | 1018 | cmd->i_state); |
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 17d8c20094fd..9ac4c151eae4 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c | |||
| @@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) | |||
| 372 | * made generic here. | 372 | * made generic here. |
| 373 | */ | 373 | */ |
| 374 | if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && | 374 | if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && |
| 375 | (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) { | 375 | iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { |
| 376 | list_del(&cmd->i_conn_node); | 376 | list_del(&cmd->i_conn_node); |
| 377 | spin_unlock_bh(&conn->cmd_lock); | 377 | spin_unlock_bh(&conn->cmd_lock); |
| 378 | iscsit_free_cmd(cmd); | 378 | iscsit_free_cmd(cmd); |
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index f8dbec05d5e5..fdb632f0ab85 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
| @@ -127,13 +127,13 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) | |||
| 127 | 127 | ||
| 128 | initiatorname_param = iscsi_find_param_from_key( | 128 | initiatorname_param = iscsi_find_param_from_key( |
| 129 | INITIATORNAME, conn->param_list); | 129 | INITIATORNAME, conn->param_list); |
| 130 | if (!initiatorname_param) | ||
| 131 | return -1; | ||
| 132 | |||
| 133 | sessiontype_param = iscsi_find_param_from_key( | 130 | sessiontype_param = iscsi_find_param_from_key( |
| 134 | SESSIONTYPE, conn->param_list); | 131 | SESSIONTYPE, conn->param_list); |
| 135 | if (!sessiontype_param) | 132 | if (!initiatorname_param || !sessiontype_param) { |
| 133 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | ||
| 134 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | ||
| 136 | return -1; | 135 | return -1; |
| 136 | } | ||
| 137 | 137 | ||
| 138 | sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0; | 138 | sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0; |
| 139 | 139 | ||
| @@ -254,9 +254,9 @@ static int iscsi_login_zero_tsih_s1( | |||
| 254 | kfree(sess); | 254 | kfree(sess); |
| 255 | return -ENOMEM; | 255 | return -ENOMEM; |
| 256 | } | 256 | } |
| 257 | spin_lock(&sess_idr_lock); | 257 | spin_lock_bh(&sess_idr_lock); |
| 258 | ret = idr_get_new(&sess_idr, NULL, &sess->session_index); | 258 | ret = idr_get_new(&sess_idr, NULL, &sess->session_index); |
| 259 | spin_unlock(&sess_idr_lock); | 259 | spin_unlock_bh(&sess_idr_lock); |
| 260 | 260 | ||
| 261 | if (ret < 0) { | 261 | if (ret < 0) { |
| 262 | pr_err("idr_get_new() for sess_idr failed\n"); | 262 | pr_err("idr_get_new() for sess_idr failed\n"); |
| @@ -1118,10 +1118,8 @@ new_sess_out: | |||
| 1118 | idr_remove(&sess_idr, conn->sess->session_index); | 1118 | idr_remove(&sess_idr, conn->sess->session_index); |
| 1119 | spin_unlock_bh(&sess_idr_lock); | 1119 | spin_unlock_bh(&sess_idr_lock); |
| 1120 | } | 1120 | } |
| 1121 | if (conn->sess->sess_ops) | 1121 | kfree(conn->sess->sess_ops); |
| 1122 | kfree(conn->sess->sess_ops); | 1122 | kfree(conn->sess); |
| 1123 | if (conn->sess) | ||
| 1124 | kfree(conn->sess); | ||
| 1125 | old_sess_out: | 1123 | old_sess_out: |
| 1126 | iscsi_stop_login_thread_timer(np); | 1124 | iscsi_stop_login_thread_timer(np); |
| 1127 | /* | 1125 | /* |
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index e9053a04f24c..9d902aefe01a 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c | |||
| @@ -620,8 +620,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log | |||
| 620 | login->req_buf, | 620 | login->req_buf, |
| 621 | payload_length, | 621 | payload_length, |
| 622 | conn); | 622 | conn); |
| 623 | if (ret < 0) | 623 | if (ret < 0) { |
| 624 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | ||
| 625 | ISCSI_LOGIN_STATUS_INIT_ERR); | ||
| 624 | return -1; | 626 | return -1; |
| 627 | } | ||
| 625 | 628 | ||
| 626 | if (login->first_request) | 629 | if (login->first_request) |
| 627 | if (iscsi_target_check_first_request(conn, login) < 0) | 630 | if (iscsi_target_check_first_request(conn, login) < 0) |
| @@ -636,8 +639,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log | |||
| 636 | login->rsp_buf, | 639 | login->rsp_buf, |
| 637 | &login->rsp_length, | 640 | &login->rsp_length, |
| 638 | conn->param_list); | 641 | conn->param_list); |
| 639 | if (ret < 0) | 642 | if (ret < 0) { |
| 643 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | ||
| 644 | ISCSI_LOGIN_STATUS_INIT_ERR); | ||
| 640 | return -1; | 645 | return -1; |
| 646 | } | ||
| 641 | 647 | ||
| 642 | if (!login->auth_complete && | 648 | if (!login->auth_complete && |
| 643 | ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) { | 649 | ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) { |
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 1bf7432bfcbc..d89164287d00 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c | |||
| @@ -154,22 +154,18 @@ static struct iscsi_param *iscsi_set_default_param(struct iscsi_param_list *para | |||
| 154 | } | 154 | } |
| 155 | INIT_LIST_HEAD(¶m->p_list); | 155 | INIT_LIST_HEAD(¶m->p_list); |
| 156 | 156 | ||
| 157 | param->name = kzalloc(strlen(name) + 1, GFP_KERNEL); | 157 | param->name = kstrdup(name, GFP_KERNEL); |
| 158 | if (!param->name) { | 158 | if (!param->name) { |
| 159 | pr_err("Unable to allocate memory for parameter name.\n"); | 159 | pr_err("Unable to allocate memory for parameter name.\n"); |
| 160 | goto out; | 160 | goto out; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | param->value = kzalloc(strlen(value) + 1, GFP_KERNEL); | 163 | param->value = kstrdup(value, GFP_KERNEL); |
| 164 | if (!param->value) { | 164 | if (!param->value) { |
| 165 | pr_err("Unable to allocate memory for parameter value.\n"); | 165 | pr_err("Unable to allocate memory for parameter value.\n"); |
| 166 | goto out; | 166 | goto out; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | memcpy(param->name, name, strlen(name)); | ||
| 170 | param->name[strlen(name)] = '\0'; | ||
| 171 | memcpy(param->value, value, strlen(value)); | ||
| 172 | param->value[strlen(value)] = '\0'; | ||
| 173 | param->phase = phase; | 169 | param->phase = phase; |
| 174 | param->scope = scope; | 170 | param->scope = scope; |
| 175 | param->sender = sender; | 171 | param->sender = sender; |
| @@ -635,11 +631,8 @@ void iscsi_release_param_list(struct iscsi_param_list *param_list) | |||
| 635 | list_del(¶m->p_list); | 631 | list_del(¶m->p_list); |
| 636 | 632 | ||
| 637 | kfree(param->name); | 633 | kfree(param->name); |
| 638 | param->name = NULL; | ||
| 639 | kfree(param->value); | 634 | kfree(param->value); |
| 640 | param->value = NULL; | ||
| 641 | kfree(param); | 635 | kfree(param); |
| 642 | param = NULL; | ||
| 643 | } | 636 | } |
| 644 | 637 | ||
| 645 | iscsi_release_extra_responses(param_list); | 638 | iscsi_release_extra_responses(param_list); |
| @@ -687,15 +680,12 @@ int iscsi_update_param_value(struct iscsi_param *param, char *value) | |||
| 687 | { | 680 | { |
| 688 | kfree(param->value); | 681 | kfree(param->value); |
| 689 | 682 | ||
| 690 | param->value = kzalloc(strlen(value) + 1, GFP_KERNEL); | 683 | param->value = kstrdup(value, GFP_KERNEL); |
| 691 | if (!param->value) { | 684 | if (!param->value) { |
| 692 | pr_err("Unable to allocate memory for value.\n"); | 685 | pr_err("Unable to allocate memory for value.\n"); |
| 693 | return -ENOMEM; | 686 | return -ENOMEM; |
| 694 | } | 687 | } |
| 695 | 688 | ||
| 696 | memcpy(param->value, value, strlen(value)); | ||
| 697 | param->value[strlen(value)] = '\0'; | ||
| 698 | |||
| 699 | pr_debug("iSCSI Parameter updated to %s=%s\n", | 689 | pr_debug("iSCSI Parameter updated to %s=%s\n", |
| 700 | param->name, param->value); | 690 | param->name, param->value); |
| 701 | return 0; | 691 | return 0; |
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c index 4a99820d063b..9d4417aae921 100644 --- a/drivers/target/iscsi/iscsi_target_tmr.c +++ b/drivers/target/iscsi/iscsi_target_tmr.c | |||
| @@ -50,8 +50,8 @@ u8 iscsit_tmr_abort_task( | |||
| 50 | if (!ref_cmd) { | 50 | if (!ref_cmd) { |
| 51 | pr_err("Unable to locate RefTaskTag: 0x%08x on CID:" | 51 | pr_err("Unable to locate RefTaskTag: 0x%08x on CID:" |
| 52 | " %hu.\n", hdr->rtt, conn->cid); | 52 | " %hu.\n", hdr->rtt, conn->cid); |
| 53 | return (be32_to_cpu(hdr->refcmdsn) >= conn->sess->exp_cmd_sn && | 53 | return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) && |
| 54 | be32_to_cpu(hdr->refcmdsn) <= conn->sess->max_cmd_sn) ? | 54 | iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ? |
| 55 | ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK; | 55 | ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK; |
| 56 | } | 56 | } |
| 57 | if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) { | 57 | if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) { |
diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c index 9d881a000e42..81289520f96b 100644 --- a/drivers/target/iscsi/iscsi_target_tq.c +++ b/drivers/target/iscsi/iscsi_target_tq.c | |||
| @@ -66,8 +66,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void) | |||
| 66 | return NULL; | 66 | return NULL; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | list_for_each_entry(ts, &inactive_ts_list, ts_list) | 69 | ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list); |
| 70 | break; | ||
| 71 | 70 | ||
| 72 | list_del(&ts->ts_list); | 71 | list_del(&ts->ts_list); |
| 73 | iscsit_global->inactive_ts--; | 72 | iscsit_global->inactive_ts--; |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 69e0cfd98870..7ce350578c82 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
| @@ -500,8 +500,8 @@ struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *c | |||
| 500 | spin_unlock_bh(&conn->immed_queue_lock); | 500 | spin_unlock_bh(&conn->immed_queue_lock); |
| 501 | return NULL; | 501 | return NULL; |
| 502 | } | 502 | } |
| 503 | list_for_each_entry(qr, &conn->immed_queue_list, qr_list) | 503 | qr = list_first_entry(&conn->immed_queue_list, |
| 504 | break; | 504 | struct iscsi_queue_req, qr_list); |
| 505 | 505 | ||
| 506 | list_del(&qr->qr_list); | 506 | list_del(&qr->qr_list); |
| 507 | if (qr->cmd) | 507 | if (qr->cmd) |
| @@ -575,8 +575,8 @@ struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *co | |||
| 575 | return NULL; | 575 | return NULL; |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | list_for_each_entry(qr, &conn->response_queue_list, qr_list) | 578 | qr = list_first_entry(&conn->response_queue_list, |
| 579 | break; | 579 | struct iscsi_queue_req, qr_list); |
| 580 | 580 | ||
| 581 | list_del(&qr->qr_list); | 581 | list_del(&qr->qr_list); |
| 582 | if (qr->cmd) | 582 | if (qr->cmd) |
diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h index 7b54893db665..dd7a84ee78e1 100644 --- a/drivers/target/loopback/tcm_loop.h +++ b/drivers/target/loopback/tcm_loop.h | |||
| @@ -53,7 +53,6 @@ struct tcm_loop_hba { | |||
| 53 | struct se_hba_s *se_hba; | 53 | struct se_hba_s *se_hba; |
| 54 | struct se_lun *tl_hba_lun; | 54 | struct se_lun *tl_hba_lun; |
| 55 | struct se_port *tl_hba_lun_sep; | 55 | struct se_port *tl_hba_lun_sep; |
| 56 | struct se_device_s *se_dev_hba_ptr; | ||
| 57 | struct tcm_loop_nexus *tl_nexus; | 56 | struct tcm_loop_nexus *tl_nexus; |
| 58 | struct device dev; | 57 | struct device dev; |
| 59 | struct Scsi_Host *sh; | 58 | struct Scsi_Host *sh; |
diff --git a/drivers/target/sbp/Kconfig b/drivers/target/sbp/Kconfig index 132da544eafc..1614bc710d4e 100644 --- a/drivers/target/sbp/Kconfig +++ b/drivers/target/sbp/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config SBP_TARGET | 1 | config SBP_TARGET |
| 2 | tristate "FireWire SBP-2 fabric module" | 2 | tristate "FireWire SBP-2 fabric module" |
| 3 | depends on FIREWIRE && EXPERIMENTAL | 3 | depends on FIREWIRE |
| 4 | help | 4 | help |
| 5 | Say Y or M here to enable SCSI target functionality over FireWire. | 5 | Say Y or M here to enable SCSI target functionality over FireWire. |
| 6 | This enables you to expose SCSI devices to other nodes on the FireWire | 6 | This enables you to expose SCSI devices to other nodes on the FireWire |
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c index 0d6d7c1f025e..2e8d06f198ae 100644 --- a/drivers/target/sbp/sbp_target.c +++ b/drivers/target/sbp/sbp_target.c | |||
| @@ -704,16 +704,17 @@ static void session_maintenance_work(struct work_struct *work) | |||
| 704 | static int tgt_agent_rw_agent_state(struct fw_card *card, int tcode, void *data, | 704 | static int tgt_agent_rw_agent_state(struct fw_card *card, int tcode, void *data, |
| 705 | struct sbp_target_agent *agent) | 705 | struct sbp_target_agent *agent) |
| 706 | { | 706 | { |
| 707 | __be32 state; | 707 | int state; |
| 708 | 708 | ||
| 709 | switch (tcode) { | 709 | switch (tcode) { |
| 710 | case TCODE_READ_QUADLET_REQUEST: | 710 | case TCODE_READ_QUADLET_REQUEST: |
| 711 | pr_debug("tgt_agent AGENT_STATE READ\n"); | 711 | pr_debug("tgt_agent AGENT_STATE READ\n"); |
| 712 | 712 | ||
| 713 | spin_lock_bh(&agent->lock); | 713 | spin_lock_bh(&agent->lock); |
| 714 | state = cpu_to_be32(agent->state); | 714 | state = agent->state; |
| 715 | spin_unlock_bh(&agent->lock); | 715 | spin_unlock_bh(&agent->lock); |
| 716 | memcpy(data, &state, sizeof(state)); | 716 | |
| 717 | *(__be32 *)data = cpu_to_be32(state); | ||
| 717 | 718 | ||
| 718 | return RCODE_COMPLETE; | 719 | return RCODE_COMPLETE; |
| 719 | 720 | ||
| @@ -2207,20 +2208,23 @@ static struct se_portal_group *sbp_make_tpg( | |||
| 2207 | tport->mgt_agt = sbp_management_agent_register(tport); | 2208 | tport->mgt_agt = sbp_management_agent_register(tport); |
| 2208 | if (IS_ERR(tport->mgt_agt)) { | 2209 | if (IS_ERR(tport->mgt_agt)) { |
| 2209 | ret = PTR_ERR(tport->mgt_agt); | 2210 | ret = PTR_ERR(tport->mgt_agt); |
| 2210 | kfree(tpg); | 2211 | goto out_free_tpg; |
| 2211 | return ERR_PTR(ret); | ||
| 2212 | } | 2212 | } |
| 2213 | 2213 | ||
| 2214 | ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn, | 2214 | ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn, |
| 2215 | &tpg->se_tpg, (void *)tpg, | 2215 | &tpg->se_tpg, (void *)tpg, |
| 2216 | TRANSPORT_TPG_TYPE_NORMAL); | 2216 | TRANSPORT_TPG_TYPE_NORMAL); |
| 2217 | if (ret < 0) { | 2217 | if (ret < 0) |
| 2218 | sbp_management_agent_unregister(tport->mgt_agt); | 2218 | goto out_unreg_mgt_agt; |
| 2219 | kfree(tpg); | ||
| 2220 | return ERR_PTR(ret); | ||
| 2221 | } | ||
| 2222 | 2219 | ||
| 2223 | return &tpg->se_tpg; | 2220 | return &tpg->se_tpg; |
| 2221 | |||
| 2222 | out_unreg_mgt_agt: | ||
| 2223 | sbp_management_agent_unregister(tport->mgt_agt); | ||
| 2224 | out_free_tpg: | ||
| 2225 | tport->tpg = NULL; | ||
| 2226 | kfree(tpg); | ||
| 2227 | return ERR_PTR(ret); | ||
| 2224 | } | 2228 | } |
| 2225 | 2229 | ||
| 2226 | static void sbp_drop_tpg(struct se_portal_group *se_tpg) | 2230 | static void sbp_drop_tpg(struct se_portal_group *se_tpg) |
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 9a5f9a7aecd2..85140f7dde1e 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c | |||
| @@ -3,8 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains SPC-3 compliant asymmetric logical unit assigntment (ALUA) | 4 | * This file contains SPC-3 compliant asymmetric logical unit assigntment (ALUA) |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2009-2010 Rising Tide Systems | 6 | * (c) Copyright 2009-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2009-2010 Linux-iSCSI.org | ||
| 8 | * | 7 | * |
| 9 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 10 | * | 9 | * |
| @@ -41,7 +40,7 @@ | |||
| 41 | #include "target_core_alua.h" | 40 | #include "target_core_alua.h" |
| 42 | #include "target_core_ua.h" | 41 | #include "target_core_ua.h" |
| 43 | 42 | ||
| 44 | static int core_alua_check_transition(int state, int *primary); | 43 | static sense_reason_t core_alua_check_transition(int state, int *primary); |
| 45 | static int core_alua_set_tg_pt_secondary_state( | 44 | static int core_alua_set_tg_pt_secondary_state( |
| 46 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, | 45 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, |
| 47 | struct se_port *port, int explict, int offline); | 46 | struct se_port *port, int explict, int offline); |
| @@ -59,15 +58,17 @@ struct t10_alua_lu_gp *default_lu_gp; | |||
| 59 | * | 58 | * |
| 60 | * See spc4r17 section 6.27 | 59 | * See spc4r17 section 6.27 |
| 61 | */ | 60 | */ |
| 62 | int target_emulate_report_target_port_groups(struct se_cmd *cmd) | 61 | sense_reason_t |
| 62 | target_emulate_report_target_port_groups(struct se_cmd *cmd) | ||
| 63 | { | 63 | { |
| 64 | struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; | 64 | struct se_device *dev = cmd->se_dev; |
| 65 | struct se_port *port; | 65 | struct se_port *port; |
| 66 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 66 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 67 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | 67 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; |
| 68 | unsigned char *buf; | 68 | unsigned char *buf; |
| 69 | u32 rd_len = 0, off; | 69 | u32 rd_len = 0, off; |
| 70 | int ext_hdr = (cmd->t_task_cdb[1] & 0x20); | 70 | int ext_hdr = (cmd->t_task_cdb[1] & 0x20); |
| 71 | |||
| 71 | /* | 72 | /* |
| 72 | * Skip over RESERVED area to first Target port group descriptor | 73 | * Skip over RESERVED area to first Target port group descriptor |
| 73 | * depending on the PARAMETER DATA FORMAT type.. | 74 | * depending on the PARAMETER DATA FORMAT type.. |
| @@ -81,13 +82,14 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) | |||
| 81 | pr_warn("REPORT TARGET PORT GROUPS allocation length %u too" | 82 | pr_warn("REPORT TARGET PORT GROUPS allocation length %u too" |
| 82 | " small for %s header\n", cmd->data_length, | 83 | " small for %s header\n", cmd->data_length, |
| 83 | (ext_hdr) ? "extended" : "normal"); | 84 | (ext_hdr) ? "extended" : "normal"); |
| 84 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 85 | return TCM_INVALID_CDB_FIELD; |
| 85 | return -EINVAL; | ||
| 86 | } | 86 | } |
| 87 | buf = transport_kmap_data_sg(cmd); | 87 | buf = transport_kmap_data_sg(cmd); |
| 88 | if (!buf) | ||
| 89 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 88 | 90 | ||
| 89 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 91 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 90 | list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, | 92 | list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, |
| 91 | tg_pt_gp_list) { | 93 | tg_pt_gp_list) { |
| 92 | /* | 94 | /* |
| 93 | * Check if the Target port group and Target port descriptor list | 95 | * Check if the Target port group and Target port descriptor list |
| @@ -160,7 +162,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) | |||
| 160 | } | 162 | } |
| 161 | spin_unlock(&tg_pt_gp->tg_pt_gp_lock); | 163 | spin_unlock(&tg_pt_gp->tg_pt_gp_lock); |
| 162 | } | 164 | } |
| 163 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 165 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 164 | /* | 166 | /* |
| 165 | * Set the RETURN DATA LENGTH set in the header of the DataIN Payload | 167 | * Set the RETURN DATA LENGTH set in the header of the DataIN Payload |
| 166 | */ | 168 | */ |
| @@ -200,32 +202,33 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) | |||
| 200 | * | 202 | * |
| 201 | * See spc4r17 section 6.35 | 203 | * See spc4r17 section 6.35 |
| 202 | */ | 204 | */ |
| 203 | int target_emulate_set_target_port_groups(struct se_cmd *cmd) | 205 | sense_reason_t |
| 206 | target_emulate_set_target_port_groups(struct se_cmd *cmd) | ||
| 204 | { | 207 | { |
| 205 | struct se_device *dev = cmd->se_dev; | 208 | struct se_device *dev = cmd->se_dev; |
| 206 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 207 | struct se_port *port, *l_port = cmd->se_lun->lun_sep; | 209 | struct se_port *port, *l_port = cmd->se_lun->lun_sep; |
| 208 | struct se_node_acl *nacl = cmd->se_sess->se_node_acl; | 210 | struct se_node_acl *nacl = cmd->se_sess->se_node_acl; |
| 209 | struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; | 211 | struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; |
| 210 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; | 212 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; |
| 211 | unsigned char *buf; | 213 | unsigned char *buf; |
| 212 | unsigned char *ptr; | 214 | unsigned char *ptr; |
| 215 | sense_reason_t rc; | ||
| 213 | u32 len = 4; /* Skip over RESERVED area in header */ | 216 | u32 len = 4; /* Skip over RESERVED area in header */ |
| 214 | int alua_access_state, primary = 0, rc; | 217 | int alua_access_state, primary = 0; |
| 215 | u16 tg_pt_id, rtpi; | 218 | u16 tg_pt_id, rtpi; |
| 216 | 219 | ||
| 217 | if (!l_port) { | 220 | if (!l_port) |
| 218 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 221 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 219 | return -EINVAL; | 222 | |
| 220 | } | ||
| 221 | if (cmd->data_length < 4) { | 223 | if (cmd->data_length < 4) { |
| 222 | pr_warn("SET TARGET PORT GROUPS parameter list length %u too" | 224 | pr_warn("SET TARGET PORT GROUPS parameter list length %u too" |
| 223 | " small\n", cmd->data_length); | 225 | " small\n", cmd->data_length); |
| 224 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 226 | return TCM_INVALID_PARAMETER_LIST; |
| 225 | return -EINVAL; | ||
| 226 | } | 227 | } |
| 227 | 228 | ||
| 228 | buf = transport_kmap_data_sg(cmd); | 229 | buf = transport_kmap_data_sg(cmd); |
| 230 | if (!buf) | ||
| 231 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 229 | 232 | ||
| 230 | /* | 233 | /* |
| 231 | * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed | 234 | * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed |
| @@ -234,8 +237,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 234 | l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; | 237 | l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; |
| 235 | if (!l_tg_pt_gp_mem) { | 238 | if (!l_tg_pt_gp_mem) { |
| 236 | pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); | 239 | pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); |
| 237 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | 240 | rc = TCM_UNSUPPORTED_SCSI_OPCODE; |
| 238 | rc = -EINVAL; | ||
| 239 | goto out; | 241 | goto out; |
| 240 | } | 242 | } |
| 241 | spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); | 243 | spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| @@ -243,24 +245,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 243 | if (!l_tg_pt_gp) { | 245 | if (!l_tg_pt_gp) { |
| 244 | spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); | 246 | spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 245 | pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); | 247 | pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); |
| 246 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | 248 | rc = TCM_UNSUPPORTED_SCSI_OPCODE; |
| 247 | rc = -EINVAL; | ||
| 248 | goto out; | 249 | goto out; |
| 249 | } | 250 | } |
| 250 | rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA); | ||
| 251 | spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); | 251 | spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 252 | 252 | ||
| 253 | if (!rc) { | 253 | if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)) { |
| 254 | pr_debug("Unable to process SET_TARGET_PORT_GROUPS" | 254 | pr_debug("Unable to process SET_TARGET_PORT_GROUPS" |
| 255 | " while TPGS_EXPLICT_ALUA is disabled\n"); | 255 | " while TPGS_EXPLICT_ALUA is disabled\n"); |
| 256 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | 256 | rc = TCM_UNSUPPORTED_SCSI_OPCODE; |
| 257 | rc = -EINVAL; | ||
| 258 | goto out; | 257 | goto out; |
| 259 | } | 258 | } |
| 260 | 259 | ||
| 261 | ptr = &buf[4]; /* Skip over RESERVED area in header */ | 260 | ptr = &buf[4]; /* Skip over RESERVED area in header */ |
| 262 | 261 | ||
| 263 | while (len < cmd->data_length) { | 262 | while (len < cmd->data_length) { |
| 263 | bool found = false; | ||
| 264 | alua_access_state = (ptr[0] & 0x0f); | 264 | alua_access_state = (ptr[0] & 0x0f); |
| 265 | /* | 265 | /* |
| 266 | * Check the received ALUA access state, and determine if | 266 | * Check the received ALUA access state, and determine if |
| @@ -268,7 +268,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 268 | * access state. | 268 | * access state. |
| 269 | */ | 269 | */ |
| 270 | rc = core_alua_check_transition(alua_access_state, &primary); | 270 | rc = core_alua_check_transition(alua_access_state, &primary); |
| 271 | if (rc != 0) { | 271 | if (rc) { |
| 272 | /* | 272 | /* |
| 273 | * If the SET TARGET PORT GROUPS attempts to establish | 273 | * If the SET TARGET PORT GROUPS attempts to establish |
| 274 | * an invalid combination of target port asymmetric | 274 | * an invalid combination of target port asymmetric |
| @@ -279,11 +279,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 279 | * REQUEST, and the additional sense code set to INVALID | 279 | * REQUEST, and the additional sense code set to INVALID |
| 280 | * FIELD IN PARAMETER LIST. | 280 | * FIELD IN PARAMETER LIST. |
| 281 | */ | 281 | */ |
| 282 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | ||
| 283 | rc = -EINVAL; | ||
| 284 | goto out; | 282 | goto out; |
| 285 | } | 283 | } |
| 286 | rc = -1; | 284 | |
| 287 | /* | 285 | /* |
| 288 | * If the ASYMMETRIC ACCESS STATE field (see table 267) | 286 | * If the ASYMMETRIC ACCESS STATE field (see table 267) |
| 289 | * specifies a primary target port asymmetric access state, | 287 | * specifies a primary target port asymmetric access state, |
| @@ -303,9 +301,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 303 | * Locate the matching target port group ID from | 301 | * Locate the matching target port group ID from |
| 304 | * the global tg_pt_gp list | 302 | * the global tg_pt_gp list |
| 305 | */ | 303 | */ |
| 306 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 304 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 307 | list_for_each_entry(tg_pt_gp, | 305 | list_for_each_entry(tg_pt_gp, |
| 308 | &su_dev->t10_alua.tg_pt_gps_list, | 306 | &dev->t10_alua.tg_pt_gps_list, |
| 309 | tg_pt_gp_list) { | 307 | tg_pt_gp_list) { |
| 310 | if (!tg_pt_gp->tg_pt_gp_valid_id) | 308 | if (!tg_pt_gp->tg_pt_gp_valid_id) |
| 311 | continue; | 309 | continue; |
| @@ -315,27 +313,20 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 315 | 313 | ||
| 316 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); | 314 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); |
| 317 | smp_mb__after_atomic_inc(); | 315 | smp_mb__after_atomic_inc(); |
| 318 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | ||
| 319 | 316 | ||
| 320 | rc = core_alua_do_port_transition(tg_pt_gp, | 317 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 318 | |||
| 319 | if (!core_alua_do_port_transition(tg_pt_gp, | ||
| 321 | dev, l_port, nacl, | 320 | dev, l_port, nacl, |
| 322 | alua_access_state, 1); | 321 | alua_access_state, 1)) |
| 322 | found = true; | ||
| 323 | 323 | ||
| 324 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 324 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 325 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); | 325 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); |
| 326 | smp_mb__after_atomic_dec(); | 326 | smp_mb__after_atomic_dec(); |
| 327 | break; | 327 | break; |
| 328 | } | 328 | } |
| 329 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 329 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 330 | /* | ||
| 331 | * If not matching target port group ID can be located | ||
| 332 | * throw an exception with ASCQ: INVALID_PARAMETER_LIST | ||
| 333 | */ | ||
| 334 | if (rc != 0) { | ||
| 335 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | ||
| 336 | rc = -EINVAL; | ||
| 337 | goto out; | ||
| 338 | } | ||
| 339 | } else { | 330 | } else { |
| 340 | /* | 331 | /* |
| 341 | * Extact the RELATIVE TARGET PORT IDENTIFIER to identify | 332 | * Extact the RELATIVE TARGET PORT IDENTIFIER to identify |
| @@ -354,25 +345,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 354 | continue; | 345 | continue; |
| 355 | 346 | ||
| 356 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | 347 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; |
| 348 | |||
| 357 | spin_unlock(&dev->se_port_lock); | 349 | spin_unlock(&dev->se_port_lock); |
| 358 | 350 | ||
| 359 | rc = core_alua_set_tg_pt_secondary_state( | 351 | if (!core_alua_set_tg_pt_secondary_state( |
| 360 | tg_pt_gp_mem, port, 1, 1); | 352 | tg_pt_gp_mem, port, 1, 1)) |
| 353 | found = true; | ||
| 361 | 354 | ||
| 362 | spin_lock(&dev->se_port_lock); | 355 | spin_lock(&dev->se_port_lock); |
| 363 | break; | 356 | break; |
| 364 | } | 357 | } |
| 365 | spin_unlock(&dev->se_port_lock); | 358 | spin_unlock(&dev->se_port_lock); |
| 366 | /* | 359 | } |
| 367 | * If not matching relative target port identifier can | 360 | |
| 368 | * be located, throw an exception with ASCQ: | 361 | if (!found) { |
| 369 | * INVALID_PARAMETER_LIST | 362 | rc = TCM_INVALID_PARAMETER_LIST; |
| 370 | */ | 363 | goto out; |
| 371 | if (rc != 0) { | ||
| 372 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | ||
| 373 | rc = -EINVAL; | ||
| 374 | goto out; | ||
| 375 | } | ||
| 376 | } | 364 | } |
| 377 | 365 | ||
| 378 | ptr += 4; | 366 | ptr += 4; |
| @@ -523,40 +511,27 @@ static inline int core_alua_state_transition( | |||
| 523 | } | 511 | } |
| 524 | 512 | ||
| 525 | /* | 513 | /* |
| 526 | * Used for alua_type SPC_ALUA_PASSTHROUGH and SPC2_ALUA_DISABLED | ||
| 527 | * in transport_cmd_sequencer(). This function is assigned to | ||
| 528 | * struct t10_alua *->state_check() in core_setup_alua() | ||
| 529 | */ | ||
| 530 | static int core_alua_state_check_nop( | ||
| 531 | struct se_cmd *cmd, | ||
| 532 | unsigned char *cdb, | ||
| 533 | u8 *alua_ascq) | ||
| 534 | { | ||
| 535 | return 0; | ||
| 536 | } | ||
| 537 | |||
| 538 | /* | ||
| 539 | * Used for alua_type SPC3_ALUA_EMULATED in transport_cmd_sequencer(). | ||
| 540 | * This function is assigned to struct t10_alua *->state_check() in | ||
| 541 | * core_setup_alua() | ||
| 542 | * | ||
| 543 | * Also, this function can return three different return codes to | ||
| 544 | * signal transport_generic_cmd_sequencer() | ||
| 545 | * | ||
| 546 | * return 1: Is used to signal LUN not accecsable, and check condition/not ready | 514 | * return 1: Is used to signal LUN not accecsable, and check condition/not ready |
| 547 | * return 0: Used to signal success | 515 | * return 0: Used to signal success |
| 548 | * reutrn -1: Used to signal failure, and invalid cdb field | 516 | * reutrn -1: Used to signal failure, and invalid cdb field |
| 549 | */ | 517 | */ |
| 550 | static int core_alua_state_check( | 518 | sense_reason_t |
| 551 | struct se_cmd *cmd, | 519 | target_alua_state_check(struct se_cmd *cmd) |
| 552 | unsigned char *cdb, | ||
| 553 | u8 *alua_ascq) | ||
| 554 | { | 520 | { |
| 521 | struct se_device *dev = cmd->se_dev; | ||
| 522 | unsigned char *cdb = cmd->t_task_cdb; | ||
| 555 | struct se_lun *lun = cmd->se_lun; | 523 | struct se_lun *lun = cmd->se_lun; |
| 556 | struct se_port *port = lun->lun_sep; | 524 | struct se_port *port = lun->lun_sep; |
| 557 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 525 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 558 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | 526 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; |
| 559 | int out_alua_state, nonop_delay_msecs; | 527 | int out_alua_state, nonop_delay_msecs; |
| 528 | u8 alua_ascq; | ||
| 529 | int ret; | ||
| 530 | |||
| 531 | if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) | ||
| 532 | return 0; | ||
| 533 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) | ||
| 534 | return 0; | ||
| 560 | 535 | ||
| 561 | if (!port) | 536 | if (!port) |
| 562 | return 0; | 537 | return 0; |
| @@ -565,11 +540,11 @@ static int core_alua_state_check( | |||
| 565 | * access state: OFFLINE | 540 | * access state: OFFLINE |
| 566 | */ | 541 | */ |
| 567 | if (atomic_read(&port->sep_tg_pt_secondary_offline)) { | 542 | if (atomic_read(&port->sep_tg_pt_secondary_offline)) { |
| 568 | *alua_ascq = ASCQ_04H_ALUA_OFFLINE; | ||
| 569 | pr_debug("ALUA: Got secondary offline status for local" | 543 | pr_debug("ALUA: Got secondary offline status for local" |
| 570 | " target port\n"); | 544 | " target port\n"); |
| 571 | *alua_ascq = ASCQ_04H_ALUA_OFFLINE; | 545 | alua_ascq = ASCQ_04H_ALUA_OFFLINE; |
| 572 | return 1; | 546 | ret = 1; |
| 547 | goto out; | ||
| 573 | } | 548 | } |
| 574 | /* | 549 | /* |
| 575 | * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the | 550 | * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the |
| @@ -594,14 +569,18 @@ static int core_alua_state_check( | |||
| 594 | 569 | ||
| 595 | switch (out_alua_state) { | 570 | switch (out_alua_state) { |
| 596 | case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: | 571 | case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: |
| 597 | return core_alua_state_nonoptimized(cmd, cdb, | 572 | ret = core_alua_state_nonoptimized(cmd, cdb, |
| 598 | nonop_delay_msecs, alua_ascq); | 573 | nonop_delay_msecs, &alua_ascq); |
| 574 | break; | ||
| 599 | case ALUA_ACCESS_STATE_STANDBY: | 575 | case ALUA_ACCESS_STATE_STANDBY: |
| 600 | return core_alua_state_standby(cmd, cdb, alua_ascq); | 576 | ret = core_alua_state_standby(cmd, cdb, &alua_ascq); |
| 577 | break; | ||
| 601 | case ALUA_ACCESS_STATE_UNAVAILABLE: | 578 | case ALUA_ACCESS_STATE_UNAVAILABLE: |
| 602 | return core_alua_state_unavailable(cmd, cdb, alua_ascq); | 579 | ret = core_alua_state_unavailable(cmd, cdb, &alua_ascq); |
| 580 | break; | ||
| 603 | case ALUA_ACCESS_STATE_TRANSITION: | 581 | case ALUA_ACCESS_STATE_TRANSITION: |
| 604 | return core_alua_state_transition(cmd, cdb, alua_ascq); | 582 | ret = core_alua_state_transition(cmd, cdb, &alua_ascq); |
| 583 | break; | ||
| 605 | /* | 584 | /* |
| 606 | * OFFLINE is a secondary ALUA target port group access state, that is | 585 | * OFFLINE is a secondary ALUA target port group access state, that is |
| 607 | * handled above with struct se_port->sep_tg_pt_secondary_offline=1 | 586 | * handled above with struct se_port->sep_tg_pt_secondary_offline=1 |
| @@ -610,7 +589,24 @@ static int core_alua_state_check( | |||
| 610 | default: | 589 | default: |
| 611 | pr_err("Unknown ALUA access state: 0x%02x\n", | 590 | pr_err("Unknown ALUA access state: 0x%02x\n", |
| 612 | out_alua_state); | 591 | out_alua_state); |
| 613 | return -EINVAL; | 592 | return TCM_INVALID_CDB_FIELD; |
| 593 | } | ||
| 594 | |||
| 595 | out: | ||
| 596 | if (ret > 0) { | ||
| 597 | /* | ||
| 598 | * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; | ||
| 599 | * The ALUA additional sense code qualifier (ASCQ) is determined | ||
| 600 | * by the ALUA primary or secondary access state.. | ||
| 601 | */ | ||
| 602 | pr_debug("[%s]: ALUA TG Port not available, " | ||
| 603 | "SenseKey: NOT_READY, ASC/ASCQ: " | ||
| 604 | "0x04/0x%02x\n", | ||
| 605 | cmd->se_tfo->get_fabric_name(), alua_ascq); | ||
| 606 | |||
| 607 | cmd->scsi_asc = 0x04; | ||
| 608 | cmd->scsi_ascq = alua_ascq; | ||
| 609 | return TCM_CHECK_CONDITION_NOT_READY; | ||
| 614 | } | 610 | } |
| 615 | 611 | ||
| 616 | return 0; | 612 | return 0; |
| @@ -619,7 +615,8 @@ static int core_alua_state_check( | |||
| 619 | /* | 615 | /* |
| 620 | * Check implict and explict ALUA state change request. | 616 | * Check implict and explict ALUA state change request. |
| 621 | */ | 617 | */ |
| 622 | static int core_alua_check_transition(int state, int *primary) | 618 | static sense_reason_t |
| 619 | core_alua_check_transition(int state, int *primary) | ||
| 623 | { | 620 | { |
| 624 | switch (state) { | 621 | switch (state) { |
| 625 | case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: | 622 | case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: |
| @@ -641,7 +638,7 @@ static int core_alua_check_transition(int state, int *primary) | |||
| 641 | break; | 638 | break; |
| 642 | default: | 639 | default: |
| 643 | pr_err("Unknown ALUA access state: 0x%02x\n", state); | 640 | pr_err("Unknown ALUA access state: 0x%02x\n", state); |
| 644 | return -EINVAL; | 641 | return TCM_INVALID_PARAMETER_LIST; |
| 645 | } | 642 | } |
| 646 | 643 | ||
| 647 | return 0; | 644 | return 0; |
| @@ -758,8 +755,7 @@ static int core_alua_update_tpg_primary_metadata( | |||
| 758 | int primary_state, | 755 | int primary_state, |
| 759 | unsigned char *md_buf) | 756 | unsigned char *md_buf) |
| 760 | { | 757 | { |
| 761 | struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; | 758 | struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn; |
| 762 | struct t10_wwn *wwn = &su_dev->t10_wwn; | ||
| 763 | char path[ALUA_METADATA_PATH_LEN]; | 759 | char path[ALUA_METADATA_PATH_LEN]; |
| 764 | int len; | 760 | int len; |
| 765 | 761 | ||
| @@ -899,7 +895,6 @@ int core_alua_do_port_transition( | |||
| 899 | { | 895 | { |
| 900 | struct se_device *dev; | 896 | struct se_device *dev; |
| 901 | struct se_port *port; | 897 | struct se_port *port; |
| 902 | struct se_subsystem_dev *su_dev; | ||
| 903 | struct se_node_acl *nacl; | 898 | struct se_node_acl *nacl; |
| 904 | struct t10_alua_lu_gp *lu_gp; | 899 | struct t10_alua_lu_gp *lu_gp; |
| 905 | struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; | 900 | struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; |
| @@ -949,14 +944,13 @@ int core_alua_do_port_transition( | |||
| 949 | lu_gp_mem_list) { | 944 | lu_gp_mem_list) { |
| 950 | 945 | ||
| 951 | dev = lu_gp_mem->lu_gp_mem_dev; | 946 | dev = lu_gp_mem->lu_gp_mem_dev; |
| 952 | su_dev = dev->se_sub_dev; | ||
| 953 | atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt); | 947 | atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt); |
| 954 | smp_mb__after_atomic_inc(); | 948 | smp_mb__after_atomic_inc(); |
| 955 | spin_unlock(&lu_gp->lu_gp_lock); | 949 | spin_unlock(&lu_gp->lu_gp_lock); |
| 956 | 950 | ||
| 957 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 951 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 958 | list_for_each_entry(tg_pt_gp, | 952 | list_for_each_entry(tg_pt_gp, |
| 959 | &su_dev->t10_alua.tg_pt_gps_list, | 953 | &dev->t10_alua.tg_pt_gps_list, |
| 960 | tg_pt_gp_list) { | 954 | tg_pt_gp_list) { |
| 961 | 955 | ||
| 962 | if (!tg_pt_gp->tg_pt_gp_valid_id) | 956 | if (!tg_pt_gp->tg_pt_gp_valid_id) |
| @@ -981,7 +975,7 @@ int core_alua_do_port_transition( | |||
| 981 | } | 975 | } |
| 982 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); | 976 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); |
| 983 | smp_mb__after_atomic_inc(); | 977 | smp_mb__after_atomic_inc(); |
| 984 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 978 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 985 | /* | 979 | /* |
| 986 | * core_alua_do_transition_tg_pt() will always return | 980 | * core_alua_do_transition_tg_pt() will always return |
| 987 | * success. | 981 | * success. |
| @@ -989,11 +983,11 @@ int core_alua_do_port_transition( | |||
| 989 | core_alua_do_transition_tg_pt(tg_pt_gp, port, | 983 | core_alua_do_transition_tg_pt(tg_pt_gp, port, |
| 990 | nacl, md_buf, new_state, explict); | 984 | nacl, md_buf, new_state, explict); |
| 991 | 985 | ||
| 992 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 986 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 993 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); | 987 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); |
| 994 | smp_mb__after_atomic_dec(); | 988 | smp_mb__after_atomic_dec(); |
| 995 | } | 989 | } |
| 996 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 990 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 997 | 991 | ||
| 998 | spin_lock(&lu_gp->lu_gp_lock); | 992 | spin_lock(&lu_gp->lu_gp_lock); |
| 999 | atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt); | 993 | atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt); |
| @@ -1268,14 +1262,9 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp) | |||
| 1268 | 1262 | ||
| 1269 | void core_alua_free_lu_gp_mem(struct se_device *dev) | 1263 | void core_alua_free_lu_gp_mem(struct se_device *dev) |
| 1270 | { | 1264 | { |
| 1271 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 1272 | struct t10_alua *alua = &su_dev->t10_alua; | ||
| 1273 | struct t10_alua_lu_gp *lu_gp; | 1265 | struct t10_alua_lu_gp *lu_gp; |
| 1274 | struct t10_alua_lu_gp_member *lu_gp_mem; | 1266 | struct t10_alua_lu_gp_member *lu_gp_mem; |
| 1275 | 1267 | ||
| 1276 | if (alua->alua_type != SPC3_ALUA_EMULATED) | ||
| 1277 | return; | ||
| 1278 | |||
| 1279 | lu_gp_mem = dev->dev_alua_lu_gp_mem; | 1268 | lu_gp_mem = dev->dev_alua_lu_gp_mem; |
| 1280 | if (!lu_gp_mem) | 1269 | if (!lu_gp_mem) |
| 1281 | return; | 1270 | return; |
| @@ -1358,10 +1347,8 @@ void __core_alua_drop_lu_gp_mem( | |||
| 1358 | spin_unlock(&lu_gp->lu_gp_lock); | 1347 | spin_unlock(&lu_gp->lu_gp_lock); |
| 1359 | } | 1348 | } |
| 1360 | 1349 | ||
| 1361 | struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( | 1350 | struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev, |
| 1362 | struct se_subsystem_dev *su_dev, | 1351 | const char *name, int def_group) |
| 1363 | const char *name, | ||
| 1364 | int def_group) | ||
| 1365 | { | 1352 | { |
| 1366 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 1353 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 1367 | 1354 | ||
| @@ -1375,7 +1362,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( | |||
| 1375 | mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); | 1362 | mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); |
| 1376 | spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); | 1363 | spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); |
| 1377 | atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); | 1364 | atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); |
| 1378 | tg_pt_gp->tg_pt_gp_su_dev = su_dev; | 1365 | tg_pt_gp->tg_pt_gp_dev = dev; |
| 1379 | tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN; | 1366 | tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN; |
| 1380 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, | 1367 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, |
| 1381 | ALUA_ACCESS_STATE_ACTIVE_OPTMIZED); | 1368 | ALUA_ACCESS_STATE_ACTIVE_OPTMIZED); |
| @@ -1392,14 +1379,14 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( | |||
| 1392 | tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS; | 1379 | tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS; |
| 1393 | 1380 | ||
| 1394 | if (def_group) { | 1381 | if (def_group) { |
| 1395 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 1382 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 1396 | tg_pt_gp->tg_pt_gp_id = | 1383 | tg_pt_gp->tg_pt_gp_id = |
| 1397 | su_dev->t10_alua.alua_tg_pt_gps_counter++; | 1384 | dev->t10_alua.alua_tg_pt_gps_counter++; |
| 1398 | tg_pt_gp->tg_pt_gp_valid_id = 1; | 1385 | tg_pt_gp->tg_pt_gp_valid_id = 1; |
| 1399 | su_dev->t10_alua.alua_tg_pt_gps_count++; | 1386 | dev->t10_alua.alua_tg_pt_gps_count++; |
| 1400 | list_add_tail(&tg_pt_gp->tg_pt_gp_list, | 1387 | list_add_tail(&tg_pt_gp->tg_pt_gp_list, |
| 1401 | &su_dev->t10_alua.tg_pt_gps_list); | 1388 | &dev->t10_alua.tg_pt_gps_list); |
| 1402 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1389 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1403 | } | 1390 | } |
| 1404 | 1391 | ||
| 1405 | return tg_pt_gp; | 1392 | return tg_pt_gp; |
| @@ -1409,9 +1396,10 @@ int core_alua_set_tg_pt_gp_id( | |||
| 1409 | struct t10_alua_tg_pt_gp *tg_pt_gp, | 1396 | struct t10_alua_tg_pt_gp *tg_pt_gp, |
| 1410 | u16 tg_pt_gp_id) | 1397 | u16 tg_pt_gp_id) |
| 1411 | { | 1398 | { |
| 1412 | struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; | 1399 | struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; |
| 1413 | struct t10_alua_tg_pt_gp *tg_pt_gp_tmp; | 1400 | struct t10_alua_tg_pt_gp *tg_pt_gp_tmp; |
| 1414 | u16 tg_pt_gp_id_tmp; | 1401 | u16 tg_pt_gp_id_tmp; |
| 1402 | |||
| 1415 | /* | 1403 | /* |
| 1416 | * The tg_pt_gp->tg_pt_gp_id may only be set once.. | 1404 | * The tg_pt_gp->tg_pt_gp_id may only be set once.. |
| 1417 | */ | 1405 | */ |
| @@ -1421,19 +1409,19 @@ int core_alua_set_tg_pt_gp_id( | |||
| 1421 | return -EINVAL; | 1409 | return -EINVAL; |
| 1422 | } | 1410 | } |
| 1423 | 1411 | ||
| 1424 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 1412 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 1425 | if (su_dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) { | 1413 | if (dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) { |
| 1426 | pr_err("Maximum ALUA alua_tg_pt_gps_count:" | 1414 | pr_err("Maximum ALUA alua_tg_pt_gps_count:" |
| 1427 | " 0x0000ffff reached\n"); | 1415 | " 0x0000ffff reached\n"); |
| 1428 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1416 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1429 | kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); | 1417 | kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); |
| 1430 | return -ENOSPC; | 1418 | return -ENOSPC; |
| 1431 | } | 1419 | } |
| 1432 | again: | 1420 | again: |
| 1433 | tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id : | 1421 | tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id : |
| 1434 | su_dev->t10_alua.alua_tg_pt_gps_counter++; | 1422 | dev->t10_alua.alua_tg_pt_gps_counter++; |
| 1435 | 1423 | ||
| 1436 | list_for_each_entry(tg_pt_gp_tmp, &su_dev->t10_alua.tg_pt_gps_list, | 1424 | list_for_each_entry(tg_pt_gp_tmp, &dev->t10_alua.tg_pt_gps_list, |
| 1437 | tg_pt_gp_list) { | 1425 | tg_pt_gp_list) { |
| 1438 | if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) { | 1426 | if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) { |
| 1439 | if (!tg_pt_gp_id) | 1427 | if (!tg_pt_gp_id) |
| @@ -1441,7 +1429,7 @@ again: | |||
| 1441 | 1429 | ||
| 1442 | pr_err("ALUA Target Port Group ID: %hu already" | 1430 | pr_err("ALUA Target Port Group ID: %hu already" |
| 1443 | " exists, ignoring request\n", tg_pt_gp_id); | 1431 | " exists, ignoring request\n", tg_pt_gp_id); |
| 1444 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1432 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1445 | return -EINVAL; | 1433 | return -EINVAL; |
| 1446 | } | 1434 | } |
| 1447 | } | 1435 | } |
| @@ -1449,9 +1437,9 @@ again: | |||
| 1449 | tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp; | 1437 | tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp; |
| 1450 | tg_pt_gp->tg_pt_gp_valid_id = 1; | 1438 | tg_pt_gp->tg_pt_gp_valid_id = 1; |
| 1451 | list_add_tail(&tg_pt_gp->tg_pt_gp_list, | 1439 | list_add_tail(&tg_pt_gp->tg_pt_gp_list, |
| 1452 | &su_dev->t10_alua.tg_pt_gps_list); | 1440 | &dev->t10_alua.tg_pt_gps_list); |
| 1453 | su_dev->t10_alua.alua_tg_pt_gps_count++; | 1441 | dev->t10_alua.alua_tg_pt_gps_count++; |
| 1454 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1442 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1455 | 1443 | ||
| 1456 | return 0; | 1444 | return 0; |
| 1457 | } | 1445 | } |
| @@ -1480,8 +1468,9 @@ struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( | |||
| 1480 | void core_alua_free_tg_pt_gp( | 1468 | void core_alua_free_tg_pt_gp( |
| 1481 | struct t10_alua_tg_pt_gp *tg_pt_gp) | 1469 | struct t10_alua_tg_pt_gp *tg_pt_gp) |
| 1482 | { | 1470 | { |
| 1483 | struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; | 1471 | struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; |
| 1484 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; | 1472 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; |
| 1473 | |||
| 1485 | /* | 1474 | /* |
| 1486 | * Once we have reached this point, config_item_put() has already | 1475 | * Once we have reached this point, config_item_put() has already |
| 1487 | * been called from target_core_alua_drop_tg_pt_gp(). | 1476 | * been called from target_core_alua_drop_tg_pt_gp(). |
| @@ -1490,10 +1479,11 @@ void core_alua_free_tg_pt_gp( | |||
| 1490 | * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS | 1479 | * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS |
| 1491 | * can be made while we are releasing struct t10_alua_tg_pt_gp. | 1480 | * can be made while we are releasing struct t10_alua_tg_pt_gp. |
| 1492 | */ | 1481 | */ |
| 1493 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 1482 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 1494 | list_del(&tg_pt_gp->tg_pt_gp_list); | 1483 | list_del(&tg_pt_gp->tg_pt_gp_list); |
| 1495 | su_dev->t10_alua.alua_tg_pt_gps_counter--; | 1484 | dev->t10_alua.alua_tg_pt_gps_counter--; |
| 1496 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1485 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1486 | |||
| 1497 | /* | 1487 | /* |
| 1498 | * Allow a struct t10_alua_tg_pt_gp_member * referenced by | 1488 | * Allow a struct t10_alua_tg_pt_gp_member * referenced by |
| 1499 | * core_alua_get_tg_pt_gp_by_name() in | 1489 | * core_alua_get_tg_pt_gp_by_name() in |
| @@ -1502,6 +1492,7 @@ void core_alua_free_tg_pt_gp( | |||
| 1502 | */ | 1492 | */ |
| 1503 | while (atomic_read(&tg_pt_gp->tg_pt_gp_ref_cnt)) | 1493 | while (atomic_read(&tg_pt_gp->tg_pt_gp_ref_cnt)) |
| 1504 | cpu_relax(); | 1494 | cpu_relax(); |
| 1495 | |||
| 1505 | /* | 1496 | /* |
| 1506 | * Release reference to struct t10_alua_tg_pt_gp from all associated | 1497 | * Release reference to struct t10_alua_tg_pt_gp from all associated |
| 1507 | * struct se_port. | 1498 | * struct se_port. |
| @@ -1525,9 +1516,9 @@ void core_alua_free_tg_pt_gp( | |||
| 1525 | * default_tg_pt_gp. | 1516 | * default_tg_pt_gp. |
| 1526 | */ | 1517 | */ |
| 1527 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 1518 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 1528 | if (tg_pt_gp != su_dev->t10_alua.default_tg_pt_gp) { | 1519 | if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) { |
| 1529 | __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, | 1520 | __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, |
| 1530 | su_dev->t10_alua.default_tg_pt_gp); | 1521 | dev->t10_alua.default_tg_pt_gp); |
| 1531 | } else | 1522 | } else |
| 1532 | tg_pt_gp_mem->tg_pt_gp = NULL; | 1523 | tg_pt_gp_mem->tg_pt_gp = NULL; |
| 1533 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 1524 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| @@ -1541,14 +1532,9 @@ void core_alua_free_tg_pt_gp( | |||
| 1541 | 1532 | ||
| 1542 | void core_alua_free_tg_pt_gp_mem(struct se_port *port) | 1533 | void core_alua_free_tg_pt_gp_mem(struct se_port *port) |
| 1543 | { | 1534 | { |
| 1544 | struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; | ||
| 1545 | struct t10_alua *alua = &su_dev->t10_alua; | ||
| 1546 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 1535 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 1547 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | 1536 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; |
| 1548 | 1537 | ||
| 1549 | if (alua->alua_type != SPC3_ALUA_EMULATED) | ||
| 1550 | return; | ||
| 1551 | |||
| 1552 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | 1538 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; |
| 1553 | if (!tg_pt_gp_mem) | 1539 | if (!tg_pt_gp_mem) |
| 1554 | return; | 1540 | return; |
| @@ -1574,25 +1560,24 @@ void core_alua_free_tg_pt_gp_mem(struct se_port *port) | |||
| 1574 | } | 1560 | } |
| 1575 | 1561 | ||
| 1576 | static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( | 1562 | static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( |
| 1577 | struct se_subsystem_dev *su_dev, | 1563 | struct se_device *dev, const char *name) |
| 1578 | const char *name) | ||
| 1579 | { | 1564 | { |
| 1580 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 1565 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 1581 | struct config_item *ci; | 1566 | struct config_item *ci; |
| 1582 | 1567 | ||
| 1583 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 1568 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 1584 | list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, | 1569 | list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, |
| 1585 | tg_pt_gp_list) { | 1570 | tg_pt_gp_list) { |
| 1586 | if (!tg_pt_gp->tg_pt_gp_valid_id) | 1571 | if (!tg_pt_gp->tg_pt_gp_valid_id) |
| 1587 | continue; | 1572 | continue; |
| 1588 | ci = &tg_pt_gp->tg_pt_gp_group.cg_item; | 1573 | ci = &tg_pt_gp->tg_pt_gp_group.cg_item; |
| 1589 | if (!strcmp(config_item_name(ci), name)) { | 1574 | if (!strcmp(config_item_name(ci), name)) { |
| 1590 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); | 1575 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); |
| 1591 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1576 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1592 | return tg_pt_gp; | 1577 | return tg_pt_gp; |
| 1593 | } | 1578 | } |
| 1594 | } | 1579 | } |
| 1595 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1580 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1596 | 1581 | ||
| 1597 | return NULL; | 1582 | return NULL; |
| 1598 | } | 1583 | } |
| @@ -1600,11 +1585,11 @@ static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( | |||
| 1600 | static void core_alua_put_tg_pt_gp_from_name( | 1585 | static void core_alua_put_tg_pt_gp_from_name( |
| 1601 | struct t10_alua_tg_pt_gp *tg_pt_gp) | 1586 | struct t10_alua_tg_pt_gp *tg_pt_gp) |
| 1602 | { | 1587 | { |
| 1603 | struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; | 1588 | struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; |
| 1604 | 1589 | ||
| 1605 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 1590 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
| 1606 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); | 1591 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); |
| 1607 | spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); | 1592 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
| 1608 | } | 1593 | } |
| 1609 | 1594 | ||
| 1610 | /* | 1595 | /* |
| @@ -1640,16 +1625,11 @@ static void __core_alua_drop_tg_pt_gp_mem( | |||
| 1640 | 1625 | ||
| 1641 | ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) | 1626 | ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) |
| 1642 | { | 1627 | { |
| 1643 | struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; | ||
| 1644 | struct config_item *tg_pt_ci; | 1628 | struct config_item *tg_pt_ci; |
| 1645 | struct t10_alua *alua = &su_dev->t10_alua; | ||
| 1646 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 1629 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 1647 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | 1630 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; |
| 1648 | ssize_t len = 0; | 1631 | ssize_t len = 0; |
| 1649 | 1632 | ||
| 1650 | if (alua->alua_type != SPC3_ALUA_EMULATED) | ||
| 1651 | return len; | ||
| 1652 | |||
| 1653 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | 1633 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; |
| 1654 | if (!tg_pt_gp_mem) | 1634 | if (!tg_pt_gp_mem) |
| 1655 | return len; | 1635 | return len; |
| @@ -1683,7 +1663,7 @@ ssize_t core_alua_store_tg_pt_gp_info( | |||
| 1683 | { | 1663 | { |
| 1684 | struct se_portal_group *tpg; | 1664 | struct se_portal_group *tpg; |
| 1685 | struct se_lun *lun; | 1665 | struct se_lun *lun; |
| 1686 | struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; | 1666 | struct se_device *dev = port->sep_lun->lun_se_dev; |
| 1687 | struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; | 1667 | struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; |
| 1688 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | 1668 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; |
| 1689 | unsigned char buf[TG_PT_GROUP_NAME_BUF]; | 1669 | unsigned char buf[TG_PT_GROUP_NAME_BUF]; |
| @@ -1692,13 +1672,9 @@ ssize_t core_alua_store_tg_pt_gp_info( | |||
| 1692 | tpg = port->sep_tpg; | 1672 | tpg = port->sep_tpg; |
| 1693 | lun = port->sep_lun; | 1673 | lun = port->sep_lun; |
| 1694 | 1674 | ||
| 1695 | if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { | 1675 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; |
| 1696 | pr_warn("SPC3_ALUA_EMULATED not enabled for" | 1676 | if (!tg_pt_gp_mem) |
| 1697 | " %s/tpgt_%hu/%s\n", tpg->se_tpg_tfo->tpg_get_wwn(tpg), | 1677 | return 0; |
| 1698 | tpg->se_tpg_tfo->tpg_get_tag(tpg), | ||
| 1699 | config_item_name(&lun->lun_group.cg_item)); | ||
| 1700 | return -EINVAL; | ||
| 1701 | } | ||
| 1702 | 1678 | ||
| 1703 | if (count > TG_PT_GROUP_NAME_BUF) { | 1679 | if (count > TG_PT_GROUP_NAME_BUF) { |
| 1704 | pr_err("ALUA Target Port Group alias too large!\n"); | 1680 | pr_err("ALUA Target Port Group alias too large!\n"); |
| @@ -1716,18 +1692,11 @@ ssize_t core_alua_store_tg_pt_gp_info( | |||
| 1716 | * struct t10_alua_tg_pt_gp. This reference is released with | 1692 | * struct t10_alua_tg_pt_gp. This reference is released with |
| 1717 | * core_alua_put_tg_pt_gp_from_name() below. | 1693 | * core_alua_put_tg_pt_gp_from_name() below. |
| 1718 | */ | 1694 | */ |
| 1719 | tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(su_dev, | 1695 | tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(dev, |
| 1720 | strstrip(buf)); | 1696 | strstrip(buf)); |
| 1721 | if (!tg_pt_gp_new) | 1697 | if (!tg_pt_gp_new) |
| 1722 | return -ENODEV; | 1698 | return -ENODEV; |
| 1723 | } | 1699 | } |
| 1724 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | ||
| 1725 | if (!tg_pt_gp_mem) { | ||
| 1726 | if (tg_pt_gp_new) | ||
| 1727 | core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new); | ||
| 1728 | pr_err("NULL struct se_port->sep_alua_tg_pt_gp_mem pointer\n"); | ||
| 1729 | return -EINVAL; | ||
| 1730 | } | ||
| 1731 | 1700 | ||
| 1732 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 1701 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 1733 | tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; | 1702 | tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; |
| @@ -1750,7 +1719,7 @@ ssize_t core_alua_store_tg_pt_gp_info( | |||
| 1750 | 1719 | ||
| 1751 | __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); | 1720 | __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); |
| 1752 | __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, | 1721 | __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, |
| 1753 | su_dev->t10_alua.default_tg_pt_gp); | 1722 | dev->t10_alua.default_tg_pt_gp); |
| 1754 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 1723 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 1755 | 1724 | ||
| 1756 | return count; | 1725 | return count; |
| @@ -2054,32 +2023,12 @@ ssize_t core_alua_store_secondary_write_metadata( | |||
| 2054 | return count; | 2023 | return count; |
| 2055 | } | 2024 | } |
| 2056 | 2025 | ||
| 2057 | int core_setup_alua(struct se_device *dev, int force_pt) | 2026 | int core_setup_alua(struct se_device *dev) |
| 2058 | { | 2027 | { |
| 2059 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | 2028 | if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV && |
| 2060 | struct t10_alua *alua = &su_dev->t10_alua; | 2029 | !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { |
| 2061 | struct t10_alua_lu_gp_member *lu_gp_mem; | 2030 | struct t10_alua_lu_gp_member *lu_gp_mem; |
| 2062 | /* | 2031 | |
| 2063 | * If this device is from Target_Core_Mod/pSCSI, use the ALUA logic | ||
| 2064 | * of the Underlying SCSI hardware. In Linux/SCSI terms, this can | ||
| 2065 | * cause a problem because libata and some SATA RAID HBAs appear | ||
| 2066 | * under Linux/SCSI, but emulate SCSI logic themselves. | ||
| 2067 | */ | ||
| 2068 | if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) && | ||
| 2069 | !(dev->se_sub_dev->se_dev_attrib.emulate_alua)) || force_pt) { | ||
| 2070 | alua->alua_type = SPC_ALUA_PASSTHROUGH; | ||
| 2071 | alua->alua_state_check = &core_alua_state_check_nop; | ||
| 2072 | pr_debug("%s: Using SPC_ALUA_PASSTHROUGH, no ALUA" | ||
| 2073 | " emulation\n", dev->transport->name); | ||
| 2074 | return 0; | ||
| 2075 | } | ||
| 2076 | /* | ||
| 2077 | * If SPC-3 or above is reported by real or emulated struct se_device, | ||
| 2078 | * use emulated ALUA. | ||
| 2079 | */ | ||
| 2080 | if (dev->transport->get_device_rev(dev) >= SCSI_3) { | ||
| 2081 | pr_debug("%s: Enabling ALUA Emulation for SPC-3" | ||
| 2082 | " device\n", dev->transport->name); | ||
| 2083 | /* | 2032 | /* |
| 2084 | * Associate this struct se_device with the default ALUA | 2033 | * Associate this struct se_device with the default ALUA |
| 2085 | * LUN Group. | 2034 | * LUN Group. |
| @@ -2088,8 +2037,6 @@ int core_setup_alua(struct se_device *dev, int force_pt) | |||
| 2088 | if (IS_ERR(lu_gp_mem)) | 2037 | if (IS_ERR(lu_gp_mem)) |
| 2089 | return PTR_ERR(lu_gp_mem); | 2038 | return PTR_ERR(lu_gp_mem); |
| 2090 | 2039 | ||
| 2091 | alua->alua_type = SPC3_ALUA_EMULATED; | ||
| 2092 | alua->alua_state_check = &core_alua_state_check; | ||
| 2093 | spin_lock(&lu_gp_mem->lu_gp_mem_lock); | 2040 | spin_lock(&lu_gp_mem->lu_gp_mem_lock); |
| 2094 | __core_alua_attach_lu_gp_mem(lu_gp_mem, | 2041 | __core_alua_attach_lu_gp_mem(lu_gp_mem, |
| 2095 | default_lu_gp); | 2042 | default_lu_gp); |
| @@ -2098,11 +2045,6 @@ int core_setup_alua(struct se_device *dev, int force_pt) | |||
| 2098 | pr_debug("%s: Adding to default ALUA LU Group:" | 2045 | pr_debug("%s: Adding to default ALUA LU Group:" |
| 2099 | " core/alua/lu_gps/default_lu_gp\n", | 2046 | " core/alua/lu_gps/default_lu_gp\n", |
| 2100 | dev->transport->name); | 2047 | dev->transport->name); |
| 2101 | } else { | ||
| 2102 | alua->alua_type = SPC2_ALUA_DISABLED; | ||
| 2103 | alua->alua_state_check = &core_alua_state_check_nop; | ||
| 2104 | pr_debug("%s: Disabling ALUA Emulation for SPC-2" | ||
| 2105 | " device\n", dev->transport->name); | ||
| 2106 | } | 2048 | } |
| 2107 | 2049 | ||
| 2108 | return 0; | 2050 | return 0; |
diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index f920c170d47b..e539c3e7f4ad 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h | |||
| @@ -72,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache; | |||
| 72 | extern struct kmem_cache *t10_alua_tg_pt_gp_cache; | 72 | extern struct kmem_cache *t10_alua_tg_pt_gp_cache; |
| 73 | extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; | 73 | extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; |
| 74 | 74 | ||
| 75 | extern int target_emulate_report_target_port_groups(struct se_cmd *); | 75 | extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *); |
| 76 | extern int target_emulate_set_target_port_groups(struct se_cmd *); | 76 | extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *); |
| 77 | extern int core_alua_check_nonop_delay(struct se_cmd *); | 77 | extern int core_alua_check_nonop_delay(struct se_cmd *); |
| 78 | extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, | 78 | extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, |
| 79 | struct se_device *, struct se_port *, | 79 | struct se_device *, struct se_port *, |
| @@ -91,7 +91,7 @@ extern void __core_alua_drop_lu_gp_mem(struct t10_alua_lu_gp_member *, | |||
| 91 | struct t10_alua_lu_gp *); | 91 | struct t10_alua_lu_gp *); |
| 92 | extern void core_alua_drop_lu_gp_dev(struct se_device *); | 92 | extern void core_alua_drop_lu_gp_dev(struct se_device *); |
| 93 | extern struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( | 93 | extern struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( |
| 94 | struct se_subsystem_dev *, const char *, int); | 94 | struct se_device *, const char *, int); |
| 95 | extern int core_alua_set_tg_pt_gp_id(struct t10_alua_tg_pt_gp *, u16); | 95 | extern int core_alua_set_tg_pt_gp_id(struct t10_alua_tg_pt_gp *, u16); |
| 96 | extern struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( | 96 | extern struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( |
| 97 | struct se_port *); | 97 | struct se_port *); |
| @@ -131,6 +131,7 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, | |||
| 131 | char *); | 131 | char *); |
| 132 | extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, | 132 | extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, |
| 133 | const char *, size_t); | 133 | const char *, size_t); |
| 134 | extern int core_setup_alua(struct se_device *, int); | 134 | extern int core_setup_alua(struct se_device *); |
| 135 | extern sense_reason_t target_alua_state_check(struct se_cmd *cmd); | ||
| 135 | 136 | ||
| 136 | #endif /* TARGET_CORE_ALUA_H */ | 137 | #endif /* TARGET_CORE_ALUA_H */ |
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index c123327499a3..4efb61b8d001 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
| @@ -3,8 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains ConfigFS logic for the Generic Target Engine project. | 4 | * This file contains ConfigFS logic for the Generic Target Engine project. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2008-2011 Rising Tide Systems | 6 | * (c) Copyright 2008-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2008-2011 Linux-iSCSI.org | ||
| 8 | * | 7 | * |
| 9 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 10 | * | 9 | * |
| @@ -565,21 +564,8 @@ static ssize_t target_core_dev_show_attr_##_name( \ | |||
| 565 | struct se_dev_attrib *da, \ | 564 | struct se_dev_attrib *da, \ |
| 566 | char *page) \ | 565 | char *page) \ |
| 567 | { \ | 566 | { \ |
| 568 | struct se_device *dev; \ | 567 | return snprintf(page, PAGE_SIZE, "%u\n", \ |
| 569 | struct se_subsystem_dev *se_dev = da->da_sub_dev; \ | 568 | (u32)da->da_dev->dev_attrib._name); \ |
| 570 | ssize_t rb; \ | ||
| 571 | \ | ||
| 572 | spin_lock(&se_dev->se_dev_lock); \ | ||
| 573 | dev = se_dev->se_dev_ptr; \ | ||
| 574 | if (!dev) { \ | ||
| 575 | spin_unlock(&se_dev->se_dev_lock); \ | ||
| 576 | return -ENODEV; \ | ||
| 577 | } \ | ||
| 578 | rb = snprintf(page, PAGE_SIZE, "%u\n", \ | ||
| 579 | (u32)dev->se_sub_dev->se_dev_attrib._name); \ | ||
| 580 | spin_unlock(&se_dev->se_dev_lock); \ | ||
| 581 | \ | ||
| 582 | return rb; \ | ||
| 583 | } | 569 | } |
| 584 | 570 | ||
| 585 | #define DEF_DEV_ATTRIB_STORE(_name) \ | 571 | #define DEF_DEV_ATTRIB_STORE(_name) \ |
| @@ -588,26 +574,16 @@ static ssize_t target_core_dev_store_attr_##_name( \ | |||
| 588 | const char *page, \ | 574 | const char *page, \ |
| 589 | size_t count) \ | 575 | size_t count) \ |
| 590 | { \ | 576 | { \ |
| 591 | struct se_device *dev; \ | ||
| 592 | struct se_subsystem_dev *se_dev = da->da_sub_dev; \ | ||
| 593 | unsigned long val; \ | 577 | unsigned long val; \ |
| 594 | int ret; \ | 578 | int ret; \ |
| 595 | \ | 579 | \ |
| 596 | spin_lock(&se_dev->se_dev_lock); \ | ||
| 597 | dev = se_dev->se_dev_ptr; \ | ||
| 598 | if (!dev) { \ | ||
| 599 | spin_unlock(&se_dev->se_dev_lock); \ | ||
| 600 | return -ENODEV; \ | ||
| 601 | } \ | ||
| 602 | ret = strict_strtoul(page, 0, &val); \ | 580 | ret = strict_strtoul(page, 0, &val); \ |
| 603 | if (ret < 0) { \ | 581 | if (ret < 0) { \ |
| 604 | spin_unlock(&se_dev->se_dev_lock); \ | ||
| 605 | pr_err("strict_strtoul() failed with" \ | 582 | pr_err("strict_strtoul() failed with" \ |
| 606 | " ret: %d\n", ret); \ | 583 | " ret: %d\n", ret); \ |
| 607 | return -EINVAL; \ | 584 | return -EINVAL; \ |
| 608 | } \ | 585 | } \ |
| 609 | ret = se_dev_set_##_name(dev, (u32)val); \ | 586 | ret = se_dev_set_##_name(da->da_dev, (u32)val); \ |
| 610 | spin_unlock(&se_dev->se_dev_lock); \ | ||
| 611 | \ | 587 | \ |
| 612 | return (!ret) ? count : -EINVAL; \ | 588 | return (!ret) ? count : -EINVAL; \ |
| 613 | } | 589 | } |
| @@ -699,6 +675,9 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR); | |||
| 699 | DEF_DEV_ATTRIB(unmap_granularity_alignment); | 675 | DEF_DEV_ATTRIB(unmap_granularity_alignment); |
| 700 | SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); | 676 | SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); |
| 701 | 677 | ||
| 678 | DEF_DEV_ATTRIB(max_write_same_len); | ||
| 679 | SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR); | ||
| 680 | |||
| 702 | CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); | 681 | CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); |
| 703 | 682 | ||
| 704 | static struct configfs_attribute *target_core_dev_attrib_attrs[] = { | 683 | static struct configfs_attribute *target_core_dev_attrib_attrs[] = { |
| @@ -724,6 +703,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { | |||
| 724 | &target_core_dev_attrib_max_unmap_block_desc_count.attr, | 703 | &target_core_dev_attrib_max_unmap_block_desc_count.attr, |
| 725 | &target_core_dev_attrib_unmap_granularity.attr, | 704 | &target_core_dev_attrib_unmap_granularity.attr, |
| 726 | &target_core_dev_attrib_unmap_granularity_alignment.attr, | 705 | &target_core_dev_attrib_unmap_granularity_alignment.attr, |
| 706 | &target_core_dev_attrib_max_write_same_len.attr, | ||
| 727 | NULL, | 707 | NULL, |
| 728 | }; | 708 | }; |
| 729 | 709 | ||
| @@ -764,13 +744,6 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial( | |||
| 764 | struct t10_wwn *t10_wwn, | 744 | struct t10_wwn *t10_wwn, |
| 765 | char *page) | 745 | char *page) |
| 766 | { | 746 | { |
| 767 | struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; | ||
| 768 | struct se_device *dev; | ||
| 769 | |||
| 770 | dev = se_dev->se_dev_ptr; | ||
| 771 | if (!dev) | ||
| 772 | return -ENODEV; | ||
| 773 | |||
| 774 | return sprintf(page, "T10 VPD Unit Serial Number: %s\n", | 747 | return sprintf(page, "T10 VPD Unit Serial Number: %s\n", |
| 775 | &t10_wwn->unit_serial[0]); | 748 | &t10_wwn->unit_serial[0]); |
| 776 | } | 749 | } |
| @@ -780,8 +753,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( | |||
| 780 | const char *page, | 753 | const char *page, |
| 781 | size_t count) | 754 | size_t count) |
| 782 | { | 755 | { |
| 783 | struct se_subsystem_dev *su_dev = t10_wwn->t10_sub_dev; | 756 | struct se_device *dev = t10_wwn->t10_dev; |
| 784 | struct se_device *dev; | ||
| 785 | unsigned char buf[INQUIRY_VPD_SERIAL_LEN]; | 757 | unsigned char buf[INQUIRY_VPD_SERIAL_LEN]; |
| 786 | 758 | ||
| 787 | /* | 759 | /* |
| @@ -794,7 +766,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( | |||
| 794 | * it is doing 'the right thing' wrt a world wide unique | 766 | * it is doing 'the right thing' wrt a world wide unique |
| 795 | * VPD Unit Serial Number that OS dependent multipath can depend on. | 767 | * VPD Unit Serial Number that OS dependent multipath can depend on. |
| 796 | */ | 768 | */ |
| 797 | if (su_dev->su_dev_flags & SDF_FIRMWARE_VPD_UNIT_SERIAL) { | 769 | if (dev->dev_flags & DF_FIRMWARE_VPD_UNIT_SERIAL) { |
| 798 | pr_err("Underlying SCSI device firmware provided VPD" | 770 | pr_err("Underlying SCSI device firmware provided VPD" |
| 799 | " Unit Serial, ignoring request\n"); | 771 | " Unit Serial, ignoring request\n"); |
| 800 | return -EOPNOTSUPP; | 772 | return -EOPNOTSUPP; |
| @@ -811,15 +783,13 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( | |||
| 811 | * (underneath the initiator side OS dependent multipath code) | 783 | * (underneath the initiator side OS dependent multipath code) |
| 812 | * could cause negative effects. | 784 | * could cause negative effects. |
| 813 | */ | 785 | */ |
| 814 | dev = su_dev->se_dev_ptr; | 786 | if (dev->export_count) { |
| 815 | if (dev) { | 787 | pr_err("Unable to set VPD Unit Serial while" |
| 816 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 788 | " active %d $FABRIC_MOD exports exist\n", |
| 817 | pr_err("Unable to set VPD Unit Serial while" | 789 | dev->export_count); |
| 818 | " active %d $FABRIC_MOD exports exist\n", | 790 | return -EINVAL; |
| 819 | atomic_read(&dev->dev_export_obj.obj_access_count)); | ||
| 820 | return -EINVAL; | ||
| 821 | } | ||
| 822 | } | 791 | } |
| 792 | |||
| 823 | /* | 793 | /* |
| 824 | * This currently assumes ASCII encoding for emulated VPD Unit Serial. | 794 | * This currently assumes ASCII encoding for emulated VPD Unit Serial. |
| 825 | * | 795 | * |
| @@ -828,12 +798,12 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( | |||
| 828 | */ | 798 | */ |
| 829 | memset(buf, 0, INQUIRY_VPD_SERIAL_LEN); | 799 | memset(buf, 0, INQUIRY_VPD_SERIAL_LEN); |
| 830 | snprintf(buf, INQUIRY_VPD_SERIAL_LEN, "%s", page); | 800 | snprintf(buf, INQUIRY_VPD_SERIAL_LEN, "%s", page); |
| 831 | snprintf(su_dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN, | 801 | snprintf(dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN, |
| 832 | "%s", strstrip(buf)); | 802 | "%s", strstrip(buf)); |
| 833 | su_dev->su_dev_flags |= SDF_EMULATED_VPD_UNIT_SERIAL; | 803 | dev->dev_flags |= DF_EMULATED_VPD_UNIT_SERIAL; |
| 834 | 804 | ||
| 835 | pr_debug("Target_Core_ConfigFS: Set emulated VPD Unit Serial:" | 805 | pr_debug("Target_Core_ConfigFS: Set emulated VPD Unit Serial:" |
| 836 | " %s\n", su_dev->t10_wwn.unit_serial); | 806 | " %s\n", dev->t10_wwn.unit_serial); |
| 837 | 807 | ||
| 838 | return count; | 808 | return count; |
| 839 | } | 809 | } |
| @@ -847,16 +817,10 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier( | |||
| 847 | struct t10_wwn *t10_wwn, | 817 | struct t10_wwn *t10_wwn, |
| 848 | char *page) | 818 | char *page) |
| 849 | { | 819 | { |
| 850 | struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; | ||
| 851 | struct se_device *dev; | ||
| 852 | struct t10_vpd *vpd; | 820 | struct t10_vpd *vpd; |
| 853 | unsigned char buf[VPD_TMP_BUF_SIZE]; | 821 | unsigned char buf[VPD_TMP_BUF_SIZE]; |
| 854 | ssize_t len = 0; | 822 | ssize_t len = 0; |
| 855 | 823 | ||
| 856 | dev = se_dev->se_dev_ptr; | ||
| 857 | if (!dev) | ||
| 858 | return -ENODEV; | ||
| 859 | |||
| 860 | memset(buf, 0, VPD_TMP_BUF_SIZE); | 824 | memset(buf, 0, VPD_TMP_BUF_SIZE); |
| 861 | 825 | ||
| 862 | spin_lock(&t10_wwn->t10_vpd_lock); | 826 | spin_lock(&t10_wwn->t10_vpd_lock); |
| @@ -894,16 +858,10 @@ static ssize_t target_core_dev_wwn_show_attr_##_name( \ | |||
| 894 | struct t10_wwn *t10_wwn, \ | 858 | struct t10_wwn *t10_wwn, \ |
| 895 | char *page) \ | 859 | char *page) \ |
| 896 | { \ | 860 | { \ |
| 897 | struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; \ | ||
| 898 | struct se_device *dev; \ | ||
| 899 | struct t10_vpd *vpd; \ | 861 | struct t10_vpd *vpd; \ |
| 900 | unsigned char buf[VPD_TMP_BUF_SIZE]; \ | 862 | unsigned char buf[VPD_TMP_BUF_SIZE]; \ |
| 901 | ssize_t len = 0; \ | 863 | ssize_t len = 0; \ |
| 902 | \ | 864 | \ |
| 903 | dev = se_dev->se_dev_ptr; \ | ||
| 904 | if (!dev) \ | ||
| 905 | return -ENODEV; \ | ||
| 906 | \ | ||
| 907 | spin_lock(&t10_wwn->t10_vpd_lock); \ | 865 | spin_lock(&t10_wwn->t10_vpd_lock); \ |
| 908 | list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) { \ | 866 | list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) { \ |
| 909 | if (vpd->association != _assoc) \ | 867 | if (vpd->association != _assoc) \ |
| @@ -1003,7 +961,7 @@ static struct config_item_type target_core_dev_wwn_cit = { | |||
| 1003 | 961 | ||
| 1004 | /* Start functions for struct config_item_type target_core_dev_pr_cit */ | 962 | /* Start functions for struct config_item_type target_core_dev_pr_cit */ |
| 1005 | 963 | ||
| 1006 | CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_subsystem_dev); | 964 | CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_device); |
| 1007 | #define SE_DEV_PR_ATTR(_name, _mode) \ | 965 | #define SE_DEV_PR_ATTR(_name, _mode) \ |
| 1008 | static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ | 966 | static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ |
| 1009 | __CONFIGFS_EATTR(_name, _mode, \ | 967 | __CONFIGFS_EATTR(_name, _mode, \ |
| @@ -1015,13 +973,8 @@ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ | |||
| 1015 | __CONFIGFS_EATTR_RO(_name, \ | 973 | __CONFIGFS_EATTR_RO(_name, \ |
| 1016 | target_core_dev_pr_show_attr_##_name); | 974 | target_core_dev_pr_show_attr_##_name); |
| 1017 | 975 | ||
| 1018 | /* | 976 | static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev, |
| 1019 | * res_holder | 977 | char *page) |
| 1020 | */ | ||
| 1021 | static ssize_t target_core_dev_pr_show_spc3_res( | ||
| 1022 | struct se_device *dev, | ||
| 1023 | char *page, | ||
| 1024 | ssize_t *len) | ||
| 1025 | { | 978 | { |
| 1026 | struct se_node_acl *se_nacl; | 979 | struct se_node_acl *se_nacl; |
| 1027 | struct t10_pr_registration *pr_reg; | 980 | struct t10_pr_registration *pr_reg; |
| @@ -1030,134 +983,82 @@ static ssize_t target_core_dev_pr_show_spc3_res( | |||
| 1030 | 983 | ||
| 1031 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); | 984 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); |
| 1032 | 985 | ||
| 1033 | spin_lock(&dev->dev_reservation_lock); | ||
| 1034 | pr_reg = dev->dev_pr_res_holder; | 986 | pr_reg = dev->dev_pr_res_holder; |
| 1035 | if (!pr_reg) { | 987 | if (!pr_reg) |
| 1036 | *len += sprintf(page + *len, "No SPC-3 Reservation holder\n"); | 988 | return sprintf(page, "No SPC-3 Reservation holder\n"); |
| 1037 | spin_unlock(&dev->dev_reservation_lock); | 989 | |
| 1038 | return *len; | ||
| 1039 | } | ||
| 1040 | se_nacl = pr_reg->pr_reg_nacl; | 990 | se_nacl = pr_reg->pr_reg_nacl; |
| 1041 | prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], | 991 | prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], |
| 1042 | PR_REG_ISID_ID_LEN); | 992 | PR_REG_ISID_ID_LEN); |
| 1043 | 993 | ||
| 1044 | *len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n", | 994 | return sprintf(page, "SPC-3 Reservation: %s Initiator: %s%s\n", |
| 1045 | se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), | 995 | se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), |
| 1046 | se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); | 996 | se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); |
| 1047 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1048 | |||
| 1049 | return *len; | ||
| 1050 | } | 997 | } |
| 1051 | 998 | ||
| 1052 | static ssize_t target_core_dev_pr_show_spc2_res( | 999 | static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev, |
| 1053 | struct se_device *dev, | 1000 | char *page) |
| 1054 | char *page, | ||
| 1055 | ssize_t *len) | ||
| 1056 | { | 1001 | { |
| 1057 | struct se_node_acl *se_nacl; | 1002 | struct se_node_acl *se_nacl; |
| 1003 | ssize_t len; | ||
| 1058 | 1004 | ||
| 1059 | spin_lock(&dev->dev_reservation_lock); | ||
| 1060 | se_nacl = dev->dev_reserved_node_acl; | 1005 | se_nacl = dev->dev_reserved_node_acl; |
| 1061 | if (!se_nacl) { | 1006 | if (se_nacl) { |
| 1062 | *len += sprintf(page + *len, "No SPC-2 Reservation holder\n"); | 1007 | len = sprintf(page, |
| 1063 | spin_unlock(&dev->dev_reservation_lock); | 1008 | "SPC-2 Reservation: %s Initiator: %s\n", |
| 1064 | return *len; | 1009 | se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), |
| 1010 | se_nacl->initiatorname); | ||
| 1011 | } else { | ||
| 1012 | len = sprintf(page, "No SPC-2 Reservation holder\n"); | ||
| 1065 | } | 1013 | } |
| 1066 | *len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n", | 1014 | return len; |
| 1067 | se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), | ||
| 1068 | se_nacl->initiatorname); | ||
| 1069 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1070 | |||
| 1071 | return *len; | ||
| 1072 | } | 1015 | } |
| 1073 | 1016 | ||
| 1074 | static ssize_t target_core_dev_pr_show_attr_res_holder( | 1017 | static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev, |
| 1075 | struct se_subsystem_dev *su_dev, | 1018 | char *page) |
| 1076 | char *page) | ||
| 1077 | { | 1019 | { |
| 1078 | ssize_t len = 0; | 1020 | int ret; |
| 1079 | 1021 | ||
| 1080 | if (!su_dev->se_dev_ptr) | 1022 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 1081 | return -ENODEV; | 1023 | return sprintf(page, "Passthrough\n"); |
| 1082 | |||
| 1083 | switch (su_dev->t10_pr.res_type) { | ||
| 1084 | case SPC3_PERSISTENT_RESERVATIONS: | ||
| 1085 | target_core_dev_pr_show_spc3_res(su_dev->se_dev_ptr, | ||
| 1086 | page, &len); | ||
| 1087 | break; | ||
| 1088 | case SPC2_RESERVATIONS: | ||
| 1089 | target_core_dev_pr_show_spc2_res(su_dev->se_dev_ptr, | ||
| 1090 | page, &len); | ||
| 1091 | break; | ||
| 1092 | case SPC_PASSTHROUGH: | ||
| 1093 | len += sprintf(page+len, "Passthrough\n"); | ||
| 1094 | break; | ||
| 1095 | default: | ||
| 1096 | len += sprintf(page+len, "Unknown\n"); | ||
| 1097 | break; | ||
| 1098 | } | ||
| 1099 | 1024 | ||
| 1100 | return len; | 1025 | spin_lock(&dev->dev_reservation_lock); |
| 1026 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) | ||
| 1027 | ret = target_core_dev_pr_show_spc2_res(dev, page); | ||
| 1028 | else | ||
| 1029 | ret = target_core_dev_pr_show_spc3_res(dev, page); | ||
| 1030 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1031 | return ret; | ||
| 1101 | } | 1032 | } |
| 1102 | 1033 | ||
| 1103 | SE_DEV_PR_ATTR_RO(res_holder); | 1034 | SE_DEV_PR_ATTR_RO(res_holder); |
| 1104 | 1035 | ||
| 1105 | /* | ||
| 1106 | * res_pr_all_tgt_pts | ||
| 1107 | */ | ||
| 1108 | static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( | 1036 | static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( |
| 1109 | struct se_subsystem_dev *su_dev, | 1037 | struct se_device *dev, char *page) |
| 1110 | char *page) | ||
| 1111 | { | 1038 | { |
| 1112 | struct se_device *dev; | ||
| 1113 | struct t10_pr_registration *pr_reg; | ||
| 1114 | ssize_t len = 0; | 1039 | ssize_t len = 0; |
| 1115 | 1040 | ||
| 1116 | dev = su_dev->se_dev_ptr; | ||
| 1117 | if (!dev) | ||
| 1118 | return -ENODEV; | ||
| 1119 | |||
| 1120 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1121 | return len; | ||
| 1122 | |||
| 1123 | spin_lock(&dev->dev_reservation_lock); | 1041 | spin_lock(&dev->dev_reservation_lock); |
| 1124 | pr_reg = dev->dev_pr_res_holder; | 1042 | if (!dev->dev_pr_res_holder) { |
| 1125 | if (!pr_reg) { | ||
| 1126 | len = sprintf(page, "No SPC-3 Reservation holder\n"); | 1043 | len = sprintf(page, "No SPC-3 Reservation holder\n"); |
| 1127 | spin_unlock(&dev->dev_reservation_lock); | 1044 | } else if (dev->dev_pr_res_holder->pr_reg_all_tg_pt) { |
| 1128 | return len; | ||
| 1129 | } | ||
| 1130 | /* | ||
| 1131 | * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3 | ||
| 1132 | * Basic PERSISTENT RESERVER OUT parameter list, page 290 | ||
| 1133 | */ | ||
| 1134 | if (pr_reg->pr_reg_all_tg_pt) | ||
| 1135 | len = sprintf(page, "SPC-3 Reservation: All Target" | 1045 | len = sprintf(page, "SPC-3 Reservation: All Target" |
| 1136 | " Ports registration\n"); | 1046 | " Ports registration\n"); |
| 1137 | else | 1047 | } else { |
| 1138 | len = sprintf(page, "SPC-3 Reservation: Single" | 1048 | len = sprintf(page, "SPC-3 Reservation: Single" |
| 1139 | " Target Port registration\n"); | 1049 | " Target Port registration\n"); |
| 1140 | spin_unlock(&dev->dev_reservation_lock); | 1050 | } |
| 1141 | 1051 | ||
| 1052 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1142 | return len; | 1053 | return len; |
| 1143 | } | 1054 | } |
| 1144 | 1055 | ||
| 1145 | SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts); | 1056 | SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts); |
| 1146 | 1057 | ||
| 1147 | /* | ||
| 1148 | * res_pr_generation | ||
| 1149 | */ | ||
| 1150 | static ssize_t target_core_dev_pr_show_attr_res_pr_generation( | 1058 | static ssize_t target_core_dev_pr_show_attr_res_pr_generation( |
| 1151 | struct se_subsystem_dev *su_dev, | 1059 | struct se_device *dev, char *page) |
| 1152 | char *page) | ||
| 1153 | { | 1060 | { |
| 1154 | if (!su_dev->se_dev_ptr) | 1061 | return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation); |
| 1155 | return -ENODEV; | ||
| 1156 | |||
| 1157 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1158 | return 0; | ||
| 1159 | |||
| 1160 | return sprintf(page, "0x%08x\n", su_dev->t10_pr.pr_generation); | ||
| 1161 | } | 1062 | } |
| 1162 | 1063 | ||
| 1163 | SE_DEV_PR_ATTR_RO(res_pr_generation); | 1064 | SE_DEV_PR_ATTR_RO(res_pr_generation); |
| @@ -1166,10 +1067,8 @@ SE_DEV_PR_ATTR_RO(res_pr_generation); | |||
| 1166 | * res_pr_holder_tg_port | 1067 | * res_pr_holder_tg_port |
| 1167 | */ | 1068 | */ |
| 1168 | static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( | 1069 | static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( |
| 1169 | struct se_subsystem_dev *su_dev, | 1070 | struct se_device *dev, char *page) |
| 1170 | char *page) | ||
| 1171 | { | 1071 | { |
| 1172 | struct se_device *dev; | ||
| 1173 | struct se_node_acl *se_nacl; | 1072 | struct se_node_acl *se_nacl; |
| 1174 | struct se_lun *lun; | 1073 | struct se_lun *lun; |
| 1175 | struct se_portal_group *se_tpg; | 1074 | struct se_portal_group *se_tpg; |
| @@ -1177,20 +1076,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( | |||
| 1177 | struct target_core_fabric_ops *tfo; | 1076 | struct target_core_fabric_ops *tfo; |
| 1178 | ssize_t len = 0; | 1077 | ssize_t len = 0; |
| 1179 | 1078 | ||
| 1180 | dev = su_dev->se_dev_ptr; | ||
| 1181 | if (!dev) | ||
| 1182 | return -ENODEV; | ||
| 1183 | |||
| 1184 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1185 | return len; | ||
| 1186 | |||
| 1187 | spin_lock(&dev->dev_reservation_lock); | 1079 | spin_lock(&dev->dev_reservation_lock); |
| 1188 | pr_reg = dev->dev_pr_res_holder; | 1080 | pr_reg = dev->dev_pr_res_holder; |
| 1189 | if (!pr_reg) { | 1081 | if (!pr_reg) { |
| 1190 | len = sprintf(page, "No SPC-3 Reservation holder\n"); | 1082 | len = sprintf(page, "No SPC-3 Reservation holder\n"); |
| 1191 | spin_unlock(&dev->dev_reservation_lock); | 1083 | goto out_unlock; |
| 1192 | return len; | ||
| 1193 | } | 1084 | } |
| 1085 | |||
| 1194 | se_nacl = pr_reg->pr_reg_nacl; | 1086 | se_nacl = pr_reg->pr_reg_nacl; |
| 1195 | se_tpg = se_nacl->se_tpg; | 1087 | se_tpg = se_nacl->se_tpg; |
| 1196 | lun = pr_reg->pr_reg_tg_pt_lun; | 1088 | lun = pr_reg->pr_reg_tg_pt_lun; |
| @@ -1204,19 +1096,16 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( | |||
| 1204 | " %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi, | 1096 | " %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi, |
| 1205 | tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg), | 1097 | tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg), |
| 1206 | tfo->get_fabric_name(), lun->unpacked_lun); | 1098 | tfo->get_fabric_name(), lun->unpacked_lun); |
| 1207 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1208 | 1099 | ||
| 1100 | out_unlock: | ||
| 1101 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1209 | return len; | 1102 | return len; |
| 1210 | } | 1103 | } |
| 1211 | 1104 | ||
| 1212 | SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port); | 1105 | SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port); |
| 1213 | 1106 | ||
| 1214 | /* | ||
| 1215 | * res_pr_registered_i_pts | ||
| 1216 | */ | ||
| 1217 | static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( | 1107 | static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( |
| 1218 | struct se_subsystem_dev *su_dev, | 1108 | struct se_device *dev, char *page) |
| 1219 | char *page) | ||
| 1220 | { | 1109 | { |
| 1221 | struct target_core_fabric_ops *tfo; | 1110 | struct target_core_fabric_ops *tfo; |
| 1222 | struct t10_pr_registration *pr_reg; | 1111 | struct t10_pr_registration *pr_reg; |
| @@ -1225,16 +1114,10 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( | |||
| 1225 | ssize_t len = 0; | 1114 | ssize_t len = 0; |
| 1226 | int reg_count = 0, prf_isid; | 1115 | int reg_count = 0, prf_isid; |
| 1227 | 1116 | ||
| 1228 | if (!su_dev->se_dev_ptr) | ||
| 1229 | return -ENODEV; | ||
| 1230 | |||
| 1231 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1232 | return len; | ||
| 1233 | |||
| 1234 | len += sprintf(page+len, "SPC-3 PR Registrations:\n"); | 1117 | len += sprintf(page+len, "SPC-3 PR Registrations:\n"); |
| 1235 | 1118 | ||
| 1236 | spin_lock(&su_dev->t10_pr.registration_lock); | 1119 | spin_lock(&dev->t10_pr.registration_lock); |
| 1237 | list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, | 1120 | list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, |
| 1238 | pr_reg_list) { | 1121 | pr_reg_list) { |
| 1239 | 1122 | ||
| 1240 | memset(buf, 0, 384); | 1123 | memset(buf, 0, 384); |
| @@ -1254,7 +1137,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( | |||
| 1254 | len += sprintf(page+len, "%s", buf); | 1137 | len += sprintf(page+len, "%s", buf); |
| 1255 | reg_count++; | 1138 | reg_count++; |
| 1256 | } | 1139 | } |
| 1257 | spin_unlock(&su_dev->t10_pr.registration_lock); | 1140 | spin_unlock(&dev->t10_pr.registration_lock); |
| 1258 | 1141 | ||
| 1259 | if (!reg_count) | 1142 | if (!reg_count) |
| 1260 | len += sprintf(page+len, "None\n"); | 1143 | len += sprintf(page+len, "None\n"); |
| @@ -1264,88 +1147,48 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( | |||
| 1264 | 1147 | ||
| 1265 | SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts); | 1148 | SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts); |
| 1266 | 1149 | ||
| 1267 | /* | ||
| 1268 | * res_pr_type | ||
| 1269 | */ | ||
| 1270 | static ssize_t target_core_dev_pr_show_attr_res_pr_type( | 1150 | static ssize_t target_core_dev_pr_show_attr_res_pr_type( |
| 1271 | struct se_subsystem_dev *su_dev, | 1151 | struct se_device *dev, char *page) |
| 1272 | char *page) | ||
| 1273 | { | 1152 | { |
| 1274 | struct se_device *dev; | ||
| 1275 | struct t10_pr_registration *pr_reg; | 1153 | struct t10_pr_registration *pr_reg; |
| 1276 | ssize_t len = 0; | 1154 | ssize_t len = 0; |
| 1277 | 1155 | ||
| 1278 | dev = su_dev->se_dev_ptr; | ||
| 1279 | if (!dev) | ||
| 1280 | return -ENODEV; | ||
| 1281 | |||
| 1282 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1283 | return len; | ||
| 1284 | |||
| 1285 | spin_lock(&dev->dev_reservation_lock); | 1156 | spin_lock(&dev->dev_reservation_lock); |
| 1286 | pr_reg = dev->dev_pr_res_holder; | 1157 | pr_reg = dev->dev_pr_res_holder; |
| 1287 | if (!pr_reg) { | 1158 | if (pr_reg) { |
| 1159 | len = sprintf(page, "SPC-3 Reservation Type: %s\n", | ||
| 1160 | core_scsi3_pr_dump_type(pr_reg->pr_res_type)); | ||
| 1161 | } else { | ||
| 1288 | len = sprintf(page, "No SPC-3 Reservation holder\n"); | 1162 | len = sprintf(page, "No SPC-3 Reservation holder\n"); |
| 1289 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1290 | return len; | ||
| 1291 | } | 1163 | } |
| 1292 | len = sprintf(page, "SPC-3 Reservation Type: %s\n", | ||
| 1293 | core_scsi3_pr_dump_type(pr_reg->pr_res_type)); | ||
| 1294 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1295 | 1164 | ||
| 1165 | spin_unlock(&dev->dev_reservation_lock); | ||
| 1296 | return len; | 1166 | return len; |
| 1297 | } | 1167 | } |
| 1298 | 1168 | ||
| 1299 | SE_DEV_PR_ATTR_RO(res_pr_type); | 1169 | SE_DEV_PR_ATTR_RO(res_pr_type); |
| 1300 | 1170 | ||
| 1301 | /* | ||
| 1302 | * res_type | ||
| 1303 | */ | ||
| 1304 | static ssize_t target_core_dev_pr_show_attr_res_type( | 1171 | static ssize_t target_core_dev_pr_show_attr_res_type( |
| 1305 | struct se_subsystem_dev *su_dev, | 1172 | struct se_device *dev, char *page) |
| 1306 | char *page) | ||
| 1307 | { | 1173 | { |
| 1308 | ssize_t len = 0; | 1174 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 1309 | 1175 | return sprintf(page, "SPC_PASSTHROUGH\n"); | |
| 1310 | if (!su_dev->se_dev_ptr) | 1176 | else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) |
| 1311 | return -ENODEV; | 1177 | return sprintf(page, "SPC2_RESERVATIONS\n"); |
| 1312 | 1178 | else | |
| 1313 | switch (su_dev->t10_pr.res_type) { | 1179 | return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); |
| 1314 | case SPC3_PERSISTENT_RESERVATIONS: | ||
| 1315 | len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); | ||
| 1316 | break; | ||
| 1317 | case SPC2_RESERVATIONS: | ||
| 1318 | len = sprintf(page, "SPC2_RESERVATIONS\n"); | ||
| 1319 | break; | ||
| 1320 | case SPC_PASSTHROUGH: | ||
| 1321 | len = sprintf(page, "SPC_PASSTHROUGH\n"); | ||
| 1322 | break; | ||
| 1323 | default: | ||
| 1324 | len = sprintf(page, "UNKNOWN\n"); | ||
| 1325 | break; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | return len; | ||
| 1329 | } | 1180 | } |
| 1330 | 1181 | ||
| 1331 | SE_DEV_PR_ATTR_RO(res_type); | 1182 | SE_DEV_PR_ATTR_RO(res_type); |
| 1332 | 1183 | ||
| 1333 | /* | ||
| 1334 | * res_aptpl_active | ||
| 1335 | */ | ||
| 1336 | |||
| 1337 | static ssize_t target_core_dev_pr_show_attr_res_aptpl_active( | 1184 | static ssize_t target_core_dev_pr_show_attr_res_aptpl_active( |
| 1338 | struct se_subsystem_dev *su_dev, | 1185 | struct se_device *dev, char *page) |
| 1339 | char *page) | ||
| 1340 | { | 1186 | { |
| 1341 | if (!su_dev->se_dev_ptr) | 1187 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 1342 | return -ENODEV; | ||
| 1343 | |||
| 1344 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1345 | return 0; | 1188 | return 0; |
| 1346 | 1189 | ||
| 1347 | return sprintf(page, "APTPL Bit Status: %s\n", | 1190 | return sprintf(page, "APTPL Bit Status: %s\n", |
| 1348 | (su_dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled"); | 1191 | (dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled"); |
| 1349 | } | 1192 | } |
| 1350 | 1193 | ||
| 1351 | SE_DEV_PR_ATTR_RO(res_aptpl_active); | 1194 | SE_DEV_PR_ATTR_RO(res_aptpl_active); |
| @@ -1354,13 +1197,9 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active); | |||
| 1354 | * res_aptpl_metadata | 1197 | * res_aptpl_metadata |
| 1355 | */ | 1198 | */ |
| 1356 | static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata( | 1199 | static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata( |
| 1357 | struct se_subsystem_dev *su_dev, | 1200 | struct se_device *dev, char *page) |
| 1358 | char *page) | ||
| 1359 | { | 1201 | { |
| 1360 | if (!su_dev->se_dev_ptr) | 1202 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 1361 | return -ENODEV; | ||
| 1362 | |||
| 1363 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1364 | return 0; | 1203 | return 0; |
| 1365 | 1204 | ||
| 1366 | return sprintf(page, "Ready to process PR APTPL metadata..\n"); | 1205 | return sprintf(page, "Ready to process PR APTPL metadata..\n"); |
| @@ -1392,11 +1231,10 @@ static match_table_t tokens = { | |||
| 1392 | }; | 1231 | }; |
| 1393 | 1232 | ||
| 1394 | static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | 1233 | static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( |
| 1395 | struct se_subsystem_dev *su_dev, | 1234 | struct se_device *dev, |
| 1396 | const char *page, | 1235 | const char *page, |
| 1397 | size_t count) | 1236 | size_t count) |
| 1398 | { | 1237 | { |
| 1399 | struct se_device *dev; | ||
| 1400 | unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL; | 1238 | unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL; |
| 1401 | unsigned char *t_fabric = NULL, *t_port = NULL; | 1239 | unsigned char *t_fabric = NULL, *t_port = NULL; |
| 1402 | char *orig, *ptr, *arg_p, *opts; | 1240 | char *orig, *ptr, *arg_p, *opts; |
| @@ -1408,14 +1246,12 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
| 1408 | u16 port_rpti = 0, tpgt = 0; | 1246 | u16 port_rpti = 0, tpgt = 0; |
| 1409 | u8 type = 0, scope; | 1247 | u8 type = 0, scope; |
| 1410 | 1248 | ||
| 1411 | dev = su_dev->se_dev_ptr; | 1249 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 1412 | if (!dev) | 1250 | return 0; |
| 1413 | return -ENODEV; | 1251 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) |
| 1414 | |||
| 1415 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | ||
| 1416 | return 0; | 1252 | return 0; |
| 1417 | 1253 | ||
| 1418 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 1254 | if (dev->export_count) { |
| 1419 | pr_debug("Unable to process APTPL metadata while" | 1255 | pr_debug("Unable to process APTPL metadata while" |
| 1420 | " active fabric exports exist\n"); | 1256 | " active fabric exports exist\n"); |
| 1421 | return -EINVAL; | 1257 | return -EINVAL; |
| @@ -1558,7 +1394,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
| 1558 | goto out; | 1394 | goto out; |
| 1559 | } | 1395 | } |
| 1560 | 1396 | ||
| 1561 | ret = core_scsi3_alloc_aptpl_registration(&su_dev->t10_pr, sa_res_key, | 1397 | ret = core_scsi3_alloc_aptpl_registration(&dev->t10_pr, sa_res_key, |
| 1562 | i_port, isid, mapped_lun, t_port, tpgt, target_lun, | 1398 | i_port, isid, mapped_lun, t_port, tpgt, target_lun, |
| 1563 | res_holder, all_tg_pt, type); | 1399 | res_holder, all_tg_pt, type); |
| 1564 | out: | 1400 | out: |
| @@ -1573,7 +1409,7 @@ out: | |||
| 1573 | 1409 | ||
| 1574 | SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR); | 1410 | SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR); |
| 1575 | 1411 | ||
| 1576 | CONFIGFS_EATTR_OPS(target_core_dev_pr, se_subsystem_dev, se_dev_pr_group); | 1412 | CONFIGFS_EATTR_OPS(target_core_dev_pr, se_device, dev_pr_group); |
| 1577 | 1413 | ||
| 1578 | static struct configfs_attribute *target_core_dev_pr_attrs[] = { | 1414 | static struct configfs_attribute *target_core_dev_pr_attrs[] = { |
| 1579 | &target_core_dev_pr_res_holder.attr, | 1415 | &target_core_dev_pr_res_holder.attr, |
| @@ -1605,18 +1441,14 @@ static struct config_item_type target_core_dev_pr_cit = { | |||
| 1605 | 1441 | ||
| 1606 | static ssize_t target_core_show_dev_info(void *p, char *page) | 1442 | static ssize_t target_core_show_dev_info(void *p, char *page) |
| 1607 | { | 1443 | { |
| 1608 | struct se_subsystem_dev *se_dev = p; | 1444 | struct se_device *dev = p; |
| 1609 | struct se_hba *hba = se_dev->se_dev_hba; | 1445 | struct se_subsystem_api *t = dev->transport; |
| 1610 | struct se_subsystem_api *t = hba->transport; | ||
| 1611 | int bl = 0; | 1446 | int bl = 0; |
| 1612 | ssize_t read_bytes = 0; | 1447 | ssize_t read_bytes = 0; |
| 1613 | 1448 | ||
| 1614 | if (!se_dev->se_dev_ptr) | 1449 | transport_dump_dev_state(dev, page, &bl); |
| 1615 | return -ENODEV; | ||
| 1616 | |||
| 1617 | transport_dump_dev_state(se_dev->se_dev_ptr, page, &bl); | ||
| 1618 | read_bytes += bl; | 1450 | read_bytes += bl; |
| 1619 | read_bytes += t->show_configfs_dev_params(hba, se_dev, page+read_bytes); | 1451 | read_bytes += t->show_configfs_dev_params(dev, page+read_bytes); |
| 1620 | return read_bytes; | 1452 | return read_bytes; |
| 1621 | } | 1453 | } |
| 1622 | 1454 | ||
| @@ -1633,17 +1465,10 @@ static ssize_t target_core_store_dev_control( | |||
| 1633 | const char *page, | 1465 | const char *page, |
| 1634 | size_t count) | 1466 | size_t count) |
| 1635 | { | 1467 | { |
| 1636 | struct se_subsystem_dev *se_dev = p; | 1468 | struct se_device *dev = p; |
| 1637 | struct se_hba *hba = se_dev->se_dev_hba; | 1469 | struct se_subsystem_api *t = dev->transport; |
| 1638 | struct se_subsystem_api *t = hba->transport; | ||
| 1639 | 1470 | ||
| 1640 | if (!se_dev->se_dev_su_ptr) { | 1471 | return t->set_configfs_dev_params(dev, page, count); |
| 1641 | pr_err("Unable to locate struct se_subsystem_dev>se" | ||
| 1642 | "_dev_su_ptr\n"); | ||
| 1643 | return -EINVAL; | ||
| 1644 | } | ||
| 1645 | |||
| 1646 | return t->set_configfs_dev_params(hba, se_dev, page, count); | ||
| 1647 | } | 1472 | } |
| 1648 | 1473 | ||
| 1649 | static struct target_core_configfs_attribute target_core_attr_dev_control = { | 1474 | static struct target_core_configfs_attribute target_core_attr_dev_control = { |
| @@ -1656,12 +1481,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_control = { | |||
| 1656 | 1481 | ||
| 1657 | static ssize_t target_core_show_dev_alias(void *p, char *page) | 1482 | static ssize_t target_core_show_dev_alias(void *p, char *page) |
| 1658 | { | 1483 | { |
| 1659 | struct se_subsystem_dev *se_dev = p; | 1484 | struct se_device *dev = p; |
| 1660 | 1485 | ||
| 1661 | if (!(se_dev->su_dev_flags & SDF_USING_ALIAS)) | 1486 | if (!(dev->dev_flags & DF_USING_ALIAS)) |
| 1662 | return 0; | 1487 | return 0; |
| 1663 | 1488 | ||
| 1664 | return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_alias); | 1489 | return snprintf(page, PAGE_SIZE, "%s\n", dev->dev_alias); |
| 1665 | } | 1490 | } |
| 1666 | 1491 | ||
| 1667 | static ssize_t target_core_store_dev_alias( | 1492 | static ssize_t target_core_store_dev_alias( |
| @@ -1669,8 +1494,8 @@ static ssize_t target_core_store_dev_alias( | |||
| 1669 | const char *page, | 1494 | const char *page, |
| 1670 | size_t count) | 1495 | size_t count) |
| 1671 | { | 1496 | { |
| 1672 | struct se_subsystem_dev *se_dev = p; | 1497 | struct se_device *dev = p; |
| 1673 | struct se_hba *hba = se_dev->se_dev_hba; | 1498 | struct se_hba *hba = dev->se_hba; |
| 1674 | ssize_t read_bytes; | 1499 | ssize_t read_bytes; |
| 1675 | 1500 | ||
| 1676 | if (count > (SE_DEV_ALIAS_LEN-1)) { | 1501 | if (count > (SE_DEV_ALIAS_LEN-1)) { |
| @@ -1680,19 +1505,18 @@ static ssize_t target_core_store_dev_alias( | |||
| 1680 | return -EINVAL; | 1505 | return -EINVAL; |
| 1681 | } | 1506 | } |
| 1682 | 1507 | ||
| 1683 | read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN, | 1508 | read_bytes = snprintf(&dev->dev_alias[0], SE_DEV_ALIAS_LEN, "%s", page); |
| 1684 | "%s", page); | ||
| 1685 | if (!read_bytes) | 1509 | if (!read_bytes) |
| 1686 | return -EINVAL; | 1510 | return -EINVAL; |
| 1687 | if (se_dev->se_dev_alias[read_bytes - 1] == '\n') | 1511 | if (dev->dev_alias[read_bytes - 1] == '\n') |
| 1688 | se_dev->se_dev_alias[read_bytes - 1] = '\0'; | 1512 | dev->dev_alias[read_bytes - 1] = '\0'; |
| 1689 | 1513 | ||
| 1690 | se_dev->su_dev_flags |= SDF_USING_ALIAS; | 1514 | dev->dev_flags |= DF_USING_ALIAS; |
| 1691 | 1515 | ||
| 1692 | pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n", | 1516 | pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n", |
| 1693 | config_item_name(&hba->hba_group.cg_item), | 1517 | config_item_name(&hba->hba_group.cg_item), |
| 1694 | config_item_name(&se_dev->se_dev_group.cg_item), | 1518 | config_item_name(&dev->dev_group.cg_item), |
| 1695 | se_dev->se_dev_alias); | 1519 | dev->dev_alias); |
| 1696 | 1520 | ||
| 1697 | return read_bytes; | 1521 | return read_bytes; |
| 1698 | } | 1522 | } |
| @@ -1707,12 +1531,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_alias = { | |||
| 1707 | 1531 | ||
| 1708 | static ssize_t target_core_show_dev_udev_path(void *p, char *page) | 1532 | static ssize_t target_core_show_dev_udev_path(void *p, char *page) |
| 1709 | { | 1533 | { |
| 1710 | struct se_subsystem_dev *se_dev = p; | 1534 | struct se_device *dev = p; |
| 1711 | 1535 | ||
| 1712 | if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) | 1536 | if (!(dev->dev_flags & DF_USING_UDEV_PATH)) |
| 1713 | return 0; | 1537 | return 0; |
| 1714 | 1538 | ||
| 1715 | return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_udev_path); | 1539 | return snprintf(page, PAGE_SIZE, "%s\n", dev->udev_path); |
| 1716 | } | 1540 | } |
| 1717 | 1541 | ||
| 1718 | static ssize_t target_core_store_dev_udev_path( | 1542 | static ssize_t target_core_store_dev_udev_path( |
| @@ -1720,8 +1544,8 @@ static ssize_t target_core_store_dev_udev_path( | |||
| 1720 | const char *page, | 1544 | const char *page, |
| 1721 | size_t count) | 1545 | size_t count) |
| 1722 | { | 1546 | { |
| 1723 | struct se_subsystem_dev *se_dev = p; | 1547 | struct se_device *dev = p; |
| 1724 | struct se_hba *hba = se_dev->se_dev_hba; | 1548 | struct se_hba *hba = dev->se_hba; |
| 1725 | ssize_t read_bytes; | 1549 | ssize_t read_bytes; |
| 1726 | 1550 | ||
| 1727 | if (count > (SE_UDEV_PATH_LEN-1)) { | 1551 | if (count > (SE_UDEV_PATH_LEN-1)) { |
| @@ -1731,19 +1555,19 @@ static ssize_t target_core_store_dev_udev_path( | |||
| 1731 | return -EINVAL; | 1555 | return -EINVAL; |
| 1732 | } | 1556 | } |
| 1733 | 1557 | ||
| 1734 | read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN, | 1558 | read_bytes = snprintf(&dev->udev_path[0], SE_UDEV_PATH_LEN, |
| 1735 | "%s", page); | 1559 | "%s", page); |
| 1736 | if (!read_bytes) | 1560 | if (!read_bytes) |
| 1737 | return -EINVAL; | 1561 | return -EINVAL; |
| 1738 | if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n') | 1562 | if (dev->udev_path[read_bytes - 1] == '\n') |
| 1739 | se_dev->se_dev_udev_path[read_bytes - 1] = '\0'; | 1563 | dev->udev_path[read_bytes - 1] = '\0'; |
| 1740 | 1564 | ||
| 1741 | se_dev->su_dev_flags |= SDF_USING_UDEV_PATH; | 1565 | dev->dev_flags |= DF_USING_UDEV_PATH; |
| 1742 | 1566 | ||
| 1743 | pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n", | 1567 | pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n", |
| 1744 | config_item_name(&hba->hba_group.cg_item), | 1568 | config_item_name(&hba->hba_group.cg_item), |
| 1745 | config_item_name(&se_dev->se_dev_group.cg_item), | 1569 | config_item_name(&dev->dev_group.cg_item), |
| 1746 | se_dev->se_dev_udev_path); | 1570 | dev->udev_path); |
| 1747 | 1571 | ||
| 1748 | return read_bytes; | 1572 | return read_bytes; |
| 1749 | } | 1573 | } |
| @@ -1761,11 +1585,9 @@ static ssize_t target_core_store_dev_enable( | |||
| 1761 | const char *page, | 1585 | const char *page, |
| 1762 | size_t count) | 1586 | size_t count) |
| 1763 | { | 1587 | { |
| 1764 | struct se_subsystem_dev *se_dev = p; | 1588 | struct se_device *dev = p; |
| 1765 | struct se_device *dev; | ||
| 1766 | struct se_hba *hba = se_dev->se_dev_hba; | ||
| 1767 | struct se_subsystem_api *t = hba->transport; | ||
| 1768 | char *ptr; | 1589 | char *ptr; |
| 1590 | int ret; | ||
| 1769 | 1591 | ||
| 1770 | ptr = strstr(page, "1"); | 1592 | ptr = strstr(page, "1"); |
| 1771 | if (!ptr) { | 1593 | if (!ptr) { |
| @@ -1773,25 +1595,10 @@ static ssize_t target_core_store_dev_enable( | |||
| 1773 | " is \"1\"\n"); | 1595 | " is \"1\"\n"); |
| 1774 | return -EINVAL; | 1596 | return -EINVAL; |
| 1775 | } | 1597 | } |
| 1776 | if (se_dev->se_dev_ptr) { | ||
| 1777 | pr_err("se_dev->se_dev_ptr already set for storage" | ||
| 1778 | " object\n"); | ||
| 1779 | return -EEXIST; | ||
| 1780 | } | ||
| 1781 | |||
| 1782 | if (t->check_configfs_dev_params(hba, se_dev) < 0) | ||
| 1783 | return -EINVAL; | ||
| 1784 | |||
| 1785 | dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); | ||
| 1786 | if (IS_ERR(dev)) | ||
| 1787 | return PTR_ERR(dev); | ||
| 1788 | else if (!dev) | ||
| 1789 | return -EINVAL; | ||
| 1790 | |||
| 1791 | se_dev->se_dev_ptr = dev; | ||
| 1792 | pr_debug("Target_Core_ConfigFS: Registered se_dev->se_dev_ptr:" | ||
| 1793 | " %p\n", se_dev->se_dev_ptr); | ||
| 1794 | 1598 | ||
| 1599 | ret = target_configure_device(dev); | ||
| 1600 | if (ret) | ||
| 1601 | return ret; | ||
| 1795 | return count; | 1602 | return count; |
| 1796 | } | 1603 | } |
| 1797 | 1604 | ||
| @@ -1805,26 +1612,15 @@ static struct target_core_configfs_attribute target_core_attr_dev_enable = { | |||
| 1805 | 1612 | ||
| 1806 | static ssize_t target_core_show_alua_lu_gp(void *p, char *page) | 1613 | static ssize_t target_core_show_alua_lu_gp(void *p, char *page) |
| 1807 | { | 1614 | { |
| 1808 | struct se_device *dev; | 1615 | struct se_device *dev = p; |
| 1809 | struct se_subsystem_dev *su_dev = p; | ||
| 1810 | struct config_item *lu_ci; | 1616 | struct config_item *lu_ci; |
| 1811 | struct t10_alua_lu_gp *lu_gp; | 1617 | struct t10_alua_lu_gp *lu_gp; |
| 1812 | struct t10_alua_lu_gp_member *lu_gp_mem; | 1618 | struct t10_alua_lu_gp_member *lu_gp_mem; |
| 1813 | ssize_t len = 0; | 1619 | ssize_t len = 0; |
| 1814 | 1620 | ||
| 1815 | dev = su_dev->se_dev_ptr; | ||
| 1816 | if (!dev) | ||
| 1817 | return -ENODEV; | ||
| 1818 | |||
| 1819 | if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) | ||
| 1820 | return len; | ||
| 1821 | |||
| 1822 | lu_gp_mem = dev->dev_alua_lu_gp_mem; | 1621 | lu_gp_mem = dev->dev_alua_lu_gp_mem; |
| 1823 | if (!lu_gp_mem) { | 1622 | if (!lu_gp_mem) |
| 1824 | pr_err("NULL struct se_device->dev_alua_lu_gp_mem" | 1623 | return 0; |
| 1825 | " pointer\n"); | ||
| 1826 | return -EINVAL; | ||
| 1827 | } | ||
| 1828 | 1624 | ||
| 1829 | spin_lock(&lu_gp_mem->lu_gp_mem_lock); | 1625 | spin_lock(&lu_gp_mem->lu_gp_mem_lock); |
| 1830 | lu_gp = lu_gp_mem->lu_gp; | 1626 | lu_gp = lu_gp_mem->lu_gp; |
| @@ -1843,24 +1639,17 @@ static ssize_t target_core_store_alua_lu_gp( | |||
| 1843 | const char *page, | 1639 | const char *page, |
| 1844 | size_t count) | 1640 | size_t count) |
| 1845 | { | 1641 | { |
| 1846 | struct se_device *dev; | 1642 | struct se_device *dev = p; |
| 1847 | struct se_subsystem_dev *su_dev = p; | 1643 | struct se_hba *hba = dev->se_hba; |
| 1848 | struct se_hba *hba = su_dev->se_dev_hba; | ||
| 1849 | struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL; | 1644 | struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL; |
| 1850 | struct t10_alua_lu_gp_member *lu_gp_mem; | 1645 | struct t10_alua_lu_gp_member *lu_gp_mem; |
| 1851 | unsigned char buf[LU_GROUP_NAME_BUF]; | 1646 | unsigned char buf[LU_GROUP_NAME_BUF]; |
| 1852 | int move = 0; | 1647 | int move = 0; |
| 1853 | 1648 | ||
| 1854 | dev = su_dev->se_dev_ptr; | 1649 | lu_gp_mem = dev->dev_alua_lu_gp_mem; |
| 1855 | if (!dev) | 1650 | if (!lu_gp_mem) |
| 1856 | return -ENODEV; | 1651 | return 0; |
| 1857 | 1652 | ||
| 1858 | if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { | ||
| 1859 | pr_warn("SPC3_ALUA_EMULATED not enabled for %s/%s\n", | ||
| 1860 | config_item_name(&hba->hba_group.cg_item), | ||
| 1861 | config_item_name(&su_dev->se_dev_group.cg_item)); | ||
| 1862 | return -EINVAL; | ||
| 1863 | } | ||
| 1864 | if (count > LU_GROUP_NAME_BUF) { | 1653 | if (count > LU_GROUP_NAME_BUF) { |
| 1865 | pr_err("ALUA LU Group Alias too large!\n"); | 1654 | pr_err("ALUA LU Group Alias too large!\n"); |
| 1866 | return -EINVAL; | 1655 | return -EINVAL; |
| @@ -1881,14 +1670,6 @@ static ssize_t target_core_store_alua_lu_gp( | |||
| 1881 | if (!lu_gp_new) | 1670 | if (!lu_gp_new) |
| 1882 | return -ENODEV; | 1671 | return -ENODEV; |
| 1883 | } | 1672 | } |
| 1884 | lu_gp_mem = dev->dev_alua_lu_gp_mem; | ||
| 1885 | if (!lu_gp_mem) { | ||
| 1886 | if (lu_gp_new) | ||
| 1887 | core_alua_put_lu_gp_from_name(lu_gp_new); | ||
| 1888 | pr_err("NULL struct se_device->dev_alua_lu_gp_mem" | ||
| 1889 | " pointer\n"); | ||
| 1890 | return -EINVAL; | ||
| 1891 | } | ||
| 1892 | 1673 | ||
| 1893 | spin_lock(&lu_gp_mem->lu_gp_mem_lock); | 1674 | spin_lock(&lu_gp_mem->lu_gp_mem_lock); |
| 1894 | lu_gp = lu_gp_mem->lu_gp; | 1675 | lu_gp = lu_gp_mem->lu_gp; |
| @@ -1902,7 +1683,7 @@ static ssize_t target_core_store_alua_lu_gp( | |||
| 1902 | " from ALUA LU Group: core/alua/lu_gps/%s, ID:" | 1683 | " from ALUA LU Group: core/alua/lu_gps/%s, ID:" |
| 1903 | " %hu\n", | 1684 | " %hu\n", |
| 1904 | config_item_name(&hba->hba_group.cg_item), | 1685 | config_item_name(&hba->hba_group.cg_item), |
| 1905 | config_item_name(&su_dev->se_dev_group.cg_item), | 1686 | config_item_name(&dev->dev_group.cg_item), |
| 1906 | config_item_name(&lu_gp->lu_gp_group.cg_item), | 1687 | config_item_name(&lu_gp->lu_gp_group.cg_item), |
| 1907 | lu_gp->lu_gp_id); | 1688 | lu_gp->lu_gp_id); |
| 1908 | 1689 | ||
| @@ -1927,7 +1708,7 @@ static ssize_t target_core_store_alua_lu_gp( | |||
| 1927 | " core/alua/lu_gps/%s, ID: %hu\n", | 1708 | " core/alua/lu_gps/%s, ID: %hu\n", |
| 1928 | (move) ? "Moving" : "Adding", | 1709 | (move) ? "Moving" : "Adding", |
| 1929 | config_item_name(&hba->hba_group.cg_item), | 1710 | config_item_name(&hba->hba_group.cg_item), |
| 1930 | config_item_name(&su_dev->se_dev_group.cg_item), | 1711 | config_item_name(&dev->dev_group.cg_item), |
| 1931 | config_item_name(&lu_gp_new->lu_gp_group.cg_item), | 1712 | config_item_name(&lu_gp_new->lu_gp_group.cg_item), |
| 1932 | lu_gp_new->lu_gp_id); | 1713 | lu_gp_new->lu_gp_id); |
| 1933 | 1714 | ||
| @@ -1955,69 +1736,44 @@ static struct configfs_attribute *lio_core_dev_attrs[] = { | |||
| 1955 | 1736 | ||
| 1956 | static void target_core_dev_release(struct config_item *item) | 1737 | static void target_core_dev_release(struct config_item *item) |
| 1957 | { | 1738 | { |
| 1958 | struct se_subsystem_dev *se_dev = container_of(to_config_group(item), | 1739 | struct config_group *dev_cg = to_config_group(item); |
| 1959 | struct se_subsystem_dev, se_dev_group); | 1740 | struct se_device *dev = |
| 1960 | struct se_hba *hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); | 1741 | container_of(dev_cg, struct se_device, dev_group); |
| 1961 | struct se_subsystem_api *t = hba->transport; | ||
| 1962 | struct config_group *dev_cg = &se_dev->se_dev_group; | ||
| 1963 | 1742 | ||
| 1964 | kfree(dev_cg->default_groups); | 1743 | kfree(dev_cg->default_groups); |
| 1965 | /* | 1744 | target_free_device(dev); |
| 1966 | * This pointer will set when the storage is enabled with: | ||
| 1967 | *`echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable` | ||
| 1968 | */ | ||
| 1969 | if (se_dev->se_dev_ptr) { | ||
| 1970 | pr_debug("Target_Core_ConfigFS: Calling se_free_" | ||
| 1971 | "virtual_device() for se_dev_ptr: %p\n", | ||
| 1972 | se_dev->se_dev_ptr); | ||
| 1973 | |||
| 1974 | se_free_virtual_device(se_dev->se_dev_ptr, hba); | ||
| 1975 | } else { | ||
| 1976 | /* | ||
| 1977 | * Release struct se_subsystem_dev->se_dev_su_ptr.. | ||
| 1978 | */ | ||
| 1979 | pr_debug("Target_Core_ConfigFS: Calling t->free_" | ||
| 1980 | "device() for se_dev_su_ptr: %p\n", | ||
| 1981 | se_dev->se_dev_su_ptr); | ||
| 1982 | |||
| 1983 | t->free_device(se_dev->se_dev_su_ptr); | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | pr_debug("Target_Core_ConfigFS: Deallocating se_subsystem" | ||
| 1987 | "_dev_t: %p\n", se_dev); | ||
| 1988 | kfree(se_dev); | ||
| 1989 | } | 1745 | } |
| 1990 | 1746 | ||
| 1991 | static ssize_t target_core_dev_show(struct config_item *item, | 1747 | static ssize_t target_core_dev_show(struct config_item *item, |
| 1992 | struct configfs_attribute *attr, | 1748 | struct configfs_attribute *attr, |
| 1993 | char *page) | 1749 | char *page) |
| 1994 | { | 1750 | { |
| 1995 | struct se_subsystem_dev *se_dev = container_of( | 1751 | struct config_group *dev_cg = to_config_group(item); |
| 1996 | to_config_group(item), struct se_subsystem_dev, | 1752 | struct se_device *dev = |
| 1997 | se_dev_group); | 1753 | container_of(dev_cg, struct se_device, dev_group); |
| 1998 | struct target_core_configfs_attribute *tc_attr = container_of( | 1754 | struct target_core_configfs_attribute *tc_attr = container_of( |
| 1999 | attr, struct target_core_configfs_attribute, attr); | 1755 | attr, struct target_core_configfs_attribute, attr); |
| 2000 | 1756 | ||
| 2001 | if (!tc_attr->show) | 1757 | if (!tc_attr->show) |
| 2002 | return -EINVAL; | 1758 | return -EINVAL; |
| 2003 | 1759 | ||
| 2004 | return tc_attr->show(se_dev, page); | 1760 | return tc_attr->show(dev, page); |
| 2005 | } | 1761 | } |
| 2006 | 1762 | ||
| 2007 | static ssize_t target_core_dev_store(struct config_item *item, | 1763 | static ssize_t target_core_dev_store(struct config_item *item, |
| 2008 | struct configfs_attribute *attr, | 1764 | struct configfs_attribute *attr, |
| 2009 | const char *page, size_t count) | 1765 | const char *page, size_t count) |
| 2010 | { | 1766 | { |
| 2011 | struct se_subsystem_dev *se_dev = container_of( | 1767 | struct config_group *dev_cg = to_config_group(item); |
| 2012 | to_config_group(item), struct se_subsystem_dev, | 1768 | struct se_device *dev = |
| 2013 | se_dev_group); | 1769 | container_of(dev_cg, struct se_device, dev_group); |
| 2014 | struct target_core_configfs_attribute *tc_attr = container_of( | 1770 | struct target_core_configfs_attribute *tc_attr = container_of( |
| 2015 | attr, struct target_core_configfs_attribute, attr); | 1771 | attr, struct target_core_configfs_attribute, attr); |
| 2016 | 1772 | ||
| 2017 | if (!tc_attr->store) | 1773 | if (!tc_attr->store) |
| 2018 | return -EINVAL; | 1774 | return -EINVAL; |
| 2019 | 1775 | ||
| 2020 | return tc_attr->store(se_dev, page, count); | 1776 | return tc_attr->store(dev, page, count); |
| 2021 | } | 1777 | } |
| 2022 | 1778 | ||
| 2023 | static struct configfs_item_operations target_core_dev_item_ops = { | 1779 | static struct configfs_item_operations target_core_dev_item_ops = { |
| @@ -2107,7 +1863,6 @@ static ssize_t target_core_alua_lu_gp_show_attr_members( | |||
| 2107 | { | 1863 | { |
| 2108 | struct se_device *dev; | 1864 | struct se_device *dev; |
| 2109 | struct se_hba *hba; | 1865 | struct se_hba *hba; |
| 2110 | struct se_subsystem_dev *su_dev; | ||
| 2111 | struct t10_alua_lu_gp_member *lu_gp_mem; | 1866 | struct t10_alua_lu_gp_member *lu_gp_mem; |
| 2112 | ssize_t len = 0, cur_len; | 1867 | ssize_t len = 0, cur_len; |
| 2113 | unsigned char buf[LU_GROUP_NAME_BUF]; | 1868 | unsigned char buf[LU_GROUP_NAME_BUF]; |
| @@ -2117,12 +1872,11 @@ static ssize_t target_core_alua_lu_gp_show_attr_members( | |||
| 2117 | spin_lock(&lu_gp->lu_gp_lock); | 1872 | spin_lock(&lu_gp->lu_gp_lock); |
| 2118 | list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { | 1873 | list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { |
| 2119 | dev = lu_gp_mem->lu_gp_mem_dev; | 1874 | dev = lu_gp_mem->lu_gp_mem_dev; |
| 2120 | su_dev = dev->se_sub_dev; | 1875 | hba = dev->se_hba; |
| 2121 | hba = su_dev->se_dev_hba; | ||
| 2122 | 1876 | ||
| 2123 | cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n", | 1877 | cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n", |
| 2124 | config_item_name(&hba->hba_group.cg_item), | 1878 | config_item_name(&hba->hba_group.cg_item), |
| 2125 | config_item_name(&su_dev->se_dev_group.cg_item)); | 1879 | config_item_name(&dev->dev_group.cg_item)); |
| 2126 | cur_len++; /* Extra byte for NULL terminator */ | 1880 | cur_len++; /* Extra byte for NULL terminator */ |
| 2127 | 1881 | ||
| 2128 | if ((cur_len + len) > PAGE_SIZE) { | 1882 | if ((cur_len + len) > PAGE_SIZE) { |
| @@ -2260,7 +2014,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state( | |||
| 2260 | const char *page, | 2014 | const char *page, |
| 2261 | size_t count) | 2015 | size_t count) |
| 2262 | { | 2016 | { |
| 2263 | struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; | 2017 | struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; |
| 2264 | unsigned long tmp; | 2018 | unsigned long tmp; |
| 2265 | int new_state, ret; | 2019 | int new_state, ret; |
| 2266 | 2020 | ||
| @@ -2284,7 +2038,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state( | |||
| 2284 | return -EINVAL; | 2038 | return -EINVAL; |
| 2285 | } | 2039 | } |
| 2286 | 2040 | ||
| 2287 | ret = core_alua_do_port_transition(tg_pt_gp, su_dev->se_dev_ptr, | 2041 | ret = core_alua_do_port_transition(tg_pt_gp, dev, |
| 2288 | NULL, NULL, new_state, 0); | 2042 | NULL, NULL, new_state, 0); |
| 2289 | return (!ret) ? count : -EINVAL; | 2043 | return (!ret) ? count : -EINVAL; |
| 2290 | } | 2044 | } |
| @@ -2620,11 +2374,10 @@ static struct config_group *target_core_alua_create_tg_pt_gp( | |||
| 2620 | struct t10_alua *alua = container_of(group, struct t10_alua, | 2374 | struct t10_alua *alua = container_of(group, struct t10_alua, |
| 2621 | alua_tg_pt_gps_group); | 2375 | alua_tg_pt_gps_group); |
| 2622 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 2376 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 2623 | struct se_subsystem_dev *su_dev = alua->t10_sub_dev; | ||
| 2624 | struct config_group *alua_tg_pt_gp_cg = NULL; | 2377 | struct config_group *alua_tg_pt_gp_cg = NULL; |
| 2625 | struct config_item *alua_tg_pt_gp_ci = NULL; | 2378 | struct config_item *alua_tg_pt_gp_ci = NULL; |
| 2626 | 2379 | ||
| 2627 | tg_pt_gp = core_alua_allocate_tg_pt_gp(su_dev, name, 0); | 2380 | tg_pt_gp = core_alua_allocate_tg_pt_gp(alua->t10_dev, name, 0); |
| 2628 | if (!tg_pt_gp) | 2381 | if (!tg_pt_gp) |
| 2629 | return NULL; | 2382 | return NULL; |
| 2630 | 2383 | ||
| @@ -2721,10 +2474,10 @@ static struct config_group *target_core_make_subdev( | |||
| 2721 | const char *name) | 2474 | const char *name) |
| 2722 | { | 2475 | { |
| 2723 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 2476 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 2724 | struct se_subsystem_dev *se_dev; | ||
| 2725 | struct se_subsystem_api *t; | 2477 | struct se_subsystem_api *t; |
| 2726 | struct config_item *hba_ci = &group->cg_item; | 2478 | struct config_item *hba_ci = &group->cg_item; |
| 2727 | struct se_hba *hba = item_to_hba(hba_ci); | 2479 | struct se_hba *hba = item_to_hba(hba_ci); |
| 2480 | struct se_device *dev; | ||
| 2728 | struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; | 2481 | struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; |
| 2729 | struct config_group *dev_stat_grp = NULL; | 2482 | struct config_group *dev_stat_grp = NULL; |
| 2730 | int errno = -ENOMEM, ret; | 2483 | int errno = -ENOMEM, ret; |
| @@ -2737,120 +2490,80 @@ static struct config_group *target_core_make_subdev( | |||
| 2737 | */ | 2490 | */ |
| 2738 | t = hba->transport; | 2491 | t = hba->transport; |
| 2739 | 2492 | ||
| 2740 | se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL); | 2493 | dev = target_alloc_device(hba, name); |
| 2741 | if (!se_dev) { | 2494 | if (!dev) |
| 2742 | pr_err("Unable to allocate memory for" | 2495 | goto out_unlock; |
| 2743 | " struct se_subsystem_dev\n"); | 2496 | |
| 2744 | goto unlock; | 2497 | dev_cg = &dev->dev_group; |
| 2745 | } | 2498 | |
| 2746 | INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); | 2499 | dev_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6, |
| 2747 | spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); | ||
| 2748 | INIT_LIST_HEAD(&se_dev->t10_pr.registration_list); | ||
| 2749 | INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list); | ||
| 2750 | spin_lock_init(&se_dev->t10_pr.registration_lock); | ||
| 2751 | spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock); | ||
| 2752 | INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list); | ||
| 2753 | spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock); | ||
| 2754 | spin_lock_init(&se_dev->se_dev_lock); | ||
| 2755 | se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; | ||
| 2756 | se_dev->t10_wwn.t10_sub_dev = se_dev; | ||
| 2757 | se_dev->t10_alua.t10_sub_dev = se_dev; | ||
| 2758 | se_dev->se_dev_attrib.da_sub_dev = se_dev; | ||
| 2759 | |||
| 2760 | se_dev->se_dev_hba = hba; | ||
| 2761 | dev_cg = &se_dev->se_dev_group; | ||
| 2762 | |||
| 2763 | dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, | ||
| 2764 | GFP_KERNEL); | 2500 | GFP_KERNEL); |
| 2765 | if (!dev_cg->default_groups) | 2501 | if (!dev_cg->default_groups) |
| 2766 | goto out; | 2502 | goto out_free_device; |
| 2767 | /* | ||
| 2768 | * Set se_dev_su_ptr from struct se_subsystem_api returned void ptr | ||
| 2769 | * for ->allocate_virtdevice() | ||
| 2770 | * | ||
| 2771 | * se_dev->se_dev_ptr will be set after ->create_virtdev() | ||
| 2772 | * has been called successfully in the next level up in the | ||
| 2773 | * configfs tree for device object's struct config_group. | ||
| 2774 | */ | ||
| 2775 | se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, name); | ||
| 2776 | if (!se_dev->se_dev_su_ptr) { | ||
| 2777 | pr_err("Unable to locate subsystem dependent pointer" | ||
| 2778 | " from allocate_virtdevice()\n"); | ||
| 2779 | goto out; | ||
| 2780 | } | ||
| 2781 | 2503 | ||
| 2782 | config_group_init_type_name(&se_dev->se_dev_group, name, | 2504 | config_group_init_type_name(dev_cg, name, &target_core_dev_cit); |
| 2783 | &target_core_dev_cit); | 2505 | config_group_init_type_name(&dev->dev_attrib.da_group, "attrib", |
| 2784 | config_group_init_type_name(&se_dev->se_dev_attrib.da_group, "attrib", | ||
| 2785 | &target_core_dev_attrib_cit); | 2506 | &target_core_dev_attrib_cit); |
| 2786 | config_group_init_type_name(&se_dev->se_dev_pr_group, "pr", | 2507 | config_group_init_type_name(&dev->dev_pr_group, "pr", |
| 2787 | &target_core_dev_pr_cit); | 2508 | &target_core_dev_pr_cit); |
| 2788 | config_group_init_type_name(&se_dev->t10_wwn.t10_wwn_group, "wwn", | 2509 | config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn", |
| 2789 | &target_core_dev_wwn_cit); | 2510 | &target_core_dev_wwn_cit); |
| 2790 | config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, | 2511 | config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group, |
| 2791 | "alua", &target_core_alua_tg_pt_gps_cit); | 2512 | "alua", &target_core_alua_tg_pt_gps_cit); |
| 2792 | config_group_init_type_name(&se_dev->dev_stat_grps.stat_group, | 2513 | config_group_init_type_name(&dev->dev_stat_grps.stat_group, |
| 2793 | "statistics", &target_core_stat_cit); | 2514 | "statistics", &target_core_stat_cit); |
| 2794 | 2515 | ||
| 2795 | dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; | 2516 | dev_cg->default_groups[0] = &dev->dev_attrib.da_group; |
| 2796 | dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; | 2517 | dev_cg->default_groups[1] = &dev->dev_pr_group; |
| 2797 | dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; | 2518 | dev_cg->default_groups[2] = &dev->t10_wwn.t10_wwn_group; |
| 2798 | dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; | 2519 | dev_cg->default_groups[3] = &dev->t10_alua.alua_tg_pt_gps_group; |
| 2799 | dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group; | 2520 | dev_cg->default_groups[4] = &dev->dev_stat_grps.stat_group; |
| 2800 | dev_cg->default_groups[5] = NULL; | 2521 | dev_cg->default_groups[5] = NULL; |
| 2801 | /* | 2522 | /* |
| 2802 | * Add core/$HBA/$DEV/alua/default_tg_pt_gp | 2523 | * Add core/$HBA/$DEV/alua/default_tg_pt_gp |
| 2803 | */ | 2524 | */ |
| 2804 | tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); | 2525 | tg_pt_gp = core_alua_allocate_tg_pt_gp(dev, "default_tg_pt_gp", 1); |
| 2805 | if (!tg_pt_gp) | 2526 | if (!tg_pt_gp) |
| 2806 | goto out; | 2527 | goto out_free_dev_cg_default_groups; |
| 2528 | dev->t10_alua.default_tg_pt_gp = tg_pt_gp; | ||
| 2807 | 2529 | ||
| 2808 | tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group; | 2530 | tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; |
| 2809 | tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 2531 | tg_pt_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
| 2810 | GFP_KERNEL); | 2532 | GFP_KERNEL); |
| 2811 | if (!tg_pt_gp_cg->default_groups) { | 2533 | if (!tg_pt_gp_cg->default_groups) { |
| 2812 | pr_err("Unable to allocate tg_pt_gp_cg->" | 2534 | pr_err("Unable to allocate tg_pt_gp_cg->" |
| 2813 | "default_groups\n"); | 2535 | "default_groups\n"); |
| 2814 | goto out; | 2536 | goto out_free_tg_pt_gp; |
| 2815 | } | 2537 | } |
| 2816 | 2538 | ||
| 2817 | config_group_init_type_name(&tg_pt_gp->tg_pt_gp_group, | 2539 | config_group_init_type_name(&tg_pt_gp->tg_pt_gp_group, |
| 2818 | "default_tg_pt_gp", &target_core_alua_tg_pt_gp_cit); | 2540 | "default_tg_pt_gp", &target_core_alua_tg_pt_gp_cit); |
| 2819 | tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; | 2541 | tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; |
| 2820 | tg_pt_gp_cg->default_groups[1] = NULL; | 2542 | tg_pt_gp_cg->default_groups[1] = NULL; |
| 2821 | se_dev->t10_alua.default_tg_pt_gp = tg_pt_gp; | ||
| 2822 | /* | 2543 | /* |
| 2823 | * Add core/$HBA/$DEV/statistics/ default groups | 2544 | * Add core/$HBA/$DEV/statistics/ default groups |
| 2824 | */ | 2545 | */ |
| 2825 | dev_stat_grp = &se_dev->dev_stat_grps.stat_group; | 2546 | dev_stat_grp = &dev->dev_stat_grps.stat_group; |
| 2826 | dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, | 2547 | dev_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 4, |
| 2827 | GFP_KERNEL); | 2548 | GFP_KERNEL); |
| 2828 | if (!dev_stat_grp->default_groups) { | 2549 | if (!dev_stat_grp->default_groups) { |
| 2829 | pr_err("Unable to allocate dev_stat_grp->default_groups\n"); | 2550 | pr_err("Unable to allocate dev_stat_grp->default_groups\n"); |
| 2830 | goto out; | 2551 | goto out_free_tg_pt_gp_cg_default_groups; |
| 2831 | } | 2552 | } |
| 2832 | target_stat_setup_dev_default_groups(se_dev); | 2553 | target_stat_setup_dev_default_groups(dev); |
| 2833 | |||
| 2834 | pr_debug("Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" | ||
| 2835 | " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); | ||
| 2836 | 2554 | ||
| 2837 | mutex_unlock(&hba->hba_access_mutex); | 2555 | mutex_unlock(&hba->hba_access_mutex); |
| 2838 | return &se_dev->se_dev_group; | 2556 | return dev_cg; |
| 2839 | out: | 2557 | |
| 2840 | if (se_dev->t10_alua.default_tg_pt_gp) { | 2558 | out_free_tg_pt_gp_cg_default_groups: |
| 2841 | core_alua_free_tg_pt_gp(se_dev->t10_alua.default_tg_pt_gp); | 2559 | kfree(tg_pt_gp_cg->default_groups); |
| 2842 | se_dev->t10_alua.default_tg_pt_gp = NULL; | 2560 | out_free_tg_pt_gp: |
| 2843 | } | 2561 | core_alua_free_tg_pt_gp(tg_pt_gp); |
| 2844 | if (dev_stat_grp) | 2562 | out_free_dev_cg_default_groups: |
| 2845 | kfree(dev_stat_grp->default_groups); | 2563 | kfree(dev_cg->default_groups); |
| 2846 | if (tg_pt_gp_cg) | 2564 | out_free_device: |
| 2847 | kfree(tg_pt_gp_cg->default_groups); | 2565 | target_free_device(dev); |
| 2848 | if (dev_cg) | 2566 | out_unlock: |
| 2849 | kfree(dev_cg->default_groups); | ||
| 2850 | if (se_dev->se_dev_su_ptr) | ||
| 2851 | t->free_device(se_dev->se_dev_su_ptr); | ||
| 2852 | kfree(se_dev); | ||
| 2853 | unlock: | ||
| 2854 | mutex_unlock(&hba->hba_access_mutex); | 2567 | mutex_unlock(&hba->hba_access_mutex); |
| 2855 | return ERR_PTR(errno); | 2568 | return ERR_PTR(errno); |
| 2856 | } | 2569 | } |
| @@ -2859,18 +2572,19 @@ static void target_core_drop_subdev( | |||
| 2859 | struct config_group *group, | 2572 | struct config_group *group, |
| 2860 | struct config_item *item) | 2573 | struct config_item *item) |
| 2861 | { | 2574 | { |
| 2862 | struct se_subsystem_dev *se_dev = container_of(to_config_group(item), | 2575 | struct config_group *dev_cg = to_config_group(item); |
| 2863 | struct se_subsystem_dev, se_dev_group); | 2576 | struct se_device *dev = |
| 2577 | container_of(dev_cg, struct se_device, dev_group); | ||
| 2864 | struct se_hba *hba; | 2578 | struct se_hba *hba; |
| 2865 | struct config_item *df_item; | 2579 | struct config_item *df_item; |
| 2866 | struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp; | 2580 | struct config_group *tg_pt_gp_cg, *dev_stat_grp; |
| 2867 | int i; | 2581 | int i; |
| 2868 | 2582 | ||
| 2869 | hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); | 2583 | hba = item_to_hba(&dev->se_hba->hba_group.cg_item); |
| 2870 | 2584 | ||
| 2871 | mutex_lock(&hba->hba_access_mutex); | 2585 | mutex_lock(&hba->hba_access_mutex); |
| 2872 | 2586 | ||
| 2873 | dev_stat_grp = &se_dev->dev_stat_grps.stat_group; | 2587 | dev_stat_grp = &dev->dev_stat_grps.stat_group; |
| 2874 | for (i = 0; dev_stat_grp->default_groups[i]; i++) { | 2588 | for (i = 0; dev_stat_grp->default_groups[i]; i++) { |
| 2875 | df_item = &dev_stat_grp->default_groups[i]->cg_item; | 2589 | df_item = &dev_stat_grp->default_groups[i]->cg_item; |
| 2876 | dev_stat_grp->default_groups[i] = NULL; | 2590 | dev_stat_grp->default_groups[i] = NULL; |
| @@ -2878,7 +2592,7 @@ static void target_core_drop_subdev( | |||
| 2878 | } | 2592 | } |
| 2879 | kfree(dev_stat_grp->default_groups); | 2593 | kfree(dev_stat_grp->default_groups); |
| 2880 | 2594 | ||
| 2881 | tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group; | 2595 | tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; |
| 2882 | for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { | 2596 | for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { |
| 2883 | df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; | 2597 | df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; |
| 2884 | tg_pt_gp_cg->default_groups[i] = NULL; | 2598 | tg_pt_gp_cg->default_groups[i] = NULL; |
| @@ -2889,17 +2603,15 @@ static void target_core_drop_subdev( | |||
| 2889 | * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp | 2603 | * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp |
| 2890 | * directly from target_core_alua_tg_pt_gp_release(). | 2604 | * directly from target_core_alua_tg_pt_gp_release(). |
| 2891 | */ | 2605 | */ |
| 2892 | se_dev->t10_alua.default_tg_pt_gp = NULL; | 2606 | dev->t10_alua.default_tg_pt_gp = NULL; |
| 2893 | 2607 | ||
| 2894 | dev_cg = &se_dev->se_dev_group; | ||
| 2895 | for (i = 0; dev_cg->default_groups[i]; i++) { | 2608 | for (i = 0; dev_cg->default_groups[i]; i++) { |
| 2896 | df_item = &dev_cg->default_groups[i]->cg_item; | 2609 | df_item = &dev_cg->default_groups[i]->cg_item; |
| 2897 | dev_cg->default_groups[i] = NULL; | 2610 | dev_cg->default_groups[i] = NULL; |
| 2898 | config_item_put(df_item); | 2611 | config_item_put(df_item); |
| 2899 | } | 2612 | } |
| 2900 | /* | 2613 | /* |
| 2901 | * The releasing of se_dev and associated se_dev->se_dev_ptr is done | 2614 | * se_dev is released from target_core_dev_item_ops->release() |
| 2902 | * from target_core_dev_item_ops->release() ->target_core_dev_release(). | ||
| 2903 | */ | 2615 | */ |
| 2904 | config_item_put(item); | 2616 | config_item_put(item); |
| 2905 | mutex_unlock(&hba->hba_access_mutex); | 2617 | mutex_unlock(&hba->hba_access_mutex); |
| @@ -2962,13 +2674,10 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba, | |||
| 2962 | return -EINVAL; | 2674 | return -EINVAL; |
| 2963 | } | 2675 | } |
| 2964 | 2676 | ||
| 2965 | spin_lock(&hba->device_lock); | 2677 | if (hba->dev_count) { |
| 2966 | if (!list_empty(&hba->hba_dev_list)) { | ||
| 2967 | pr_err("Unable to set hba_mode with active devices\n"); | 2678 | pr_err("Unable to set hba_mode with active devices\n"); |
| 2968 | spin_unlock(&hba->device_lock); | ||
| 2969 | return -EINVAL; | 2679 | return -EINVAL; |
| 2970 | } | 2680 | } |
| 2971 | spin_unlock(&hba->device_lock); | ||
| 2972 | 2681 | ||
| 2973 | ret = transport->pmode_enable_hba(hba, mode_flag); | 2682 | ret = transport->pmode_enable_hba(hba, mode_flag); |
| 2974 | if (ret < 0) | 2683 | if (ret < 0) |
| @@ -3120,7 +2829,7 @@ static int __init target_core_init_configfs(void) | |||
| 3120 | * and ALUA Logical Unit Group and Target Port Group infrastructure. | 2829 | * and ALUA Logical Unit Group and Target Port Group infrastructure. |
| 3121 | */ | 2830 | */ |
| 3122 | target_cg = &subsys->su_group; | 2831 | target_cg = &subsys->su_group; |
| 3123 | target_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 2832 | target_cg->default_groups = kmalloc(sizeof(struct config_group) * 2, |
| 3124 | GFP_KERNEL); | 2833 | GFP_KERNEL); |
| 3125 | if (!target_cg->default_groups) { | 2834 | if (!target_cg->default_groups) { |
| 3126 | pr_err("Unable to allocate target_cg->default_groups\n"); | 2835 | pr_err("Unable to allocate target_cg->default_groups\n"); |
| @@ -3136,7 +2845,7 @@ static int __init target_core_init_configfs(void) | |||
| 3136 | * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/ | 2845 | * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/ |
| 3137 | */ | 2846 | */ |
| 3138 | hba_cg = &target_core_hbagroup; | 2847 | hba_cg = &target_core_hbagroup; |
| 3139 | hba_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 2848 | hba_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
| 3140 | GFP_KERNEL); | 2849 | GFP_KERNEL); |
| 3141 | if (!hba_cg->default_groups) { | 2850 | if (!hba_cg->default_groups) { |
| 3142 | pr_err("Unable to allocate hba_cg->default_groups\n"); | 2851 | pr_err("Unable to allocate hba_cg->default_groups\n"); |
| @@ -3152,7 +2861,7 @@ static int __init target_core_init_configfs(void) | |||
| 3152 | * groups under /sys/kernel/config/target/core/alua/ | 2861 | * groups under /sys/kernel/config/target/core/alua/ |
| 3153 | */ | 2862 | */ |
| 3154 | alua_cg = &alua_group; | 2863 | alua_cg = &alua_group; |
| 3155 | alua_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 2864 | alua_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
| 3156 | GFP_KERNEL); | 2865 | GFP_KERNEL); |
| 3157 | if (!alua_cg->default_groups) { | 2866 | if (!alua_cg->default_groups) { |
| 3158 | pr_err("Unable to allocate alua_cg->default_groups\n"); | 2867 | pr_err("Unable to allocate alua_cg->default_groups\n"); |
| @@ -3174,7 +2883,7 @@ static int __init target_core_init_configfs(void) | |||
| 3174 | } | 2883 | } |
| 3175 | 2884 | ||
| 3176 | lu_gp_cg = &alua_lu_gps_group; | 2885 | lu_gp_cg = &alua_lu_gps_group; |
| 3177 | lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 2886 | lu_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
| 3178 | GFP_KERNEL); | 2887 | GFP_KERNEL); |
| 3179 | if (!lu_gp_cg->default_groups) { | 2888 | if (!lu_gp_cg->default_groups) { |
| 3180 | pr_err("Unable to allocate lu_gp_cg->default_groups\n"); | 2889 | pr_err("Unable to allocate lu_gp_cg->default_groups\n"); |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 9abef9f8eb76..e2695101bb99 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
| @@ -4,10 +4,7 @@ | |||
| 4 | * This file contains the TCM Virtual Device and Disk Transport | 4 | * This file contains the TCM Virtual Device and Disk Transport |
| 5 | * agnostic related functions. | 5 | * agnostic related functions. |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. | 7 | * (c) Copyright 2003-2012 RisingTide Systems LLC. |
| 8 | * Copyright (c) 2005-2006 SBE, Inc. All Rights Reserved. | ||
| 9 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 10 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 11 | * | 8 | * |
| 12 | * Nicholas A. Bellinger <nab@kernel.org> | 9 | * Nicholas A. Bellinger <nab@kernel.org> |
| 13 | * | 10 | * |
| @@ -50,26 +47,20 @@ | |||
| 50 | #include "target_core_pr.h" | 47 | #include "target_core_pr.h" |
| 51 | #include "target_core_ua.h" | 48 | #include "target_core_ua.h" |
| 52 | 49 | ||
| 53 | static void se_dev_start(struct se_device *dev); | ||
| 54 | static void se_dev_stop(struct se_device *dev); | ||
| 55 | |||
| 56 | static struct se_hba *lun0_hba; | 50 | static struct se_hba *lun0_hba; |
| 57 | static struct se_subsystem_dev *lun0_su_dev; | ||
| 58 | /* not static, needed by tpg.c */ | 51 | /* not static, needed by tpg.c */ |
| 59 | struct se_device *g_lun0_dev; | 52 | struct se_device *g_lun0_dev; |
| 60 | 53 | ||
| 61 | int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) | 54 | sense_reason_t |
| 55 | transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) | ||
| 62 | { | 56 | { |
| 63 | struct se_lun *se_lun = NULL; | 57 | struct se_lun *se_lun = NULL; |
| 64 | struct se_session *se_sess = se_cmd->se_sess; | 58 | struct se_session *se_sess = se_cmd->se_sess; |
| 65 | struct se_device *dev; | 59 | struct se_device *dev; |
| 66 | unsigned long flags; | 60 | unsigned long flags; |
| 67 | 61 | ||
| 68 | if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { | 62 | if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) |
| 69 | se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; | 63 | return TCM_NON_EXISTENT_LUN; |
| 70 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 71 | return -ENODEV; | ||
| 72 | } | ||
| 73 | 64 | ||
| 74 | spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); | 65 | spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); |
| 75 | se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; | 66 | se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; |
| @@ -81,14 +72,12 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) | |||
| 81 | 72 | ||
| 82 | if ((se_cmd->data_direction == DMA_TO_DEVICE) && | 73 | if ((se_cmd->data_direction == DMA_TO_DEVICE) && |
| 83 | (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) { | 74 | (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) { |
| 84 | se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; | ||
| 85 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 86 | pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" | 75 | pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" |
| 87 | " Access for 0x%08x\n", | 76 | " Access for 0x%08x\n", |
| 88 | se_cmd->se_tfo->get_fabric_name(), | 77 | se_cmd->se_tfo->get_fabric_name(), |
| 89 | unpacked_lun); | 78 | unpacked_lun); |
| 90 | spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); | 79 | spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); |
| 91 | return -EACCES; | 80 | return TCM_WRITE_PROTECTED; |
| 92 | } | 81 | } |
| 93 | 82 | ||
| 94 | if (se_cmd->data_direction == DMA_TO_DEVICE) | 83 | if (se_cmd->data_direction == DMA_TO_DEVICE) |
| @@ -113,38 +102,24 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) | |||
| 113 | * MappedLUN=0 exists for this Initiator Port. | 102 | * MappedLUN=0 exists for this Initiator Port. |
| 114 | */ | 103 | */ |
| 115 | if (unpacked_lun != 0) { | 104 | if (unpacked_lun != 0) { |
| 116 | se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; | ||
| 117 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 118 | pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN" | 105 | pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN" |
| 119 | " Access for 0x%08x\n", | 106 | " Access for 0x%08x\n", |
| 120 | se_cmd->se_tfo->get_fabric_name(), | 107 | se_cmd->se_tfo->get_fabric_name(), |
| 121 | unpacked_lun); | 108 | unpacked_lun); |
| 122 | return -ENODEV; | 109 | return TCM_NON_EXISTENT_LUN; |
| 123 | } | 110 | } |
| 124 | /* | 111 | /* |
| 125 | * Force WRITE PROTECT for virtual LUN 0 | 112 | * Force WRITE PROTECT for virtual LUN 0 |
| 126 | */ | 113 | */ |
| 127 | if ((se_cmd->data_direction != DMA_FROM_DEVICE) && | 114 | if ((se_cmd->data_direction != DMA_FROM_DEVICE) && |
| 128 | (se_cmd->data_direction != DMA_NONE)) { | 115 | (se_cmd->data_direction != DMA_NONE)) |
| 129 | se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; | 116 | return TCM_WRITE_PROTECTED; |
| 130 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 131 | return -EACCES; | ||
| 132 | } | ||
| 133 | 117 | ||
| 134 | se_lun = &se_sess->se_tpg->tpg_virt_lun0; | 118 | se_lun = &se_sess->se_tpg->tpg_virt_lun0; |
| 135 | se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0; | 119 | se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0; |
| 136 | se_cmd->orig_fe_lun = 0; | 120 | se_cmd->orig_fe_lun = 0; |
| 137 | se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; | 121 | se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; |
| 138 | } | 122 | } |
| 139 | /* | ||
| 140 | * Determine if the struct se_lun is online. | ||
| 141 | * FIXME: Check for LUN_RESET + UNIT Attention | ||
| 142 | */ | ||
| 143 | if (se_dev_check_online(se_lun->lun_se_dev) != 0) { | ||
| 144 | se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; | ||
| 145 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 146 | return -ENODEV; | ||
| 147 | } | ||
| 148 | 123 | ||
| 149 | /* Directly associate cmd with se_dev */ | 124 | /* Directly associate cmd with se_dev */ |
| 150 | se_cmd->se_dev = se_lun->lun_se_dev; | 125 | se_cmd->se_dev = se_lun->lun_se_dev; |
| @@ -175,11 +150,8 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) | |||
| 175 | struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; | 150 | struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; |
| 176 | unsigned long flags; | 151 | unsigned long flags; |
| 177 | 152 | ||
| 178 | if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { | 153 | if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) |
| 179 | se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; | ||
| 180 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 181 | return -ENODEV; | 154 | return -ENODEV; |
| 182 | } | ||
| 183 | 155 | ||
| 184 | spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); | 156 | spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); |
| 185 | se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; | 157 | se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; |
| @@ -199,15 +171,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) | |||
| 199 | " Access for 0x%08x\n", | 171 | " Access for 0x%08x\n", |
| 200 | se_cmd->se_tfo->get_fabric_name(), | 172 | se_cmd->se_tfo->get_fabric_name(), |
| 201 | unpacked_lun); | 173 | unpacked_lun); |
| 202 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 203 | return -ENODEV; | ||
| 204 | } | ||
| 205 | /* | ||
| 206 | * Determine if the struct se_lun is online. | ||
| 207 | * FIXME: Check for LUN_RESET + UNIT Attention | ||
| 208 | */ | ||
| 209 | if (se_dev_check_online(se_lun->lun_se_dev) != 0) { | ||
| 210 | se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 211 | return -ENODEV; | 174 | return -ENODEV; |
| 212 | } | 175 | } |
| 213 | 176 | ||
| @@ -565,7 +528,6 @@ static void core_export_port( | |||
| 565 | struct se_port *port, | 528 | struct se_port *port, |
| 566 | struct se_lun *lun) | 529 | struct se_lun *lun) |
| 567 | { | 530 | { |
| 568 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 569 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem = NULL; | 531 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem = NULL; |
| 570 | 532 | ||
| 571 | spin_lock(&dev->se_port_lock); | 533 | spin_lock(&dev->se_port_lock); |
| @@ -578,7 +540,8 @@ static void core_export_port( | |||
| 578 | list_add_tail(&port->sep_list, &dev->dev_sep_list); | 540 | list_add_tail(&port->sep_list, &dev->dev_sep_list); |
| 579 | spin_unlock(&dev->se_port_lock); | 541 | spin_unlock(&dev->se_port_lock); |
| 580 | 542 | ||
| 581 | if (su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { | 543 | if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV && |
| 544 | !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { | ||
| 582 | tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port); | 545 | tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port); |
| 583 | if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) { | 546 | if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) { |
| 584 | pr_err("Unable to allocate t10_alua_tg_pt" | 547 | pr_err("Unable to allocate t10_alua_tg_pt" |
| @@ -587,7 +550,7 @@ static void core_export_port( | |||
| 587 | } | 550 | } |
| 588 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 551 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 589 | __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, | 552 | __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, |
| 590 | su_dev->t10_alua.default_tg_pt_gp); | 553 | dev->t10_alua.default_tg_pt_gp); |
| 591 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 554 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 592 | pr_debug("%s/%s: Adding to default ALUA Target Port" | 555 | pr_debug("%s/%s: Adding to default ALUA Target Port" |
| 593 | " Group: alua/default_tg_pt_gp\n", | 556 | " Group: alua/default_tg_pt_gp\n", |
| @@ -625,6 +588,7 @@ int core_dev_export( | |||
| 625 | struct se_portal_group *tpg, | 588 | struct se_portal_group *tpg, |
| 626 | struct se_lun *lun) | 589 | struct se_lun *lun) |
| 627 | { | 590 | { |
| 591 | struct se_hba *hba = dev->se_hba; | ||
| 628 | struct se_port *port; | 592 | struct se_port *port; |
| 629 | 593 | ||
| 630 | port = core_alloc_port(dev); | 594 | port = core_alloc_port(dev); |
| @@ -632,9 +596,11 @@ int core_dev_export( | |||
| 632 | return PTR_ERR(port); | 596 | return PTR_ERR(port); |
| 633 | 597 | ||
| 634 | lun->lun_se_dev = dev; | 598 | lun->lun_se_dev = dev; |
| 635 | se_dev_start(dev); | ||
| 636 | 599 | ||
| 637 | atomic_inc(&dev->dev_export_obj.obj_access_count); | 600 | spin_lock(&hba->device_lock); |
| 601 | dev->export_count++; | ||
| 602 | spin_unlock(&hba->device_lock); | ||
| 603 | |||
| 638 | core_export_port(dev, tpg, port, lun); | 604 | core_export_port(dev, tpg, port, lun); |
| 639 | return 0; | 605 | return 0; |
| 640 | } | 606 | } |
| @@ -644,6 +610,7 @@ void core_dev_unexport( | |||
| 644 | struct se_portal_group *tpg, | 610 | struct se_portal_group *tpg, |
| 645 | struct se_lun *lun) | 611 | struct se_lun *lun) |
| 646 | { | 612 | { |
| 613 | struct se_hba *hba = dev->se_hba; | ||
| 647 | struct se_port *port = lun->lun_sep; | 614 | struct se_port *port = lun->lun_sep; |
| 648 | 615 | ||
| 649 | spin_lock(&lun->lun_sep_lock); | 616 | spin_lock(&lun->lun_sep_lock); |
| @@ -654,198 +621,27 @@ void core_dev_unexport( | |||
| 654 | spin_unlock(&lun->lun_sep_lock); | 621 | spin_unlock(&lun->lun_sep_lock); |
| 655 | 622 | ||
| 656 | spin_lock(&dev->se_port_lock); | 623 | spin_lock(&dev->se_port_lock); |
| 657 | atomic_dec(&dev->dev_export_obj.obj_access_count); | ||
| 658 | core_release_port(dev, port); | 624 | core_release_port(dev, port); |
| 659 | spin_unlock(&dev->se_port_lock); | 625 | spin_unlock(&dev->se_port_lock); |
| 660 | 626 | ||
| 661 | se_dev_stop(dev); | ||
| 662 | lun->lun_se_dev = NULL; | ||
| 663 | } | ||
| 664 | |||
| 665 | int target_report_luns(struct se_cmd *se_cmd) | ||
| 666 | { | ||
| 667 | struct se_dev_entry *deve; | ||
| 668 | struct se_session *se_sess = se_cmd->se_sess; | ||
| 669 | unsigned char *buf; | ||
| 670 | u32 lun_count = 0, offset = 8, i; | ||
| 671 | |||
| 672 | if (se_cmd->data_length < 16) { | ||
| 673 | pr_warn("REPORT LUNS allocation length %u too small\n", | ||
| 674 | se_cmd->data_length); | ||
| 675 | se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 676 | return -EINVAL; | ||
| 677 | } | ||
| 678 | |||
| 679 | buf = transport_kmap_data_sg(se_cmd); | ||
| 680 | if (!buf) | ||
| 681 | return -ENOMEM; | ||
| 682 | |||
| 683 | /* | ||
| 684 | * If no struct se_session pointer is present, this struct se_cmd is | ||
| 685 | * coming via a target_core_mod PASSTHROUGH op, and not through | ||
| 686 | * a $FABRIC_MOD. In that case, report LUN=0 only. | ||
| 687 | */ | ||
| 688 | if (!se_sess) { | ||
| 689 | int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); | ||
| 690 | lun_count = 1; | ||
| 691 | goto done; | ||
| 692 | } | ||
| 693 | |||
| 694 | spin_lock_irq(&se_sess->se_node_acl->device_list_lock); | ||
| 695 | for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { | ||
| 696 | deve = se_sess->se_node_acl->device_list[i]; | ||
| 697 | if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) | ||
| 698 | continue; | ||
| 699 | /* | ||
| 700 | * We determine the correct LUN LIST LENGTH even once we | ||
| 701 | * have reached the initial allocation length. | ||
| 702 | * See SPC2-R20 7.19. | ||
| 703 | */ | ||
| 704 | lun_count++; | ||
| 705 | if ((offset + 8) > se_cmd->data_length) | ||
| 706 | continue; | ||
| 707 | |||
| 708 | int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); | ||
| 709 | offset += 8; | ||
| 710 | } | ||
| 711 | spin_unlock_irq(&se_sess->se_node_acl->device_list_lock); | ||
| 712 | |||
| 713 | /* | ||
| 714 | * See SPC3 r07, page 159. | ||
| 715 | */ | ||
| 716 | done: | ||
| 717 | lun_count *= 8; | ||
| 718 | buf[0] = ((lun_count >> 24) & 0xff); | ||
| 719 | buf[1] = ((lun_count >> 16) & 0xff); | ||
| 720 | buf[2] = ((lun_count >> 8) & 0xff); | ||
| 721 | buf[3] = (lun_count & 0xff); | ||
| 722 | transport_kunmap_data_sg(se_cmd); | ||
| 723 | |||
| 724 | target_complete_cmd(se_cmd, GOOD); | ||
| 725 | return 0; | ||
| 726 | } | ||
| 727 | |||
| 728 | /* se_release_device_for_hba(): | ||
| 729 | * | ||
| 730 | * | ||
| 731 | */ | ||
| 732 | void se_release_device_for_hba(struct se_device *dev) | ||
| 733 | { | ||
| 734 | struct se_hba *hba = dev->se_hba; | ||
| 735 | |||
| 736 | if ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) || | ||
| 737 | (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED) || | ||
| 738 | (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN) || | ||
| 739 | (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_ACTIVATED) || | ||
| 740 | (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_DEACTIVATED)) | ||
| 741 | se_dev_stop(dev); | ||
| 742 | |||
| 743 | if (dev->dev_ptr) { | ||
| 744 | destroy_workqueue(dev->tmr_wq); | ||
| 745 | if (dev->transport->free_device) | ||
| 746 | dev->transport->free_device(dev->dev_ptr); | ||
| 747 | } | ||
| 748 | |||
| 749 | spin_lock(&hba->device_lock); | 627 | spin_lock(&hba->device_lock); |
| 750 | list_del(&dev->dev_list); | 628 | dev->export_count--; |
| 751 | hba->dev_count--; | ||
| 752 | spin_unlock(&hba->device_lock); | 629 | spin_unlock(&hba->device_lock); |
| 753 | 630 | ||
| 754 | core_scsi3_free_all_registrations(dev); | 631 | lun->lun_se_dev = NULL; |
| 755 | se_release_vpd_for_dev(dev); | ||
| 756 | |||
| 757 | kfree(dev); | ||
| 758 | } | 632 | } |
| 759 | 633 | ||
| 760 | void se_release_vpd_for_dev(struct se_device *dev) | 634 | static void se_release_vpd_for_dev(struct se_device *dev) |
| 761 | { | 635 | { |
| 762 | struct t10_vpd *vpd, *vpd_tmp; | 636 | struct t10_vpd *vpd, *vpd_tmp; |
| 763 | 637 | ||
| 764 | spin_lock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock); | 638 | spin_lock(&dev->t10_wwn.t10_vpd_lock); |
| 765 | list_for_each_entry_safe(vpd, vpd_tmp, | 639 | list_for_each_entry_safe(vpd, vpd_tmp, |
| 766 | &dev->se_sub_dev->t10_wwn.t10_vpd_list, vpd_list) { | 640 | &dev->t10_wwn.t10_vpd_list, vpd_list) { |
| 767 | list_del(&vpd->vpd_list); | 641 | list_del(&vpd->vpd_list); |
| 768 | kfree(vpd); | 642 | kfree(vpd); |
| 769 | } | 643 | } |
| 770 | spin_unlock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock); | 644 | spin_unlock(&dev->t10_wwn.t10_vpd_lock); |
| 771 | } | ||
| 772 | |||
| 773 | /* se_free_virtual_device(): | ||
| 774 | * | ||
| 775 | * Used for IBLOCK, RAMDISK, and FILEIO Transport Drivers. | ||
| 776 | */ | ||
| 777 | int se_free_virtual_device(struct se_device *dev, struct se_hba *hba) | ||
| 778 | { | ||
| 779 | if (!list_empty(&dev->dev_sep_list)) | ||
| 780 | dump_stack(); | ||
| 781 | |||
| 782 | core_alua_free_lu_gp_mem(dev); | ||
| 783 | se_release_device_for_hba(dev); | ||
| 784 | |||
| 785 | return 0; | ||
| 786 | } | ||
| 787 | |||
| 788 | static void se_dev_start(struct se_device *dev) | ||
| 789 | { | ||
| 790 | struct se_hba *hba = dev->se_hba; | ||
| 791 | |||
| 792 | spin_lock(&hba->device_lock); | ||
| 793 | atomic_inc(&dev->dev_obj.obj_access_count); | ||
| 794 | if (atomic_read(&dev->dev_obj.obj_access_count) == 1) { | ||
| 795 | if (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED) { | ||
| 796 | dev->dev_status &= ~TRANSPORT_DEVICE_DEACTIVATED; | ||
| 797 | dev->dev_status |= TRANSPORT_DEVICE_ACTIVATED; | ||
| 798 | } else if (dev->dev_status & | ||
| 799 | TRANSPORT_DEVICE_OFFLINE_DEACTIVATED) { | ||
| 800 | dev->dev_status &= | ||
| 801 | ~TRANSPORT_DEVICE_OFFLINE_DEACTIVATED; | ||
| 802 | dev->dev_status |= TRANSPORT_DEVICE_OFFLINE_ACTIVATED; | ||
| 803 | } | ||
| 804 | } | ||
| 805 | spin_unlock(&hba->device_lock); | ||
| 806 | } | ||
| 807 | |||
| 808 | static void se_dev_stop(struct se_device *dev) | ||
| 809 | { | ||
| 810 | struct se_hba *hba = dev->se_hba; | ||
| 811 | |||
| 812 | spin_lock(&hba->device_lock); | ||
| 813 | atomic_dec(&dev->dev_obj.obj_access_count); | ||
| 814 | if (atomic_read(&dev->dev_obj.obj_access_count) == 0) { | ||
| 815 | if (dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) { | ||
| 816 | dev->dev_status &= ~TRANSPORT_DEVICE_ACTIVATED; | ||
| 817 | dev->dev_status |= TRANSPORT_DEVICE_DEACTIVATED; | ||
| 818 | } else if (dev->dev_status & | ||
| 819 | TRANSPORT_DEVICE_OFFLINE_ACTIVATED) { | ||
| 820 | dev->dev_status &= ~TRANSPORT_DEVICE_OFFLINE_ACTIVATED; | ||
| 821 | dev->dev_status |= TRANSPORT_DEVICE_OFFLINE_DEACTIVATED; | ||
| 822 | } | ||
| 823 | } | ||
| 824 | spin_unlock(&hba->device_lock); | ||
| 825 | } | ||
| 826 | |||
| 827 | int se_dev_check_online(struct se_device *dev) | ||
| 828 | { | ||
| 829 | unsigned long flags; | ||
| 830 | int ret; | ||
| 831 | |||
| 832 | spin_lock_irqsave(&dev->dev_status_lock, flags); | ||
| 833 | ret = ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) || | ||
| 834 | (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED)) ? 0 : 1; | ||
| 835 | spin_unlock_irqrestore(&dev->dev_status_lock, flags); | ||
| 836 | |||
| 837 | return ret; | ||
| 838 | } | ||
| 839 | |||
| 840 | int se_dev_check_shutdown(struct se_device *dev) | ||
| 841 | { | ||
| 842 | int ret; | ||
| 843 | |||
| 844 | spin_lock_irq(&dev->dev_status_lock); | ||
| 845 | ret = (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN); | ||
| 846 | spin_unlock_irq(&dev->dev_status_lock); | ||
| 847 | |||
| 848 | return ret; | ||
| 849 | } | 645 | } |
| 850 | 646 | ||
| 851 | static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) | 647 | static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) |
| @@ -866,72 +662,13 @@ static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) | |||
| 866 | return aligned_max_sectors; | 662 | return aligned_max_sectors; |
| 867 | } | 663 | } |
| 868 | 664 | ||
| 869 | void se_dev_set_default_attribs( | ||
| 870 | struct se_device *dev, | ||
| 871 | struct se_dev_limits *dev_limits) | ||
| 872 | { | ||
| 873 | struct queue_limits *limits = &dev_limits->limits; | ||
| 874 | |||
| 875 | dev->se_sub_dev->se_dev_attrib.emulate_dpo = DA_EMULATE_DPO; | ||
| 876 | dev->se_sub_dev->se_dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE; | ||
| 877 | dev->se_sub_dev->se_dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ; | ||
| 878 | dev->se_sub_dev->se_dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; | ||
| 879 | dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; | ||
| 880 | dev->se_sub_dev->se_dev_attrib.emulate_tas = DA_EMULATE_TAS; | ||
| 881 | dev->se_sub_dev->se_dev_attrib.emulate_tpu = DA_EMULATE_TPU; | ||
| 882 | dev->se_sub_dev->se_dev_attrib.emulate_tpws = DA_EMULATE_TPWS; | ||
| 883 | dev->se_sub_dev->se_dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; | ||
| 884 | dev->se_sub_dev->se_dev_attrib.emulate_alua = DA_EMULATE_ALUA; | ||
| 885 | dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; | ||
| 886 | dev->se_sub_dev->se_dev_attrib.is_nonrot = DA_IS_NONROT; | ||
| 887 | dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; | ||
| 888 | /* | ||
| 889 | * The TPU=1 and TPWS=1 settings will be set in TCM/IBLOCK | ||
| 890 | * iblock_create_virtdevice() from struct queue_limits values | ||
| 891 | * if blk_queue_discard()==1 | ||
| 892 | */ | ||
| 893 | dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT; | ||
| 894 | dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = | ||
| 895 | DA_MAX_UNMAP_BLOCK_DESC_COUNT; | ||
| 896 | dev->se_sub_dev->se_dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; | ||
| 897 | dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = | ||
| 898 | DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; | ||
| 899 | /* | ||
| 900 | * block_size is based on subsystem plugin dependent requirements. | ||
| 901 | */ | ||
| 902 | dev->se_sub_dev->se_dev_attrib.hw_block_size = limits->logical_block_size; | ||
| 903 | dev->se_sub_dev->se_dev_attrib.block_size = limits->logical_block_size; | ||
| 904 | /* | ||
| 905 | * Align max_hw_sectors down to PAGE_SIZE I/O transfers | ||
| 906 | */ | ||
| 907 | limits->max_hw_sectors = se_dev_align_max_sectors(limits->max_hw_sectors, | ||
| 908 | limits->logical_block_size); | ||
| 909 | dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors; | ||
| 910 | |||
| 911 | /* | ||
| 912 | * Set fabric_max_sectors, which is reported in block limits | ||
| 913 | * VPD page (B0h). | ||
| 914 | */ | ||
| 915 | dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; | ||
| 916 | /* | ||
| 917 | * Set optimal_sectors from fabric_max_sectors, which can be | ||
| 918 | * lowered via configfs. | ||
| 919 | */ | ||
| 920 | dev->se_sub_dev->se_dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; | ||
| 921 | /* | ||
| 922 | * queue_depth is based on subsystem plugin dependent requirements. | ||
| 923 | */ | ||
| 924 | dev->se_sub_dev->se_dev_attrib.hw_queue_depth = dev_limits->hw_queue_depth; | ||
| 925 | dev->se_sub_dev->se_dev_attrib.queue_depth = dev_limits->queue_depth; | ||
| 926 | } | ||
| 927 | |||
| 928 | int se_dev_set_max_unmap_lba_count( | 665 | int se_dev_set_max_unmap_lba_count( |
| 929 | struct se_device *dev, | 666 | struct se_device *dev, |
| 930 | u32 max_unmap_lba_count) | 667 | u32 max_unmap_lba_count) |
| 931 | { | 668 | { |
| 932 | dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = max_unmap_lba_count; | 669 | dev->dev_attrib.max_unmap_lba_count = max_unmap_lba_count; |
| 933 | pr_debug("dev[%p]: Set max_unmap_lba_count: %u\n", | 670 | pr_debug("dev[%p]: Set max_unmap_lba_count: %u\n", |
| 934 | dev, dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count); | 671 | dev, dev->dev_attrib.max_unmap_lba_count); |
| 935 | return 0; | 672 | return 0; |
| 936 | } | 673 | } |
| 937 | 674 | ||
| @@ -939,10 +676,10 @@ int se_dev_set_max_unmap_block_desc_count( | |||
| 939 | struct se_device *dev, | 676 | struct se_device *dev, |
| 940 | u32 max_unmap_block_desc_count) | 677 | u32 max_unmap_block_desc_count) |
| 941 | { | 678 | { |
| 942 | dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = | 679 | dev->dev_attrib.max_unmap_block_desc_count = |
| 943 | max_unmap_block_desc_count; | 680 | max_unmap_block_desc_count; |
| 944 | pr_debug("dev[%p]: Set max_unmap_block_desc_count: %u\n", | 681 | pr_debug("dev[%p]: Set max_unmap_block_desc_count: %u\n", |
| 945 | dev, dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count); | 682 | dev, dev->dev_attrib.max_unmap_block_desc_count); |
| 946 | return 0; | 683 | return 0; |
| 947 | } | 684 | } |
| 948 | 685 | ||
| @@ -950,9 +687,9 @@ int se_dev_set_unmap_granularity( | |||
| 950 | struct se_device *dev, | 687 | struct se_device *dev, |
| 951 | u32 unmap_granularity) | 688 | u32 unmap_granularity) |
| 952 | { | 689 | { |
| 953 | dev->se_sub_dev->se_dev_attrib.unmap_granularity = unmap_granularity; | 690 | dev->dev_attrib.unmap_granularity = unmap_granularity; |
| 954 | pr_debug("dev[%p]: Set unmap_granularity: %u\n", | 691 | pr_debug("dev[%p]: Set unmap_granularity: %u\n", |
| 955 | dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity); | 692 | dev, dev->dev_attrib.unmap_granularity); |
| 956 | return 0; | 693 | return 0; |
| 957 | } | 694 | } |
| 958 | 695 | ||
| @@ -960,9 +697,19 @@ int se_dev_set_unmap_granularity_alignment( | |||
| 960 | struct se_device *dev, | 697 | struct se_device *dev, |
| 961 | u32 unmap_granularity_alignment) | 698 | u32 unmap_granularity_alignment) |
| 962 | { | 699 | { |
| 963 | dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = unmap_granularity_alignment; | 700 | dev->dev_attrib.unmap_granularity_alignment = unmap_granularity_alignment; |
| 964 | pr_debug("dev[%p]: Set unmap_granularity_alignment: %u\n", | 701 | pr_debug("dev[%p]: Set unmap_granularity_alignment: %u\n", |
| 965 | dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment); | 702 | dev, dev->dev_attrib.unmap_granularity_alignment); |
| 703 | return 0; | ||
| 704 | } | ||
| 705 | |||
| 706 | int se_dev_set_max_write_same_len( | ||
| 707 | struct se_device *dev, | ||
| 708 | u32 max_write_same_len) | ||
| 709 | { | ||
| 710 | dev->dev_attrib.max_write_same_len = max_write_same_len; | ||
| 711 | pr_debug("dev[%p]: Set max_write_same_len: %u\n", | ||
| 712 | dev, dev->dev_attrib.max_write_same_len); | ||
| 966 | return 0; | 713 | return 0; |
| 967 | } | 714 | } |
| 968 | 715 | ||
| @@ -993,9 +740,9 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) | |||
| 993 | pr_err("emulate_fua_write not supported for pSCSI\n"); | 740 | pr_err("emulate_fua_write not supported for pSCSI\n"); |
| 994 | return -EINVAL; | 741 | return -EINVAL; |
| 995 | } | 742 | } |
| 996 | dev->se_sub_dev->se_dev_attrib.emulate_fua_write = flag; | 743 | dev->dev_attrib.emulate_fua_write = flag; |
| 997 | pr_debug("dev[%p]: SE Device Forced Unit Access WRITEs: %d\n", | 744 | pr_debug("dev[%p]: SE Device Forced Unit Access WRITEs: %d\n", |
| 998 | dev, dev->se_sub_dev->se_dev_attrib.emulate_fua_write); | 745 | dev, dev->dev_attrib.emulate_fua_write); |
| 999 | return 0; | 746 | return 0; |
| 1000 | } | 747 | } |
| 1001 | 748 | ||
| @@ -1025,9 +772,9 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) | |||
| 1025 | pr_err("emulate_write_cache not supported for pSCSI\n"); | 772 | pr_err("emulate_write_cache not supported for pSCSI\n"); |
| 1026 | return -EINVAL; | 773 | return -EINVAL; |
| 1027 | } | 774 | } |
| 1028 | dev->se_sub_dev->se_dev_attrib.emulate_write_cache = flag; | 775 | dev->dev_attrib.emulate_write_cache = flag; |
| 1029 | pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n", | 776 | pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n", |
| 1030 | dev, dev->se_sub_dev->se_dev_attrib.emulate_write_cache); | 777 | dev, dev->dev_attrib.emulate_write_cache); |
| 1031 | return 0; | 778 | return 0; |
| 1032 | } | 779 | } |
| 1033 | 780 | ||
| @@ -1038,16 +785,15 @@ int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *dev, int flag) | |||
| 1038 | return -EINVAL; | 785 | return -EINVAL; |
| 1039 | } | 786 | } |
| 1040 | 787 | ||
| 1041 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 788 | if (dev->export_count) { |
| 1042 | pr_err("dev[%p]: Unable to change SE Device" | 789 | pr_err("dev[%p]: Unable to change SE Device" |
| 1043 | " UA_INTRLCK_CTRL while dev_export_obj: %d count" | 790 | " UA_INTRLCK_CTRL while export_count is %d\n", |
| 1044 | " exists\n", dev, | 791 | dev, dev->export_count); |
| 1045 | atomic_read(&dev->dev_export_obj.obj_access_count)); | ||
| 1046 | return -EINVAL; | 792 | return -EINVAL; |
| 1047 | } | 793 | } |
| 1048 | dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = flag; | 794 | dev->dev_attrib.emulate_ua_intlck_ctrl = flag; |
| 1049 | pr_debug("dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n", | 795 | pr_debug("dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n", |
| 1050 | dev, dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl); | 796 | dev, dev->dev_attrib.emulate_ua_intlck_ctrl); |
| 1051 | 797 | ||
| 1052 | return 0; | 798 | return 0; |
| 1053 | } | 799 | } |
| @@ -1059,15 +805,15 @@ int se_dev_set_emulate_tas(struct se_device *dev, int flag) | |||
| 1059 | return -EINVAL; | 805 | return -EINVAL; |
| 1060 | } | 806 | } |
| 1061 | 807 | ||
| 1062 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 808 | if (dev->export_count) { |
| 1063 | pr_err("dev[%p]: Unable to change SE Device TAS while" | 809 | pr_err("dev[%p]: Unable to change SE Device TAS while" |
| 1064 | " dev_export_obj: %d count exists\n", dev, | 810 | " export_count is %d\n", |
| 1065 | atomic_read(&dev->dev_export_obj.obj_access_count)); | 811 | dev, dev->export_count); |
| 1066 | return -EINVAL; | 812 | return -EINVAL; |
| 1067 | } | 813 | } |
| 1068 | dev->se_sub_dev->se_dev_attrib.emulate_tas = flag; | 814 | dev->dev_attrib.emulate_tas = flag; |
| 1069 | pr_debug("dev[%p]: SE Device TASK_ABORTED status bit: %s\n", | 815 | pr_debug("dev[%p]: SE Device TASK_ABORTED status bit: %s\n", |
| 1070 | dev, (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? "Enabled" : "Disabled"); | 816 | dev, (dev->dev_attrib.emulate_tas) ? "Enabled" : "Disabled"); |
| 1071 | 817 | ||
| 1072 | return 0; | 818 | return 0; |
| 1073 | } | 819 | } |
| @@ -1082,12 +828,12 @@ int se_dev_set_emulate_tpu(struct se_device *dev, int flag) | |||
| 1082 | * We expect this value to be non-zero when generic Block Layer | 828 | * We expect this value to be non-zero when generic Block Layer |
| 1083 | * Discard supported is detected iblock_create_virtdevice(). | 829 | * Discard supported is detected iblock_create_virtdevice(). |
| 1084 | */ | 830 | */ |
| 1085 | if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { | 831 | if (flag && !dev->dev_attrib.max_unmap_block_desc_count) { |
| 1086 | pr_err("Generic Block Discard not supported\n"); | 832 | pr_err("Generic Block Discard not supported\n"); |
| 1087 | return -ENOSYS; | 833 | return -ENOSYS; |
| 1088 | } | 834 | } |
| 1089 | 835 | ||
| 1090 | dev->se_sub_dev->se_dev_attrib.emulate_tpu = flag; | 836 | dev->dev_attrib.emulate_tpu = flag; |
| 1091 | pr_debug("dev[%p]: SE Device Thin Provisioning UNMAP bit: %d\n", | 837 | pr_debug("dev[%p]: SE Device Thin Provisioning UNMAP bit: %d\n", |
| 1092 | dev, flag); | 838 | dev, flag); |
| 1093 | return 0; | 839 | return 0; |
| @@ -1103,12 +849,12 @@ int se_dev_set_emulate_tpws(struct se_device *dev, int flag) | |||
| 1103 | * We expect this value to be non-zero when generic Block Layer | 849 | * We expect this value to be non-zero when generic Block Layer |
| 1104 | * Discard supported is detected iblock_create_virtdevice(). | 850 | * Discard supported is detected iblock_create_virtdevice(). |
| 1105 | */ | 851 | */ |
| 1106 | if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { | 852 | if (flag && !dev->dev_attrib.max_unmap_block_desc_count) { |
| 1107 | pr_err("Generic Block Discard not supported\n"); | 853 | pr_err("Generic Block Discard not supported\n"); |
| 1108 | return -ENOSYS; | 854 | return -ENOSYS; |
| 1109 | } | 855 | } |
| 1110 | 856 | ||
| 1111 | dev->se_sub_dev->se_dev_attrib.emulate_tpws = flag; | 857 | dev->dev_attrib.emulate_tpws = flag; |
| 1112 | pr_debug("dev[%p]: SE Device Thin Provisioning WRITE_SAME: %d\n", | 858 | pr_debug("dev[%p]: SE Device Thin Provisioning WRITE_SAME: %d\n", |
| 1113 | dev, flag); | 859 | dev, flag); |
| 1114 | return 0; | 860 | return 0; |
| @@ -1120,9 +866,9 @@ int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) | |||
| 1120 | pr_err("Illegal value %d\n", flag); | 866 | pr_err("Illegal value %d\n", flag); |
| 1121 | return -EINVAL; | 867 | return -EINVAL; |
| 1122 | } | 868 | } |
| 1123 | dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = flag; | 869 | dev->dev_attrib.enforce_pr_isids = flag; |
| 1124 | pr_debug("dev[%p]: SE Device enforce_pr_isids bit: %s\n", dev, | 870 | pr_debug("dev[%p]: SE Device enforce_pr_isids bit: %s\n", dev, |
| 1125 | (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled"); | 871 | (dev->dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled"); |
| 1126 | return 0; | 872 | return 0; |
| 1127 | } | 873 | } |
| 1128 | 874 | ||
| @@ -1132,7 +878,7 @@ int se_dev_set_is_nonrot(struct se_device *dev, int flag) | |||
| 1132 | printk(KERN_ERR "Illegal value %d\n", flag); | 878 | printk(KERN_ERR "Illegal value %d\n", flag); |
| 1133 | return -EINVAL; | 879 | return -EINVAL; |
| 1134 | } | 880 | } |
| 1135 | dev->se_sub_dev->se_dev_attrib.is_nonrot = flag; | 881 | dev->dev_attrib.is_nonrot = flag; |
| 1136 | pr_debug("dev[%p]: SE Device is_nonrot bit: %d\n", | 882 | pr_debug("dev[%p]: SE Device is_nonrot bit: %d\n", |
| 1137 | dev, flag); | 883 | dev, flag); |
| 1138 | return 0; | 884 | return 0; |
| @@ -1145,7 +891,7 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag) | |||
| 1145 | " reordering not implemented\n", dev); | 891 | " reordering not implemented\n", dev); |
| 1146 | return -ENOSYS; | 892 | return -ENOSYS; |
| 1147 | } | 893 | } |
| 1148 | dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = flag; | 894 | dev->dev_attrib.emulate_rest_reord = flag; |
| 1149 | pr_debug("dev[%p]: SE Device emulate_rest_reord: %d\n", dev, flag); | 895 | pr_debug("dev[%p]: SE Device emulate_rest_reord: %d\n", dev, flag); |
| 1150 | return 0; | 896 | return 0; |
| 1151 | } | 897 | } |
| @@ -1155,10 +901,10 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag) | |||
| 1155 | */ | 901 | */ |
| 1156 | int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) | 902 | int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) |
| 1157 | { | 903 | { |
| 1158 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 904 | if (dev->export_count) { |
| 1159 | pr_err("dev[%p]: Unable to change SE Device TCQ while" | 905 | pr_err("dev[%p]: Unable to change SE Device TCQ while" |
| 1160 | " dev_export_obj: %d count exists\n", dev, | 906 | " export_count is %d\n", |
| 1161 | atomic_read(&dev->dev_export_obj.obj_access_count)); | 907 | dev, dev->export_count); |
| 1162 | return -EINVAL; | 908 | return -EINVAL; |
| 1163 | } | 909 | } |
| 1164 | if (!queue_depth) { | 910 | if (!queue_depth) { |
| @@ -1168,26 +914,26 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) | |||
| 1168 | } | 914 | } |
| 1169 | 915 | ||
| 1170 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { | 916 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { |
| 1171 | if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) { | 917 | if (queue_depth > dev->dev_attrib.hw_queue_depth) { |
| 1172 | pr_err("dev[%p]: Passed queue_depth: %u" | 918 | pr_err("dev[%p]: Passed queue_depth: %u" |
| 1173 | " exceeds TCM/SE_Device TCQ: %u\n", | 919 | " exceeds TCM/SE_Device TCQ: %u\n", |
| 1174 | dev, queue_depth, | 920 | dev, queue_depth, |
| 1175 | dev->se_sub_dev->se_dev_attrib.hw_queue_depth); | 921 | dev->dev_attrib.hw_queue_depth); |
| 1176 | return -EINVAL; | 922 | return -EINVAL; |
| 1177 | } | 923 | } |
| 1178 | } else { | 924 | } else { |
| 1179 | if (queue_depth > dev->se_sub_dev->se_dev_attrib.queue_depth) { | 925 | if (queue_depth > dev->dev_attrib.queue_depth) { |
| 1180 | if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) { | 926 | if (queue_depth > dev->dev_attrib.hw_queue_depth) { |
| 1181 | pr_err("dev[%p]: Passed queue_depth:" | 927 | pr_err("dev[%p]: Passed queue_depth:" |
| 1182 | " %u exceeds TCM/SE_Device MAX" | 928 | " %u exceeds TCM/SE_Device MAX" |
| 1183 | " TCQ: %u\n", dev, queue_depth, | 929 | " TCQ: %u\n", dev, queue_depth, |
| 1184 | dev->se_sub_dev->se_dev_attrib.hw_queue_depth); | 930 | dev->dev_attrib.hw_queue_depth); |
| 1185 | return -EINVAL; | 931 | return -EINVAL; |
| 1186 | } | 932 | } |
| 1187 | } | 933 | } |
| 1188 | } | 934 | } |
| 1189 | 935 | ||
| 1190 | dev->se_sub_dev->se_dev_attrib.queue_depth = dev->queue_depth = queue_depth; | 936 | dev->dev_attrib.queue_depth = dev->queue_depth = queue_depth; |
| 1191 | pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n", | 937 | pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n", |
| 1192 | dev, queue_depth); | 938 | dev, queue_depth); |
| 1193 | return 0; | 939 | return 0; |
| @@ -1195,10 +941,10 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) | |||
| 1195 | 941 | ||
| 1196 | int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) | 942 | int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) |
| 1197 | { | 943 | { |
| 1198 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 944 | if (dev->export_count) { |
| 1199 | pr_err("dev[%p]: Unable to change SE Device" | 945 | pr_err("dev[%p]: Unable to change SE Device" |
| 1200 | " fabric_max_sectors while dev_export_obj: %d count exists\n", | 946 | " fabric_max_sectors while export_count is %d\n", |
| 1201 | dev, atomic_read(&dev->dev_export_obj.obj_access_count)); | 947 | dev, dev->export_count); |
| 1202 | return -EINVAL; | 948 | return -EINVAL; |
| 1203 | } | 949 | } |
| 1204 | if (!fabric_max_sectors) { | 950 | if (!fabric_max_sectors) { |
| @@ -1213,11 +959,11 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) | |||
| 1213 | return -EINVAL; | 959 | return -EINVAL; |
| 1214 | } | 960 | } |
| 1215 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { | 961 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { |
| 1216 | if (fabric_max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) { | 962 | if (fabric_max_sectors > dev->dev_attrib.hw_max_sectors) { |
| 1217 | pr_err("dev[%p]: Passed fabric_max_sectors: %u" | 963 | pr_err("dev[%p]: Passed fabric_max_sectors: %u" |
| 1218 | " greater than TCM/SE_Device max_sectors:" | 964 | " greater than TCM/SE_Device max_sectors:" |
| 1219 | " %u\n", dev, fabric_max_sectors, | 965 | " %u\n", dev, fabric_max_sectors, |
| 1220 | dev->se_sub_dev->se_dev_attrib.hw_max_sectors); | 966 | dev->dev_attrib.hw_max_sectors); |
| 1221 | return -EINVAL; | 967 | return -EINVAL; |
| 1222 | } | 968 | } |
| 1223 | } else { | 969 | } else { |
| @@ -1233,9 +979,9 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) | |||
| 1233 | * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() | 979 | * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() |
| 1234 | */ | 980 | */ |
| 1235 | fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, | 981 | fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, |
| 1236 | dev->se_sub_dev->se_dev_attrib.block_size); | 982 | dev->dev_attrib.block_size); |
| 1237 | 983 | ||
| 1238 | dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = fabric_max_sectors; | 984 | dev->dev_attrib.fabric_max_sectors = fabric_max_sectors; |
| 1239 | pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", | 985 | pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", |
| 1240 | dev, fabric_max_sectors); | 986 | dev, fabric_max_sectors); |
| 1241 | return 0; | 987 | return 0; |
| @@ -1243,10 +989,10 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) | |||
| 1243 | 989 | ||
| 1244 | int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) | 990 | int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) |
| 1245 | { | 991 | { |
| 1246 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 992 | if (dev->export_count) { |
| 1247 | pr_err("dev[%p]: Unable to change SE Device" | 993 | pr_err("dev[%p]: Unable to change SE Device" |
| 1248 | " optimal_sectors while dev_export_obj: %d count exists\n", | 994 | " optimal_sectors while export_count is %d\n", |
| 1249 | dev, atomic_read(&dev->dev_export_obj.obj_access_count)); | 995 | dev, dev->export_count); |
| 1250 | return -EINVAL; | 996 | return -EINVAL; |
| 1251 | } | 997 | } |
| 1252 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { | 998 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { |
| @@ -1254,14 +1000,14 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) | |||
| 1254 | " changed for TCM/pSCSI\n", dev); | 1000 | " changed for TCM/pSCSI\n", dev); |
| 1255 | return -EINVAL; | 1001 | return -EINVAL; |
| 1256 | } | 1002 | } |
| 1257 | if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.fabric_max_sectors) { | 1003 | if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) { |
| 1258 | pr_err("dev[%p]: Passed optimal_sectors %u cannot be" | 1004 | pr_err("dev[%p]: Passed optimal_sectors %u cannot be" |
| 1259 | " greater than fabric_max_sectors: %u\n", dev, | 1005 | " greater than fabric_max_sectors: %u\n", dev, |
| 1260 | optimal_sectors, dev->se_sub_dev->se_dev_attrib.fabric_max_sectors); | 1006 | optimal_sectors, dev->dev_attrib.fabric_max_sectors); |
| 1261 | return -EINVAL; | 1007 | return -EINVAL; |
| 1262 | } | 1008 | } |
| 1263 | 1009 | ||
| 1264 | dev->se_sub_dev->se_dev_attrib.optimal_sectors = optimal_sectors; | 1010 | dev->dev_attrib.optimal_sectors = optimal_sectors; |
| 1265 | pr_debug("dev[%p]: SE Device optimal_sectors changed to %u\n", | 1011 | pr_debug("dev[%p]: SE Device optimal_sectors changed to %u\n", |
| 1266 | dev, optimal_sectors); | 1012 | dev, optimal_sectors); |
| 1267 | return 0; | 1013 | return 0; |
| @@ -1269,10 +1015,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) | |||
| 1269 | 1015 | ||
| 1270 | int se_dev_set_block_size(struct se_device *dev, u32 block_size) | 1016 | int se_dev_set_block_size(struct se_device *dev, u32 block_size) |
| 1271 | { | 1017 | { |
| 1272 | if (atomic_read(&dev->dev_export_obj.obj_access_count)) { | 1018 | if (dev->export_count) { |
| 1273 | pr_err("dev[%p]: Unable to change SE Device block_size" | 1019 | pr_err("dev[%p]: Unable to change SE Device block_size" |
| 1274 | " while dev_export_obj: %d count exists\n", dev, | 1020 | " while export_count is %d\n", |
| 1275 | atomic_read(&dev->dev_export_obj.obj_access_count)); | 1021 | dev, dev->export_count); |
| 1276 | return -EINVAL; | 1022 | return -EINVAL; |
| 1277 | } | 1023 | } |
| 1278 | 1024 | ||
| @@ -1293,7 +1039,7 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size) | |||
| 1293 | return -EINVAL; | 1039 | return -EINVAL; |
| 1294 | } | 1040 | } |
| 1295 | 1041 | ||
| 1296 | dev->se_sub_dev->se_dev_attrib.block_size = block_size; | 1042 | dev->dev_attrib.block_size = block_size; |
| 1297 | pr_debug("dev[%p]: SE Device block_size changed to %u\n", | 1043 | pr_debug("dev[%p]: SE Device block_size changed to %u\n", |
| 1298 | dev, block_size); | 1044 | dev, block_size); |
| 1299 | return 0; | 1045 | return 0; |
| @@ -1307,12 +1053,6 @@ struct se_lun *core_dev_add_lun( | |||
| 1307 | struct se_lun *lun_p; | 1053 | struct se_lun *lun_p; |
| 1308 | int rc; | 1054 | int rc; |
| 1309 | 1055 | ||
| 1310 | if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) { | ||
| 1311 | pr_err("Unable to export struct se_device while dev_access_obj: %d\n", | ||
| 1312 | atomic_read(&dev->dev_access_obj.obj_access_count)); | ||
| 1313 | return ERR_PTR(-EACCES); | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | lun_p = core_tpg_pre_addlun(tpg, lun); | 1056 | lun_p = core_tpg_pre_addlun(tpg, lun); |
| 1317 | if (IS_ERR(lun_p)) | 1057 | if (IS_ERR(lun_p)) |
| 1318 | return lun_p; | 1058 | return lun_p; |
| @@ -1568,12 +1308,211 @@ void core_dev_free_initiator_node_lun_acl( | |||
| 1568 | kfree(lacl); | 1308 | kfree(lacl); |
| 1569 | } | 1309 | } |
| 1570 | 1310 | ||
| 1311 | static void scsi_dump_inquiry(struct se_device *dev) | ||
| 1312 | { | ||
| 1313 | struct t10_wwn *wwn = &dev->t10_wwn; | ||
| 1314 | char buf[17]; | ||
| 1315 | int i, device_type; | ||
| 1316 | /* | ||
| 1317 | * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer | ||
| 1318 | */ | ||
| 1319 | for (i = 0; i < 8; i++) | ||
| 1320 | if (wwn->vendor[i] >= 0x20) | ||
| 1321 | buf[i] = wwn->vendor[i]; | ||
| 1322 | else | ||
| 1323 | buf[i] = ' '; | ||
| 1324 | buf[i] = '\0'; | ||
| 1325 | pr_debug(" Vendor: %s\n", buf); | ||
| 1326 | |||
| 1327 | for (i = 0; i < 16; i++) | ||
| 1328 | if (wwn->model[i] >= 0x20) | ||
| 1329 | buf[i] = wwn->model[i]; | ||
| 1330 | else | ||
| 1331 | buf[i] = ' '; | ||
| 1332 | buf[i] = '\0'; | ||
| 1333 | pr_debug(" Model: %s\n", buf); | ||
| 1334 | |||
| 1335 | for (i = 0; i < 4; i++) | ||
| 1336 | if (wwn->revision[i] >= 0x20) | ||
| 1337 | buf[i] = wwn->revision[i]; | ||
| 1338 | else | ||
| 1339 | buf[i] = ' '; | ||
| 1340 | buf[i] = '\0'; | ||
| 1341 | pr_debug(" Revision: %s\n", buf); | ||
| 1342 | |||
| 1343 | device_type = dev->transport->get_device_type(dev); | ||
| 1344 | pr_debug(" Type: %s ", scsi_device_type(device_type)); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | ||
| 1348 | { | ||
| 1349 | struct se_device *dev; | ||
| 1350 | |||
| 1351 | dev = hba->transport->alloc_device(hba, name); | ||
| 1352 | if (!dev) | ||
| 1353 | return NULL; | ||
| 1354 | |||
| 1355 | dev->dev_link_magic = SE_DEV_LINK_MAGIC; | ||
| 1356 | dev->se_hba = hba; | ||
| 1357 | dev->transport = hba->transport; | ||
| 1358 | |||
| 1359 | INIT_LIST_HEAD(&dev->dev_list); | ||
| 1360 | INIT_LIST_HEAD(&dev->dev_sep_list); | ||
| 1361 | INIT_LIST_HEAD(&dev->dev_tmr_list); | ||
| 1362 | INIT_LIST_HEAD(&dev->delayed_cmd_list); | ||
| 1363 | INIT_LIST_HEAD(&dev->state_list); | ||
| 1364 | INIT_LIST_HEAD(&dev->qf_cmd_list); | ||
| 1365 | spin_lock_init(&dev->stats_lock); | ||
| 1366 | spin_lock_init(&dev->execute_task_lock); | ||
| 1367 | spin_lock_init(&dev->delayed_cmd_lock); | ||
| 1368 | spin_lock_init(&dev->dev_reservation_lock); | ||
| 1369 | spin_lock_init(&dev->se_port_lock); | ||
| 1370 | spin_lock_init(&dev->se_tmr_lock); | ||
| 1371 | spin_lock_init(&dev->qf_cmd_lock); | ||
| 1372 | atomic_set(&dev->dev_ordered_id, 0); | ||
| 1373 | INIT_LIST_HEAD(&dev->t10_wwn.t10_vpd_list); | ||
| 1374 | spin_lock_init(&dev->t10_wwn.t10_vpd_lock); | ||
| 1375 | INIT_LIST_HEAD(&dev->t10_pr.registration_list); | ||
| 1376 | INIT_LIST_HEAD(&dev->t10_pr.aptpl_reg_list); | ||
| 1377 | spin_lock_init(&dev->t10_pr.registration_lock); | ||
| 1378 | spin_lock_init(&dev->t10_pr.aptpl_reg_lock); | ||
| 1379 | INIT_LIST_HEAD(&dev->t10_alua.tg_pt_gps_list); | ||
| 1380 | spin_lock_init(&dev->t10_alua.tg_pt_gps_lock); | ||
| 1381 | |||
| 1382 | dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; | ||
| 1383 | dev->t10_wwn.t10_dev = dev; | ||
| 1384 | dev->t10_alua.t10_dev = dev; | ||
| 1385 | |||
| 1386 | dev->dev_attrib.da_dev = dev; | ||
| 1387 | dev->dev_attrib.emulate_dpo = DA_EMULATE_DPO; | ||
| 1388 | dev->dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE; | ||
| 1389 | dev->dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ; | ||
| 1390 | dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; | ||
| 1391 | dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; | ||
| 1392 | dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; | ||
| 1393 | dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; | ||
| 1394 | dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; | ||
| 1395 | dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; | ||
| 1396 | dev->dev_attrib.is_nonrot = DA_IS_NONROT; | ||
| 1397 | dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; | ||
| 1398 | dev->dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT; | ||
| 1399 | dev->dev_attrib.max_unmap_block_desc_count = | ||
| 1400 | DA_MAX_UNMAP_BLOCK_DESC_COUNT; | ||
| 1401 | dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; | ||
| 1402 | dev->dev_attrib.unmap_granularity_alignment = | ||
| 1403 | DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; | ||
| 1404 | dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; | ||
| 1405 | dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; | ||
| 1406 | dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; | ||
| 1407 | |||
| 1408 | return dev; | ||
| 1409 | } | ||
| 1410 | |||
| 1411 | int target_configure_device(struct se_device *dev) | ||
| 1412 | { | ||
| 1413 | struct se_hba *hba = dev->se_hba; | ||
| 1414 | int ret; | ||
| 1415 | |||
| 1416 | if (dev->dev_flags & DF_CONFIGURED) { | ||
| 1417 | pr_err("se_dev->se_dev_ptr already set for storage" | ||
| 1418 | " object\n"); | ||
| 1419 | return -EEXIST; | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | ret = dev->transport->configure_device(dev); | ||
| 1423 | if (ret) | ||
| 1424 | goto out; | ||
| 1425 | dev->dev_flags |= DF_CONFIGURED; | ||
| 1426 | |||
| 1427 | /* | ||
| 1428 | * XXX: there is not much point to have two different values here.. | ||
| 1429 | */ | ||
| 1430 | dev->dev_attrib.block_size = dev->dev_attrib.hw_block_size; | ||
| 1431 | dev->dev_attrib.queue_depth = dev->dev_attrib.hw_queue_depth; | ||
| 1432 | |||
| 1433 | /* | ||
| 1434 | * Align max_hw_sectors down to PAGE_SIZE I/O transfers | ||
| 1435 | */ | ||
| 1436 | dev->dev_attrib.hw_max_sectors = | ||
| 1437 | se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors, | ||
| 1438 | dev->dev_attrib.hw_block_size); | ||
| 1439 | |||
| 1440 | dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); | ||
| 1441 | dev->creation_time = get_jiffies_64(); | ||
| 1442 | |||
| 1443 | ret = core_setup_alua(dev); | ||
| 1444 | if (ret) | ||
| 1445 | goto out; | ||
| 1446 | |||
| 1447 | /* | ||
| 1448 | * Startup the struct se_device processing thread | ||
| 1449 | */ | ||
| 1450 | dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1, | ||
| 1451 | dev->transport->name); | ||
| 1452 | if (!dev->tmr_wq) { | ||
| 1453 | pr_err("Unable to create tmr workqueue for %s\n", | ||
| 1454 | dev->transport->name); | ||
| 1455 | ret = -ENOMEM; | ||
| 1456 | goto out_free_alua; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | /* | ||
| 1460 | * Setup work_queue for QUEUE_FULL | ||
| 1461 | */ | ||
| 1462 | INIT_WORK(&dev->qf_work_queue, target_qf_do_work); | ||
| 1463 | |||
| 1464 | /* | ||
| 1465 | * Preload the initial INQUIRY const values if we are doing | ||
| 1466 | * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI | ||
| 1467 | * passthrough because this is being provided by the backend LLD. | ||
| 1468 | */ | ||
| 1469 | if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { | ||
| 1470 | strncpy(&dev->t10_wwn.vendor[0], "LIO-ORG", 8); | ||
| 1471 | strncpy(&dev->t10_wwn.model[0], | ||
| 1472 | dev->transport->inquiry_prod, 16); | ||
| 1473 | strncpy(&dev->t10_wwn.revision[0], | ||
| 1474 | dev->transport->inquiry_rev, 4); | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | scsi_dump_inquiry(dev); | ||
| 1478 | |||
| 1479 | spin_lock(&hba->device_lock); | ||
| 1480 | hba->dev_count++; | ||
| 1481 | spin_unlock(&hba->device_lock); | ||
| 1482 | return 0; | ||
| 1483 | |||
| 1484 | out_free_alua: | ||
| 1485 | core_alua_free_lu_gp_mem(dev); | ||
| 1486 | out: | ||
| 1487 | se_release_vpd_for_dev(dev); | ||
| 1488 | return ret; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | void target_free_device(struct se_device *dev) | ||
| 1492 | { | ||
| 1493 | struct se_hba *hba = dev->se_hba; | ||
| 1494 | |||
| 1495 | WARN_ON(!list_empty(&dev->dev_sep_list)); | ||
| 1496 | |||
| 1497 | if (dev->dev_flags & DF_CONFIGURED) { | ||
| 1498 | destroy_workqueue(dev->tmr_wq); | ||
| 1499 | |||
| 1500 | spin_lock(&hba->device_lock); | ||
| 1501 | hba->dev_count--; | ||
| 1502 | spin_unlock(&hba->device_lock); | ||
| 1503 | } | ||
| 1504 | |||
| 1505 | core_alua_free_lu_gp_mem(dev); | ||
| 1506 | core_scsi3_free_all_registrations(dev); | ||
| 1507 | se_release_vpd_for_dev(dev); | ||
| 1508 | |||
| 1509 | dev->transport->free_device(dev); | ||
| 1510 | } | ||
| 1511 | |||
| 1571 | int core_dev_setup_virtual_lun0(void) | 1512 | int core_dev_setup_virtual_lun0(void) |
| 1572 | { | 1513 | { |
| 1573 | struct se_hba *hba; | 1514 | struct se_hba *hba; |
| 1574 | struct se_device *dev; | 1515 | struct se_device *dev; |
| 1575 | struct se_subsystem_dev *se_dev = NULL; | ||
| 1576 | struct se_subsystem_api *t; | ||
| 1577 | char buf[16]; | 1516 | char buf[16]; |
| 1578 | int ret; | 1517 | int ret; |
| 1579 | 1518 | ||
| @@ -1581,60 +1520,28 @@ int core_dev_setup_virtual_lun0(void) | |||
| 1581 | if (IS_ERR(hba)) | 1520 | if (IS_ERR(hba)) |
| 1582 | return PTR_ERR(hba); | 1521 | return PTR_ERR(hba); |
| 1583 | 1522 | ||
| 1584 | lun0_hba = hba; | 1523 | dev = target_alloc_device(hba, "virt_lun0"); |
| 1585 | t = hba->transport; | 1524 | if (!dev) { |
| 1586 | |||
| 1587 | se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL); | ||
| 1588 | if (!se_dev) { | ||
| 1589 | pr_err("Unable to allocate memory for" | ||
| 1590 | " struct se_subsystem_dev\n"); | ||
| 1591 | ret = -ENOMEM; | 1525 | ret = -ENOMEM; |
| 1592 | goto out; | 1526 | goto out_free_hba; |
| 1593 | } | 1527 | } |
| 1594 | INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); | ||
| 1595 | spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); | ||
| 1596 | INIT_LIST_HEAD(&se_dev->t10_pr.registration_list); | ||
| 1597 | INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list); | ||
| 1598 | spin_lock_init(&se_dev->t10_pr.registration_lock); | ||
| 1599 | spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock); | ||
| 1600 | INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list); | ||
| 1601 | spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock); | ||
| 1602 | spin_lock_init(&se_dev->se_dev_lock); | ||
| 1603 | se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; | ||
| 1604 | se_dev->t10_wwn.t10_sub_dev = se_dev; | ||
| 1605 | se_dev->t10_alua.t10_sub_dev = se_dev; | ||
| 1606 | se_dev->se_dev_attrib.da_sub_dev = se_dev; | ||
| 1607 | se_dev->se_dev_hba = hba; | ||
| 1608 | |||
| 1609 | se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, "virt_lun0"); | ||
| 1610 | if (!se_dev->se_dev_su_ptr) { | ||
| 1611 | pr_err("Unable to locate subsystem dependent pointer" | ||
| 1612 | " from allocate_virtdevice()\n"); | ||
| 1613 | ret = -ENOMEM; | ||
| 1614 | goto out; | ||
| 1615 | } | ||
| 1616 | lun0_su_dev = se_dev; | ||
| 1617 | 1528 | ||
| 1618 | memset(buf, 0, 16); | 1529 | memset(buf, 0, 16); |
| 1619 | sprintf(buf, "rd_pages=8"); | 1530 | sprintf(buf, "rd_pages=8"); |
| 1620 | t->set_configfs_dev_params(hba, se_dev, buf, sizeof(buf)); | 1531 | hba->transport->set_configfs_dev_params(dev, buf, sizeof(buf)); |
| 1621 | 1532 | ||
| 1622 | dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); | 1533 | ret = target_configure_device(dev); |
| 1623 | if (IS_ERR(dev)) { | 1534 | if (ret) |
| 1624 | ret = PTR_ERR(dev); | 1535 | goto out_free_se_dev; |
| 1625 | goto out; | ||
| 1626 | } | ||
| 1627 | se_dev->se_dev_ptr = dev; | ||
| 1628 | g_lun0_dev = dev; | ||
| 1629 | 1536 | ||
| 1537 | lun0_hba = hba; | ||
| 1538 | g_lun0_dev = dev; | ||
| 1630 | return 0; | 1539 | return 0; |
| 1631 | out: | 1540 | |
| 1632 | lun0_su_dev = NULL; | 1541 | out_free_se_dev: |
| 1633 | kfree(se_dev); | 1542 | target_free_device(dev); |
| 1634 | if (lun0_hba) { | 1543 | out_free_hba: |
| 1635 | core_delete_hba(lun0_hba); | 1544 | core_delete_hba(hba); |
| 1636 | lun0_hba = NULL; | ||
| 1637 | } | ||
| 1638 | return ret; | 1545 | return ret; |
| 1639 | } | 1546 | } |
| 1640 | 1547 | ||
| @@ -1642,14 +1549,11 @@ out: | |||
| 1642 | void core_dev_release_virtual_lun0(void) | 1549 | void core_dev_release_virtual_lun0(void) |
| 1643 | { | 1550 | { |
| 1644 | struct se_hba *hba = lun0_hba; | 1551 | struct se_hba *hba = lun0_hba; |
| 1645 | struct se_subsystem_dev *su_dev = lun0_su_dev; | ||
| 1646 | 1552 | ||
| 1647 | if (!hba) | 1553 | if (!hba) |
| 1648 | return; | 1554 | return; |
| 1649 | 1555 | ||
| 1650 | if (g_lun0_dev) | 1556 | if (g_lun0_dev) |
| 1651 | se_free_virtual_device(g_lun0_dev, hba); | 1557 | target_free_device(g_lun0_dev); |
| 1652 | |||
| 1653 | kfree(su_dev); | ||
| 1654 | core_delete_hba(hba); | 1558 | core_delete_hba(hba); |
| 1655 | } | 1559 | } |
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index bca737bb813d..810263dfa4a1 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c | |||
| @@ -4,10 +4,9 @@ | |||
| 4 | * This file contains generic fabric module configfs infrastructure for | 4 | * This file contains generic fabric module configfs infrastructure for |
| 5 | * TCM v4.x code | 5 | * TCM v4.x code |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2010,2011 Rising Tide Systems | 7 | * (c) Copyright 2010-2012 RisingTide Systems LLC. |
| 8 | * Copyright (c) 2010,2011 Linux-iSCSI.org | ||
| 9 | * | 8 | * |
| 10 | * Copyright (c) Nicholas A. Bellinger <nab@linux-iscsi.org> | 9 | * Nicholas A. Bellinger <nab@linux-iscsi.org> |
| 11 | * | 10 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -71,6 +70,12 @@ static int target_fabric_mappedlun_link( | |||
| 71 | struct se_portal_group *se_tpg; | 70 | struct se_portal_group *se_tpg; |
| 72 | struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; | 71 | struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; |
| 73 | int ret = 0, lun_access; | 72 | int ret = 0, lun_access; |
| 73 | |||
| 74 | if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { | ||
| 75 | pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" | ||
| 76 | " %p to struct lun: %p\n", lun_ci, lun); | ||
| 77 | return -EFAULT; | ||
| 78 | } | ||
| 74 | /* | 79 | /* |
| 75 | * Ensure that the source port exists | 80 | * Ensure that the source port exists |
| 76 | */ | 81 | */ |
| @@ -358,7 +363,7 @@ static struct config_group *target_fabric_make_mappedlun( | |||
| 358 | } | 363 | } |
| 359 | 364 | ||
| 360 | lacl_cg = &lacl->se_lun_group; | 365 | lacl_cg = &lacl->se_lun_group; |
| 361 | lacl_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 366 | lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
| 362 | GFP_KERNEL); | 367 | GFP_KERNEL); |
| 363 | if (!lacl_cg->default_groups) { | 368 | if (!lacl_cg->default_groups) { |
| 364 | pr_err("Unable to allocate lacl_cg->default_groups\n"); | 369 | pr_err("Unable to allocate lacl_cg->default_groups\n"); |
| @@ -374,7 +379,7 @@ static struct config_group *target_fabric_make_mappedlun( | |||
| 374 | lacl_cg->default_groups[1] = NULL; | 379 | lacl_cg->default_groups[1] = NULL; |
| 375 | 380 | ||
| 376 | ml_stat_grp = &lacl->ml_stat_grps.stat_group; | 381 | ml_stat_grp = &lacl->ml_stat_grps.stat_group; |
| 377 | ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, | 382 | ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3, |
| 378 | GFP_KERNEL); | 383 | GFP_KERNEL); |
| 379 | if (!ml_stat_grp->default_groups) { | 384 | if (!ml_stat_grp->default_groups) { |
| 380 | pr_err("Unable to allocate ml_stat_grp->default_groups\n"); | 385 | pr_err("Unable to allocate ml_stat_grp->default_groups\n"); |
| @@ -734,17 +739,21 @@ static int target_fabric_port_link( | |||
| 734 | struct config_item *se_dev_ci) | 739 | struct config_item *se_dev_ci) |
| 735 | { | 740 | { |
| 736 | struct config_item *tpg_ci; | 741 | struct config_item *tpg_ci; |
| 737 | struct se_device *dev; | ||
| 738 | struct se_lun *lun = container_of(to_config_group(lun_ci), | 742 | struct se_lun *lun = container_of(to_config_group(lun_ci), |
| 739 | struct se_lun, lun_group); | 743 | struct se_lun, lun_group); |
| 740 | struct se_lun *lun_p; | 744 | struct se_lun *lun_p; |
| 741 | struct se_portal_group *se_tpg; | 745 | struct se_portal_group *se_tpg; |
| 742 | struct se_subsystem_dev *se_dev = container_of( | 746 | struct se_device *dev = |
| 743 | to_config_group(se_dev_ci), struct se_subsystem_dev, | 747 | container_of(to_config_group(se_dev_ci), struct se_device, dev_group); |
| 744 | se_dev_group); | ||
| 745 | struct target_fabric_configfs *tf; | 748 | struct target_fabric_configfs *tf; |
| 746 | int ret; | 749 | int ret; |
| 747 | 750 | ||
| 751 | if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { | ||
| 752 | pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" | ||
| 753 | " %p to struct se_device: %p\n", se_dev_ci, dev); | ||
| 754 | return -EFAULT; | ||
| 755 | } | ||
| 756 | |||
| 748 | tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; | 757 | tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; |
| 749 | se_tpg = container_of(to_config_group(tpg_ci), | 758 | se_tpg = container_of(to_config_group(tpg_ci), |
| 750 | struct se_portal_group, tpg_group); | 759 | struct se_portal_group, tpg_group); |
| @@ -755,14 +764,6 @@ static int target_fabric_port_link( | |||
| 755 | return -EEXIST; | 764 | return -EEXIST; |
| 756 | } | 765 | } |
| 757 | 766 | ||
| 758 | dev = se_dev->se_dev_ptr; | ||
| 759 | if (!dev) { | ||
| 760 | pr_err("Unable to locate struct se_device pointer from" | ||
| 761 | " %s\n", config_item_name(se_dev_ci)); | ||
| 762 | ret = -ENODEV; | ||
| 763 | goto out; | ||
| 764 | } | ||
| 765 | |||
| 766 | lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun); | 767 | lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun); |
| 767 | if (IS_ERR(lun_p)) { | 768 | if (IS_ERR(lun_p)) { |
| 768 | pr_err("core_dev_add_lun() failed\n"); | 769 | pr_err("core_dev_add_lun() failed\n"); |
| @@ -869,7 +870,7 @@ static struct config_group *target_fabric_make_lun( | |||
| 869 | return ERR_PTR(-EINVAL); | 870 | return ERR_PTR(-EINVAL); |
| 870 | 871 | ||
| 871 | lun_cg = &lun->lun_group; | 872 | lun_cg = &lun->lun_group; |
| 872 | lun_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | 873 | lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
| 873 | GFP_KERNEL); | 874 | GFP_KERNEL); |
| 874 | if (!lun_cg->default_groups) { | 875 | if (!lun_cg->default_groups) { |
| 875 | pr_err("Unable to allocate lun_cg->default_groups\n"); | 876 | pr_err("Unable to allocate lun_cg->default_groups\n"); |
diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c index e460d6233a0a..687b0b0a4aa6 100644 --- a/drivers/target/target_core_fabric_lib.c +++ b/drivers/target/target_core_fabric_lib.c | |||
| @@ -4,8 +4,7 @@ | |||
| 4 | * This file contains generic high level protocol identifier and PR | 4 | * This file contains generic high level protocol identifier and PR |
| 5 | * handlers for TCM fabric modules | 5 | * handlers for TCM fabric modules |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2010 Rising Tide Systems, Inc. | 7 | * (c) Copyright 2010-2012 RisingTide Systems LLC. |
| 8 | * Copyright (c) 2010 Linux-iSCSI.org | ||
| 9 | * | 8 | * |
| 10 | * Nicholas A. Bellinger <nab@linux-iscsi.org> | 9 | * Nicholas A. Bellinger <nab@linux-iscsi.org> |
| 11 | * | 10 | * |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 0360383dfb94..b9c88497e8f0 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
| @@ -3,10 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains the Storage Engine <-> FILEIO transport specific functions | 4 | * This file contains the Storage Engine <-> FILEIO transport specific functions |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2005 PyX Technologies, Inc. | 6 | * (c) Copyright 2005-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2005-2006 SBE, Inc. All Rights Reserved. | ||
| 8 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 9 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 10 | * | 7 | * |
| 11 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 12 | * | 9 | * |
| @@ -41,7 +38,10 @@ | |||
| 41 | 38 | ||
| 42 | #include "target_core_file.h" | 39 | #include "target_core_file.h" |
| 43 | 40 | ||
| 44 | static struct se_subsystem_api fileio_template; | 41 | static inline struct fd_dev *FD_DEV(struct se_device *dev) |
| 42 | { | ||
| 43 | return container_of(dev, struct fd_dev, dev); | ||
| 44 | } | ||
| 45 | 45 | ||
| 46 | /* fd_attach_hba(): (Part of se_subsystem_api_t template) | 46 | /* fd_attach_hba(): (Part of se_subsystem_api_t template) |
| 47 | * | 47 | * |
| @@ -82,7 +82,7 @@ static void fd_detach_hba(struct se_hba *hba) | |||
| 82 | hba->hba_ptr = NULL; | 82 | hba->hba_ptr = NULL; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name) | 85 | static struct se_device *fd_alloc_device(struct se_hba *hba, const char *name) |
| 86 | { | 86 | { |
| 87 | struct fd_dev *fd_dev; | 87 | struct fd_dev *fd_dev; |
| 88 | struct fd_host *fd_host = hba->hba_ptr; | 88 | struct fd_host *fd_host = hba->hba_ptr; |
| @@ -97,34 +97,28 @@ static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name) | |||
| 97 | 97 | ||
| 98 | pr_debug("FILEIO: Allocated fd_dev for %p\n", name); | 98 | pr_debug("FILEIO: Allocated fd_dev for %p\n", name); |
| 99 | 99 | ||
| 100 | return fd_dev; | 100 | return &fd_dev->dev; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | /* fd_create_virtdevice(): (Part of se_subsystem_api_t template) | 103 | static int fd_configure_device(struct se_device *dev) |
| 104 | * | ||
| 105 | * | ||
| 106 | */ | ||
| 107 | static struct se_device *fd_create_virtdevice( | ||
| 108 | struct se_hba *hba, | ||
| 109 | struct se_subsystem_dev *se_dev, | ||
| 110 | void *p) | ||
| 111 | { | 104 | { |
| 112 | struct se_device *dev; | 105 | struct fd_dev *fd_dev = FD_DEV(dev); |
| 113 | struct se_dev_limits dev_limits; | 106 | struct fd_host *fd_host = dev->se_hba->hba_ptr; |
| 114 | struct queue_limits *limits; | ||
| 115 | struct fd_dev *fd_dev = p; | ||
| 116 | struct fd_host *fd_host = hba->hba_ptr; | ||
| 117 | struct file *file; | 107 | struct file *file; |
| 118 | struct inode *inode = NULL; | 108 | struct inode *inode = NULL; |
| 119 | int dev_flags = 0, flags, ret = -EINVAL; | 109 | int flags, ret = -EINVAL; |
| 120 | 110 | ||
| 121 | memset(&dev_limits, 0, sizeof(struct se_dev_limits)); | 111 | if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) { |
| 112 | pr_err("Missing fd_dev_name=\n"); | ||
| 113 | return -EINVAL; | ||
| 114 | } | ||
| 122 | 115 | ||
| 123 | /* | 116 | /* |
| 124 | * Use O_DSYNC by default instead of O_SYNC to forgo syncing | 117 | * Use O_DSYNC by default instead of O_SYNC to forgo syncing |
| 125 | * of pure timestamp updates. | 118 | * of pure timestamp updates. |
| 126 | */ | 119 | */ |
| 127 | flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; | 120 | flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; |
| 121 | |||
| 128 | /* | 122 | /* |
| 129 | * Optionally allow fd_buffered_io=1 to be enabled for people | 123 | * Optionally allow fd_buffered_io=1 to be enabled for people |
| 130 | * who want use the fs buffer cache as an WriteCache mechanism. | 124 | * who want use the fs buffer cache as an WriteCache mechanism. |
| @@ -154,22 +148,17 @@ static struct se_device *fd_create_virtdevice( | |||
| 154 | */ | 148 | */ |
| 155 | inode = file->f_mapping->host; | 149 | inode = file->f_mapping->host; |
| 156 | if (S_ISBLK(inode->i_mode)) { | 150 | if (S_ISBLK(inode->i_mode)) { |
| 157 | struct request_queue *q; | 151 | struct request_queue *q = bdev_get_queue(inode->i_bdev); |
| 158 | unsigned long long dev_size; | 152 | unsigned long long dev_size; |
| 159 | /* | 153 | |
| 160 | * Setup the local scope queue_limits from struct request_queue->limits | 154 | dev->dev_attrib.hw_block_size = |
| 161 | * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. | 155 | bdev_logical_block_size(inode->i_bdev); |
| 162 | */ | 156 | dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); |
| 163 | q = bdev_get_queue(inode->i_bdev); | 157 | |
| 164 | limits = &dev_limits.limits; | ||
| 165 | limits->logical_block_size = bdev_logical_block_size(inode->i_bdev); | ||
| 166 | limits->max_hw_sectors = queue_max_hw_sectors(q); | ||
| 167 | limits->max_sectors = queue_max_sectors(q); | ||
| 168 | /* | 158 | /* |
| 169 | * Determine the number of bytes from i_size_read() minus | 159 | * Determine the number of bytes from i_size_read() minus |
| 170 | * one (1) logical sector from underlying struct block_device | 160 | * one (1) logical sector from underlying struct block_device |
| 171 | */ | 161 | */ |
| 172 | fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); | ||
| 173 | dev_size = (i_size_read(file->f_mapping->host) - | 162 | dev_size = (i_size_read(file->f_mapping->host) - |
| 174 | fd_dev->fd_block_size); | 163 | fd_dev->fd_block_size); |
| 175 | 164 | ||
| @@ -185,26 +174,18 @@ static struct se_device *fd_create_virtdevice( | |||
| 185 | goto fail; | 174 | goto fail; |
| 186 | } | 175 | } |
| 187 | 176 | ||
| 188 | limits = &dev_limits.limits; | 177 | dev->dev_attrib.hw_block_size = FD_BLOCKSIZE; |
| 189 | limits->logical_block_size = FD_BLOCKSIZE; | 178 | dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS; |
| 190 | limits->max_hw_sectors = FD_MAX_SECTORS; | ||
| 191 | limits->max_sectors = FD_MAX_SECTORS; | ||
| 192 | fd_dev->fd_block_size = FD_BLOCKSIZE; | ||
| 193 | } | 179 | } |
| 194 | 180 | ||
| 195 | dev_limits.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH; | 181 | fd_dev->fd_block_size = dev->dev_attrib.hw_block_size; |
| 196 | dev_limits.queue_depth = FD_DEVICE_QUEUE_DEPTH; | ||
| 197 | 182 | ||
| 198 | dev = transport_add_device_to_core_hba(hba, &fileio_template, | 183 | dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH; |
| 199 | se_dev, dev_flags, fd_dev, | ||
| 200 | &dev_limits, "FILEIO", FD_VERSION); | ||
| 201 | if (!dev) | ||
| 202 | goto fail; | ||
| 203 | 184 | ||
| 204 | if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { | 185 | if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { |
| 205 | pr_debug("FILEIO: Forcing setting of emulate_write_cache=1" | 186 | pr_debug("FILEIO: Forcing setting of emulate_write_cache=1" |
| 206 | " with FDBD_HAS_BUFFERED_IO_WCE\n"); | 187 | " with FDBD_HAS_BUFFERED_IO_WCE\n"); |
| 207 | dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1; | 188 | dev->dev_attrib.emulate_write_cache = 1; |
| 208 | } | 189 | } |
| 209 | 190 | ||
| 210 | fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; | 191 | fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; |
| @@ -214,22 +195,18 @@ static struct se_device *fd_create_virtdevice( | |||
| 214 | " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, | 195 | " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, |
| 215 | fd_dev->fd_dev_name, fd_dev->fd_dev_size); | 196 | fd_dev->fd_dev_name, fd_dev->fd_dev_size); |
| 216 | 197 | ||
| 217 | return dev; | 198 | return 0; |
| 218 | fail: | 199 | fail: |
| 219 | if (fd_dev->fd_file) { | 200 | if (fd_dev->fd_file) { |
| 220 | filp_close(fd_dev->fd_file, NULL); | 201 | filp_close(fd_dev->fd_file, NULL); |
| 221 | fd_dev->fd_file = NULL; | 202 | fd_dev->fd_file = NULL; |
| 222 | } | 203 | } |
| 223 | return ERR_PTR(ret); | 204 | return ret; |
| 224 | } | 205 | } |
| 225 | 206 | ||
| 226 | /* fd_free_device(): (Part of se_subsystem_api_t template) | 207 | static void fd_free_device(struct se_device *dev) |
| 227 | * | ||
| 228 | * | ||
| 229 | */ | ||
| 230 | static void fd_free_device(void *p) | ||
| 231 | { | 208 | { |
| 232 | struct fd_dev *fd_dev = p; | 209 | struct fd_dev *fd_dev = FD_DEV(dev); |
| 233 | 210 | ||
| 234 | if (fd_dev->fd_file) { | 211 | if (fd_dev->fd_file) { |
| 235 | filp_close(fd_dev->fd_file, NULL); | 212 | filp_close(fd_dev->fd_file, NULL); |
| @@ -239,17 +216,16 @@ static void fd_free_device(void *p) | |||
| 239 | kfree(fd_dev); | 216 | kfree(fd_dev); |
| 240 | } | 217 | } |
| 241 | 218 | ||
| 242 | static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl, | 219 | static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl, |
| 243 | u32 sgl_nents) | 220 | u32 sgl_nents, int is_write) |
| 244 | { | 221 | { |
| 245 | struct se_device *se_dev = cmd->se_dev; | 222 | struct se_device *se_dev = cmd->se_dev; |
| 246 | struct fd_dev *dev = se_dev->dev_ptr; | 223 | struct fd_dev *dev = FD_DEV(se_dev); |
| 247 | struct file *fd = dev->fd_file; | 224 | struct file *fd = dev->fd_file; |
| 248 | struct scatterlist *sg; | 225 | struct scatterlist *sg; |
| 249 | struct iovec *iov; | 226 | struct iovec *iov; |
| 250 | mm_segment_t old_fs; | 227 | mm_segment_t old_fs; |
| 251 | loff_t pos = (cmd->t_task_lba * | 228 | loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size); |
| 252 | se_dev->se_sub_dev->se_dev_attrib.block_size); | ||
| 253 | int ret = 0, i; | 229 | int ret = 0, i; |
| 254 | 230 | ||
| 255 | iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL); | 231 | iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL); |
| @@ -260,81 +236,58 @@ static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl, | |||
| 260 | 236 | ||
| 261 | for_each_sg(sgl, sg, sgl_nents, i) { | 237 | for_each_sg(sgl, sg, sgl_nents, i) { |
| 262 | iov[i].iov_len = sg->length; | 238 | iov[i].iov_len = sg->length; |
| 263 | iov[i].iov_base = sg_virt(sg); | 239 | iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; |
| 264 | } | 240 | } |
| 265 | 241 | ||
| 266 | old_fs = get_fs(); | 242 | old_fs = get_fs(); |
| 267 | set_fs(get_ds()); | 243 | set_fs(get_ds()); |
| 268 | ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); | 244 | |
| 245 | if (is_write) | ||
| 246 | ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); | ||
| 247 | else | ||
| 248 | ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); | ||
| 249 | |||
| 269 | set_fs(old_fs); | 250 | set_fs(old_fs); |
| 270 | 251 | ||
| 252 | for_each_sg(sgl, sg, sgl_nents, i) | ||
| 253 | kunmap(sg_page(sg)); | ||
| 254 | |||
| 271 | kfree(iov); | 255 | kfree(iov); |
| 272 | /* | 256 | |
| 273 | * Return zeros and GOOD status even if the READ did not return | 257 | if (is_write) { |
| 274 | * the expected virt_size for struct file w/o a backing struct | ||
| 275 | * block_device. | ||
| 276 | */ | ||
| 277 | if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) { | ||
| 278 | if (ret < 0 || ret != cmd->data_length) { | 258 | if (ret < 0 || ret != cmd->data_length) { |
| 279 | pr_err("vfs_readv() returned %d," | 259 | pr_err("%s() write returned %d\n", __func__, ret); |
| 280 | " expecting %d for S_ISBLK\n", ret, | ||
| 281 | (int)cmd->data_length); | ||
| 282 | return (ret < 0 ? ret : -EINVAL); | 260 | return (ret < 0 ? ret : -EINVAL); |
| 283 | } | 261 | } |
| 284 | } else { | 262 | } else { |
| 285 | if (ret < 0) { | 263 | /* |
| 286 | pr_err("vfs_readv() returned %d for non" | 264 | * Return zeros and GOOD status even if the READ did not return |
| 287 | " S_ISBLK\n", ret); | 265 | * the expected virt_size for struct file w/o a backing struct |
| 288 | return ret; | 266 | * block_device. |
| 267 | */ | ||
| 268 | if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) { | ||
| 269 | if (ret < 0 || ret != cmd->data_length) { | ||
| 270 | pr_err("%s() returned %d, expecting %u for " | ||
| 271 | "S_ISBLK\n", __func__, ret, | ||
| 272 | cmd->data_length); | ||
| 273 | return (ret < 0 ? ret : -EINVAL); | ||
| 274 | } | ||
| 275 | } else { | ||
| 276 | if (ret < 0) { | ||
| 277 | pr_err("%s() returned %d for non S_ISBLK\n", | ||
| 278 | __func__, ret); | ||
| 279 | return ret; | ||
| 280 | } | ||
| 289 | } | 281 | } |
| 290 | } | 282 | } |
| 291 | |||
| 292 | return 1; | ||
| 293 | } | ||
| 294 | |||
| 295 | static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, | ||
| 296 | u32 sgl_nents) | ||
| 297 | { | ||
| 298 | struct se_device *se_dev = cmd->se_dev; | ||
| 299 | struct fd_dev *dev = se_dev->dev_ptr; | ||
| 300 | struct file *fd = dev->fd_file; | ||
| 301 | struct scatterlist *sg; | ||
| 302 | struct iovec *iov; | ||
| 303 | mm_segment_t old_fs; | ||
| 304 | loff_t pos = (cmd->t_task_lba * | ||
| 305 | se_dev->se_sub_dev->se_dev_attrib.block_size); | ||
| 306 | int ret, i = 0; | ||
| 307 | |||
| 308 | iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL); | ||
| 309 | if (!iov) { | ||
| 310 | pr_err("Unable to allocate fd_do_writev iov[]\n"); | ||
| 311 | return -ENOMEM; | ||
| 312 | } | ||
| 313 | |||
| 314 | for_each_sg(sgl, sg, sgl_nents, i) { | ||
| 315 | iov[i].iov_len = sg->length; | ||
| 316 | iov[i].iov_base = sg_virt(sg); | ||
| 317 | } | ||
| 318 | |||
| 319 | old_fs = get_fs(); | ||
| 320 | set_fs(get_ds()); | ||
| 321 | ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); | ||
| 322 | set_fs(old_fs); | ||
| 323 | |||
| 324 | kfree(iov); | ||
| 325 | |||
| 326 | if (ret < 0 || ret != cmd->data_length) { | ||
| 327 | pr_err("vfs_writev() returned %d\n", ret); | ||
| 328 | return (ret < 0 ? ret : -EINVAL); | ||
| 329 | } | ||
| 330 | |||
| 331 | return 1; | 283 | return 1; |
| 332 | } | 284 | } |
| 333 | 285 | ||
| 334 | static int fd_execute_sync_cache(struct se_cmd *cmd) | 286 | static sense_reason_t |
| 287 | fd_execute_sync_cache(struct se_cmd *cmd) | ||
| 335 | { | 288 | { |
| 336 | struct se_device *dev = cmd->se_dev; | 289 | struct se_device *dev = cmd->se_dev; |
| 337 | struct fd_dev *fd_dev = dev->dev_ptr; | 290 | struct fd_dev *fd_dev = FD_DEV(dev); |
| 338 | int immed = (cmd->t_task_cdb[1] & 0x2); | 291 | int immed = (cmd->t_task_cdb[1] & 0x2); |
| 339 | loff_t start, end; | 292 | loff_t start, end; |
| 340 | int ret; | 293 | int ret; |
| @@ -353,7 +306,7 @@ static int fd_execute_sync_cache(struct se_cmd *cmd) | |||
| 353 | start = 0; | 306 | start = 0; |
| 354 | end = LLONG_MAX; | 307 | end = LLONG_MAX; |
| 355 | } else { | 308 | } else { |
| 356 | start = cmd->t_task_lba * dev->se_sub_dev->se_dev_attrib.block_size; | 309 | start = cmd->t_task_lba * dev->dev_attrib.block_size; |
| 357 | if (cmd->data_length) | 310 | if (cmd->data_length) |
| 358 | end = start + cmd->data_length; | 311 | end = start + cmd->data_length; |
| 359 | else | 312 | else |
| @@ -367,17 +320,16 @@ static int fd_execute_sync_cache(struct se_cmd *cmd) | |||
| 367 | if (immed) | 320 | if (immed) |
| 368 | return 0; | 321 | return 0; |
| 369 | 322 | ||
| 370 | if (ret) { | 323 | if (ret) |
| 371 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 372 | target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); | 324 | target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); |
| 373 | } else { | 325 | else |
| 374 | target_complete_cmd(cmd, SAM_STAT_GOOD); | 326 | target_complete_cmd(cmd, SAM_STAT_GOOD); |
| 375 | } | ||
| 376 | 327 | ||
| 377 | return 0; | 328 | return 0; |
| 378 | } | 329 | } |
| 379 | 330 | ||
| 380 | static int fd_execute_rw(struct se_cmd *cmd) | 331 | static sense_reason_t |
| 332 | fd_execute_rw(struct se_cmd *cmd) | ||
| 381 | { | 333 | { |
| 382 | struct scatterlist *sgl = cmd->t_data_sg; | 334 | struct scatterlist *sgl = cmd->t_data_sg; |
| 383 | u32 sgl_nents = cmd->t_data_nents; | 335 | u32 sgl_nents = cmd->t_data_nents; |
| @@ -390,30 +342,29 @@ static int fd_execute_rw(struct se_cmd *cmd) | |||
| 390 | * physical memory addresses to struct iovec virtual memory. | 342 | * physical memory addresses to struct iovec virtual memory. |
| 391 | */ | 343 | */ |
| 392 | if (data_direction == DMA_FROM_DEVICE) { | 344 | if (data_direction == DMA_FROM_DEVICE) { |
| 393 | ret = fd_do_readv(cmd, sgl, sgl_nents); | 345 | ret = fd_do_rw(cmd, sgl, sgl_nents, 0); |
| 394 | } else { | 346 | } else { |
| 395 | ret = fd_do_writev(cmd, sgl, sgl_nents); | 347 | ret = fd_do_rw(cmd, sgl, sgl_nents, 1); |
| 396 | /* | 348 | /* |
| 397 | * Perform implict vfs_fsync_range() for fd_do_writev() ops | 349 | * Perform implict vfs_fsync_range() for fd_do_writev() ops |
| 398 | * for SCSI WRITEs with Forced Unit Access (FUA) set. | 350 | * for SCSI WRITEs with Forced Unit Access (FUA) set. |
| 399 | * Allow this to happen independent of WCE=0 setting. | 351 | * Allow this to happen independent of WCE=0 setting. |
| 400 | */ | 352 | */ |
| 401 | if (ret > 0 && | 353 | if (ret > 0 && |
| 402 | dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && | 354 | dev->dev_attrib.emulate_fua_write > 0 && |
| 403 | (cmd->se_cmd_flags & SCF_FUA)) { | 355 | (cmd->se_cmd_flags & SCF_FUA)) { |
| 404 | struct fd_dev *fd_dev = dev->dev_ptr; | 356 | struct fd_dev *fd_dev = FD_DEV(dev); |
| 405 | loff_t start = cmd->t_task_lba * | 357 | loff_t start = cmd->t_task_lba * |
| 406 | dev->se_sub_dev->se_dev_attrib.block_size; | 358 | dev->dev_attrib.block_size; |
| 407 | loff_t end = start + cmd->data_length; | 359 | loff_t end = start + cmd->data_length; |
| 408 | 360 | ||
| 409 | vfs_fsync_range(fd_dev->fd_file, start, end, 1); | 361 | vfs_fsync_range(fd_dev->fd_file, start, end, 1); |
| 410 | } | 362 | } |
| 411 | } | 363 | } |
| 412 | 364 | ||
| 413 | if (ret < 0) { | 365 | if (ret < 0) |
| 414 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 366 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 415 | return ret; | 367 | |
| 416 | } | ||
| 417 | if (ret) | 368 | if (ret) |
| 418 | target_complete_cmd(cmd, SAM_STAT_GOOD); | 369 | target_complete_cmd(cmd, SAM_STAT_GOOD); |
| 419 | return 0; | 370 | return 0; |
| @@ -430,12 +381,10 @@ static match_table_t tokens = { | |||
| 430 | {Opt_err, NULL} | 381 | {Opt_err, NULL} |
| 431 | }; | 382 | }; |
| 432 | 383 | ||
| 433 | static ssize_t fd_set_configfs_dev_params( | 384 | static ssize_t fd_set_configfs_dev_params(struct se_device *dev, |
| 434 | struct se_hba *hba, | 385 | const char *page, ssize_t count) |
| 435 | struct se_subsystem_dev *se_dev, | ||
| 436 | const char *page, ssize_t count) | ||
| 437 | { | 386 | { |
| 438 | struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; | 387 | struct fd_dev *fd_dev = FD_DEV(dev); |
| 439 | char *orig, *ptr, *arg_p, *opts; | 388 | char *orig, *ptr, *arg_p, *opts; |
| 440 | substring_t args[MAX_OPT_ARGS]; | 389 | substring_t args[MAX_OPT_ARGS]; |
| 441 | int ret = 0, arg, token; | 390 | int ret = 0, arg, token; |
| @@ -502,24 +451,9 @@ out: | |||
| 502 | return (!ret) ? count : ret; | 451 | return (!ret) ? count : ret; |
| 503 | } | 452 | } |
| 504 | 453 | ||
| 505 | static ssize_t fd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev) | 454 | static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b) |
| 506 | { | 455 | { |
| 507 | struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; | 456 | struct fd_dev *fd_dev = FD_DEV(dev); |
| 508 | |||
| 509 | if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) { | ||
| 510 | pr_err("Missing fd_dev_name=\n"); | ||
| 511 | return -EINVAL; | ||
| 512 | } | ||
| 513 | |||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | static ssize_t fd_show_configfs_dev_params( | ||
| 518 | struct se_hba *hba, | ||
| 519 | struct se_subsystem_dev *se_dev, | ||
| 520 | char *b) | ||
| 521 | { | ||
| 522 | struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; | ||
| 523 | ssize_t bl = 0; | 457 | ssize_t bl = 0; |
| 524 | 458 | ||
| 525 | bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); | 459 | bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); |
| @@ -530,27 +464,9 @@ static ssize_t fd_show_configfs_dev_params( | |||
| 530 | return bl; | 464 | return bl; |
| 531 | } | 465 | } |
| 532 | 466 | ||
| 533 | /* fd_get_device_rev(): (Part of se_subsystem_api_t template) | ||
| 534 | * | ||
| 535 | * | ||
| 536 | */ | ||
| 537 | static u32 fd_get_device_rev(struct se_device *dev) | ||
| 538 | { | ||
| 539 | return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ | ||
| 540 | } | ||
| 541 | |||
| 542 | /* fd_get_device_type(): (Part of se_subsystem_api_t template) | ||
| 543 | * | ||
| 544 | * | ||
| 545 | */ | ||
| 546 | static u32 fd_get_device_type(struct se_device *dev) | ||
| 547 | { | ||
| 548 | return TYPE_DISK; | ||
| 549 | } | ||
| 550 | |||
| 551 | static sector_t fd_get_blocks(struct se_device *dev) | 467 | static sector_t fd_get_blocks(struct se_device *dev) |
| 552 | { | 468 | { |
| 553 | struct fd_dev *fd_dev = dev->dev_ptr; | 469 | struct fd_dev *fd_dev = FD_DEV(dev); |
| 554 | struct file *f = fd_dev->fd_file; | 470 | struct file *f = fd_dev->fd_file; |
| 555 | struct inode *i = f->f_mapping->host; | 471 | struct inode *i = f->f_mapping->host; |
| 556 | unsigned long long dev_size; | 472 | unsigned long long dev_size; |
| @@ -564,34 +480,35 @@ static sector_t fd_get_blocks(struct se_device *dev) | |||
| 564 | else | 480 | else |
| 565 | dev_size = fd_dev->fd_dev_size; | 481 | dev_size = fd_dev->fd_dev_size; |
| 566 | 482 | ||
| 567 | return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size); | 483 | return div_u64(dev_size, dev->dev_attrib.block_size); |
| 568 | } | 484 | } |
| 569 | 485 | ||
| 570 | static struct spc_ops fd_spc_ops = { | 486 | static struct sbc_ops fd_sbc_ops = { |
| 571 | .execute_rw = fd_execute_rw, | 487 | .execute_rw = fd_execute_rw, |
| 572 | .execute_sync_cache = fd_execute_sync_cache, | 488 | .execute_sync_cache = fd_execute_sync_cache, |
| 573 | }; | 489 | }; |
| 574 | 490 | ||
| 575 | static int fd_parse_cdb(struct se_cmd *cmd) | 491 | static sense_reason_t |
| 492 | fd_parse_cdb(struct se_cmd *cmd) | ||
| 576 | { | 493 | { |
| 577 | return sbc_parse_cdb(cmd, &fd_spc_ops); | 494 | return sbc_parse_cdb(cmd, &fd_sbc_ops); |
| 578 | } | 495 | } |
| 579 | 496 | ||
| 580 | static struct se_subsystem_api fileio_template = { | 497 | static struct se_subsystem_api fileio_template = { |
| 581 | .name = "fileio", | 498 | .name = "fileio", |
| 499 | .inquiry_prod = "FILEIO", | ||
| 500 | .inquiry_rev = FD_VERSION, | ||
| 582 | .owner = THIS_MODULE, | 501 | .owner = THIS_MODULE, |
| 583 | .transport_type = TRANSPORT_PLUGIN_VHBA_PDEV, | 502 | .transport_type = TRANSPORT_PLUGIN_VHBA_PDEV, |
| 584 | .attach_hba = fd_attach_hba, | 503 | .attach_hba = fd_attach_hba, |
| 585 | .detach_hba = fd_detach_hba, | 504 | .detach_hba = fd_detach_hba, |
| 586 | .allocate_virtdevice = fd_allocate_virtdevice, | 505 | .alloc_device = fd_alloc_device, |
| 587 | .create_virtdevice = fd_create_virtdevice, | 506 | .configure_device = fd_configure_device, |
| 588 | .free_device = fd_free_device, | 507 | .free_device = fd_free_device, |
| 589 | .parse_cdb = fd_parse_cdb, | 508 | .parse_cdb = fd_parse_cdb, |
| 590 | .check_configfs_dev_params = fd_check_configfs_dev_params, | ||
| 591 | .set_configfs_dev_params = fd_set_configfs_dev_params, | 509 | .set_configfs_dev_params = fd_set_configfs_dev_params, |
| 592 | .show_configfs_dev_params = fd_show_configfs_dev_params, | 510 | .show_configfs_dev_params = fd_show_configfs_dev_params, |
| 593 | .get_device_rev = fd_get_device_rev, | 511 | .get_device_type = sbc_get_device_type, |
| 594 | .get_device_type = fd_get_device_type, | ||
| 595 | .get_blocks = fd_get_blocks, | 512 | .get_blocks = fd_get_blocks, |
| 596 | }; | 513 | }; |
| 597 | 514 | ||
diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h index 876ae53ef5b8..bc02b018ae46 100644 --- a/drivers/target/target_core_file.h +++ b/drivers/target/target_core_file.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #define FDBD_HAS_BUFFERED_IO_WCE 0x04 | 17 | #define FDBD_HAS_BUFFERED_IO_WCE 0x04 |
| 18 | 18 | ||
| 19 | struct fd_dev { | 19 | struct fd_dev { |
| 20 | struct se_device dev; | ||
| 21 | |||
| 20 | u32 fbd_flags; | 22 | u32 fbd_flags; |
| 21 | unsigned char fd_dev_name[FD_MAX_DEV_NAME]; | 23 | unsigned char fd_dev_name[FD_MAX_DEV_NAME]; |
| 22 | /* Unique Ramdisk Device ID in Ramdisk HBA */ | 24 | /* Unique Ramdisk Device ID in Ramdisk HBA */ |
diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c index 3dd1bd4b6f71..d2616cd48f1e 100644 --- a/drivers/target/target_core_hba.c +++ b/drivers/target/target_core_hba.c | |||
| @@ -3,10 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains the TCM HBA Transport related functions. | 4 | * This file contains the TCM HBA Transport related functions. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. | 6 | * (c) Copyright 2003-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 8 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 9 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 10 | * | 7 | * |
| 11 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 12 | * | 9 | * |
| @@ -113,7 +110,6 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags) | |||
| 113 | return ERR_PTR(-ENOMEM); | 110 | return ERR_PTR(-ENOMEM); |
| 114 | } | 111 | } |
| 115 | 112 | ||
| 116 | INIT_LIST_HEAD(&hba->hba_dev_list); | ||
| 117 | spin_lock_init(&hba->device_lock); | 113 | spin_lock_init(&hba->device_lock); |
| 118 | mutex_init(&hba->hba_access_mutex); | 114 | mutex_init(&hba->hba_access_mutex); |
| 119 | 115 | ||
| @@ -152,8 +148,7 @@ out_free_hba: | |||
| 152 | int | 148 | int |
| 153 | core_delete_hba(struct se_hba *hba) | 149 | core_delete_hba(struct se_hba *hba) |
| 154 | { | 150 | { |
| 155 | if (!list_empty(&hba->hba_dev_list)) | 151 | WARN_ON(hba->dev_count); |
| 156 | dump_stack(); | ||
| 157 | 152 | ||
| 158 | hba->transport->detach_hba(hba); | 153 | hba->transport->detach_hba(hba); |
| 159 | 154 | ||
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 57d7674c5013..b526d23dcd4f 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
| @@ -4,10 +4,7 @@ | |||
| 4 | * This file contains the Storage Engine <-> Linux BlockIO transport | 4 | * This file contains the Storage Engine <-> Linux BlockIO transport |
| 5 | * specific functions. | 5 | * specific functions. |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. | 7 | * (c) Copyright 2003-2012 RisingTide Systems LLC. |
| 8 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 9 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 10 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 11 | * | 8 | * |
| 12 | * Nicholas A. Bellinger <nab@kernel.org> | 9 | * Nicholas A. Bellinger <nab@kernel.org> |
| 13 | * | 10 | * |
| @@ -50,9 +47,13 @@ | |||
| 50 | #define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */ | 47 | #define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */ |
| 51 | #define IBLOCK_BIO_POOL_SIZE 128 | 48 | #define IBLOCK_BIO_POOL_SIZE 128 |
| 52 | 49 | ||
| 53 | static struct se_subsystem_api iblock_template; | 50 | static inline struct iblock_dev *IBLOCK_DEV(struct se_device *dev) |
| 51 | { | ||
| 52 | return container_of(dev, struct iblock_dev, dev); | ||
| 53 | } | ||
| 54 | |||
| 54 | 55 | ||
| 55 | static void iblock_bio_done(struct bio *, int); | 56 | static struct se_subsystem_api iblock_template; |
| 56 | 57 | ||
| 57 | /* iblock_attach_hba(): (Part of se_subsystem_api_t template) | 58 | /* iblock_attach_hba(): (Part of se_subsystem_api_t template) |
| 58 | * | 59 | * |
| @@ -70,7 +71,7 @@ static void iblock_detach_hba(struct se_hba *hba) | |||
| 70 | { | 71 | { |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name) | 74 | static struct se_device *iblock_alloc_device(struct se_hba *hba, const char *name) |
| 74 | { | 75 | { |
| 75 | struct iblock_dev *ib_dev = NULL; | 76 | struct iblock_dev *ib_dev = NULL; |
| 76 | 77 | ||
| @@ -82,40 +83,28 @@ static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name) | |||
| 82 | 83 | ||
| 83 | pr_debug( "IBLOCK: Allocated ib_dev for %s\n", name); | 84 | pr_debug( "IBLOCK: Allocated ib_dev for %s\n", name); |
| 84 | 85 | ||
| 85 | return ib_dev; | 86 | return &ib_dev->dev; |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | static struct se_device *iblock_create_virtdevice( | 89 | static int iblock_configure_device(struct se_device *dev) |
| 89 | struct se_hba *hba, | ||
| 90 | struct se_subsystem_dev *se_dev, | ||
| 91 | void *p) | ||
| 92 | { | 90 | { |
| 93 | struct iblock_dev *ib_dev = p; | 91 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
| 94 | struct se_device *dev; | ||
| 95 | struct se_dev_limits dev_limits; | ||
| 96 | struct block_device *bd = NULL; | ||
| 97 | struct request_queue *q; | 92 | struct request_queue *q; |
| 98 | struct queue_limits *limits; | 93 | struct block_device *bd = NULL; |
| 99 | u32 dev_flags = 0; | ||
| 100 | fmode_t mode; | 94 | fmode_t mode; |
| 101 | int ret = -EINVAL; | 95 | int ret = -ENOMEM; |
| 102 | 96 | ||
| 103 | if (!ib_dev) { | 97 | if (!(ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH)) { |
| 104 | pr_err("Unable to locate struct iblock_dev parameter\n"); | 98 | pr_err("Missing udev_path= parameters for IBLOCK\n"); |
| 105 | return ERR_PTR(ret); | 99 | return -EINVAL; |
| 106 | } | 100 | } |
| 107 | memset(&dev_limits, 0, sizeof(struct se_dev_limits)); | ||
| 108 | 101 | ||
| 109 | ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0); | 102 | ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0); |
| 110 | if (!ib_dev->ibd_bio_set) { | 103 | if (!ib_dev->ibd_bio_set) { |
| 111 | pr_err("IBLOCK: Unable to create bioset()\n"); | 104 | pr_err("IBLOCK: Unable to create bioset\n"); |
| 112 | return ERR_PTR(-ENOMEM); | 105 | goto out; |
| 113 | } | 106 | } |
| 114 | pr_debug("IBLOCK: Created bio_set()\n"); | 107 | |
| 115 | /* | ||
| 116 | * iblock_check_configfs_dev_params() ensures that ib_dev->ibd_udev_path | ||
| 117 | * must already have been set in order for echo 1 > $HBA/$DEV/enable to run. | ||
| 118 | */ | ||
| 119 | pr_debug( "IBLOCK: Claiming struct block_device: %s\n", | 108 | pr_debug( "IBLOCK: Claiming struct block_device: %s\n", |
| 120 | ib_dev->ibd_udev_path); | 109 | ib_dev->ibd_udev_path); |
| 121 | 110 | ||
| @@ -126,27 +115,15 @@ static struct se_device *iblock_create_virtdevice( | |||
| 126 | bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev); | 115 | bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev); |
| 127 | if (IS_ERR(bd)) { | 116 | if (IS_ERR(bd)) { |
| 128 | ret = PTR_ERR(bd); | 117 | ret = PTR_ERR(bd); |
| 129 | goto failed; | 118 | goto out_free_bioset; |
| 130 | } | 119 | } |
| 131 | /* | ||
| 132 | * Setup the local scope queue_limits from struct request_queue->limits | ||
| 133 | * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. | ||
| 134 | */ | ||
| 135 | q = bdev_get_queue(bd); | ||
| 136 | limits = &dev_limits.limits; | ||
| 137 | limits->logical_block_size = bdev_logical_block_size(bd); | ||
| 138 | limits->max_hw_sectors = UINT_MAX; | ||
| 139 | limits->max_sectors = UINT_MAX; | ||
| 140 | dev_limits.hw_queue_depth = q->nr_requests; | ||
| 141 | dev_limits.queue_depth = q->nr_requests; | ||
| 142 | |||
| 143 | ib_dev->ibd_bd = bd; | 120 | ib_dev->ibd_bd = bd; |
| 144 | 121 | ||
| 145 | dev = transport_add_device_to_core_hba(hba, | 122 | q = bdev_get_queue(bd); |
| 146 | &iblock_template, se_dev, dev_flags, ib_dev, | 123 | |
| 147 | &dev_limits, "IBLOCK", IBLOCK_VERSION); | 124 | dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); |
| 148 | if (!dev) | 125 | dev->dev_attrib.hw_max_sectors = UINT_MAX; |
| 149 | goto failed; | 126 | dev->dev_attrib.hw_queue_depth = q->nr_requests; |
| 150 | 127 | ||
| 151 | /* | 128 | /* |
| 152 | * Check if the underlying struct block_device request_queue supports | 129 | * Check if the underlying struct block_device request_queue supports |
| @@ -154,38 +131,41 @@ static struct se_device *iblock_create_virtdevice( | |||
| 154 | * in ATA and we need to set TPE=1 | 131 | * in ATA and we need to set TPE=1 |
| 155 | */ | 132 | */ |
| 156 | if (blk_queue_discard(q)) { | 133 | if (blk_queue_discard(q)) { |
| 157 | dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = | 134 | dev->dev_attrib.max_unmap_lba_count = |
| 158 | q->limits.max_discard_sectors; | 135 | q->limits.max_discard_sectors; |
| 136 | |||
| 159 | /* | 137 | /* |
| 160 | * Currently hardcoded to 1 in Linux/SCSI code.. | 138 | * Currently hardcoded to 1 in Linux/SCSI code.. |
| 161 | */ | 139 | */ |
| 162 | dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1; | 140 | dev->dev_attrib.max_unmap_block_desc_count = 1; |
| 163 | dev->se_sub_dev->se_dev_attrib.unmap_granularity = | 141 | dev->dev_attrib.unmap_granularity = |
| 164 | q->limits.discard_granularity >> 9; | 142 | q->limits.discard_granularity >> 9; |
| 165 | dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = | 143 | dev->dev_attrib.unmap_granularity_alignment = |
| 166 | q->limits.discard_alignment; | 144 | q->limits.discard_alignment; |
| 167 | 145 | ||
| 168 | pr_debug("IBLOCK: BLOCK Discard support available," | 146 | pr_debug("IBLOCK: BLOCK Discard support available," |
| 169 | " disabled by default\n"); | 147 | " disabled by default\n"); |
| 170 | } | 148 | } |
| 149 | /* | ||
| 150 | * Enable write same emulation for IBLOCK and use 0xFFFF as | ||
| 151 | * the smaller WRITE_SAME(10) only has a two-byte block count. | ||
| 152 | */ | ||
| 153 | dev->dev_attrib.max_write_same_len = 0xFFFF; | ||
| 171 | 154 | ||
| 172 | if (blk_queue_nonrot(q)) | 155 | if (blk_queue_nonrot(q)) |
| 173 | dev->se_sub_dev->se_dev_attrib.is_nonrot = 1; | 156 | dev->dev_attrib.is_nonrot = 1; |
| 174 | 157 | return 0; | |
| 175 | return dev; | ||
| 176 | 158 | ||
| 177 | failed: | 159 | out_free_bioset: |
| 178 | if (ib_dev->ibd_bio_set) { | 160 | bioset_free(ib_dev->ibd_bio_set); |
| 179 | bioset_free(ib_dev->ibd_bio_set); | 161 | ib_dev->ibd_bio_set = NULL; |
| 180 | ib_dev->ibd_bio_set = NULL; | 162 | out: |
| 181 | } | 163 | return ret; |
| 182 | ib_dev->ibd_bd = NULL; | ||
| 183 | return ERR_PTR(ret); | ||
| 184 | } | 164 | } |
| 185 | 165 | ||
| 186 | static void iblock_free_device(void *p) | 166 | static void iblock_free_device(struct se_device *dev) |
| 187 | { | 167 | { |
| 188 | struct iblock_dev *ib_dev = p; | 168 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
| 189 | 169 | ||
| 190 | if (ib_dev->ibd_bd != NULL) | 170 | if (ib_dev->ibd_bd != NULL) |
| 191 | blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); | 171 | blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); |
| @@ -203,12 +183,12 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( | |||
| 203 | bdev_logical_block_size(bd)) - 1); | 183 | bdev_logical_block_size(bd)) - 1); |
| 204 | u32 block_size = bdev_logical_block_size(bd); | 184 | u32 block_size = bdev_logical_block_size(bd); |
| 205 | 185 | ||
| 206 | if (block_size == dev->se_sub_dev->se_dev_attrib.block_size) | 186 | if (block_size == dev->dev_attrib.block_size) |
| 207 | return blocks_long; | 187 | return blocks_long; |
| 208 | 188 | ||
| 209 | switch (block_size) { | 189 | switch (block_size) { |
| 210 | case 4096: | 190 | case 4096: |
| 211 | switch (dev->se_sub_dev->se_dev_attrib.block_size) { | 191 | switch (dev->dev_attrib.block_size) { |
| 212 | case 2048: | 192 | case 2048: |
| 213 | blocks_long <<= 1; | 193 | blocks_long <<= 1; |
| 214 | break; | 194 | break; |
| @@ -222,7 +202,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( | |||
| 222 | } | 202 | } |
| 223 | break; | 203 | break; |
| 224 | case 2048: | 204 | case 2048: |
| 225 | switch (dev->se_sub_dev->se_dev_attrib.block_size) { | 205 | switch (dev->dev_attrib.block_size) { |
| 226 | case 4096: | 206 | case 4096: |
| 227 | blocks_long >>= 1; | 207 | blocks_long >>= 1; |
| 228 | break; | 208 | break; |
| @@ -237,7 +217,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( | |||
| 237 | } | 217 | } |
| 238 | break; | 218 | break; |
| 239 | case 1024: | 219 | case 1024: |
| 240 | switch (dev->se_sub_dev->se_dev_attrib.block_size) { | 220 | switch (dev->dev_attrib.block_size) { |
| 241 | case 4096: | 221 | case 4096: |
| 242 | blocks_long >>= 2; | 222 | blocks_long >>= 2; |
| 243 | break; | 223 | break; |
| @@ -252,7 +232,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( | |||
| 252 | } | 232 | } |
| 253 | break; | 233 | break; |
| 254 | case 512: | 234 | case 512: |
| 255 | switch (dev->se_sub_dev->se_dev_attrib.block_size) { | 235 | switch (dev->dev_attrib.block_size) { |
| 256 | case 4096: | 236 | case 4096: |
| 257 | blocks_long >>= 3; | 237 | blocks_long >>= 3; |
| 258 | break; | 238 | break; |
| @@ -273,6 +253,87 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( | |||
| 273 | return blocks_long; | 253 | return blocks_long; |
| 274 | } | 254 | } |
| 275 | 255 | ||
| 256 | static void iblock_complete_cmd(struct se_cmd *cmd) | ||
| 257 | { | ||
| 258 | struct iblock_req *ibr = cmd->priv; | ||
| 259 | u8 status; | ||
| 260 | |||
| 261 | if (!atomic_dec_and_test(&ibr->pending)) | ||
| 262 | return; | ||
| 263 | |||
| 264 | if (atomic_read(&ibr->ib_bio_err_cnt)) | ||
| 265 | status = SAM_STAT_CHECK_CONDITION; | ||
| 266 | else | ||
| 267 | status = SAM_STAT_GOOD; | ||
| 268 | |||
| 269 | target_complete_cmd(cmd, status); | ||
| 270 | kfree(ibr); | ||
| 271 | } | ||
| 272 | |||
| 273 | static void iblock_bio_done(struct bio *bio, int err) | ||
| 274 | { | ||
| 275 | struct se_cmd *cmd = bio->bi_private; | ||
| 276 | struct iblock_req *ibr = cmd->priv; | ||
| 277 | |||
| 278 | /* | ||
| 279 | * Set -EIO if !BIO_UPTODATE and the passed is still err=0 | ||
| 280 | */ | ||
| 281 | if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err) | ||
| 282 | err = -EIO; | ||
| 283 | |||
| 284 | if (err != 0) { | ||
| 285 | pr_err("test_bit(BIO_UPTODATE) failed for bio: %p," | ||
| 286 | " err: %d\n", bio, err); | ||
| 287 | /* | ||
| 288 | * Bump the ib_bio_err_cnt and release bio. | ||
| 289 | */ | ||
| 290 | atomic_inc(&ibr->ib_bio_err_cnt); | ||
| 291 | smp_mb__after_atomic_inc(); | ||
| 292 | } | ||
| 293 | |||
| 294 | bio_put(bio); | ||
| 295 | |||
| 296 | iblock_complete_cmd(cmd); | ||
| 297 | } | ||
| 298 | |||
| 299 | static struct bio * | ||
| 300 | iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) | ||
| 301 | { | ||
| 302 | struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); | ||
| 303 | struct bio *bio; | ||
| 304 | |||
| 305 | /* | ||
| 306 | * Only allocate as many vector entries as the bio code allows us to, | ||
| 307 | * we'll loop later on until we have handled the whole request. | ||
| 308 | */ | ||
| 309 | if (sg_num > BIO_MAX_PAGES) | ||
| 310 | sg_num = BIO_MAX_PAGES; | ||
| 311 | |||
| 312 | bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set); | ||
| 313 | if (!bio) { | ||
| 314 | pr_err("Unable to allocate memory for bio\n"); | ||
| 315 | return NULL; | ||
| 316 | } | ||
| 317 | |||
| 318 | bio->bi_bdev = ib_dev->ibd_bd; | ||
| 319 | bio->bi_private = cmd; | ||
| 320 | bio->bi_end_io = &iblock_bio_done; | ||
| 321 | bio->bi_sector = lba; | ||
| 322 | |||
| 323 | return bio; | ||
| 324 | } | ||
| 325 | |||
| 326 | static void iblock_submit_bios(struct bio_list *list, int rw) | ||
| 327 | { | ||
| 328 | struct blk_plug plug; | ||
| 329 | struct bio *bio; | ||
| 330 | |||
| 331 | blk_start_plug(&plug); | ||
| 332 | while ((bio = bio_list_pop(list))) | ||
| 333 | submit_bio(rw, bio); | ||
| 334 | blk_finish_plug(&plug); | ||
| 335 | } | ||
| 336 | |||
| 276 | static void iblock_end_io_flush(struct bio *bio, int err) | 337 | static void iblock_end_io_flush(struct bio *bio, int err) |
| 277 | { | 338 | { |
| 278 | struct se_cmd *cmd = bio->bi_private; | 339 | struct se_cmd *cmd = bio->bi_private; |
| @@ -281,13 +342,10 @@ static void iblock_end_io_flush(struct bio *bio, int err) | |||
| 281 | pr_err("IBLOCK: cache flush failed: %d\n", err); | 342 | pr_err("IBLOCK: cache flush failed: %d\n", err); |
| 282 | 343 | ||
| 283 | if (cmd) { | 344 | if (cmd) { |
| 284 | if (err) { | 345 | if (err) |
| 285 | cmd->scsi_sense_reason = | ||
| 286 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 287 | target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); | 346 | target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); |
| 288 | } else { | 347 | else |
| 289 | target_complete_cmd(cmd, SAM_STAT_GOOD); | 348 | target_complete_cmd(cmd, SAM_STAT_GOOD); |
| 290 | } | ||
| 291 | } | 349 | } |
| 292 | 350 | ||
| 293 | bio_put(bio); | 351 | bio_put(bio); |
| @@ -297,9 +355,10 @@ static void iblock_end_io_flush(struct bio *bio, int err) | |||
| 297 | * Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must | 355 | * Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must |
| 298 | * always flush the whole cache. | 356 | * always flush the whole cache. |
| 299 | */ | 357 | */ |
| 300 | static int iblock_execute_sync_cache(struct se_cmd *cmd) | 358 | static sense_reason_t |
| 359 | iblock_execute_sync_cache(struct se_cmd *cmd) | ||
| 301 | { | 360 | { |
| 302 | struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr; | 361 | struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); |
| 303 | int immed = (cmd->t_task_cdb[1] & 0x2); | 362 | int immed = (cmd->t_task_cdb[1] & 0x2); |
| 304 | struct bio *bio; | 363 | struct bio *bio; |
| 305 | 364 | ||
| @@ -319,25 +378,27 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd) | |||
| 319 | return 0; | 378 | return 0; |
| 320 | } | 379 | } |
| 321 | 380 | ||
| 322 | static int iblock_execute_unmap(struct se_cmd *cmd) | 381 | static sense_reason_t |
| 382 | iblock_execute_unmap(struct se_cmd *cmd) | ||
| 323 | { | 383 | { |
| 324 | struct se_device *dev = cmd->se_dev; | 384 | struct se_device *dev = cmd->se_dev; |
| 325 | struct iblock_dev *ibd = dev->dev_ptr; | 385 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
| 326 | unsigned char *buf, *ptr = NULL; | 386 | unsigned char *buf, *ptr = NULL; |
| 327 | sector_t lba; | 387 | sector_t lba; |
| 328 | int size; | 388 | int size; |
| 329 | u32 range; | 389 | u32 range; |
| 330 | int ret = 0; | 390 | sense_reason_t ret = 0; |
| 331 | int dl, bd_dl; | 391 | int dl, bd_dl, err; |
| 332 | 392 | ||
| 333 | if (cmd->data_length < 8) { | 393 | if (cmd->data_length < 8) { |
| 334 | pr_warn("UNMAP parameter list length %u too small\n", | 394 | pr_warn("UNMAP parameter list length %u too small\n", |
| 335 | cmd->data_length); | 395 | cmd->data_length); |
| 336 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 396 | return TCM_INVALID_PARAMETER_LIST; |
| 337 | return -EINVAL; | ||
| 338 | } | 397 | } |
| 339 | 398 | ||
| 340 | buf = transport_kmap_data_sg(cmd); | 399 | buf = transport_kmap_data_sg(cmd); |
| 400 | if (!buf) | ||
| 401 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 341 | 402 | ||
| 342 | dl = get_unaligned_be16(&buf[0]); | 403 | dl = get_unaligned_be16(&buf[0]); |
| 343 | bd_dl = get_unaligned_be16(&buf[2]); | 404 | bd_dl = get_unaligned_be16(&buf[2]); |
| @@ -349,9 +410,8 @@ static int iblock_execute_unmap(struct se_cmd *cmd) | |||
| 349 | else | 410 | else |
| 350 | size = bd_dl; | 411 | size = bd_dl; |
| 351 | 412 | ||
| 352 | if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { | 413 | if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { |
| 353 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 414 | ret = TCM_INVALID_PARAMETER_LIST; |
| 354 | ret = -EINVAL; | ||
| 355 | goto err; | 415 | goto err; |
| 356 | } | 416 | } |
| 357 | 417 | ||
| @@ -366,23 +426,22 @@ static int iblock_execute_unmap(struct se_cmd *cmd) | |||
| 366 | pr_debug("UNMAP: Using lba: %llu and range: %u\n", | 426 | pr_debug("UNMAP: Using lba: %llu and range: %u\n", |
| 367 | (unsigned long long)lba, range); | 427 | (unsigned long long)lba, range); |
| 368 | 428 | ||
| 369 | if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) { | 429 | if (range > dev->dev_attrib.max_unmap_lba_count) { |
| 370 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 430 | ret = TCM_INVALID_PARAMETER_LIST; |
| 371 | ret = -EINVAL; | ||
| 372 | goto err; | 431 | goto err; |
| 373 | } | 432 | } |
| 374 | 433 | ||
| 375 | if (lba + range > dev->transport->get_blocks(dev) + 1) { | 434 | if (lba + range > dev->transport->get_blocks(dev) + 1) { |
| 376 | cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; | 435 | ret = TCM_ADDRESS_OUT_OF_RANGE; |
| 377 | ret = -EINVAL; | ||
| 378 | goto err; | 436 | goto err; |
| 379 | } | 437 | } |
| 380 | 438 | ||
| 381 | ret = blkdev_issue_discard(ibd->ibd_bd, lba, range, | 439 | err = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, |
| 382 | GFP_KERNEL, 0); | 440 | GFP_KERNEL, 0); |
| 383 | if (ret < 0) { | 441 | if (err < 0) { |
| 384 | pr_err("blkdev_issue_discard() failed: %d\n", | 442 | pr_err("blkdev_issue_discard() failed: %d\n", |
| 385 | ret); | 443 | err); |
| 444 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 386 | goto err; | 445 | goto err; |
| 387 | } | 446 | } |
| 388 | 447 | ||
| @@ -397,23 +456,86 @@ err: | |||
| 397 | return ret; | 456 | return ret; |
| 398 | } | 457 | } |
| 399 | 458 | ||
| 400 | static int iblock_execute_write_same(struct se_cmd *cmd) | 459 | static sense_reason_t |
| 460 | iblock_execute_write_same_unmap(struct se_cmd *cmd) | ||
| 401 | { | 461 | { |
| 402 | struct iblock_dev *ibd = cmd->se_dev->dev_ptr; | 462 | struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); |
| 403 | int ret; | 463 | int rc; |
| 404 | 464 | ||
| 405 | ret = blkdev_issue_discard(ibd->ibd_bd, cmd->t_task_lba, | 465 | rc = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba, |
| 406 | spc_get_write_same_sectors(cmd), GFP_KERNEL, | 466 | spc_get_write_same_sectors(cmd), GFP_KERNEL, 0); |
| 407 | 0); | 467 | if (rc < 0) { |
| 408 | if (ret < 0) { | 468 | pr_warn("blkdev_issue_discard() failed: %d\n", rc); |
| 409 | pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n"); | 469 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 410 | return ret; | ||
| 411 | } | 470 | } |
| 412 | 471 | ||
| 413 | target_complete_cmd(cmd, GOOD); | 472 | target_complete_cmd(cmd, GOOD); |
| 414 | return 0; | 473 | return 0; |
| 415 | } | 474 | } |
| 416 | 475 | ||
| 476 | static sense_reason_t | ||
| 477 | iblock_execute_write_same(struct se_cmd *cmd) | ||
| 478 | { | ||
| 479 | struct iblock_req *ibr; | ||
| 480 | struct scatterlist *sg; | ||
| 481 | struct bio *bio; | ||
| 482 | struct bio_list list; | ||
| 483 | sector_t block_lba = cmd->t_task_lba; | ||
| 484 | sector_t sectors = spc_get_write_same_sectors(cmd); | ||
| 485 | |||
| 486 | sg = &cmd->t_data_sg[0]; | ||
| 487 | |||
| 488 | if (cmd->t_data_nents > 1 || | ||
| 489 | sg->length != cmd->se_dev->dev_attrib.block_size) { | ||
| 490 | pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u" | ||
| 491 | " block_size: %u\n", cmd->t_data_nents, sg->length, | ||
| 492 | cmd->se_dev->dev_attrib.block_size); | ||
| 493 | return TCM_INVALID_CDB_FIELD; | ||
| 494 | } | ||
| 495 | |||
| 496 | ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); | ||
| 497 | if (!ibr) | ||
| 498 | goto fail; | ||
| 499 | cmd->priv = ibr; | ||
| 500 | |||
| 501 | bio = iblock_get_bio(cmd, block_lba, 1); | ||
| 502 | if (!bio) | ||
| 503 | goto fail_free_ibr; | ||
| 504 | |||
| 505 | bio_list_init(&list); | ||
| 506 | bio_list_add(&list, bio); | ||
| 507 | |||
| 508 | atomic_set(&ibr->pending, 1); | ||
| 509 | |||
| 510 | while (sectors) { | ||
| 511 | while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) | ||
| 512 | != sg->length) { | ||
| 513 | |||
| 514 | bio = iblock_get_bio(cmd, block_lba, 1); | ||
| 515 | if (!bio) | ||
| 516 | goto fail_put_bios; | ||
| 517 | |||
| 518 | atomic_inc(&ibr->pending); | ||
| 519 | bio_list_add(&list, bio); | ||
| 520 | } | ||
| 521 | |||
| 522 | /* Always in 512 byte units for Linux/Block */ | ||
| 523 | block_lba += sg->length >> IBLOCK_LBA_SHIFT; | ||
| 524 | sectors -= 1; | ||
| 525 | } | ||
| 526 | |||
| 527 | iblock_submit_bios(&list, WRITE); | ||
| 528 | return 0; | ||
| 529 | |||
| 530 | fail_put_bios: | ||
| 531 | while ((bio = bio_list_pop(&list))) | ||
| 532 | bio_put(bio); | ||
| 533 | fail_free_ibr: | ||
| 534 | kfree(ibr); | ||
| 535 | fail: | ||
| 536 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 537 | } | ||
| 538 | |||
| 417 | enum { | 539 | enum { |
| 418 | Opt_udev_path, Opt_readonly, Opt_force, Opt_err | 540 | Opt_udev_path, Opt_readonly, Opt_force, Opt_err |
| 419 | }; | 541 | }; |
| @@ -425,11 +547,10 @@ static match_table_t tokens = { | |||
| 425 | {Opt_err, NULL} | 547 | {Opt_err, NULL} |
| 426 | }; | 548 | }; |
| 427 | 549 | ||
| 428 | static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba, | 550 | static ssize_t iblock_set_configfs_dev_params(struct se_device *dev, |
| 429 | struct se_subsystem_dev *se_dev, | 551 | const char *page, ssize_t count) |
| 430 | const char *page, ssize_t count) | ||
| 431 | { | 552 | { |
| 432 | struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr; | 553 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
| 433 | char *orig, *ptr, *arg_p, *opts; | 554 | char *orig, *ptr, *arg_p, *opts; |
| 434 | substring_t args[MAX_OPT_ARGS]; | 555 | substring_t args[MAX_OPT_ARGS]; |
| 435 | int ret = 0, token; | 556 | int ret = 0, token; |
| @@ -491,43 +612,26 @@ out: | |||
| 491 | return (!ret) ? count : ret; | 612 | return (!ret) ? count : ret; |
| 492 | } | 613 | } |
| 493 | 614 | ||
| 494 | static ssize_t iblock_check_configfs_dev_params( | 615 | static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b) |
| 495 | struct se_hba *hba, | ||
| 496 | struct se_subsystem_dev *se_dev) | ||
| 497 | { | 616 | { |
| 498 | struct iblock_dev *ibd = se_dev->se_dev_su_ptr; | 617 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
| 499 | 618 | struct block_device *bd = ib_dev->ibd_bd; | |
| 500 | if (!(ibd->ibd_flags & IBDF_HAS_UDEV_PATH)) { | ||
| 501 | pr_err("Missing udev_path= parameters for IBLOCK\n"); | ||
| 502 | return -EINVAL; | ||
| 503 | } | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | static ssize_t iblock_show_configfs_dev_params( | ||
| 509 | struct se_hba *hba, | ||
| 510 | struct se_subsystem_dev *se_dev, | ||
| 511 | char *b) | ||
| 512 | { | ||
| 513 | struct iblock_dev *ibd = se_dev->se_dev_su_ptr; | ||
| 514 | struct block_device *bd = ibd->ibd_bd; | ||
| 515 | char buf[BDEVNAME_SIZE]; | 619 | char buf[BDEVNAME_SIZE]; |
| 516 | ssize_t bl = 0; | 620 | ssize_t bl = 0; |
| 517 | 621 | ||
| 518 | if (bd) | 622 | if (bd) |
| 519 | bl += sprintf(b + bl, "iBlock device: %s", | 623 | bl += sprintf(b + bl, "iBlock device: %s", |
| 520 | bdevname(bd, buf)); | 624 | bdevname(bd, buf)); |
| 521 | if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH) | 625 | if (ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH) |
| 522 | bl += sprintf(b + bl, " UDEV PATH: %s", | 626 | bl += sprintf(b + bl, " UDEV PATH: %s", |
| 523 | ibd->ibd_udev_path); | 627 | ib_dev->ibd_udev_path); |
| 524 | bl += sprintf(b + bl, " readonly: %d\n", ibd->ibd_readonly); | 628 | bl += sprintf(b + bl, " readonly: %d\n", ib_dev->ibd_readonly); |
| 525 | 629 | ||
| 526 | bl += sprintf(b + bl, " "); | 630 | bl += sprintf(b + bl, " "); |
| 527 | if (bd) { | 631 | if (bd) { |
| 528 | bl += sprintf(b + bl, "Major: %d Minor: %d %s\n", | 632 | bl += sprintf(b + bl, "Major: %d Minor: %d %s\n", |
| 529 | MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ? | 633 | MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ? |
| 530 | "" : (bd->bd_holder == ibd) ? | 634 | "" : (bd->bd_holder == ib_dev) ? |
| 531 | "CLAIMED: IBLOCK" : "CLAIMED: OS"); | 635 | "CLAIMED: IBLOCK" : "CLAIMED: OS"); |
| 532 | } else { | 636 | } else { |
| 533 | bl += sprintf(b + bl, "Major: 0 Minor: 0\n"); | 637 | bl += sprintf(b + bl, "Major: 0 Minor: 0\n"); |
| @@ -536,61 +640,8 @@ static ssize_t iblock_show_configfs_dev_params( | |||
| 536 | return bl; | 640 | return bl; |
| 537 | } | 641 | } |
| 538 | 642 | ||
| 539 | static void iblock_complete_cmd(struct se_cmd *cmd) | 643 | static sense_reason_t |
| 540 | { | 644 | iblock_execute_rw(struct se_cmd *cmd) |
| 541 | struct iblock_req *ibr = cmd->priv; | ||
| 542 | u8 status; | ||
| 543 | |||
| 544 | if (!atomic_dec_and_test(&ibr->pending)) | ||
| 545 | return; | ||
| 546 | |||
| 547 | if (atomic_read(&ibr->ib_bio_err_cnt)) | ||
| 548 | status = SAM_STAT_CHECK_CONDITION; | ||
| 549 | else | ||
| 550 | status = SAM_STAT_GOOD; | ||
| 551 | |||
| 552 | target_complete_cmd(cmd, status); | ||
| 553 | kfree(ibr); | ||
| 554 | } | ||
| 555 | |||
| 556 | static struct bio * | ||
| 557 | iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) | ||
| 558 | { | ||
| 559 | struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr; | ||
| 560 | struct bio *bio; | ||
| 561 | |||
| 562 | /* | ||
| 563 | * Only allocate as many vector entries as the bio code allows us to, | ||
| 564 | * we'll loop later on until we have handled the whole request. | ||
| 565 | */ | ||
| 566 | if (sg_num > BIO_MAX_PAGES) | ||
| 567 | sg_num = BIO_MAX_PAGES; | ||
| 568 | |||
| 569 | bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set); | ||
| 570 | if (!bio) { | ||
| 571 | pr_err("Unable to allocate memory for bio\n"); | ||
| 572 | return NULL; | ||
| 573 | } | ||
| 574 | |||
| 575 | bio->bi_bdev = ib_dev->ibd_bd; | ||
| 576 | bio->bi_private = cmd; | ||
| 577 | bio->bi_end_io = &iblock_bio_done; | ||
| 578 | bio->bi_sector = lba; | ||
| 579 | return bio; | ||
| 580 | } | ||
| 581 | |||
| 582 | static void iblock_submit_bios(struct bio_list *list, int rw) | ||
| 583 | { | ||
| 584 | struct blk_plug plug; | ||
| 585 | struct bio *bio; | ||
| 586 | |||
| 587 | blk_start_plug(&plug); | ||
| 588 | while ((bio = bio_list_pop(list))) | ||
| 589 | submit_bio(rw, bio); | ||
| 590 | blk_finish_plug(&plug); | ||
| 591 | } | ||
| 592 | |||
| 593 | static int iblock_execute_rw(struct se_cmd *cmd) | ||
| 594 | { | 645 | { |
| 595 | struct scatterlist *sgl = cmd->t_data_sg; | 646 | struct scatterlist *sgl = cmd->t_data_sg; |
| 596 | u32 sgl_nents = cmd->t_data_nents; | 647 | u32 sgl_nents = cmd->t_data_nents; |
| @@ -611,8 +662,8 @@ static int iblock_execute_rw(struct se_cmd *cmd) | |||
| 611 | * Force data to disk if we pretend to not have a volatile | 662 | * Force data to disk if we pretend to not have a volatile |
| 612 | * write cache, or the initiator set the Force Unit Access bit. | 663 | * write cache, or the initiator set the Force Unit Access bit. |
| 613 | */ | 664 | */ |
| 614 | if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 || | 665 | if (dev->dev_attrib.emulate_write_cache == 0 || |
| 615 | (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && | 666 | (dev->dev_attrib.emulate_fua_write > 0 && |
| 616 | (cmd->se_cmd_flags & SCF_FUA))) | 667 | (cmd->se_cmd_flags & SCF_FUA))) |
| 617 | rw = WRITE_FUA; | 668 | rw = WRITE_FUA; |
| 618 | else | 669 | else |
| @@ -625,19 +676,18 @@ static int iblock_execute_rw(struct se_cmd *cmd) | |||
| 625 | * Convert the blocksize advertised to the initiator to the 512 byte | 676 | * Convert the blocksize advertised to the initiator to the 512 byte |
| 626 | * units unconditionally used by the Linux block layer. | 677 | * units unconditionally used by the Linux block layer. |
| 627 | */ | 678 | */ |
| 628 | if (dev->se_sub_dev->se_dev_attrib.block_size == 4096) | 679 | if (dev->dev_attrib.block_size == 4096) |
| 629 | block_lba = (cmd->t_task_lba << 3); | 680 | block_lba = (cmd->t_task_lba << 3); |
| 630 | else if (dev->se_sub_dev->se_dev_attrib.block_size == 2048) | 681 | else if (dev->dev_attrib.block_size == 2048) |
| 631 | block_lba = (cmd->t_task_lba << 2); | 682 | block_lba = (cmd->t_task_lba << 2); |
| 632 | else if (dev->se_sub_dev->se_dev_attrib.block_size == 1024) | 683 | else if (dev->dev_attrib.block_size == 1024) |
| 633 | block_lba = (cmd->t_task_lba << 1); | 684 | block_lba = (cmd->t_task_lba << 1); |
| 634 | else if (dev->se_sub_dev->se_dev_attrib.block_size == 512) | 685 | else if (dev->dev_attrib.block_size == 512) |
| 635 | block_lba = cmd->t_task_lba; | 686 | block_lba = cmd->t_task_lba; |
| 636 | else { | 687 | else { |
| 637 | pr_err("Unsupported SCSI -> BLOCK LBA conversion:" | 688 | pr_err("Unsupported SCSI -> BLOCK LBA conversion:" |
| 638 | " %u\n", dev->se_sub_dev->se_dev_attrib.block_size); | 689 | " %u\n", dev->dev_attrib.block_size); |
| 639 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 690 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 640 | return -ENOSYS; | ||
| 641 | } | 691 | } |
| 642 | 692 | ||
| 643 | ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); | 693 | ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); |
| @@ -697,83 +747,48 @@ fail_put_bios: | |||
| 697 | bio_put(bio); | 747 | bio_put(bio); |
| 698 | fail_free_ibr: | 748 | fail_free_ibr: |
| 699 | kfree(ibr); | 749 | kfree(ibr); |
| 700 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 701 | fail: | 750 | fail: |
| 702 | return -ENOMEM; | 751 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 703 | } | ||
| 704 | |||
| 705 | static u32 iblock_get_device_rev(struct se_device *dev) | ||
| 706 | { | ||
| 707 | return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ | ||
| 708 | } | ||
| 709 | |||
| 710 | static u32 iblock_get_device_type(struct se_device *dev) | ||
| 711 | { | ||
| 712 | return TYPE_DISK; | ||
| 713 | } | 752 | } |
| 714 | 753 | ||
| 715 | static sector_t iblock_get_blocks(struct se_device *dev) | 754 | static sector_t iblock_get_blocks(struct se_device *dev) |
| 716 | { | 755 | { |
| 717 | struct iblock_dev *ibd = dev->dev_ptr; | 756 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
| 718 | struct block_device *bd = ibd->ibd_bd; | 757 | struct block_device *bd = ib_dev->ibd_bd; |
| 719 | struct request_queue *q = bdev_get_queue(bd); | 758 | struct request_queue *q = bdev_get_queue(bd); |
| 720 | 759 | ||
| 721 | return iblock_emulate_read_cap_with_block_size(dev, bd, q); | 760 | return iblock_emulate_read_cap_with_block_size(dev, bd, q); |
| 722 | } | 761 | } |
| 723 | 762 | ||
| 724 | static void iblock_bio_done(struct bio *bio, int err) | 763 | static struct sbc_ops iblock_sbc_ops = { |
| 725 | { | ||
| 726 | struct se_cmd *cmd = bio->bi_private; | ||
| 727 | struct iblock_req *ibr = cmd->priv; | ||
| 728 | |||
| 729 | /* | ||
| 730 | * Set -EIO if !BIO_UPTODATE and the passed is still err=0 | ||
| 731 | */ | ||
| 732 | if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err) | ||
| 733 | err = -EIO; | ||
| 734 | |||
| 735 | if (err != 0) { | ||
| 736 | pr_err("test_bit(BIO_UPTODATE) failed for bio: %p," | ||
| 737 | " err: %d\n", bio, err); | ||
| 738 | /* | ||
| 739 | * Bump the ib_bio_err_cnt and release bio. | ||
| 740 | */ | ||
| 741 | atomic_inc(&ibr->ib_bio_err_cnt); | ||
| 742 | smp_mb__after_atomic_inc(); | ||
| 743 | } | ||
| 744 | |||
| 745 | bio_put(bio); | ||
| 746 | |||
| 747 | iblock_complete_cmd(cmd); | ||
| 748 | } | ||
| 749 | |||
| 750 | static struct spc_ops iblock_spc_ops = { | ||
| 751 | .execute_rw = iblock_execute_rw, | 764 | .execute_rw = iblock_execute_rw, |
| 752 | .execute_sync_cache = iblock_execute_sync_cache, | 765 | .execute_sync_cache = iblock_execute_sync_cache, |
| 753 | .execute_write_same = iblock_execute_write_same, | 766 | .execute_write_same = iblock_execute_write_same, |
| 767 | .execute_write_same_unmap = iblock_execute_write_same_unmap, | ||
| 754 | .execute_unmap = iblock_execute_unmap, | 768 | .execute_unmap = iblock_execute_unmap, |
| 755 | }; | 769 | }; |
| 756 | 770 | ||
| 757 | static int iblock_parse_cdb(struct se_cmd *cmd) | 771 | static sense_reason_t |
| 772 | iblock_parse_cdb(struct se_cmd *cmd) | ||
| 758 | { | 773 | { |
| 759 | return sbc_parse_cdb(cmd, &iblock_spc_ops); | 774 | return sbc_parse_cdb(cmd, &iblock_sbc_ops); |
| 760 | } | 775 | } |
| 761 | 776 | ||
| 762 | static struct se_subsystem_api iblock_template = { | 777 | static struct se_subsystem_api iblock_template = { |
| 763 | .name = "iblock", | 778 | .name = "iblock", |
| 779 | .inquiry_prod = "IBLOCK", | ||
| 780 | .inquiry_rev = IBLOCK_VERSION, | ||
| 764 | .owner = THIS_MODULE, | 781 | .owner = THIS_MODULE, |
| 765 | .transport_type = TRANSPORT_PLUGIN_VHBA_PDEV, | 782 | .transport_type = TRANSPORT_PLUGIN_VHBA_PDEV, |
| 766 | .attach_hba = iblock_attach_hba, | 783 | .attach_hba = iblock_attach_hba, |
| 767 | .detach_hba = iblock_detach_hba, | 784 | .detach_hba = iblock_detach_hba, |
| 768 | .allocate_virtdevice = iblock_allocate_virtdevice, | 785 | .alloc_device = iblock_alloc_device, |
| 769 | .create_virtdevice = iblock_create_virtdevice, | 786 | .configure_device = iblock_configure_device, |
| 770 | .free_device = iblock_free_device, | 787 | .free_device = iblock_free_device, |
| 771 | .parse_cdb = iblock_parse_cdb, | 788 | .parse_cdb = iblock_parse_cdb, |
| 772 | .check_configfs_dev_params = iblock_check_configfs_dev_params, | ||
| 773 | .set_configfs_dev_params = iblock_set_configfs_dev_params, | 789 | .set_configfs_dev_params = iblock_set_configfs_dev_params, |
| 774 | .show_configfs_dev_params = iblock_show_configfs_dev_params, | 790 | .show_configfs_dev_params = iblock_show_configfs_dev_params, |
| 775 | .get_device_rev = iblock_get_device_rev, | 791 | .get_device_type = sbc_get_device_type, |
| 776 | .get_device_type = iblock_get_device_type, | ||
| 777 | .get_blocks = iblock_get_blocks, | 792 | .get_blocks = iblock_get_blocks, |
| 778 | }; | 793 | }; |
| 779 | 794 | ||
diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h index 533627ae79ec..01c2afd81500 100644 --- a/drivers/target/target_core_iblock.h +++ b/drivers/target/target_core_iblock.h | |||
| @@ -14,6 +14,7 @@ struct iblock_req { | |||
| 14 | #define IBDF_HAS_UDEV_PATH 0x01 | 14 | #define IBDF_HAS_UDEV_PATH 0x01 |
| 15 | 15 | ||
| 16 | struct iblock_dev { | 16 | struct iblock_dev { |
| 17 | struct se_device dev; | ||
| 17 | unsigned char ibd_udev_path[SE_UDEV_PATH_LEN]; | 18 | unsigned char ibd_udev_path[SE_UDEV_PATH_LEN]; |
| 18 | u32 ibd_flags; | 19 | u32 ibd_flags; |
| 19 | struct bio_set *ibd_bio_set; | 20 | struct bio_set *ibd_bio_set; |
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 0fd428225d11..93e9c1f580b0 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h | |||
| @@ -19,18 +19,12 @@ int core_dev_export(struct se_device *, struct se_portal_group *, | |||
| 19 | struct se_lun *); | 19 | struct se_lun *); |
| 20 | void core_dev_unexport(struct se_device *, struct se_portal_group *, | 20 | void core_dev_unexport(struct se_device *, struct se_portal_group *, |
| 21 | struct se_lun *); | 21 | struct se_lun *); |
| 22 | int target_report_luns(struct se_cmd *); | ||
| 23 | void se_release_device_for_hba(struct se_device *); | ||
| 24 | void se_release_vpd_for_dev(struct se_device *); | ||
| 25 | int se_free_virtual_device(struct se_device *, struct se_hba *); | ||
| 26 | int se_dev_check_online(struct se_device *); | ||
| 27 | int se_dev_check_shutdown(struct se_device *); | ||
| 28 | void se_dev_set_default_attribs(struct se_device *, struct se_dev_limits *); | ||
| 29 | int se_dev_set_task_timeout(struct se_device *, u32); | 22 | int se_dev_set_task_timeout(struct se_device *, u32); |
| 30 | int se_dev_set_max_unmap_lba_count(struct se_device *, u32); | 23 | int se_dev_set_max_unmap_lba_count(struct se_device *, u32); |
| 31 | int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); | 24 | int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); |
| 32 | int se_dev_set_unmap_granularity(struct se_device *, u32); | 25 | int se_dev_set_unmap_granularity(struct se_device *, u32); |
| 33 | int se_dev_set_unmap_granularity_alignment(struct se_device *, u32); | 26 | int se_dev_set_unmap_granularity_alignment(struct se_device *, u32); |
| 27 | int se_dev_set_max_write_same_len(struct se_device *, u32); | ||
| 34 | int se_dev_set_emulate_dpo(struct se_device *, int); | 28 | int se_dev_set_emulate_dpo(struct se_device *, int); |
| 35 | int se_dev_set_emulate_fua_write(struct se_device *, int); | 29 | int se_dev_set_emulate_fua_write(struct se_device *, int); |
| 36 | int se_dev_set_emulate_fua_read(struct se_device *, int); | 30 | int se_dev_set_emulate_fua_read(struct se_device *, int); |
| @@ -60,6 +54,9 @@ void core_dev_free_initiator_node_lun_acl(struct se_portal_group *, | |||
| 60 | struct se_lun_acl *lacl); | 54 | struct se_lun_acl *lacl); |
| 61 | int core_dev_setup_virtual_lun0(void); | 55 | int core_dev_setup_virtual_lun0(void); |
| 62 | void core_dev_release_virtual_lun0(void); | 56 | void core_dev_release_virtual_lun0(void); |
| 57 | struct se_device *target_alloc_device(struct se_hba *hba, const char *name); | ||
| 58 | int target_configure_device(struct se_device *dev); | ||
| 59 | void target_free_device(struct se_device *); | ||
| 63 | 60 | ||
| 64 | /* target_core_hba.c */ | 61 | /* target_core_hba.c */ |
| 65 | struct se_hba *core_alloc_hba(const char *, u32, u32); | 62 | struct se_hba *core_alloc_hba(const char *, u32, u32); |
| @@ -105,10 +102,11 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); | |||
| 105 | bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); | 102 | bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); |
| 106 | int transport_clear_lun_from_sessions(struct se_lun *); | 103 | int transport_clear_lun_from_sessions(struct se_lun *); |
| 107 | void transport_send_task_abort(struct se_cmd *); | 104 | void transport_send_task_abort(struct se_cmd *); |
| 108 | int target_cmd_size_check(struct se_cmd *cmd, unsigned int size); | 105 | sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); |
| 106 | void target_qf_do_work(struct work_struct *work); | ||
| 109 | 107 | ||
| 110 | /* target_core_stat.c */ | 108 | /* target_core_stat.c */ |
| 111 | void target_stat_setup_dev_default_groups(struct se_subsystem_dev *); | 109 | void target_stat_setup_dev_default_groups(struct se_device *); |
| 112 | void target_stat_setup_port_default_groups(struct se_lun *); | 110 | void target_stat_setup_port_default_groups(struct se_lun *); |
| 113 | void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *); | 111 | void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *); |
| 114 | 112 | ||
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 8c323a98c4a0..e35dbf85841f 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c | |||
| @@ -4,8 +4,7 @@ | |||
| 4 | * This file contains SPC-3 compliant persistent reservations and | 4 | * This file contains SPC-3 compliant persistent reservations and |
| 5 | * legacy SPC-2 reservations with compatible reservation handling (CRH=1) | 5 | * legacy SPC-2 reservations with compatible reservation handling (CRH=1) |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2009, 2010 Rising Tide Systems | 7 | * (c) Copyright 2009-2012 RisingTide Systems LLC. |
| 8 | * Copyright (c) 2009, 2010 Linux-iSCSI.org | ||
| 9 | * | 8 | * |
| 10 | * Nicholas A. Bellinger <nab@kernel.org> | 9 | * Nicholas A. Bellinger <nab@kernel.org> |
| 11 | * | 10 | * |
| @@ -68,49 +67,33 @@ int core_pr_dump_initiator_port( | |||
| 68 | static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, | 67 | static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, |
| 69 | struct t10_pr_registration *, int); | 68 | struct t10_pr_registration *, int); |
| 70 | 69 | ||
| 71 | static int core_scsi2_reservation_seq_non_holder( | 70 | static sense_reason_t |
| 72 | struct se_cmd *cmd, | 71 | target_scsi2_reservation_check(struct se_cmd *cmd) |
| 73 | unsigned char *cdb, | ||
| 74 | u32 pr_reg_type) | ||
| 75 | { | 72 | { |
| 76 | switch (cdb[0]) { | 73 | struct se_device *dev = cmd->se_dev; |
| 74 | struct se_session *sess = cmd->se_sess; | ||
| 75 | |||
| 76 | switch (cmd->t_task_cdb[0]) { | ||
| 77 | case INQUIRY: | 77 | case INQUIRY: |
| 78 | case RELEASE: | 78 | case RELEASE: |
| 79 | case RELEASE_10: | 79 | case RELEASE_10: |
| 80 | return 0; | 80 | return 0; |
| 81 | default: | 81 | default: |
| 82 | return 1; | 82 | break; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | return 1; | 85 | if (!dev->dev_reserved_node_acl || !sess) |
| 86 | } | ||
| 87 | |||
| 88 | static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type) | ||
| 89 | { | ||
| 90 | struct se_device *dev = cmd->se_dev; | ||
| 91 | struct se_session *sess = cmd->se_sess; | ||
| 92 | int ret; | ||
| 93 | |||
| 94 | if (!sess) | ||
| 95 | return 0; | 86 | return 0; |
| 96 | 87 | ||
| 97 | spin_lock(&dev->dev_reservation_lock); | 88 | if (dev->dev_reserved_node_acl != sess->se_node_acl) |
| 98 | if (!dev->dev_reserved_node_acl || !sess) { | 89 | return TCM_RESERVATION_CONFLICT; |
| 99 | spin_unlock(&dev->dev_reservation_lock); | 90 | |
| 100 | return 0; | 91 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { |
| 101 | } | 92 | if (dev->dev_res_bin_isid != sess->sess_bin_isid) |
| 102 | if (dev->dev_reserved_node_acl != sess->se_node_acl) { | 93 | return TCM_RESERVATION_CONFLICT; |
| 103 | spin_unlock(&dev->dev_reservation_lock); | ||
| 104 | return -EINVAL; | ||
| 105 | } | ||
| 106 | if (!(dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID)) { | ||
| 107 | spin_unlock(&dev->dev_reservation_lock); | ||
| 108 | return 0; | ||
| 109 | } | 94 | } |
| 110 | ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL; | ||
| 111 | spin_unlock(&dev->dev_reservation_lock); | ||
| 112 | 95 | ||
| 113 | return ret; | 96 | return 0; |
| 114 | } | 97 | } |
| 115 | 98 | ||
| 116 | static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *, | 99 | static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *, |
| @@ -120,15 +103,11 @@ static void core_scsi3_put_pr_reg(struct t10_pr_registration *); | |||
| 120 | static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) | 103 | static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) |
| 121 | { | 104 | { |
| 122 | struct se_session *se_sess = cmd->se_sess; | 105 | struct se_session *se_sess = cmd->se_sess; |
| 123 | struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; | 106 | struct se_device *dev = cmd->se_dev; |
| 124 | struct t10_pr_registration *pr_reg; | 107 | struct t10_pr_registration *pr_reg; |
| 125 | struct t10_reservation *pr_tmpl = &su_dev->t10_pr; | 108 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 126 | int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS); | ||
| 127 | int conflict = 0; | 109 | int conflict = 0; |
| 128 | 110 | ||
| 129 | if (!crh) | ||
| 130 | return -EINVAL; | ||
| 131 | |||
| 132 | pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, | 111 | pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, |
| 133 | se_sess); | 112 | se_sess); |
| 134 | if (pr_reg) { | 113 | if (pr_reg) { |
| @@ -186,32 +165,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) | |||
| 186 | pr_err("Received legacy SPC-2 RESERVE/RELEASE" | 165 | pr_err("Received legacy SPC-2 RESERVE/RELEASE" |
| 187 | " while active SPC-3 registrations exist," | 166 | " while active SPC-3 registrations exist," |
| 188 | " returning RESERVATION_CONFLICT\n"); | 167 | " returning RESERVATION_CONFLICT\n"); |
| 189 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | ||
| 190 | return -EBUSY; | 168 | return -EBUSY; |
| 191 | } | 169 | } |
| 192 | 170 | ||
| 193 | return 0; | 171 | return 0; |
| 194 | } | 172 | } |
| 195 | 173 | ||
| 196 | int target_scsi2_reservation_release(struct se_cmd *cmd) | 174 | sense_reason_t |
| 175 | target_scsi2_reservation_release(struct se_cmd *cmd) | ||
| 197 | { | 176 | { |
| 198 | struct se_device *dev = cmd->se_dev; | 177 | struct se_device *dev = cmd->se_dev; |
| 199 | struct se_session *sess = cmd->se_sess; | 178 | struct se_session *sess = cmd->se_sess; |
| 200 | struct se_portal_group *tpg; | 179 | struct se_portal_group *tpg; |
| 201 | int ret = 0, rc; | 180 | int rc; |
| 202 | 181 | ||
| 203 | if (!sess || !sess->se_tpg) | 182 | if (!sess || !sess->se_tpg) |
| 204 | goto out; | 183 | goto out; |
| 205 | rc = target_check_scsi2_reservation_conflict(cmd); | 184 | rc = target_check_scsi2_reservation_conflict(cmd); |
| 206 | if (rc == 1) | 185 | if (rc == 1) |
| 207 | goto out; | 186 | goto out; |
| 208 | else if (rc < 0) { | 187 | if (rc < 0) |
| 209 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 188 | return TCM_RESERVATION_CONFLICT; |
| 210 | ret = -EINVAL; | ||
| 211 | goto out; | ||
| 212 | } | ||
| 213 | 189 | ||
| 214 | ret = 0; | ||
| 215 | spin_lock(&dev->dev_reservation_lock); | 190 | spin_lock(&dev->dev_reservation_lock); |
| 216 | if (!dev->dev_reserved_node_acl || !sess) | 191 | if (!dev->dev_reserved_node_acl || !sess) |
| 217 | goto out_unlock; | 192 | goto out_unlock; |
| @@ -223,10 +198,10 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) | |||
| 223 | goto out_unlock; | 198 | goto out_unlock; |
| 224 | 199 | ||
| 225 | dev->dev_reserved_node_acl = NULL; | 200 | dev->dev_reserved_node_acl = NULL; |
| 226 | dev->dev_flags &= ~DF_SPC2_RESERVATIONS; | 201 | dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS; |
| 227 | if (dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID) { | 202 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { |
| 228 | dev->dev_res_bin_isid = 0; | 203 | dev->dev_res_bin_isid = 0; |
| 229 | dev->dev_flags &= ~DF_SPC2_RESERVATIONS_WITH_ISID; | 204 | dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID; |
| 230 | } | 205 | } |
| 231 | tpg = sess->se_tpg; | 206 | tpg = sess->se_tpg; |
| 232 | pr_debug("SCSI-2 Released reservation for %s LUN: %u ->" | 207 | pr_debug("SCSI-2 Released reservation for %s LUN: %u ->" |
| @@ -237,25 +212,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) | |||
| 237 | out_unlock: | 212 | out_unlock: |
| 238 | spin_unlock(&dev->dev_reservation_lock); | 213 | spin_unlock(&dev->dev_reservation_lock); |
| 239 | out: | 214 | out: |
| 240 | if (!ret) | 215 | target_complete_cmd(cmd, GOOD); |
| 241 | target_complete_cmd(cmd, GOOD); | 216 | return 0; |
| 242 | return ret; | ||
| 243 | } | 217 | } |
| 244 | 218 | ||
| 245 | int target_scsi2_reservation_reserve(struct se_cmd *cmd) | 219 | sense_reason_t |
| 220 | target_scsi2_reservation_reserve(struct se_cmd *cmd) | ||
| 246 | { | 221 | { |
| 247 | struct se_device *dev = cmd->se_dev; | 222 | struct se_device *dev = cmd->se_dev; |
| 248 | struct se_session *sess = cmd->se_sess; | 223 | struct se_session *sess = cmd->se_sess; |
| 249 | struct se_portal_group *tpg; | 224 | struct se_portal_group *tpg; |
| 250 | int ret = 0, rc; | 225 | sense_reason_t ret = 0; |
| 226 | int rc; | ||
| 251 | 227 | ||
| 252 | if ((cmd->t_task_cdb[1] & 0x01) && | 228 | if ((cmd->t_task_cdb[1] & 0x01) && |
| 253 | (cmd->t_task_cdb[1] & 0x02)) { | 229 | (cmd->t_task_cdb[1] & 0x02)) { |
| 254 | pr_err("LongIO and Obselete Bits set, returning" | 230 | pr_err("LongIO and Obselete Bits set, returning" |
| 255 | " ILLEGAL_REQUEST\n"); | 231 | " ILLEGAL_REQUEST\n"); |
| 256 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | 232 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 257 | ret = -EINVAL; | ||
| 258 | goto out; | ||
| 259 | } | 233 | } |
| 260 | /* | 234 | /* |
| 261 | * This is currently the case for target_core_mod passthrough struct se_cmd | 235 | * This is currently the case for target_core_mod passthrough struct se_cmd |
| @@ -266,13 +240,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) | |||
| 266 | rc = target_check_scsi2_reservation_conflict(cmd); | 240 | rc = target_check_scsi2_reservation_conflict(cmd); |
| 267 | if (rc == 1) | 241 | if (rc == 1) |
| 268 | goto out; | 242 | goto out; |
| 269 | else if (rc < 0) { | ||
| 270 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | ||
| 271 | ret = -EINVAL; | ||
| 272 | goto out; | ||
| 273 | } | ||
| 274 | 243 | ||
| 275 | ret = 0; | 244 | if (rc < 0) |
| 245 | return TCM_RESERVATION_CONFLICT; | ||
| 246 | |||
| 276 | tpg = sess->se_tpg; | 247 | tpg = sess->se_tpg; |
| 277 | spin_lock(&dev->dev_reservation_lock); | 248 | spin_lock(&dev->dev_reservation_lock); |
| 278 | if (dev->dev_reserved_node_acl && | 249 | if (dev->dev_reserved_node_acl && |
| @@ -286,16 +257,15 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) | |||
| 286 | " from %s \n", cmd->se_lun->unpacked_lun, | 257 | " from %s \n", cmd->se_lun->unpacked_lun, |
| 287 | cmd->se_deve->mapped_lun, | 258 | cmd->se_deve->mapped_lun, |
| 288 | sess->se_node_acl->initiatorname); | 259 | sess->se_node_acl->initiatorname); |
| 289 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 260 | ret = TCM_RESERVATION_CONFLICT; |
| 290 | ret = -EINVAL; | ||
| 291 | goto out_unlock; | 261 | goto out_unlock; |
| 292 | } | 262 | } |
| 293 | 263 | ||
| 294 | dev->dev_reserved_node_acl = sess->se_node_acl; | 264 | dev->dev_reserved_node_acl = sess->se_node_acl; |
| 295 | dev->dev_flags |= DF_SPC2_RESERVATIONS; | 265 | dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS; |
| 296 | if (sess->sess_bin_isid != 0) { | 266 | if (sess->sess_bin_isid != 0) { |
| 297 | dev->dev_res_bin_isid = sess->sess_bin_isid; | 267 | dev->dev_res_bin_isid = sess->sess_bin_isid; |
| 298 | dev->dev_flags |= DF_SPC2_RESERVATIONS_WITH_ISID; | 268 | dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID; |
| 299 | } | 269 | } |
| 300 | pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u" | 270 | pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u" |
| 301 | " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), | 271 | " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), |
| @@ -319,9 +289,9 @@ out: | |||
| 319 | */ | 289 | */ |
| 320 | static int core_scsi3_pr_seq_non_holder( | 290 | static int core_scsi3_pr_seq_non_holder( |
| 321 | struct se_cmd *cmd, | 291 | struct se_cmd *cmd, |
| 322 | unsigned char *cdb, | ||
| 323 | u32 pr_reg_type) | 292 | u32 pr_reg_type) |
| 324 | { | 293 | { |
| 294 | unsigned char *cdb = cmd->t_task_cdb; | ||
| 325 | struct se_dev_entry *se_deve; | 295 | struct se_dev_entry *se_deve; |
| 326 | struct se_session *se_sess = cmd->se_sess; | 296 | struct se_session *se_sess = cmd->se_sess; |
| 327 | int other_cdb = 0, ignore_reg; | 297 | int other_cdb = 0, ignore_reg; |
| @@ -330,17 +300,11 @@ static int core_scsi3_pr_seq_non_holder( | |||
| 330 | int we = 0; /* Write Exclusive */ | 300 | int we = 0; /* Write Exclusive */ |
| 331 | int legacy = 0; /* Act like a legacy device and return | 301 | int legacy = 0; /* Act like a legacy device and return |
| 332 | * RESERVATION CONFLICT on some CDBs */ | 302 | * RESERVATION CONFLICT on some CDBs */ |
| 333 | /* | ||
| 334 | * A legacy SPC-2 reservation is being held. | ||
| 335 | */ | ||
| 336 | if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) | ||
| 337 | return core_scsi2_reservation_seq_non_holder(cmd, | ||
| 338 | cdb, pr_reg_type); | ||
| 339 | 303 | ||
| 340 | se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; | 304 | se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; |
| 341 | /* | 305 | /* |
| 342 | * Determine if the registration should be ignored due to | 306 | * Determine if the registration should be ignored due to |
| 343 | * non-matching ISIDs in core_scsi3_pr_reservation_check(). | 307 | * non-matching ISIDs in target_scsi3_pr_reservation_check(). |
| 344 | */ | 308 | */ |
| 345 | ignore_reg = (pr_reg_type & 0x80000000); | 309 | ignore_reg = (pr_reg_type & 0x80000000); |
| 346 | if (ignore_reg) | 310 | if (ignore_reg) |
| @@ -563,10 +527,41 @@ static int core_scsi3_pr_seq_non_holder( | |||
| 563 | return 1; /* Conflict by default */ | 527 | return 1; /* Conflict by default */ |
| 564 | } | 528 | } |
| 565 | 529 | ||
| 530 | static sense_reason_t | ||
| 531 | target_scsi3_pr_reservation_check(struct se_cmd *cmd) | ||
| 532 | { | ||
| 533 | struct se_device *dev = cmd->se_dev; | ||
| 534 | struct se_session *sess = cmd->se_sess; | ||
| 535 | u32 pr_reg_type; | ||
| 536 | |||
| 537 | if (!dev->dev_pr_res_holder) | ||
| 538 | return 0; | ||
| 539 | |||
| 540 | pr_reg_type = dev->dev_pr_res_holder->pr_res_type; | ||
| 541 | cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; | ||
| 542 | if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) | ||
| 543 | goto check_nonholder; | ||
| 544 | |||
| 545 | if (dev->dev_pr_res_holder->isid_present_at_reg) { | ||
| 546 | if (dev->dev_pr_res_holder->pr_reg_bin_isid != | ||
| 547 | sess->sess_bin_isid) { | ||
| 548 | pr_reg_type |= 0x80000000; | ||
| 549 | goto check_nonholder; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 553 | return 0; | ||
| 554 | |||
| 555 | check_nonholder: | ||
| 556 | if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) | ||
| 557 | return TCM_RESERVATION_CONFLICT; | ||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | |||
| 566 | static u32 core_scsi3_pr_generation(struct se_device *dev) | 561 | static u32 core_scsi3_pr_generation(struct se_device *dev) |
| 567 | { | 562 | { |
| 568 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 569 | u32 prg; | 563 | u32 prg; |
| 564 | |||
| 570 | /* | 565 | /* |
| 571 | * PRGeneration field shall contain the value of a 32-bit wrapping | 566 | * PRGeneration field shall contain the value of a 32-bit wrapping |
| 572 | * counter mainted by the device server. | 567 | * counter mainted by the device server. |
| @@ -577,56 +572,12 @@ static u32 core_scsi3_pr_generation(struct se_device *dev) | |||
| 577 | * See spc4r17 section 6.3.12 READ_KEYS service action | 572 | * See spc4r17 section 6.3.12 READ_KEYS service action |
| 578 | */ | 573 | */ |
| 579 | spin_lock(&dev->dev_reservation_lock); | 574 | spin_lock(&dev->dev_reservation_lock); |
| 580 | prg = su_dev->t10_pr.pr_generation++; | 575 | prg = dev->t10_pr.pr_generation++; |
| 581 | spin_unlock(&dev->dev_reservation_lock); | 576 | spin_unlock(&dev->dev_reservation_lock); |
| 582 | 577 | ||
| 583 | return prg; | 578 | return prg; |
| 584 | } | 579 | } |
| 585 | 580 | ||
| 586 | static int core_scsi3_pr_reservation_check( | ||
| 587 | struct se_cmd *cmd, | ||
| 588 | u32 *pr_reg_type) | ||
| 589 | { | ||
| 590 | struct se_device *dev = cmd->se_dev; | ||
| 591 | struct se_session *sess = cmd->se_sess; | ||
| 592 | int ret; | ||
| 593 | |||
| 594 | if (!sess) | ||
| 595 | return 0; | ||
| 596 | /* | ||
| 597 | * A legacy SPC-2 reservation is being held. | ||
| 598 | */ | ||
| 599 | if (dev->dev_flags & DF_SPC2_RESERVATIONS) | ||
| 600 | return core_scsi2_reservation_check(cmd, pr_reg_type); | ||
| 601 | |||
| 602 | spin_lock(&dev->dev_reservation_lock); | ||
| 603 | if (!dev->dev_pr_res_holder) { | ||
| 604 | spin_unlock(&dev->dev_reservation_lock); | ||
| 605 | return 0; | ||
| 606 | } | ||
| 607 | *pr_reg_type = dev->dev_pr_res_holder->pr_res_type; | ||
| 608 | cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; | ||
| 609 | if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) { | ||
| 610 | spin_unlock(&dev->dev_reservation_lock); | ||
| 611 | return -EINVAL; | ||
| 612 | } | ||
| 613 | if (!dev->dev_pr_res_holder->isid_present_at_reg) { | ||
| 614 | spin_unlock(&dev->dev_reservation_lock); | ||
| 615 | return 0; | ||
| 616 | } | ||
| 617 | ret = (dev->dev_pr_res_holder->pr_reg_bin_isid == | ||
| 618 | sess->sess_bin_isid) ? 0 : -EINVAL; | ||
| 619 | /* | ||
| 620 | * Use bit in *pr_reg_type to notify ISID mismatch in | ||
| 621 | * core_scsi3_pr_seq_non_holder(). | ||
| 622 | */ | ||
| 623 | if (ret != 0) | ||
| 624 | *pr_reg_type |= 0x80000000; | ||
| 625 | spin_unlock(&dev->dev_reservation_lock); | ||
| 626 | |||
| 627 | return ret; | ||
| 628 | } | ||
| 629 | |||
| 630 | static struct t10_pr_registration *__core_scsi3_do_alloc_registration( | 581 | static struct t10_pr_registration *__core_scsi3_do_alloc_registration( |
| 631 | struct se_device *dev, | 582 | struct se_device *dev, |
| 632 | struct se_node_acl *nacl, | 583 | struct se_node_acl *nacl, |
| @@ -636,7 +587,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( | |||
| 636 | int all_tg_pt, | 587 | int all_tg_pt, |
| 637 | int aptpl) | 588 | int aptpl) |
| 638 | { | 589 | { |
| 639 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 640 | struct t10_pr_registration *pr_reg; | 590 | struct t10_pr_registration *pr_reg; |
| 641 | 591 | ||
| 642 | pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_ATOMIC); | 592 | pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_ATOMIC); |
| @@ -645,7 +595,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( | |||
| 645 | return NULL; | 595 | return NULL; |
| 646 | } | 596 | } |
| 647 | 597 | ||
| 648 | pr_reg->pr_aptpl_buf = kzalloc(su_dev->t10_pr.pr_aptpl_buf_len, | 598 | pr_reg->pr_aptpl_buf = kzalloc(dev->t10_pr.pr_aptpl_buf_len, |
| 649 | GFP_ATOMIC); | 599 | GFP_ATOMIC); |
| 650 | if (!pr_reg->pr_aptpl_buf) { | 600 | if (!pr_reg->pr_aptpl_buf) { |
| 651 | pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n"); | 601 | pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n"); |
| @@ -929,7 +879,7 @@ static int __core_scsi3_check_aptpl_registration( | |||
| 929 | struct se_dev_entry *deve) | 879 | struct se_dev_entry *deve) |
| 930 | { | 880 | { |
| 931 | struct t10_pr_registration *pr_reg, *pr_reg_tmp; | 881 | struct t10_pr_registration *pr_reg, *pr_reg_tmp; |
| 932 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 882 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 933 | unsigned char i_port[PR_APTPL_MAX_IPORT_LEN]; | 883 | unsigned char i_port[PR_APTPL_MAX_IPORT_LEN]; |
| 934 | unsigned char t_port[PR_APTPL_MAX_TPORT_LEN]; | 884 | unsigned char t_port[PR_APTPL_MAX_TPORT_LEN]; |
| 935 | u16 tpgt; | 885 | u16 tpgt; |
| @@ -996,11 +946,10 @@ int core_scsi3_check_aptpl_registration( | |||
| 996 | struct se_lun *lun, | 946 | struct se_lun *lun, |
| 997 | struct se_lun_acl *lun_acl) | 947 | struct se_lun_acl *lun_acl) |
| 998 | { | 948 | { |
| 999 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 1000 | struct se_node_acl *nacl = lun_acl->se_lun_nacl; | 949 | struct se_node_acl *nacl = lun_acl->se_lun_nacl; |
| 1001 | struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; | 950 | struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; |
| 1002 | 951 | ||
| 1003 | if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) | 952 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) |
| 1004 | return 0; | 953 | return 0; |
| 1005 | 954 | ||
| 1006 | return __core_scsi3_check_aptpl_registration(dev, tpg, lun, | 955 | return __core_scsi3_check_aptpl_registration(dev, tpg, lun, |
| @@ -1051,10 +1000,9 @@ static void __core_scsi3_add_registration( | |||
| 1051 | int register_type, | 1000 | int register_type, |
| 1052 | int register_move) | 1001 | int register_move) |
| 1053 | { | 1002 | { |
| 1054 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 1055 | struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; | 1003 | struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; |
| 1056 | struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe; | 1004 | struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe; |
| 1057 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 1005 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 1058 | 1006 | ||
| 1059 | /* | 1007 | /* |
| 1060 | * Increment PRgeneration counter for struct se_device upon a successful | 1008 | * Increment PRgeneration counter for struct se_device upon a successful |
| @@ -1066,7 +1014,7 @@ static void __core_scsi3_add_registration( | |||
| 1066 | * for the REGISTER. | 1014 | * for the REGISTER. |
| 1067 | */ | 1015 | */ |
| 1068 | pr_reg->pr_res_generation = (register_move) ? | 1016 | pr_reg->pr_res_generation = (register_move) ? |
| 1069 | su_dev->t10_pr.pr_generation++ : | 1017 | dev->t10_pr.pr_generation++ : |
| 1070 | core_scsi3_pr_generation(dev); | 1018 | core_scsi3_pr_generation(dev); |
| 1071 | 1019 | ||
| 1072 | spin_lock(&pr_tmpl->registration_lock); | 1020 | spin_lock(&pr_tmpl->registration_lock); |
| @@ -1135,7 +1083,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( | |||
| 1135 | struct se_node_acl *nacl, | 1083 | struct se_node_acl *nacl, |
| 1136 | unsigned char *isid) | 1084 | unsigned char *isid) |
| 1137 | { | 1085 | { |
| 1138 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 1086 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 1139 | struct t10_pr_registration *pr_reg, *pr_reg_tmp; | 1087 | struct t10_pr_registration *pr_reg, *pr_reg_tmp; |
| 1140 | struct se_portal_group *tpg; | 1088 | struct se_portal_group *tpg; |
| 1141 | 1089 | ||
| @@ -1160,7 +1108,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( | |||
| 1160 | * for fabric modules (iSCSI) requiring them. | 1108 | * for fabric modules (iSCSI) requiring them. |
| 1161 | */ | 1109 | */ |
| 1162 | if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) { | 1110 | if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) { |
| 1163 | if (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids) | 1111 | if (dev->dev_attrib.enforce_pr_isids) |
| 1164 | continue; | 1112 | continue; |
| 1165 | } | 1113 | } |
| 1166 | atomic_inc(&pr_reg->pr_res_holders); | 1114 | atomic_inc(&pr_reg->pr_res_holders); |
| @@ -1274,7 +1222,7 @@ static void __core_scsi3_free_registration( | |||
| 1274 | { | 1222 | { |
| 1275 | struct target_core_fabric_ops *tfo = | 1223 | struct target_core_fabric_ops *tfo = |
| 1276 | pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; | 1224 | pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; |
| 1277 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 1225 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 1278 | char i_buf[PR_REG_ISID_ID_LEN]; | 1226 | char i_buf[PR_REG_ISID_ID_LEN]; |
| 1279 | int prf_isid; | 1227 | int prf_isid; |
| 1280 | 1228 | ||
| @@ -1335,7 +1283,7 @@ void core_scsi3_free_pr_reg_from_nacl( | |||
| 1335 | struct se_device *dev, | 1283 | struct se_device *dev, |
| 1336 | struct se_node_acl *nacl) | 1284 | struct se_node_acl *nacl) |
| 1337 | { | 1285 | { |
| 1338 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 1286 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 1339 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; | 1287 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; |
| 1340 | /* | 1288 | /* |
| 1341 | * If the passed se_node_acl matches the reservation holder, | 1289 | * If the passed se_node_acl matches the reservation holder, |
| @@ -1365,7 +1313,7 @@ void core_scsi3_free_pr_reg_from_nacl( | |||
| 1365 | void core_scsi3_free_all_registrations( | 1313 | void core_scsi3_free_all_registrations( |
| 1366 | struct se_device *dev) | 1314 | struct se_device *dev) |
| 1367 | { | 1315 | { |
| 1368 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 1316 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 1369 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; | 1317 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; |
| 1370 | 1318 | ||
| 1371 | spin_lock(&dev->dev_reservation_lock); | 1319 | spin_lock(&dev->dev_reservation_lock); |
| @@ -1479,7 +1427,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve) | |||
| 1479 | smp_mb__after_atomic_dec(); | 1427 | smp_mb__after_atomic_dec(); |
| 1480 | } | 1428 | } |
| 1481 | 1429 | ||
| 1482 | static int core_scsi3_decode_spec_i_port( | 1430 | static sense_reason_t |
| 1431 | core_scsi3_decode_spec_i_port( | ||
| 1483 | struct se_cmd *cmd, | 1432 | struct se_cmd *cmd, |
| 1484 | struct se_portal_group *tpg, | 1433 | struct se_portal_group *tpg, |
| 1485 | unsigned char *l_isid, | 1434 | unsigned char *l_isid, |
| @@ -1501,8 +1450,9 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1501 | unsigned char *buf; | 1450 | unsigned char *buf; |
| 1502 | unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; | 1451 | unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; |
| 1503 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; | 1452 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; |
| 1453 | sense_reason_t ret; | ||
| 1504 | u32 tpdl, tid_len = 0; | 1454 | u32 tpdl, tid_len = 0; |
| 1505 | int ret, dest_local_nexus, prf_isid; | 1455 | int dest_local_nexus, prf_isid; |
| 1506 | u32 dest_rtpi = 0; | 1456 | u32 dest_rtpi = 0; |
| 1507 | 1457 | ||
| 1508 | memset(dest_iport, 0, 64); | 1458 | memset(dest_iport, 0, 64); |
| @@ -1517,8 +1467,7 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1517 | tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); | 1467 | tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); |
| 1518 | if (!tidh_new) { | 1468 | if (!tidh_new) { |
| 1519 | pr_err("Unable to allocate tidh_new\n"); | 1469 | pr_err("Unable to allocate tidh_new\n"); |
| 1520 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1470 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1521 | return -EINVAL; | ||
| 1522 | } | 1471 | } |
| 1523 | INIT_LIST_HEAD(&tidh_new->dest_list); | 1472 | INIT_LIST_HEAD(&tidh_new->dest_list); |
| 1524 | tidh_new->dest_tpg = tpg; | 1473 | tidh_new->dest_tpg = tpg; |
| @@ -1530,8 +1479,7 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1530 | sa_res_key, all_tg_pt, aptpl); | 1479 | sa_res_key, all_tg_pt, aptpl); |
| 1531 | if (!local_pr_reg) { | 1480 | if (!local_pr_reg) { |
| 1532 | kfree(tidh_new); | 1481 | kfree(tidh_new); |
| 1533 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1482 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1534 | return -ENOMEM; | ||
| 1535 | } | 1483 | } |
| 1536 | tidh_new->dest_pr_reg = local_pr_reg; | 1484 | tidh_new->dest_pr_reg = local_pr_reg; |
| 1537 | /* | 1485 | /* |
| @@ -1545,12 +1493,16 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1545 | if (cmd->data_length < 28) { | 1493 | if (cmd->data_length < 28) { |
| 1546 | pr_warn("SPC-PR: Received PR OUT parameter list" | 1494 | pr_warn("SPC-PR: Received PR OUT parameter list" |
| 1547 | " length too small: %u\n", cmd->data_length); | 1495 | " length too small: %u\n", cmd->data_length); |
| 1548 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1496 | ret = TCM_INVALID_PARAMETER_LIST; |
| 1549 | ret = -EINVAL; | ||
| 1550 | goto out; | 1497 | goto out; |
| 1551 | } | 1498 | } |
| 1552 | 1499 | ||
| 1553 | buf = transport_kmap_data_sg(cmd); | 1500 | buf = transport_kmap_data_sg(cmd); |
| 1501 | if (!buf) { | ||
| 1502 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1503 | goto out; | ||
| 1504 | } | ||
| 1505 | |||
| 1554 | /* | 1506 | /* |
| 1555 | * For a PERSISTENT RESERVE OUT specify initiator ports payload, | 1507 | * For a PERSISTENT RESERVE OUT specify initiator ports payload, |
| 1556 | * first extract TransportID Parameter Data Length, and make sure | 1508 | * first extract TransportID Parameter Data Length, and make sure |
| @@ -1565,9 +1517,8 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1565 | pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" | 1517 | pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" |
| 1566 | " does not equal CDB data_length: %u\n", tpdl, | 1518 | " does not equal CDB data_length: %u\n", tpdl, |
| 1567 | cmd->data_length); | 1519 | cmd->data_length); |
| 1568 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1520 | ret = TCM_INVALID_PARAMETER_LIST; |
| 1569 | ret = -EINVAL; | 1521 | goto out_unmap; |
| 1570 | goto out; | ||
| 1571 | } | 1522 | } |
| 1572 | /* | 1523 | /* |
| 1573 | * Start processing the received transport IDs using the | 1524 | * Start processing the received transport IDs using the |
| @@ -1610,16 +1561,13 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1610 | smp_mb__after_atomic_inc(); | 1561 | smp_mb__after_atomic_inc(); |
| 1611 | spin_unlock(&dev->se_port_lock); | 1562 | spin_unlock(&dev->se_port_lock); |
| 1612 | 1563 | ||
| 1613 | ret = core_scsi3_tpg_depend_item(tmp_tpg); | 1564 | if (core_scsi3_tpg_depend_item(tmp_tpg)) { |
| 1614 | if (ret != 0) { | ||
| 1615 | pr_err(" core_scsi3_tpg_depend_item()" | 1565 | pr_err(" core_scsi3_tpg_depend_item()" |
| 1616 | " for tmp_tpg\n"); | 1566 | " for tmp_tpg\n"); |
| 1617 | atomic_dec(&tmp_tpg->tpg_pr_ref_count); | 1567 | atomic_dec(&tmp_tpg->tpg_pr_ref_count); |
| 1618 | smp_mb__after_atomic_dec(); | 1568 | smp_mb__after_atomic_dec(); |
| 1619 | cmd->scsi_sense_reason = | 1569 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1620 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1570 | goto out_unmap; |
| 1621 | ret = -EINVAL; | ||
| 1622 | goto out; | ||
| 1623 | } | 1571 | } |
| 1624 | /* | 1572 | /* |
| 1625 | * Locate the destination initiator ACL to be registered | 1573 | * Locate the destination initiator ACL to be registered |
| @@ -1641,17 +1589,14 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1641 | continue; | 1589 | continue; |
| 1642 | } | 1590 | } |
| 1643 | 1591 | ||
| 1644 | ret = core_scsi3_nodeacl_depend_item(dest_node_acl); | 1592 | if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { |
| 1645 | if (ret != 0) { | ||
| 1646 | pr_err("configfs_depend_item() failed" | 1593 | pr_err("configfs_depend_item() failed" |
| 1647 | " for dest_node_acl->acl_group\n"); | 1594 | " for dest_node_acl->acl_group\n"); |
| 1648 | atomic_dec(&dest_node_acl->acl_pr_ref_count); | 1595 | atomic_dec(&dest_node_acl->acl_pr_ref_count); |
| 1649 | smp_mb__after_atomic_dec(); | 1596 | smp_mb__after_atomic_dec(); |
| 1650 | core_scsi3_tpg_undepend_item(tmp_tpg); | 1597 | core_scsi3_tpg_undepend_item(tmp_tpg); |
| 1651 | cmd->scsi_sense_reason = | 1598 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1652 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1599 | goto out_unmap; |
| 1653 | ret = -EINVAL; | ||
| 1654 | goto out; | ||
| 1655 | } | 1600 | } |
| 1656 | 1601 | ||
| 1657 | dest_tpg = tmp_tpg; | 1602 | dest_tpg = tmp_tpg; |
| @@ -1668,9 +1613,8 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1668 | if (!dest_tpg) { | 1613 | if (!dest_tpg) { |
| 1669 | pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" | 1614 | pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" |
| 1670 | " dest_tpg\n"); | 1615 | " dest_tpg\n"); |
| 1671 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1616 | ret = TCM_INVALID_PARAMETER_LIST; |
| 1672 | ret = -EINVAL; | 1617 | goto out_unmap; |
| 1673 | goto out; | ||
| 1674 | } | 1618 | } |
| 1675 | 1619 | ||
| 1676 | pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" | 1620 | pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" |
| @@ -1683,9 +1627,8 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1683 | " %u for Transport ID: %s\n", tid_len, ptr); | 1627 | " %u for Transport ID: %s\n", tid_len, ptr); |
| 1684 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1628 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
| 1685 | core_scsi3_tpg_undepend_item(dest_tpg); | 1629 | core_scsi3_tpg_undepend_item(dest_tpg); |
| 1686 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1630 | ret = TCM_INVALID_PARAMETER_LIST; |
| 1687 | ret = -EINVAL; | 1631 | goto out_unmap; |
| 1688 | goto out; | ||
| 1689 | } | 1632 | } |
| 1690 | /* | 1633 | /* |
| 1691 | * Locate the desintation struct se_dev_entry pointer for matching | 1634 | * Locate the desintation struct se_dev_entry pointer for matching |
| @@ -1702,23 +1645,19 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1702 | 1645 | ||
| 1703 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1646 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
| 1704 | core_scsi3_tpg_undepend_item(dest_tpg); | 1647 | core_scsi3_tpg_undepend_item(dest_tpg); |
| 1705 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1648 | ret = TCM_INVALID_PARAMETER_LIST; |
| 1706 | ret = -EINVAL; | 1649 | goto out_unmap; |
| 1707 | goto out; | ||
| 1708 | } | 1650 | } |
| 1709 | 1651 | ||
| 1710 | ret = core_scsi3_lunacl_depend_item(dest_se_deve); | 1652 | if (core_scsi3_lunacl_depend_item(dest_se_deve)) { |
| 1711 | if (ret < 0) { | ||
| 1712 | pr_err("core_scsi3_lunacl_depend_item()" | 1653 | pr_err("core_scsi3_lunacl_depend_item()" |
| 1713 | " failed\n"); | 1654 | " failed\n"); |
| 1714 | atomic_dec(&dest_se_deve->pr_ref_count); | 1655 | atomic_dec(&dest_se_deve->pr_ref_count); |
| 1715 | smp_mb__after_atomic_dec(); | 1656 | smp_mb__after_atomic_dec(); |
| 1716 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1657 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
| 1717 | core_scsi3_tpg_undepend_item(dest_tpg); | 1658 | core_scsi3_tpg_undepend_item(dest_tpg); |
| 1718 | cmd->scsi_sense_reason = | 1659 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1719 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1660 | goto out_unmap; |
| 1720 | ret = -EINVAL; | ||
| 1721 | goto out; | ||
| 1722 | } | 1661 | } |
| 1723 | 1662 | ||
| 1724 | pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" | 1663 | pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" |
| @@ -1754,10 +1693,8 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1754 | core_scsi3_lunacl_undepend_item(dest_se_deve); | 1693 | core_scsi3_lunacl_undepend_item(dest_se_deve); |
| 1755 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1694 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
| 1756 | core_scsi3_tpg_undepend_item(dest_tpg); | 1695 | core_scsi3_tpg_undepend_item(dest_tpg); |
| 1757 | cmd->scsi_sense_reason = | 1696 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1758 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1697 | goto out_unmap; |
| 1759 | ret = -ENOMEM; | ||
| 1760 | goto out; | ||
| 1761 | } | 1698 | } |
| 1762 | INIT_LIST_HEAD(&tidh_new->dest_list); | 1699 | INIT_LIST_HEAD(&tidh_new->dest_list); |
| 1763 | tidh_new->dest_tpg = dest_tpg; | 1700 | tidh_new->dest_tpg = dest_tpg; |
| @@ -1788,9 +1725,8 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1788 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1725 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
| 1789 | core_scsi3_tpg_undepend_item(dest_tpg); | 1726 | core_scsi3_tpg_undepend_item(dest_tpg); |
| 1790 | kfree(tidh_new); | 1727 | kfree(tidh_new); |
| 1791 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1728 | ret = TCM_INVALID_PARAMETER_LIST; |
| 1792 | ret = -EINVAL; | 1729 | goto out_unmap; |
| 1793 | goto out; | ||
| 1794 | } | 1730 | } |
| 1795 | tidh_new->dest_pr_reg = dest_pr_reg; | 1731 | tidh_new->dest_pr_reg = dest_pr_reg; |
| 1796 | list_add_tail(&tidh_new->dest_list, &tid_dest_list); | 1732 | list_add_tail(&tidh_new->dest_list, &tid_dest_list); |
| @@ -1848,8 +1784,9 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1848 | } | 1784 | } |
| 1849 | 1785 | ||
| 1850 | return 0; | 1786 | return 0; |
| 1851 | out: | 1787 | out_unmap: |
| 1852 | transport_kunmap_data_sg(cmd); | 1788 | transport_kunmap_data_sg(cmd); |
| 1789 | out: | ||
| 1853 | /* | 1790 | /* |
| 1854 | * For the failure case, release everything from tid_dest_list | 1791 | * For the failure case, release everything from tid_dest_list |
| 1855 | * including *dest_pr_reg and the configfs dependances.. | 1792 | * including *dest_pr_reg and the configfs dependances.. |
| @@ -1899,7 +1836,6 @@ static int __core_scsi3_update_aptpl_buf( | |||
| 1899 | { | 1836 | { |
| 1900 | struct se_lun *lun; | 1837 | struct se_lun *lun; |
| 1901 | struct se_portal_group *tpg; | 1838 | struct se_portal_group *tpg; |
| 1902 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 1903 | struct t10_pr_registration *pr_reg; | 1839 | struct t10_pr_registration *pr_reg; |
| 1904 | unsigned char tmp[512], isid_buf[32]; | 1840 | unsigned char tmp[512], isid_buf[32]; |
| 1905 | ssize_t len = 0; | 1841 | ssize_t len = 0; |
| @@ -1917,8 +1853,8 @@ static int __core_scsi3_update_aptpl_buf( | |||
| 1917 | /* | 1853 | /* |
| 1918 | * Walk the registration list.. | 1854 | * Walk the registration list.. |
| 1919 | */ | 1855 | */ |
| 1920 | spin_lock(&su_dev->t10_pr.registration_lock); | 1856 | spin_lock(&dev->t10_pr.registration_lock); |
| 1921 | list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, | 1857 | list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, |
| 1922 | pr_reg_list) { | 1858 | pr_reg_list) { |
| 1923 | 1859 | ||
| 1924 | tmp[0] = '\0'; | 1860 | tmp[0] = '\0'; |
| @@ -1963,7 +1899,7 @@ static int __core_scsi3_update_aptpl_buf( | |||
| 1963 | if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { | 1899 | if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { |
| 1964 | pr_err("Unable to update renaming" | 1900 | pr_err("Unable to update renaming" |
| 1965 | " APTPL metadata\n"); | 1901 | " APTPL metadata\n"); |
| 1966 | spin_unlock(&su_dev->t10_pr.registration_lock); | 1902 | spin_unlock(&dev->t10_pr.registration_lock); |
| 1967 | return -EMSGSIZE; | 1903 | return -EMSGSIZE; |
| 1968 | } | 1904 | } |
| 1969 | len += sprintf(buf+len, "%s", tmp); | 1905 | len += sprintf(buf+len, "%s", tmp); |
| @@ -1981,13 +1917,13 @@ static int __core_scsi3_update_aptpl_buf( | |||
| 1981 | if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { | 1917 | if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { |
| 1982 | pr_err("Unable to update renaming" | 1918 | pr_err("Unable to update renaming" |
| 1983 | " APTPL metadata\n"); | 1919 | " APTPL metadata\n"); |
| 1984 | spin_unlock(&su_dev->t10_pr.registration_lock); | 1920 | spin_unlock(&dev->t10_pr.registration_lock); |
| 1985 | return -EMSGSIZE; | 1921 | return -EMSGSIZE; |
| 1986 | } | 1922 | } |
| 1987 | len += sprintf(buf+len, "%s", tmp); | 1923 | len += sprintf(buf+len, "%s", tmp); |
| 1988 | reg_count++; | 1924 | reg_count++; |
| 1989 | } | 1925 | } |
| 1990 | spin_unlock(&su_dev->t10_pr.registration_lock); | 1926 | spin_unlock(&dev->t10_pr.registration_lock); |
| 1991 | 1927 | ||
| 1992 | if (!reg_count) | 1928 | if (!reg_count) |
| 1993 | len += sprintf(buf+len, "No Registrations or Reservations"); | 1929 | len += sprintf(buf+len, "No Registrations or Reservations"); |
| @@ -2019,7 +1955,7 @@ static int __core_scsi3_write_aptpl_to_file( | |||
| 2019 | unsigned char *buf, | 1955 | unsigned char *buf, |
| 2020 | u32 pr_aptpl_buf_len) | 1956 | u32 pr_aptpl_buf_len) |
| 2021 | { | 1957 | { |
| 2022 | struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; | 1958 | struct t10_wwn *wwn = &dev->t10_wwn; |
| 2023 | struct file *file; | 1959 | struct file *file; |
| 2024 | struct iovec iov[1]; | 1960 | struct iovec iov[1]; |
| 2025 | mm_segment_t old_fs; | 1961 | mm_segment_t old_fs; |
| @@ -2065,14 +2001,15 @@ static int __core_scsi3_write_aptpl_to_file( | |||
| 2065 | return 0; | 2001 | return 0; |
| 2066 | } | 2002 | } |
| 2067 | 2003 | ||
| 2068 | static int core_scsi3_update_and_write_aptpl( | 2004 | static int |
| 2069 | struct se_device *dev, | 2005 | core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, |
| 2070 | unsigned char *in_buf, | 2006 | u32 in_pr_aptpl_buf_len) |
| 2071 | u32 in_pr_aptpl_buf_len) | ||
| 2072 | { | 2007 | { |
| 2073 | unsigned char null_buf[64], *buf; | 2008 | unsigned char null_buf[64], *buf; |
| 2074 | u32 pr_aptpl_buf_len; | 2009 | u32 pr_aptpl_buf_len; |
| 2075 | int ret, clear_aptpl_metadata = 0; | 2010 | int clear_aptpl_metadata = 0; |
| 2011 | int ret; | ||
| 2012 | |||
| 2076 | /* | 2013 | /* |
| 2077 | * Can be called with a NULL pointer from PROUT service action CLEAR | 2014 | * Can be called with a NULL pointer from PROUT service action CLEAR |
| 2078 | */ | 2015 | */ |
| @@ -2094,25 +2031,17 @@ static int core_scsi3_update_and_write_aptpl( | |||
| 2094 | clear_aptpl_metadata); | 2031 | clear_aptpl_metadata); |
| 2095 | if (ret != 0) | 2032 | if (ret != 0) |
| 2096 | return ret; | 2033 | return ret; |
| 2034 | |||
| 2097 | /* | 2035 | /* |
| 2098 | * __core_scsi3_write_aptpl_to_file() will call strlen() | 2036 | * __core_scsi3_write_aptpl_to_file() will call strlen() |
| 2099 | * on the passed buf to determine pr_aptpl_buf_len. | 2037 | * on the passed buf to determine pr_aptpl_buf_len. |
| 2100 | */ | 2038 | */ |
| 2101 | ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0); | 2039 | return __core_scsi3_write_aptpl_to_file(dev, buf, 0); |
| 2102 | if (ret != 0) | ||
| 2103 | return ret; | ||
| 2104 | |||
| 2105 | return ret; | ||
| 2106 | } | 2040 | } |
| 2107 | 2041 | ||
| 2108 | static int core_scsi3_emulate_pro_register( | 2042 | static sense_reason_t |
| 2109 | struct se_cmd *cmd, | 2043 | core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, |
| 2110 | u64 res_key, | 2044 | int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key) |
| 2111 | u64 sa_res_key, | ||
| 2112 | int aptpl, | ||
| 2113 | int all_tg_pt, | ||
| 2114 | int spec_i_pt, | ||
| 2115 | int ignore_key) | ||
| 2116 | { | 2045 | { |
| 2117 | struct se_session *se_sess = cmd->se_sess; | 2046 | struct se_session *se_sess = cmd->se_sess; |
| 2118 | struct se_device *dev = cmd->se_dev; | 2047 | struct se_device *dev = cmd->se_dev; |
| @@ -2120,16 +2049,16 @@ static int core_scsi3_emulate_pro_register( | |||
| 2120 | struct se_lun *se_lun = cmd->se_lun; | 2049 | struct se_lun *se_lun = cmd->se_lun; |
| 2121 | struct se_portal_group *se_tpg; | 2050 | struct se_portal_group *se_tpg; |
| 2122 | struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e; | 2051 | struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e; |
| 2123 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 2052 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 2124 | /* Used for APTPL metadata w/ UNREGISTER */ | 2053 | /* Used for APTPL metadata w/ UNREGISTER */ |
| 2125 | unsigned char *pr_aptpl_buf = NULL; | 2054 | unsigned char *pr_aptpl_buf = NULL; |
| 2126 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; | 2055 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; |
| 2127 | int pr_holder = 0, ret = 0, type; | 2056 | sense_reason_t ret; |
| 2057 | int pr_holder = 0, type; | ||
| 2128 | 2058 | ||
| 2129 | if (!se_sess || !se_lun) { | 2059 | if (!se_sess || !se_lun) { |
| 2130 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 2060 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
| 2131 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2061 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 2132 | return -EINVAL; | ||
| 2133 | } | 2062 | } |
| 2134 | se_tpg = se_sess->se_tpg; | 2063 | se_tpg = se_sess->se_tpg; |
| 2135 | se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; | 2064 | se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; |
| @@ -2148,8 +2077,7 @@ static int core_scsi3_emulate_pro_register( | |||
| 2148 | if (res_key) { | 2077 | if (res_key) { |
| 2149 | pr_warn("SPC-3 PR: Reservation Key non-zero" | 2078 | pr_warn("SPC-3 PR: Reservation Key non-zero" |
| 2150 | " for SA REGISTER, returning CONFLICT\n"); | 2079 | " for SA REGISTER, returning CONFLICT\n"); |
| 2151 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2080 | return TCM_RESERVATION_CONFLICT; |
| 2152 | return -EINVAL; | ||
| 2153 | } | 2081 | } |
| 2154 | /* | 2082 | /* |
| 2155 | * Do nothing but return GOOD status. | 2083 | * Do nothing but return GOOD status. |
| @@ -2163,15 +2091,13 @@ static int core_scsi3_emulate_pro_register( | |||
| 2163 | * Port Endpoint that the PRO was received from on the | 2091 | * Port Endpoint that the PRO was received from on the |
| 2164 | * Logical Unit of the SCSI device server. | 2092 | * Logical Unit of the SCSI device server. |
| 2165 | */ | 2093 | */ |
| 2166 | ret = core_scsi3_alloc_registration(cmd->se_dev, | 2094 | if (core_scsi3_alloc_registration(cmd->se_dev, |
| 2167 | se_sess->se_node_acl, se_deve, isid_ptr, | 2095 | se_sess->se_node_acl, se_deve, isid_ptr, |
| 2168 | sa_res_key, all_tg_pt, aptpl, | 2096 | sa_res_key, all_tg_pt, aptpl, |
| 2169 | ignore_key, 0); | 2097 | ignore_key, 0)) { |
| 2170 | if (ret != 0) { | ||
| 2171 | pr_err("Unable to allocate" | 2098 | pr_err("Unable to allocate" |
| 2172 | " struct t10_pr_registration\n"); | 2099 | " struct t10_pr_registration\n"); |
| 2173 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2100 | return TCM_INVALID_PARAMETER_LIST; |
| 2174 | return -EINVAL; | ||
| 2175 | } | 2101 | } |
| 2176 | } else { | 2102 | } else { |
| 2177 | /* | 2103 | /* |
| @@ -2205,201 +2131,192 @@ static int core_scsi3_emulate_pro_register( | |||
| 2205 | pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, | 2131 | pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, |
| 2206 | se_sess->se_node_acl, se_sess); | 2132 | se_sess->se_node_acl, se_sess); |
| 2207 | 2133 | ||
| 2208 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 2134 | if (core_scsi3_update_and_write_aptpl(cmd->se_dev, |
| 2209 | &pr_reg->pr_aptpl_buf[0], | 2135 | &pr_reg->pr_aptpl_buf[0], |
| 2210 | pr_tmpl->pr_aptpl_buf_len); | 2136 | pr_tmpl->pr_aptpl_buf_len)) { |
| 2211 | if (!ret) { | ||
| 2212 | pr_tmpl->pr_aptpl_active = 1; | 2137 | pr_tmpl->pr_aptpl_active = 1; |
| 2213 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); | 2138 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); |
| 2214 | } | 2139 | } |
| 2215 | 2140 | ||
| 2216 | core_scsi3_put_pr_reg(pr_reg); | 2141 | goto out_put_pr_reg; |
| 2217 | return ret; | 2142 | } |
| 2218 | } else { | 2143 | |
| 2219 | /* | 2144 | /* |
| 2220 | * Locate the existing *pr_reg via struct se_node_acl pointers | 2145 | * Locate the existing *pr_reg via struct se_node_acl pointers |
| 2221 | */ | 2146 | */ |
| 2222 | pr_reg = pr_reg_e; | 2147 | pr_reg = pr_reg_e; |
| 2223 | type = pr_reg->pr_res_type; | 2148 | type = pr_reg->pr_res_type; |
| 2224 | 2149 | ||
| 2225 | if (!ignore_key) { | 2150 | if (!ignore_key) { |
| 2226 | if (res_key != pr_reg->pr_res_key) { | 2151 | if (res_key != pr_reg->pr_res_key) { |
| 2227 | pr_err("SPC-3 PR REGISTER: Received" | 2152 | pr_err("SPC-3 PR REGISTER: Received" |
| 2228 | " res_key: 0x%016Lx does not match" | 2153 | " res_key: 0x%016Lx does not match" |
| 2229 | " existing SA REGISTER res_key:" | 2154 | " existing SA REGISTER res_key:" |
| 2230 | " 0x%016Lx\n", res_key, | 2155 | " 0x%016Lx\n", res_key, |
| 2231 | pr_reg->pr_res_key); | 2156 | pr_reg->pr_res_key); |
| 2232 | core_scsi3_put_pr_reg(pr_reg); | 2157 | ret = TCM_RESERVATION_CONFLICT; |
| 2233 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2158 | goto out_put_pr_reg; |
| 2234 | return -EINVAL; | ||
| 2235 | } | ||
| 2236 | } | 2159 | } |
| 2237 | if (spec_i_pt) { | 2160 | } |
| 2238 | pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" | 2161 | |
| 2239 | " set while sa_res_key=0\n"); | 2162 | if (spec_i_pt) { |
| 2240 | core_scsi3_put_pr_reg(pr_reg); | 2163 | pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" |
| 2241 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2164 | " set while sa_res_key=0\n"); |
| 2242 | return -EINVAL; | 2165 | ret = TCM_INVALID_PARAMETER_LIST; |
| 2166 | goto out_put_pr_reg; | ||
| 2167 | } | ||
| 2168 | |||
| 2169 | /* | ||
| 2170 | * An existing ALL_TG_PT=1 registration being released | ||
| 2171 | * must also set ALL_TG_PT=1 in the incoming PROUT. | ||
| 2172 | */ | ||
| 2173 | if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { | ||
| 2174 | pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" | ||
| 2175 | " registration exists, but ALL_TG_PT=1 bit not" | ||
| 2176 | " present in received PROUT\n"); | ||
| 2177 | ret = TCM_INVALID_CDB_FIELD; | ||
| 2178 | goto out_put_pr_reg; | ||
| 2179 | } | ||
| 2180 | |||
| 2181 | /* | ||
| 2182 | * Allocate APTPL metadata buffer used for UNREGISTER ops | ||
| 2183 | */ | ||
| 2184 | if (aptpl) { | ||
| 2185 | pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, | ||
| 2186 | GFP_KERNEL); | ||
| 2187 | if (!pr_aptpl_buf) { | ||
| 2188 | pr_err("Unable to allocate" | ||
| 2189 | " pr_aptpl_buf\n"); | ||
| 2190 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 2191 | goto out_put_pr_reg; | ||
| 2243 | } | 2192 | } |
| 2244 | /* | 2193 | } |
| 2245 | * An existing ALL_TG_PT=1 registration being released | 2194 | |
| 2246 | * must also set ALL_TG_PT=1 in the incoming PROUT. | 2195 | /* |
| 2247 | */ | 2196 | * sa_res_key=0 Unregister Reservation Key for registered I_T |
| 2248 | if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { | 2197 | * Nexus sa_res_key=1 Change Reservation Key for registered I_T |
| 2249 | pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" | 2198 | * Nexus. |
| 2250 | " registration exists, but ALL_TG_PT=1 bit not" | 2199 | */ |
| 2251 | " present in received PROUT\n"); | 2200 | if (!sa_res_key) { |
| 2252 | core_scsi3_put_pr_reg(pr_reg); | 2201 | pr_holder = core_scsi3_check_implict_release( |
| 2253 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 2202 | cmd->se_dev, pr_reg); |
| 2254 | return -EINVAL; | 2203 | if (pr_holder < 0) { |
| 2204 | kfree(pr_aptpl_buf); | ||
| 2205 | ret = TCM_RESERVATION_CONFLICT; | ||
| 2206 | goto out_put_pr_reg; | ||
| 2255 | } | 2207 | } |
| 2208 | |||
| 2209 | spin_lock(&pr_tmpl->registration_lock); | ||
| 2256 | /* | 2210 | /* |
| 2257 | * Allocate APTPL metadata buffer used for UNREGISTER ops | 2211 | * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port |
| 2212 | * and matching pr_res_key. | ||
| 2258 | */ | 2213 | */ |
| 2259 | if (aptpl) { | 2214 | if (pr_reg->pr_reg_all_tg_pt) { |
| 2260 | pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, | 2215 | list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, |
| 2261 | GFP_KERNEL); | 2216 | &pr_tmpl->registration_list, |
| 2262 | if (!pr_aptpl_buf) { | 2217 | pr_reg_list) { |
| 2263 | pr_err("Unable to allocate" | 2218 | |
| 2264 | " pr_aptpl_buf\n"); | 2219 | if (!pr_reg_p->pr_reg_all_tg_pt) |
| 2265 | core_scsi3_put_pr_reg(pr_reg); | 2220 | continue; |
| 2266 | cmd->scsi_sense_reason = | 2221 | if (pr_reg_p->pr_res_key != res_key) |
| 2267 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2222 | continue; |
| 2268 | return -EINVAL; | 2223 | if (pr_reg == pr_reg_p) |
| 2224 | continue; | ||
| 2225 | if (strcmp(pr_reg->pr_reg_nacl->initiatorname, | ||
| 2226 | pr_reg_p->pr_reg_nacl->initiatorname)) | ||
| 2227 | continue; | ||
| 2228 | |||
| 2229 | __core_scsi3_free_registration(dev, | ||
| 2230 | pr_reg_p, NULL, 0); | ||
| 2269 | } | 2231 | } |
| 2270 | } | 2232 | } |
| 2233 | |||
| 2271 | /* | 2234 | /* |
| 2272 | * sa_res_key=0 Unregister Reservation Key for registered I_T | 2235 | * Release the calling I_T Nexus registration now.. |
| 2273 | * Nexus sa_res_key=1 Change Reservation Key for registered I_T | ||
| 2274 | * Nexus. | ||
| 2275 | */ | 2236 | */ |
| 2276 | if (!sa_res_key) { | 2237 | __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1); |
| 2277 | pr_holder = core_scsi3_check_implict_release( | ||
| 2278 | cmd->se_dev, pr_reg); | ||
| 2279 | if (pr_holder < 0) { | ||
| 2280 | kfree(pr_aptpl_buf); | ||
| 2281 | core_scsi3_put_pr_reg(pr_reg); | ||
| 2282 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | ||
| 2283 | return -EINVAL; | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | spin_lock(&pr_tmpl->registration_lock); | ||
| 2287 | /* | ||
| 2288 | * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port | ||
| 2289 | * and matching pr_res_key. | ||
| 2290 | */ | ||
| 2291 | if (pr_reg->pr_reg_all_tg_pt) { | ||
| 2292 | list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, | ||
| 2293 | &pr_tmpl->registration_list, | ||
| 2294 | pr_reg_list) { | ||
| 2295 | |||
| 2296 | if (!pr_reg_p->pr_reg_all_tg_pt) | ||
| 2297 | continue; | ||
| 2298 | 2238 | ||
| 2299 | if (pr_reg_p->pr_res_key != res_key) | 2239 | /* |
| 2300 | continue; | 2240 | * From spc4r17, section 5.7.11.3 Unregistering |
| 2301 | 2241 | * | |
| 2302 | if (pr_reg == pr_reg_p) | 2242 | * If the persistent reservation is a registrants only |
| 2303 | continue; | 2243 | * type, the device server shall establish a unit |
| 2304 | 2244 | * attention condition for the initiator port associated | |
| 2305 | if (strcmp(pr_reg->pr_reg_nacl->initiatorname, | 2245 | * with every registered I_T nexus except for the I_T |
| 2306 | pr_reg_p->pr_reg_nacl->initiatorname)) | 2246 | * nexus on which the PERSISTENT RESERVE OUT command was |
| 2307 | continue; | 2247 | * received, with the additional sense code set to |
| 2308 | 2248 | * RESERVATIONS RELEASED. | |
| 2309 | __core_scsi3_free_registration(dev, | 2249 | */ |
| 2310 | pr_reg_p, NULL, 0); | 2250 | if (pr_holder && |
| 2311 | } | 2251 | (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || |
| 2312 | } | 2252 | type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { |
| 2313 | /* | 2253 | list_for_each_entry(pr_reg_p, |
| 2314 | * Release the calling I_T Nexus registration now.. | 2254 | &pr_tmpl->registration_list, |
| 2315 | */ | 2255 | pr_reg_list) { |
| 2316 | __core_scsi3_free_registration(cmd->se_dev, pr_reg, | 2256 | |
| 2317 | NULL, 1); | 2257 | core_scsi3_ua_allocate( |
| 2318 | /* | 2258 | pr_reg_p->pr_reg_nacl, |
| 2319 | * From spc4r17, section 5.7.11.3 Unregistering | 2259 | pr_reg_p->pr_res_mapped_lun, |
| 2320 | * | 2260 | 0x2A, |
| 2321 | * If the persistent reservation is a registrants only | 2261 | ASCQ_2AH_RESERVATIONS_RELEASED); |
| 2322 | * type, the device server shall establish a unit | ||
| 2323 | * attention condition for the initiator port associated | ||
| 2324 | * with every registered I_T nexus except for the I_T | ||
| 2325 | * nexus on which the PERSISTENT RESERVE OUT command was | ||
| 2326 | * received, with the additional sense code set to | ||
| 2327 | * RESERVATIONS RELEASED. | ||
| 2328 | */ | ||
| 2329 | if (pr_holder && | ||
| 2330 | ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) || | ||
| 2331 | (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) { | ||
| 2332 | list_for_each_entry(pr_reg_p, | ||
| 2333 | &pr_tmpl->registration_list, | ||
| 2334 | pr_reg_list) { | ||
| 2335 | |||
| 2336 | core_scsi3_ua_allocate( | ||
| 2337 | pr_reg_p->pr_reg_nacl, | ||
| 2338 | pr_reg_p->pr_res_mapped_lun, | ||
| 2339 | 0x2A, | ||
| 2340 | ASCQ_2AH_RESERVATIONS_RELEASED); | ||
| 2341 | } | ||
| 2342 | } | 2262 | } |
| 2343 | spin_unlock(&pr_tmpl->registration_lock); | 2263 | } |
| 2264 | spin_unlock(&pr_tmpl->registration_lock); | ||
| 2344 | 2265 | ||
| 2345 | if (!aptpl) { | 2266 | if (!aptpl) { |
| 2346 | pr_tmpl->pr_aptpl_active = 0; | 2267 | pr_tmpl->pr_aptpl_active = 0; |
| 2347 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); | 2268 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); |
| 2348 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" | 2269 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" |
| 2349 | " for UNREGISTER\n"); | 2270 | " for UNREGISTER\n"); |
| 2350 | return 0; | 2271 | return 0; |
| 2351 | } | 2272 | } |
| 2352 | 2273 | ||
| 2353 | ret = core_scsi3_update_and_write_aptpl(dev, | 2274 | if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], |
| 2354 | &pr_aptpl_buf[0], | 2275 | pr_tmpl->pr_aptpl_buf_len)) { |
| 2355 | pr_tmpl->pr_aptpl_buf_len); | 2276 | pr_tmpl->pr_aptpl_active = 1; |
| 2356 | if (!ret) { | 2277 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" |
| 2357 | pr_tmpl->pr_aptpl_active = 1; | 2278 | " for UNREGISTER\n"); |
| 2358 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" | 2279 | } |
| 2359 | " for UNREGISTER\n"); | ||
| 2360 | } | ||
| 2361 | 2280 | ||
| 2362 | kfree(pr_aptpl_buf); | 2281 | goto out_free_aptpl_buf; |
| 2363 | return ret; | 2282 | } |
| 2364 | } else { | ||
| 2365 | /* | ||
| 2366 | * Increment PRgeneration counter for struct se_device" | ||
| 2367 | * upon a successful REGISTER, see spc4r17 section 6.3.2 | ||
| 2368 | * READ_KEYS service action. | ||
| 2369 | */ | ||
| 2370 | pr_reg->pr_res_generation = core_scsi3_pr_generation( | ||
| 2371 | cmd->se_dev); | ||
| 2372 | pr_reg->pr_res_key = sa_res_key; | ||
| 2373 | pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" | ||
| 2374 | " Key for %s to: 0x%016Lx PRgeneration:" | ||
| 2375 | " 0x%08x\n", cmd->se_tfo->get_fabric_name(), | ||
| 2376 | (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", | ||
| 2377 | pr_reg->pr_reg_nacl->initiatorname, | ||
| 2378 | pr_reg->pr_res_key, pr_reg->pr_res_generation); | ||
| 2379 | |||
| 2380 | if (!aptpl) { | ||
| 2381 | pr_tmpl->pr_aptpl_active = 0; | ||
| 2382 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); | ||
| 2383 | core_scsi3_put_pr_reg(pr_reg); | ||
| 2384 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" | ||
| 2385 | " for REGISTER\n"); | ||
| 2386 | return 0; | ||
| 2387 | } | ||
| 2388 | 2283 | ||
| 2389 | ret = core_scsi3_update_and_write_aptpl(dev, | 2284 | /* |
| 2390 | &pr_aptpl_buf[0], | 2285 | * Increment PRgeneration counter for struct se_device" |
| 2391 | pr_tmpl->pr_aptpl_buf_len); | 2286 | * upon a successful REGISTER, see spc4r17 section 6.3.2 |
| 2392 | if (!ret) { | 2287 | * READ_KEYS service action. |
| 2393 | pr_tmpl->pr_aptpl_active = 1; | 2288 | */ |
| 2394 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" | 2289 | pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev); |
| 2395 | " for REGISTER\n"); | 2290 | pr_reg->pr_res_key = sa_res_key; |
| 2396 | } | 2291 | pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" |
| 2292 | " Key for %s to: 0x%016Lx PRgeneration:" | ||
| 2293 | " 0x%08x\n", cmd->se_tfo->get_fabric_name(), | ||
| 2294 | (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", | ||
| 2295 | pr_reg->pr_reg_nacl->initiatorname, | ||
| 2296 | pr_reg->pr_res_key, pr_reg->pr_res_generation); | ||
| 2397 | 2297 | ||
| 2398 | kfree(pr_aptpl_buf); | 2298 | if (!aptpl) { |
| 2399 | core_scsi3_put_pr_reg(pr_reg); | 2299 | pr_tmpl->pr_aptpl_active = 0; |
| 2400 | } | 2300 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); |
| 2301 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" | ||
| 2302 | " for REGISTER\n"); | ||
| 2303 | ret = 0; | ||
| 2304 | goto out_put_pr_reg; | ||
| 2401 | } | 2305 | } |
| 2402 | return 0; | 2306 | |
| 2307 | if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], | ||
| 2308 | pr_tmpl->pr_aptpl_buf_len)) { | ||
| 2309 | pr_tmpl->pr_aptpl_active = 1; | ||
| 2310 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" | ||
| 2311 | " for REGISTER\n"); | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | out_free_aptpl_buf: | ||
| 2315 | kfree(pr_aptpl_buf); | ||
| 2316 | ret = 0; | ||
| 2317 | out_put_pr_reg: | ||
| 2318 | core_scsi3_put_pr_reg(pr_reg); | ||
| 2319 | return ret; | ||
| 2403 | } | 2320 | } |
| 2404 | 2321 | ||
| 2405 | unsigned char *core_scsi3_pr_dump_type(int type) | 2322 | unsigned char *core_scsi3_pr_dump_type(int type) |
| @@ -2424,26 +2341,23 @@ unsigned char *core_scsi3_pr_dump_type(int type) | |||
| 2424 | return "Unknown SPC-3 PR Type"; | 2341 | return "Unknown SPC-3 PR Type"; |
| 2425 | } | 2342 | } |
| 2426 | 2343 | ||
| 2427 | static int core_scsi3_pro_reserve( | 2344 | static sense_reason_t |
| 2428 | struct se_cmd *cmd, | 2345 | core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) |
| 2429 | struct se_device *dev, | ||
| 2430 | int type, | ||
| 2431 | int scope, | ||
| 2432 | u64 res_key) | ||
| 2433 | { | 2346 | { |
| 2347 | struct se_device *dev = cmd->se_dev; | ||
| 2434 | struct se_session *se_sess = cmd->se_sess; | 2348 | struct se_session *se_sess = cmd->se_sess; |
| 2435 | struct se_lun *se_lun = cmd->se_lun; | 2349 | struct se_lun *se_lun = cmd->se_lun; |
| 2436 | struct t10_pr_registration *pr_reg, *pr_res_holder; | 2350 | struct t10_pr_registration *pr_reg, *pr_res_holder; |
| 2437 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 2351 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 2438 | char i_buf[PR_REG_ISID_ID_LEN]; | 2352 | char i_buf[PR_REG_ISID_ID_LEN]; |
| 2439 | int ret, prf_isid; | 2353 | sense_reason_t ret; |
| 2354 | int prf_isid; | ||
| 2440 | 2355 | ||
| 2441 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); | 2356 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); |
| 2442 | 2357 | ||
| 2443 | if (!se_sess || !se_lun) { | 2358 | if (!se_sess || !se_lun) { |
| 2444 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 2359 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
| 2445 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2360 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 2446 | return -EINVAL; | ||
| 2447 | } | 2361 | } |
| 2448 | /* | 2362 | /* |
| 2449 | * Locate the existing *pr_reg via struct se_node_acl pointers | 2363 | * Locate the existing *pr_reg via struct se_node_acl pointers |
| @@ -2453,8 +2367,7 @@ static int core_scsi3_pro_reserve( | |||
| 2453 | if (!pr_reg) { | 2367 | if (!pr_reg) { |
| 2454 | pr_err("SPC-3 PR: Unable to locate" | 2368 | pr_err("SPC-3 PR: Unable to locate" |
| 2455 | " PR_REGISTERED *pr_reg for RESERVE\n"); | 2369 | " PR_REGISTERED *pr_reg for RESERVE\n"); |
| 2456 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2370 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 2457 | return -EINVAL; | ||
| 2458 | } | 2371 | } |
| 2459 | /* | 2372 | /* |
| 2460 | * From spc4r17 Section 5.7.9: Reserving: | 2373 | * From spc4r17 Section 5.7.9: Reserving: |
| @@ -2469,9 +2382,8 @@ static int core_scsi3_pro_reserve( | |||
| 2469 | pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" | 2382 | pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" |
| 2470 | " does not match existing SA REGISTER res_key:" | 2383 | " does not match existing SA REGISTER res_key:" |
| 2471 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); | 2384 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); |
| 2472 | core_scsi3_put_pr_reg(pr_reg); | 2385 | ret = TCM_RESERVATION_CONFLICT; |
| 2473 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2386 | goto out_put_pr_reg; |
| 2474 | return -EINVAL; | ||
| 2475 | } | 2387 | } |
| 2476 | /* | 2388 | /* |
| 2477 | * From spc4r17 Section 5.7.9: Reserving: | 2389 | * From spc4r17 Section 5.7.9: Reserving: |
| @@ -2485,9 +2397,8 @@ static int core_scsi3_pro_reserve( | |||
| 2485 | */ | 2397 | */ |
| 2486 | if (scope != PR_SCOPE_LU_SCOPE) { | 2398 | if (scope != PR_SCOPE_LU_SCOPE) { |
| 2487 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); | 2399 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); |
| 2488 | core_scsi3_put_pr_reg(pr_reg); | 2400 | ret = TCM_INVALID_PARAMETER_LIST; |
| 2489 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2401 | goto out_put_pr_reg; |
| 2490 | return -EINVAL; | ||
| 2491 | } | 2402 | } |
| 2492 | /* | 2403 | /* |
| 2493 | * See if we have an existing PR reservation holder pointer at | 2404 | * See if we have an existing PR reservation holder pointer at |
| @@ -2518,9 +2429,8 @@ static int core_scsi3_pro_reserve( | |||
| 2518 | pr_res_holder->pr_reg_nacl->initiatorname); | 2429 | pr_res_holder->pr_reg_nacl->initiatorname); |
| 2519 | 2430 | ||
| 2520 | spin_unlock(&dev->dev_reservation_lock); | 2431 | spin_unlock(&dev->dev_reservation_lock); |
| 2521 | core_scsi3_put_pr_reg(pr_reg); | 2432 | ret = TCM_RESERVATION_CONFLICT; |
| 2522 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2433 | goto out_put_pr_reg; |
| 2523 | return -EINVAL; | ||
| 2524 | } | 2434 | } |
| 2525 | /* | 2435 | /* |
| 2526 | * From spc4r17 Section 5.7.9: Reserving: | 2436 | * From spc4r17 Section 5.7.9: Reserving: |
| @@ -2542,9 +2452,8 @@ static int core_scsi3_pro_reserve( | |||
| 2542 | pr_res_holder->pr_reg_nacl->initiatorname); | 2452 | pr_res_holder->pr_reg_nacl->initiatorname); |
| 2543 | 2453 | ||
| 2544 | spin_unlock(&dev->dev_reservation_lock); | 2454 | spin_unlock(&dev->dev_reservation_lock); |
| 2545 | core_scsi3_put_pr_reg(pr_reg); | 2455 | ret = TCM_RESERVATION_CONFLICT; |
| 2546 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2456 | goto out_put_pr_reg; |
| 2547 | return -EINVAL; | ||
| 2548 | } | 2457 | } |
| 2549 | /* | 2458 | /* |
| 2550 | * From spc4r17 Section 5.7.9: Reserving: | 2459 | * From spc4r17 Section 5.7.9: Reserving: |
| @@ -2557,8 +2466,8 @@ static int core_scsi3_pro_reserve( | |||
| 2557 | * shall completethe command with GOOD status. | 2466 | * shall completethe command with GOOD status. |
| 2558 | */ | 2467 | */ |
| 2559 | spin_unlock(&dev->dev_reservation_lock); | 2468 | spin_unlock(&dev->dev_reservation_lock); |
| 2560 | core_scsi3_put_pr_reg(pr_reg); | 2469 | ret = 0; |
| 2561 | return 0; | 2470 | goto out_put_pr_reg; |
| 2562 | } | 2471 | } |
| 2563 | /* | 2472 | /* |
| 2564 | * Otherwise, our *pr_reg becomes the PR reservation holder for said | 2473 | * Otherwise, our *pr_reg becomes the PR reservation holder for said |
| @@ -2582,27 +2491,24 @@ static int core_scsi3_pro_reserve( | |||
| 2582 | spin_unlock(&dev->dev_reservation_lock); | 2491 | spin_unlock(&dev->dev_reservation_lock); |
| 2583 | 2492 | ||
| 2584 | if (pr_tmpl->pr_aptpl_active) { | 2493 | if (pr_tmpl->pr_aptpl_active) { |
| 2585 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 2494 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
| 2586 | &pr_reg->pr_aptpl_buf[0], | 2495 | &pr_reg->pr_aptpl_buf[0], |
| 2587 | pr_tmpl->pr_aptpl_buf_len); | 2496 | pr_tmpl->pr_aptpl_buf_len)) { |
| 2588 | if (!ret) | ||
| 2589 | pr_debug("SPC-3 PR: Updated APTPL metadata" | 2497 | pr_debug("SPC-3 PR: Updated APTPL metadata" |
| 2590 | " for RESERVE\n"); | 2498 | " for RESERVE\n"); |
| 2499 | } | ||
| 2591 | } | 2500 | } |
| 2592 | 2501 | ||
| 2502 | ret = 0; | ||
| 2503 | out_put_pr_reg: | ||
| 2593 | core_scsi3_put_pr_reg(pr_reg); | 2504 | core_scsi3_put_pr_reg(pr_reg); |
| 2594 | return 0; | 2505 | return ret; |
| 2595 | } | 2506 | } |
| 2596 | 2507 | ||
| 2597 | static int core_scsi3_emulate_pro_reserve( | 2508 | static sense_reason_t |
| 2598 | struct se_cmd *cmd, | 2509 | core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope, |
| 2599 | int type, | 2510 | u64 res_key) |
| 2600 | int scope, | ||
| 2601 | u64 res_key) | ||
| 2602 | { | 2511 | { |
| 2603 | struct se_device *dev = cmd->se_dev; | ||
| 2604 | int ret = 0; | ||
| 2605 | |||
| 2606 | switch (type) { | 2512 | switch (type) { |
| 2607 | case PR_TYPE_WRITE_EXCLUSIVE: | 2513 | case PR_TYPE_WRITE_EXCLUSIVE: |
| 2608 | case PR_TYPE_EXCLUSIVE_ACCESS: | 2514 | case PR_TYPE_EXCLUSIVE_ACCESS: |
| @@ -2610,16 +2516,12 @@ static int core_scsi3_emulate_pro_reserve( | |||
| 2610 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: | 2516 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: |
| 2611 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: | 2517 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: |
| 2612 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: | 2518 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: |
| 2613 | ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key); | 2519 | return core_scsi3_pro_reserve(cmd, type, scope, res_key); |
| 2614 | break; | ||
| 2615 | default: | 2520 | default: |
| 2616 | pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" | 2521 | pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" |
| 2617 | " 0x%02x\n", type); | 2522 | " 0x%02x\n", type); |
| 2618 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 2523 | return TCM_INVALID_CDB_FIELD; |
| 2619 | return -EINVAL; | ||
| 2620 | } | 2524 | } |
| 2621 | |||
| 2622 | return ret; | ||
| 2623 | } | 2525 | } |
| 2624 | 2526 | ||
| 2625 | /* | 2527 | /* |
| @@ -2657,23 +2559,21 @@ static void __core_scsi3_complete_pro_release( | |||
| 2657 | pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; | 2559 | pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; |
| 2658 | } | 2560 | } |
| 2659 | 2561 | ||
| 2660 | static int core_scsi3_emulate_pro_release( | 2562 | static sense_reason_t |
| 2661 | struct se_cmd *cmd, | 2563 | core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, |
| 2662 | int type, | 2564 | u64 res_key) |
| 2663 | int scope, | ||
| 2664 | u64 res_key) | ||
| 2665 | { | 2565 | { |
| 2666 | struct se_device *dev = cmd->se_dev; | 2566 | struct se_device *dev = cmd->se_dev; |
| 2667 | struct se_session *se_sess = cmd->se_sess; | 2567 | struct se_session *se_sess = cmd->se_sess; |
| 2668 | struct se_lun *se_lun = cmd->se_lun; | 2568 | struct se_lun *se_lun = cmd->se_lun; |
| 2669 | struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; | 2569 | struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; |
| 2670 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 2570 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 2671 | int ret, all_reg = 0; | 2571 | int all_reg = 0; |
| 2572 | sense_reason_t ret = 0; | ||
| 2672 | 2573 | ||
| 2673 | if (!se_sess || !se_lun) { | 2574 | if (!se_sess || !se_lun) { |
| 2674 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 2575 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
| 2675 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2576 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 2676 | return -EINVAL; | ||
| 2677 | } | 2577 | } |
| 2678 | /* | 2578 | /* |
| 2679 | * Locate the existing *pr_reg via struct se_node_acl pointers | 2579 | * Locate the existing *pr_reg via struct se_node_acl pointers |
| @@ -2682,8 +2582,7 @@ static int core_scsi3_emulate_pro_release( | |||
| 2682 | if (!pr_reg) { | 2582 | if (!pr_reg) { |
| 2683 | pr_err("SPC-3 PR: Unable to locate" | 2583 | pr_err("SPC-3 PR: Unable to locate" |
| 2684 | " PR_REGISTERED *pr_reg for RELEASE\n"); | 2584 | " PR_REGISTERED *pr_reg for RELEASE\n"); |
| 2685 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2585 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 2686 | return -EINVAL; | ||
| 2687 | } | 2586 | } |
| 2688 | /* | 2587 | /* |
| 2689 | * From spc4r17 Section 5.7.11.2 Releasing: | 2588 | * From spc4r17 Section 5.7.11.2 Releasing: |
| @@ -2704,8 +2603,7 @@ static int core_scsi3_emulate_pro_release( | |||
| 2704 | * No persistent reservation, return GOOD status. | 2603 | * No persistent reservation, return GOOD status. |
| 2705 | */ | 2604 | */ |
| 2706 | spin_unlock(&dev->dev_reservation_lock); | 2605 | spin_unlock(&dev->dev_reservation_lock); |
| 2707 | core_scsi3_put_pr_reg(pr_reg); | 2606 | goto out_put_pr_reg; |
| 2708 | return 0; | ||
| 2709 | } | 2607 | } |
| 2710 | if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || | 2608 | if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || |
| 2711 | (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) | 2609 | (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) |
| @@ -2718,9 +2616,9 @@ static int core_scsi3_emulate_pro_release( | |||
| 2718 | * persistent reservation holder. return GOOD status. | 2616 | * persistent reservation holder. return GOOD status. |
| 2719 | */ | 2617 | */ |
| 2720 | spin_unlock(&dev->dev_reservation_lock); | 2618 | spin_unlock(&dev->dev_reservation_lock); |
| 2721 | core_scsi3_put_pr_reg(pr_reg); | 2619 | goto out_put_pr_reg; |
| 2722 | return 0; | ||
| 2723 | } | 2620 | } |
| 2621 | |||
| 2724 | /* | 2622 | /* |
| 2725 | * From spc4r17 Section 5.7.11.2 Releasing: | 2623 | * From spc4r17 Section 5.7.11.2 Releasing: |
| 2726 | * | 2624 | * |
| @@ -2740,9 +2638,8 @@ static int core_scsi3_emulate_pro_release( | |||
| 2740 | " does not match existing SA REGISTER res_key:" | 2638 | " does not match existing SA REGISTER res_key:" |
| 2741 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); | 2639 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); |
| 2742 | spin_unlock(&dev->dev_reservation_lock); | 2640 | spin_unlock(&dev->dev_reservation_lock); |
| 2743 | core_scsi3_put_pr_reg(pr_reg); | 2641 | ret = TCM_RESERVATION_CONFLICT; |
| 2744 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2642 | goto out_put_pr_reg; |
| 2745 | return -EINVAL; | ||
| 2746 | } | 2643 | } |
| 2747 | /* | 2644 | /* |
| 2748 | * From spc4r17 Section 5.7.11.2 Releasing and above: | 2645 | * From spc4r17 Section 5.7.11.2 Releasing and above: |
| @@ -2763,9 +2660,8 @@ static int core_scsi3_emulate_pro_release( | |||
| 2763 | pr_res_holder->pr_reg_nacl->initiatorname); | 2660 | pr_res_holder->pr_reg_nacl->initiatorname); |
| 2764 | 2661 | ||
| 2765 | spin_unlock(&dev->dev_reservation_lock); | 2662 | spin_unlock(&dev->dev_reservation_lock); |
| 2766 | core_scsi3_put_pr_reg(pr_reg); | 2663 | ret = TCM_RESERVATION_CONFLICT; |
| 2767 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2664 | goto out_put_pr_reg; |
| 2768 | return -EINVAL; | ||
| 2769 | } | 2665 | } |
| 2770 | /* | 2666 | /* |
| 2771 | * In response to a persistent reservation release request from the | 2667 | * In response to a persistent reservation release request from the |
| @@ -2818,25 +2714,23 @@ static int core_scsi3_emulate_pro_release( | |||
| 2818 | 2714 | ||
| 2819 | write_aptpl: | 2715 | write_aptpl: |
| 2820 | if (pr_tmpl->pr_aptpl_active) { | 2716 | if (pr_tmpl->pr_aptpl_active) { |
| 2821 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 2717 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
| 2822 | &pr_reg->pr_aptpl_buf[0], | 2718 | &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { |
| 2823 | pr_tmpl->pr_aptpl_buf_len); | ||
| 2824 | if (!ret) | ||
| 2825 | pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); | 2719 | pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); |
| 2720 | } | ||
| 2826 | } | 2721 | } |
| 2827 | 2722 | out_put_pr_reg: | |
| 2828 | core_scsi3_put_pr_reg(pr_reg); | 2723 | core_scsi3_put_pr_reg(pr_reg); |
| 2829 | return 0; | 2724 | return ret; |
| 2830 | } | 2725 | } |
| 2831 | 2726 | ||
| 2832 | static int core_scsi3_emulate_pro_clear( | 2727 | static sense_reason_t |
| 2833 | struct se_cmd *cmd, | 2728 | core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) |
| 2834 | u64 res_key) | ||
| 2835 | { | 2729 | { |
| 2836 | struct se_device *dev = cmd->se_dev; | 2730 | struct se_device *dev = cmd->se_dev; |
| 2837 | struct se_node_acl *pr_reg_nacl; | 2731 | struct se_node_acl *pr_reg_nacl; |
| 2838 | struct se_session *se_sess = cmd->se_sess; | 2732 | struct se_session *se_sess = cmd->se_sess; |
| 2839 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 2733 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 2840 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; | 2734 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; |
| 2841 | u32 pr_res_mapped_lun = 0; | 2735 | u32 pr_res_mapped_lun = 0; |
| 2842 | int calling_it_nexus = 0; | 2736 | int calling_it_nexus = 0; |
| @@ -2848,8 +2742,7 @@ static int core_scsi3_emulate_pro_clear( | |||
| 2848 | if (!pr_reg_n) { | 2742 | if (!pr_reg_n) { |
| 2849 | pr_err("SPC-3 PR: Unable to locate" | 2743 | pr_err("SPC-3 PR: Unable to locate" |
| 2850 | " PR_REGISTERED *pr_reg for CLEAR\n"); | 2744 | " PR_REGISTERED *pr_reg for CLEAR\n"); |
| 2851 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2745 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 2852 | return -EINVAL; | ||
| 2853 | } | 2746 | } |
| 2854 | /* | 2747 | /* |
| 2855 | * From spc4r17 section 5.7.11.6, Clearing: | 2748 | * From spc4r17 section 5.7.11.6, Clearing: |
| @@ -2868,8 +2761,7 @@ static int core_scsi3_emulate_pro_clear( | |||
| 2868 | " existing SA REGISTER res_key:" | 2761 | " existing SA REGISTER res_key:" |
| 2869 | " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); | 2762 | " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); |
| 2870 | core_scsi3_put_pr_reg(pr_reg_n); | 2763 | core_scsi3_put_pr_reg(pr_reg_n); |
| 2871 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2764 | return TCM_RESERVATION_CONFLICT; |
| 2872 | return -EINVAL; | ||
| 2873 | } | 2765 | } |
| 2874 | /* | 2766 | /* |
| 2875 | * a) Release the persistent reservation, if any; | 2767 | * a) Release the persistent reservation, if any; |
| @@ -2993,28 +2885,22 @@ static void core_scsi3_release_preempt_and_abort( | |||
| 2993 | } | 2885 | } |
| 2994 | } | 2886 | } |
| 2995 | 2887 | ||
| 2996 | static int core_scsi3_pro_preempt( | 2888 | static sense_reason_t |
| 2997 | struct se_cmd *cmd, | 2889 | core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, |
| 2998 | int type, | 2890 | u64 sa_res_key, int abort) |
| 2999 | int scope, | ||
| 3000 | u64 res_key, | ||
| 3001 | u64 sa_res_key, | ||
| 3002 | int abort) | ||
| 3003 | { | 2891 | { |
| 3004 | struct se_device *dev = cmd->se_dev; | 2892 | struct se_device *dev = cmd->se_dev; |
| 3005 | struct se_node_acl *pr_reg_nacl; | 2893 | struct se_node_acl *pr_reg_nacl; |
| 3006 | struct se_session *se_sess = cmd->se_sess; | 2894 | struct se_session *se_sess = cmd->se_sess; |
| 3007 | LIST_HEAD(preempt_and_abort_list); | 2895 | LIST_HEAD(preempt_and_abort_list); |
| 3008 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; | 2896 | struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; |
| 3009 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 2897 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 3010 | u32 pr_res_mapped_lun = 0; | 2898 | u32 pr_res_mapped_lun = 0; |
| 3011 | int all_reg = 0, calling_it_nexus = 0, released_regs = 0; | 2899 | int all_reg = 0, calling_it_nexus = 0, released_regs = 0; |
| 3012 | int prh_type = 0, prh_scope = 0, ret; | 2900 | int prh_type = 0, prh_scope = 0; |
| 3013 | 2901 | ||
| 3014 | if (!se_sess) { | 2902 | if (!se_sess) |
| 3015 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2903 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3016 | return -EINVAL; | ||
| 3017 | } | ||
| 3018 | 2904 | ||
| 3019 | pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, | 2905 | pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, |
| 3020 | se_sess); | 2906 | se_sess); |
| @@ -3022,19 +2908,16 @@ static int core_scsi3_pro_preempt( | |||
| 3022 | pr_err("SPC-3 PR: Unable to locate" | 2908 | pr_err("SPC-3 PR: Unable to locate" |
| 3023 | " PR_REGISTERED *pr_reg for PREEMPT%s\n", | 2909 | " PR_REGISTERED *pr_reg for PREEMPT%s\n", |
| 3024 | (abort) ? "_AND_ABORT" : ""); | 2910 | (abort) ? "_AND_ABORT" : ""); |
| 3025 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2911 | return TCM_RESERVATION_CONFLICT; |
| 3026 | return -EINVAL; | ||
| 3027 | } | 2912 | } |
| 3028 | if (pr_reg_n->pr_res_key != res_key) { | 2913 | if (pr_reg_n->pr_res_key != res_key) { |
| 3029 | core_scsi3_put_pr_reg(pr_reg_n); | 2914 | core_scsi3_put_pr_reg(pr_reg_n); |
| 3030 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2915 | return TCM_RESERVATION_CONFLICT; |
| 3031 | return -EINVAL; | ||
| 3032 | } | 2916 | } |
| 3033 | if (scope != PR_SCOPE_LU_SCOPE) { | 2917 | if (scope != PR_SCOPE_LU_SCOPE) { |
| 3034 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); | 2918 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); |
| 3035 | core_scsi3_put_pr_reg(pr_reg_n); | 2919 | core_scsi3_put_pr_reg(pr_reg_n); |
| 3036 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2920 | return TCM_INVALID_PARAMETER_LIST; |
| 3037 | return -EINVAL; | ||
| 3038 | } | 2921 | } |
| 3039 | 2922 | ||
| 3040 | spin_lock(&dev->dev_reservation_lock); | 2923 | spin_lock(&dev->dev_reservation_lock); |
| @@ -3047,8 +2930,7 @@ static int core_scsi3_pro_preempt( | |||
| 3047 | if (!all_reg && !sa_res_key) { | 2930 | if (!all_reg && !sa_res_key) { |
| 3048 | spin_unlock(&dev->dev_reservation_lock); | 2931 | spin_unlock(&dev->dev_reservation_lock); |
| 3049 | core_scsi3_put_pr_reg(pr_reg_n); | 2932 | core_scsi3_put_pr_reg(pr_reg_n); |
| 3050 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2933 | return TCM_INVALID_PARAMETER_LIST; |
| 3051 | return -EINVAL; | ||
| 3052 | } | 2934 | } |
| 3053 | /* | 2935 | /* |
| 3054 | * From spc4r17, section 5.7.11.4.4 Removing Registrations: | 2936 | * From spc4r17, section 5.7.11.4.4 Removing Registrations: |
| @@ -3142,8 +3024,7 @@ static int core_scsi3_pro_preempt( | |||
| 3142 | if (!released_regs) { | 3024 | if (!released_regs) { |
| 3143 | spin_unlock(&dev->dev_reservation_lock); | 3025 | spin_unlock(&dev->dev_reservation_lock); |
| 3144 | core_scsi3_put_pr_reg(pr_reg_n); | 3026 | core_scsi3_put_pr_reg(pr_reg_n); |
| 3145 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3027 | return TCM_RESERVATION_CONFLICT; |
| 3146 | return -EINVAL; | ||
| 3147 | } | 3028 | } |
| 3148 | /* | 3029 | /* |
| 3149 | * For an existing all registrants type reservation | 3030 | * For an existing all registrants type reservation |
| @@ -3162,13 +3043,13 @@ static int core_scsi3_pro_preempt( | |||
| 3162 | spin_unlock(&dev->dev_reservation_lock); | 3043 | spin_unlock(&dev->dev_reservation_lock); |
| 3163 | 3044 | ||
| 3164 | if (pr_tmpl->pr_aptpl_active) { | 3045 | if (pr_tmpl->pr_aptpl_active) { |
| 3165 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 3046 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
| 3166 | &pr_reg_n->pr_aptpl_buf[0], | 3047 | &pr_reg_n->pr_aptpl_buf[0], |
| 3167 | pr_tmpl->pr_aptpl_buf_len); | 3048 | pr_tmpl->pr_aptpl_buf_len)) { |
| 3168 | if (!ret) | ||
| 3169 | pr_debug("SPC-3 PR: Updated APTPL" | 3049 | pr_debug("SPC-3 PR: Updated APTPL" |
| 3170 | " metadata for PREEMPT%s\n", (abort) ? | 3050 | " metadata for PREEMPT%s\n", (abort) ? |
| 3171 | "_AND_ABORT" : ""); | 3051 | "_AND_ABORT" : ""); |
| 3052 | } | ||
| 3172 | } | 3053 | } |
| 3173 | 3054 | ||
| 3174 | core_scsi3_put_pr_reg(pr_reg_n); | 3055 | core_scsi3_put_pr_reg(pr_reg_n); |
| @@ -3298,12 +3179,12 @@ static int core_scsi3_pro_preempt( | |||
| 3298 | } | 3179 | } |
| 3299 | 3180 | ||
| 3300 | if (pr_tmpl->pr_aptpl_active) { | 3181 | if (pr_tmpl->pr_aptpl_active) { |
| 3301 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 3182 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
| 3302 | &pr_reg_n->pr_aptpl_buf[0], | 3183 | &pr_reg_n->pr_aptpl_buf[0], |
| 3303 | pr_tmpl->pr_aptpl_buf_len); | 3184 | pr_tmpl->pr_aptpl_buf_len)) { |
| 3304 | if (!ret) | ||
| 3305 | pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" | 3185 | pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" |
| 3306 | "%s\n", (abort) ? "_AND_ABORT" : ""); | 3186 | "%s\n", abort ? "_AND_ABORT" : ""); |
| 3187 | } | ||
| 3307 | } | 3188 | } |
| 3308 | 3189 | ||
| 3309 | core_scsi3_put_pr_reg(pr_reg_n); | 3190 | core_scsi3_put_pr_reg(pr_reg_n); |
| @@ -3311,16 +3192,10 @@ static int core_scsi3_pro_preempt( | |||
| 3311 | return 0; | 3192 | return 0; |
| 3312 | } | 3193 | } |
| 3313 | 3194 | ||
| 3314 | static int core_scsi3_emulate_pro_preempt( | 3195 | static sense_reason_t |
| 3315 | struct se_cmd *cmd, | 3196 | core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope, |
| 3316 | int type, | 3197 | u64 res_key, u64 sa_res_key, int abort) |
| 3317 | int scope, | ||
| 3318 | u64 res_key, | ||
| 3319 | u64 sa_res_key, | ||
| 3320 | int abort) | ||
| 3321 | { | 3198 | { |
| 3322 | int ret = 0; | ||
| 3323 | |||
| 3324 | switch (type) { | 3199 | switch (type) { |
| 3325 | case PR_TYPE_WRITE_EXCLUSIVE: | 3200 | case PR_TYPE_WRITE_EXCLUSIVE: |
| 3326 | case PR_TYPE_EXCLUSIVE_ACCESS: | 3201 | case PR_TYPE_EXCLUSIVE_ACCESS: |
| @@ -3328,26 +3203,19 @@ static int core_scsi3_emulate_pro_preempt( | |||
| 3328 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: | 3203 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: |
| 3329 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: | 3204 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: |
| 3330 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: | 3205 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: |
| 3331 | ret = core_scsi3_pro_preempt(cmd, type, scope, | 3206 | return core_scsi3_pro_preempt(cmd, type, scope, res_key, |
| 3332 | res_key, sa_res_key, abort); | 3207 | sa_res_key, abort); |
| 3333 | break; | ||
| 3334 | default: | 3208 | default: |
| 3335 | pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" | 3209 | pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" |
| 3336 | " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); | 3210 | " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); |
| 3337 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3211 | return TCM_INVALID_CDB_FIELD; |
| 3338 | return -EINVAL; | ||
| 3339 | } | 3212 | } |
| 3340 | |||
| 3341 | return ret; | ||
| 3342 | } | 3213 | } |
| 3343 | 3214 | ||
| 3344 | 3215 | ||
| 3345 | static int core_scsi3_emulate_pro_register_and_move( | 3216 | static sense_reason_t |
| 3346 | struct se_cmd *cmd, | 3217 | core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, |
| 3347 | u64 res_key, | 3218 | u64 sa_res_key, int aptpl, int unreg) |
| 3348 | u64 sa_res_key, | ||
| 3349 | int aptpl, | ||
| 3350 | int unreg) | ||
| 3351 | { | 3219 | { |
| 3352 | struct se_session *se_sess = cmd->se_sess; | 3220 | struct se_session *se_sess = cmd->se_sess; |
| 3353 | struct se_device *dev = cmd->se_dev; | 3221 | struct se_device *dev = cmd->se_dev; |
| @@ -3358,20 +3226,21 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3358 | struct se_portal_group *se_tpg, *dest_se_tpg = NULL; | 3226 | struct se_portal_group *se_tpg, *dest_se_tpg = NULL; |
| 3359 | struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops; | 3227 | struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops; |
| 3360 | struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg; | 3228 | struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg; |
| 3361 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 3229 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 3362 | unsigned char *buf; | 3230 | unsigned char *buf; |
| 3363 | unsigned char *initiator_str; | 3231 | unsigned char *initiator_str; |
| 3364 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; | 3232 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; |
| 3365 | u32 tid_len, tmp_tid_len; | 3233 | u32 tid_len, tmp_tid_len; |
| 3366 | int new_reg = 0, type, scope, ret, matching_iname, prf_isid; | 3234 | int new_reg = 0, type, scope, matching_iname, prf_isid; |
| 3235 | sense_reason_t ret; | ||
| 3367 | unsigned short rtpi; | 3236 | unsigned short rtpi; |
| 3368 | unsigned char proto_ident; | 3237 | unsigned char proto_ident; |
| 3369 | 3238 | ||
| 3370 | if (!se_sess || !se_lun) { | 3239 | if (!se_sess || !se_lun) { |
| 3371 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 3240 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
| 3372 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3241 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3373 | return -EINVAL; | ||
| 3374 | } | 3242 | } |
| 3243 | |||
| 3375 | memset(dest_iport, 0, 64); | 3244 | memset(dest_iport, 0, 64); |
| 3376 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); | 3245 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); |
| 3377 | se_tpg = se_sess->se_tpg; | 3246 | se_tpg = se_sess->se_tpg; |
| @@ -3387,8 +3256,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3387 | if (!pr_reg) { | 3256 | if (!pr_reg) { |
| 3388 | pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" | 3257 | pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" |
| 3389 | " *pr_reg for REGISTER_AND_MOVE\n"); | 3258 | " *pr_reg for REGISTER_AND_MOVE\n"); |
| 3390 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3259 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3391 | return -EINVAL; | ||
| 3392 | } | 3260 | } |
| 3393 | /* | 3261 | /* |
| 3394 | * The provided reservation key much match the existing reservation key | 3262 | * The provided reservation key much match the existing reservation key |
| @@ -3398,9 +3266,8 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3398 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" | 3266 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" |
| 3399 | " res_key: 0x%016Lx does not match existing SA REGISTER" | 3267 | " res_key: 0x%016Lx does not match existing SA REGISTER" |
| 3400 | " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); | 3268 | " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); |
| 3401 | core_scsi3_put_pr_reg(pr_reg); | 3269 | ret = TCM_RESERVATION_CONFLICT; |
| 3402 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3270 | goto out_put_pr_reg; |
| 3403 | return -EINVAL; | ||
| 3404 | } | 3271 | } |
| 3405 | /* | 3272 | /* |
| 3406 | * The service active reservation key needs to be non zero | 3273 | * The service active reservation key needs to be non zero |
| @@ -3408,9 +3275,8 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3408 | if (!sa_res_key) { | 3275 | if (!sa_res_key) { |
| 3409 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" | 3276 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" |
| 3410 | " sa_res_key\n"); | 3277 | " sa_res_key\n"); |
| 3411 | core_scsi3_put_pr_reg(pr_reg); | 3278 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3412 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3279 | goto out_put_pr_reg; |
| 3413 | return -EINVAL; | ||
| 3414 | } | 3280 | } |
| 3415 | 3281 | ||
| 3416 | /* | 3282 | /* |
| @@ -3419,6 +3285,11 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3419 | * information. | 3285 | * information. |
| 3420 | */ | 3286 | */ |
| 3421 | buf = transport_kmap_data_sg(cmd); | 3287 | buf = transport_kmap_data_sg(cmd); |
| 3288 | if (!buf) { | ||
| 3289 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 3290 | goto out_put_pr_reg; | ||
| 3291 | } | ||
| 3292 | |||
| 3422 | rtpi = (buf[18] & 0xff) << 8; | 3293 | rtpi = (buf[18] & 0xff) << 8; |
| 3423 | rtpi |= buf[19] & 0xff; | 3294 | rtpi |= buf[19] & 0xff; |
| 3424 | tid_len = (buf[20] & 0xff) << 24; | 3295 | tid_len = (buf[20] & 0xff) << 24; |
| @@ -3432,9 +3303,8 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3432 | pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" | 3303 | pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" |
| 3433 | " does not equal CDB data_length: %u\n", tid_len, | 3304 | " does not equal CDB data_length: %u\n", tid_len, |
| 3434 | cmd->data_length); | 3305 | cmd->data_length); |
| 3435 | core_scsi3_put_pr_reg(pr_reg); | 3306 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3436 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3307 | goto out_put_pr_reg; |
| 3437 | return -EINVAL; | ||
| 3438 | } | 3308 | } |
| 3439 | 3309 | ||
| 3440 | spin_lock(&dev->se_port_lock); | 3310 | spin_lock(&dev->se_port_lock); |
| @@ -3452,15 +3322,13 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3452 | smp_mb__after_atomic_inc(); | 3322 | smp_mb__after_atomic_inc(); |
| 3453 | spin_unlock(&dev->se_port_lock); | 3323 | spin_unlock(&dev->se_port_lock); |
| 3454 | 3324 | ||
| 3455 | ret = core_scsi3_tpg_depend_item(dest_se_tpg); | 3325 | if (core_scsi3_tpg_depend_item(dest_se_tpg)) { |
| 3456 | if (ret != 0) { | ||
| 3457 | pr_err("core_scsi3_tpg_depend_item() failed" | 3326 | pr_err("core_scsi3_tpg_depend_item() failed" |
| 3458 | " for dest_se_tpg\n"); | 3327 | " for dest_se_tpg\n"); |
| 3459 | atomic_dec(&dest_se_tpg->tpg_pr_ref_count); | 3328 | atomic_dec(&dest_se_tpg->tpg_pr_ref_count); |
| 3460 | smp_mb__after_atomic_dec(); | 3329 | smp_mb__after_atomic_dec(); |
| 3461 | core_scsi3_put_pr_reg(pr_reg); | 3330 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3462 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3331 | goto out_put_pr_reg; |
| 3463 | return -EINVAL; | ||
| 3464 | } | 3332 | } |
| 3465 | 3333 | ||
| 3466 | spin_lock(&dev->se_port_lock); | 3334 | spin_lock(&dev->se_port_lock); |
| @@ -3472,12 +3340,15 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3472 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" | 3340 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" |
| 3473 | " fabric ops from Relative Target Port Identifier:" | 3341 | " fabric ops from Relative Target Port Identifier:" |
| 3474 | " %hu\n", rtpi); | 3342 | " %hu\n", rtpi); |
| 3475 | core_scsi3_put_pr_reg(pr_reg); | 3343 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3476 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3344 | goto out_put_pr_reg; |
| 3477 | return -EINVAL; | ||
| 3478 | } | 3345 | } |
| 3479 | 3346 | ||
| 3480 | buf = transport_kmap_data_sg(cmd); | 3347 | buf = transport_kmap_data_sg(cmd); |
| 3348 | if (!buf) { | ||
| 3349 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 3350 | goto out_put_pr_reg; | ||
| 3351 | } | ||
| 3481 | proto_ident = (buf[24] & 0x0f); | 3352 | proto_ident = (buf[24] & 0x0f); |
| 3482 | 3353 | ||
| 3483 | pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" | 3354 | pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" |
| @@ -3489,16 +3360,14 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3489 | " from fabric: %s\n", proto_ident, | 3360 | " from fabric: %s\n", proto_ident, |
| 3490 | dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), | 3361 | dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), |
| 3491 | dest_tf_ops->get_fabric_name()); | 3362 | dest_tf_ops->get_fabric_name()); |
| 3492 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3363 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3493 | ret = -EINVAL; | ||
| 3494 | goto out; | 3364 | goto out; |
| 3495 | } | 3365 | } |
| 3496 | if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { | 3366 | if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { |
| 3497 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" | 3367 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" |
| 3498 | " containg a valid tpg_parse_pr_out_transport_id" | 3368 | " containg a valid tpg_parse_pr_out_transport_id" |
| 3499 | " function pointer\n"); | 3369 | " function pointer\n"); |
| 3500 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3370 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3501 | ret = -EINVAL; | ||
| 3502 | goto out; | 3371 | goto out; |
| 3503 | } | 3372 | } |
| 3504 | initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, | 3373 | initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, |
| @@ -3506,8 +3375,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3506 | if (!initiator_str) { | 3375 | if (!initiator_str) { |
| 3507 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" | 3376 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" |
| 3508 | " initiator_str from Transport ID\n"); | 3377 | " initiator_str from Transport ID\n"); |
| 3509 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3378 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3510 | ret = -EINVAL; | ||
| 3511 | goto out; | 3379 | goto out; |
| 3512 | } | 3380 | } |
| 3513 | 3381 | ||
| @@ -3536,8 +3404,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3536 | pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" | 3404 | pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" |
| 3537 | " matches: %s on received I_T Nexus\n", initiator_str, | 3405 | " matches: %s on received I_T Nexus\n", initiator_str, |
| 3538 | pr_reg_nacl->initiatorname); | 3406 | pr_reg_nacl->initiatorname); |
| 3539 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3407 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3540 | ret = -EINVAL; | ||
| 3541 | goto out; | 3408 | goto out; |
| 3542 | } | 3409 | } |
| 3543 | if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { | 3410 | if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { |
| @@ -3545,8 +3412,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
| 3545 | " matches: %s %s on received I_T Nexus\n", | 3412 | " matches: %s %s on received I_T Nexus\n", |
| 3546 | initiator_str, iport_ptr, pr_reg_nacl->initiatorname, | 3413 | initiator_str, iport_ptr, pr_reg_nacl->initiatorname, |
| 3547 | pr_reg->pr_reg_isid); | 3414 | pr_reg->pr_reg_isid); |
| 3548 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3415 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3549 | ret = -EINVAL; | ||
| 3550 | goto out; | 3416 | goto out; |
| 3551 | } | 3417 | } |
| 3552 | after_iport_check: | 3418 | after_iport_check: |
| @@ -3566,19 +3432,17 @@ after_iport_check: | |||
| 3566 | pr_err("Unable to locate %s dest_node_acl for" | 3432 | pr_err("Unable to locate %s dest_node_acl for" |
| 3567 | " TransportID%s\n", dest_tf_ops->get_fabric_name(), | 3433 | " TransportID%s\n", dest_tf_ops->get_fabric_name(), |
| 3568 | initiator_str); | 3434 | initiator_str); |
| 3569 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3435 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3570 | ret = -EINVAL; | ||
| 3571 | goto out; | 3436 | goto out; |
| 3572 | } | 3437 | } |
| 3573 | ret = core_scsi3_nodeacl_depend_item(dest_node_acl); | 3438 | |
| 3574 | if (ret != 0) { | 3439 | if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { |
| 3575 | pr_err("core_scsi3_nodeacl_depend_item() for" | 3440 | pr_err("core_scsi3_nodeacl_depend_item() for" |
| 3576 | " dest_node_acl\n"); | 3441 | " dest_node_acl\n"); |
| 3577 | atomic_dec(&dest_node_acl->acl_pr_ref_count); | 3442 | atomic_dec(&dest_node_acl->acl_pr_ref_count); |
| 3578 | smp_mb__after_atomic_dec(); | 3443 | smp_mb__after_atomic_dec(); |
| 3579 | dest_node_acl = NULL; | 3444 | dest_node_acl = NULL; |
| 3580 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3445 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3581 | ret = -EINVAL; | ||
| 3582 | goto out; | 3446 | goto out; |
| 3583 | } | 3447 | } |
| 3584 | 3448 | ||
| @@ -3594,19 +3458,16 @@ after_iport_check: | |||
| 3594 | if (!dest_se_deve) { | 3458 | if (!dest_se_deve) { |
| 3595 | pr_err("Unable to locate %s dest_se_deve from RTPI:" | 3459 | pr_err("Unable to locate %s dest_se_deve from RTPI:" |
| 3596 | " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); | 3460 | " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); |
| 3597 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3461 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3598 | ret = -EINVAL; | ||
| 3599 | goto out; | 3462 | goto out; |
| 3600 | } | 3463 | } |
| 3601 | 3464 | ||
| 3602 | ret = core_scsi3_lunacl_depend_item(dest_se_deve); | 3465 | if (core_scsi3_lunacl_depend_item(dest_se_deve)) { |
| 3603 | if (ret < 0) { | ||
| 3604 | pr_err("core_scsi3_lunacl_depend_item() failed\n"); | 3466 | pr_err("core_scsi3_lunacl_depend_item() failed\n"); |
| 3605 | atomic_dec(&dest_se_deve->pr_ref_count); | 3467 | atomic_dec(&dest_se_deve->pr_ref_count); |
| 3606 | smp_mb__after_atomic_dec(); | 3468 | smp_mb__after_atomic_dec(); |
| 3607 | dest_se_deve = NULL; | 3469 | dest_se_deve = NULL; |
| 3608 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3470 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3609 | ret = -EINVAL; | ||
| 3610 | goto out; | 3471 | goto out; |
| 3611 | } | 3472 | } |
| 3612 | 3473 | ||
| @@ -3625,8 +3486,7 @@ after_iport_check: | |||
| 3625 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" | 3486 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" |
| 3626 | " currently held\n"); | 3487 | " currently held\n"); |
| 3627 | spin_unlock(&dev->dev_reservation_lock); | 3488 | spin_unlock(&dev->dev_reservation_lock); |
| 3628 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3489 | ret = TCM_INVALID_CDB_FIELD; |
| 3629 | ret = -EINVAL; | ||
| 3630 | goto out; | 3490 | goto out; |
| 3631 | } | 3491 | } |
| 3632 | /* | 3492 | /* |
| @@ -3639,8 +3499,7 @@ after_iport_check: | |||
| 3639 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" | 3499 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" |
| 3640 | " Nexus is not reservation holder\n"); | 3500 | " Nexus is not reservation holder\n"); |
| 3641 | spin_unlock(&dev->dev_reservation_lock); | 3501 | spin_unlock(&dev->dev_reservation_lock); |
| 3642 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3502 | ret = TCM_RESERVATION_CONFLICT; |
| 3643 | ret = -EINVAL; | ||
| 3644 | goto out; | 3503 | goto out; |
| 3645 | } | 3504 | } |
| 3646 | /* | 3505 | /* |
| @@ -3658,8 +3517,7 @@ after_iport_check: | |||
| 3658 | " reservation for type: %s\n", | 3517 | " reservation for type: %s\n", |
| 3659 | core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); | 3518 | core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); |
| 3660 | spin_unlock(&dev->dev_reservation_lock); | 3519 | spin_unlock(&dev->dev_reservation_lock); |
| 3661 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3520 | ret = TCM_RESERVATION_CONFLICT; |
| 3662 | ret = -EINVAL; | ||
| 3663 | goto out; | 3521 | goto out; |
| 3664 | } | 3522 | } |
| 3665 | pr_res_nacl = pr_res_holder->pr_reg_nacl; | 3523 | pr_res_nacl = pr_res_holder->pr_reg_nacl; |
| @@ -3691,13 +3549,11 @@ after_iport_check: | |||
| 3691 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, | 3549 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, |
| 3692 | iport_ptr); | 3550 | iport_ptr); |
| 3693 | if (!dest_pr_reg) { | 3551 | if (!dest_pr_reg) { |
| 3694 | ret = core_scsi3_alloc_registration(cmd->se_dev, | 3552 | if (core_scsi3_alloc_registration(cmd->se_dev, |
| 3695 | dest_node_acl, dest_se_deve, iport_ptr, | 3553 | dest_node_acl, dest_se_deve, iport_ptr, |
| 3696 | sa_res_key, 0, aptpl, 2, 1); | 3554 | sa_res_key, 0, aptpl, 2, 1)) { |
| 3697 | if (ret != 0) { | ||
| 3698 | spin_unlock(&dev->dev_reservation_lock); | 3555 | spin_unlock(&dev->dev_reservation_lock); |
| 3699 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3556 | ret = TCM_INVALID_PARAMETER_LIST; |
| 3700 | ret = -EINVAL; | ||
| 3701 | goto out; | 3557 | goto out; |
| 3702 | } | 3558 | } |
| 3703 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, | 3559 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, |
| @@ -3768,12 +3624,12 @@ after_iport_check: | |||
| 3768 | " REGISTER_AND_MOVE\n"); | 3624 | " REGISTER_AND_MOVE\n"); |
| 3769 | } else { | 3625 | } else { |
| 3770 | pr_tmpl->pr_aptpl_active = 1; | 3626 | pr_tmpl->pr_aptpl_active = 1; |
| 3771 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 3627 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
| 3772 | &dest_pr_reg->pr_aptpl_buf[0], | 3628 | &dest_pr_reg->pr_aptpl_buf[0], |
| 3773 | pr_tmpl->pr_aptpl_buf_len); | 3629 | pr_tmpl->pr_aptpl_buf_len)) { |
| 3774 | if (!ret) | ||
| 3775 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for" | 3630 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for" |
| 3776 | " REGISTER_AND_MOVE\n"); | 3631 | " REGISTER_AND_MOVE\n"); |
| 3632 | } | ||
| 3777 | } | 3633 | } |
| 3778 | 3634 | ||
| 3779 | transport_kunmap_data_sg(cmd); | 3635 | transport_kunmap_data_sg(cmd); |
| @@ -3788,6 +3644,8 @@ out: | |||
| 3788 | if (dest_node_acl) | 3644 | if (dest_node_acl) |
| 3789 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 3645 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
| 3790 | core_scsi3_tpg_undepend_item(dest_se_tpg); | 3646 | core_scsi3_tpg_undepend_item(dest_se_tpg); |
| 3647 | |||
| 3648 | out_put_pr_reg: | ||
| 3791 | core_scsi3_put_pr_reg(pr_reg); | 3649 | core_scsi3_put_pr_reg(pr_reg); |
| 3792 | return ret; | 3650 | return ret; |
| 3793 | } | 3651 | } |
| @@ -3805,14 +3663,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) | |||
| 3805 | /* | 3663 | /* |
| 3806 | * See spc4r17 section 6.14 Table 170 | 3664 | * See spc4r17 section 6.14 Table 170 |
| 3807 | */ | 3665 | */ |
| 3808 | int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | 3666 | sense_reason_t |
| 3667 | target_scsi3_emulate_pr_out(struct se_cmd *cmd) | ||
| 3809 | { | 3668 | { |
| 3810 | unsigned char *cdb = &cmd->t_task_cdb[0]; | 3669 | unsigned char *cdb = &cmd->t_task_cdb[0]; |
| 3811 | unsigned char *buf; | 3670 | unsigned char *buf; |
| 3812 | u64 res_key, sa_res_key; | 3671 | u64 res_key, sa_res_key; |
| 3813 | int sa, scope, type, aptpl; | 3672 | int sa, scope, type, aptpl; |
| 3814 | int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; | 3673 | int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; |
| 3815 | int ret; | 3674 | sense_reason_t ret; |
| 3816 | 3675 | ||
| 3817 | /* | 3676 | /* |
| 3818 | * Following spc2r20 5.5.1 Reservations overview: | 3677 | * Following spc2r20 5.5.1 Reservations overview: |
| @@ -3823,32 +3682,26 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
| 3823 | * initiator or service action and shall terminate with a RESERVATION | 3682 | * initiator or service action and shall terminate with a RESERVATION |
| 3824 | * CONFLICT status. | 3683 | * CONFLICT status. |
| 3825 | */ | 3684 | */ |
| 3826 | if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { | 3685 | if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) { |
| 3827 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" | 3686 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" |
| 3828 | " SPC-2 reservation is held, returning" | 3687 | " SPC-2 reservation is held, returning" |
| 3829 | " RESERVATION_CONFLICT\n"); | 3688 | " RESERVATION_CONFLICT\n"); |
| 3830 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3689 | return TCM_RESERVATION_CONFLICT; |
| 3831 | ret = -EINVAL; | ||
| 3832 | goto out; | ||
| 3833 | } | 3690 | } |
| 3834 | 3691 | ||
| 3835 | /* | 3692 | /* |
| 3836 | * FIXME: A NULL struct se_session pointer means an this is not coming from | 3693 | * FIXME: A NULL struct se_session pointer means an this is not coming from |
| 3837 | * a $FABRIC_MOD's nexus, but from internal passthrough ops. | 3694 | * a $FABRIC_MOD's nexus, but from internal passthrough ops. |
| 3838 | */ | 3695 | */ |
| 3839 | if (!cmd->se_sess) { | 3696 | if (!cmd->se_sess) |
| 3840 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3697 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3841 | ret = -EINVAL; | ||
| 3842 | goto out; | ||
| 3843 | } | ||
| 3844 | 3698 | ||
| 3845 | if (cmd->data_length < 24) { | 3699 | if (cmd->data_length < 24) { |
| 3846 | pr_warn("SPC-PR: Received PR OUT parameter list" | 3700 | pr_warn("SPC-PR: Received PR OUT parameter list" |
| 3847 | " length too small: %u\n", cmd->data_length); | 3701 | " length too small: %u\n", cmd->data_length); |
| 3848 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3702 | return TCM_INVALID_PARAMETER_LIST; |
| 3849 | ret = -EINVAL; | ||
| 3850 | goto out; | ||
| 3851 | } | 3703 | } |
| 3704 | |||
| 3852 | /* | 3705 | /* |
| 3853 | * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) | 3706 | * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) |
| 3854 | */ | 3707 | */ |
| @@ -3857,6 +3710,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
| 3857 | type = (cdb[2] & 0x0f); | 3710 | type = (cdb[2] & 0x0f); |
| 3858 | 3711 | ||
| 3859 | buf = transport_kmap_data_sg(cmd); | 3712 | buf = transport_kmap_data_sg(cmd); |
| 3713 | if (!buf) | ||
| 3714 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 3715 | |||
| 3860 | /* | 3716 | /* |
| 3861 | * From PERSISTENT_RESERVE_OUT parameter list (payload) | 3717 | * From PERSISTENT_RESERVE_OUT parameter list (payload) |
| 3862 | */ | 3718 | */ |
| @@ -3880,11 +3736,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
| 3880 | /* | 3736 | /* |
| 3881 | * SPEC_I_PT=1 is only valid for Service action: REGISTER | 3737 | * SPEC_I_PT=1 is only valid for Service action: REGISTER |
| 3882 | */ | 3738 | */ |
| 3883 | if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { | 3739 | if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) |
| 3884 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3740 | return TCM_INVALID_PARAMETER_LIST; |
| 3885 | ret = -EINVAL; | ||
| 3886 | goto out; | ||
| 3887 | } | ||
| 3888 | 3741 | ||
| 3889 | /* | 3742 | /* |
| 3890 | * From spc4r17 section 6.14: | 3743 | * From spc4r17 section 6.14: |
| @@ -3899,10 +3752,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
| 3899 | (cmd->data_length != 24)) { | 3752 | (cmd->data_length != 24)) { |
| 3900 | pr_warn("SPC-PR: Received PR OUT illegal parameter" | 3753 | pr_warn("SPC-PR: Received PR OUT illegal parameter" |
| 3901 | " list length: %u\n", cmd->data_length); | 3754 | " list length: %u\n", cmd->data_length); |
| 3902 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3755 | return TCM_INVALID_PARAMETER_LIST; |
| 3903 | ret = -EINVAL; | ||
| 3904 | goto out; | ||
| 3905 | } | 3756 | } |
| 3757 | |||
| 3906 | /* | 3758 | /* |
| 3907 | * (core_scsi3_emulate_pro_* function parameters | 3759 | * (core_scsi3_emulate_pro_* function parameters |
| 3908 | * are defined by spc4r17 Table 174: | 3760 | * are defined by spc4r17 Table 174: |
| @@ -3941,12 +3793,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
| 3941 | default: | 3793 | default: |
| 3942 | pr_err("Unknown PERSISTENT_RESERVE_OUT service" | 3794 | pr_err("Unknown PERSISTENT_RESERVE_OUT service" |
| 3943 | " action: 0x%02x\n", cdb[1] & 0x1f); | 3795 | " action: 0x%02x\n", cdb[1] & 0x1f); |
| 3944 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3796 | return TCM_INVALID_CDB_FIELD; |
| 3945 | ret = -EINVAL; | ||
| 3946 | break; | ||
| 3947 | } | 3797 | } |
| 3948 | 3798 | ||
| 3949 | out: | ||
| 3950 | if (!ret) | 3799 | if (!ret) |
| 3951 | target_complete_cmd(cmd, GOOD); | 3800 | target_complete_cmd(cmd, GOOD); |
| 3952 | return ret; | 3801 | return ret; |
| @@ -3957,10 +3806,10 @@ out: | |||
| 3957 | * | 3806 | * |
| 3958 | * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 | 3807 | * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 |
| 3959 | */ | 3808 | */ |
| 3960 | static int core_scsi3_pri_read_keys(struct se_cmd *cmd) | 3809 | static sense_reason_t |
| 3810 | core_scsi3_pri_read_keys(struct se_cmd *cmd) | ||
| 3961 | { | 3811 | { |
| 3962 | struct se_device *se_dev = cmd->se_dev; | 3812 | struct se_device *dev = cmd->se_dev; |
| 3963 | struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; | ||
| 3964 | struct t10_pr_registration *pr_reg; | 3813 | struct t10_pr_registration *pr_reg; |
| 3965 | unsigned char *buf; | 3814 | unsigned char *buf; |
| 3966 | u32 add_len = 0, off = 8; | 3815 | u32 add_len = 0, off = 8; |
| @@ -3968,18 +3817,20 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) | |||
| 3968 | if (cmd->data_length < 8) { | 3817 | if (cmd->data_length < 8) { |
| 3969 | pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" | 3818 | pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" |
| 3970 | " too small\n", cmd->data_length); | 3819 | " too small\n", cmd->data_length); |
| 3971 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3820 | return TCM_INVALID_CDB_FIELD; |
| 3972 | return -EINVAL; | ||
| 3973 | } | 3821 | } |
| 3974 | 3822 | ||
| 3975 | buf = transport_kmap_data_sg(cmd); | 3823 | buf = transport_kmap_data_sg(cmd); |
| 3976 | buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); | 3824 | if (!buf) |
| 3977 | buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); | 3825 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3978 | buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); | ||
| 3979 | buf[3] = (su_dev->t10_pr.pr_generation & 0xff); | ||
| 3980 | 3826 | ||
| 3981 | spin_lock(&su_dev->t10_pr.registration_lock); | 3827 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); |
| 3982 | list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, | 3828 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); |
| 3829 | buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); | ||
| 3830 | buf[3] = (dev->t10_pr.pr_generation & 0xff); | ||
| 3831 | |||
| 3832 | spin_lock(&dev->t10_pr.registration_lock); | ||
| 3833 | list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, | ||
| 3983 | pr_reg_list) { | 3834 | pr_reg_list) { |
| 3984 | /* | 3835 | /* |
| 3985 | * Check for overflow of 8byte PRI READ_KEYS payload and | 3836 | * Check for overflow of 8byte PRI READ_KEYS payload and |
| @@ -3999,7 +3850,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) | |||
| 3999 | 3850 | ||
| 4000 | add_len += 8; | 3851 | add_len += 8; |
| 4001 | } | 3852 | } |
| 4002 | spin_unlock(&su_dev->t10_pr.registration_lock); | 3853 | spin_unlock(&dev->t10_pr.registration_lock); |
| 4003 | 3854 | ||
| 4004 | buf[4] = ((add_len >> 24) & 0xff); | 3855 | buf[4] = ((add_len >> 24) & 0xff); |
| 4005 | buf[5] = ((add_len >> 16) & 0xff); | 3856 | buf[5] = ((add_len >> 16) & 0xff); |
| @@ -4016,10 +3867,10 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) | |||
| 4016 | * | 3867 | * |
| 4017 | * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 | 3868 | * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 |
| 4018 | */ | 3869 | */ |
| 4019 | static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) | 3870 | static sense_reason_t |
| 3871 | core_scsi3_pri_read_reservation(struct se_cmd *cmd) | ||
| 4020 | { | 3872 | { |
| 4021 | struct se_device *se_dev = cmd->se_dev; | 3873 | struct se_device *dev = cmd->se_dev; |
| 4022 | struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; | ||
| 4023 | struct t10_pr_registration *pr_reg; | 3874 | struct t10_pr_registration *pr_reg; |
| 4024 | unsigned char *buf; | 3875 | unsigned char *buf; |
| 4025 | u64 pr_res_key; | 3876 | u64 pr_res_key; |
| @@ -4028,18 +3879,20 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) | |||
| 4028 | if (cmd->data_length < 8) { | 3879 | if (cmd->data_length < 8) { |
| 4029 | pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" | 3880 | pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" |
| 4030 | " too small\n", cmd->data_length); | 3881 | " too small\n", cmd->data_length); |
| 4031 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3882 | return TCM_INVALID_CDB_FIELD; |
| 4032 | return -EINVAL; | ||
| 4033 | } | 3883 | } |
| 4034 | 3884 | ||
| 4035 | buf = transport_kmap_data_sg(cmd); | 3885 | buf = transport_kmap_data_sg(cmd); |
| 4036 | buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); | 3886 | if (!buf) |
| 4037 | buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); | 3887 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 4038 | buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); | ||
| 4039 | buf[3] = (su_dev->t10_pr.pr_generation & 0xff); | ||
| 4040 | 3888 | ||
| 4041 | spin_lock(&se_dev->dev_reservation_lock); | 3889 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); |
| 4042 | pr_reg = se_dev->dev_pr_res_holder; | 3890 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); |
| 3891 | buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); | ||
| 3892 | buf[3] = (dev->t10_pr.pr_generation & 0xff); | ||
| 3893 | |||
| 3894 | spin_lock(&dev->dev_reservation_lock); | ||
| 3895 | pr_reg = dev->dev_pr_res_holder; | ||
| 4043 | if (pr_reg) { | 3896 | if (pr_reg) { |
| 4044 | /* | 3897 | /* |
| 4045 | * Set the hardcoded Additional Length | 3898 | * Set the hardcoded Additional Length |
| @@ -4090,7 +3943,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) | |||
| 4090 | } | 3943 | } |
| 4091 | 3944 | ||
| 4092 | err: | 3945 | err: |
| 4093 | spin_unlock(&se_dev->dev_reservation_lock); | 3946 | spin_unlock(&dev->dev_reservation_lock); |
| 4094 | transport_kunmap_data_sg(cmd); | 3947 | transport_kunmap_data_sg(cmd); |
| 4095 | 3948 | ||
| 4096 | return 0; | 3949 | return 0; |
| @@ -4101,21 +3954,23 @@ err: | |||
| 4101 | * | 3954 | * |
| 4102 | * See spc4r17 section 6.13.4 Table 165 | 3955 | * See spc4r17 section 6.13.4 Table 165 |
| 4103 | */ | 3956 | */ |
| 4104 | static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) | 3957 | static sense_reason_t |
| 3958 | core_scsi3_pri_report_capabilities(struct se_cmd *cmd) | ||
| 4105 | { | 3959 | { |
| 4106 | struct se_device *dev = cmd->se_dev; | 3960 | struct se_device *dev = cmd->se_dev; |
| 4107 | struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; | 3961 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 4108 | unsigned char *buf; | 3962 | unsigned char *buf; |
| 4109 | u16 add_len = 8; /* Hardcoded to 8. */ | 3963 | u16 add_len = 8; /* Hardcoded to 8. */ |
| 4110 | 3964 | ||
| 4111 | if (cmd->data_length < 6) { | 3965 | if (cmd->data_length < 6) { |
| 4112 | pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" | 3966 | pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" |
| 4113 | " %u too small\n", cmd->data_length); | 3967 | " %u too small\n", cmd->data_length); |
| 4114 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3968 | return TCM_INVALID_CDB_FIELD; |
| 4115 | return -EINVAL; | ||
| 4116 | } | 3969 | } |
| 4117 | 3970 | ||
| 4118 | buf = transport_kmap_data_sg(cmd); | 3971 | buf = transport_kmap_data_sg(cmd); |
| 3972 | if (!buf) | ||
| 3973 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 4119 | 3974 | ||
| 4120 | buf[0] = ((add_len << 8) & 0xff); | 3975 | buf[0] = ((add_len << 8) & 0xff); |
| 4121 | buf[1] = (add_len & 0xff); | 3976 | buf[1] = (add_len & 0xff); |
| @@ -4157,14 +4012,14 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) | |||
| 4157 | * | 4012 | * |
| 4158 | * See spc4r17 section 6.13.5 Table 168 and 169 | 4013 | * See spc4r17 section 6.13.5 Table 168 and 169 |
| 4159 | */ | 4014 | */ |
| 4160 | static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) | 4015 | static sense_reason_t |
| 4016 | core_scsi3_pri_read_full_status(struct se_cmd *cmd) | ||
| 4161 | { | 4017 | { |
| 4162 | struct se_device *se_dev = cmd->se_dev; | 4018 | struct se_device *dev = cmd->se_dev; |
| 4163 | struct se_node_acl *se_nacl; | 4019 | struct se_node_acl *se_nacl; |
| 4164 | struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; | ||
| 4165 | struct se_portal_group *se_tpg; | 4020 | struct se_portal_group *se_tpg; |
| 4166 | struct t10_pr_registration *pr_reg, *pr_reg_tmp; | 4021 | struct t10_pr_registration *pr_reg, *pr_reg_tmp; |
| 4167 | struct t10_reservation *pr_tmpl = &se_dev->se_sub_dev->t10_pr; | 4022 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
| 4168 | unsigned char *buf; | 4023 | unsigned char *buf; |
| 4169 | u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; | 4024 | u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; |
| 4170 | u32 off = 8; /* off into first Full Status descriptor */ | 4025 | u32 off = 8; /* off into first Full Status descriptor */ |
| @@ -4173,16 +4028,17 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) | |||
| 4173 | if (cmd->data_length < 8) { | 4028 | if (cmd->data_length < 8) { |
| 4174 | pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" | 4029 | pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" |
| 4175 | " too small\n", cmd->data_length); | 4030 | " too small\n", cmd->data_length); |
| 4176 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 4031 | return TCM_INVALID_CDB_FIELD; |
| 4177 | return -EINVAL; | ||
| 4178 | } | 4032 | } |
| 4179 | 4033 | ||
| 4180 | buf = transport_kmap_data_sg(cmd); | 4034 | buf = transport_kmap_data_sg(cmd); |
| 4035 | if (!buf) | ||
| 4036 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 4181 | 4037 | ||
| 4182 | buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); | 4038 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); |
| 4183 | buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); | 4039 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); |
| 4184 | buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); | 4040 | buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); |
| 4185 | buf[3] = (su_dev->t10_pr.pr_generation & 0xff); | 4041 | buf[3] = (dev->t10_pr.pr_generation & 0xff); |
| 4186 | 4042 | ||
| 4187 | spin_lock(&pr_tmpl->registration_lock); | 4043 | spin_lock(&pr_tmpl->registration_lock); |
| 4188 | list_for_each_entry_safe(pr_reg, pr_reg_tmp, | 4044 | list_for_each_entry_safe(pr_reg, pr_reg_tmp, |
| @@ -4303,9 +4159,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) | |||
| 4303 | return 0; | 4159 | return 0; |
| 4304 | } | 4160 | } |
| 4305 | 4161 | ||
| 4306 | int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | 4162 | sense_reason_t |
| 4163 | target_scsi3_emulate_pr_in(struct se_cmd *cmd) | ||
| 4307 | { | 4164 | { |
| 4308 | int ret; | 4165 | sense_reason_t ret; |
| 4309 | 4166 | ||
| 4310 | /* | 4167 | /* |
| 4311 | * Following spc2r20 5.5.1 Reservations overview: | 4168 | * Following spc2r20 5.5.1 Reservations overview: |
| @@ -4316,12 +4173,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | |||
| 4316 | * initiator or service action and shall terminate with a RESERVATION | 4173 | * initiator or service action and shall terminate with a RESERVATION |
| 4317 | * CONFLICT status. | 4174 | * CONFLICT status. |
| 4318 | */ | 4175 | */ |
| 4319 | if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { | 4176 | if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) { |
| 4320 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" | 4177 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" |
| 4321 | " SPC-2 reservation is held, returning" | 4178 | " SPC-2 reservation is held, returning" |
| 4322 | " RESERVATION_CONFLICT\n"); | 4179 | " RESERVATION_CONFLICT\n"); |
| 4323 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 4180 | return TCM_RESERVATION_CONFLICT; |
| 4324 | return -EINVAL; | ||
| 4325 | } | 4181 | } |
| 4326 | 4182 | ||
| 4327 | switch (cmd->t_task_cdb[1] & 0x1f) { | 4183 | switch (cmd->t_task_cdb[1] & 0x1f) { |
| @@ -4340,9 +4196,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | |||
| 4340 | default: | 4196 | default: |
| 4341 | pr_err("Unknown PERSISTENT_RESERVE_IN service" | 4197 | pr_err("Unknown PERSISTENT_RESERVE_IN service" |
| 4342 | " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); | 4198 | " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); |
| 4343 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 4199 | return TCM_INVALID_CDB_FIELD; |
| 4344 | ret = -EINVAL; | ||
| 4345 | break; | ||
| 4346 | } | 4200 | } |
| 4347 | 4201 | ||
| 4348 | if (!ret) | 4202 | if (!ret) |
| @@ -4350,56 +4204,25 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | |||
| 4350 | return ret; | 4204 | return ret; |
| 4351 | } | 4205 | } |
| 4352 | 4206 | ||
| 4353 | static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type) | 4207 | sense_reason_t |
| 4354 | { | 4208 | target_check_reservation(struct se_cmd *cmd) |
| 4355 | return 0; | ||
| 4356 | } | ||
| 4357 | |||
| 4358 | static int core_pt_seq_non_holder( | ||
| 4359 | struct se_cmd *cmd, | ||
| 4360 | unsigned char *cdb, | ||
| 4361 | u32 pr_reg_type) | ||
| 4362 | { | 4209 | { |
| 4363 | return 0; | 4210 | struct se_device *dev = cmd->se_dev; |
| 4364 | } | 4211 | sense_reason_t ret; |
| 4365 | 4212 | ||
| 4366 | int core_setup_reservations(struct se_device *dev, int force_pt) | 4213 | if (!cmd->se_sess) |
| 4367 | { | 4214 | return 0; |
| 4368 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | 4215 | if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) |
| 4369 | struct t10_reservation *rest = &su_dev->t10_pr; | 4216 | return 0; |
| 4370 | /* | 4217 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 4371 | * If this device is from Target_Core_Mod/pSCSI, use the reservations | ||
| 4372 | * of the Underlying SCSI hardware. In Linux/SCSI terms, this can | ||
| 4373 | * cause a problem because libata and some SATA RAID HBAs appear | ||
| 4374 | * under Linux/SCSI, but to emulate reservations themselves. | ||
| 4375 | */ | ||
| 4376 | if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) && | ||
| 4377 | !(dev->se_sub_dev->se_dev_attrib.emulate_reservations)) || force_pt) { | ||
| 4378 | rest->res_type = SPC_PASSTHROUGH; | ||
| 4379 | rest->pr_ops.t10_reservation_check = &core_pt_reservation_check; | ||
| 4380 | rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder; | ||
| 4381 | pr_debug("%s: Using SPC_PASSTHROUGH, no reservation" | ||
| 4382 | " emulation\n", dev->transport->name); | ||
| 4383 | return 0; | 4218 | return 0; |
| 4384 | } | ||
| 4385 | /* | ||
| 4386 | * If SPC-3 or above is reported by real or emulated struct se_device, | ||
| 4387 | * use emulated Persistent Reservations. | ||
| 4388 | */ | ||
| 4389 | if (dev->transport->get_device_rev(dev) >= SCSI_3) { | ||
| 4390 | rest->res_type = SPC3_PERSISTENT_RESERVATIONS; | ||
| 4391 | rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check; | ||
| 4392 | rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder; | ||
| 4393 | pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS" | ||
| 4394 | " emulation\n", dev->transport->name); | ||
| 4395 | } else { | ||
| 4396 | rest->res_type = SPC2_RESERVATIONS; | ||
| 4397 | rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check; | ||
| 4398 | rest->pr_ops.t10_seq_non_holder = | ||
| 4399 | &core_scsi2_reservation_seq_non_holder; | ||
| 4400 | pr_debug("%s: Using SPC2_RESERVATIONS emulation\n", | ||
| 4401 | dev->transport->name); | ||
| 4402 | } | ||
| 4403 | 4219 | ||
| 4404 | return 0; | 4220 | spin_lock(&dev->dev_reservation_lock); |
| 4221 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) | ||
| 4222 | ret = target_scsi2_reservation_check(cmd); | ||
| 4223 | else | ||
| 4224 | ret = target_scsi3_pr_reservation_check(cmd); | ||
| 4225 | spin_unlock(&dev->dev_reservation_lock); | ||
| 4226 | |||
| 4227 | return ret; | ||
| 4405 | } | 4228 | } |
diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index af6c460d886d..b4a004247ab2 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h | |||
| @@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache; | |||
| 47 | 47 | ||
| 48 | extern int core_pr_dump_initiator_port(struct t10_pr_registration *, | 48 | extern int core_pr_dump_initiator_port(struct t10_pr_registration *, |
| 49 | char *, u32); | 49 | char *, u32); |
| 50 | extern int target_scsi2_reservation_release(struct se_cmd *); | 50 | extern sense_reason_t target_scsi2_reservation_release(struct se_cmd *); |
| 51 | extern int target_scsi2_reservation_reserve(struct se_cmd *); | 51 | extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *); |
| 52 | extern int core_scsi3_alloc_aptpl_registration( | 52 | extern int core_scsi3_alloc_aptpl_registration( |
| 53 | struct t10_reservation *, u64, | 53 | struct t10_reservation *, u64, |
| 54 | unsigned char *, unsigned char *, u32, | 54 | unsigned char *, unsigned char *, u32, |
| @@ -61,8 +61,8 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *, | |||
| 61 | extern void core_scsi3_free_all_registrations(struct se_device *); | 61 | extern void core_scsi3_free_all_registrations(struct se_device *); |
| 62 | extern unsigned char *core_scsi3_pr_dump_type(int); | 62 | extern unsigned char *core_scsi3_pr_dump_type(int); |
| 63 | 63 | ||
| 64 | extern int target_scsi3_emulate_pr_in(struct se_cmd *); | 64 | extern sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *); |
| 65 | extern int target_scsi3_emulate_pr_out(struct se_cmd *); | 65 | extern sense_reason_t target_scsi3_emulate_pr_out(struct se_cmd *); |
| 66 | extern int core_setup_reservations(struct se_device *, int); | 66 | extern sense_reason_t target_check_reservation(struct se_cmd *); |
| 67 | 67 | ||
| 68 | #endif /* TARGET_CORE_PR_H */ | 68 | #endif /* TARGET_CORE_PR_H */ |
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 617c086a8a02..2bcfd79cf595 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c | |||
| @@ -3,10 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains the generic target mode <-> Linux SCSI subsystem plugin. | 4 | * This file contains the generic target mode <-> Linux SCSI subsystem plugin. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. | 6 | * (c) Copyright 2003-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 8 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 9 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 10 | * | 7 | * |
| 11 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 12 | * | 9 | * |
| @@ -53,9 +50,14 @@ | |||
| 53 | 50 | ||
| 54 | #define ISPRINT(a) ((a >= ' ') && (a <= '~')) | 51 | #define ISPRINT(a) ((a >= ' ') && (a <= '~')) |
| 55 | 52 | ||
| 53 | static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev) | ||
| 54 | { | ||
| 55 | return container_of(dev, struct pscsi_dev_virt, dev); | ||
| 56 | } | ||
| 57 | |||
| 56 | static struct se_subsystem_api pscsi_template; | 58 | static struct se_subsystem_api pscsi_template; |
| 57 | 59 | ||
| 58 | static int pscsi_execute_cmd(struct se_cmd *cmd); | 60 | static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd); |
| 59 | static void pscsi_req_done(struct request *, int); | 61 | static void pscsi_req_done(struct request *, int); |
| 60 | 62 | ||
| 61 | /* pscsi_attach_hba(): | 63 | /* pscsi_attach_hba(): |
| @@ -219,7 +221,7 @@ pscsi_get_inquiry_vpd_serial(struct scsi_device *sdev, struct t10_wwn *wwn) | |||
| 219 | 221 | ||
| 220 | snprintf(&wwn->unit_serial[0], INQUIRY_VPD_SERIAL_LEN, "%s", &buf[4]); | 222 | snprintf(&wwn->unit_serial[0], INQUIRY_VPD_SERIAL_LEN, "%s", &buf[4]); |
| 221 | 223 | ||
| 222 | wwn->t10_sub_dev->su_dev_flags |= SDF_FIRMWARE_VPD_UNIT_SERIAL; | 224 | wwn->t10_dev->dev_flags |= DF_FIRMWARE_VPD_UNIT_SERIAL; |
| 223 | 225 | ||
| 224 | kfree(buf); | 226 | kfree(buf); |
| 225 | return 0; | 227 | return 0; |
| @@ -299,23 +301,13 @@ out: | |||
| 299 | kfree(buf); | 301 | kfree(buf); |
| 300 | } | 302 | } |
| 301 | 303 | ||
| 302 | /* pscsi_add_device_to_list(): | 304 | static int pscsi_add_device_to_list(struct se_device *dev, |
| 303 | * | 305 | struct scsi_device *sd) |
| 304 | * | ||
| 305 | */ | ||
| 306 | static struct se_device *pscsi_add_device_to_list( | ||
| 307 | struct se_hba *hba, | ||
| 308 | struct se_subsystem_dev *se_dev, | ||
| 309 | struct pscsi_dev_virt *pdv, | ||
| 310 | struct scsi_device *sd, | ||
| 311 | int dev_flags) | ||
| 312 | { | 306 | { |
| 313 | struct se_device *dev; | 307 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); |
| 314 | struct se_dev_limits dev_limits; | 308 | struct request_queue *q = sd->request_queue; |
| 315 | struct request_queue *q; | ||
| 316 | struct queue_limits *limits; | ||
| 317 | 309 | ||
| 318 | memset(&dev_limits, 0, sizeof(struct se_dev_limits)); | 310 | pdv->pdv_sd = sd; |
| 319 | 311 | ||
| 320 | if (!sd->queue_depth) { | 312 | if (!sd->queue_depth) { |
| 321 | sd->queue_depth = PSCSI_DEFAULT_QUEUEDEPTH; | 313 | sd->queue_depth = PSCSI_DEFAULT_QUEUEDEPTH; |
| @@ -324,54 +316,27 @@ static struct se_device *pscsi_add_device_to_list( | |||
| 324 | " queue_depth to %d\n", sd->channel, sd->id, | 316 | " queue_depth to %d\n", sd->channel, sd->id, |
| 325 | sd->lun, sd->queue_depth); | 317 | sd->lun, sd->queue_depth); |
| 326 | } | 318 | } |
| 327 | /* | 319 | |
| 328 | * Setup the local scope queue_limits from struct request_queue->limits | 320 | dev->dev_attrib.hw_block_size = sd->sector_size; |
| 329 | * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. | 321 | dev->dev_attrib.hw_max_sectors = |
| 330 | */ | 322 | min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q)); |
| 331 | q = sd->request_queue; | 323 | dev->dev_attrib.hw_queue_depth = sd->queue_depth; |
| 332 | limits = &dev_limits.limits; | ||
| 333 | limits->logical_block_size = sd->sector_size; | ||
| 334 | limits->max_hw_sectors = min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q)); | ||
| 335 | limits->max_sectors = min_t(int, sd->host->max_sectors, queue_max_sectors(q)); | ||
| 336 | dev_limits.hw_queue_depth = sd->queue_depth; | ||
| 337 | dev_limits.queue_depth = sd->queue_depth; | ||
| 338 | /* | ||
| 339 | * Setup our standard INQUIRY info into se_dev->t10_wwn | ||
| 340 | */ | ||
| 341 | pscsi_set_inquiry_info(sd, &se_dev->t10_wwn); | ||
| 342 | 324 | ||
| 343 | /* | 325 | /* |
| 344 | * Set the pointer pdv->pdv_sd to from passed struct scsi_device, | 326 | * Setup our standard INQUIRY info into se_dev->t10_wwn |
| 345 | * which has already been referenced with Linux SCSI code with | ||
| 346 | * scsi_device_get() in this file's pscsi_create_virtdevice(). | ||
| 347 | * | ||
| 348 | * The passthrough operations called by the transport_add_device_* | ||
| 349 | * function below will require this pointer to be set for passthroug | ||
| 350 | * ops. | ||
| 351 | * | ||
| 352 | * For the shutdown case in pscsi_free_device(), this struct | ||
| 353 | * scsi_device reference is released with Linux SCSI code | ||
| 354 | * scsi_device_put() and the pdv->pdv_sd cleared. | ||
| 355 | */ | 327 | */ |
| 356 | pdv->pdv_sd = sd; | 328 | pscsi_set_inquiry_info(sd, &dev->t10_wwn); |
| 357 | dev = transport_add_device_to_core_hba(hba, &pscsi_template, | ||
| 358 | se_dev, dev_flags, pdv, | ||
| 359 | &dev_limits, NULL, NULL); | ||
| 360 | if (!dev) { | ||
| 361 | pdv->pdv_sd = NULL; | ||
| 362 | return NULL; | ||
| 363 | } | ||
| 364 | 329 | ||
| 365 | /* | 330 | /* |
| 366 | * Locate VPD WWN Information used for various purposes within | 331 | * Locate VPD WWN Information used for various purposes within |
| 367 | * the Storage Engine. | 332 | * the Storage Engine. |
| 368 | */ | 333 | */ |
| 369 | if (!pscsi_get_inquiry_vpd_serial(sd, &se_dev->t10_wwn)) { | 334 | if (!pscsi_get_inquiry_vpd_serial(sd, &dev->t10_wwn)) { |
| 370 | /* | 335 | /* |
| 371 | * If VPD Unit Serial returned GOOD status, try | 336 | * If VPD Unit Serial returned GOOD status, try |
| 372 | * VPD Device Identification page (0x83). | 337 | * VPD Device Identification page (0x83). |
| 373 | */ | 338 | */ |
| 374 | pscsi_get_inquiry_vpd_device_ident(sd, &se_dev->t10_wwn); | 339 | pscsi_get_inquiry_vpd_device_ident(sd, &dev->t10_wwn); |
| 375 | } | 340 | } |
| 376 | 341 | ||
| 377 | /* | 342 | /* |
| @@ -379,10 +344,11 @@ static struct se_device *pscsi_add_device_to_list( | |||
| 379 | */ | 344 | */ |
| 380 | if (sd->type == TYPE_TAPE) | 345 | if (sd->type == TYPE_TAPE) |
| 381 | pscsi_tape_read_blocksize(dev, sd); | 346 | pscsi_tape_read_blocksize(dev, sd); |
| 382 | return dev; | 347 | return 0; |
| 383 | } | 348 | } |
| 384 | 349 | ||
| 385 | static void *pscsi_allocate_virtdevice(struct se_hba *hba, const char *name) | 350 | static struct se_device *pscsi_alloc_device(struct se_hba *hba, |
| 351 | const char *name) | ||
| 386 | { | 352 | { |
| 387 | struct pscsi_dev_virt *pdv; | 353 | struct pscsi_dev_virt *pdv; |
| 388 | 354 | ||
| @@ -391,139 +357,125 @@ static void *pscsi_allocate_virtdevice(struct se_hba *hba, const char *name) | |||
| 391 | pr_err("Unable to allocate memory for struct pscsi_dev_virt\n"); | 357 | pr_err("Unable to allocate memory for struct pscsi_dev_virt\n"); |
| 392 | return NULL; | 358 | return NULL; |
| 393 | } | 359 | } |
| 394 | pdv->pdv_se_hba = hba; | ||
| 395 | 360 | ||
| 396 | pr_debug("PSCSI: Allocated pdv: %p for %s\n", pdv, name); | 361 | pr_debug("PSCSI: Allocated pdv: %p for %s\n", pdv, name); |
| 397 | return pdv; | 362 | return &pdv->dev; |
| 398 | } | 363 | } |
| 399 | 364 | ||
| 400 | /* | 365 | /* |
| 401 | * Called with struct Scsi_Host->host_lock called. | 366 | * Called with struct Scsi_Host->host_lock called. |
| 402 | */ | 367 | */ |
| 403 | static struct se_device *pscsi_create_type_disk( | 368 | static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) |
| 404 | struct scsi_device *sd, | ||
| 405 | struct pscsi_dev_virt *pdv, | ||
| 406 | struct se_subsystem_dev *se_dev, | ||
| 407 | struct se_hba *hba) | ||
| 408 | __releases(sh->host_lock) | 369 | __releases(sh->host_lock) |
| 409 | { | 370 | { |
| 410 | struct se_device *dev; | 371 | struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; |
| 411 | struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; | 372 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); |
| 412 | struct Scsi_Host *sh = sd->host; | 373 | struct Scsi_Host *sh = sd->host; |
| 413 | struct block_device *bd; | 374 | struct block_device *bd; |
| 414 | u32 dev_flags = 0; | 375 | int ret; |
| 415 | 376 | ||
| 416 | if (scsi_device_get(sd)) { | 377 | if (scsi_device_get(sd)) { |
| 417 | pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", | 378 | pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", |
| 418 | sh->host_no, sd->channel, sd->id, sd->lun); | 379 | sh->host_no, sd->channel, sd->id, sd->lun); |
| 419 | spin_unlock_irq(sh->host_lock); | 380 | spin_unlock_irq(sh->host_lock); |
| 420 | return NULL; | 381 | return -EIO; |
| 421 | } | 382 | } |
| 422 | spin_unlock_irq(sh->host_lock); | 383 | spin_unlock_irq(sh->host_lock); |
| 423 | /* | 384 | /* |
| 424 | * Claim exclusive struct block_device access to struct scsi_device | 385 | * Claim exclusive struct block_device access to struct scsi_device |
| 425 | * for TYPE_DISK using supplied udev_path | 386 | * for TYPE_DISK using supplied udev_path |
| 426 | */ | 387 | */ |
| 427 | bd = blkdev_get_by_path(se_dev->se_dev_udev_path, | 388 | bd = blkdev_get_by_path(dev->udev_path, |
| 428 | FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv); | 389 | FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv); |
| 429 | if (IS_ERR(bd)) { | 390 | if (IS_ERR(bd)) { |
| 430 | pr_err("pSCSI: blkdev_get_by_path() failed\n"); | 391 | pr_err("pSCSI: blkdev_get_by_path() failed\n"); |
| 431 | scsi_device_put(sd); | 392 | scsi_device_put(sd); |
| 432 | return NULL; | 393 | return PTR_ERR(bd); |
| 433 | } | 394 | } |
| 434 | pdv->pdv_bd = bd; | 395 | pdv->pdv_bd = bd; |
| 435 | 396 | ||
| 436 | dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags); | 397 | ret = pscsi_add_device_to_list(dev, sd); |
| 437 | if (!dev) { | 398 | if (ret) { |
| 438 | blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); | 399 | blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); |
| 439 | scsi_device_put(sd); | 400 | scsi_device_put(sd); |
| 440 | return NULL; | 401 | return ret; |
| 441 | } | 402 | } |
| 403 | |||
| 442 | pr_debug("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%d\n", | 404 | pr_debug("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%d\n", |
| 443 | phv->phv_host_id, sh->host_no, sd->channel, sd->id, sd->lun); | 405 | phv->phv_host_id, sh->host_no, sd->channel, sd->id, sd->lun); |
| 444 | 406 | return 0; | |
| 445 | return dev; | ||
| 446 | } | 407 | } |
| 447 | 408 | ||
| 448 | /* | 409 | /* |
| 449 | * Called with struct Scsi_Host->host_lock called. | 410 | * Called with struct Scsi_Host->host_lock called. |
| 450 | */ | 411 | */ |
| 451 | static struct se_device *pscsi_create_type_rom( | 412 | static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd) |
| 452 | struct scsi_device *sd, | ||
| 453 | struct pscsi_dev_virt *pdv, | ||
| 454 | struct se_subsystem_dev *se_dev, | ||
| 455 | struct se_hba *hba) | ||
| 456 | __releases(sh->host_lock) | 413 | __releases(sh->host_lock) |
| 457 | { | 414 | { |
| 458 | struct se_device *dev; | 415 | struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; |
| 459 | struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; | ||
| 460 | struct Scsi_Host *sh = sd->host; | 416 | struct Scsi_Host *sh = sd->host; |
| 461 | u32 dev_flags = 0; | 417 | int ret; |
| 462 | 418 | ||
| 463 | if (scsi_device_get(sd)) { | 419 | if (scsi_device_get(sd)) { |
| 464 | pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", | 420 | pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", |
| 465 | sh->host_no, sd->channel, sd->id, sd->lun); | 421 | sh->host_no, sd->channel, sd->id, sd->lun); |
| 466 | spin_unlock_irq(sh->host_lock); | 422 | spin_unlock_irq(sh->host_lock); |
| 467 | return NULL; | 423 | return -EIO; |
| 468 | } | 424 | } |
| 469 | spin_unlock_irq(sh->host_lock); | 425 | spin_unlock_irq(sh->host_lock); |
| 470 | 426 | ||
| 471 | dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags); | 427 | ret = pscsi_add_device_to_list(dev, sd); |
| 472 | if (!dev) { | 428 | if (ret) { |
| 473 | scsi_device_put(sd); | 429 | scsi_device_put(sd); |
| 474 | return NULL; | 430 | return ret; |
| 475 | } | 431 | } |
| 476 | pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", | 432 | pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", |
| 477 | phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, | 433 | phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, |
| 478 | sd->channel, sd->id, sd->lun); | 434 | sd->channel, sd->id, sd->lun); |
| 479 | 435 | ||
| 480 | return dev; | 436 | return 0; |
| 481 | } | 437 | } |
| 482 | 438 | ||
| 483 | /* | 439 | /* |
| 484 | *Called with struct Scsi_Host->host_lock called. | 440 | * Called with struct Scsi_Host->host_lock called. |
| 485 | */ | 441 | */ |
| 486 | static struct se_device *pscsi_create_type_other( | 442 | static int pscsi_create_type_other(struct se_device *dev, |
| 487 | struct scsi_device *sd, | 443 | struct scsi_device *sd) |
| 488 | struct pscsi_dev_virt *pdv, | ||
| 489 | struct se_subsystem_dev *se_dev, | ||
| 490 | struct se_hba *hba) | ||
| 491 | __releases(sh->host_lock) | 444 | __releases(sh->host_lock) |
| 492 | { | 445 | { |
| 493 | struct se_device *dev; | 446 | struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; |
| 494 | struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; | ||
| 495 | struct Scsi_Host *sh = sd->host; | 447 | struct Scsi_Host *sh = sd->host; |
| 496 | u32 dev_flags = 0; | 448 | int ret; |
| 497 | 449 | ||
| 498 | spin_unlock_irq(sh->host_lock); | 450 | spin_unlock_irq(sh->host_lock); |
| 499 | dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags); | 451 | ret = pscsi_add_device_to_list(dev, sd); |
| 500 | if (!dev) | 452 | if (ret) |
| 501 | return NULL; | 453 | return ret; |
| 502 | 454 | ||
| 503 | pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", | 455 | pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", |
| 504 | phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, | 456 | phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, |
| 505 | sd->channel, sd->id, sd->lun); | 457 | sd->channel, sd->id, sd->lun); |
| 506 | 458 | return 0; | |
| 507 | return dev; | ||
| 508 | } | 459 | } |
| 509 | 460 | ||
| 510 | static struct se_device *pscsi_create_virtdevice( | 461 | static int pscsi_configure_device(struct se_device *dev) |
| 511 | struct se_hba *hba, | ||
| 512 | struct se_subsystem_dev *se_dev, | ||
| 513 | void *p) | ||
| 514 | { | 462 | { |
| 515 | struct pscsi_dev_virt *pdv = p; | 463 | struct se_hba *hba = dev->se_hba; |
| 516 | struct se_device *dev; | 464 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); |
| 517 | struct scsi_device *sd; | 465 | struct scsi_device *sd; |
| 518 | struct pscsi_hba_virt *phv = hba->hba_ptr; | 466 | struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; |
| 519 | struct Scsi_Host *sh = phv->phv_lld_host; | 467 | struct Scsi_Host *sh = phv->phv_lld_host; |
| 520 | int legacy_mode_enable = 0; | 468 | int legacy_mode_enable = 0; |
| 469 | int ret; | ||
| 521 | 470 | ||
| 522 | if (!pdv) { | 471 | if (!(pdv->pdv_flags & PDF_HAS_CHANNEL_ID) || |
| 523 | pr_err("Unable to locate struct pscsi_dev_virt" | 472 | !(pdv->pdv_flags & PDF_HAS_TARGET_ID) || |
| 524 | " parameter\n"); | 473 | !(pdv->pdv_flags & PDF_HAS_LUN_ID)) { |
| 525 | return ERR_PTR(-EINVAL); | 474 | pr_err("Missing scsi_channel_id=, scsi_target_id= and" |
| 475 | " scsi_lun_id= parameters\n"); | ||
| 476 | return -EINVAL; | ||
| 526 | } | 477 | } |
| 478 | |||
| 527 | /* | 479 | /* |
| 528 | * If not running in PHV_LLD_SCSI_HOST_NO mode, locate the | 480 | * If not running in PHV_LLD_SCSI_HOST_NO mode, locate the |
| 529 | * struct Scsi_Host we will need to bring the TCM/pSCSI object online | 481 | * struct Scsi_Host we will need to bring the TCM/pSCSI object online |
| @@ -532,16 +484,16 @@ static struct se_device *pscsi_create_virtdevice( | |||
| 532 | if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) { | 484 | if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) { |
| 533 | pr_err("pSCSI: Unable to locate struct" | 485 | pr_err("pSCSI: Unable to locate struct" |
| 534 | " Scsi_Host for PHV_LLD_SCSI_HOST_NO\n"); | 486 | " Scsi_Host for PHV_LLD_SCSI_HOST_NO\n"); |
| 535 | return ERR_PTR(-ENODEV); | 487 | return -ENODEV; |
| 536 | } | 488 | } |
| 537 | /* | 489 | /* |
| 538 | * For the newer PHV_VIRTUAL_HOST_ID struct scsi_device | 490 | * For the newer PHV_VIRTUAL_HOST_ID struct scsi_device |
| 539 | * reference, we enforce that udev_path has been set | 491 | * reference, we enforce that udev_path has been set |
| 540 | */ | 492 | */ |
| 541 | if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) { | 493 | if (!(dev->dev_flags & DF_USING_UDEV_PATH)) { |
| 542 | pr_err("pSCSI: udev_path attribute has not" | 494 | pr_err("pSCSI: udev_path attribute has not" |
| 543 | " been set before ENABLE=1\n"); | 495 | " been set before ENABLE=1\n"); |
| 544 | return ERR_PTR(-EINVAL); | 496 | return -EINVAL; |
| 545 | } | 497 | } |
| 546 | /* | 498 | /* |
| 547 | * If no scsi_host_id= was passed for PHV_VIRTUAL_HOST_ID, | 499 | * If no scsi_host_id= was passed for PHV_VIRTUAL_HOST_ID, |
| @@ -549,17 +501,14 @@ static struct se_device *pscsi_create_virtdevice( | |||
| 549 | * and enable for PHV_LLD_SCSI_HOST_NO mode. | 501 | * and enable for PHV_LLD_SCSI_HOST_NO mode. |
| 550 | */ | 502 | */ |
| 551 | if (!(pdv->pdv_flags & PDF_HAS_VIRT_HOST_ID)) { | 503 | if (!(pdv->pdv_flags & PDF_HAS_VIRT_HOST_ID)) { |
| 552 | spin_lock(&hba->device_lock); | 504 | if (hba->dev_count) { |
| 553 | if (!list_empty(&hba->hba_dev_list)) { | ||
| 554 | pr_err("pSCSI: Unable to set hba_mode" | 505 | pr_err("pSCSI: Unable to set hba_mode" |
| 555 | " with active devices\n"); | 506 | " with active devices\n"); |
| 556 | spin_unlock(&hba->device_lock); | 507 | return -EEXIST; |
| 557 | return ERR_PTR(-EEXIST); | ||
| 558 | } | 508 | } |
| 559 | spin_unlock(&hba->device_lock); | ||
| 560 | 509 | ||
| 561 | if (pscsi_pmode_enable_hba(hba, 1) != 1) | 510 | if (pscsi_pmode_enable_hba(hba, 1) != 1) |
| 562 | return ERR_PTR(-ENODEV); | 511 | return -ENODEV; |
| 563 | 512 | ||
| 564 | legacy_mode_enable = 1; | 513 | legacy_mode_enable = 1; |
| 565 | hba->hba_flags |= HBA_FLAGS_PSCSI_MODE; | 514 | hba->hba_flags |= HBA_FLAGS_PSCSI_MODE; |
| @@ -569,14 +518,14 @@ static struct se_device *pscsi_create_virtdevice( | |||
| 569 | if (IS_ERR(sh)) { | 518 | if (IS_ERR(sh)) { |
| 570 | pr_err("pSCSI: Unable to locate" | 519 | pr_err("pSCSI: Unable to locate" |
| 571 | " pdv_host_id: %d\n", pdv->pdv_host_id); | 520 | " pdv_host_id: %d\n", pdv->pdv_host_id); |
| 572 | return ERR_CAST(sh); | 521 | return PTR_ERR(sh); |
| 573 | } | 522 | } |
| 574 | } | 523 | } |
| 575 | } else { | 524 | } else { |
| 576 | if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) { | 525 | if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) { |
| 577 | pr_err("pSCSI: PHV_VIRTUAL_HOST_ID set while" | 526 | pr_err("pSCSI: PHV_VIRTUAL_HOST_ID set while" |
| 578 | " struct Scsi_Host exists\n"); | 527 | " struct Scsi_Host exists\n"); |
| 579 | return ERR_PTR(-EEXIST); | 528 | return -EEXIST; |
| 580 | } | 529 | } |
| 581 | } | 530 | } |
| 582 | 531 | ||
| @@ -593,17 +542,17 @@ static struct se_device *pscsi_create_virtdevice( | |||
| 593 | */ | 542 | */ |
| 594 | switch (sd->type) { | 543 | switch (sd->type) { |
| 595 | case TYPE_DISK: | 544 | case TYPE_DISK: |
| 596 | dev = pscsi_create_type_disk(sd, pdv, se_dev, hba); | 545 | ret = pscsi_create_type_disk(dev, sd); |
| 597 | break; | 546 | break; |
| 598 | case TYPE_ROM: | 547 | case TYPE_ROM: |
| 599 | dev = pscsi_create_type_rom(sd, pdv, se_dev, hba); | 548 | ret = pscsi_create_type_rom(dev, sd); |
| 600 | break; | 549 | break; |
| 601 | default: | 550 | default: |
| 602 | dev = pscsi_create_type_other(sd, pdv, se_dev, hba); | 551 | ret = pscsi_create_type_other(dev, sd); |
| 603 | break; | 552 | break; |
| 604 | } | 553 | } |
| 605 | 554 | ||
| 606 | if (!dev) { | 555 | if (ret) { |
| 607 | if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) | 556 | if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) |
| 608 | scsi_host_put(sh); | 557 | scsi_host_put(sh); |
| 609 | else if (legacy_mode_enable) { | 558 | else if (legacy_mode_enable) { |
| @@ -611,9 +560,9 @@ static struct se_device *pscsi_create_virtdevice( | |||
| 611 | hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE; | 560 | hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE; |
| 612 | } | 561 | } |
| 613 | pdv->pdv_sd = NULL; | 562 | pdv->pdv_sd = NULL; |
| 614 | return ERR_PTR(-ENODEV); | 563 | return ret; |
| 615 | } | 564 | } |
| 616 | return dev; | 565 | return 0; |
| 617 | } | 566 | } |
| 618 | spin_unlock_irq(sh->host_lock); | 567 | spin_unlock_irq(sh->host_lock); |
| 619 | 568 | ||
| @@ -627,17 +576,13 @@ static struct se_device *pscsi_create_virtdevice( | |||
| 627 | hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE; | 576 | hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE; |
| 628 | } | 577 | } |
| 629 | 578 | ||
| 630 | return ERR_PTR(-ENODEV); | 579 | return -ENODEV; |
| 631 | } | 580 | } |
| 632 | 581 | ||
| 633 | /* pscsi_free_device(): (Part of se_subsystem_api_t template) | 582 | static void pscsi_free_device(struct se_device *dev) |
| 634 | * | ||
| 635 | * | ||
| 636 | */ | ||
| 637 | static void pscsi_free_device(void *p) | ||
| 638 | { | 583 | { |
| 639 | struct pscsi_dev_virt *pdv = p; | 584 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); |
| 640 | struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; | 585 | struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; |
| 641 | struct scsi_device *sd = pdv->pdv_sd; | 586 | struct scsi_device *sd = pdv->pdv_sd; |
| 642 | 587 | ||
| 643 | if (sd) { | 588 | if (sd) { |
| @@ -670,7 +615,7 @@ static void pscsi_free_device(void *p) | |||
| 670 | static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, | 615 | static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, |
| 671 | unsigned char *sense_buffer) | 616 | unsigned char *sense_buffer) |
| 672 | { | 617 | { |
| 673 | struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; | 618 | struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); |
| 674 | struct scsi_device *sd = pdv->pdv_sd; | 619 | struct scsi_device *sd = pdv->pdv_sd; |
| 675 | int result; | 620 | int result; |
| 676 | struct pscsi_plugin_task *pt = cmd->priv; | 621 | struct pscsi_plugin_task *pt = cmd->priv; |
| @@ -694,7 +639,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, | |||
| 694 | if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && | 639 | if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && |
| 695 | (status_byte(result) << 1) == SAM_STAT_GOOD) { | 640 | (status_byte(result) << 1) == SAM_STAT_GOOD) { |
| 696 | if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { | 641 | if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { |
| 697 | unsigned char *buf = transport_kmap_data_sg(cmd); | 642 | unsigned char *buf; |
| 643 | |||
| 644 | buf = transport_kmap_data_sg(cmd); | ||
| 645 | if (!buf) | ||
| 646 | ; /* XXX: TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE */ | ||
| 698 | 647 | ||
| 699 | if (cdb[0] == MODE_SENSE_10) { | 648 | if (cdb[0] == MODE_SENSE_10) { |
| 700 | if (!(buf[3] & 0x80)) | 649 | if (!(buf[3] & 0x80)) |
| @@ -770,13 +719,11 @@ static match_table_t tokens = { | |||
| 770 | {Opt_err, NULL} | 719 | {Opt_err, NULL} |
| 771 | }; | 720 | }; |
| 772 | 721 | ||
| 773 | static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba, | 722 | static ssize_t pscsi_set_configfs_dev_params(struct se_device *dev, |
| 774 | struct se_subsystem_dev *se_dev, | 723 | const char *page, ssize_t count) |
| 775 | const char *page, | ||
| 776 | ssize_t count) | ||
| 777 | { | 724 | { |
| 778 | struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr; | 725 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); |
| 779 | struct pscsi_hba_virt *phv = hba->hba_ptr; | 726 | struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; |
| 780 | char *orig, *ptr, *opts; | 727 | char *orig, *ptr, *opts; |
| 781 | substring_t args[MAX_OPT_ARGS]; | 728 | substring_t args[MAX_OPT_ARGS]; |
| 782 | int ret = 0, arg, token; | 729 | int ret = 0, arg, token; |
| @@ -841,29 +788,10 @@ out: | |||
| 841 | return (!ret) ? count : ret; | 788 | return (!ret) ? count : ret; |
| 842 | } | 789 | } |
| 843 | 790 | ||
| 844 | static ssize_t pscsi_check_configfs_dev_params( | 791 | static ssize_t pscsi_show_configfs_dev_params(struct se_device *dev, char *b) |
| 845 | struct se_hba *hba, | ||
| 846 | struct se_subsystem_dev *se_dev) | ||
| 847 | { | 792 | { |
| 848 | struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr; | 793 | struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; |
| 849 | 794 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); | |
| 850 | if (!(pdv->pdv_flags & PDF_HAS_CHANNEL_ID) || | ||
| 851 | !(pdv->pdv_flags & PDF_HAS_TARGET_ID) || | ||
| 852 | !(pdv->pdv_flags & PDF_HAS_LUN_ID)) { | ||
| 853 | pr_err("Missing scsi_channel_id=, scsi_target_id= and" | ||
| 854 | " scsi_lun_id= parameters\n"); | ||
| 855 | return -EINVAL; | ||
| 856 | } | ||
| 857 | |||
| 858 | return 0; | ||
| 859 | } | ||
| 860 | |||
| 861 | static ssize_t pscsi_show_configfs_dev_params(struct se_hba *hba, | ||
| 862 | struct se_subsystem_dev *se_dev, | ||
| 863 | char *b) | ||
| 864 | { | ||
| 865 | struct pscsi_hba_virt *phv = hba->hba_ptr; | ||
| 866 | struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr; | ||
| 867 | struct scsi_device *sd = pdv->pdv_sd; | 795 | struct scsi_device *sd = pdv->pdv_sd; |
| 868 | unsigned char host_id[16]; | 796 | unsigned char host_id[16]; |
| 869 | ssize_t bl; | 797 | ssize_t bl; |
| @@ -929,11 +857,11 @@ static inline struct bio *pscsi_get_bio(int sg_num) | |||
| 929 | return bio; | 857 | return bio; |
| 930 | } | 858 | } |
| 931 | 859 | ||
| 932 | static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, | 860 | static sense_reason_t |
| 933 | u32 sgl_nents, enum dma_data_direction data_direction, | 861 | pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, |
| 934 | struct bio **hbio) | 862 | enum dma_data_direction data_direction, struct bio **hbio) |
| 935 | { | 863 | { |
| 936 | struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; | 864 | struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); |
| 937 | struct bio *bio = NULL, *tbio = NULL; | 865 | struct bio *bio = NULL, *tbio = NULL; |
| 938 | struct page *page; | 866 | struct page *page; |
| 939 | struct scatterlist *sg; | 867 | struct scatterlist *sg; |
| @@ -1019,7 +947,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, | |||
| 1019 | } | 947 | } |
| 1020 | } | 948 | } |
| 1021 | 949 | ||
| 1022 | return sgl_nents; | 950 | return 0; |
| 1023 | fail: | 951 | fail: |
| 1024 | while (*hbio) { | 952 | while (*hbio) { |
| 1025 | bio = *hbio; | 953 | bio = *hbio; |
| @@ -1027,8 +955,7 @@ fail: | |||
| 1027 | bio->bi_next = NULL; | 955 | bio->bi_next = NULL; |
| 1028 | bio_endio(bio, 0); /* XXX: should be error */ | 956 | bio_endio(bio, 0); /* XXX: should be error */ |
| 1029 | } | 957 | } |
| 1030 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 958 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1031 | return -ENOMEM; | ||
| 1032 | } | 959 | } |
| 1033 | 960 | ||
| 1034 | /* | 961 | /* |
| @@ -1055,17 +982,13 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb) | |||
| 1055 | } | 982 | } |
| 1056 | } | 983 | } |
| 1057 | 984 | ||
| 1058 | static int pscsi_parse_cdb(struct se_cmd *cmd) | 985 | static sense_reason_t |
| 986 | pscsi_parse_cdb(struct se_cmd *cmd) | ||
| 1059 | { | 987 | { |
| 1060 | unsigned char *cdb = cmd->t_task_cdb; | 988 | unsigned char *cdb = cmd->t_task_cdb; |
| 1061 | unsigned int dummy_size; | ||
| 1062 | int ret; | ||
| 1063 | 989 | ||
| 1064 | if (cmd->se_cmd_flags & SCF_BIDI) { | 990 | if (cmd->se_cmd_flags & SCF_BIDI) |
| 1065 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 991 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 1066 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | ||
| 1067 | return -EINVAL; | ||
| 1068 | } | ||
| 1069 | 992 | ||
| 1070 | pscsi_clear_cdb_lun(cdb); | 993 | pscsi_clear_cdb_lun(cdb); |
| 1071 | 994 | ||
| @@ -1076,10 +999,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) | |||
| 1076 | */ | 999 | */ |
| 1077 | switch (cdb[0]) { | 1000 | switch (cdb[0]) { |
| 1078 | case REPORT_LUNS: | 1001 | case REPORT_LUNS: |
| 1079 | ret = spc_parse_cdb(cmd, &dummy_size); | 1002 | cmd->execute_cmd = spc_emulate_report_luns; |
| 1080 | if (ret) | 1003 | return 0; |
| 1081 | return ret; | ||
| 1082 | break; | ||
| 1083 | case READ_6: | 1004 | case READ_6: |
| 1084 | case READ_10: | 1005 | case READ_10: |
| 1085 | case READ_12: | 1006 | case READ_12: |
| @@ -1093,22 +1014,21 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) | |||
| 1093 | /* FALLTHROUGH*/ | 1014 | /* FALLTHROUGH*/ |
| 1094 | default: | 1015 | default: |
| 1095 | cmd->execute_cmd = pscsi_execute_cmd; | 1016 | cmd->execute_cmd = pscsi_execute_cmd; |
| 1096 | break; | 1017 | return 0; |
| 1097 | } | 1018 | } |
| 1098 | |||
| 1099 | return 0; | ||
| 1100 | } | 1019 | } |
| 1101 | 1020 | ||
| 1102 | static int pscsi_execute_cmd(struct se_cmd *cmd) | 1021 | static sense_reason_t |
| 1022 | pscsi_execute_cmd(struct se_cmd *cmd) | ||
| 1103 | { | 1023 | { |
| 1104 | struct scatterlist *sgl = cmd->t_data_sg; | 1024 | struct scatterlist *sgl = cmd->t_data_sg; |
| 1105 | u32 sgl_nents = cmd->t_data_nents; | 1025 | u32 sgl_nents = cmd->t_data_nents; |
| 1106 | enum dma_data_direction data_direction = cmd->data_direction; | 1026 | enum dma_data_direction data_direction = cmd->data_direction; |
| 1107 | struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; | 1027 | struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); |
| 1108 | struct pscsi_plugin_task *pt; | 1028 | struct pscsi_plugin_task *pt; |
| 1109 | struct request *req; | 1029 | struct request *req; |
| 1110 | struct bio *hbio; | 1030 | struct bio *hbio; |
| 1111 | int ret; | 1031 | sense_reason_t ret; |
| 1112 | 1032 | ||
| 1113 | /* | 1033 | /* |
| 1114 | * Dynamically alloc cdb space, since it may be larger than | 1034 | * Dynamically alloc cdb space, since it may be larger than |
| @@ -1116,8 +1036,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) | |||
| 1116 | */ | 1036 | */ |
| 1117 | pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL); | 1037 | pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL); |
| 1118 | if (!pt) { | 1038 | if (!pt) { |
| 1119 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1039 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1120 | return -ENOMEM; | ||
| 1121 | } | 1040 | } |
| 1122 | cmd->priv = pt; | 1041 | cmd->priv = pt; |
| 1123 | 1042 | ||
| @@ -1131,24 +1050,21 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) | |||
| 1131 | if (!req || IS_ERR(req)) { | 1050 | if (!req || IS_ERR(req)) { |
| 1132 | pr_err("PSCSI: blk_get_request() failed: %ld\n", | 1051 | pr_err("PSCSI: blk_get_request() failed: %ld\n", |
| 1133 | req ? IS_ERR(req) : -ENOMEM); | 1052 | req ? IS_ERR(req) : -ENOMEM); |
| 1134 | cmd->scsi_sense_reason = | 1053 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1135 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1136 | goto fail; | 1054 | goto fail; |
| 1137 | } | 1055 | } |
| 1138 | } else { | 1056 | } else { |
| 1139 | BUG_ON(!cmd->data_length); | 1057 | BUG_ON(!cmd->data_length); |
| 1140 | 1058 | ||
| 1141 | ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio); | 1059 | ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio); |
| 1142 | if (ret < 0) { | 1060 | if (ret) |
| 1143 | cmd->scsi_sense_reason = | ||
| 1144 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1145 | goto fail; | 1061 | goto fail; |
| 1146 | } | ||
| 1147 | 1062 | ||
| 1148 | req = blk_make_request(pdv->pdv_sd->request_queue, hbio, | 1063 | req = blk_make_request(pdv->pdv_sd->request_queue, hbio, |
| 1149 | GFP_KERNEL); | 1064 | GFP_KERNEL); |
| 1150 | if (IS_ERR(req)) { | 1065 | if (IS_ERR(req)) { |
| 1151 | pr_err("pSCSI: blk_make_request() failed\n"); | 1066 | pr_err("pSCSI: blk_make_request() failed\n"); |
| 1067 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1152 | goto fail_free_bio; | 1068 | goto fail_free_bio; |
| 1153 | } | 1069 | } |
| 1154 | } | 1070 | } |
| @@ -1179,22 +1095,10 @@ fail_free_bio: | |||
| 1179 | bio->bi_next = NULL; | 1095 | bio->bi_next = NULL; |
| 1180 | bio_endio(bio, 0); /* XXX: should be error */ | 1096 | bio_endio(bio, 0); /* XXX: should be error */ |
| 1181 | } | 1097 | } |
| 1182 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1098 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 1183 | fail: | 1099 | fail: |
| 1184 | kfree(pt); | 1100 | kfree(pt); |
| 1185 | return -ENOMEM; | 1101 | return ret; |
| 1186 | } | ||
| 1187 | |||
| 1188 | /* pscsi_get_device_rev(): | ||
| 1189 | * | ||
| 1190 | * | ||
| 1191 | */ | ||
| 1192 | static u32 pscsi_get_device_rev(struct se_device *dev) | ||
| 1193 | { | ||
| 1194 | struct pscsi_dev_virt *pdv = dev->dev_ptr; | ||
| 1195 | struct scsi_device *sd = pdv->pdv_sd; | ||
| 1196 | |||
| 1197 | return (sd->scsi_level - 1) ? sd->scsi_level - 1 : 1; | ||
| 1198 | } | 1102 | } |
| 1199 | 1103 | ||
| 1200 | /* pscsi_get_device_type(): | 1104 | /* pscsi_get_device_type(): |
| @@ -1203,7 +1107,7 @@ static u32 pscsi_get_device_rev(struct se_device *dev) | |||
| 1203 | */ | 1107 | */ |
| 1204 | static u32 pscsi_get_device_type(struct se_device *dev) | 1108 | static u32 pscsi_get_device_type(struct se_device *dev) |
| 1205 | { | 1109 | { |
| 1206 | struct pscsi_dev_virt *pdv = dev->dev_ptr; | 1110 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); |
| 1207 | struct scsi_device *sd = pdv->pdv_sd; | 1111 | struct scsi_device *sd = pdv->pdv_sd; |
| 1208 | 1112 | ||
| 1209 | return sd->type; | 1113 | return sd->type; |
| @@ -1211,7 +1115,7 @@ static u32 pscsi_get_device_type(struct se_device *dev) | |||
| 1211 | 1115 | ||
| 1212 | static sector_t pscsi_get_blocks(struct se_device *dev) | 1116 | static sector_t pscsi_get_blocks(struct se_device *dev) |
| 1213 | { | 1117 | { |
| 1214 | struct pscsi_dev_virt *pdv = dev->dev_ptr; | 1118 | struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); |
| 1215 | 1119 | ||
| 1216 | if (pdv->pdv_bd && pdv->pdv_bd->bd_part) | 1120 | if (pdv->pdv_bd && pdv->pdv_bd->bd_part) |
| 1217 | return pdv->pdv_bd->bd_part->nr_sects; | 1121 | return pdv->pdv_bd->bd_part->nr_sects; |
| @@ -1243,7 +1147,6 @@ static void pscsi_req_done(struct request *req, int uptodate) | |||
| 1243 | pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" | 1147 | pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" |
| 1244 | " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0], | 1148 | " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0], |
| 1245 | pt->pscsi_result); | 1149 | pt->pscsi_result); |
| 1246 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | ||
| 1247 | target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); | 1150 | target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); |
| 1248 | break; | 1151 | break; |
| 1249 | } | 1152 | } |
| @@ -1259,15 +1162,13 @@ static struct se_subsystem_api pscsi_template = { | |||
| 1259 | .attach_hba = pscsi_attach_hba, | 1162 | .attach_hba = pscsi_attach_hba, |
| 1260 | .detach_hba = pscsi_detach_hba, | 1163 | .detach_hba = pscsi_detach_hba, |
| 1261 | .pmode_enable_hba = pscsi_pmode_enable_hba, | 1164 | .pmode_enable_hba = pscsi_pmode_enable_hba, |
| 1262 | .allocate_virtdevice = pscsi_allocate_virtdevice, | 1165 | .alloc_device = pscsi_alloc_device, |
| 1263 | .create_virtdevice = pscsi_create_virtdevice, | 1166 | .configure_device = pscsi_configure_device, |
| 1264 | .free_device = pscsi_free_device, | 1167 | .free_device = pscsi_free_device, |
| 1265 | .transport_complete = pscsi_transport_complete, | 1168 | .transport_complete = pscsi_transport_complete, |
| 1266 | .parse_cdb = pscsi_parse_cdb, | 1169 | .parse_cdb = pscsi_parse_cdb, |
| 1267 | .check_configfs_dev_params = pscsi_check_configfs_dev_params, | ||
| 1268 | .set_configfs_dev_params = pscsi_set_configfs_dev_params, | 1170 | .set_configfs_dev_params = pscsi_set_configfs_dev_params, |
| 1269 | .show_configfs_dev_params = pscsi_show_configfs_dev_params, | 1171 | .show_configfs_dev_params = pscsi_show_configfs_dev_params, |
| 1270 | .get_device_rev = pscsi_get_device_rev, | ||
| 1271 | .get_device_type = pscsi_get_device_type, | 1172 | .get_device_type = pscsi_get_device_type, |
| 1272 | .get_blocks = pscsi_get_blocks, | 1173 | .get_blocks = pscsi_get_blocks, |
| 1273 | }; | 1174 | }; |
diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h index bc1e5e11eca0..1bd757dff8ee 100644 --- a/drivers/target/target_core_pscsi.h +++ b/drivers/target/target_core_pscsi.h | |||
| @@ -37,6 +37,7 @@ struct pscsi_plugin_task { | |||
| 37 | #define PDF_HAS_VIRT_HOST_ID 0x20 | 37 | #define PDF_HAS_VIRT_HOST_ID 0x20 |
| 38 | 38 | ||
| 39 | struct pscsi_dev_virt { | 39 | struct pscsi_dev_virt { |
| 40 | struct se_device dev; | ||
| 40 | int pdv_flags; | 41 | int pdv_flags; |
| 41 | int pdv_host_id; | 42 | int pdv_host_id; |
| 42 | int pdv_channel_id; | 43 | int pdv_channel_id; |
| @@ -44,7 +45,6 @@ struct pscsi_dev_virt { | |||
| 44 | int pdv_lun_id; | 45 | int pdv_lun_id; |
| 45 | struct block_device *pdv_bd; | 46 | struct block_device *pdv_bd; |
| 46 | struct scsi_device *pdv_sd; | 47 | struct scsi_device *pdv_sd; |
| 47 | struct se_hba *pdv_se_hba; | ||
| 48 | } ____cacheline_aligned; | 48 | } ____cacheline_aligned; |
| 49 | 49 | ||
| 50 | typedef enum phv_modes { | 50 | typedef enum phv_modes { |
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index d00bbe33ff8b..0457de362e68 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c | |||
| @@ -4,10 +4,7 @@ | |||
| 4 | * This file contains the Storage Engine <-> Ramdisk transport | 4 | * This file contains the Storage Engine <-> Ramdisk transport |
| 5 | * specific functions. | 5 | * specific functions. |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. | 7 | * (c) Copyright 2003-2012 RisingTide Systems LLC. |
| 8 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 9 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 10 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 11 | * | 8 | * |
| 12 | * Nicholas A. Bellinger <nab@kernel.org> | 9 | * Nicholas A. Bellinger <nab@kernel.org> |
| 13 | * | 10 | * |
| @@ -41,7 +38,10 @@ | |||
| 41 | 38 | ||
| 42 | #include "target_core_rd.h" | 39 | #include "target_core_rd.h" |
| 43 | 40 | ||
| 44 | static struct se_subsystem_api rd_mcp_template; | 41 | static inline struct rd_dev *RD_DEV(struct se_device *dev) |
| 42 | { | ||
| 43 | return container_of(dev, struct rd_dev, dev); | ||
| 44 | } | ||
| 45 | 45 | ||
| 46 | /* rd_attach_hba(): (Part of se_subsystem_api_t template) | 46 | /* rd_attach_hba(): (Part of se_subsystem_api_t template) |
| 47 | * | 47 | * |
| @@ -196,7 +196,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev) | |||
| 196 | return 0; | 196 | return 0; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | static void *rd_allocate_virtdevice(struct se_hba *hba, const char *name) | 199 | static struct se_device *rd_alloc_device(struct se_hba *hba, const char *name) |
| 200 | { | 200 | { |
| 201 | struct rd_dev *rd_dev; | 201 | struct rd_dev *rd_dev; |
| 202 | struct rd_host *rd_host = hba->hba_ptr; | 202 | struct rd_host *rd_host = hba->hba_ptr; |
| @@ -209,39 +209,27 @@ static void *rd_allocate_virtdevice(struct se_hba *hba, const char *name) | |||
| 209 | 209 | ||
| 210 | rd_dev->rd_host = rd_host; | 210 | rd_dev->rd_host = rd_host; |
| 211 | 211 | ||
| 212 | return rd_dev; | 212 | return &rd_dev->dev; |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | static struct se_device *rd_create_virtdevice(struct se_hba *hba, | 215 | static int rd_configure_device(struct se_device *dev) |
| 216 | struct se_subsystem_dev *se_dev, void *p) | ||
| 217 | { | 216 | { |
| 218 | struct se_device *dev; | 217 | struct rd_dev *rd_dev = RD_DEV(dev); |
| 219 | struct se_dev_limits dev_limits; | 218 | struct rd_host *rd_host = dev->se_hba->hba_ptr; |
| 220 | struct rd_dev *rd_dev = p; | 219 | int ret; |
| 221 | struct rd_host *rd_host = hba->hba_ptr; | ||
| 222 | int dev_flags = 0, ret; | ||
| 223 | char prod[16], rev[4]; | ||
| 224 | 220 | ||
| 225 | memset(&dev_limits, 0, sizeof(struct se_dev_limits)); | 221 | if (!(rd_dev->rd_flags & RDF_HAS_PAGE_COUNT)) { |
| 222 | pr_debug("Missing rd_pages= parameter\n"); | ||
| 223 | return -EINVAL; | ||
| 224 | } | ||
| 226 | 225 | ||
| 227 | ret = rd_build_device_space(rd_dev); | 226 | ret = rd_build_device_space(rd_dev); |
| 228 | if (ret < 0) | 227 | if (ret < 0) |
| 229 | goto fail; | 228 | goto fail; |
| 230 | 229 | ||
| 231 | snprintf(prod, 16, "RAMDISK-MCP"); | 230 | dev->dev_attrib.hw_block_size = RD_BLOCKSIZE; |
| 232 | snprintf(rev, 4, "%s", RD_MCP_VERSION); | 231 | dev->dev_attrib.hw_max_sectors = UINT_MAX; |
| 233 | 232 | dev->dev_attrib.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH; | |
| 234 | dev_limits.limits.logical_block_size = RD_BLOCKSIZE; | ||
| 235 | dev_limits.limits.max_hw_sectors = UINT_MAX; | ||
| 236 | dev_limits.limits.max_sectors = UINT_MAX; | ||
| 237 | dev_limits.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH; | ||
| 238 | dev_limits.queue_depth = RD_DEVICE_QUEUE_DEPTH; | ||
| 239 | |||
| 240 | dev = transport_add_device_to_core_hba(hba, | ||
| 241 | &rd_mcp_template, se_dev, dev_flags, rd_dev, | ||
| 242 | &dev_limits, prod, rev); | ||
| 243 | if (!dev) | ||
| 244 | goto fail; | ||
| 245 | 233 | ||
| 246 | rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++; | 234 | rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++; |
| 247 | 235 | ||
| @@ -251,16 +239,16 @@ static struct se_device *rd_create_virtdevice(struct se_hba *hba, | |||
| 251 | rd_dev->sg_table_count, | 239 | rd_dev->sg_table_count, |
| 252 | (unsigned long)(rd_dev->rd_page_count * PAGE_SIZE)); | 240 | (unsigned long)(rd_dev->rd_page_count * PAGE_SIZE)); |
| 253 | 241 | ||
| 254 | return dev; | 242 | return 0; |
| 255 | 243 | ||
| 256 | fail: | 244 | fail: |
| 257 | rd_release_device_space(rd_dev); | 245 | rd_release_device_space(rd_dev); |
| 258 | return ERR_PTR(ret); | 246 | return ret; |
| 259 | } | 247 | } |
| 260 | 248 | ||
| 261 | static void rd_free_device(void *p) | 249 | static void rd_free_device(struct se_device *dev) |
| 262 | { | 250 | { |
| 263 | struct rd_dev *rd_dev = p; | 251 | struct rd_dev *rd_dev = RD_DEV(dev); |
| 264 | 252 | ||
| 265 | rd_release_device_space(rd_dev); | 253 | rd_release_device_space(rd_dev); |
| 266 | kfree(rd_dev); | 254 | kfree(rd_dev); |
| @@ -284,13 +272,14 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) | |||
| 284 | return NULL; | 272 | return NULL; |
| 285 | } | 273 | } |
| 286 | 274 | ||
| 287 | static int rd_execute_rw(struct se_cmd *cmd) | 275 | static sense_reason_t |
| 276 | rd_execute_rw(struct se_cmd *cmd) | ||
| 288 | { | 277 | { |
| 289 | struct scatterlist *sgl = cmd->t_data_sg; | 278 | struct scatterlist *sgl = cmd->t_data_sg; |
| 290 | u32 sgl_nents = cmd->t_data_nents; | 279 | u32 sgl_nents = cmd->t_data_nents; |
| 291 | enum dma_data_direction data_direction = cmd->data_direction; | 280 | enum dma_data_direction data_direction = cmd->data_direction; |
| 292 | struct se_device *se_dev = cmd->se_dev; | 281 | struct se_device *se_dev = cmd->se_dev; |
| 293 | struct rd_dev *dev = se_dev->dev_ptr; | 282 | struct rd_dev *dev = RD_DEV(se_dev); |
| 294 | struct rd_dev_sg_table *table; | 283 | struct rd_dev_sg_table *table; |
| 295 | struct scatterlist *rd_sg; | 284 | struct scatterlist *rd_sg; |
| 296 | struct sg_mapping_iter m; | 285 | struct sg_mapping_iter m; |
| @@ -300,14 +289,14 @@ static int rd_execute_rw(struct se_cmd *cmd) | |||
| 300 | u32 src_len; | 289 | u32 src_len; |
| 301 | u64 tmp; | 290 | u64 tmp; |
| 302 | 291 | ||
| 303 | tmp = cmd->t_task_lba * se_dev->se_sub_dev->se_dev_attrib.block_size; | 292 | tmp = cmd->t_task_lba * se_dev->dev_attrib.block_size; |
| 304 | rd_offset = do_div(tmp, PAGE_SIZE); | 293 | rd_offset = do_div(tmp, PAGE_SIZE); |
| 305 | rd_page = tmp; | 294 | rd_page = tmp; |
| 306 | rd_size = cmd->data_length; | 295 | rd_size = cmd->data_length; |
| 307 | 296 | ||
| 308 | table = rd_get_sg_table(dev, rd_page); | 297 | table = rd_get_sg_table(dev, rd_page); |
| 309 | if (!table) | 298 | if (!table) |
| 310 | return -EINVAL; | 299 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 311 | 300 | ||
| 312 | rd_sg = &table->sg_table[rd_page - table->page_start_offset]; | 301 | rd_sg = &table->sg_table[rd_page - table->page_start_offset]; |
| 313 | 302 | ||
| @@ -357,7 +346,7 @@ static int rd_execute_rw(struct se_cmd *cmd) | |||
| 357 | table = rd_get_sg_table(dev, rd_page); | 346 | table = rd_get_sg_table(dev, rd_page); |
| 358 | if (!table) { | 347 | if (!table) { |
| 359 | sg_miter_stop(&m); | 348 | sg_miter_stop(&m); |
| 360 | return -EINVAL; | 349 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 361 | } | 350 | } |
| 362 | 351 | ||
| 363 | /* since we increment, the first sg entry is correct */ | 352 | /* since we increment, the first sg entry is correct */ |
| @@ -378,13 +367,10 @@ static match_table_t tokens = { | |||
| 378 | {Opt_err, NULL} | 367 | {Opt_err, NULL} |
| 379 | }; | 368 | }; |
| 380 | 369 | ||
| 381 | static ssize_t rd_set_configfs_dev_params( | 370 | static ssize_t rd_set_configfs_dev_params(struct se_device *dev, |
| 382 | struct se_hba *hba, | 371 | const char *page, ssize_t count) |
| 383 | struct se_subsystem_dev *se_dev, | ||
| 384 | const char *page, | ||
| 385 | ssize_t count) | ||
| 386 | { | 372 | { |
| 387 | struct rd_dev *rd_dev = se_dev->se_dev_su_ptr; | 373 | struct rd_dev *rd_dev = RD_DEV(dev); |
| 388 | char *orig, *ptr, *opts; | 374 | char *orig, *ptr, *opts; |
| 389 | substring_t args[MAX_OPT_ARGS]; | 375 | substring_t args[MAX_OPT_ARGS]; |
| 390 | int ret = 0, arg, token; | 376 | int ret = 0, arg, token; |
| @@ -417,24 +403,10 @@ static ssize_t rd_set_configfs_dev_params( | |||
| 417 | return (!ret) ? count : ret; | 403 | return (!ret) ? count : ret; |
| 418 | } | 404 | } |
| 419 | 405 | ||
| 420 | static ssize_t rd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev) | 406 | static ssize_t rd_show_configfs_dev_params(struct se_device *dev, char *b) |
| 421 | { | 407 | { |
| 422 | struct rd_dev *rd_dev = se_dev->se_dev_su_ptr; | 408 | struct rd_dev *rd_dev = RD_DEV(dev); |
| 423 | 409 | ||
| 424 | if (!(rd_dev->rd_flags & RDF_HAS_PAGE_COUNT)) { | ||
| 425 | pr_debug("Missing rd_pages= parameter\n"); | ||
| 426 | return -EINVAL; | ||
| 427 | } | ||
| 428 | |||
| 429 | return 0; | ||
| 430 | } | ||
| 431 | |||
| 432 | static ssize_t rd_show_configfs_dev_params( | ||
| 433 | struct se_hba *hba, | ||
| 434 | struct se_subsystem_dev *se_dev, | ||
| 435 | char *b) | ||
| 436 | { | ||
| 437 | struct rd_dev *rd_dev = se_dev->se_dev_su_ptr; | ||
| 438 | ssize_t bl = sprintf(b, "TCM RamDisk ID: %u RamDisk Makeup: rd_mcp\n", | 410 | ssize_t bl = sprintf(b, "TCM RamDisk ID: %u RamDisk Makeup: rd_mcp\n", |
| 439 | rd_dev->rd_dev_id); | 411 | rd_dev->rd_dev_id); |
| 440 | bl += sprintf(b + bl, " PAGES/PAGE_SIZE: %u*%lu" | 412 | bl += sprintf(b + bl, " PAGES/PAGE_SIZE: %u*%lu" |
| @@ -443,48 +415,40 @@ static ssize_t rd_show_configfs_dev_params( | |||
| 443 | return bl; | 415 | return bl; |
| 444 | } | 416 | } |
| 445 | 417 | ||
| 446 | static u32 rd_get_device_rev(struct se_device *dev) | ||
| 447 | { | ||
| 448 | return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ | ||
| 449 | } | ||
| 450 | |||
| 451 | static u32 rd_get_device_type(struct se_device *dev) | ||
| 452 | { | ||
| 453 | return TYPE_DISK; | ||
| 454 | } | ||
| 455 | |||
| 456 | static sector_t rd_get_blocks(struct se_device *dev) | 418 | static sector_t rd_get_blocks(struct se_device *dev) |
| 457 | { | 419 | { |
| 458 | struct rd_dev *rd_dev = dev->dev_ptr; | 420 | struct rd_dev *rd_dev = RD_DEV(dev); |
| 421 | |||
| 459 | unsigned long long blocks_long = ((rd_dev->rd_page_count * PAGE_SIZE) / | 422 | unsigned long long blocks_long = ((rd_dev->rd_page_count * PAGE_SIZE) / |
| 460 | dev->se_sub_dev->se_dev_attrib.block_size) - 1; | 423 | dev->dev_attrib.block_size) - 1; |
| 461 | 424 | ||
| 462 | return blocks_long; | 425 | return blocks_long; |
| 463 | } | 426 | } |
| 464 | 427 | ||
| 465 | static struct spc_ops rd_spc_ops = { | 428 | static struct sbc_ops rd_sbc_ops = { |
| 466 | .execute_rw = rd_execute_rw, | 429 | .execute_rw = rd_execute_rw, |
| 467 | }; | 430 | }; |
| 468 | 431 | ||
| 469 | static int rd_parse_cdb(struct se_cmd *cmd) | 432 | static sense_reason_t |
| 433 | rd_parse_cdb(struct se_cmd *cmd) | ||
| 470 | { | 434 | { |
| 471 | return sbc_parse_cdb(cmd, &rd_spc_ops); | 435 | return sbc_parse_cdb(cmd, &rd_sbc_ops); |
| 472 | } | 436 | } |
| 473 | 437 | ||
| 474 | static struct se_subsystem_api rd_mcp_template = { | 438 | static struct se_subsystem_api rd_mcp_template = { |
| 475 | .name = "rd_mcp", | 439 | .name = "rd_mcp", |
| 440 | .inquiry_prod = "RAMDISK-MCP", | ||
| 441 | .inquiry_rev = RD_MCP_VERSION, | ||
| 476 | .transport_type = TRANSPORT_PLUGIN_VHBA_VDEV, | 442 | .transport_type = TRANSPORT_PLUGIN_VHBA_VDEV, |
| 477 | .attach_hba = rd_attach_hba, | 443 | .attach_hba = rd_attach_hba, |
| 478 | .detach_hba = rd_detach_hba, | 444 | .detach_hba = rd_detach_hba, |
| 479 | .allocate_virtdevice = rd_allocate_virtdevice, | 445 | .alloc_device = rd_alloc_device, |
| 480 | .create_virtdevice = rd_create_virtdevice, | 446 | .configure_device = rd_configure_device, |
| 481 | .free_device = rd_free_device, | 447 | .free_device = rd_free_device, |
| 482 | .parse_cdb = rd_parse_cdb, | 448 | .parse_cdb = rd_parse_cdb, |
| 483 | .check_configfs_dev_params = rd_check_configfs_dev_params, | ||
| 484 | .set_configfs_dev_params = rd_set_configfs_dev_params, | 449 | .set_configfs_dev_params = rd_set_configfs_dev_params, |
| 485 | .show_configfs_dev_params = rd_show_configfs_dev_params, | 450 | .show_configfs_dev_params = rd_show_configfs_dev_params, |
| 486 | .get_device_rev = rd_get_device_rev, | 451 | .get_device_type = sbc_get_device_type, |
| 487 | .get_device_type = rd_get_device_type, | ||
| 488 | .get_blocks = rd_get_blocks, | 452 | .get_blocks = rd_get_blocks, |
| 489 | }; | 453 | }; |
| 490 | 454 | ||
diff --git a/drivers/target/target_core_rd.h b/drivers/target/target_core_rd.h index 21458125fe51..933b38b6e563 100644 --- a/drivers/target/target_core_rd.h +++ b/drivers/target/target_core_rd.h | |||
| @@ -24,6 +24,7 @@ struct rd_dev_sg_table { | |||
| 24 | #define RDF_HAS_PAGE_COUNT 0x01 | 24 | #define RDF_HAS_PAGE_COUNT 0x01 |
| 25 | 25 | ||
| 26 | struct rd_dev { | 26 | struct rd_dev { |
| 27 | struct se_device dev; | ||
| 27 | u32 rd_flags; | 28 | u32 rd_flags; |
| 28 | /* Unique Ramdisk Device ID in Ramdisk HBA */ | 29 | /* Unique Ramdisk Device ID in Ramdisk HBA */ |
| 29 | u32 rd_dev_id; | 30 | u32 rd_dev_id; |
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a6e27d967c7b..26a6d183ccb1 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
| @@ -1,10 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * SCSI Block Commands (SBC) parsing and emulation. | 2 | * SCSI Block Commands (SBC) parsing and emulation. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. | 4 | * (c) Copyright 2002-2012 RisingTide Systems LLC. |
| 5 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 6 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 7 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 8 | * | 5 | * |
| 9 | * Nicholas A. Bellinger <nab@kernel.org> | 6 | * Nicholas A. Bellinger <nab@kernel.org> |
| 10 | * | 7 | * |
| @@ -37,7 +34,8 @@ | |||
| 37 | #include "target_core_ua.h" | 34 | #include "target_core_ua.h" |
| 38 | 35 | ||
| 39 | 36 | ||
| 40 | static int sbc_emulate_readcapacity(struct se_cmd *cmd) | 37 | static sense_reason_t |
| 38 | sbc_emulate_readcapacity(struct se_cmd *cmd) | ||
| 41 | { | 39 | { |
| 42 | struct se_device *dev = cmd->se_dev; | 40 | struct se_device *dev = cmd->se_dev; |
| 43 | unsigned long long blocks_long = dev->transport->get_blocks(dev); | 41 | unsigned long long blocks_long = dev->transport->get_blocks(dev); |
| @@ -54,22 +52,24 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd) | |||
| 54 | buf[1] = (blocks >> 16) & 0xff; | 52 | buf[1] = (blocks >> 16) & 0xff; |
| 55 | buf[2] = (blocks >> 8) & 0xff; | 53 | buf[2] = (blocks >> 8) & 0xff; |
| 56 | buf[3] = blocks & 0xff; | 54 | buf[3] = blocks & 0xff; |
| 57 | buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff; | 55 | buf[4] = (dev->dev_attrib.block_size >> 24) & 0xff; |
| 58 | buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff; | 56 | buf[5] = (dev->dev_attrib.block_size >> 16) & 0xff; |
| 59 | buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff; | 57 | buf[6] = (dev->dev_attrib.block_size >> 8) & 0xff; |
| 60 | buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff; | 58 | buf[7] = dev->dev_attrib.block_size & 0xff; |
| 61 | 59 | ||
| 62 | rbuf = transport_kmap_data_sg(cmd); | 60 | rbuf = transport_kmap_data_sg(cmd); |
| 63 | if (rbuf) { | 61 | if (!rbuf) |
| 64 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 62 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 65 | transport_kunmap_data_sg(cmd); | 63 | |
| 66 | } | 64 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
| 65 | transport_kunmap_data_sg(cmd); | ||
| 67 | 66 | ||
| 68 | target_complete_cmd(cmd, GOOD); | 67 | target_complete_cmd(cmd, GOOD); |
| 69 | return 0; | 68 | return 0; |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) | 71 | static sense_reason_t |
| 72 | sbc_emulate_readcapacity_16(struct se_cmd *cmd) | ||
| 73 | { | 73 | { |
| 74 | struct se_device *dev = cmd->se_dev; | 74 | struct se_device *dev = cmd->se_dev; |
| 75 | unsigned char *rbuf; | 75 | unsigned char *rbuf; |
| @@ -85,28 +85,29 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) | |||
| 85 | buf[5] = (blocks >> 16) & 0xff; | 85 | buf[5] = (blocks >> 16) & 0xff; |
| 86 | buf[6] = (blocks >> 8) & 0xff; | 86 | buf[6] = (blocks >> 8) & 0xff; |
| 87 | buf[7] = blocks & 0xff; | 87 | buf[7] = blocks & 0xff; |
| 88 | buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff; | 88 | buf[8] = (dev->dev_attrib.block_size >> 24) & 0xff; |
| 89 | buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff; | 89 | buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff; |
| 90 | buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff; | 90 | buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff; |
| 91 | buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff; | 91 | buf[11] = dev->dev_attrib.block_size & 0xff; |
| 92 | /* | 92 | /* |
| 93 | * Set Thin Provisioning Enable bit following sbc3r22 in section | 93 | * Set Thin Provisioning Enable bit following sbc3r22 in section |
| 94 | * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled. | 94 | * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled. |
| 95 | */ | 95 | */ |
| 96 | if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) | 96 | if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) |
| 97 | buf[14] = 0x80; | 97 | buf[14] = 0x80; |
| 98 | 98 | ||
| 99 | rbuf = transport_kmap_data_sg(cmd); | 99 | rbuf = transport_kmap_data_sg(cmd); |
| 100 | if (rbuf) { | 100 | if (!rbuf) |
| 101 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 101 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 102 | transport_kunmap_data_sg(cmd); | 102 | |
| 103 | } | 103 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
| 104 | transport_kunmap_data_sg(cmd); | ||
| 104 | 105 | ||
| 105 | target_complete_cmd(cmd, GOOD); | 106 | target_complete_cmd(cmd, GOOD); |
| 106 | return 0; | 107 | return 0; |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | int spc_get_write_same_sectors(struct se_cmd *cmd) | 110 | sector_t spc_get_write_same_sectors(struct se_cmd *cmd) |
| 110 | { | 111 | { |
| 111 | u32 num_blocks; | 112 | u32 num_blocks; |
| 112 | 113 | ||
| @@ -129,13 +130,8 @@ int spc_get_write_same_sectors(struct se_cmd *cmd) | |||
| 129 | } | 130 | } |
| 130 | EXPORT_SYMBOL(spc_get_write_same_sectors); | 131 | EXPORT_SYMBOL(spc_get_write_same_sectors); |
| 131 | 132 | ||
| 132 | static int sbc_emulate_verify(struct se_cmd *cmd) | 133 | static sense_reason_t |
| 133 | { | 134 | sbc_emulate_noop(struct se_cmd *cmd) |
| 134 | target_complete_cmd(cmd, GOOD); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int sbc_emulate_noop(struct se_cmd *cmd) | ||
| 139 | { | 135 | { |
| 140 | target_complete_cmd(cmd, GOOD); | 136 | target_complete_cmd(cmd, GOOD); |
| 141 | return 0; | 137 | return 0; |
| @@ -143,7 +139,7 @@ static int sbc_emulate_noop(struct se_cmd *cmd) | |||
| 143 | 139 | ||
| 144 | static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) | 140 | static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) |
| 145 | { | 141 | { |
| 146 | return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; | 142 | return cmd->se_dev->dev_attrib.block_size * sectors; |
| 147 | } | 143 | } |
| 148 | 144 | ||
| 149 | static int sbc_check_valid_sectors(struct se_cmd *cmd) | 145 | static int sbc_check_valid_sectors(struct se_cmd *cmd) |
| @@ -152,7 +148,7 @@ static int sbc_check_valid_sectors(struct se_cmd *cmd) | |||
| 152 | unsigned long long end_lba; | 148 | unsigned long long end_lba; |
| 153 | u32 sectors; | 149 | u32 sectors; |
| 154 | 150 | ||
| 155 | sectors = cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size; | 151 | sectors = cmd->data_length / dev->dev_attrib.block_size; |
| 156 | end_lba = dev->transport->get_blocks(dev) + 1; | 152 | end_lba = dev->transport->get_blocks(dev) + 1; |
| 157 | 153 | ||
| 158 | if (cmd->t_task_lba + sectors > end_lba) { | 154 | if (cmd->t_task_lba + sectors > end_lba) { |
| @@ -236,26 +232,37 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) | |||
| 236 | return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; | 232 | return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; |
| 237 | } | 233 | } |
| 238 | 234 | ||
| 239 | static int sbc_write_same_supported(struct se_device *dev, | 235 | static sense_reason_t |
| 240 | unsigned char *flags) | 236 | sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) |
| 241 | { | 237 | { |
| 238 | unsigned int sectors = spc_get_write_same_sectors(cmd); | ||
| 239 | |||
| 242 | if ((flags[0] & 0x04) || (flags[0] & 0x02)) { | 240 | if ((flags[0] & 0x04) || (flags[0] & 0x02)) { |
| 243 | pr_err("WRITE_SAME PBDATA and LBDATA" | 241 | pr_err("WRITE_SAME PBDATA and LBDATA" |
| 244 | " bits not supported for Block Discard" | 242 | " bits not supported for Block Discard" |
| 245 | " Emulation\n"); | 243 | " Emulation\n"); |
| 246 | return -ENOSYS; | 244 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 245 | } | ||
| 246 | if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) { | ||
| 247 | pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n", | ||
| 248 | sectors, cmd->se_dev->dev_attrib.max_write_same_len); | ||
| 249 | return TCM_INVALID_CDB_FIELD; | ||
| 247 | } | 250 | } |
| 248 | |||
| 249 | /* | 251 | /* |
| 250 | * Currently for the emulated case we only accept | 252 | * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting |
| 251 | * tpws with the UNMAP=1 bit set. | 253 | * translated into block discard requests within backend code. |
| 252 | */ | 254 | */ |
| 253 | if (!(flags[0] & 0x08)) { | 255 | if (flags[0] & 0x08) { |
| 254 | pr_err("WRITE_SAME w/o UNMAP bit not" | 256 | if (!ops->execute_write_same_unmap) |
| 255 | " supported for Block Discard Emulation\n"); | 257 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 256 | return -ENOSYS; | 258 | |
| 259 | cmd->execute_cmd = ops->execute_write_same_unmap; | ||
| 260 | return 0; | ||
| 257 | } | 261 | } |
| 262 | if (!ops->execute_write_same) | ||
| 263 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
| 258 | 264 | ||
| 265 | cmd->execute_cmd = ops->execute_write_same; | ||
| 259 | return 0; | 266 | return 0; |
| 260 | } | 267 | } |
| 261 | 268 | ||
| @@ -313,14 +320,14 @@ out: | |||
| 313 | kfree(buf); | 320 | kfree(buf); |
| 314 | } | 321 | } |
| 315 | 322 | ||
| 316 | int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | 323 | sense_reason_t |
| 324 | sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | ||
| 317 | { | 325 | { |
| 318 | struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; | ||
| 319 | struct se_device *dev = cmd->se_dev; | 326 | struct se_device *dev = cmd->se_dev; |
| 320 | unsigned char *cdb = cmd->t_task_cdb; | 327 | unsigned char *cdb = cmd->t_task_cdb; |
| 321 | unsigned int size; | 328 | unsigned int size; |
| 322 | u32 sectors = 0; | 329 | u32 sectors = 0; |
| 323 | int ret; | 330 | sense_reason_t ret; |
| 324 | 331 | ||
| 325 | switch (cdb[0]) { | 332 | switch (cdb[0]) { |
| 326 | case READ_6: | 333 | case READ_6: |
| @@ -379,9 +386,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 379 | cmd->execute_cmd = ops->execute_rw; | 386 | cmd->execute_cmd = ops->execute_rw; |
| 380 | break; | 387 | break; |
| 381 | case XDWRITEREAD_10: | 388 | case XDWRITEREAD_10: |
| 382 | if ((cmd->data_direction != DMA_TO_DEVICE) || | 389 | if (cmd->data_direction != DMA_TO_DEVICE || |
| 383 | !(cmd->se_cmd_flags & SCF_BIDI)) | 390 | !(cmd->se_cmd_flags & SCF_BIDI)) |
| 384 | goto out_invalid_cdb_field; | 391 | return TCM_INVALID_CDB_FIELD; |
| 385 | sectors = transport_get_sectors_10(cdb); | 392 | sectors = transport_get_sectors_10(cdb); |
| 386 | 393 | ||
| 387 | cmd->t_task_lba = transport_lba_32(cdb); | 394 | cmd->t_task_lba = transport_lba_32(cdb); |
| @@ -419,27 +426,24 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 419 | cmd->se_cmd_flags |= SCF_FUA; | 426 | cmd->se_cmd_flags |= SCF_FUA; |
| 420 | break; | 427 | break; |
| 421 | case WRITE_SAME_32: | 428 | case WRITE_SAME_32: |
| 422 | if (!ops->execute_write_same) | ||
| 423 | goto out_unsupported_cdb; | ||
| 424 | |||
| 425 | sectors = transport_get_sectors_32(cdb); | 429 | sectors = transport_get_sectors_32(cdb); |
| 426 | if (!sectors) { | 430 | if (!sectors) { |
| 427 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" | 431 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" |
| 428 | " supported\n"); | 432 | " supported\n"); |
| 429 | goto out_invalid_cdb_field; | 433 | return TCM_INVALID_CDB_FIELD; |
| 430 | } | 434 | } |
| 431 | 435 | ||
| 432 | size = sbc_get_size(cmd, 1); | 436 | size = sbc_get_size(cmd, 1); |
| 433 | cmd->t_task_lba = get_unaligned_be64(&cdb[12]); | 437 | cmd->t_task_lba = get_unaligned_be64(&cdb[12]); |
| 434 | 438 | ||
| 435 | if (sbc_write_same_supported(dev, &cdb[10]) < 0) | 439 | ret = sbc_setup_write_same(cmd, &cdb[10], ops); |
| 436 | goto out_unsupported_cdb; | 440 | if (ret) |
| 437 | cmd->execute_cmd = ops->execute_write_same; | 441 | return ret; |
| 438 | break; | 442 | break; |
| 439 | default: | 443 | default: |
| 440 | pr_err("VARIABLE_LENGTH_CMD service action" | 444 | pr_err("VARIABLE_LENGTH_CMD service action" |
| 441 | " 0x%04x not supported\n", service_action); | 445 | " 0x%04x not supported\n", service_action); |
| 442 | goto out_unsupported_cdb; | 446 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 443 | } | 447 | } |
| 444 | break; | 448 | break; |
| 445 | } | 449 | } |
| @@ -455,7 +459,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 455 | default: | 459 | default: |
| 456 | pr_err("Unsupported SA: 0x%02x\n", | 460 | pr_err("Unsupported SA: 0x%02x\n", |
| 457 | cmd->t_task_cdb[1] & 0x1f); | 461 | cmd->t_task_cdb[1] & 0x1f); |
| 458 | goto out_invalid_cdb_field; | 462 | return TCM_INVALID_CDB_FIELD; |
| 459 | } | 463 | } |
| 460 | size = (cdb[10] << 24) | (cdb[11] << 16) | | 464 | size = (cdb[10] << 24) | (cdb[11] << 16) | |
| 461 | (cdb[12] << 8) | cdb[13]; | 465 | (cdb[12] << 8) | cdb[13]; |
| @@ -463,7 +467,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 463 | case SYNCHRONIZE_CACHE: | 467 | case SYNCHRONIZE_CACHE: |
| 464 | case SYNCHRONIZE_CACHE_16: | 468 | case SYNCHRONIZE_CACHE_16: |
| 465 | if (!ops->execute_sync_cache) | 469 | if (!ops->execute_sync_cache) |
| 466 | goto out_unsupported_cdb; | 470 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 467 | 471 | ||
| 468 | /* | 472 | /* |
| 469 | * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE | 473 | * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE |
| @@ -484,42 +488,36 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 484 | */ | 488 | */ |
| 485 | if (cmd->t_task_lba || sectors) { | 489 | if (cmd->t_task_lba || sectors) { |
| 486 | if (sbc_check_valid_sectors(cmd) < 0) | 490 | if (sbc_check_valid_sectors(cmd) < 0) |
| 487 | goto out_invalid_cdb_field; | 491 | return TCM_INVALID_CDB_FIELD; |
| 488 | } | 492 | } |
| 489 | cmd->execute_cmd = ops->execute_sync_cache; | 493 | cmd->execute_cmd = ops->execute_sync_cache; |
| 490 | break; | 494 | break; |
| 491 | case UNMAP: | 495 | case UNMAP: |
| 492 | if (!ops->execute_unmap) | 496 | if (!ops->execute_unmap) |
| 493 | goto out_unsupported_cdb; | 497 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 494 | 498 | ||
| 495 | size = get_unaligned_be16(&cdb[7]); | 499 | size = get_unaligned_be16(&cdb[7]); |
| 496 | cmd->execute_cmd = ops->execute_unmap; | 500 | cmd->execute_cmd = ops->execute_unmap; |
| 497 | break; | 501 | break; |
| 498 | case WRITE_SAME_16: | 502 | case WRITE_SAME_16: |
| 499 | if (!ops->execute_write_same) | ||
| 500 | goto out_unsupported_cdb; | ||
| 501 | |||
| 502 | sectors = transport_get_sectors_16(cdb); | 503 | sectors = transport_get_sectors_16(cdb); |
| 503 | if (!sectors) { | 504 | if (!sectors) { |
| 504 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); | 505 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); |
| 505 | goto out_invalid_cdb_field; | 506 | return TCM_INVALID_CDB_FIELD; |
| 506 | } | 507 | } |
| 507 | 508 | ||
| 508 | size = sbc_get_size(cmd, 1); | 509 | size = sbc_get_size(cmd, 1); |
| 509 | cmd->t_task_lba = get_unaligned_be64(&cdb[2]); | 510 | cmd->t_task_lba = get_unaligned_be64(&cdb[2]); |
| 510 | 511 | ||
| 511 | if (sbc_write_same_supported(dev, &cdb[1]) < 0) | 512 | ret = sbc_setup_write_same(cmd, &cdb[1], ops); |
| 512 | goto out_unsupported_cdb; | 513 | if (ret) |
| 513 | cmd->execute_cmd = ops->execute_write_same; | 514 | return ret; |
| 514 | break; | 515 | break; |
| 515 | case WRITE_SAME: | 516 | case WRITE_SAME: |
| 516 | if (!ops->execute_write_same) | ||
| 517 | goto out_unsupported_cdb; | ||
| 518 | |||
| 519 | sectors = transport_get_sectors_10(cdb); | 517 | sectors = transport_get_sectors_10(cdb); |
| 520 | if (!sectors) { | 518 | if (!sectors) { |
| 521 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); | 519 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); |
| 522 | goto out_invalid_cdb_field; | 520 | return TCM_INVALID_CDB_FIELD; |
| 523 | } | 521 | } |
| 524 | 522 | ||
| 525 | size = sbc_get_size(cmd, 1); | 523 | size = sbc_get_size(cmd, 1); |
| @@ -529,13 +527,13 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 529 | * Follow sbcr26 with WRITE_SAME (10) and check for the existence | 527 | * Follow sbcr26 with WRITE_SAME (10) and check for the existence |
| 530 | * of byte 1 bit 3 UNMAP instead of original reserved field | 528 | * of byte 1 bit 3 UNMAP instead of original reserved field |
| 531 | */ | 529 | */ |
| 532 | if (sbc_write_same_supported(dev, &cdb[1]) < 0) | 530 | ret = sbc_setup_write_same(cmd, &cdb[1], ops); |
| 533 | goto out_unsupported_cdb; | 531 | if (ret) |
| 534 | cmd->execute_cmd = ops->execute_write_same; | 532 | return ret; |
| 535 | break; | 533 | break; |
| 536 | case VERIFY: | 534 | case VERIFY: |
| 537 | size = 0; | 535 | size = 0; |
| 538 | cmd->execute_cmd = sbc_emulate_verify; | 536 | cmd->execute_cmd = sbc_emulate_noop; |
| 539 | break; | 537 | break; |
| 540 | case REZERO_UNIT: | 538 | case REZERO_UNIT: |
| 541 | case SEEK_6: | 539 | case SEEK_6: |
| @@ -557,24 +555,24 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 557 | 555 | ||
| 558 | /* reject any command that we don't have a handler for */ | 556 | /* reject any command that we don't have a handler for */ |
| 559 | if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd) | 557 | if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd) |
| 560 | goto out_unsupported_cdb; | 558 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 561 | 559 | ||
| 562 | if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { | 560 | if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { |
| 563 | unsigned long long end_lba; | 561 | unsigned long long end_lba; |
| 564 | 562 | ||
| 565 | if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) { | 563 | if (sectors > dev->dev_attrib.fabric_max_sectors) { |
| 566 | printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" | 564 | printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" |
| 567 | " big sectors %u exceeds fabric_max_sectors:" | 565 | " big sectors %u exceeds fabric_max_sectors:" |
| 568 | " %u\n", cdb[0], sectors, | 566 | " %u\n", cdb[0], sectors, |
| 569 | su_dev->se_dev_attrib.fabric_max_sectors); | 567 | dev->dev_attrib.fabric_max_sectors); |
| 570 | goto out_invalid_cdb_field; | 568 | return TCM_INVALID_CDB_FIELD; |
| 571 | } | 569 | } |
| 572 | if (sectors > su_dev->se_dev_attrib.hw_max_sectors) { | 570 | if (sectors > dev->dev_attrib.hw_max_sectors) { |
| 573 | printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" | 571 | printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" |
| 574 | " big sectors %u exceeds backend hw_max_sectors:" | 572 | " big sectors %u exceeds backend hw_max_sectors:" |
| 575 | " %u\n", cdb[0], sectors, | 573 | " %u\n", cdb[0], sectors, |
| 576 | su_dev->se_dev_attrib.hw_max_sectors); | 574 | dev->dev_attrib.hw_max_sectors); |
| 577 | goto out_invalid_cdb_field; | 575 | return TCM_INVALID_CDB_FIELD; |
| 578 | } | 576 | } |
| 579 | 577 | ||
| 580 | end_lba = dev->transport->get_blocks(dev) + 1; | 578 | end_lba = dev->transport->get_blocks(dev) + 1; |
| @@ -582,25 +580,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
| 582 | pr_err("cmd exceeds last lba %llu " | 580 | pr_err("cmd exceeds last lba %llu " |
| 583 | "(lba %llu, sectors %u)\n", | 581 | "(lba %llu, sectors %u)\n", |
| 584 | end_lba, cmd->t_task_lba, sectors); | 582 | end_lba, cmd->t_task_lba, sectors); |
| 585 | goto out_invalid_cdb_field; | 583 | return TCM_INVALID_CDB_FIELD; |
| 586 | } | 584 | } |
| 587 | 585 | ||
| 588 | size = sbc_get_size(cmd, sectors); | 586 | size = sbc_get_size(cmd, sectors); |
| 589 | } | 587 | } |
| 590 | 588 | ||
| 591 | ret = target_cmd_size_check(cmd, size); | 589 | return target_cmd_size_check(cmd, size); |
| 592 | if (ret < 0) | ||
| 593 | return ret; | ||
| 594 | |||
| 595 | return 0; | ||
| 596 | |||
| 597 | out_unsupported_cdb: | ||
| 598 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 599 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | ||
| 600 | return -EINVAL; | ||
| 601 | out_invalid_cdb_field: | ||
| 602 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 603 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 604 | return -EINVAL; | ||
| 605 | } | 590 | } |
| 606 | EXPORT_SYMBOL(sbc_parse_cdb); | 591 | EXPORT_SYMBOL(sbc_parse_cdb); |
| 592 | |||
| 593 | u32 sbc_get_device_type(struct se_device *dev) | ||
| 594 | { | ||
| 595 | return TYPE_DISK; | ||
| 596 | } | ||
| 597 | EXPORT_SYMBOL(sbc_get_device_type); | ||
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 6fd434d3d7e4..84f9e96e8ace 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c | |||
| @@ -1,10 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * SCSI Primary Commands (SPC) parsing and emulation. | 2 | * SCSI Primary Commands (SPC) parsing and emulation. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. | 4 | * (c) Copyright 2002-2012 RisingTide Systems LLC. |
| 5 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 6 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 7 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 8 | * | 5 | * |
| 9 | * Nicholas A. Bellinger <nab@kernel.org> | 6 | * Nicholas A. Bellinger <nab@kernel.org> |
| 10 | * | 7 | * |
| @@ -69,7 +66,8 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf) | |||
| 69 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 66 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
| 70 | } | 67 | } |
| 71 | 68 | ||
| 72 | static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) | 69 | static sense_reason_t |
| 70 | spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) | ||
| 73 | { | 71 | { |
| 74 | struct se_lun *lun = cmd->se_lun; | 72 | struct se_lun *lun = cmd->se_lun; |
| 75 | struct se_device *dev = cmd->se_dev; | 73 | struct se_device *dev = cmd->se_dev; |
| @@ -78,7 +76,7 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) | |||
| 78 | if (dev->transport->get_device_type(dev) == TYPE_TAPE) | 76 | if (dev->transport->get_device_type(dev) == TYPE_TAPE) |
| 79 | buf[1] = 0x80; | 77 | buf[1] = 0x80; |
| 80 | 78 | ||
| 81 | buf[2] = dev->transport->get_device_rev(dev); | 79 | buf[2] = 0x05; /* SPC-3 */ |
| 82 | 80 | ||
| 83 | /* | 81 | /* |
| 84 | * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2 | 82 | * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2 |
| @@ -95,34 +93,32 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) | |||
| 95 | /* | 93 | /* |
| 96 | * Enable SCCS and TPGS fields for Emulated ALUA | 94 | * Enable SCCS and TPGS fields for Emulated ALUA |
| 97 | */ | 95 | */ |
| 98 | if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) | 96 | spc_fill_alua_data(lun->lun_sep, buf); |
| 99 | spc_fill_alua_data(lun->lun_sep, buf); | ||
| 100 | 97 | ||
| 101 | buf[7] = 0x2; /* CmdQue=1 */ | 98 | buf[7] = 0x2; /* CmdQue=1 */ |
| 102 | 99 | ||
| 103 | snprintf(&buf[8], 8, "LIO-ORG"); | 100 | snprintf(&buf[8], 8, "LIO-ORG"); |
| 104 | snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model); | 101 | snprintf(&buf[16], 16, "%s", dev->t10_wwn.model); |
| 105 | snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision); | 102 | snprintf(&buf[32], 4, "%s", dev->t10_wwn.revision); |
| 106 | buf[4] = 31; /* Set additional length to 31 */ | 103 | buf[4] = 31; /* Set additional length to 31 */ |
| 107 | 104 | ||
| 108 | return 0; | 105 | return 0; |
| 109 | } | 106 | } |
| 110 | 107 | ||
| 111 | /* unit serial number */ | 108 | /* unit serial number */ |
| 112 | static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) | 109 | static sense_reason_t |
| 110 | spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) | ||
| 113 | { | 111 | { |
| 114 | struct se_device *dev = cmd->se_dev; | 112 | struct se_device *dev = cmd->se_dev; |
| 115 | u16 len = 0; | 113 | u16 len = 0; |
| 116 | 114 | ||
| 117 | if (dev->se_sub_dev->su_dev_flags & | 115 | if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { |
| 118 | SDF_EMULATED_VPD_UNIT_SERIAL) { | ||
| 119 | u32 unit_serial_len; | 116 | u32 unit_serial_len; |
| 120 | 117 | ||
| 121 | unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial); | 118 | unit_serial_len = strlen(dev->t10_wwn.unit_serial); |
| 122 | unit_serial_len++; /* For NULL Terminator */ | 119 | unit_serial_len++; /* For NULL Terminator */ |
| 123 | 120 | ||
| 124 | len += sprintf(&buf[4], "%s", | 121 | len += sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial); |
| 125 | dev->se_sub_dev->t10_wwn.unit_serial); | ||
| 126 | len++; /* Extra Byte for NULL Terminator */ | 122 | len++; /* Extra Byte for NULL Terminator */ |
| 127 | buf[3] = len; | 123 | buf[3] = len; |
| 128 | } | 124 | } |
| @@ -132,7 +128,7 @@ static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) | |||
| 132 | static void spc_parse_naa_6h_vendor_specific(struct se_device *dev, | 128 | static void spc_parse_naa_6h_vendor_specific(struct se_device *dev, |
| 133 | unsigned char *buf) | 129 | unsigned char *buf) |
| 134 | { | 130 | { |
| 135 | unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0]; | 131 | unsigned char *p = &dev->t10_wwn.unit_serial[0]; |
| 136 | int cnt; | 132 | int cnt; |
| 137 | bool next = true; | 133 | bool next = true; |
| 138 | 134 | ||
| @@ -164,7 +160,8 @@ static void spc_parse_naa_6h_vendor_specific(struct se_device *dev, | |||
| 164 | * Device identification VPD, for a complete list of | 160 | * Device identification VPD, for a complete list of |
| 165 | * DESIGNATOR TYPEs see spc4r17 Table 459. | 161 | * DESIGNATOR TYPEs see spc4r17 Table 459. |
| 166 | */ | 162 | */ |
| 167 | static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) | 163 | static sense_reason_t |
| 164 | spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) | ||
| 168 | { | 165 | { |
| 169 | struct se_device *dev = cmd->se_dev; | 166 | struct se_device *dev = cmd->se_dev; |
| 170 | struct se_lun *lun = cmd->se_lun; | 167 | struct se_lun *lun = cmd->se_lun; |
| @@ -173,7 +170,7 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) | |||
| 173 | struct t10_alua_lu_gp_member *lu_gp_mem; | 170 | struct t10_alua_lu_gp_member *lu_gp_mem; |
| 174 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 171 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
| 175 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | 172 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; |
| 176 | unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0]; | 173 | unsigned char *prod = &dev->t10_wwn.model[0]; |
| 177 | u32 prod_len; | 174 | u32 prod_len; |
| 178 | u32 unit_serial_len, off = 0; | 175 | u32 unit_serial_len, off = 0; |
| 179 | u16 len = 0, id_len; | 176 | u16 len = 0, id_len; |
| @@ -188,7 +185,7 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) | |||
| 188 | * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial | 185 | * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial |
| 189 | * value in order to return the NAA id. | 186 | * value in order to return the NAA id. |
| 190 | */ | 187 | */ |
| 191 | if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL)) | 188 | if (!(dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL)) |
| 192 | goto check_t10_vend_desc; | 189 | goto check_t10_vend_desc; |
| 193 | 190 | ||
| 194 | /* CODE SET == Binary */ | 191 | /* CODE SET == Binary */ |
| @@ -236,14 +233,12 @@ check_t10_vend_desc: | |||
| 236 | prod_len += strlen(prod); | 233 | prod_len += strlen(prod); |
| 237 | prod_len++; /* For : */ | 234 | prod_len++; /* For : */ |
| 238 | 235 | ||
| 239 | if (dev->se_sub_dev->su_dev_flags & | 236 | if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { |
| 240 | SDF_EMULATED_VPD_UNIT_SERIAL) { | 237 | unit_serial_len = strlen(&dev->t10_wwn.unit_serial[0]); |
| 241 | unit_serial_len = | ||
| 242 | strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]); | ||
| 243 | unit_serial_len++; /* For NULL Terminator */ | 238 | unit_serial_len++; /* For NULL Terminator */ |
| 244 | 239 | ||
| 245 | id_len += sprintf(&buf[off+12], "%s:%s", prod, | 240 | id_len += sprintf(&buf[off+12], "%s:%s", prod, |
| 246 | &dev->se_sub_dev->t10_wwn.unit_serial[0]); | 241 | &dev->t10_wwn.unit_serial[0]); |
| 247 | } | 242 | } |
| 248 | buf[off] = 0x2; /* ASCII */ | 243 | buf[off] = 0x2; /* ASCII */ |
| 249 | buf[off+1] = 0x1; /* T10 Vendor ID */ | 244 | buf[off+1] = 0x1; /* T10 Vendor ID */ |
| @@ -298,10 +293,6 @@ check_t10_vend_desc: | |||
| 298 | * Get the PROTOCOL IDENTIFIER as defined by spc4r17 | 293 | * Get the PROTOCOL IDENTIFIER as defined by spc4r17 |
| 299 | * section 7.5.1 Table 362 | 294 | * section 7.5.1 Table 362 |
| 300 | */ | 295 | */ |
| 301 | if (dev->se_sub_dev->t10_alua.alua_type != | ||
| 302 | SPC3_ALUA_EMULATED) | ||
| 303 | goto check_scsi_name; | ||
| 304 | |||
| 305 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | 296 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; |
| 306 | if (!tg_pt_gp_mem) | 297 | if (!tg_pt_gp_mem) |
| 307 | goto check_lu_gp; | 298 | goto check_lu_gp; |
| @@ -415,20 +406,22 @@ check_scsi_name: | |||
| 415 | } | 406 | } |
| 416 | 407 | ||
| 417 | /* Extended INQUIRY Data VPD Page */ | 408 | /* Extended INQUIRY Data VPD Page */ |
| 418 | static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) | 409 | static sense_reason_t |
| 410 | spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) | ||
| 419 | { | 411 | { |
| 420 | buf[3] = 0x3c; | 412 | buf[3] = 0x3c; |
| 421 | /* Set HEADSUP, ORDSUP, SIMPSUP */ | 413 | /* Set HEADSUP, ORDSUP, SIMPSUP */ |
| 422 | buf[5] = 0x07; | 414 | buf[5] = 0x07; |
| 423 | 415 | ||
| 424 | /* If WriteCache emulation is enabled, set V_SUP */ | 416 | /* If WriteCache emulation is enabled, set V_SUP */ |
| 425 | if (cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) | 417 | if (cmd->se_dev->dev_attrib.emulate_write_cache > 0) |
| 426 | buf[6] = 0x01; | 418 | buf[6] = 0x01; |
| 427 | return 0; | 419 | return 0; |
| 428 | } | 420 | } |
| 429 | 421 | ||
| 430 | /* Block Limits VPD page */ | 422 | /* Block Limits VPD page */ |
| 431 | static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | 423 | static sense_reason_t |
| 424 | spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | ||
| 432 | { | 425 | { |
| 433 | struct se_device *dev = cmd->se_dev; | 426 | struct se_device *dev = cmd->se_dev; |
| 434 | u32 max_sectors; | 427 | u32 max_sectors; |
| @@ -439,7 +432,7 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | |||
| 439 | * emulate_tpu=1 or emulate_tpws=1 we will be expect a | 432 | * emulate_tpu=1 or emulate_tpws=1 we will be expect a |
| 440 | * different page length for Thin Provisioning. | 433 | * different page length for Thin Provisioning. |
| 441 | */ | 434 | */ |
| 442 | if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) | 435 | if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) |
| 443 | have_tp = 1; | 436 | have_tp = 1; |
| 444 | 437 | ||
| 445 | buf[0] = dev->transport->get_device_type(dev); | 438 | buf[0] = dev->transport->get_device_type(dev); |
| @@ -456,62 +449,70 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | |||
| 456 | /* | 449 | /* |
| 457 | * Set MAXIMUM TRANSFER LENGTH | 450 | * Set MAXIMUM TRANSFER LENGTH |
| 458 | */ | 451 | */ |
| 459 | max_sectors = min(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors, | 452 | max_sectors = min(dev->dev_attrib.fabric_max_sectors, |
| 460 | dev->se_sub_dev->se_dev_attrib.hw_max_sectors); | 453 | dev->dev_attrib.hw_max_sectors); |
| 461 | put_unaligned_be32(max_sectors, &buf[8]); | 454 | put_unaligned_be32(max_sectors, &buf[8]); |
| 462 | 455 | ||
| 463 | /* | 456 | /* |
| 464 | * Set OPTIMAL TRANSFER LENGTH | 457 | * Set OPTIMAL TRANSFER LENGTH |
| 465 | */ | 458 | */ |
| 466 | put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]); | 459 | put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]); |
| 467 | 460 | ||
| 468 | /* | 461 | /* |
| 469 | * Exit now if we don't support TP. | 462 | * Exit now if we don't support TP. |
| 470 | */ | 463 | */ |
| 471 | if (!have_tp) | 464 | if (!have_tp) |
| 472 | return 0; | 465 | goto max_write_same; |
| 473 | 466 | ||
| 474 | /* | 467 | /* |
| 475 | * Set MAXIMUM UNMAP LBA COUNT | 468 | * Set MAXIMUM UNMAP LBA COUNT |
| 476 | */ | 469 | */ |
| 477 | put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count, &buf[20]); | 470 | put_unaligned_be32(dev->dev_attrib.max_unmap_lba_count, &buf[20]); |
| 478 | 471 | ||
| 479 | /* | 472 | /* |
| 480 | * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT | 473 | * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT |
| 481 | */ | 474 | */ |
| 482 | put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count, | 475 | put_unaligned_be32(dev->dev_attrib.max_unmap_block_desc_count, |
| 483 | &buf[24]); | 476 | &buf[24]); |
| 484 | 477 | ||
| 485 | /* | 478 | /* |
| 486 | * Set OPTIMAL UNMAP GRANULARITY | 479 | * Set OPTIMAL UNMAP GRANULARITY |
| 487 | */ | 480 | */ |
| 488 | put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity, &buf[28]); | 481 | put_unaligned_be32(dev->dev_attrib.unmap_granularity, &buf[28]); |
| 489 | 482 | ||
| 490 | /* | 483 | /* |
| 491 | * UNMAP GRANULARITY ALIGNMENT | 484 | * UNMAP GRANULARITY ALIGNMENT |
| 492 | */ | 485 | */ |
| 493 | put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment, | 486 | put_unaligned_be32(dev->dev_attrib.unmap_granularity_alignment, |
| 494 | &buf[32]); | 487 | &buf[32]); |
| 495 | if (dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment != 0) | 488 | if (dev->dev_attrib.unmap_granularity_alignment != 0) |
| 496 | buf[32] |= 0x80; /* Set the UGAVALID bit */ | 489 | buf[32] |= 0x80; /* Set the UGAVALID bit */ |
| 497 | 490 | ||
| 491 | /* | ||
| 492 | * MAXIMUM WRITE SAME LENGTH | ||
| 493 | */ | ||
| 494 | max_write_same: | ||
| 495 | put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]); | ||
| 496 | |||
| 498 | return 0; | 497 | return 0; |
| 499 | } | 498 | } |
| 500 | 499 | ||
| 501 | /* Block Device Characteristics VPD page */ | 500 | /* Block Device Characteristics VPD page */ |
| 502 | static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) | 501 | static sense_reason_t |
| 502 | spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) | ||
| 503 | { | 503 | { |
| 504 | struct se_device *dev = cmd->se_dev; | 504 | struct se_device *dev = cmd->se_dev; |
| 505 | 505 | ||
| 506 | buf[0] = dev->transport->get_device_type(dev); | 506 | buf[0] = dev->transport->get_device_type(dev); |
| 507 | buf[3] = 0x3c; | 507 | buf[3] = 0x3c; |
| 508 | buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0; | 508 | buf[5] = dev->dev_attrib.is_nonrot ? 1 : 0; |
| 509 | 509 | ||
| 510 | return 0; | 510 | return 0; |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | /* Thin Provisioning VPD */ | 513 | /* Thin Provisioning VPD */ |
| 514 | static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) | 514 | static sense_reason_t |
| 515 | spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) | ||
| 515 | { | 516 | { |
| 516 | struct se_device *dev = cmd->se_dev; | 517 | struct se_device *dev = cmd->se_dev; |
| 517 | 518 | ||
| @@ -546,7 +547,7 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) | |||
| 546 | * the UNMAP command (see 5.25). A TPU bit set to zero indicates | 547 | * the UNMAP command (see 5.25). A TPU bit set to zero indicates |
| 547 | * that the device server does not support the UNMAP command. | 548 | * that the device server does not support the UNMAP command. |
| 548 | */ | 549 | */ |
| 549 | if (dev->se_sub_dev->se_dev_attrib.emulate_tpu != 0) | 550 | if (dev->dev_attrib.emulate_tpu != 0) |
| 550 | buf[5] = 0x80; | 551 | buf[5] = 0x80; |
| 551 | 552 | ||
| 552 | /* | 553 | /* |
| @@ -555,17 +556,18 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) | |||
| 555 | * A TPWS bit set to zero indicates that the device server does not | 556 | * A TPWS bit set to zero indicates that the device server does not |
| 556 | * support the use of the WRITE SAME (16) command to unmap LBAs. | 557 | * support the use of the WRITE SAME (16) command to unmap LBAs. |
| 557 | */ | 558 | */ |
| 558 | if (dev->se_sub_dev->se_dev_attrib.emulate_tpws != 0) | 559 | if (dev->dev_attrib.emulate_tpws != 0) |
| 559 | buf[5] |= 0x40; | 560 | buf[5] |= 0x40; |
| 560 | 561 | ||
| 561 | return 0; | 562 | return 0; |
| 562 | } | 563 | } |
| 563 | 564 | ||
| 564 | static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); | 565 | static sense_reason_t |
| 566 | spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); | ||
| 565 | 567 | ||
| 566 | static struct { | 568 | static struct { |
| 567 | uint8_t page; | 569 | uint8_t page; |
| 568 | int (*emulate)(struct se_cmd *, unsigned char *); | 570 | sense_reason_t (*emulate)(struct se_cmd *, unsigned char *); |
| 569 | } evpd_handlers[] = { | 571 | } evpd_handlers[] = { |
| 570 | { .page = 0x00, .emulate = spc_emulate_evpd_00 }, | 572 | { .page = 0x00, .emulate = spc_emulate_evpd_00 }, |
| 571 | { .page = 0x80, .emulate = spc_emulate_evpd_80 }, | 573 | { .page = 0x80, .emulate = spc_emulate_evpd_80 }, |
| @@ -577,7 +579,8 @@ static struct { | |||
| 577 | }; | 579 | }; |
| 578 | 580 | ||
| 579 | /* supported vital product data pages */ | 581 | /* supported vital product data pages */ |
| 580 | static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) | 582 | static sense_reason_t |
| 583 | spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) | ||
| 581 | { | 584 | { |
| 582 | int p; | 585 | int p; |
| 583 | 586 | ||
| @@ -586,8 +589,7 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) | |||
| 586 | * Registered Extended LUN WWN has been set via ConfigFS | 589 | * Registered Extended LUN WWN has been set via ConfigFS |
| 587 | * during device creation/restart. | 590 | * during device creation/restart. |
| 588 | */ | 591 | */ |
| 589 | if (cmd->se_dev->se_sub_dev->su_dev_flags & | 592 | if (cmd->se_dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { |
| 590 | SDF_EMULATED_VPD_UNIT_SERIAL) { | ||
| 591 | buf[3] = ARRAY_SIZE(evpd_handlers); | 593 | buf[3] = ARRAY_SIZE(evpd_handlers); |
| 592 | for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) | 594 | for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) |
| 593 | buf[p + 4] = evpd_handlers[p].page; | 595 | buf[p + 4] = evpd_handlers[p].page; |
| @@ -596,14 +598,16 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) | |||
| 596 | return 0; | 598 | return 0; |
| 597 | } | 599 | } |
| 598 | 600 | ||
| 599 | static int spc_emulate_inquiry(struct se_cmd *cmd) | 601 | static sense_reason_t |
| 602 | spc_emulate_inquiry(struct se_cmd *cmd) | ||
| 600 | { | 603 | { |
| 601 | struct se_device *dev = cmd->se_dev; | 604 | struct se_device *dev = cmd->se_dev; |
| 602 | struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; | 605 | struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; |
| 603 | unsigned char *rbuf; | 606 | unsigned char *rbuf; |
| 604 | unsigned char *cdb = cmd->t_task_cdb; | 607 | unsigned char *cdb = cmd->t_task_cdb; |
| 605 | unsigned char buf[SE_INQUIRY_BUF]; | 608 | unsigned char buf[SE_INQUIRY_BUF]; |
| 606 | int p, ret; | 609 | sense_reason_t ret; |
| 610 | int p; | ||
| 607 | 611 | ||
| 608 | memset(buf, 0, SE_INQUIRY_BUF); | 612 | memset(buf, 0, SE_INQUIRY_BUF); |
| 609 | 613 | ||
| @@ -616,8 +620,7 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) | |||
| 616 | if (cdb[2]) { | 620 | if (cdb[2]) { |
| 617 | pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", | 621 | pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", |
| 618 | cdb[2]); | 622 | cdb[2]); |
| 619 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 623 | ret = TCM_INVALID_CDB_FIELD; |
| 620 | ret = -EINVAL; | ||
| 621 | goto out; | 624 | goto out; |
| 622 | } | 625 | } |
| 623 | 626 | ||
| @@ -634,33 +637,43 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) | |||
| 634 | } | 637 | } |
| 635 | 638 | ||
| 636 | pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); | 639 | pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); |
| 637 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 640 | ret = TCM_INVALID_CDB_FIELD; |
| 638 | ret = -EINVAL; | ||
| 639 | 641 | ||
| 640 | out: | 642 | out: |
| 641 | rbuf = transport_kmap_data_sg(cmd); | 643 | rbuf = transport_kmap_data_sg(cmd); |
| 642 | if (rbuf) { | 644 | if (!rbuf) |
| 643 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 645 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 644 | transport_kunmap_data_sg(cmd); | 646 | |
| 645 | } | 647 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
| 648 | transport_kunmap_data_sg(cmd); | ||
| 646 | 649 | ||
| 647 | if (!ret) | 650 | if (!ret) |
| 648 | target_complete_cmd(cmd, GOOD); | 651 | target_complete_cmd(cmd, GOOD); |
| 649 | return ret; | 652 | return ret; |
| 650 | } | 653 | } |
| 651 | 654 | ||
| 652 | static int spc_modesense_rwrecovery(unsigned char *p) | 655 | static int spc_modesense_rwrecovery(struct se_device *dev, u8 pc, u8 *p) |
| 653 | { | 656 | { |
| 654 | p[0] = 0x01; | 657 | p[0] = 0x01; |
| 655 | p[1] = 0x0a; | 658 | p[1] = 0x0a; |
| 656 | 659 | ||
| 660 | /* No changeable values for now */ | ||
| 661 | if (pc == 1) | ||
| 662 | goto out; | ||
| 663 | |||
| 664 | out: | ||
| 657 | return 12; | 665 | return 12; |
| 658 | } | 666 | } |
| 659 | 667 | ||
| 660 | static int spc_modesense_control(struct se_device *dev, unsigned char *p) | 668 | static int spc_modesense_control(struct se_device *dev, u8 pc, u8 *p) |
| 661 | { | 669 | { |
| 662 | p[0] = 0x0a; | 670 | p[0] = 0x0a; |
| 663 | p[1] = 0x0a; | 671 | p[1] = 0x0a; |
| 672 | |||
| 673 | /* No changeable values for now */ | ||
| 674 | if (pc == 1) | ||
| 675 | goto out; | ||
| 676 | |||
| 664 | p[2] = 2; | 677 | p[2] = 2; |
| 665 | /* | 678 | /* |
| 666 | * From spc4r23, 7.4.7 Control mode page | 679 | * From spc4r23, 7.4.7 Control mode page |
| @@ -690,7 +703,7 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p) | |||
| 690 | * command sequence order shall be explicitly handled by the application client | 703 | * command sequence order shall be explicitly handled by the application client |
| 691 | * through the selection of appropriate ommands and task attributes. | 704 | * through the selection of appropriate ommands and task attributes. |
| 692 | */ | 705 | */ |
| 693 | p[3] = (dev->se_sub_dev->se_dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10; | 706 | p[3] = (dev->dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10; |
| 694 | /* | 707 | /* |
| 695 | * From spc4r17, section 7.4.6 Control mode Page | 708 | * From spc4r17, section 7.4.6 Control mode Page |
| 696 | * | 709 | * |
| @@ -720,8 +733,8 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p) | |||
| 720 | * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless | 733 | * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless |
| 721 | * to the number of commands completed with one of those status codes. | 734 | * to the number of commands completed with one of those status codes. |
| 722 | */ | 735 | */ |
| 723 | p[4] = (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 : | 736 | p[4] = (dev->dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 : |
| 724 | (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00; | 737 | (dev->dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00; |
| 725 | /* | 738 | /* |
| 726 | * From spc4r17, section 7.4.6 Control mode Page | 739 | * From spc4r17, section 7.4.6 Control mode Page |
| 727 | * | 740 | * |
| @@ -734,25 +747,56 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p) | |||
| 734 | * which the command was received shall be completed with TASK ABORTED | 747 | * which the command was received shall be completed with TASK ABORTED |
| 735 | * status (see SAM-4). | 748 | * status (see SAM-4). |
| 736 | */ | 749 | */ |
| 737 | p[5] = (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? 0x40 : 0x00; | 750 | p[5] = (dev->dev_attrib.emulate_tas) ? 0x40 : 0x00; |
| 738 | p[8] = 0xff; | 751 | p[8] = 0xff; |
| 739 | p[9] = 0xff; | 752 | p[9] = 0xff; |
| 740 | p[11] = 30; | 753 | p[11] = 30; |
| 741 | 754 | ||
| 755 | out: | ||
| 742 | return 12; | 756 | return 12; |
| 743 | } | 757 | } |
| 744 | 758 | ||
| 745 | static int spc_modesense_caching(struct se_device *dev, unsigned char *p) | 759 | static int spc_modesense_caching(struct se_device *dev, u8 pc, u8 *p) |
| 746 | { | 760 | { |
| 747 | p[0] = 0x08; | 761 | p[0] = 0x08; |
| 748 | p[1] = 0x12; | 762 | p[1] = 0x12; |
| 749 | if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) | 763 | |
| 764 | /* No changeable values for now */ | ||
| 765 | if (pc == 1) | ||
| 766 | goto out; | ||
| 767 | |||
| 768 | if (dev->dev_attrib.emulate_write_cache > 0) | ||
| 750 | p[2] = 0x04; /* Write Cache Enable */ | 769 | p[2] = 0x04; /* Write Cache Enable */ |
| 751 | p[12] = 0x20; /* Disabled Read Ahead */ | 770 | p[12] = 0x20; /* Disabled Read Ahead */ |
| 752 | 771 | ||
| 772 | out: | ||
| 753 | return 20; | 773 | return 20; |
| 754 | } | 774 | } |
| 755 | 775 | ||
| 776 | static int spc_modesense_informational_exceptions(struct se_device *dev, u8 pc, unsigned char *p) | ||
| 777 | { | ||
| 778 | p[0] = 0x1c; | ||
| 779 | p[1] = 0x0a; | ||
| 780 | |||
| 781 | /* No changeable values for now */ | ||
| 782 | if (pc == 1) | ||
| 783 | goto out; | ||
| 784 | |||
| 785 | out: | ||
| 786 | return 12; | ||
| 787 | } | ||
| 788 | |||
| 789 | static struct { | ||
| 790 | uint8_t page; | ||
| 791 | uint8_t subpage; | ||
| 792 | int (*emulate)(struct se_device *, u8, unsigned char *); | ||
| 793 | } modesense_handlers[] = { | ||
| 794 | { .page = 0x01, .subpage = 0x00, .emulate = spc_modesense_rwrecovery }, | ||
| 795 | { .page = 0x08, .subpage = 0x00, .emulate = spc_modesense_caching }, | ||
| 796 | { .page = 0x0a, .subpage = 0x00, .emulate = spc_modesense_control }, | ||
| 797 | { .page = 0x1c, .subpage = 0x00, .emulate = spc_modesense_informational_exceptions }, | ||
| 798 | }; | ||
| 799 | |||
| 756 | static void spc_modesense_write_protect(unsigned char *buf, int type) | 800 | static void spc_modesense_write_protect(unsigned char *buf, int type) |
| 757 | { | 801 | { |
| 758 | /* | 802 | /* |
| @@ -779,82 +823,224 @@ static void spc_modesense_dpofua(unsigned char *buf, int type) | |||
| 779 | } | 823 | } |
| 780 | } | 824 | } |
| 781 | 825 | ||
| 782 | static int spc_emulate_modesense(struct se_cmd *cmd) | 826 | static int spc_modesense_blockdesc(unsigned char *buf, u64 blocks, u32 block_size) |
| 827 | { | ||
| 828 | *buf++ = 8; | ||
| 829 | put_unaligned_be32(min(blocks, 0xffffffffull), buf); | ||
| 830 | buf += 4; | ||
| 831 | put_unaligned_be32(block_size, buf); | ||
| 832 | return 9; | ||
| 833 | } | ||
| 834 | |||
| 835 | static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 block_size) | ||
| 836 | { | ||
| 837 | if (blocks <= 0xffffffff) | ||
| 838 | return spc_modesense_blockdesc(buf + 3, blocks, block_size) + 3; | ||
| 839 | |||
| 840 | *buf++ = 1; /* LONGLBA */ | ||
| 841 | buf += 2; | ||
| 842 | *buf++ = 16; | ||
| 843 | put_unaligned_be64(blocks, buf); | ||
| 844 | buf += 12; | ||
| 845 | put_unaligned_be32(block_size, buf); | ||
| 846 | |||
| 847 | return 17; | ||
| 848 | } | ||
| 849 | |||
| 850 | static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | ||
| 783 | { | 851 | { |
| 784 | struct se_device *dev = cmd->se_dev; | 852 | struct se_device *dev = cmd->se_dev; |
| 785 | char *cdb = cmd->t_task_cdb; | 853 | char *cdb = cmd->t_task_cdb; |
| 786 | unsigned char *rbuf; | 854 | unsigned char *buf, *map_buf; |
| 787 | int type = dev->transport->get_device_type(dev); | 855 | int type = dev->transport->get_device_type(dev); |
| 788 | int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); | 856 | int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); |
| 789 | u32 offset = ten ? 8 : 4; | 857 | bool dbd = !!(cdb[1] & 0x08); |
| 858 | bool llba = ten ? !!(cdb[1] & 0x10) : false; | ||
| 859 | u8 pc = cdb[2] >> 6; | ||
| 860 | u8 page = cdb[2] & 0x3f; | ||
| 861 | u8 subpage = cdb[3]; | ||
| 790 | int length = 0; | 862 | int length = 0; |
| 791 | unsigned char buf[SE_MODE_PAGE_BUF]; | 863 | int ret; |
| 792 | 864 | int i; | |
| 793 | memset(buf, 0, SE_MODE_PAGE_BUF); | ||
| 794 | 865 | ||
| 795 | switch (cdb[2] & 0x3f) { | 866 | map_buf = transport_kmap_data_sg(cmd); |
| 796 | case 0x01: | 867 | if (!map_buf) |
| 797 | length = spc_modesense_rwrecovery(&buf[offset]); | 868 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 798 | break; | 869 | /* |
| 799 | case 0x08: | 870 | * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we |
| 800 | length = spc_modesense_caching(dev, &buf[offset]); | 871 | * know we actually allocated a full page. Otherwise, if the |
| 801 | break; | 872 | * data buffer is too small, allocate a temporary buffer so we |
| 802 | case 0x0a: | 873 | * don't have to worry about overruns in all our INQUIRY |
| 803 | length = spc_modesense_control(dev, &buf[offset]); | 874 | * emulation handling. |
| 804 | break; | 875 | */ |
| 805 | case 0x3f: | 876 | if (cmd->data_length < SE_MODE_PAGE_BUF && |
| 806 | length = spc_modesense_rwrecovery(&buf[offset]); | 877 | (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { |
| 807 | length += spc_modesense_caching(dev, &buf[offset+length]); | 878 | buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); |
| 808 | length += spc_modesense_control(dev, &buf[offset+length]); | 879 | if (!buf) { |
| 809 | break; | 880 | transport_kunmap_data_sg(cmd); |
| 810 | default: | 881 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 811 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", | 882 | } |
| 812 | cdb[2] & 0x3f, cdb[3]); | 883 | } else { |
| 813 | cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; | 884 | buf = map_buf; |
| 814 | return -EINVAL; | ||
| 815 | } | 885 | } |
| 816 | offset += length; | 886 | /* |
| 817 | 887 | * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for | |
| 818 | if (ten) { | 888 | * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). |
| 819 | offset -= 2; | 889 | */ |
| 820 | buf[0] = (offset >> 8) & 0xff; | 890 | length = ten ? 3 : 2; |
| 821 | buf[1] = offset & 0xff; | 891 | |
| 822 | offset += 2; | 892 | /* DEVICE-SPECIFIC PARAMETER */ |
| 823 | 893 | if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || | |
| 824 | if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || | 894 | (cmd->se_deve && |
| 825 | (cmd->se_deve && | 895 | (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) |
| 826 | (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) | 896 | spc_modesense_write_protect(&buf[length], type); |
| 827 | spc_modesense_write_protect(&buf[3], type); | 897 | |
| 828 | 898 | if ((dev->dev_attrib.emulate_write_cache > 0) && | |
| 829 | if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && | 899 | (dev->dev_attrib.emulate_fua_write > 0)) |
| 830 | (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) | 900 | spc_modesense_dpofua(&buf[length], type); |
| 831 | spc_modesense_dpofua(&buf[3], type); | 901 | |
| 902 | ++length; | ||
| 903 | |||
| 904 | /* BLOCK DESCRIPTOR */ | ||
| 905 | |||
| 906 | /* | ||
| 907 | * For now we only include a block descriptor for disk (SBC) | ||
| 908 | * devices; other command sets use a slightly different format. | ||
| 909 | */ | ||
| 910 | if (!dbd && type == TYPE_DISK) { | ||
| 911 | u64 blocks = dev->transport->get_blocks(dev); | ||
| 912 | u32 block_size = dev->dev_attrib.block_size; | ||
| 913 | |||
| 914 | if (ten) { | ||
| 915 | if (llba) { | ||
| 916 | length += spc_modesense_long_blockdesc(&buf[length], | ||
| 917 | blocks, block_size); | ||
| 918 | } else { | ||
| 919 | length += 3; | ||
| 920 | length += spc_modesense_blockdesc(&buf[length], | ||
| 921 | blocks, block_size); | ||
| 922 | } | ||
| 923 | } else { | ||
| 924 | length += spc_modesense_blockdesc(&buf[length], blocks, | ||
| 925 | block_size); | ||
| 926 | } | ||
| 832 | } else { | 927 | } else { |
| 833 | offset -= 1; | 928 | if (ten) |
| 834 | buf[0] = offset & 0xff; | 929 | length += 4; |
| 835 | offset += 1; | 930 | else |
| 836 | 931 | length += 1; | |
| 837 | if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || | ||
| 838 | (cmd->se_deve && | ||
| 839 | (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) | ||
| 840 | spc_modesense_write_protect(&buf[2], type); | ||
| 841 | |||
| 842 | if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && | ||
| 843 | (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) | ||
| 844 | spc_modesense_dpofua(&buf[2], type); | ||
| 845 | } | 932 | } |
| 846 | 933 | ||
| 847 | rbuf = transport_kmap_data_sg(cmd); | 934 | if (page == 0x3f) { |
| 848 | if (rbuf) { | 935 | if (subpage != 0x00 && subpage != 0xff) { |
| 849 | memcpy(rbuf, buf, min(offset, cmd->data_length)); | 936 | pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); |
| 850 | transport_kunmap_data_sg(cmd); | 937 | kfree(buf); |
| 938 | transport_kunmap_data_sg(cmd); | ||
| 939 | return TCM_INVALID_CDB_FIELD; | ||
| 940 | } | ||
| 941 | |||
| 942 | for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) { | ||
| 943 | /* | ||
| 944 | * Tricky way to say all subpage 00h for | ||
| 945 | * subpage==0, all subpages for subpage==0xff | ||
| 946 | * (and we just checked above that those are | ||
| 947 | * the only two possibilities). | ||
| 948 | */ | ||
| 949 | if ((modesense_handlers[i].subpage & ~subpage) == 0) { | ||
| 950 | ret = modesense_handlers[i].emulate(dev, pc, &buf[length]); | ||
| 951 | if (!ten && length + ret >= 255) | ||
| 952 | break; | ||
| 953 | length += ret; | ||
| 954 | } | ||
| 955 | } | ||
| 956 | |||
| 957 | goto set_length; | ||
| 958 | } | ||
| 959 | |||
| 960 | for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) | ||
| 961 | if (modesense_handlers[i].page == page && | ||
| 962 | modesense_handlers[i].subpage == subpage) { | ||
| 963 | length += modesense_handlers[i].emulate(dev, pc, &buf[length]); | ||
| 964 | goto set_length; | ||
| 965 | } | ||
| 966 | |||
| 967 | /* | ||
| 968 | * We don't intend to implement: | ||
| 969 | * - obsolete page 03h "format parameters" (checked by Solaris) | ||
| 970 | */ | ||
| 971 | if (page != 0x03) | ||
| 972 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", | ||
| 973 | page, subpage); | ||
| 974 | |||
| 975 | transport_kunmap_data_sg(cmd); | ||
| 976 | return TCM_UNKNOWN_MODE_PAGE; | ||
| 977 | |||
| 978 | set_length: | ||
| 979 | if (ten) | ||
| 980 | put_unaligned_be16(length - 2, buf); | ||
| 981 | else | ||
| 982 | buf[0] = length - 1; | ||
| 983 | |||
| 984 | if (buf != map_buf) { | ||
| 985 | memcpy(map_buf, buf, cmd->data_length); | ||
| 986 | kfree(buf); | ||
| 851 | } | 987 | } |
| 852 | 988 | ||
| 989 | transport_kunmap_data_sg(cmd); | ||
| 853 | target_complete_cmd(cmd, GOOD); | 990 | target_complete_cmd(cmd, GOOD); |
| 854 | return 0; | 991 | return 0; |
| 855 | } | 992 | } |
| 856 | 993 | ||
| 857 | static int spc_emulate_request_sense(struct se_cmd *cmd) | 994 | static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd) |
| 995 | { | ||
| 996 | struct se_device *dev = cmd->se_dev; | ||
| 997 | char *cdb = cmd->t_task_cdb; | ||
| 998 | bool ten = cdb[0] == MODE_SELECT_10; | ||
| 999 | int off = ten ? 8 : 4; | ||
| 1000 | bool pf = !!(cdb[1] & 0x10); | ||
| 1001 | u8 page, subpage; | ||
| 1002 | unsigned char *buf; | ||
| 1003 | unsigned char tbuf[SE_MODE_PAGE_BUF]; | ||
| 1004 | int length; | ||
| 1005 | int ret = 0; | ||
| 1006 | int i; | ||
| 1007 | |||
| 1008 | buf = transport_kmap_data_sg(cmd); | ||
| 1009 | if (!buf) | ||
| 1010 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1011 | |||
| 1012 | if (!pf) { | ||
| 1013 | ret = TCM_INVALID_CDB_FIELD; | ||
| 1014 | goto out; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | page = buf[off] & 0x3f; | ||
| 1018 | subpage = buf[off] & 0x40 ? buf[off + 1] : 0; | ||
| 1019 | |||
| 1020 | for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) | ||
| 1021 | if (modesense_handlers[i].page == page && | ||
| 1022 | modesense_handlers[i].subpage == subpage) { | ||
| 1023 | memset(tbuf, 0, SE_MODE_PAGE_BUF); | ||
| 1024 | length = modesense_handlers[i].emulate(dev, 0, tbuf); | ||
| 1025 | goto check_contents; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | ret = TCM_UNKNOWN_MODE_PAGE; | ||
| 1029 | goto out; | ||
| 1030 | |||
| 1031 | check_contents: | ||
| 1032 | if (memcmp(buf + off, tbuf, length)) | ||
| 1033 | ret = TCM_INVALID_PARAMETER_LIST; | ||
| 1034 | |||
| 1035 | out: | ||
| 1036 | transport_kunmap_data_sg(cmd); | ||
| 1037 | |||
| 1038 | if (!ret) | ||
| 1039 | target_complete_cmd(cmd, GOOD); | ||
| 1040 | return ret; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) | ||
| 858 | { | 1044 | { |
| 859 | unsigned char *cdb = cmd->t_task_cdb; | 1045 | unsigned char *cdb = cmd->t_task_cdb; |
| 860 | unsigned char *rbuf; | 1046 | unsigned char *rbuf; |
| @@ -866,19 +1052,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) | |||
| 866 | if (cdb[1] & 0x01) { | 1052 | if (cdb[1] & 0x01) { |
| 867 | pr_err("REQUEST_SENSE description emulation not" | 1053 | pr_err("REQUEST_SENSE description emulation not" |
| 868 | " supported\n"); | 1054 | " supported\n"); |
| 869 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 1055 | return TCM_INVALID_CDB_FIELD; |
| 870 | return -ENOSYS; | ||
| 871 | } | 1056 | } |
| 872 | 1057 | ||
| 873 | rbuf = transport_kmap_data_sg(cmd); | 1058 | rbuf = transport_kmap_data_sg(cmd); |
| 874 | if (cmd->scsi_sense_reason != 0) { | 1059 | if (!rbuf) |
| 875 | /* | 1060 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 876 | * Out of memory. We will fail with CHECK CONDITION, so | 1061 | |
| 877 | * we must not clear the unit attention condition. | 1062 | if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { |
| 878 | */ | ||
| 879 | target_complete_cmd(cmd, CHECK_CONDITION); | ||
| 880 | return 0; | ||
| 881 | } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { | ||
| 882 | /* | 1063 | /* |
| 883 | * CURRENT ERROR, UNIT ATTENTION | 1064 | * CURRENT ERROR, UNIT ATTENTION |
| 884 | */ | 1065 | */ |
| @@ -905,33 +1086,97 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) | |||
| 905 | buf[7] = 0x0A; | 1086 | buf[7] = 0x0A; |
| 906 | } | 1087 | } |
| 907 | 1088 | ||
| 908 | if (rbuf) { | 1089 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
| 909 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 1090 | transport_kunmap_data_sg(cmd); |
| 910 | transport_kunmap_data_sg(cmd); | 1091 | |
| 1092 | target_complete_cmd(cmd, GOOD); | ||
| 1093 | return 0; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) | ||
| 1097 | { | ||
| 1098 | struct se_dev_entry *deve; | ||
| 1099 | struct se_session *sess = cmd->se_sess; | ||
| 1100 | unsigned char *buf; | ||
| 1101 | u32 lun_count = 0, offset = 8, i; | ||
| 1102 | |||
| 1103 | if (cmd->data_length < 16) { | ||
| 1104 | pr_warn("REPORT LUNS allocation length %u too small\n", | ||
| 1105 | cmd->data_length); | ||
| 1106 | return TCM_INVALID_CDB_FIELD; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | buf = transport_kmap_data_sg(cmd); | ||
| 1110 | if (!buf) | ||
| 1111 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1112 | |||
| 1113 | /* | ||
| 1114 | * If no struct se_session pointer is present, this struct se_cmd is | ||
| 1115 | * coming via a target_core_mod PASSTHROUGH op, and not through | ||
| 1116 | * a $FABRIC_MOD. In that case, report LUN=0 only. | ||
| 1117 | */ | ||
| 1118 | if (!sess) { | ||
| 1119 | int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); | ||
| 1120 | lun_count = 1; | ||
| 1121 | goto done; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | spin_lock_irq(&sess->se_node_acl->device_list_lock); | ||
| 1125 | for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { | ||
| 1126 | deve = sess->se_node_acl->device_list[i]; | ||
| 1127 | if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) | ||
| 1128 | continue; | ||
| 1129 | /* | ||
| 1130 | * We determine the correct LUN LIST LENGTH even once we | ||
| 1131 | * have reached the initial allocation length. | ||
| 1132 | * See SPC2-R20 7.19. | ||
| 1133 | */ | ||
| 1134 | lun_count++; | ||
| 1135 | if ((offset + 8) > cmd->data_length) | ||
| 1136 | continue; | ||
| 1137 | |||
| 1138 | int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); | ||
| 1139 | offset += 8; | ||
| 911 | } | 1140 | } |
| 1141 | spin_unlock_irq(&sess->se_node_acl->device_list_lock); | ||
| 1142 | |||
| 1143 | /* | ||
| 1144 | * See SPC3 r07, page 159. | ||
| 1145 | */ | ||
| 1146 | done: | ||
| 1147 | lun_count *= 8; | ||
| 1148 | buf[0] = ((lun_count >> 24) & 0xff); | ||
| 1149 | buf[1] = ((lun_count >> 16) & 0xff); | ||
| 1150 | buf[2] = ((lun_count >> 8) & 0xff); | ||
| 1151 | buf[3] = (lun_count & 0xff); | ||
| 1152 | transport_kunmap_data_sg(cmd); | ||
| 912 | 1153 | ||
| 913 | target_complete_cmd(cmd, GOOD); | 1154 | target_complete_cmd(cmd, GOOD); |
| 914 | return 0; | 1155 | return 0; |
| 915 | } | 1156 | } |
| 1157 | EXPORT_SYMBOL(spc_emulate_report_luns); | ||
| 916 | 1158 | ||
| 917 | static int spc_emulate_testunitready(struct se_cmd *cmd) | 1159 | static sense_reason_t |
| 1160 | spc_emulate_testunitready(struct se_cmd *cmd) | ||
| 918 | { | 1161 | { |
| 919 | target_complete_cmd(cmd, GOOD); | 1162 | target_complete_cmd(cmd, GOOD); |
| 920 | return 0; | 1163 | return 0; |
| 921 | } | 1164 | } |
| 922 | 1165 | ||
| 923 | int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | 1166 | sense_reason_t |
| 1167 | spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | ||
| 924 | { | 1168 | { |
| 925 | struct se_device *dev = cmd->se_dev; | 1169 | struct se_device *dev = cmd->se_dev; |
| 926 | struct se_subsystem_dev *su_dev = dev->se_sub_dev; | ||
| 927 | unsigned char *cdb = cmd->t_task_cdb; | 1170 | unsigned char *cdb = cmd->t_task_cdb; |
| 928 | 1171 | ||
| 929 | switch (cdb[0]) { | 1172 | switch (cdb[0]) { |
| 930 | case MODE_SELECT: | 1173 | case MODE_SELECT: |
| 931 | *size = cdb[4]; | 1174 | *size = cdb[4]; |
| 1175 | cmd->execute_cmd = spc_emulate_modeselect; | ||
| 932 | break; | 1176 | break; |
| 933 | case MODE_SELECT_10: | 1177 | case MODE_SELECT_10: |
| 934 | *size = (cdb[7] << 8) + cdb[8]; | 1178 | *size = (cdb[7] << 8) + cdb[8]; |
| 1179 | cmd->execute_cmd = spc_emulate_modeselect; | ||
| 935 | break; | 1180 | break; |
| 936 | case MODE_SENSE: | 1181 | case MODE_SENSE: |
| 937 | *size = cdb[4]; | 1182 | *size = cdb[4]; |
| @@ -946,14 +1191,12 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 946 | *size = (cdb[7] << 8) + cdb[8]; | 1191 | *size = (cdb[7] << 8) + cdb[8]; |
| 947 | break; | 1192 | break; |
| 948 | case PERSISTENT_RESERVE_IN: | 1193 | case PERSISTENT_RESERVE_IN: |
| 949 | if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) | ||
| 950 | cmd->execute_cmd = target_scsi3_emulate_pr_in; | ||
| 951 | *size = (cdb[7] << 8) + cdb[8]; | 1194 | *size = (cdb[7] << 8) + cdb[8]; |
| 1195 | cmd->execute_cmd = target_scsi3_emulate_pr_in; | ||
| 952 | break; | 1196 | break; |
| 953 | case PERSISTENT_RESERVE_OUT: | 1197 | case PERSISTENT_RESERVE_OUT: |
| 954 | if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) | ||
| 955 | cmd->execute_cmd = target_scsi3_emulate_pr_out; | ||
| 956 | *size = (cdb[7] << 8) + cdb[8]; | 1198 | *size = (cdb[7] << 8) + cdb[8]; |
| 1199 | cmd->execute_cmd = target_scsi3_emulate_pr_out; | ||
| 957 | break; | 1200 | break; |
| 958 | case RELEASE: | 1201 | case RELEASE: |
| 959 | case RELEASE_10: | 1202 | case RELEASE_10: |
| @@ -962,8 +1205,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 962 | else | 1205 | else |
| 963 | *size = cmd->data_length; | 1206 | *size = cmd->data_length; |
| 964 | 1207 | ||
| 965 | if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) | 1208 | cmd->execute_cmd = target_scsi2_reservation_release; |
| 966 | cmd->execute_cmd = target_scsi2_reservation_release; | ||
| 967 | break; | 1209 | break; |
| 968 | case RESERVE: | 1210 | case RESERVE: |
| 969 | case RESERVE_10: | 1211 | case RESERVE_10: |
| @@ -976,15 +1218,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 976 | else | 1218 | else |
| 977 | *size = cmd->data_length; | 1219 | *size = cmd->data_length; |
| 978 | 1220 | ||
| 979 | /* | 1221 | cmd->execute_cmd = target_scsi2_reservation_reserve; |
| 980 | * Setup the legacy emulated handler for SPC-2 and | ||
| 981 | * >= SPC-3 compatible reservation handling (CRH=1) | ||
| 982 | * Otherwise, we assume the underlying SCSI logic is | ||
| 983 | * is running in SPC_PASSTHROUGH, and wants reservations | ||
| 984 | * emulation disabled. | ||
| 985 | */ | ||
| 986 | if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) | ||
| 987 | cmd->execute_cmd = target_scsi2_reservation_reserve; | ||
| 988 | break; | 1222 | break; |
| 989 | case REQUEST_SENSE: | 1223 | case REQUEST_SENSE: |
| 990 | *size = cdb[4]; | 1224 | *size = cdb[4]; |
| @@ -997,8 +1231,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 997 | * Do implict HEAD_OF_QUEUE processing for INQUIRY. | 1231 | * Do implict HEAD_OF_QUEUE processing for INQUIRY. |
| 998 | * See spc4r17 section 5.3 | 1232 | * See spc4r17 section 5.3 |
| 999 | */ | 1233 | */ |
| 1000 | if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 1234 | cmd->sam_task_attr = MSG_HEAD_TAG; |
| 1001 | cmd->sam_task_attr = MSG_HEAD_TAG; | ||
| 1002 | cmd->execute_cmd = spc_emulate_inquiry; | 1235 | cmd->execute_cmd = spc_emulate_inquiry; |
| 1003 | break; | 1236 | break; |
| 1004 | case SECURITY_PROTOCOL_IN: | 1237 | case SECURITY_PROTOCOL_IN: |
| @@ -1020,14 +1253,13 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 1020 | *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; | 1253 | *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; |
| 1021 | break; | 1254 | break; |
| 1022 | case REPORT_LUNS: | 1255 | case REPORT_LUNS: |
| 1023 | cmd->execute_cmd = target_report_luns; | 1256 | cmd->execute_cmd = spc_emulate_report_luns; |
| 1024 | *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; | 1257 | *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; |
| 1025 | /* | 1258 | /* |
| 1026 | * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS | 1259 | * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS |
| 1027 | * See spc4r17 section 5.3 | 1260 | * See spc4r17 section 5.3 |
| 1028 | */ | 1261 | */ |
| 1029 | if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 1262 | cmd->sam_task_attr = MSG_HEAD_TAG; |
| 1030 | cmd->sam_task_attr = MSG_HEAD_TAG; | ||
| 1031 | break; | 1263 | break; |
| 1032 | case TEST_UNIT_READY: | 1264 | case TEST_UNIT_READY: |
| 1033 | cmd->execute_cmd = spc_emulate_testunitready; | 1265 | cmd->execute_cmd = spc_emulate_testunitready; |
| @@ -1039,8 +1271,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 1039 | * MAINTENANCE_IN from SCC-2 | 1271 | * MAINTENANCE_IN from SCC-2 |
| 1040 | * Check for emulated MI_REPORT_TARGET_PGS | 1272 | * Check for emulated MI_REPORT_TARGET_PGS |
| 1041 | */ | 1273 | */ |
| 1042 | if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS && | 1274 | if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS) { |
| 1043 | su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { | ||
| 1044 | cmd->execute_cmd = | 1275 | cmd->execute_cmd = |
| 1045 | target_emulate_report_target_port_groups; | 1276 | target_emulate_report_target_port_groups; |
| 1046 | } | 1277 | } |
| @@ -1058,8 +1289,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 1058 | * MAINTENANCE_OUT from SCC-2 | 1289 | * MAINTENANCE_OUT from SCC-2 |
| 1059 | * Check for emulated MO_SET_TARGET_PGS. | 1290 | * Check for emulated MO_SET_TARGET_PGS. |
| 1060 | */ | 1291 | */ |
| 1061 | if (cdb[1] == MO_SET_TARGET_PGS && | 1292 | if (cdb[1] == MO_SET_TARGET_PGS) { |
| 1062 | su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { | ||
| 1063 | cmd->execute_cmd = | 1293 | cmd->execute_cmd = |
| 1064 | target_emulate_set_target_port_groups; | 1294 | target_emulate_set_target_port_groups; |
| 1065 | } | 1295 | } |
| @@ -1075,9 +1305,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) | |||
| 1075 | pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" | 1305 | pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" |
| 1076 | " 0x%02x, sending CHECK_CONDITION.\n", | 1306 | " 0x%02x, sending CHECK_CONDITION.\n", |
| 1077 | cmd->se_tfo->get_fabric_name(), cdb[0]); | 1307 | cmd->se_tfo->get_fabric_name(), cdb[0]); |
| 1078 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 1308 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
| 1079 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | ||
| 1080 | return -EINVAL; | ||
| 1081 | } | 1309 | } |
| 1082 | 1310 | ||
| 1083 | return 0; | 1311 | return 0; |
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c index cb6b0036ae95..d154ce797180 100644 --- a/drivers/target/target_core_stat.c +++ b/drivers/target/target_core_stat.c | |||
| @@ -1,13 +1,10 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * Filename: target_core_stat.c | 2 | * Filename: target_core_stat.c |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2011 Rising Tide Systems | ||
| 5 | * Copyright (c) 2011 Linux-iSCSI.org | ||
| 6 | * | ||
| 7 | * Modern ConfigFS group context specific statistics based on original | 4 | * Modern ConfigFS group context specific statistics based on original |
| 8 | * target_core_mib.c code | 5 | * target_core_mib.c code |
| 9 | * | 6 | * |
| 10 | * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved. | 7 | * (c) Copyright 2006-2012 RisingTide Systems LLC. |
| 11 | * | 8 | * |
| 12 | * Nicholas A. Bellinger <nab@linux-iscsi.org> | 9 | * Nicholas A. Bellinger <nab@linux-iscsi.org> |
| 13 | * | 10 | * |
| @@ -80,13 +77,9 @@ static struct target_stat_scsi_dev_attribute \ | |||
| 80 | static ssize_t target_stat_scsi_dev_show_attr_inst( | 77 | static ssize_t target_stat_scsi_dev_show_attr_inst( |
| 81 | struct se_dev_stat_grps *sgrps, char *page) | 78 | struct se_dev_stat_grps *sgrps, char *page) |
| 82 | { | 79 | { |
| 83 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 80 | struct se_device *dev = |
| 84 | struct se_subsystem_dev, dev_stat_grps); | 81 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 85 | struct se_hba *hba = se_subdev->se_dev_hba; | 82 | struct se_hba *hba = dev->se_hba; |
| 86 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 87 | |||
| 88 | if (!dev) | ||
| 89 | return -ENODEV; | ||
| 90 | 83 | ||
| 91 | return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); | 84 | return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); |
| 92 | } | 85 | } |
| @@ -95,12 +88,8 @@ DEV_STAT_SCSI_DEV_ATTR_RO(inst); | |||
| 95 | static ssize_t target_stat_scsi_dev_show_attr_indx( | 88 | static ssize_t target_stat_scsi_dev_show_attr_indx( |
| 96 | struct se_dev_stat_grps *sgrps, char *page) | 89 | struct se_dev_stat_grps *sgrps, char *page) |
| 97 | { | 90 | { |
| 98 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 91 | struct se_device *dev = |
| 99 | struct se_subsystem_dev, dev_stat_grps); | 92 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 100 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 101 | |||
| 102 | if (!dev) | ||
| 103 | return -ENODEV; | ||
| 104 | 93 | ||
| 105 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); | 94 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); |
| 106 | } | 95 | } |
| @@ -109,13 +98,6 @@ DEV_STAT_SCSI_DEV_ATTR_RO(indx); | |||
| 109 | static ssize_t target_stat_scsi_dev_show_attr_role( | 98 | static ssize_t target_stat_scsi_dev_show_attr_role( |
| 110 | struct se_dev_stat_grps *sgrps, char *page) | 99 | struct se_dev_stat_grps *sgrps, char *page) |
| 111 | { | 100 | { |
| 112 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | ||
| 113 | struct se_subsystem_dev, dev_stat_grps); | ||
| 114 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 115 | |||
| 116 | if (!dev) | ||
| 117 | return -ENODEV; | ||
| 118 | |||
| 119 | return snprintf(page, PAGE_SIZE, "Target\n"); | 101 | return snprintf(page, PAGE_SIZE, "Target\n"); |
| 120 | } | 102 | } |
| 121 | DEV_STAT_SCSI_DEV_ATTR_RO(role); | 103 | DEV_STAT_SCSI_DEV_ATTR_RO(role); |
| @@ -123,12 +105,8 @@ DEV_STAT_SCSI_DEV_ATTR_RO(role); | |||
| 123 | static ssize_t target_stat_scsi_dev_show_attr_ports( | 105 | static ssize_t target_stat_scsi_dev_show_attr_ports( |
| 124 | struct se_dev_stat_grps *sgrps, char *page) | 106 | struct se_dev_stat_grps *sgrps, char *page) |
| 125 | { | 107 | { |
| 126 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 108 | struct se_device *dev = |
| 127 | struct se_subsystem_dev, dev_stat_grps); | 109 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 128 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 129 | |||
| 130 | if (!dev) | ||
| 131 | return -ENODEV; | ||
| 132 | 110 | ||
| 133 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_port_count); | 111 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_port_count); |
| 134 | } | 112 | } |
| @@ -176,13 +154,9 @@ static struct target_stat_scsi_tgt_dev_attribute \ | |||
| 176 | static ssize_t target_stat_scsi_tgt_dev_show_attr_inst( | 154 | static ssize_t target_stat_scsi_tgt_dev_show_attr_inst( |
| 177 | struct se_dev_stat_grps *sgrps, char *page) | 155 | struct se_dev_stat_grps *sgrps, char *page) |
| 178 | { | 156 | { |
| 179 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 157 | struct se_device *dev = |
| 180 | struct se_subsystem_dev, dev_stat_grps); | 158 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 181 | struct se_hba *hba = se_subdev->se_dev_hba; | 159 | struct se_hba *hba = dev->se_hba; |
| 182 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 183 | |||
| 184 | if (!dev) | ||
| 185 | return -ENODEV; | ||
| 186 | 160 | ||
| 187 | return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); | 161 | return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); |
| 188 | } | 162 | } |
| @@ -191,12 +165,8 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(inst); | |||
| 191 | static ssize_t target_stat_scsi_tgt_dev_show_attr_indx( | 165 | static ssize_t target_stat_scsi_tgt_dev_show_attr_indx( |
| 192 | struct se_dev_stat_grps *sgrps, char *page) | 166 | struct se_dev_stat_grps *sgrps, char *page) |
| 193 | { | 167 | { |
| 194 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 168 | struct se_device *dev = |
| 195 | struct se_subsystem_dev, dev_stat_grps); | 169 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 196 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 197 | |||
| 198 | if (!dev) | ||
| 199 | return -ENODEV; | ||
| 200 | 170 | ||
| 201 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); | 171 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); |
| 202 | } | 172 | } |
| @@ -205,13 +175,6 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(indx); | |||
| 205 | static ssize_t target_stat_scsi_tgt_dev_show_attr_num_lus( | 175 | static ssize_t target_stat_scsi_tgt_dev_show_attr_num_lus( |
| 206 | struct se_dev_stat_grps *sgrps, char *page) | 176 | struct se_dev_stat_grps *sgrps, char *page) |
| 207 | { | 177 | { |
| 208 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | ||
| 209 | struct se_subsystem_dev, dev_stat_grps); | ||
| 210 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 211 | |||
| 212 | if (!dev) | ||
| 213 | return -ENODEV; | ||
| 214 | |||
| 215 | return snprintf(page, PAGE_SIZE, "%u\n", LU_COUNT); | 178 | return snprintf(page, PAGE_SIZE, "%u\n", LU_COUNT); |
| 216 | } | 179 | } |
| 217 | DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus); | 180 | DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus); |
| @@ -219,60 +182,27 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus); | |||
| 219 | static ssize_t target_stat_scsi_tgt_dev_show_attr_status( | 182 | static ssize_t target_stat_scsi_tgt_dev_show_attr_status( |
| 220 | struct se_dev_stat_grps *sgrps, char *page) | 183 | struct se_dev_stat_grps *sgrps, char *page) |
| 221 | { | 184 | { |
| 222 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 185 | struct se_device *dev = |
| 223 | struct se_subsystem_dev, dev_stat_grps); | 186 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 224 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 225 | char status[16]; | ||
| 226 | 187 | ||
| 227 | if (!dev) | 188 | if (dev->export_count) |
| 228 | return -ENODEV; | 189 | return snprintf(page, PAGE_SIZE, "activated"); |
| 229 | 190 | else | |
| 230 | switch (dev->dev_status) { | 191 | return snprintf(page, PAGE_SIZE, "deactivated"); |
| 231 | case TRANSPORT_DEVICE_ACTIVATED: | ||
| 232 | strcpy(status, "activated"); | ||
| 233 | break; | ||
| 234 | case TRANSPORT_DEVICE_DEACTIVATED: | ||
| 235 | strcpy(status, "deactivated"); | ||
| 236 | break; | ||
| 237 | case TRANSPORT_DEVICE_SHUTDOWN: | ||
| 238 | strcpy(status, "shutdown"); | ||
| 239 | break; | ||
| 240 | case TRANSPORT_DEVICE_OFFLINE_ACTIVATED: | ||
| 241 | case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED: | ||
| 242 | strcpy(status, "offline"); | ||
| 243 | break; | ||
| 244 | default: | ||
| 245 | sprintf(status, "unknown(%d)", dev->dev_status); | ||
| 246 | break; | ||
| 247 | } | ||
| 248 | |||
| 249 | return snprintf(page, PAGE_SIZE, "%s\n", status); | ||
| 250 | } | 192 | } |
| 251 | DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status); | 193 | DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status); |
| 252 | 194 | ||
| 253 | static ssize_t target_stat_scsi_tgt_dev_show_attr_non_access_lus( | 195 | static ssize_t target_stat_scsi_tgt_dev_show_attr_non_access_lus( |
| 254 | struct se_dev_stat_grps *sgrps, char *page) | 196 | struct se_dev_stat_grps *sgrps, char *page) |
| 255 | { | 197 | { |
| 256 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 198 | struct se_device *dev = |
| 257 | struct se_subsystem_dev, dev_stat_grps); | 199 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 258 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 259 | int non_accessible_lus; | 200 | int non_accessible_lus; |
| 260 | 201 | ||
| 261 | if (!dev) | 202 | if (dev->export_count) |
| 262 | return -ENODEV; | ||
| 263 | |||
| 264 | switch (dev->dev_status) { | ||
| 265 | case TRANSPORT_DEVICE_ACTIVATED: | ||
| 266 | non_accessible_lus = 0; | 203 | non_accessible_lus = 0; |
| 267 | break; | 204 | else |
| 268 | case TRANSPORT_DEVICE_DEACTIVATED: | ||
| 269 | case TRANSPORT_DEVICE_SHUTDOWN: | ||
| 270 | case TRANSPORT_DEVICE_OFFLINE_ACTIVATED: | ||
| 271 | case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED: | ||
| 272 | default: | ||
| 273 | non_accessible_lus = 1; | 205 | non_accessible_lus = 1; |
| 274 | break; | ||
| 275 | } | ||
| 276 | 206 | ||
| 277 | return snprintf(page, PAGE_SIZE, "%u\n", non_accessible_lus); | 207 | return snprintf(page, PAGE_SIZE, "%u\n", non_accessible_lus); |
| 278 | } | 208 | } |
| @@ -281,12 +211,8 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(non_access_lus); | |||
| 281 | static ssize_t target_stat_scsi_tgt_dev_show_attr_resets( | 211 | static ssize_t target_stat_scsi_tgt_dev_show_attr_resets( |
| 282 | struct se_dev_stat_grps *sgrps, char *page) | 212 | struct se_dev_stat_grps *sgrps, char *page) |
| 283 | { | 213 | { |
| 284 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 214 | struct se_device *dev = |
| 285 | struct se_subsystem_dev, dev_stat_grps); | 215 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 286 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 287 | |||
| 288 | if (!dev) | ||
| 289 | return -ENODEV; | ||
| 290 | 216 | ||
| 291 | return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets); | 217 | return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets); |
| 292 | } | 218 | } |
| @@ -335,13 +261,9 @@ static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \ | |||
| 335 | static ssize_t target_stat_scsi_lu_show_attr_inst( | 261 | static ssize_t target_stat_scsi_lu_show_attr_inst( |
| 336 | struct se_dev_stat_grps *sgrps, char *page) | 262 | struct se_dev_stat_grps *sgrps, char *page) |
| 337 | { | 263 | { |
| 338 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 264 | struct se_device *dev = |
| 339 | struct se_subsystem_dev, dev_stat_grps); | 265 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 340 | struct se_hba *hba = se_subdev->se_dev_hba; | 266 | struct se_hba *hba = dev->se_hba; |
| 341 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 342 | |||
| 343 | if (!dev) | ||
| 344 | return -ENODEV; | ||
| 345 | 267 | ||
| 346 | return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); | 268 | return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); |
| 347 | } | 269 | } |
| @@ -350,12 +272,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(inst); | |||
| 350 | static ssize_t target_stat_scsi_lu_show_attr_dev( | 272 | static ssize_t target_stat_scsi_lu_show_attr_dev( |
| 351 | struct se_dev_stat_grps *sgrps, char *page) | 273 | struct se_dev_stat_grps *sgrps, char *page) |
| 352 | { | 274 | { |
| 353 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 275 | struct se_device *dev = |
| 354 | struct se_subsystem_dev, dev_stat_grps); | 276 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 355 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 356 | |||
| 357 | if (!dev) | ||
| 358 | return -ENODEV; | ||
| 359 | 277 | ||
| 360 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); | 278 | return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); |
| 361 | } | 279 | } |
| @@ -364,13 +282,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(dev); | |||
| 364 | static ssize_t target_stat_scsi_lu_show_attr_indx( | 282 | static ssize_t target_stat_scsi_lu_show_attr_indx( |
| 365 | struct se_dev_stat_grps *sgrps, char *page) | 283 | struct se_dev_stat_grps *sgrps, char *page) |
| 366 | { | 284 | { |
| 367 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | ||
| 368 | struct se_subsystem_dev, dev_stat_grps); | ||
| 369 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 370 | |||
| 371 | if (!dev) | ||
| 372 | return -ENODEV; | ||
| 373 | |||
| 374 | return snprintf(page, PAGE_SIZE, "%u\n", SCSI_LU_INDEX); | 285 | return snprintf(page, PAGE_SIZE, "%u\n", SCSI_LU_INDEX); |
| 375 | } | 286 | } |
| 376 | DEV_STAT_SCSI_LU_ATTR_RO(indx); | 287 | DEV_STAT_SCSI_LU_ATTR_RO(indx); |
| @@ -378,12 +289,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(indx); | |||
| 378 | static ssize_t target_stat_scsi_lu_show_attr_lun( | 289 | static ssize_t target_stat_scsi_lu_show_attr_lun( |
| 379 | struct se_dev_stat_grps *sgrps, char *page) | 290 | struct se_dev_stat_grps *sgrps, char *page) |
| 380 | { | 291 | { |
| 381 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | ||
| 382 | struct se_subsystem_dev, dev_stat_grps); | ||
| 383 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 384 | |||
| 385 | if (!dev) | ||
| 386 | return -ENODEV; | ||
| 387 | /* FIXME: scsiLuDefaultLun */ | 292 | /* FIXME: scsiLuDefaultLun */ |
| 388 | return snprintf(page, PAGE_SIZE, "%llu\n", (unsigned long long)0); | 293 | return snprintf(page, PAGE_SIZE, "%llu\n", (unsigned long long)0); |
| 389 | } | 294 | } |
| @@ -392,35 +297,28 @@ DEV_STAT_SCSI_LU_ATTR_RO(lun); | |||
| 392 | static ssize_t target_stat_scsi_lu_show_attr_lu_name( | 297 | static ssize_t target_stat_scsi_lu_show_attr_lu_name( |
| 393 | struct se_dev_stat_grps *sgrps, char *page) | 298 | struct se_dev_stat_grps *sgrps, char *page) |
| 394 | { | 299 | { |
| 395 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 300 | struct se_device *dev = |
| 396 | struct se_subsystem_dev, dev_stat_grps); | 301 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 397 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 398 | 302 | ||
| 399 | if (!dev) | ||
| 400 | return -ENODEV; | ||
| 401 | /* scsiLuWwnName */ | 303 | /* scsiLuWwnName */ |
| 402 | return snprintf(page, PAGE_SIZE, "%s\n", | 304 | return snprintf(page, PAGE_SIZE, "%s\n", |
| 403 | (strlen(dev->se_sub_dev->t10_wwn.unit_serial)) ? | 305 | (strlen(dev->t10_wwn.unit_serial)) ? |
| 404 | dev->se_sub_dev->t10_wwn.unit_serial : "None"); | 306 | dev->t10_wwn.unit_serial : "None"); |
| 405 | } | 307 | } |
| 406 | DEV_STAT_SCSI_LU_ATTR_RO(lu_name); | 308 | DEV_STAT_SCSI_LU_ATTR_RO(lu_name); |
| 407 | 309 | ||
| 408 | static ssize_t target_stat_scsi_lu_show_attr_vend( | 310 | static ssize_t target_stat_scsi_lu_show_attr_vend( |
| 409 | struct se_dev_stat_grps *sgrps, char *page) | 311 | struct se_dev_stat_grps *sgrps, char *page) |
| 410 | { | 312 | { |
| 411 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 313 | struct se_device *dev = |
| 412 | struct se_subsystem_dev, dev_stat_grps); | 314 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 413 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 414 | int i; | 315 | int i; |
| 415 | char str[sizeof(dev->se_sub_dev->t10_wwn.vendor)+1]; | 316 | char str[sizeof(dev->t10_wwn.vendor)+1]; |
| 416 | |||
| 417 | if (!dev) | ||
| 418 | return -ENODEV; | ||
| 419 | 317 | ||
| 420 | /* scsiLuVendorId */ | 318 | /* scsiLuVendorId */ |
| 421 | for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++) | 319 | for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++) |
| 422 | str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.vendor[i]) ? | 320 | str[i] = ISPRINT(dev->t10_wwn.vendor[i]) ? |
| 423 | dev->se_sub_dev->t10_wwn.vendor[i] : ' '; | 321 | dev->t10_wwn.vendor[i] : ' '; |
| 424 | str[i] = '\0'; | 322 | str[i] = '\0'; |
| 425 | return snprintf(page, PAGE_SIZE, "%s\n", str); | 323 | return snprintf(page, PAGE_SIZE, "%s\n", str); |
| 426 | } | 324 | } |
| @@ -429,19 +327,15 @@ DEV_STAT_SCSI_LU_ATTR_RO(vend); | |||
| 429 | static ssize_t target_stat_scsi_lu_show_attr_prod( | 327 | static ssize_t target_stat_scsi_lu_show_attr_prod( |
| 430 | struct se_dev_stat_grps *sgrps, char *page) | 328 | struct se_dev_stat_grps *sgrps, char *page) |
| 431 | { | 329 | { |
| 432 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 330 | struct se_device *dev = |
| 433 | struct se_subsystem_dev, dev_stat_grps); | 331 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 434 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 435 | int i; | 332 | int i; |
| 436 | char str[sizeof(dev->se_sub_dev->t10_wwn.model)+1]; | 333 | char str[sizeof(dev->t10_wwn.model)+1]; |
| 437 | |||
| 438 | if (!dev) | ||
| 439 | return -ENODEV; | ||
| 440 | 334 | ||
| 441 | /* scsiLuProductId */ | 335 | /* scsiLuProductId */ |
| 442 | for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++) | 336 | for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++) |
| 443 | str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.model[i]) ? | 337 | str[i] = ISPRINT(dev->t10_wwn.model[i]) ? |
| 444 | dev->se_sub_dev->t10_wwn.model[i] : ' '; | 338 | dev->t10_wwn.model[i] : ' '; |
| 445 | str[i] = '\0'; | 339 | str[i] = '\0'; |
| 446 | return snprintf(page, PAGE_SIZE, "%s\n", str); | 340 | return snprintf(page, PAGE_SIZE, "%s\n", str); |
| 447 | } | 341 | } |
| @@ -450,19 +344,15 @@ DEV_STAT_SCSI_LU_ATTR_RO(prod); | |||
| 450 | static ssize_t target_stat_scsi_lu_show_attr_rev( | 344 | static ssize_t target_stat_scsi_lu_show_attr_rev( |
| 451 | struct se_dev_stat_grps *sgrps, char *page) | 345 | struct se_dev_stat_grps *sgrps, char *page) |
| 452 | { | 346 | { |
| 453 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 347 | struct se_device *dev = |
| 454 | struct se_subsystem_dev, dev_stat_grps); | 348 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 455 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 456 | int i; | 349 | int i; |
| 457 | char str[sizeof(dev->se_sub_dev->t10_wwn.revision)+1]; | 350 | char str[sizeof(dev->t10_wwn.revision)+1]; |
| 458 | |||
| 459 | if (!dev) | ||
| 460 | return -ENODEV; | ||
| 461 | 351 | ||
| 462 | /* scsiLuRevisionId */ | 352 | /* scsiLuRevisionId */ |
| 463 | for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.revision); i++) | 353 | for (i = 0; i < sizeof(dev->t10_wwn.revision); i++) |
| 464 | str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.revision[i]) ? | 354 | str[i] = ISPRINT(dev->t10_wwn.revision[i]) ? |
| 465 | dev->se_sub_dev->t10_wwn.revision[i] : ' '; | 355 | dev->t10_wwn.revision[i] : ' '; |
| 466 | str[i] = '\0'; | 356 | str[i] = '\0'; |
| 467 | return snprintf(page, PAGE_SIZE, "%s\n", str); | 357 | return snprintf(page, PAGE_SIZE, "%s\n", str); |
| 468 | } | 358 | } |
| @@ -471,12 +361,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(rev); | |||
| 471 | static ssize_t target_stat_scsi_lu_show_attr_dev_type( | 361 | static ssize_t target_stat_scsi_lu_show_attr_dev_type( |
| 472 | struct se_dev_stat_grps *sgrps, char *page) | 362 | struct se_dev_stat_grps *sgrps, char *page) |
| 473 | { | 363 | { |
| 474 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 364 | struct se_device *dev = |
| 475 | struct se_subsystem_dev, dev_stat_grps); | 365 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 476 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 477 | |||
| 478 | if (!dev) | ||
| 479 | return -ENODEV; | ||
| 480 | 366 | ||
| 481 | /* scsiLuPeripheralType */ | 367 | /* scsiLuPeripheralType */ |
| 482 | return snprintf(page, PAGE_SIZE, "%u\n", | 368 | return snprintf(page, PAGE_SIZE, "%u\n", |
| @@ -487,30 +373,18 @@ DEV_STAT_SCSI_LU_ATTR_RO(dev_type); | |||
| 487 | static ssize_t target_stat_scsi_lu_show_attr_status( | 373 | static ssize_t target_stat_scsi_lu_show_attr_status( |
| 488 | struct se_dev_stat_grps *sgrps, char *page) | 374 | struct se_dev_stat_grps *sgrps, char *page) |
| 489 | { | 375 | { |
| 490 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 376 | struct se_device *dev = |
| 491 | struct se_subsystem_dev, dev_stat_grps); | 377 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 492 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 493 | |||
| 494 | if (!dev) | ||
| 495 | return -ENODEV; | ||
| 496 | 378 | ||
| 497 | /* scsiLuStatus */ | 379 | /* scsiLuStatus */ |
| 498 | return snprintf(page, PAGE_SIZE, "%s\n", | 380 | return snprintf(page, PAGE_SIZE, "%s\n", |
| 499 | (dev->dev_status == TRANSPORT_DEVICE_ACTIVATED) ? | 381 | (dev->export_count) ? "available" : "notavailable"); |
| 500 | "available" : "notavailable"); | ||
| 501 | } | 382 | } |
| 502 | DEV_STAT_SCSI_LU_ATTR_RO(status); | 383 | DEV_STAT_SCSI_LU_ATTR_RO(status); |
| 503 | 384 | ||
| 504 | static ssize_t target_stat_scsi_lu_show_attr_state_bit( | 385 | static ssize_t target_stat_scsi_lu_show_attr_state_bit( |
| 505 | struct se_dev_stat_grps *sgrps, char *page) | 386 | struct se_dev_stat_grps *sgrps, char *page) |
| 506 | { | 387 | { |
| 507 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | ||
| 508 | struct se_subsystem_dev, dev_stat_grps); | ||
| 509 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 510 | |||
| 511 | if (!dev) | ||
| 512 | return -ENODEV; | ||
| 513 | |||
| 514 | /* scsiLuState */ | 388 | /* scsiLuState */ |
| 515 | return snprintf(page, PAGE_SIZE, "exposed\n"); | 389 | return snprintf(page, PAGE_SIZE, "exposed\n"); |
| 516 | } | 390 | } |
| @@ -519,12 +393,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(state_bit); | |||
| 519 | static ssize_t target_stat_scsi_lu_show_attr_num_cmds( | 393 | static ssize_t target_stat_scsi_lu_show_attr_num_cmds( |
| 520 | struct se_dev_stat_grps *sgrps, char *page) | 394 | struct se_dev_stat_grps *sgrps, char *page) |
| 521 | { | 395 | { |
| 522 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 396 | struct se_device *dev = |
| 523 | struct se_subsystem_dev, dev_stat_grps); | 397 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 524 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 525 | |||
| 526 | if (!dev) | ||
| 527 | return -ENODEV; | ||
| 528 | 398 | ||
| 529 | /* scsiLuNumCommands */ | 399 | /* scsiLuNumCommands */ |
| 530 | return snprintf(page, PAGE_SIZE, "%llu\n", | 400 | return snprintf(page, PAGE_SIZE, "%llu\n", |
| @@ -535,12 +405,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(num_cmds); | |||
| 535 | static ssize_t target_stat_scsi_lu_show_attr_read_mbytes( | 405 | static ssize_t target_stat_scsi_lu_show_attr_read_mbytes( |
| 536 | struct se_dev_stat_grps *sgrps, char *page) | 406 | struct se_dev_stat_grps *sgrps, char *page) |
| 537 | { | 407 | { |
| 538 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 408 | struct se_device *dev = |
| 539 | struct se_subsystem_dev, dev_stat_grps); | 409 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 540 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 541 | |||
| 542 | if (!dev) | ||
| 543 | return -ENODEV; | ||
| 544 | 410 | ||
| 545 | /* scsiLuReadMegaBytes */ | 411 | /* scsiLuReadMegaBytes */ |
| 546 | return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->read_bytes >> 20)); | 412 | return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->read_bytes >> 20)); |
| @@ -550,12 +416,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(read_mbytes); | |||
| 550 | static ssize_t target_stat_scsi_lu_show_attr_write_mbytes( | 416 | static ssize_t target_stat_scsi_lu_show_attr_write_mbytes( |
| 551 | struct se_dev_stat_grps *sgrps, char *page) | 417 | struct se_dev_stat_grps *sgrps, char *page) |
| 552 | { | 418 | { |
| 553 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 419 | struct se_device *dev = |
| 554 | struct se_subsystem_dev, dev_stat_grps); | 420 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 555 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 556 | |||
| 557 | if (!dev) | ||
| 558 | return -ENODEV; | ||
| 559 | 421 | ||
| 560 | /* scsiLuWrittenMegaBytes */ | 422 | /* scsiLuWrittenMegaBytes */ |
| 561 | return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->write_bytes >> 20)); | 423 | return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->write_bytes >> 20)); |
| @@ -565,12 +427,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(write_mbytes); | |||
| 565 | static ssize_t target_stat_scsi_lu_show_attr_resets( | 427 | static ssize_t target_stat_scsi_lu_show_attr_resets( |
| 566 | struct se_dev_stat_grps *sgrps, char *page) | 428 | struct se_dev_stat_grps *sgrps, char *page) |
| 567 | { | 429 | { |
| 568 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 430 | struct se_device *dev = |
| 569 | struct se_subsystem_dev, dev_stat_grps); | 431 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 570 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 571 | |||
| 572 | if (!dev) | ||
| 573 | return -ENODEV; | ||
| 574 | 432 | ||
| 575 | /* scsiLuInResets */ | 433 | /* scsiLuInResets */ |
| 576 | return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets); | 434 | return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets); |
| @@ -580,13 +438,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(resets); | |||
| 580 | static ssize_t target_stat_scsi_lu_show_attr_full_stat( | 438 | static ssize_t target_stat_scsi_lu_show_attr_full_stat( |
| 581 | struct se_dev_stat_grps *sgrps, char *page) | 439 | struct se_dev_stat_grps *sgrps, char *page) |
| 582 | { | 440 | { |
| 583 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | ||
| 584 | struct se_subsystem_dev, dev_stat_grps); | ||
| 585 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 586 | |||
| 587 | if (!dev) | ||
| 588 | return -ENODEV; | ||
| 589 | |||
| 590 | /* FIXME: scsiLuOutTaskSetFullStatus */ | 441 | /* FIXME: scsiLuOutTaskSetFullStatus */ |
| 591 | return snprintf(page, PAGE_SIZE, "%u\n", 0); | 442 | return snprintf(page, PAGE_SIZE, "%u\n", 0); |
| 592 | } | 443 | } |
| @@ -595,13 +446,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(full_stat); | |||
| 595 | static ssize_t target_stat_scsi_lu_show_attr_hs_num_cmds( | 446 | static ssize_t target_stat_scsi_lu_show_attr_hs_num_cmds( |
| 596 | struct se_dev_stat_grps *sgrps, char *page) | 447 | struct se_dev_stat_grps *sgrps, char *page) |
| 597 | { | 448 | { |
| 598 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | ||
| 599 | struct se_subsystem_dev, dev_stat_grps); | ||
| 600 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 601 | |||
| 602 | if (!dev) | ||
| 603 | return -ENODEV; | ||
| 604 | |||
| 605 | /* FIXME: scsiLuHSInCommands */ | 449 | /* FIXME: scsiLuHSInCommands */ |
| 606 | return snprintf(page, PAGE_SIZE, "%u\n", 0); | 450 | return snprintf(page, PAGE_SIZE, "%u\n", 0); |
| 607 | } | 451 | } |
| @@ -610,12 +454,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(hs_num_cmds); | |||
| 610 | static ssize_t target_stat_scsi_lu_show_attr_creation_time( | 454 | static ssize_t target_stat_scsi_lu_show_attr_creation_time( |
| 611 | struct se_dev_stat_grps *sgrps, char *page) | 455 | struct se_dev_stat_grps *sgrps, char *page) |
| 612 | { | 456 | { |
| 613 | struct se_subsystem_dev *se_subdev = container_of(sgrps, | 457 | struct se_device *dev = |
| 614 | struct se_subsystem_dev, dev_stat_grps); | 458 | container_of(sgrps, struct se_device, dev_stat_grps); |
| 615 | struct se_device *dev = se_subdev->se_dev_ptr; | ||
| 616 | |||
| 617 | if (!dev) | ||
| 618 | return -ENODEV; | ||
| 619 | 459 | ||
| 620 | /* scsiLuCreationTime */ | 460 | /* scsiLuCreationTime */ |
| 621 | return snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)dev->creation_time - | 461 | return snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)dev->creation_time - |
| @@ -662,20 +502,20 @@ static struct config_item_type target_stat_scsi_lu_cit = { | |||
| 662 | * Called from target_core_configfs.c:target_core_make_subdev() to setup | 502 | * Called from target_core_configfs.c:target_core_make_subdev() to setup |
| 663 | * the target statistics groups + configfs CITs located in target_core_stat.c | 503 | * the target statistics groups + configfs CITs located in target_core_stat.c |
| 664 | */ | 504 | */ |
| 665 | void target_stat_setup_dev_default_groups(struct se_subsystem_dev *se_subdev) | 505 | void target_stat_setup_dev_default_groups(struct se_device *dev) |
| 666 | { | 506 | { |
| 667 | struct config_group *dev_stat_grp = &se_subdev->dev_stat_grps.stat_group; | 507 | struct config_group *dev_stat_grp = &dev->dev_stat_grps.stat_group; |
| 668 | 508 | ||
| 669 | config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_dev_group, | 509 | config_group_init_type_name(&dev->dev_stat_grps.scsi_dev_group, |
| 670 | "scsi_dev", &target_stat_scsi_dev_cit); | 510 | "scsi_dev", &target_stat_scsi_dev_cit); |
| 671 | config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_tgt_dev_group, | 511 | config_group_init_type_name(&dev->dev_stat_grps.scsi_tgt_dev_group, |
| 672 | "scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit); | 512 | "scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit); |
| 673 | config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_lu_group, | 513 | config_group_init_type_name(&dev->dev_stat_grps.scsi_lu_group, |
| 674 | "scsi_lu", &target_stat_scsi_lu_cit); | 514 | "scsi_lu", &target_stat_scsi_lu_cit); |
| 675 | 515 | ||
| 676 | dev_stat_grp->default_groups[0] = &se_subdev->dev_stat_grps.scsi_dev_group; | 516 | dev_stat_grp->default_groups[0] = &dev->dev_stat_grps.scsi_dev_group; |
| 677 | dev_stat_grp->default_groups[1] = &se_subdev->dev_stat_grps.scsi_tgt_dev_group; | 517 | dev_stat_grp->default_groups[1] = &dev->dev_stat_grps.scsi_tgt_dev_group; |
| 678 | dev_stat_grp->default_groups[2] = &se_subdev->dev_stat_grps.scsi_lu_group; | 518 | dev_stat_grp->default_groups[2] = &dev->dev_stat_grps.scsi_lu_group; |
| 679 | dev_stat_grp->default_groups[3] = NULL; | 519 | dev_stat_grp->default_groups[3] = NULL; |
| 680 | } | 520 | } |
| 681 | 521 | ||
| @@ -1161,7 +1001,7 @@ static ssize_t target_stat_scsi_transport_show_attr_dev_name( | |||
| 1161 | return -ENODEV; | 1001 | return -ENODEV; |
| 1162 | } | 1002 | } |
| 1163 | tpg = sep->sep_tpg; | 1003 | tpg = sep->sep_tpg; |
| 1164 | wwn = &dev->se_sub_dev->t10_wwn; | 1004 | wwn = &dev->t10_wwn; |
| 1165 | /* scsiTransportDevName */ | 1005 | /* scsiTransportDevName */ |
| 1166 | ret = snprintf(page, PAGE_SIZE, "%s+%s\n", | 1006 | ret = snprintf(page, PAGE_SIZE, "%s+%s\n", |
| 1167 | tpg->se_tpg_tfo->tpg_get_wwn(tpg), | 1007 | tpg->se_tpg_tfo->tpg_get_wwn(tpg), |
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index be75c4331a92..c6e0293ffdb0 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c | |||
| @@ -3,8 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains SPC-3 task management infrastructure | 4 | * This file contains SPC-3 task management infrastructure |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2009,2010 Rising Tide Systems | 6 | * (c) Copyright 2009-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2009,2010 Linux-iSCSI.org | ||
| 8 | * | 7 | * |
| 9 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 10 | * | 9 | * |
| @@ -371,7 +370,7 @@ int core_tmr_lun_reset( | |||
| 371 | * which the command was received shall be completed with TASK ABORTED | 370 | * which the command was received shall be completed with TASK ABORTED |
| 372 | * status (see SAM-4). | 371 | * status (see SAM-4). |
| 373 | */ | 372 | */ |
| 374 | tas = dev->se_sub_dev->se_dev_attrib.emulate_tas; | 373 | tas = dev->dev_attrib.emulate_tas; |
| 375 | /* | 374 | /* |
| 376 | * Determine if this se_tmr is coming from a $FABRIC_MOD | 375 | * Determine if this se_tmr is coming from a $FABRIC_MOD |
| 377 | * or struct se_device passthrough.. | 376 | * or struct se_device passthrough.. |
| @@ -399,10 +398,10 @@ int core_tmr_lun_reset( | |||
| 399 | * LOGICAL UNIT RESET | 398 | * LOGICAL UNIT RESET |
| 400 | */ | 399 | */ |
| 401 | if (!preempt_and_abort_list && | 400 | if (!preempt_and_abort_list && |
| 402 | (dev->dev_flags & DF_SPC2_RESERVATIONS)) { | 401 | (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)) { |
| 403 | spin_lock(&dev->dev_reservation_lock); | 402 | spin_lock(&dev->dev_reservation_lock); |
| 404 | dev->dev_reserved_node_acl = NULL; | 403 | dev->dev_reserved_node_acl = NULL; |
| 405 | dev->dev_flags &= ~DF_SPC2_RESERVATIONS; | 404 | dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS; |
| 406 | spin_unlock(&dev->dev_reservation_lock); | 405 | spin_unlock(&dev->dev_reservation_lock); |
| 407 | pr_debug("LUN_RESET: SCSI-2 Released reservation\n"); | 406 | pr_debug("LUN_RESET: SCSI-2 Released reservation\n"); |
| 408 | } | 407 | } |
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index a531fe282b1e..5192ac0337f7 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c | |||
| @@ -3,10 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains generic Target Portal Group related functions. | 4 | * This file contains generic Target Portal Group related functions. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. | 6 | * (c) Copyright 2002-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 8 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 9 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 10 | * | 7 | * |
| 11 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 12 | * | 9 | * |
| @@ -619,6 +616,29 @@ int core_tpg_set_initiator_node_queue_depth( | |||
| 619 | } | 616 | } |
| 620 | EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth); | 617 | EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth); |
| 621 | 618 | ||
| 619 | /* core_tpg_set_initiator_node_tag(): | ||
| 620 | * | ||
| 621 | * Initiator nodeacl tags are not used internally, but may be used by | ||
| 622 | * userspace to emulate aliases or groups. | ||
| 623 | * Returns length of newly-set tag or -EINVAL. | ||
| 624 | */ | ||
| 625 | int core_tpg_set_initiator_node_tag( | ||
| 626 | struct se_portal_group *tpg, | ||
| 627 | struct se_node_acl *acl, | ||
| 628 | const char *new_tag) | ||
| 629 | { | ||
| 630 | if (strlen(new_tag) >= MAX_ACL_TAG_SIZE) | ||
| 631 | return -EINVAL; | ||
| 632 | |||
| 633 | if (!strncmp("NULL", new_tag, 4)) { | ||
| 634 | acl->acl_tag[0] = '\0'; | ||
| 635 | return 0; | ||
| 636 | } | ||
| 637 | |||
| 638 | return snprintf(acl->acl_tag, MAX_ACL_TAG_SIZE, "%s", new_tag); | ||
| 639 | } | ||
| 640 | EXPORT_SYMBOL(core_tpg_set_initiator_node_tag); | ||
| 641 | |||
| 622 | static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) | 642 | static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) |
| 623 | { | 643 | { |
| 624 | /* Set in core_dev_setup_virtual_lun0() */ | 644 | /* Set in core_dev_setup_virtual_lun0() */ |
| @@ -672,6 +692,7 @@ int core_tpg_register( | |||
| 672 | for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { | 692 | for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { |
| 673 | lun = se_tpg->tpg_lun_list[i]; | 693 | lun = se_tpg->tpg_lun_list[i]; |
| 674 | lun->unpacked_lun = i; | 694 | lun->unpacked_lun = i; |
| 695 | lun->lun_link_magic = SE_LUN_LINK_MAGIC; | ||
| 675 | lun->lun_status = TRANSPORT_LUN_STATUS_FREE; | 696 | lun->lun_status = TRANSPORT_LUN_STATUS_FREE; |
| 676 | atomic_set(&lun->lun_acl_count, 0); | 697 | atomic_set(&lun->lun_acl_count, 0); |
| 677 | init_completion(&lun->lun_shutdown_comp); | 698 | init_completion(&lun->lun_shutdown_comp); |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index dcecbfb17243..c23c76ccef65 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -3,10 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains the Generic Target Engine Core. | 4 | * This file contains the Generic Target Engine Core. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. | 6 | * (c) Copyright 2002-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
| 8 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
| 9 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
| 10 | * | 7 | * |
| 11 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 12 | * | 9 | * |
| @@ -70,7 +67,6 @@ static void transport_handle_queue_full(struct se_cmd *cmd, | |||
| 70 | static int transport_generic_get_mem(struct se_cmd *cmd); | 67 | static int transport_generic_get_mem(struct se_cmd *cmd); |
| 71 | static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool); | 68 | static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool); |
| 72 | static void transport_put_cmd(struct se_cmd *cmd); | 69 | static void transport_put_cmd(struct se_cmd *cmd); |
| 73 | static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq); | ||
| 74 | static void target_complete_ok_work(struct work_struct *work); | 70 | static void target_complete_ok_work(struct work_struct *work); |
| 75 | 71 | ||
| 76 | int init_se_kmem_caches(void) | 72 | int init_se_kmem_caches(void) |
| @@ -297,7 +293,7 @@ void transport_register_session( | |||
| 297 | } | 293 | } |
| 298 | EXPORT_SYMBOL(transport_register_session); | 294 | EXPORT_SYMBOL(transport_register_session); |
| 299 | 295 | ||
| 300 | void target_release_session(struct kref *kref) | 296 | static void target_release_session(struct kref *kref) |
| 301 | { | 297 | { |
| 302 | struct se_session *se_sess = container_of(kref, | 298 | struct se_session *se_sess = container_of(kref, |
| 303 | struct se_session, sess_kref); | 299 | struct se_session, sess_kref); |
| @@ -558,7 +554,8 @@ static void target_complete_failure_work(struct work_struct *work) | |||
| 558 | { | 554 | { |
| 559 | struct se_cmd *cmd = container_of(work, struct se_cmd, work); | 555 | struct se_cmd *cmd = container_of(work, struct se_cmd, work); |
| 560 | 556 | ||
| 561 | transport_generic_request_failure(cmd); | 557 | transport_generic_request_failure(cmd, |
| 558 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE); | ||
| 562 | } | 559 | } |
| 563 | 560 | ||
| 564 | /* | 561 | /* |
| @@ -626,7 +623,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) | |||
| 626 | complete(&cmd->t_transport_stop_comp); | 623 | complete(&cmd->t_transport_stop_comp); |
| 627 | return; | 624 | return; |
| 628 | } else if (cmd->transport_state & CMD_T_FAILED) { | 625 | } else if (cmd->transport_state & CMD_T_FAILED) { |
| 629 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 630 | INIT_WORK(&cmd->work, target_complete_failure_work); | 626 | INIT_WORK(&cmd->work, target_complete_failure_work); |
| 631 | } else { | 627 | } else { |
| 632 | INIT_WORK(&cmd->work, target_complete_ok_work); | 628 | INIT_WORK(&cmd->work, target_complete_ok_work); |
| @@ -659,7 +655,7 @@ static void target_add_to_state_list(struct se_cmd *cmd) | |||
| 659 | static void transport_write_pending_qf(struct se_cmd *cmd); | 655 | static void transport_write_pending_qf(struct se_cmd *cmd); |
| 660 | static void transport_complete_qf(struct se_cmd *cmd); | 656 | static void transport_complete_qf(struct se_cmd *cmd); |
| 661 | 657 | ||
| 662 | static void target_qf_do_work(struct work_struct *work) | 658 | void target_qf_do_work(struct work_struct *work) |
| 663 | { | 659 | { |
| 664 | struct se_device *dev = container_of(work, struct se_device, | 660 | struct se_device *dev = container_of(work, struct se_device, |
| 665 | qf_work_queue); | 661 | qf_work_queue); |
| @@ -712,29 +708,15 @@ void transport_dump_dev_state( | |||
| 712 | int *bl) | 708 | int *bl) |
| 713 | { | 709 | { |
| 714 | *bl += sprintf(b + *bl, "Status: "); | 710 | *bl += sprintf(b + *bl, "Status: "); |
| 715 | switch (dev->dev_status) { | 711 | if (dev->export_count) |
| 716 | case TRANSPORT_DEVICE_ACTIVATED: | ||
| 717 | *bl += sprintf(b + *bl, "ACTIVATED"); | 712 | *bl += sprintf(b + *bl, "ACTIVATED"); |
| 718 | break; | 713 | else |
| 719 | case TRANSPORT_DEVICE_DEACTIVATED: | ||
| 720 | *bl += sprintf(b + *bl, "DEACTIVATED"); | 714 | *bl += sprintf(b + *bl, "DEACTIVATED"); |
| 721 | break; | ||
| 722 | case TRANSPORT_DEVICE_SHUTDOWN: | ||
| 723 | *bl += sprintf(b + *bl, "SHUTDOWN"); | ||
| 724 | break; | ||
| 725 | case TRANSPORT_DEVICE_OFFLINE_ACTIVATED: | ||
| 726 | case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED: | ||
| 727 | *bl += sprintf(b + *bl, "OFFLINE"); | ||
| 728 | break; | ||
| 729 | default: | ||
| 730 | *bl += sprintf(b + *bl, "UNKNOWN=%d", dev->dev_status); | ||
| 731 | break; | ||
| 732 | } | ||
| 733 | 715 | ||
| 734 | *bl += sprintf(b + *bl, " Max Queue Depth: %d", dev->queue_depth); | 716 | *bl += sprintf(b + *bl, " Max Queue Depth: %d", dev->queue_depth); |
| 735 | *bl += sprintf(b + *bl, " SectorSize: %u HwMaxSectors: %u\n", | 717 | *bl += sprintf(b + *bl, " SectorSize: %u HwMaxSectors: %u\n", |
| 736 | dev->se_sub_dev->se_dev_attrib.block_size, | 718 | dev->dev_attrib.block_size, |
| 737 | dev->se_sub_dev->se_dev_attrib.hw_max_sectors); | 719 | dev->dev_attrib.hw_max_sectors); |
| 738 | *bl += sprintf(b + *bl, " "); | 720 | *bl += sprintf(b + *bl, " "); |
| 739 | } | 721 | } |
| 740 | 722 | ||
| @@ -991,186 +973,8 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83) | |||
| 991 | } | 973 | } |
| 992 | EXPORT_SYMBOL(transport_set_vpd_ident); | 974 | EXPORT_SYMBOL(transport_set_vpd_ident); |
| 993 | 975 | ||
| 994 | static void core_setup_task_attr_emulation(struct se_device *dev) | 976 | sense_reason_t |
| 995 | { | 977 | target_cmd_size_check(struct se_cmd *cmd, unsigned int size) |
| 996 | /* | ||
| 997 | * If this device is from Target_Core_Mod/pSCSI, disable the | ||
| 998 | * SAM Task Attribute emulation. | ||
| 999 | * | ||
| 1000 | * This is currently not available in upsream Linux/SCSI Target | ||
| 1001 | * mode code, and is assumed to be disabled while using TCM/pSCSI. | ||
| 1002 | */ | ||
| 1003 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { | ||
| 1004 | dev->dev_task_attr_type = SAM_TASK_ATTR_PASSTHROUGH; | ||
| 1005 | return; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | dev->dev_task_attr_type = SAM_TASK_ATTR_EMULATED; | ||
| 1009 | pr_debug("%s: Using SAM_TASK_ATTR_EMULATED for SPC: 0x%02x" | ||
| 1010 | " device\n", dev->transport->name, | ||
| 1011 | dev->transport->get_device_rev(dev)); | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | static void scsi_dump_inquiry(struct se_device *dev) | ||
| 1015 | { | ||
| 1016 | struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; | ||
| 1017 | char buf[17]; | ||
| 1018 | int i, device_type; | ||
| 1019 | /* | ||
| 1020 | * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer | ||
| 1021 | */ | ||
| 1022 | for (i = 0; i < 8; i++) | ||
| 1023 | if (wwn->vendor[i] >= 0x20) | ||
| 1024 | buf[i] = wwn->vendor[i]; | ||
| 1025 | else | ||
| 1026 | buf[i] = ' '; | ||
| 1027 | buf[i] = '\0'; | ||
| 1028 | pr_debug(" Vendor: %s\n", buf); | ||
| 1029 | |||
| 1030 | for (i = 0; i < 16; i++) | ||
| 1031 | if (wwn->model[i] >= 0x20) | ||
| 1032 | buf[i] = wwn->model[i]; | ||
| 1033 | else | ||
| 1034 | buf[i] = ' '; | ||
| 1035 | buf[i] = '\0'; | ||
| 1036 | pr_debug(" Model: %s\n", buf); | ||
| 1037 | |||
| 1038 | for (i = 0; i < 4; i++) | ||
| 1039 | if (wwn->revision[i] >= 0x20) | ||
| 1040 | buf[i] = wwn->revision[i]; | ||
| 1041 | else | ||
| 1042 | buf[i] = ' '; | ||
| 1043 | buf[i] = '\0'; | ||
| 1044 | pr_debug(" Revision: %s\n", buf); | ||
| 1045 | |||
| 1046 | device_type = dev->transport->get_device_type(dev); | ||
| 1047 | pr_debug(" Type: %s ", scsi_device_type(device_type)); | ||
| 1048 | pr_debug(" ANSI SCSI revision: %02x\n", | ||
| 1049 | dev->transport->get_device_rev(dev)); | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | struct se_device *transport_add_device_to_core_hba( | ||
| 1053 | struct se_hba *hba, | ||
| 1054 | struct se_subsystem_api *transport, | ||
| 1055 | struct se_subsystem_dev *se_dev, | ||
| 1056 | u32 device_flags, | ||
| 1057 | void *transport_dev, | ||
| 1058 | struct se_dev_limits *dev_limits, | ||
| 1059 | const char *inquiry_prod, | ||
| 1060 | const char *inquiry_rev) | ||
| 1061 | { | ||
| 1062 | int force_pt; | ||
| 1063 | struct se_device *dev; | ||
| 1064 | |||
| 1065 | dev = kzalloc(sizeof(struct se_device), GFP_KERNEL); | ||
| 1066 | if (!dev) { | ||
| 1067 | pr_err("Unable to allocate memory for se_dev_t\n"); | ||
| 1068 | return NULL; | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | dev->dev_flags = device_flags; | ||
| 1072 | dev->dev_status |= TRANSPORT_DEVICE_DEACTIVATED; | ||
| 1073 | dev->dev_ptr = transport_dev; | ||
| 1074 | dev->se_hba = hba; | ||
| 1075 | dev->se_sub_dev = se_dev; | ||
| 1076 | dev->transport = transport; | ||
| 1077 | INIT_LIST_HEAD(&dev->dev_list); | ||
| 1078 | INIT_LIST_HEAD(&dev->dev_sep_list); | ||
| 1079 | INIT_LIST_HEAD(&dev->dev_tmr_list); | ||
| 1080 | INIT_LIST_HEAD(&dev->delayed_cmd_list); | ||
| 1081 | INIT_LIST_HEAD(&dev->state_list); | ||
| 1082 | INIT_LIST_HEAD(&dev->qf_cmd_list); | ||
| 1083 | spin_lock_init(&dev->execute_task_lock); | ||
| 1084 | spin_lock_init(&dev->delayed_cmd_lock); | ||
| 1085 | spin_lock_init(&dev->dev_reservation_lock); | ||
| 1086 | spin_lock_init(&dev->dev_status_lock); | ||
| 1087 | spin_lock_init(&dev->se_port_lock); | ||
| 1088 | spin_lock_init(&dev->se_tmr_lock); | ||
| 1089 | spin_lock_init(&dev->qf_cmd_lock); | ||
| 1090 | atomic_set(&dev->dev_ordered_id, 0); | ||
| 1091 | |||
| 1092 | se_dev_set_default_attribs(dev, dev_limits); | ||
| 1093 | |||
| 1094 | dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); | ||
| 1095 | dev->creation_time = get_jiffies_64(); | ||
| 1096 | spin_lock_init(&dev->stats_lock); | ||
| 1097 | |||
| 1098 | spin_lock(&hba->device_lock); | ||
| 1099 | list_add_tail(&dev->dev_list, &hba->hba_dev_list); | ||
| 1100 | hba->dev_count++; | ||
| 1101 | spin_unlock(&hba->device_lock); | ||
| 1102 | /* | ||
| 1103 | * Setup the SAM Task Attribute emulation for struct se_device | ||
| 1104 | */ | ||
| 1105 | core_setup_task_attr_emulation(dev); | ||
| 1106 | /* | ||
| 1107 | * Force PR and ALUA passthrough emulation with internal object use. | ||
| 1108 | */ | ||
| 1109 | force_pt = (hba->hba_flags & HBA_FLAGS_INTERNAL_USE); | ||
| 1110 | /* | ||
| 1111 | * Setup the Reservations infrastructure for struct se_device | ||
| 1112 | */ | ||
| 1113 | core_setup_reservations(dev, force_pt); | ||
| 1114 | /* | ||
| 1115 | * Setup the Asymmetric Logical Unit Assignment for struct se_device | ||
| 1116 | */ | ||
| 1117 | if (core_setup_alua(dev, force_pt) < 0) | ||
| 1118 | goto err_dev_list; | ||
| 1119 | |||
| 1120 | /* | ||
| 1121 | * Startup the struct se_device processing thread | ||
| 1122 | */ | ||
| 1123 | dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1, | ||
| 1124 | dev->transport->name); | ||
| 1125 | if (!dev->tmr_wq) { | ||
| 1126 | pr_err("Unable to create tmr workqueue for %s\n", | ||
| 1127 | dev->transport->name); | ||
| 1128 | goto err_dev_list; | ||
| 1129 | } | ||
| 1130 | /* | ||
| 1131 | * Setup work_queue for QUEUE_FULL | ||
| 1132 | */ | ||
| 1133 | INIT_WORK(&dev->qf_work_queue, target_qf_do_work); | ||
| 1134 | /* | ||
| 1135 | * Preload the initial INQUIRY const values if we are doing | ||
| 1136 | * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI | ||
| 1137 | * passthrough because this is being provided by the backend LLD. | ||
| 1138 | * This is required so that transport_get_inquiry() copies these | ||
| 1139 | * originals once back into DEV_T10_WWN(dev) for the virtual device | ||
| 1140 | * setup. | ||
| 1141 | */ | ||
| 1142 | if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { | ||
| 1143 | if (!inquiry_prod || !inquiry_rev) { | ||
| 1144 | pr_err("All non TCM/pSCSI plugins require" | ||
| 1145 | " INQUIRY consts\n"); | ||
| 1146 | goto err_wq; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | strncpy(&dev->se_sub_dev->t10_wwn.vendor[0], "LIO-ORG", 8); | ||
| 1150 | strncpy(&dev->se_sub_dev->t10_wwn.model[0], inquiry_prod, 16); | ||
| 1151 | strncpy(&dev->se_sub_dev->t10_wwn.revision[0], inquiry_rev, 4); | ||
| 1152 | } | ||
| 1153 | scsi_dump_inquiry(dev); | ||
| 1154 | |||
| 1155 | return dev; | ||
| 1156 | |||
| 1157 | err_wq: | ||
| 1158 | destroy_workqueue(dev->tmr_wq); | ||
| 1159 | err_dev_list: | ||
| 1160 | spin_lock(&hba->device_lock); | ||
| 1161 | list_del(&dev->dev_list); | ||
| 1162 | hba->dev_count--; | ||
| 1163 | spin_unlock(&hba->device_lock); | ||
| 1164 | |||
| 1165 | se_release_vpd_for_dev(dev); | ||
| 1166 | |||
| 1167 | kfree(dev); | ||
| 1168 | |||
| 1169 | return NULL; | ||
| 1170 | } | ||
| 1171 | EXPORT_SYMBOL(transport_add_device_to_core_hba); | ||
| 1172 | |||
| 1173 | int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) | ||
| 1174 | { | 978 | { |
| 1175 | struct se_device *dev = cmd->se_dev; | 979 | struct se_device *dev = cmd->se_dev; |
| 1176 | 980 | ||
| @@ -1185,18 +989,18 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) | |||
| 1185 | if (cmd->data_direction == DMA_TO_DEVICE) { | 989 | if (cmd->data_direction == DMA_TO_DEVICE) { |
| 1186 | pr_err("Rejecting underflow/overflow" | 990 | pr_err("Rejecting underflow/overflow" |
| 1187 | " WRITE data\n"); | 991 | " WRITE data\n"); |
| 1188 | goto out_invalid_cdb_field; | 992 | return TCM_INVALID_CDB_FIELD; |
| 1189 | } | 993 | } |
| 1190 | /* | 994 | /* |
| 1191 | * Reject READ_* or WRITE_* with overflow/underflow for | 995 | * Reject READ_* or WRITE_* with overflow/underflow for |
| 1192 | * type SCF_SCSI_DATA_CDB. | 996 | * type SCF_SCSI_DATA_CDB. |
| 1193 | */ | 997 | */ |
| 1194 | if (dev->se_sub_dev->se_dev_attrib.block_size != 512) { | 998 | if (dev->dev_attrib.block_size != 512) { |
| 1195 | pr_err("Failing OVERFLOW/UNDERFLOW for LBA op" | 999 | pr_err("Failing OVERFLOW/UNDERFLOW for LBA op" |
| 1196 | " CDB on non 512-byte sector setup subsystem" | 1000 | " CDB on non 512-byte sector setup subsystem" |
| 1197 | " plugin: %s\n", dev->transport->name); | 1001 | " plugin: %s\n", dev->transport->name); |
| 1198 | /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ | 1002 | /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ |
| 1199 | goto out_invalid_cdb_field; | 1003 | return TCM_INVALID_CDB_FIELD; |
| 1200 | } | 1004 | } |
| 1201 | /* | 1005 | /* |
| 1202 | * For the overflow case keep the existing fabric provided | 1006 | * For the overflow case keep the existing fabric provided |
| @@ -1216,10 +1020,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) | |||
| 1216 | 1020 | ||
| 1217 | return 0; | 1021 | return 0; |
| 1218 | 1022 | ||
| 1219 | out_invalid_cdb_field: | ||
| 1220 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1221 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 1222 | return -EINVAL; | ||
| 1223 | } | 1023 | } |
| 1224 | 1024 | ||
| 1225 | /* | 1025 | /* |
| @@ -1259,45 +1059,41 @@ void transport_init_se_cmd( | |||
| 1259 | } | 1059 | } |
| 1260 | EXPORT_SYMBOL(transport_init_se_cmd); | 1060 | EXPORT_SYMBOL(transport_init_se_cmd); |
| 1261 | 1061 | ||
| 1262 | static int transport_check_alloc_task_attr(struct se_cmd *cmd) | 1062 | static sense_reason_t |
| 1063 | transport_check_alloc_task_attr(struct se_cmd *cmd) | ||
| 1263 | { | 1064 | { |
| 1065 | struct se_device *dev = cmd->se_dev; | ||
| 1066 | |||
| 1264 | /* | 1067 | /* |
| 1265 | * Check if SAM Task Attribute emulation is enabled for this | 1068 | * Check if SAM Task Attribute emulation is enabled for this |
| 1266 | * struct se_device storage object | 1069 | * struct se_device storage object |
| 1267 | */ | 1070 | */ |
| 1268 | if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) | 1071 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 1269 | return 0; | 1072 | return 0; |
| 1270 | 1073 | ||
| 1271 | if (cmd->sam_task_attr == MSG_ACA_TAG) { | 1074 | if (cmd->sam_task_attr == MSG_ACA_TAG) { |
| 1272 | pr_debug("SAM Task Attribute ACA" | 1075 | pr_debug("SAM Task Attribute ACA" |
| 1273 | " emulation is not supported\n"); | 1076 | " emulation is not supported\n"); |
| 1274 | return -EINVAL; | 1077 | return TCM_INVALID_CDB_FIELD; |
| 1275 | } | 1078 | } |
| 1276 | /* | 1079 | /* |
| 1277 | * Used to determine when ORDERED commands should go from | 1080 | * Used to determine when ORDERED commands should go from |
| 1278 | * Dormant to Active status. | 1081 | * Dormant to Active status. |
| 1279 | */ | 1082 | */ |
| 1280 | cmd->se_ordered_id = atomic_inc_return(&cmd->se_dev->dev_ordered_id); | 1083 | cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id); |
| 1281 | smp_mb__after_atomic_inc(); | 1084 | smp_mb__after_atomic_inc(); |
| 1282 | pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n", | 1085 | pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n", |
| 1283 | cmd->se_ordered_id, cmd->sam_task_attr, | 1086 | cmd->se_ordered_id, cmd->sam_task_attr, |
| 1284 | cmd->se_dev->transport->name); | 1087 | dev->transport->name); |
| 1285 | return 0; | 1088 | return 0; |
| 1286 | } | 1089 | } |
| 1287 | 1090 | ||
| 1288 | /* target_setup_cmd_from_cdb(): | 1091 | sense_reason_t |
| 1289 | * | 1092 | target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) |
| 1290 | * Called from fabric RX Thread. | ||
| 1291 | */ | ||
| 1292 | int target_setup_cmd_from_cdb( | ||
| 1293 | struct se_cmd *cmd, | ||
| 1294 | unsigned char *cdb) | ||
| 1295 | { | 1093 | { |
| 1296 | struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; | 1094 | struct se_device *dev = cmd->se_dev; |
| 1297 | u32 pr_reg_type = 0; | ||
| 1298 | u8 alua_ascq = 0; | ||
| 1299 | unsigned long flags; | 1095 | unsigned long flags; |
| 1300 | int ret; | 1096 | sense_reason_t ret; |
| 1301 | 1097 | ||
| 1302 | /* | 1098 | /* |
| 1303 | * Ensure that the received CDB is less than the max (252 + 8) bytes | 1099 | * Ensure that the received CDB is less than the max (252 + 8) bytes |
| @@ -1307,9 +1103,7 @@ int target_setup_cmd_from_cdb( | |||
| 1307 | pr_err("Received SCSI CDB with command_size: %d that" | 1103 | pr_err("Received SCSI CDB with command_size: %d that" |
| 1308 | " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", | 1104 | " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", |
| 1309 | scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE); | 1105 | scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE); |
| 1310 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 1106 | return TCM_INVALID_CDB_FIELD; |
| 1311 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 1312 | return -EINVAL; | ||
| 1313 | } | 1107 | } |
| 1314 | /* | 1108 | /* |
| 1315 | * If the received CDB is larger than TCM_MAX_COMMAND_SIZE, | 1109 | * If the received CDB is larger than TCM_MAX_COMMAND_SIZE, |
| @@ -1324,10 +1118,7 @@ int target_setup_cmd_from_cdb( | |||
| 1324 | " %u > sizeof(cmd->__t_task_cdb): %lu ops\n", | 1118 | " %u > sizeof(cmd->__t_task_cdb): %lu ops\n", |
| 1325 | scsi_command_size(cdb), | 1119 | scsi_command_size(cdb), |
| 1326 | (unsigned long)sizeof(cmd->__t_task_cdb)); | 1120 | (unsigned long)sizeof(cmd->__t_task_cdb)); |
| 1327 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 1121 | return TCM_OUT_OF_RESOURCES; |
| 1328 | cmd->scsi_sense_reason = | ||
| 1329 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1330 | return -ENOMEM; | ||
| 1331 | } | 1122 | } |
| 1332 | } else | 1123 | } else |
| 1333 | cmd->t_task_cdb = &cmd->__t_task_cdb[0]; | 1124 | cmd->t_task_cdb = &cmd->__t_task_cdb[0]; |
| @@ -1339,70 +1130,30 @@ int target_setup_cmd_from_cdb( | |||
| 1339 | /* | 1130 | /* |
| 1340 | * Check for an existing UNIT ATTENTION condition | 1131 | * Check for an existing UNIT ATTENTION condition |
| 1341 | */ | 1132 | */ |
| 1342 | if (core_scsi3_ua_check(cmd, cdb) < 0) { | 1133 | ret = target_scsi3_ua_check(cmd); |
| 1343 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 1134 | if (ret) |
| 1344 | cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION; | 1135 | return ret; |
| 1345 | return -EINVAL; | ||
| 1346 | } | ||
| 1347 | 1136 | ||
| 1348 | ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq); | 1137 | ret = target_alua_state_check(cmd); |
| 1349 | if (ret != 0) { | 1138 | if (ret) |
| 1350 | /* | 1139 | return ret; |
| 1351 | * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; | ||
| 1352 | * The ALUA additional sense code qualifier (ASCQ) is determined | ||
| 1353 | * by the ALUA primary or secondary access state.. | ||
| 1354 | */ | ||
| 1355 | if (ret > 0) { | ||
| 1356 | pr_debug("[%s]: ALUA TG Port not available, " | ||
| 1357 | "SenseKey: NOT_READY, ASC/ASCQ: " | ||
| 1358 | "0x04/0x%02x\n", | ||
| 1359 | cmd->se_tfo->get_fabric_name(), alua_ascq); | ||
| 1360 | |||
| 1361 | transport_set_sense_codes(cmd, 0x04, alua_ascq); | ||
| 1362 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1363 | cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; | ||
| 1364 | return -EINVAL; | ||
| 1365 | } | ||
| 1366 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1367 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 1368 | return -EINVAL; | ||
| 1369 | } | ||
| 1370 | 1140 | ||
| 1371 | /* | 1141 | ret = target_check_reservation(cmd); |
| 1372 | * Check status for SPC-3 Persistent Reservations | 1142 | if (ret) |
| 1373 | */ | 1143 | return ret; |
| 1374 | if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) { | ||
| 1375 | if (su_dev->t10_pr.pr_ops.t10_seq_non_holder( | ||
| 1376 | cmd, cdb, pr_reg_type) != 0) { | ||
| 1377 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1378 | cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; | ||
| 1379 | cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; | ||
| 1380 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | ||
| 1381 | return -EBUSY; | ||
| 1382 | } | ||
| 1383 | /* | ||
| 1384 | * This means the CDB is allowed for the SCSI Initiator port | ||
| 1385 | * when said port is *NOT* holding the legacy SPC-2 or | ||
| 1386 | * SPC-3 Persistent Reservation. | ||
| 1387 | */ | ||
| 1388 | } | ||
| 1389 | 1144 | ||
| 1390 | ret = cmd->se_dev->transport->parse_cdb(cmd); | 1145 | ret = dev->transport->parse_cdb(cmd); |
| 1391 | if (ret < 0) | 1146 | if (ret) |
| 1147 | return ret; | ||
| 1148 | |||
| 1149 | ret = transport_check_alloc_task_attr(cmd); | ||
| 1150 | if (ret) | ||
| 1392 | return ret; | 1151 | return ret; |
| 1393 | 1152 | ||
| 1394 | spin_lock_irqsave(&cmd->t_state_lock, flags); | 1153 | spin_lock_irqsave(&cmd->t_state_lock, flags); |
| 1395 | cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; | 1154 | cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; |
| 1396 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 1155 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
| 1397 | 1156 | ||
| 1398 | /* | ||
| 1399 | * Check for SAM Task Attribute Emulation | ||
| 1400 | */ | ||
| 1401 | if (transport_check_alloc_task_attr(cmd) < 0) { | ||
| 1402 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 1403 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 1404 | return -EINVAL; | ||
| 1405 | } | ||
| 1406 | spin_lock(&cmd->se_lun->lun_sep_lock); | 1157 | spin_lock(&cmd->se_lun->lun_sep_lock); |
| 1407 | if (cmd->se_lun->lun_sep) | 1158 | if (cmd->se_lun->lun_sep) |
| 1408 | cmd->se_lun->lun_sep->sep_stats.cmd_pdus++; | 1159 | cmd->se_lun->lun_sep->sep_stats.cmd_pdus++; |
| @@ -1418,7 +1169,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb); | |||
| 1418 | int transport_handle_cdb_direct( | 1169 | int transport_handle_cdb_direct( |
| 1419 | struct se_cmd *cmd) | 1170 | struct se_cmd *cmd) |
| 1420 | { | 1171 | { |
| 1421 | int ret; | 1172 | sense_reason_t ret; |
| 1422 | 1173 | ||
| 1423 | if (!cmd->se_lun) { | 1174 | if (!cmd->se_lun) { |
| 1424 | dump_stack(); | 1175 | dump_stack(); |
| @@ -1448,13 +1199,41 @@ int transport_handle_cdb_direct( | |||
| 1448 | * and call transport_generic_request_failure() if necessary.. | 1199 | * and call transport_generic_request_failure() if necessary.. |
| 1449 | */ | 1200 | */ |
| 1450 | ret = transport_generic_new_cmd(cmd); | 1201 | ret = transport_generic_new_cmd(cmd); |
| 1451 | if (ret < 0) | 1202 | if (ret) |
| 1452 | transport_generic_request_failure(cmd); | 1203 | transport_generic_request_failure(cmd, ret); |
| 1453 | |||
| 1454 | return 0; | 1204 | return 0; |
| 1455 | } | 1205 | } |
| 1456 | EXPORT_SYMBOL(transport_handle_cdb_direct); | 1206 | EXPORT_SYMBOL(transport_handle_cdb_direct); |
| 1457 | 1207 | ||
| 1208 | static sense_reason_t | ||
| 1209 | transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, | ||
| 1210 | u32 sgl_count, struct scatterlist *sgl_bidi, u32 sgl_bidi_count) | ||
| 1211 | { | ||
| 1212 | if (!sgl || !sgl_count) | ||
| 1213 | return 0; | ||
| 1214 | |||
| 1215 | /* | ||
| 1216 | * Reject SCSI data overflow with map_mem_to_cmd() as incoming | ||
| 1217 | * scatterlists already have been set to follow what the fabric | ||
| 1218 | * passes for the original expected data transfer length. | ||
| 1219 | */ | ||
| 1220 | if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { | ||
| 1221 | pr_warn("Rejecting SCSI DATA overflow for fabric using" | ||
| 1222 | " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); | ||
| 1223 | return TCM_INVALID_CDB_FIELD; | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | cmd->t_data_sg = sgl; | ||
| 1227 | cmd->t_data_nents = sgl_count; | ||
| 1228 | |||
| 1229 | if (sgl_bidi && sgl_bidi_count) { | ||
| 1230 | cmd->t_bidi_data_sg = sgl_bidi; | ||
| 1231 | cmd->t_bidi_data_nents = sgl_bidi_count; | ||
| 1232 | } | ||
| 1233 | cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; | ||
| 1234 | return 0; | ||
| 1235 | } | ||
| 1236 | |||
| 1458 | /* | 1237 | /* |
| 1459 | * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized | 1238 | * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized |
| 1460 | * se_cmd + use pre-allocated SGL memory. | 1239 | * se_cmd + use pre-allocated SGL memory. |
| @@ -1487,7 +1266,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess | |||
| 1487 | struct scatterlist *sgl_bidi, u32 sgl_bidi_count) | 1266 | struct scatterlist *sgl_bidi, u32 sgl_bidi_count) |
| 1488 | { | 1267 | { |
| 1489 | struct se_portal_group *se_tpg; | 1268 | struct se_portal_group *se_tpg; |
| 1490 | int rc; | 1269 | sense_reason_t rc; |
| 1270 | int ret; | ||
| 1491 | 1271 | ||
| 1492 | se_tpg = se_sess->se_tpg; | 1272 | se_tpg = se_sess->se_tpg; |
| 1493 | BUG_ON(!se_tpg); | 1273 | BUG_ON(!se_tpg); |
| @@ -1508,9 +1288,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess | |||
| 1508 | * for fabrics using TARGET_SCF_ACK_KREF that expect a second | 1288 | * for fabrics using TARGET_SCF_ACK_KREF that expect a second |
| 1509 | * kref_put() to happen during fabric packet acknowledgement. | 1289 | * kref_put() to happen during fabric packet acknowledgement. |
| 1510 | */ | 1290 | */ |
| 1511 | rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); | 1291 | ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); |
| 1512 | if (rc) | 1292 | if (ret) |
| 1513 | return rc; | 1293 | return ret; |
| 1514 | /* | 1294 | /* |
| 1515 | * Signal bidirectional data payloads to target-core | 1295 | * Signal bidirectional data payloads to target-core |
| 1516 | */ | 1296 | */ |
| @@ -1519,16 +1299,16 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess | |||
| 1519 | /* | 1299 | /* |
| 1520 | * Locate se_lun pointer and attach it to struct se_cmd | 1300 | * Locate se_lun pointer and attach it to struct se_cmd |
| 1521 | */ | 1301 | */ |
| 1522 | if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { | 1302 | rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun); |
| 1523 | transport_send_check_condition_and_sense(se_cmd, | 1303 | if (rc) { |
| 1524 | se_cmd->scsi_sense_reason, 0); | 1304 | transport_send_check_condition_and_sense(se_cmd, rc, 0); |
| 1525 | target_put_sess_cmd(se_sess, se_cmd); | 1305 | target_put_sess_cmd(se_sess, se_cmd); |
| 1526 | return 0; | 1306 | return 0; |
| 1527 | } | 1307 | } |
| 1528 | 1308 | ||
| 1529 | rc = target_setup_cmd_from_cdb(se_cmd, cdb); | 1309 | rc = target_setup_cmd_from_cdb(se_cmd, cdb); |
| 1530 | if (rc != 0) { | 1310 | if (rc != 0) { |
| 1531 | transport_generic_request_failure(se_cmd); | 1311 | transport_generic_request_failure(se_cmd, rc); |
| 1532 | return 0; | 1312 | return 0; |
| 1533 | } | 1313 | } |
| 1534 | /* | 1314 | /* |
| @@ -1563,7 +1343,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess | |||
| 1563 | rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count, | 1343 | rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count, |
| 1564 | sgl_bidi, sgl_bidi_count); | 1344 | sgl_bidi, sgl_bidi_count); |
| 1565 | if (rc != 0) { | 1345 | if (rc != 0) { |
| 1566 | transport_generic_request_failure(se_cmd); | 1346 | transport_generic_request_failure(se_cmd, rc); |
| 1567 | return 0; | 1347 | return 0; |
| 1568 | } | 1348 | } |
| 1569 | } | 1349 | } |
| @@ -1709,16 +1489,17 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags) | |||
| 1709 | /* | 1489 | /* |
| 1710 | * Handle SAM-esque emulation for generic transport request failures. | 1490 | * Handle SAM-esque emulation for generic transport request failures. |
| 1711 | */ | 1491 | */ |
| 1712 | void transport_generic_request_failure(struct se_cmd *cmd) | 1492 | void transport_generic_request_failure(struct se_cmd *cmd, |
| 1493 | sense_reason_t sense_reason) | ||
| 1713 | { | 1494 | { |
| 1714 | int ret = 0; | 1495 | int ret = 0; |
| 1715 | 1496 | ||
| 1716 | pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x" | 1497 | pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x" |
| 1717 | " CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd), | 1498 | " CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd), |
| 1718 | cmd->t_task_cdb[0]); | 1499 | cmd->t_task_cdb[0]); |
| 1719 | pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n", | 1500 | pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n", |
| 1720 | cmd->se_tfo->get_cmd_state(cmd), | 1501 | cmd->se_tfo->get_cmd_state(cmd), |
| 1721 | cmd->t_state, cmd->scsi_sense_reason); | 1502 | cmd->t_state, sense_reason); |
| 1722 | pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n", | 1503 | pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n", |
| 1723 | (cmd->transport_state & CMD_T_ACTIVE) != 0, | 1504 | (cmd->transport_state & CMD_T_ACTIVE) != 0, |
| 1724 | (cmd->transport_state & CMD_T_STOP) != 0, | 1505 | (cmd->transport_state & CMD_T_STOP) != 0, |
| @@ -1727,10 +1508,9 @@ void transport_generic_request_failure(struct se_cmd *cmd) | |||
| 1727 | /* | 1508 | /* |
| 1728 | * For SAM Task Attribute emulation for failed struct se_cmd | 1509 | * For SAM Task Attribute emulation for failed struct se_cmd |
| 1729 | */ | 1510 | */ |
| 1730 | if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 1511 | transport_complete_task_attr(cmd); |
| 1731 | transport_complete_task_attr(cmd); | ||
| 1732 | 1512 | ||
| 1733 | switch (cmd->scsi_sense_reason) { | 1513 | switch (sense_reason) { |
| 1734 | case TCM_NON_EXISTENT_LUN: | 1514 | case TCM_NON_EXISTENT_LUN: |
| 1735 | case TCM_UNSUPPORTED_SCSI_OPCODE: | 1515 | case TCM_UNSUPPORTED_SCSI_OPCODE: |
| 1736 | case TCM_INVALID_CDB_FIELD: | 1516 | case TCM_INVALID_CDB_FIELD: |
| @@ -1743,6 +1523,9 @@ void transport_generic_request_failure(struct se_cmd *cmd) | |||
| 1743 | case TCM_CHECK_CONDITION_UNIT_ATTENTION: | 1523 | case TCM_CHECK_CONDITION_UNIT_ATTENTION: |
| 1744 | case TCM_CHECK_CONDITION_NOT_READY: | 1524 | case TCM_CHECK_CONDITION_NOT_READY: |
| 1745 | break; | 1525 | break; |
| 1526 | case TCM_OUT_OF_RESOURCES: | ||
| 1527 | sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 1528 | break; | ||
| 1746 | case TCM_RESERVATION_CONFLICT: | 1529 | case TCM_RESERVATION_CONFLICT: |
| 1747 | /* | 1530 | /* |
| 1748 | * No SENSE Data payload for this case, set SCSI Status | 1531 | * No SENSE Data payload for this case, set SCSI Status |
| @@ -1759,7 +1542,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) | |||
| 1759 | * See spc4r17, section 7.4.6 Control Mode Page, Table 349 | 1542 | * See spc4r17, section 7.4.6 Control Mode Page, Table 349 |
| 1760 | */ | 1543 | */ |
| 1761 | if (cmd->se_sess && | 1544 | if (cmd->se_sess && |
| 1762 | cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) | 1545 | cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl == 2) |
| 1763 | core_scsi3_ua_allocate(cmd->se_sess->se_node_acl, | 1546 | core_scsi3_ua_allocate(cmd->se_sess->se_node_acl, |
| 1764 | cmd->orig_fe_lun, 0x2C, | 1547 | cmd->orig_fe_lun, 0x2C, |
| 1765 | ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); | 1548 | ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); |
| @@ -1770,13 +1553,12 @@ void transport_generic_request_failure(struct se_cmd *cmd) | |||
| 1770 | goto check_stop; | 1553 | goto check_stop; |
| 1771 | default: | 1554 | default: |
| 1772 | pr_err("Unknown transport error for CDB 0x%02x: %d\n", | 1555 | pr_err("Unknown transport error for CDB 0x%02x: %d\n", |
| 1773 | cmd->t_task_cdb[0], cmd->scsi_sense_reason); | 1556 | cmd->t_task_cdb[0], sense_reason); |
| 1774 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | 1557 | sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; |
| 1775 | break; | 1558 | break; |
| 1776 | } | 1559 | } |
| 1777 | 1560 | ||
| 1778 | ret = transport_send_check_condition_and_sense(cmd, | 1561 | ret = transport_send_check_condition_and_sense(cmd, sense_reason, 0); |
| 1779 | cmd->scsi_sense_reason, 0); | ||
| 1780 | if (ret == -EAGAIN || ret == -ENOMEM) | 1562 | if (ret == -EAGAIN || ret == -ENOMEM) |
| 1781 | goto queue_full; | 1563 | goto queue_full; |
| 1782 | 1564 | ||
| @@ -1794,69 +1576,30 @@ EXPORT_SYMBOL(transport_generic_request_failure); | |||
| 1794 | 1576 | ||
| 1795 | static void __target_execute_cmd(struct se_cmd *cmd) | 1577 | static void __target_execute_cmd(struct se_cmd *cmd) |
| 1796 | { | 1578 | { |
| 1797 | int error = 0; | 1579 | sense_reason_t ret; |
| 1798 | 1580 | ||
| 1799 | spin_lock_irq(&cmd->t_state_lock); | 1581 | spin_lock_irq(&cmd->t_state_lock); |
| 1800 | cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT); | 1582 | cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT); |
| 1801 | spin_unlock_irq(&cmd->t_state_lock); | 1583 | spin_unlock_irq(&cmd->t_state_lock); |
| 1802 | 1584 | ||
| 1803 | if (cmd->execute_cmd) | 1585 | if (cmd->execute_cmd) { |
| 1804 | error = cmd->execute_cmd(cmd); | 1586 | ret = cmd->execute_cmd(cmd); |
| 1587 | if (ret) { | ||
| 1588 | spin_lock_irq(&cmd->t_state_lock); | ||
| 1589 | cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); | ||
| 1590 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1805 | 1591 | ||
| 1806 | if (error) { | 1592 | transport_generic_request_failure(cmd, ret); |
| 1807 | spin_lock_irq(&cmd->t_state_lock); | 1593 | } |
| 1808 | cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); | ||
| 1809 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1810 | |||
| 1811 | transport_generic_request_failure(cmd); | ||
| 1812 | } | 1594 | } |
| 1813 | } | 1595 | } |
| 1814 | 1596 | ||
| 1815 | void target_execute_cmd(struct se_cmd *cmd) | 1597 | static bool target_handle_task_attr(struct se_cmd *cmd) |
| 1816 | { | 1598 | { |
| 1817 | struct se_device *dev = cmd->se_dev; | 1599 | struct se_device *dev = cmd->se_dev; |
| 1818 | 1600 | ||
| 1819 | /* | 1601 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) |
| 1820 | * If the received CDB has aleady been aborted stop processing it here. | 1602 | return false; |
| 1821 | */ | ||
| 1822 | if (transport_check_aborted_status(cmd, 1)) { | ||
| 1823 | complete(&cmd->t_transport_stop_comp); | ||
| 1824 | return; | ||
| 1825 | } | ||
| 1826 | |||
| 1827 | /* | ||
| 1828 | * Determine if IOCTL context caller in requesting the stopping of this | ||
| 1829 | * command for LUN shutdown purposes. | ||
| 1830 | */ | ||
| 1831 | spin_lock_irq(&cmd->t_state_lock); | ||
| 1832 | if (cmd->transport_state & CMD_T_LUN_STOP) { | ||
| 1833 | pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n", | ||
| 1834 | __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd)); | ||
| 1835 | |||
| 1836 | cmd->transport_state &= ~CMD_T_ACTIVE; | ||
| 1837 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1838 | complete(&cmd->transport_lun_stop_comp); | ||
| 1839 | return; | ||
| 1840 | } | ||
| 1841 | /* | ||
| 1842 | * Determine if frontend context caller is requesting the stopping of | ||
| 1843 | * this command for frontend exceptions. | ||
| 1844 | */ | ||
| 1845 | if (cmd->transport_state & CMD_T_STOP) { | ||
| 1846 | pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", | ||
| 1847 | __func__, __LINE__, | ||
| 1848 | cmd->se_tfo->get_task_tag(cmd)); | ||
| 1849 | |||
| 1850 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1851 | complete(&cmd->t_transport_stop_comp); | ||
| 1852 | return; | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | cmd->t_state = TRANSPORT_PROCESSING; | ||
| 1856 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1857 | |||
| 1858 | if (dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) | ||
| 1859 | goto execute; | ||
| 1860 | 1603 | ||
| 1861 | /* | 1604 | /* |
| 1862 | * Check for the existence of HEAD_OF_QUEUE, and if true return 1 | 1605 | * Check for the existence of HEAD_OF_QUEUE, and if true return 1 |
| @@ -1867,7 +1610,7 @@ void target_execute_cmd(struct se_cmd *cmd) | |||
| 1867 | pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, " | 1610 | pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, " |
| 1868 | "se_ordered_id: %u\n", | 1611 | "se_ordered_id: %u\n", |
| 1869 | cmd->t_task_cdb[0], cmd->se_ordered_id); | 1612 | cmd->t_task_cdb[0], cmd->se_ordered_id); |
| 1870 | goto execute; | 1613 | return false; |
| 1871 | case MSG_ORDERED_TAG: | 1614 | case MSG_ORDERED_TAG: |
| 1872 | atomic_inc(&dev->dev_ordered_sync); | 1615 | atomic_inc(&dev->dev_ordered_sync); |
| 1873 | smp_mb__after_atomic_inc(); | 1616 | smp_mb__after_atomic_inc(); |
| @@ -1881,7 +1624,7 @@ void target_execute_cmd(struct se_cmd *cmd) | |||
| 1881 | * exist that need to be completed first. | 1624 | * exist that need to be completed first. |
| 1882 | */ | 1625 | */ |
| 1883 | if (!atomic_read(&dev->simple_cmds)) | 1626 | if (!atomic_read(&dev->simple_cmds)) |
| 1884 | goto execute; | 1627 | return false; |
| 1885 | break; | 1628 | break; |
| 1886 | default: | 1629 | default: |
| 1887 | /* | 1630 | /* |
| @@ -1892,23 +1635,63 @@ void target_execute_cmd(struct se_cmd *cmd) | |||
| 1892 | break; | 1635 | break; |
| 1893 | } | 1636 | } |
| 1894 | 1637 | ||
| 1895 | if (atomic_read(&dev->dev_ordered_sync) != 0) { | 1638 | if (atomic_read(&dev->dev_ordered_sync) == 0) |
| 1896 | spin_lock(&dev->delayed_cmd_lock); | 1639 | return false; |
| 1897 | list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); | ||
| 1898 | spin_unlock(&dev->delayed_cmd_lock); | ||
| 1899 | 1640 | ||
| 1900 | pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to" | 1641 | spin_lock(&dev->delayed_cmd_lock); |
| 1901 | " delayed CMD list, se_ordered_id: %u\n", | 1642 | list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); |
| 1902 | cmd->t_task_cdb[0], cmd->sam_task_attr, | 1643 | spin_unlock(&dev->delayed_cmd_lock); |
| 1903 | cmd->se_ordered_id); | 1644 | |
| 1645 | pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to" | ||
| 1646 | " delayed CMD list, se_ordered_id: %u\n", | ||
| 1647 | cmd->t_task_cdb[0], cmd->sam_task_attr, | ||
| 1648 | cmd->se_ordered_id); | ||
| 1649 | return true; | ||
| 1650 | } | ||
| 1651 | |||
| 1652 | void target_execute_cmd(struct se_cmd *cmd) | ||
| 1653 | { | ||
| 1654 | /* | ||
| 1655 | * If the received CDB has aleady been aborted stop processing it here. | ||
| 1656 | */ | ||
| 1657 | if (transport_check_aborted_status(cmd, 1)) { | ||
| 1658 | complete(&cmd->transport_lun_stop_comp); | ||
| 1904 | return; | 1659 | return; |
| 1905 | } | 1660 | } |
| 1906 | 1661 | ||
| 1907 | execute: | ||
| 1908 | /* | 1662 | /* |
| 1909 | * Otherwise, no ORDERED task attributes exist.. | 1663 | * Determine if IOCTL context caller in requesting the stopping of this |
| 1664 | * command for LUN shutdown purposes. | ||
| 1910 | */ | 1665 | */ |
| 1911 | __target_execute_cmd(cmd); | 1666 | spin_lock_irq(&cmd->t_state_lock); |
| 1667 | if (cmd->transport_state & CMD_T_LUN_STOP) { | ||
| 1668 | pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n", | ||
| 1669 | __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd)); | ||
| 1670 | |||
| 1671 | cmd->transport_state &= ~CMD_T_ACTIVE; | ||
| 1672 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1673 | complete(&cmd->transport_lun_stop_comp); | ||
| 1674 | return; | ||
| 1675 | } | ||
| 1676 | /* | ||
| 1677 | * Determine if frontend context caller is requesting the stopping of | ||
| 1678 | * this command for frontend exceptions. | ||
| 1679 | */ | ||
| 1680 | if (cmd->transport_state & CMD_T_STOP) { | ||
| 1681 | pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", | ||
| 1682 | __func__, __LINE__, | ||
| 1683 | cmd->se_tfo->get_task_tag(cmd)); | ||
| 1684 | |||
| 1685 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1686 | complete(&cmd->t_transport_stop_comp); | ||
| 1687 | return; | ||
| 1688 | } | ||
| 1689 | |||
| 1690 | cmd->t_state = TRANSPORT_PROCESSING; | ||
| 1691 | spin_unlock_irq(&cmd->t_state_lock); | ||
| 1692 | |||
| 1693 | if (!target_handle_task_attr(cmd)) | ||
| 1694 | __target_execute_cmd(cmd); | ||
| 1912 | } | 1695 | } |
| 1913 | EXPORT_SYMBOL(target_execute_cmd); | 1696 | EXPORT_SYMBOL(target_execute_cmd); |
| 1914 | 1697 | ||
| @@ -1947,6 +1730,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd) | |||
| 1947 | { | 1730 | { |
| 1948 | struct se_device *dev = cmd->se_dev; | 1731 | struct se_device *dev = cmd->se_dev; |
| 1949 | 1732 | ||
| 1733 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) | ||
| 1734 | return; | ||
| 1735 | |||
| 1950 | if (cmd->sam_task_attr == MSG_SIMPLE_TAG) { | 1736 | if (cmd->sam_task_attr == MSG_SIMPLE_TAG) { |
| 1951 | atomic_dec(&dev->simple_cmds); | 1737 | atomic_dec(&dev->simple_cmds); |
| 1952 | smp_mb__after_atomic_dec(); | 1738 | smp_mb__after_atomic_dec(); |
| @@ -1975,8 +1761,7 @@ static void transport_complete_qf(struct se_cmd *cmd) | |||
| 1975 | { | 1761 | { |
| 1976 | int ret = 0; | 1762 | int ret = 0; |
| 1977 | 1763 | ||
| 1978 | if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 1764 | transport_complete_task_attr(cmd); |
| 1979 | transport_complete_task_attr(cmd); | ||
| 1980 | 1765 | ||
| 1981 | if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { | 1766 | if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { |
| 1982 | ret = cmd->se_tfo->queue_status(cmd); | 1767 | ret = cmd->se_tfo->queue_status(cmd); |
| @@ -2034,8 +1819,8 @@ static void target_complete_ok_work(struct work_struct *work) | |||
| 2034 | * delayed execution list after a HEAD_OF_QUEUE or ORDERED Task | 1819 | * delayed execution list after a HEAD_OF_QUEUE or ORDERED Task |
| 2035 | * Attribute. | 1820 | * Attribute. |
| 2036 | */ | 1821 | */ |
| 2037 | if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 1822 | transport_complete_task_attr(cmd); |
| 2038 | transport_complete_task_attr(cmd); | 1823 | |
| 2039 | /* | 1824 | /* |
| 2040 | * Check to schedule QUEUE_FULL work, or execute an existing | 1825 | * Check to schedule QUEUE_FULL work, or execute an existing |
| 2041 | * cmd->transport_qf_callback() | 1826 | * cmd->transport_qf_callback() |
| @@ -2183,9 +1968,10 @@ static void transport_put_cmd(struct se_cmd *cmd) | |||
| 2183 | unsigned long flags; | 1968 | unsigned long flags; |
| 2184 | 1969 | ||
| 2185 | spin_lock_irqsave(&cmd->t_state_lock, flags); | 1970 | spin_lock_irqsave(&cmd->t_state_lock, flags); |
| 2186 | if (atomic_read(&cmd->t_fe_count)) { | 1971 | if (atomic_read(&cmd->t_fe_count) && |
| 2187 | if (!atomic_dec_and_test(&cmd->t_fe_count)) | 1972 | !atomic_dec_and_test(&cmd->t_fe_count)) { |
| 2188 | goto out_busy; | 1973 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
| 1974 | return; | ||
| 2189 | } | 1975 | } |
| 2190 | 1976 | ||
| 2191 | if (cmd->transport_state & CMD_T_DEV_ACTIVE) { | 1977 | if (cmd->transport_state & CMD_T_DEV_ACTIVE) { |
| @@ -2197,56 +1983,7 @@ static void transport_put_cmd(struct se_cmd *cmd) | |||
| 2197 | transport_free_pages(cmd); | 1983 | transport_free_pages(cmd); |
| 2198 | transport_release_cmd(cmd); | 1984 | transport_release_cmd(cmd); |
| 2199 | return; | 1985 | return; |
| 2200 | out_busy: | ||
| 2201 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | /* | ||
| 2205 | * transport_generic_map_mem_to_cmd - Use fabric-alloced pages instead of | ||
| 2206 | * allocating in the core. | ||
| 2207 | * @cmd: Associated se_cmd descriptor | ||
| 2208 | * @mem: SGL style memory for TCM WRITE / READ | ||
| 2209 | * @sg_mem_num: Number of SGL elements | ||
| 2210 | * @mem_bidi_in: SGL style memory for TCM BIDI READ | ||
| 2211 | * @sg_mem_bidi_num: Number of BIDI READ SGL elements | ||
| 2212 | * | ||
| 2213 | * Return: nonzero return cmd was rejected for -ENOMEM or inproper usage | ||
| 2214 | * of parameters. | ||
| 2215 | */ | ||
| 2216 | int transport_generic_map_mem_to_cmd( | ||
| 2217 | struct se_cmd *cmd, | ||
| 2218 | struct scatterlist *sgl, | ||
| 2219 | u32 sgl_count, | ||
| 2220 | struct scatterlist *sgl_bidi, | ||
| 2221 | u32 sgl_bidi_count) | ||
| 2222 | { | ||
| 2223 | if (!sgl || !sgl_count) | ||
| 2224 | return 0; | ||
| 2225 | |||
| 2226 | /* | ||
| 2227 | * Reject SCSI data overflow with map_mem_to_cmd() as incoming | ||
| 2228 | * scatterlists already have been set to follow what the fabric | ||
| 2229 | * passes for the original expected data transfer length. | ||
| 2230 | */ | ||
| 2231 | if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { | ||
| 2232 | pr_warn("Rejecting SCSI DATA overflow for fabric using" | ||
| 2233 | " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); | ||
| 2234 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 2235 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 2236 | return -EINVAL; | ||
| 2237 | } | ||
| 2238 | |||
| 2239 | cmd->t_data_sg = sgl; | ||
| 2240 | cmd->t_data_nents = sgl_count; | ||
| 2241 | |||
| 2242 | if (sgl_bidi && sgl_bidi_count) { | ||
| 2243 | cmd->t_bidi_data_sg = sgl_bidi; | ||
| 2244 | cmd->t_bidi_data_nents = sgl_bidi_count; | ||
| 2245 | } | ||
| 2246 | cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; | ||
| 2247 | return 0; | ||
| 2248 | } | 1986 | } |
| 2249 | EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); | ||
| 2250 | 1987 | ||
| 2251 | void *transport_kmap_data_sg(struct se_cmd *cmd) | 1988 | void *transport_kmap_data_sg(struct se_cmd *cmd) |
| 2252 | { | 1989 | { |
| @@ -2268,10 +2005,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) | |||
| 2268 | 2005 | ||
| 2269 | /* >1 page. use vmap */ | 2006 | /* >1 page. use vmap */ |
| 2270 | pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); | 2007 | pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); |
| 2271 | if (!pages) { | 2008 | if (!pages) |
| 2272 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 2273 | return NULL; | 2009 | return NULL; |
| 2274 | } | ||
| 2275 | 2010 | ||
| 2276 | /* convert sg[] to pages[] */ | 2011 | /* convert sg[] to pages[] */ |
| 2277 | for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { | 2012 | for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { |
| @@ -2280,10 +2015,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) | |||
| 2280 | 2015 | ||
| 2281 | cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); | 2016 | cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); |
| 2282 | kfree(pages); | 2017 | kfree(pages); |
| 2283 | if (!cmd->t_data_vmap) { | 2018 | if (!cmd->t_data_vmap) |
| 2284 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 2285 | return NULL; | 2019 | return NULL; |
| 2286 | } | ||
| 2287 | 2020 | ||
| 2288 | return cmd->t_data_vmap + cmd->t_data_sg[0].offset; | 2021 | return cmd->t_data_vmap + cmd->t_data_sg[0].offset; |
| 2289 | } | 2022 | } |
| @@ -2349,7 +2082,8 @@ out: | |||
| 2349 | * might not have the payload yet, so notify the fabric via a call to | 2082 | * might not have the payload yet, so notify the fabric via a call to |
| 2350 | * ->write_pending instead. Otherwise place it on the execution queue. | 2083 | * ->write_pending instead. Otherwise place it on the execution queue. |
| 2351 | */ | 2084 | */ |
| 2352 | int transport_generic_new_cmd(struct se_cmd *cmd) | 2085 | sense_reason_t |
| 2086 | transport_generic_new_cmd(struct se_cmd *cmd) | ||
| 2353 | { | 2087 | { |
| 2354 | int ret = 0; | 2088 | int ret = 0; |
| 2355 | 2089 | ||
| @@ -2362,7 +2096,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd) | |||
| 2362 | cmd->data_length) { | 2096 | cmd->data_length) { |
| 2363 | ret = transport_generic_get_mem(cmd); | 2097 | ret = transport_generic_get_mem(cmd); |
| 2364 | if (ret < 0) | 2098 | if (ret < 0) |
| 2365 | goto out_fail; | 2099 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 2366 | } | 2100 | } |
| 2367 | 2101 | ||
| 2368 | atomic_inc(&cmd->t_fe_count); | 2102 | atomic_inc(&cmd->t_fe_count); |
| @@ -2388,14 +2122,11 @@ int transport_generic_new_cmd(struct se_cmd *cmd) | |||
| 2388 | if (ret == -EAGAIN || ret == -ENOMEM) | 2122 | if (ret == -EAGAIN || ret == -ENOMEM) |
| 2389 | goto queue_full; | 2123 | goto queue_full; |
| 2390 | 2124 | ||
| 2391 | if (ret < 0) | 2125 | /* fabric drivers should only return -EAGAIN or -ENOMEM as error */ |
| 2392 | return ret; | 2126 | WARN_ON(ret); |
| 2393 | return 1; | 2127 | |
| 2128 | return (!ret) ? 0 : TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 2394 | 2129 | ||
| 2395 | out_fail: | ||
| 2396 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | ||
| 2397 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 2398 | return -EINVAL; | ||
| 2399 | queue_full: | 2130 | queue_full: |
| 2400 | pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); | 2131 | pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); |
| 2401 | cmd->t_state = TRANSPORT_COMPLETE_QF_WP; | 2132 | cmd->t_state = TRANSPORT_COMPLETE_QF_WP; |
| @@ -2839,21 +2570,9 @@ static int transport_get_sense_codes( | |||
| 2839 | return 0; | 2570 | return 0; |
| 2840 | } | 2571 | } |
| 2841 | 2572 | ||
| 2842 | static int transport_set_sense_codes( | 2573 | int |
| 2843 | struct se_cmd *cmd, | 2574 | transport_send_check_condition_and_sense(struct se_cmd *cmd, |
| 2844 | u8 asc, | 2575 | sense_reason_t reason, int from_transport) |
| 2845 | u8 ascq) | ||
| 2846 | { | ||
| 2847 | cmd->scsi_asc = asc; | ||
| 2848 | cmd->scsi_ascq = ascq; | ||
| 2849 | |||
| 2850 | return 0; | ||
| 2851 | } | ||
| 2852 | |||
| 2853 | int transport_send_check_condition_and_sense( | ||
| 2854 | struct se_cmd *cmd, | ||
| 2855 | u8 reason, | ||
| 2856 | int from_transport) | ||
| 2857 | { | 2576 | { |
| 2858 | unsigned char *buffer = cmd->sense_buffer; | 2577 | unsigned char *buffer = cmd->sense_buffer; |
| 2859 | unsigned long flags; | 2578 | unsigned long flags; |
| @@ -3044,23 +2763,19 @@ EXPORT_SYMBOL(transport_send_check_condition_and_sense); | |||
| 3044 | 2763 | ||
| 3045 | int transport_check_aborted_status(struct se_cmd *cmd, int send_status) | 2764 | int transport_check_aborted_status(struct se_cmd *cmd, int send_status) |
| 3046 | { | 2765 | { |
| 3047 | int ret = 0; | 2766 | if (!(cmd->transport_state & CMD_T_ABORTED)) |
| 2767 | return 0; | ||
| 3048 | 2768 | ||
| 3049 | if (cmd->transport_state & CMD_T_ABORTED) { | 2769 | if (!send_status || (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS)) |
| 3050 | if (!send_status || | 2770 | return 1; |
| 3051 | (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS)) | ||
| 3052 | return 1; | ||
| 3053 | 2771 | ||
| 3054 | pr_debug("Sending delayed SAM_STAT_TASK_ABORTED" | 2772 | pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n", |
| 3055 | " status for CDB: 0x%02x ITT: 0x%08x\n", | 2773 | cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); |
| 3056 | cmd->t_task_cdb[0], | ||
| 3057 | cmd->se_tfo->get_task_tag(cmd)); | ||
| 3058 | 2774 | ||
| 3059 | cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; | 2775 | cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; |
| 3060 | cmd->se_tfo->queue_status(cmd); | 2776 | cmd->se_tfo->queue_status(cmd); |
| 3061 | ret = 1; | 2777 | |
| 3062 | } | 2778 | return 1; |
| 3063 | return ret; | ||
| 3064 | } | 2779 | } |
| 3065 | EXPORT_SYMBOL(transport_check_aborted_status); | 2780 | EXPORT_SYMBOL(transport_check_aborted_status); |
| 3066 | 2781 | ||
diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 6666a0c74f60..bf0e390ce2d7 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c | |||
| @@ -3,8 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file contains logic for SPC-3 Unit Attention emulation | 4 | * This file contains logic for SPC-3 Unit Attention emulation |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2009,2010 Rising Tide Systems | 6 | * (c) Copyright 2009-2012 RisingTide Systems LLC. |
| 7 | * Copyright (c) 2009,2010 Linux-iSCSI.org | ||
| 8 | * | 7 | * |
| 9 | * Nicholas A. Bellinger <nab@kernel.org> | 8 | * Nicholas A. Bellinger <nab@kernel.org> |
| 10 | * | 9 | * |
| @@ -38,9 +37,8 @@ | |||
| 38 | #include "target_core_pr.h" | 37 | #include "target_core_pr.h" |
| 39 | #include "target_core_ua.h" | 38 | #include "target_core_ua.h" |
| 40 | 39 | ||
| 41 | int core_scsi3_ua_check( | 40 | sense_reason_t |
| 42 | struct se_cmd *cmd, | 41 | target_scsi3_ua_check(struct se_cmd *cmd) |
| 43 | unsigned char *cdb) | ||
| 44 | { | 42 | { |
| 45 | struct se_dev_entry *deve; | 43 | struct se_dev_entry *deve; |
| 46 | struct se_session *sess = cmd->se_sess; | 44 | struct se_session *sess = cmd->se_sess; |
| @@ -71,16 +69,14 @@ int core_scsi3_ua_check( | |||
| 71 | * was received, then the device server shall process the command | 69 | * was received, then the device server shall process the command |
| 72 | * and either: | 70 | * and either: |
| 73 | */ | 71 | */ |
| 74 | switch (cdb[0]) { | 72 | switch (cmd->t_task_cdb[0]) { |
| 75 | case INQUIRY: | 73 | case INQUIRY: |
| 76 | case REPORT_LUNS: | 74 | case REPORT_LUNS: |
| 77 | case REQUEST_SENSE: | 75 | case REQUEST_SENSE: |
| 78 | return 0; | 76 | return 0; |
| 79 | default: | 77 | default: |
| 80 | return -EINVAL; | 78 | return TCM_CHECK_CONDITION_UNIT_ATTENTION; |
| 81 | } | 79 | } |
| 82 | |||
| 83 | return -EINVAL; | ||
| 84 | } | 80 | } |
| 85 | 81 | ||
| 86 | int core_scsi3_ua_allocate( | 82 | int core_scsi3_ua_allocate( |
| @@ -237,7 +233,7 @@ void core_scsi3_ua_for_check_condition( | |||
| 237 | * highest priority UNIT_ATTENTION and ASC/ASCQ without | 233 | * highest priority UNIT_ATTENTION and ASC/ASCQ without |
| 238 | * clearing it. | 234 | * clearing it. |
| 239 | */ | 235 | */ |
| 240 | if (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) { | 236 | if (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) { |
| 241 | *asc = ua->ua_asc; | 237 | *asc = ua->ua_asc; |
| 242 | *ascq = ua->ua_ascq; | 238 | *ascq = ua->ua_ascq; |
| 243 | break; | 239 | break; |
| @@ -265,8 +261,8 @@ void core_scsi3_ua_for_check_condition( | |||
| 265 | " INTLCK_CTRL: %d, mapped LUN: %u, got CDB: 0x%02x" | 261 | " INTLCK_CTRL: %d, mapped LUN: %u, got CDB: 0x%02x" |
| 266 | " reported ASC: 0x%02x, ASCQ: 0x%02x\n", | 262 | " reported ASC: 0x%02x, ASCQ: 0x%02x\n", |
| 267 | nacl->se_tpg->se_tpg_tfo->get_fabric_name(), | 263 | nacl->se_tpg->se_tpg_tfo->get_fabric_name(), |
| 268 | (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : | 264 | (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : |
| 269 | "Releasing", dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl, | 265 | "Releasing", dev->dev_attrib.emulate_ua_intlck_ctrl, |
| 270 | cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq); | 266 | cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq); |
| 271 | } | 267 | } |
| 272 | 268 | ||
diff --git a/drivers/target/target_core_ua.h b/drivers/target/target_core_ua.h index 6e6b03460a1a..0204952fe4d3 100644 --- a/drivers/target/target_core_ua.h +++ b/drivers/target/target_core_ua.h | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | extern struct kmem_cache *se_ua_cache; | 27 | extern struct kmem_cache *se_ua_cache; |
| 28 | 28 | ||
| 29 | extern int core_scsi3_ua_check(struct se_cmd *, unsigned char *); | 29 | extern sense_reason_t target_scsi3_ua_check(struct se_cmd *); |
| 30 | extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8); | 30 | extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8); |
| 31 | extern void core_scsi3_ua_release_all(struct se_dev_entry *); | 31 | extern void core_scsi3_ua_release_all(struct se_dev_entry *); |
| 32 | extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *); | 32 | extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *); |
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 9585010964ec..12d6fa21e5e1 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c | |||
| @@ -430,7 +430,6 @@ static void ft_sess_rcu_free(struct rcu_head *rcu) | |||
| 430 | { | 430 | { |
| 431 | struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); | 431 | struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); |
| 432 | 432 | ||
| 433 | transport_deregister_session(sess->se_sess); | ||
| 434 | kfree(sess); | 433 | kfree(sess); |
| 435 | } | 434 | } |
| 436 | 435 | ||
| @@ -438,6 +437,7 @@ static void ft_sess_free(struct kref *kref) | |||
| 438 | { | 437 | { |
| 439 | struct ft_sess *sess = container_of(kref, struct ft_sess, kref); | 438 | struct ft_sess *sess = container_of(kref, struct ft_sess, kref); |
| 440 | 439 | ||
| 440 | transport_deregister_session(sess->se_sess); | ||
| 441 | call_rcu(&sess->rcu, ft_sess_rcu_free); | 441 | call_rcu(&sess->rcu, ft_sess_rcu_free); |
| 442 | } | 442 | } |
| 443 | 443 | ||
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index d670130ee687..b20df5c829f5 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c | |||
| @@ -538,10 +538,6 @@ static void tcm_vhost_submission_work(struct work_struct *work) | |||
| 538 | 538 | ||
| 539 | if (tv_cmd->tvc_sgl_count) { | 539 | if (tv_cmd->tvc_sgl_count) { |
| 540 | sg_ptr = tv_cmd->tvc_sgl; | 540 | sg_ptr = tv_cmd->tvc_sgl; |
| 541 | /* | ||
| 542 | * For BIDI commands, pass in the extra READ buffer | ||
| 543 | * to transport_generic_map_mem_to_cmd() below.. | ||
| 544 | */ | ||
| 545 | /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ | 541 | /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ |
| 546 | #if 0 | 542 | #if 0 |
| 547 | if (se_cmd->se_cmd_flags & SCF_BIDI) { | 543 | if (se_cmd->se_cmd_flags & SCF_BIDI) { |
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 2acd54018b64..507910992c59 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h | |||
| @@ -9,6 +9,8 @@ struct se_subsystem_api { | |||
| 9 | struct list_head sub_api_list; | 9 | struct list_head sub_api_list; |
| 10 | 10 | ||
| 11 | char name[16]; | 11 | char name[16]; |
| 12 | char inquiry_prod[16]; | ||
| 13 | char inquiry_rev[4]; | ||
| 12 | struct module *owner; | 14 | struct module *owner; |
| 13 | 15 | ||
| 14 | u8 transport_type; | 16 | u8 transport_type; |
| @@ -16,46 +18,45 @@ struct se_subsystem_api { | |||
| 16 | int (*attach_hba)(struct se_hba *, u32); | 18 | int (*attach_hba)(struct se_hba *, u32); |
| 17 | void (*detach_hba)(struct se_hba *); | 19 | void (*detach_hba)(struct se_hba *); |
| 18 | int (*pmode_enable_hba)(struct se_hba *, unsigned long); | 20 | int (*pmode_enable_hba)(struct se_hba *, unsigned long); |
| 19 | void *(*allocate_virtdevice)(struct se_hba *, const char *); | 21 | |
| 20 | struct se_device *(*create_virtdevice)(struct se_hba *, | 22 | struct se_device *(*alloc_device)(struct se_hba *, const char *); |
| 21 | struct se_subsystem_dev *, void *); | 23 | int (*configure_device)(struct se_device *); |
| 22 | void (*free_device)(void *); | 24 | void (*free_device)(struct se_device *device); |
| 25 | |||
| 26 | ssize_t (*set_configfs_dev_params)(struct se_device *, | ||
| 27 | const char *, ssize_t); | ||
| 28 | ssize_t (*show_configfs_dev_params)(struct se_device *, char *); | ||
| 29 | |||
| 23 | void (*transport_complete)(struct se_cmd *cmd, | 30 | void (*transport_complete)(struct se_cmd *cmd, |
| 24 | struct scatterlist *, | 31 | struct scatterlist *, |
| 25 | unsigned char *); | 32 | unsigned char *); |
| 26 | 33 | ||
| 27 | int (*parse_cdb)(struct se_cmd *cmd); | 34 | sense_reason_t (*parse_cdb)(struct se_cmd *cmd); |
| 28 | ssize_t (*check_configfs_dev_params)(struct se_hba *, | ||
| 29 | struct se_subsystem_dev *); | ||
| 30 | ssize_t (*set_configfs_dev_params)(struct se_hba *, | ||
| 31 | struct se_subsystem_dev *, const char *, ssize_t); | ||
| 32 | ssize_t (*show_configfs_dev_params)(struct se_hba *, | ||
| 33 | struct se_subsystem_dev *, char *); | ||
| 34 | u32 (*get_device_rev)(struct se_device *); | ||
| 35 | u32 (*get_device_type)(struct se_device *); | 35 | u32 (*get_device_type)(struct se_device *); |
| 36 | sector_t (*get_blocks)(struct se_device *); | 36 | sector_t (*get_blocks)(struct se_device *); |
| 37 | unsigned char *(*get_sense_buffer)(struct se_cmd *); | 37 | unsigned char *(*get_sense_buffer)(struct se_cmd *); |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | struct spc_ops { | 40 | struct sbc_ops { |
| 41 | int (*execute_rw)(struct se_cmd *cmd); | 41 | sense_reason_t (*execute_rw)(struct se_cmd *cmd); |
| 42 | int (*execute_sync_cache)(struct se_cmd *cmd); | 42 | sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); |
| 43 | int (*execute_write_same)(struct se_cmd *cmd); | 43 | sense_reason_t (*execute_write_same)(struct se_cmd *cmd); |
| 44 | int (*execute_unmap)(struct se_cmd *cmd); | 44 | sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd); |
| 45 | sense_reason_t (*execute_unmap)(struct se_cmd *cmd); | ||
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | int transport_subsystem_register(struct se_subsystem_api *); | 48 | int transport_subsystem_register(struct se_subsystem_api *); |
| 48 | void transport_subsystem_release(struct se_subsystem_api *); | 49 | void transport_subsystem_release(struct se_subsystem_api *); |
| 49 | 50 | ||
| 50 | struct se_device *transport_add_device_to_core_hba(struct se_hba *, | ||
| 51 | struct se_subsystem_api *, struct se_subsystem_dev *, u32, | ||
| 52 | void *, struct se_dev_limits *, const char *, const char *); | ||
| 53 | |||
| 54 | void target_complete_cmd(struct se_cmd *, u8); | 51 | void target_complete_cmd(struct se_cmd *, u8); |
| 55 | 52 | ||
| 56 | int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops); | 53 | sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); |
| 57 | int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); | 54 | sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd); |
| 58 | int spc_get_write_same_sectors(struct se_cmd *cmd); | 55 | sector_t spc_get_write_same_sectors(struct se_cmd *cmd); |
| 56 | |||
| 57 | sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); | ||
| 58 | u32 sbc_get_device_rev(struct se_device *dev); | ||
| 59 | u32 sbc_get_device_type(struct se_device *dev); | ||
| 59 | 60 | ||
| 60 | void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); | 61 | void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); |
| 61 | int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); | 62 | int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5be89373ceac..7cae2360221e 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
| @@ -62,20 +62,6 @@ | |||
| 62 | 62 | ||
| 63 | #define PYX_TRANSPORT_STATUS_INTERVAL 5 /* In seconds */ | 63 | #define PYX_TRANSPORT_STATUS_INTERVAL 5 /* In seconds */ |
| 64 | 64 | ||
| 65 | /* | ||
| 66 | * struct se_subsystem_dev->su_dev_flags | ||
| 67 | */ | ||
| 68 | #define SDF_FIRMWARE_VPD_UNIT_SERIAL 0x00000001 | ||
| 69 | #define SDF_EMULATED_VPD_UNIT_SERIAL 0x00000002 | ||
| 70 | #define SDF_USING_UDEV_PATH 0x00000004 | ||
| 71 | #define SDF_USING_ALIAS 0x00000008 | ||
| 72 | |||
| 73 | /* | ||
| 74 | * struct se_device->dev_flags | ||
| 75 | */ | ||
| 76 | #define DF_SPC2_RESERVATIONS 0x00000001 | ||
| 77 | #define DF_SPC2_RESERVATIONS_WITH_ISID 0x00000002 | ||
| 78 | |||
| 79 | /* struct se_dev_attrib sanity values */ | 65 | /* struct se_dev_attrib sanity values */ |
| 80 | /* Default max_unmap_lba_count */ | 66 | /* Default max_unmap_lba_count */ |
| 81 | #define DA_MAX_UNMAP_LBA_COUNT 0 | 67 | #define DA_MAX_UNMAP_LBA_COUNT 0 |
| @@ -85,6 +71,8 @@ | |||
| 85 | #define DA_UNMAP_GRANULARITY_DEFAULT 0 | 71 | #define DA_UNMAP_GRANULARITY_DEFAULT 0 |
| 86 | /* Default unmap_granularity_alignment */ | 72 | /* Default unmap_granularity_alignment */ |
| 87 | #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0 | 73 | #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0 |
| 74 | /* Default max_write_same_len, disabled by default */ | ||
| 75 | #define DA_MAX_WRITE_SAME_LEN 0 | ||
| 88 | /* Default max transfer length */ | 76 | /* Default max transfer length */ |
| 89 | #define DA_FABRIC_MAX_SECTORS 8192 | 77 | #define DA_FABRIC_MAX_SECTORS 8192 |
| 90 | /* Emulation for Direct Page Out */ | 78 | /* Emulation for Direct Page Out */ |
| @@ -107,8 +95,6 @@ | |||
| 107 | */ | 95 | */ |
| 108 | #define DA_EMULATE_TPWS 0 | 96 | #define DA_EMULATE_TPWS 0 |
| 109 | /* No Emulation for PSCSI by default */ | 97 | /* No Emulation for PSCSI by default */ |
| 110 | #define DA_EMULATE_RESERVATIONS 0 | ||
| 111 | /* No Emulation for PSCSI by default */ | ||
| 112 | #define DA_EMULATE_ALUA 0 | 98 | #define DA_EMULATE_ALUA 0 |
| 113 | /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */ | 99 | /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */ |
| 114 | #define DA_ENFORCE_PR_ISIDS 1 | 100 | #define DA_ENFORCE_PR_ISIDS 1 |
| @@ -160,8 +146,6 @@ enum se_cmd_flags_table { | |||
| 160 | SCF_EMULATED_TASK_SENSE = 0x00000004, | 146 | SCF_EMULATED_TASK_SENSE = 0x00000004, |
| 161 | SCF_SCSI_DATA_CDB = 0x00000008, | 147 | SCF_SCSI_DATA_CDB = 0x00000008, |
| 162 | SCF_SCSI_TMR_CDB = 0x00000010, | 148 | SCF_SCSI_TMR_CDB = 0x00000010, |
| 163 | SCF_SCSI_CDB_EXCEPTION = 0x00000020, | ||
| 164 | SCF_SCSI_RESERVATION_CONFLICT = 0x00000040, | ||
| 165 | SCF_FUA = 0x00000080, | 149 | SCF_FUA = 0x00000080, |
| 166 | SCF_SE_LUN_CMD = 0x00000100, | 150 | SCF_SE_LUN_CMD = 0x00000100, |
| 167 | SCF_BIDI = 0x00000400, | 151 | SCF_BIDI = 0x00000400, |
| @@ -182,38 +166,33 @@ enum transport_lunflags_table { | |||
| 182 | TRANSPORT_LUNFLAGS_READ_WRITE = 0x04, | 166 | TRANSPORT_LUNFLAGS_READ_WRITE = 0x04, |
| 183 | }; | 167 | }; |
| 184 | 168 | ||
| 185 | /* struct se_device->dev_status */ | ||
| 186 | enum transport_device_status_table { | ||
| 187 | TRANSPORT_DEVICE_ACTIVATED = 0x01, | ||
| 188 | TRANSPORT_DEVICE_DEACTIVATED = 0x02, | ||
| 189 | TRANSPORT_DEVICE_QUEUE_FULL = 0x04, | ||
| 190 | TRANSPORT_DEVICE_SHUTDOWN = 0x08, | ||
| 191 | TRANSPORT_DEVICE_OFFLINE_ACTIVATED = 0x10, | ||
| 192 | TRANSPORT_DEVICE_OFFLINE_DEACTIVATED = 0x20, | ||
| 193 | }; | ||
| 194 | |||
| 195 | /* | 169 | /* |
| 196 | * Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason | 170 | * Used by transport_send_check_condition_and_sense() |
| 197 | * to signal which ASC/ASCQ sense payload should be built. | 171 | * to signal which ASC/ASCQ sense payload should be built. |
| 198 | */ | 172 | */ |
| 173 | typedef unsigned __bitwise__ sense_reason_t; | ||
| 174 | |||
| 199 | enum tcm_sense_reason_table { | 175 | enum tcm_sense_reason_table { |
| 200 | TCM_NON_EXISTENT_LUN = 0x01, | 176 | #define R(x) (__force sense_reason_t )(x) |
| 201 | TCM_UNSUPPORTED_SCSI_OPCODE = 0x02, | 177 | TCM_NON_EXISTENT_LUN = R(0x01), |
| 202 | TCM_INCORRECT_AMOUNT_OF_DATA = 0x03, | 178 | TCM_UNSUPPORTED_SCSI_OPCODE = R(0x02), |
| 203 | TCM_UNEXPECTED_UNSOLICITED_DATA = 0x04, | 179 | TCM_INCORRECT_AMOUNT_OF_DATA = R(0x03), |
| 204 | TCM_SERVICE_CRC_ERROR = 0x05, | 180 | TCM_UNEXPECTED_UNSOLICITED_DATA = R(0x04), |
| 205 | TCM_SNACK_REJECTED = 0x06, | 181 | TCM_SERVICE_CRC_ERROR = R(0x05), |
| 206 | TCM_SECTOR_COUNT_TOO_MANY = 0x07, | 182 | TCM_SNACK_REJECTED = R(0x06), |
| 207 | TCM_INVALID_CDB_FIELD = 0x08, | 183 | TCM_SECTOR_COUNT_TOO_MANY = R(0x07), |
| 208 | TCM_INVALID_PARAMETER_LIST = 0x09, | 184 | TCM_INVALID_CDB_FIELD = R(0x08), |
| 209 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = 0x0a, | 185 | TCM_INVALID_PARAMETER_LIST = R(0x09), |
| 210 | TCM_UNKNOWN_MODE_PAGE = 0x0b, | 186 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = R(0x0a), |
| 211 | TCM_WRITE_PROTECTED = 0x0c, | 187 | TCM_UNKNOWN_MODE_PAGE = R(0x0b), |
| 212 | TCM_CHECK_CONDITION_ABORT_CMD = 0x0d, | 188 | TCM_WRITE_PROTECTED = R(0x0c), |
| 213 | TCM_CHECK_CONDITION_UNIT_ATTENTION = 0x0e, | 189 | TCM_CHECK_CONDITION_ABORT_CMD = R(0x0d), |
| 214 | TCM_CHECK_CONDITION_NOT_READY = 0x0f, | 190 | TCM_CHECK_CONDITION_UNIT_ATTENTION = R(0x0e), |
| 215 | TCM_RESERVATION_CONFLICT = 0x10, | 191 | TCM_CHECK_CONDITION_NOT_READY = R(0x0f), |
| 216 | TCM_ADDRESS_OUT_OF_RANGE = 0x11, | 192 | TCM_RESERVATION_CONFLICT = R(0x10), |
| 193 | TCM_ADDRESS_OUT_OF_RANGE = R(0x11), | ||
| 194 | TCM_OUT_OF_RESOURCES = R(0x12), | ||
| 195 | #undef R | ||
| 217 | }; | 196 | }; |
| 218 | 197 | ||
| 219 | enum target_sc_flags_table { | 198 | enum target_sc_flags_table { |
| @@ -246,30 +225,6 @@ enum tcm_tmrsp_table { | |||
| 246 | TMR_FUNCTION_REJECTED = 255, | 225 | TMR_FUNCTION_REJECTED = 255, |
| 247 | }; | 226 | }; |
| 248 | 227 | ||
| 249 | struct se_obj { | ||
| 250 | atomic_t obj_access_count; | ||
| 251 | }; | ||
| 252 | |||
| 253 | /* | ||
| 254 | * Used by TCM Core internally to signal if ALUA emulation is enabled or | ||
| 255 | * disabled, or running in with TCM/pSCSI passthrough mode | ||
| 256 | */ | ||
| 257 | typedef enum { | ||
| 258 | SPC_ALUA_PASSTHROUGH, | ||
| 259 | SPC2_ALUA_DISABLED, | ||
| 260 | SPC3_ALUA_EMULATED | ||
| 261 | } t10_alua_index_t; | ||
| 262 | |||
| 263 | /* | ||
| 264 | * Used by TCM Core internally to signal if SAM Task Attribute emulation | ||
| 265 | * is enabled or disabled, or running in with TCM/pSCSI passthrough mode | ||
| 266 | */ | ||
| 267 | typedef enum { | ||
| 268 | SAM_TASK_ATTR_PASSTHROUGH, | ||
| 269 | SAM_TASK_ATTR_UNTAGGED, | ||
| 270 | SAM_TASK_ATTR_EMULATED | ||
| 271 | } t10_task_attr_index_t; | ||
| 272 | |||
| 273 | /* | 228 | /* |
| 274 | * Used for target SCSI statistics | 229 | * Used for target SCSI statistics |
| 275 | */ | 230 | */ |
| @@ -283,17 +238,15 @@ typedef enum { | |||
| 283 | struct se_cmd; | 238 | struct se_cmd; |
| 284 | 239 | ||
| 285 | struct t10_alua { | 240 | struct t10_alua { |
| 286 | t10_alua_index_t alua_type; | ||
| 287 | /* ALUA Target Port Group ID */ | 241 | /* ALUA Target Port Group ID */ |
| 288 | u16 alua_tg_pt_gps_counter; | 242 | u16 alua_tg_pt_gps_counter; |
| 289 | u32 alua_tg_pt_gps_count; | 243 | u32 alua_tg_pt_gps_count; |
| 290 | spinlock_t tg_pt_gps_lock; | 244 | spinlock_t tg_pt_gps_lock; |
| 291 | struct se_subsystem_dev *t10_sub_dev; | 245 | struct se_device *t10_dev; |
| 292 | /* Used for default ALUA Target Port Group */ | 246 | /* Used for default ALUA Target Port Group */ |
| 293 | struct t10_alua_tg_pt_gp *default_tg_pt_gp; | 247 | struct t10_alua_tg_pt_gp *default_tg_pt_gp; |
| 294 | /* Used for default ALUA Target Port Group ConfigFS group */ | 248 | /* Used for default ALUA Target Port Group ConfigFS group */ |
| 295 | struct config_group alua_tg_pt_gps_group; | 249 | struct config_group alua_tg_pt_gps_group; |
| 296 | int (*alua_state_check)(struct se_cmd *, unsigned char *, u8 *); | ||
| 297 | struct list_head tg_pt_gps_list; | 250 | struct list_head tg_pt_gps_list; |
| 298 | }; | 251 | }; |
| 299 | 252 | ||
| @@ -335,7 +288,7 @@ struct t10_alua_tg_pt_gp { | |||
| 335 | atomic_t tg_pt_gp_ref_cnt; | 288 | atomic_t tg_pt_gp_ref_cnt; |
| 336 | spinlock_t tg_pt_gp_lock; | 289 | spinlock_t tg_pt_gp_lock; |
| 337 | struct mutex tg_pt_gp_md_mutex; | 290 | struct mutex tg_pt_gp_md_mutex; |
| 338 | struct se_subsystem_dev *tg_pt_gp_su_dev; | 291 | struct se_device *tg_pt_gp_dev; |
| 339 | struct config_group tg_pt_gp_group; | 292 | struct config_group tg_pt_gp_group; |
| 340 | struct list_head tg_pt_gp_list; | 293 | struct list_head tg_pt_gp_list; |
| 341 | struct list_head tg_pt_gp_mem_list; | 294 | struct list_head tg_pt_gp_mem_list; |
| @@ -366,23 +319,11 @@ struct t10_wwn { | |||
| 366 | char revision[4]; | 319 | char revision[4]; |
| 367 | char unit_serial[INQUIRY_VPD_SERIAL_LEN]; | 320 | char unit_serial[INQUIRY_VPD_SERIAL_LEN]; |
| 368 | spinlock_t t10_vpd_lock; | 321 | spinlock_t t10_vpd_lock; |
| 369 | struct se_subsystem_dev *t10_sub_dev; | 322 | struct se_device *t10_dev; |
| 370 | struct config_group t10_wwn_group; | 323 | struct config_group t10_wwn_group; |
| 371 | struct list_head t10_vpd_list; | 324 | struct list_head t10_vpd_list; |
| 372 | }; | 325 | }; |
| 373 | 326 | ||
| 374 | |||
| 375 | /* | ||
| 376 | * Used by TCM Core internally to signal if >= SPC-3 persistent reservations | ||
| 377 | * emulation is enabled or disabled, or running in with TCM/pSCSI passthrough | ||
| 378 | * mode | ||
| 379 | */ | ||
| 380 | typedef enum { | ||
| 381 | SPC_PASSTHROUGH, | ||
| 382 | SPC2_RESERVATIONS, | ||
| 383 | SPC3_PERSISTENT_RESERVATIONS | ||
| 384 | } t10_reservations_index_t; | ||
| 385 | |||
| 386 | struct t10_pr_registration { | 327 | struct t10_pr_registration { |
| 387 | /* Used for fabrics that contain WWN+ISID */ | 328 | /* Used for fabrics that contain WWN+ISID */ |
| 388 | #define PR_REG_ISID_LEN 16 | 329 | #define PR_REG_ISID_LEN 16 |
| @@ -424,18 +365,6 @@ struct t10_pr_registration { | |||
| 424 | struct list_head pr_reg_atp_mem_list; | 365 | struct list_head pr_reg_atp_mem_list; |
| 425 | }; | 366 | }; |
| 426 | 367 | ||
| 427 | /* | ||
| 428 | * This set of function pointer ops is set based upon SPC3_PERSISTENT_RESERVATIONS, | ||
| 429 | * SPC2_RESERVATIONS or SPC_PASSTHROUGH in drivers/target/target_core_pr.c: | ||
| 430 | * core_setup_reservations() | ||
| 431 | */ | ||
| 432 | struct t10_reservation_ops { | ||
| 433 | int (*t10_reservation_check)(struct se_cmd *, u32 *); | ||
| 434 | int (*t10_seq_non_holder)(struct se_cmd *, unsigned char *, u32); | ||
| 435 | int (*t10_pr_register)(struct se_cmd *); | ||
| 436 | int (*t10_pr_clear)(struct se_cmd *); | ||
| 437 | }; | ||
| 438 | |||
| 439 | struct t10_reservation { | 368 | struct t10_reservation { |
| 440 | /* Reservation effects all target ports */ | 369 | /* Reservation effects all target ports */ |
| 441 | int pr_all_tg_pt; | 370 | int pr_all_tg_pt; |
| @@ -446,7 +375,6 @@ struct t10_reservation { | |||
| 446 | #define PR_APTPL_BUF_LEN 8192 | 375 | #define PR_APTPL_BUF_LEN 8192 |
| 447 | u32 pr_aptpl_buf_len; | 376 | u32 pr_aptpl_buf_len; |
| 448 | u32 pr_generation; | 377 | u32 pr_generation; |
| 449 | t10_reservations_index_t res_type; | ||
| 450 | spinlock_t registration_lock; | 378 | spinlock_t registration_lock; |
| 451 | spinlock_t aptpl_reg_lock; | 379 | spinlock_t aptpl_reg_lock; |
| 452 | /* | 380 | /* |
| @@ -462,7 +390,6 @@ struct t10_reservation { | |||
| 462 | struct se_node_acl *pr_res_holder; | 390 | struct se_node_acl *pr_res_holder; |
| 463 | struct list_head registration_list; | 391 | struct list_head registration_list; |
| 464 | struct list_head aptpl_reg_list; | 392 | struct list_head aptpl_reg_list; |
| 465 | struct t10_reservation_ops pr_ops; | ||
| 466 | }; | 393 | }; |
| 467 | 394 | ||
| 468 | struct se_tmr_req { | 395 | struct se_tmr_req { |
| @@ -485,7 +412,6 @@ struct se_cmd { | |||
| 485 | u8 scsi_status; | 412 | u8 scsi_status; |
| 486 | u8 scsi_asc; | 413 | u8 scsi_asc; |
| 487 | u8 scsi_ascq; | 414 | u8 scsi_ascq; |
| 488 | u8 scsi_sense_reason; | ||
| 489 | u16 scsi_sense_length; | 415 | u16 scsi_sense_length; |
| 490 | /* Delay for ALUA Active/NonOptimized state access in milliseconds */ | 416 | /* Delay for ALUA Active/NonOptimized state access in milliseconds */ |
| 491 | int alua_nonop_delay; | 417 | int alua_nonop_delay; |
| @@ -523,7 +449,7 @@ struct se_cmd { | |||
| 523 | struct completion cmd_wait_comp; | 449 | struct completion cmd_wait_comp; |
| 524 | struct kref cmd_kref; | 450 | struct kref cmd_kref; |
| 525 | struct target_core_fabric_ops *se_tfo; | 451 | struct target_core_fabric_ops *se_tfo; |
| 526 | int (*execute_cmd)(struct se_cmd *); | 452 | sense_reason_t (*execute_cmd)(struct se_cmd *); |
| 527 | void (*transport_complete_callback)(struct se_cmd *); | 453 | void (*transport_complete_callback)(struct se_cmd *); |
| 528 | 454 | ||
| 529 | unsigned char *t_task_cdb; | 455 | unsigned char *t_task_cdb; |
| @@ -581,6 +507,8 @@ struct se_node_acl { | |||
| 581 | bool acl_stop:1; | 507 | bool acl_stop:1; |
| 582 | u32 queue_depth; | 508 | u32 queue_depth; |
| 583 | u32 acl_index; | 509 | u32 acl_index; |
| 510 | #define MAX_ACL_TAG_SIZE 64 | ||
| 511 | char acl_tag[MAX_ACL_TAG_SIZE]; | ||
| 584 | u64 num_cmds; | 512 | u64 num_cmds; |
| 585 | u64 read_bytes; | 513 | u64 read_bytes; |
| 586 | u64 write_bytes; | 514 | u64 write_bytes; |
| @@ -662,15 +590,6 @@ struct se_dev_entry { | |||
| 662 | struct list_head ua_list; | 590 | struct list_head ua_list; |
| 663 | }; | 591 | }; |
| 664 | 592 | ||
| 665 | struct se_dev_limits { | ||
| 666 | /* Max supported HW queue depth */ | ||
| 667 | u32 hw_queue_depth; | ||
| 668 | /* Max supported virtual queue depth */ | ||
| 669 | u32 queue_depth; | ||
| 670 | /* From include/linux/blkdev.h for the other HW/SW limits. */ | ||
| 671 | struct queue_limits limits; | ||
| 672 | }; | ||
| 673 | |||
| 674 | struct se_dev_attrib { | 593 | struct se_dev_attrib { |
| 675 | int emulate_dpo; | 594 | int emulate_dpo; |
| 676 | int emulate_fua_write; | 595 | int emulate_fua_write; |
| @@ -680,8 +599,6 @@ struct se_dev_attrib { | |||
| 680 | int emulate_tas; | 599 | int emulate_tas; |
| 681 | int emulate_tpu; | 600 | int emulate_tpu; |
| 682 | int emulate_tpws; | 601 | int emulate_tpws; |
| 683 | int emulate_reservations; | ||
| 684 | int emulate_alua; | ||
| 685 | int enforce_pr_isids; | 602 | int enforce_pr_isids; |
| 686 | int is_nonrot; | 603 | int is_nonrot; |
| 687 | int emulate_rest_reord; | 604 | int emulate_rest_reord; |
| @@ -696,7 +613,8 @@ struct se_dev_attrib { | |||
| 696 | u32 max_unmap_block_desc_count; | 613 | u32 max_unmap_block_desc_count; |
| 697 | u32 unmap_granularity; | 614 | u32 unmap_granularity; |
| 698 | u32 unmap_granularity_alignment; | 615 | u32 unmap_granularity_alignment; |
| 699 | struct se_subsystem_dev *da_sub_dev; | 616 | u32 max_write_same_len; |
| 617 | struct se_device *da_dev; | ||
| 700 | struct config_group da_group; | 618 | struct config_group da_group; |
| 701 | }; | 619 | }; |
| 702 | 620 | ||
| @@ -707,48 +625,25 @@ struct se_dev_stat_grps { | |||
| 707 | struct config_group scsi_lu_group; | 625 | struct config_group scsi_lu_group; |
| 708 | }; | 626 | }; |
| 709 | 627 | ||
| 710 | struct se_subsystem_dev { | ||
| 711 | /* Used for struct se_subsystem_dev-->se_dev_alias, must be less than PAGE_SIZE */ | ||
| 712 | #define SE_DEV_ALIAS_LEN 512 | ||
| 713 | unsigned char se_dev_alias[SE_DEV_ALIAS_LEN]; | ||
| 714 | /* Used for struct se_subsystem_dev->se_dev_udev_path[], must be less than PAGE_SIZE */ | ||
| 715 | #define SE_UDEV_PATH_LEN 512 | ||
| 716 | unsigned char se_dev_udev_path[SE_UDEV_PATH_LEN]; | ||
| 717 | u32 su_dev_flags; | ||
| 718 | struct se_hba *se_dev_hba; | ||
| 719 | struct se_device *se_dev_ptr; | ||
| 720 | struct se_dev_attrib se_dev_attrib; | ||
| 721 | /* T10 Asymmetric Logical Unit Assignment for Target Ports */ | ||
| 722 | struct t10_alua t10_alua; | ||
| 723 | /* T10 Inquiry and VPD WWN Information */ | ||
| 724 | struct t10_wwn t10_wwn; | ||
| 725 | /* T10 SPC-2 + SPC-3 Reservations */ | ||
| 726 | struct t10_reservation t10_pr; | ||
| 727 | spinlock_t se_dev_lock; | ||
| 728 | void *se_dev_su_ptr; | ||
| 729 | struct config_group se_dev_group; | ||
| 730 | /* For T10 Reservations */ | ||
| 731 | struct config_group se_dev_pr_group; | ||
| 732 | /* For target_core_stat.c groups */ | ||
| 733 | struct se_dev_stat_grps dev_stat_grps; | ||
| 734 | }; | ||
| 735 | |||
| 736 | struct se_device { | 628 | struct se_device { |
| 629 | #define SE_DEV_LINK_MAGIC 0xfeeddeef | ||
| 630 | u32 dev_link_magic; | ||
| 737 | /* RELATIVE TARGET PORT IDENTIFER Counter */ | 631 | /* RELATIVE TARGET PORT IDENTIFER Counter */ |
| 738 | u16 dev_rpti_counter; | 632 | u16 dev_rpti_counter; |
| 739 | /* Used for SAM Task Attribute ordering */ | 633 | /* Used for SAM Task Attribute ordering */ |
| 740 | u32 dev_cur_ordered_id; | 634 | u32 dev_cur_ordered_id; |
| 741 | u32 dev_flags; | 635 | u32 dev_flags; |
| 636 | #define DF_CONFIGURED 0x00000001 | ||
| 637 | #define DF_FIRMWARE_VPD_UNIT_SERIAL 0x00000002 | ||
| 638 | #define DF_EMULATED_VPD_UNIT_SERIAL 0x00000004 | ||
| 639 | #define DF_USING_UDEV_PATH 0x00000008 | ||
| 640 | #define DF_USING_ALIAS 0x00000010 | ||
| 742 | u32 dev_port_count; | 641 | u32 dev_port_count; |
| 743 | /* See transport_device_status_table */ | ||
| 744 | u32 dev_status; | ||
| 745 | /* Physical device queue depth */ | 642 | /* Physical device queue depth */ |
| 746 | u32 queue_depth; | 643 | u32 queue_depth; |
| 747 | /* Used for SPC-2 reservations enforce of ISIDs */ | 644 | /* Used for SPC-2 reservations enforce of ISIDs */ |
| 748 | u64 dev_res_bin_isid; | 645 | u64 dev_res_bin_isid; |
| 749 | t10_task_attr_index_t dev_task_attr_type; | ||
| 750 | /* Pointer to transport specific device structure */ | 646 | /* Pointer to transport specific device structure */ |
| 751 | void *dev_ptr; | ||
| 752 | u32 dev_index; | 647 | u32 dev_index; |
| 753 | u64 creation_time; | 648 | u64 creation_time; |
| 754 | u32 num_resets; | 649 | u32 num_resets; |
| @@ -761,13 +656,13 @@ struct se_device { | |||
| 761 | atomic_t dev_ordered_id; | 656 | atomic_t dev_ordered_id; |
| 762 | atomic_t dev_ordered_sync; | 657 | atomic_t dev_ordered_sync; |
| 763 | atomic_t dev_qf_count; | 658 | atomic_t dev_qf_count; |
| 764 | struct se_obj dev_obj; | 659 | int export_count; |
| 765 | struct se_obj dev_access_obj; | ||
| 766 | struct se_obj dev_export_obj; | ||
| 767 | spinlock_t delayed_cmd_lock; | 660 | spinlock_t delayed_cmd_lock; |
| 768 | spinlock_t execute_task_lock; | 661 | spinlock_t execute_task_lock; |
| 769 | spinlock_t dev_reservation_lock; | 662 | spinlock_t dev_reservation_lock; |
| 770 | spinlock_t dev_status_lock; | 663 | unsigned int dev_reservation_flags; |
| 664 | #define DRF_SPC2_RESERVATIONS 0x00000001 | ||
| 665 | #define DRF_SPC2_RESERVATIONS_WITH_ISID 0x00000002 | ||
| 771 | spinlock_t se_port_lock; | 666 | spinlock_t se_port_lock; |
| 772 | spinlock_t se_tmr_lock; | 667 | spinlock_t se_tmr_lock; |
| 773 | spinlock_t qf_cmd_lock; | 668 | spinlock_t qf_cmd_lock; |
| @@ -786,7 +681,20 @@ struct se_device { | |||
| 786 | struct list_head qf_cmd_list; | 681 | struct list_head qf_cmd_list; |
| 787 | /* Pointer to associated SE HBA */ | 682 | /* Pointer to associated SE HBA */ |
| 788 | struct se_hba *se_hba; | 683 | struct se_hba *se_hba; |
| 789 | struct se_subsystem_dev *se_sub_dev; | 684 | /* T10 Inquiry and VPD WWN Information */ |
| 685 | struct t10_wwn t10_wwn; | ||
| 686 | /* T10 Asymmetric Logical Unit Assignment for Target Ports */ | ||
| 687 | struct t10_alua t10_alua; | ||
| 688 | /* T10 SPC-2 + SPC-3 Reservations */ | ||
| 689 | struct t10_reservation t10_pr; | ||
| 690 | struct se_dev_attrib dev_attrib; | ||
| 691 | struct config_group dev_group; | ||
| 692 | struct config_group dev_pr_group; | ||
| 693 | struct se_dev_stat_grps dev_stat_grps; | ||
| 694 | #define SE_DEV_ALIAS_LEN 512 /* must be less than PAGE_SIZE */ | ||
| 695 | unsigned char dev_alias[SE_DEV_ALIAS_LEN]; | ||
| 696 | #define SE_UDEV_PATH_LEN 512 /* must be less than PAGE_SIZE */ | ||
| 697 | unsigned char udev_path[SE_UDEV_PATH_LEN]; | ||
| 790 | /* Pointer to template of function pointers for transport */ | 698 | /* Pointer to template of function pointers for transport */ |
| 791 | struct se_subsystem_api *transport; | 699 | struct se_subsystem_api *transport; |
| 792 | /* Linked list for struct se_hba struct se_device list */ | 700 | /* Linked list for struct se_hba struct se_device list */ |
| @@ -803,8 +711,6 @@ struct se_hba { | |||
| 803 | u32 hba_index; | 711 | u32 hba_index; |
| 804 | /* Pointer to transport specific host structure. */ | 712 | /* Pointer to transport specific host structure. */ |
| 805 | void *hba_ptr; | 713 | void *hba_ptr; |
| 806 | /* Linked list for struct se_device */ | ||
| 807 | struct list_head hba_dev_list; | ||
| 808 | struct list_head hba_node; | 714 | struct list_head hba_node; |
| 809 | spinlock_t device_lock; | 715 | spinlock_t device_lock; |
| 810 | struct config_group hba_group; | 716 | struct config_group hba_group; |
| @@ -820,6 +726,8 @@ struct se_port_stat_grps { | |||
| 820 | }; | 726 | }; |
| 821 | 727 | ||
| 822 | struct se_lun { | 728 | struct se_lun { |
| 729 | #define SE_LUN_LINK_MAGIC 0xffff7771 | ||
| 730 | u32 lun_link_magic; | ||
| 823 | /* See transport_lun_status_table */ | 731 | /* See transport_lun_status_table */ |
| 824 | enum transport_lun_status_table lun_status; | 732 | enum transport_lun_status_table lun_status; |
| 825 | u32 lun_access; | 733 | u32 lun_access; |
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 81ddb4ae6c3f..aaa1ee6ab391 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h | |||
| @@ -98,8 +98,8 @@ void transport_deregister_session(struct se_session *); | |||
| 98 | 98 | ||
| 99 | void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, | 99 | void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, |
| 100 | struct se_session *, u32, int, int, unsigned char *); | 100 | struct se_session *, u32, int, int, unsigned char *); |
| 101 | int transport_lookup_cmd_lun(struct se_cmd *, u32); | 101 | sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32); |
| 102 | int target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); | 102 | sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); |
| 103 | int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, | 103 | int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, |
| 104 | unsigned char *, unsigned char *, u32, u32, int, int, int, | 104 | unsigned char *, unsigned char *, u32, u32, int, int, int, |
| 105 | struct scatterlist *, u32, struct scatterlist *, u32); | 105 | struct scatterlist *, u32, struct scatterlist *, u32); |
| @@ -110,9 +110,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, | |||
| 110 | void *fabric_tmr_ptr, unsigned char tm_type, | 110 | void *fabric_tmr_ptr, unsigned char tm_type, |
| 111 | gfp_t, unsigned int, int); | 111 | gfp_t, unsigned int, int); |
| 112 | int transport_handle_cdb_direct(struct se_cmd *); | 112 | int transport_handle_cdb_direct(struct se_cmd *); |
| 113 | int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, | 113 | sense_reason_t transport_generic_new_cmd(struct se_cmd *); |
| 114 | struct scatterlist *, u32, struct scatterlist *, u32); | ||
| 115 | int transport_generic_new_cmd(struct se_cmd *); | ||
| 116 | 114 | ||
| 117 | void target_execute_cmd(struct se_cmd *cmd); | 115 | void target_execute_cmd(struct se_cmd *cmd); |
| 118 | 116 | ||
| @@ -120,7 +118,8 @@ void transport_generic_free_cmd(struct se_cmd *, int); | |||
| 120 | 118 | ||
| 121 | bool transport_wait_for_tasks(struct se_cmd *); | 119 | bool transport_wait_for_tasks(struct se_cmd *); |
| 122 | int transport_check_aborted_status(struct se_cmd *, int); | 120 | int transport_check_aborted_status(struct se_cmd *, int); |
| 123 | int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); | 121 | int transport_send_check_condition_and_sense(struct se_cmd *, |
| 122 | sense_reason_t, int); | ||
| 124 | 123 | ||
| 125 | int target_put_sess_cmd(struct se_session *, struct se_cmd *); | 124 | int target_put_sess_cmd(struct se_session *, struct se_cmd *); |
| 126 | void target_sess_cmd_list_set_waiting(struct se_session *); | 125 | void target_sess_cmd_list_set_waiting(struct se_session *); |
| @@ -131,7 +130,7 @@ int core_alua_check_nonop_delay(struct se_cmd *); | |||
| 131 | int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t); | 130 | int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t); |
| 132 | void core_tmr_release_req(struct se_tmr_req *); | 131 | void core_tmr_release_req(struct se_tmr_req *); |
| 133 | int transport_generic_handle_tmr(struct se_cmd *); | 132 | int transport_generic_handle_tmr(struct se_cmd *); |
| 134 | void transport_generic_request_failure(struct se_cmd *); | 133 | void transport_generic_request_failure(struct se_cmd *, sense_reason_t); |
| 135 | int transport_lookup_tmr_lun(struct se_cmd *, u32); | 134 | int transport_lookup_tmr_lun(struct se_cmd *, u32); |
| 136 | 135 | ||
| 137 | struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, | 136 | struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, |
| @@ -143,6 +142,8 @@ int core_tpg_del_initiator_node_acl(struct se_portal_group *, | |||
| 143 | struct se_node_acl *, int); | 142 | struct se_node_acl *, int); |
| 144 | int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *, | 143 | int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *, |
| 145 | unsigned char *, u32, int); | 144 | unsigned char *, u32, int); |
| 145 | int core_tpg_set_initiator_node_tag(struct se_portal_group *, | ||
| 146 | struct se_node_acl *, const char *); | ||
| 146 | int core_tpg_register(struct target_core_fabric_ops *, struct se_wwn *, | 147 | int core_tpg_register(struct target_core_fabric_ops *, struct se_wwn *, |
| 147 | struct se_portal_group *, void *, int); | 148 | struct se_portal_group *, void *, int); |
| 148 | int core_tpg_deregister(struct se_portal_group *); | 149 | int core_tpg_deregister(struct se_portal_group *); |
