Merged revisions 6934-6958 from trunk

------------------------------------------------------------------------
r6934 | mlx-storage | 2016-08-17 10:17:37 +0300 (Wed, 17 Aug 2016) | 4 lines

isert: make sure rdma_disconnect is called only once

------------------------------------------------------------------------
r6935 | mlx-storage | 2016-08-17 10:27:06 +0300 (Wed, 17 Aug 2016) | 8 lines

isert: fix cleaning isert_con_dev

------------------------------------------------------------------------
r6936 | mlx-storage | 2016-08-17 10:27:11 +0300 (Wed, 17 Aug 2016) | 4 lines

isert: add assertions for connection teardwon flow

------------------------------------------------------------------------
r6937 | mlx-storage | 2016-08-17 10:27:15 +0300 (Wed, 17 Aug 2016) | 8 lines

isert: fix a possible extra refcount put of isert connection

------------------------------------------------------------------------
r6938 | mlx-storage | 2016-08-17 10:27:19 +0300 (Wed, 17 Aug 2016) | 4 lines

isert: change wrong dev_conn bug on

------------------------------------------------------------------------
r6939 | mlx-storage | 2016-08-17 10:27:24 +0300 (Wed, 17 Aug 2016) | 6 lines

isert: fix fops ioctl using invalid conn

------------------------------------------------------------------------
r6940 | mlx-storage | 2016-08-17 10:27:28 +0300 (Wed, 17 Aug 2016) | 9 lines

isert: fix race between ioctl events and disconnect flow

------------------------------------------------------------------------
r6941 | mlx-storage | 2016-08-17 10:27:33 +0300 (Wed, 17 Aug 2016) | 7 lines

isert: fix isert conn refcount release at unreachable event

------------------------------------------------------------------------
r6942 | mlx-storage | 2016-08-17 10:27:38 +0300 (Wed, 17 Aug 2016) | 7 lines

isert: fix missing refcount cleanup at error flow

------------------------------------------------------------------------
r6943 | mlx-storage | 2016-08-17 10:27:43 +0300 (Wed, 17 Aug 2016) | 8 lines

isert: add assertion if send/recv was posted after post drain

------------------------------------------------------------------------
r6944 | mlx-storage | 2016-08-17 10:27:48 +0300 (Wed, 17 Aug 2016) | 4 lines

isert: replace kernel prints with scst macros

------------------------------------------------------------------------
r6945 | mlx-storage | 2016-08-17 10:27:53 +0300 (Wed, 17 Aug 2016) | 12 lines

isert: fix a race between timewait exit handler and poll cq

------------------------------------------------------------------------
r6946 | mlx-storage | 2016-08-17 10:27:57 +0300 (Wed, 17 Aug 2016) | 9 lines

isert: fix a race when drain wr is not the last flush

------------------------------------------------------------------------
r6947 | mlx-storage | 2016-08-17 10:28:02 +0300 (Wed, 17 Aug 2016) | 8 lines

isert: fix isert connection kref leak at estabished event handler

------------------------------------------------------------------------
r6948 | mlx-storage | 2016-08-17 10:28:06 +0300 (Wed, 17 Aug 2016) | 7 lines

isert: close isert connection earlier

------------------------------------------------------------------------
r6949 | mlx-storage | 2016-08-17 10:28:11 +0300 (Wed, 17 Aug 2016) | 4 lines

isert: change dev conn_lock spinlock to mutex

------------------------------------------------------------------------
r6950 | mlx-storage | 2016-08-17 10:28:16 +0300 (Wed, 17 Aug 2016) | 13 lines

isert: fix a race between calling to rdma_disconnect and connect flow

------------------------------------------------------------------------
r6951 | mlx-storage | 2016-08-17 10:28:20 +0300 (Wed, 17 Aug 2016) | 8 lines

isert: fix isert connection kref leak

------------------------------------------------------------------------
r6952 | mlx-storage | 2016-08-17 10:28:25 +0300 (Wed, 17 Aug 2016) | 9 lines

isert: faster release of isert_scst module

-----------------------------------------------------------------------
r6953 | mlx-storage | 2016-08-17 10:28:29 +0300 (Wed, 17 Aug 2016) | 9 lines

isert: fix races between conn fops read/write and disconnect flow

------------------------------------------------------------------------
r6954 | mlx-storage | 2016-08-17 10:28:34 +0300 (Wed, 17 Aug 2016) | 4 lines

isert: add missing fd put on error flow

------------------------------------------------------------------------
r6955 | mlx-storage | 2016-08-17 10:28:38 +0300 (Wed, 17 Aug 2016) | 9 lines

isert: fix working with freed conn object

------------------------------------------------------------------------
r6956 | mlx-storage | 2016-08-17 10:28:43 +0300 (Wed, 17 Aug 2016) | 8 lines

isert: fix isert conn cleanup when rdma_accept fails

------------------------------------------------------------------------
r6957 | mlx-storage | 2016-08-17 10:28:47 +0300 (Wed, 17 Aug 2016) | 7 lines

isert: add conn to portal conn list only if rdma_accept succeeded

------------------------------------------------------------------------
r6958 | mlx-storage | 2016-08-17 10:28:52 +0300 (Wed, 17 Aug 2016) | 4 lines

isert: fix redundant module put on error flow when handling connect request

------------------------------------------------------------------------

git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.2.x@6966 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Israel Rukshin
2016-08-21 09:36:18 +00:00
parent 94e0d33e4f
commit 377c61ddd0
11 changed files with 487 additions and 302 deletions

View File

@@ -2035,6 +2035,8 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req)
atomic_inc(&session->active_cmds);
req->dec_active_cmds = 1;
sBUG_ON(session->scst_sess == NULL);
scst_cmd = scst_rx_cmd(session->scst_sess,
(uint8_t *)&req_hdr->lun, sizeof(req_hdr->lun),
req_hdr->scb, sizeof(req_hdr->scb), SCST_NON_ATOMIC);

View File

@@ -63,6 +63,7 @@ struct isert_portal {
/* protected by dev_list_mutex */
struct list_head conn_list; /* head of conns list */
enum isert_portal_state state;
int refcnt;
};
struct isert_buf {
@@ -158,8 +159,11 @@ struct isert_cq {
#define ISERT_CONNECTION_ABORTED 0
#define ISERT_DRAIN_POSTED 1
#define ISERT_DRAIN_FAILED 2
#define ISERT_DISCON_CALLED 3
#define ISERT_DISCON_CALLED 2
#define ISERT_DRAINED_RQ 3
#define ISERT_DRAINED_SQ 4
#define ISERT_CONNECTION_CLOSE 5
#define ISERT_IN_PORTAL_LIST 6
struct isert_connection {
struct iscsi_conn iscsi ____cacheline_aligned;
@@ -185,6 +189,7 @@ struct isert_connection {
struct isert_cq *cq_desc;
enum isert_conn_state state;
struct mutex state_mutex;
u32 responder_resources;
u32 initiator_depth;
@@ -216,7 +221,9 @@ struct isert_connection {
struct work_struct close_work;
struct work_struct drain_work;
struct work_struct discon_work;
struct isert_wr drain_wr;
struct work_struct free_work;
struct isert_wr drain_wr_sq;
struct isert_wr drain_wr_rq;
struct kref kref;
struct isert_portal *portal;
@@ -287,6 +294,7 @@ void isert_free_conn_resources(struct isert_connection *isert_conn);
void isert_conn_free(struct isert_connection *isert_conn);
void isert_conn_disconnect(struct isert_connection *isert_conn);
void isert_post_drain(struct isert_connection *isert_conn);
void isert_sched_conn_free(struct isert_connection *isert_conn);
static inline struct isert_connection *isert_conn_zalloc(void)
{

View File

@@ -52,7 +52,7 @@ static int isert_buf_alloc_pg(struct ib_device *ib_dev,
isert_buf->sg = kmalloc_array(isert_buf->sg_cnt, sizeof(*isert_buf->sg),
GFP_KERNEL);
if (unlikely(!isert_buf->sg)) {
pr_err("Failed to allocate buffer SG\n");
PRINT_ERROR("Failed to allocate buffer SG");
res = -ENOMEM;
goto out;
}
@@ -63,7 +63,7 @@ static int isert_buf_alloc_pg(struct ib_device *ib_dev,
page = alloc_page(GFP_KERNEL);
if (unlikely(!page)) {
pr_err("Failed to allocate page\n");
PRINT_ERROR("Failed to allocate page");
res = -ENOMEM;
goto out_map_failed;
}
@@ -74,8 +74,8 @@ static int isert_buf_alloc_pg(struct ib_device *ib_dev,
res = ib_dma_map_sg(ib_dev, isert_buf->sg, isert_buf->sg_cnt, dma_dir);
if (unlikely(!res)) {
--i; /* do not overrun isert_buf->sg */
pr_err("Failed to DMA map iser sg:%p len:%d\n",
isert_buf->sg, isert_buf->sg_cnt);
PRINT_ERROR("Failed to DMA map iser sg:%p len:%d",
isert_buf->sg, isert_buf->sg_cnt);
res = -ENOMEM;
goto out_map_failed;
}
@@ -111,14 +111,14 @@ static int isert_buf_malloc(struct ib_device *ib_dev,
isert_buf->sg_cnt = 1;
isert_buf->sg = kmalloc(sizeof(isert_buf->sg[0]), GFP_KERNEL);
if (unlikely(!isert_buf->sg)) {
pr_err("Failed to allocate buffer SG\n");
PRINT_ERROR("Failed to allocate buffer SG");
res = -ENOMEM;
goto out;
}
isert_buf->addr = kmalloc(size, GFP_KERNEL);
if (unlikely(!isert_buf->addr)) {
pr_err("Failed to allocate data buffer\n");
PRINT_ERROR("Failed to allocate data buffer");
res = -ENOMEM;
goto data_malloc_failed;
}
@@ -127,8 +127,8 @@ static int isert_buf_malloc(struct ib_device *ib_dev,
res = ib_dma_map_sg(ib_dev, isert_buf->sg, isert_buf->sg_cnt, dma_dir);
if (unlikely(!res)) {
pr_err("Failed to DMA map iser sg:%p len:%d\n",
isert_buf->sg, isert_buf->sg_cnt);
PRINT_ERROR("Failed to DMA map iser sg:%p len:%d",
isert_buf->sg, isert_buf->sg_cnt);
res = -ENOMEM;
goto out_map_failed;
}
@@ -233,7 +233,7 @@ int isert_wr_init(struct isert_wr *wr,
case ISER_WR_RDMA_READ:
send_wr_op = IB_WR_RDMA_READ;
if (unlikely(!pdu->is_wstag_valid)) {
pr_err("No write tag/va specified for RDMA op\n");
PRINT_ERROR("No write tag/va specified for RDMA op");
isert_buf_release(isert_buf);
buff_offset = -EFAULT;
goto out;
@@ -250,7 +250,7 @@ int isert_wr_init(struct isert_wr *wr,
case ISER_WR_RDMA_WRITE:
send_wr_op = IB_WR_RDMA_WRITE;
if (unlikely(!pdu->is_rstag_valid)) {
pr_err("No read tag/va specified for RDMA op\n");
PRINT_ERROR("No read tag/va specified for RDMA op");
isert_buf_release(isert_buf);
buff_offset = -EFAULT;
goto out;

View File

@@ -47,7 +47,7 @@ int isert_datamover_init(void)
err = isert_global_init();
if (unlikely(err)) {
pr_err("iser datamover init failed, err:%d\n", err);
PRINT_ERROR("iser datamover init failed, err:%d", err);
return err;
}
return 0;
@@ -189,7 +189,7 @@ int isert_login_rsp_tx(struct iscsi_cmnd *login_rsp, int last, int discovery)
if (last && !discovery) {
err = isert_alloc_conn_resources(isert_conn);
if (unlikely(err)) {
pr_err("Failed to init conn resources\n");
PRINT_ERROR("Failed to init conn resources");
return err;
}
isert_pdu_free(isert_conn->login_req_pdu);
@@ -199,7 +199,7 @@ int isert_login_rsp_tx(struct iscsi_cmnd *login_rsp, int last, int discovery)
&isert_conn->login_req_pdu->wr[0],
1);
if (unlikely(err)) {
pr_err("Failed to post recv login req rx buf, err:%d\n", err);
PRINT_ERROR("Failed to post recv login req rx buf, err:%d", err);
return err;
}
}

View File

@@ -86,7 +86,8 @@ int isert_data_in_sent(struct iscsi_cmnd *cmd);
int isert_pdu_sent(struct iscsi_cmnd *pdu);
void isert_pdu_err(struct iscsi_cmnd *pdu);
int isert_connection_closed(struct iscsi_conn *iscsi_conn);
void isert_connection_closed(struct iscsi_conn *iscsi_conn);
void isert_connection_abort(struct iscsi_conn *iscsi_conn);
void *isert_get_priv(struct iscsi_conn *iscsi_conn);
void isert_set_priv(struct iscsi_conn *iscsi_conn, void *priv);

View File

@@ -106,7 +106,7 @@ int isert_global_init(void)
isert_glob.conn_wq = create_workqueue("isert_conn_wq");
if (!isert_glob.conn_wq) {
pr_err("Failed to alloc iser conn work queue\n");
PRINT_ERROR("Failed to alloc iser conn work queue");
return -ENOMEM;
}
@@ -114,7 +114,7 @@ int isert_global_init(void)
SCST_SLAB_FLAGS|SLAB_HWCACHE_ALIGN);
if (!isert_cmnd_cache) {
destroy_workqueue(isert_glob.conn_wq);
pr_err("Failed to alloc iser command cache\n");
PRINT_ERROR("Failed to alloc iser command cache");
return -ENOMEM;
}
@@ -123,7 +123,7 @@ int isert_global_init(void)
if (!isert_conn_cache) {
destroy_workqueue(isert_glob.conn_wq);
kmem_cache_destroy(isert_cmnd_cache);
pr_err("Failed to alloc iser connection cache\n");
PRINT_ERROR("Failed to alloc iser connection cache");
return -ENOMEM;
}
@@ -153,7 +153,7 @@ int isert_get_addr_size(struct sockaddr *sa, size_t *addr_len)
*addr_len = sizeof(struct sockaddr_in6);
break;
default:
pr_err("Unknown address family\n");
PRINT_ERROR("Unknown address family");
ret = -EINVAL;
goto out;
}

View File

@@ -263,8 +263,8 @@ int isert_prepare_rdma(struct isert_cmnd *isert_pdu,
err = ib_dma_map_sg(ib_dev, isert_buf->sg, isert_buf->sg_cnt,
isert_buf->dma_dir);
if (unlikely(!err)) {
pr_err("Failed to DMA map iser sg:%p len:%d\n",
isert_buf->sg, isert_buf->sg_cnt);
PRINT_ERROR("Failed to DMA map iser sg:%p len:%d",
isert_buf->sg, isert_buf->sg_cnt);
wr_cnt = -EFAULT;
goto out;
}
@@ -331,27 +331,27 @@ struct isert_cmnd *isert_rx_pdu_alloc(struct isert_connection *isert_conn,
pdu = isert_pdu_alloc();
if (unlikely(!pdu)) {
pr_err("Failed to alloc pdu\n");
PRINT_ERROR("Failed to alloc pdu");
goto out;
}
err = isert_alloc_for_rdma(pdu, 4, isert_conn);
if (unlikely(err)) {
pr_err("Failed to alloc sge and wr for rx pdu\n");
PRINT_ERROR("Failed to alloc sge and wr for rx pdu");
goto out;
}
err = isert_buf_alloc_data_buf(isert_conn->isert_dev->ib_dev,
&pdu->buf, size, DMA_FROM_DEVICE);
if (unlikely(err)) {
pr_err("Failed to alloc rx pdu buf sz:%zd\n", size);
PRINT_ERROR("Failed to alloc rx pdu buf sz:%zd", size);
goto buf_alloc_failed;
}
err = isert_rx_pdu_init(pdu, isert_conn);
if (unlikely(err)) {
pr_err("Failed to init rx pdu wr:%p size:%zd err:%d\n",
&pdu->wr, size, err);
PRINT_ERROR("Failed to init rx pdu wr:%p size:%zd err:%d",
&pdu->wr, size, err);
goto pdu_init_failed;
}
@@ -379,27 +379,27 @@ struct isert_cmnd *isert_tx_pdu_alloc(struct isert_connection *isert_conn,
pdu = isert_pdu_alloc();
if (unlikely(!pdu)) {
pr_err("Failed to alloc pdu\n");
PRINT_ERROR("Failed to alloc pdu");
goto out;
}
err = isert_alloc_for_rdma(pdu, 4, isert_conn);
if (unlikely(err)) {
pr_err("Failed to alloc sge and wr for tx pdu\n");
PRINT_ERROR("Failed to alloc sge and wr for tx pdu");
goto out;
}
err = isert_buf_alloc_data_buf(isert_conn->isert_dev->ib_dev,
&pdu->buf, size, DMA_TO_DEVICE);
if (unlikely(err)) {
pr_err("Failed to alloc tx pdu buf sz:%zd\n", size);
PRINT_ERROR("Failed to alloc tx pdu buf sz:%zd", size);
goto buf_alloc_failed;
}
err = isert_pdu_tx_buf_init(pdu, isert_conn);
if (unlikely(err < 0)) {
pr_err("Failed to init tx pdu wr:%p size:%zd err:%d\n",
&pdu->wr, size, err);
PRINT_ERROR("Failed to init tx pdu wr:%p size:%zd err:%d",
&pdu->wr, size, err);
goto buf_init_failed;
}
@@ -449,8 +449,8 @@ int isert_alloc_conn_resources(struct isert_connection *isert_conn)
to_alloc = isert_conn->queue_depth * 2 + isert_conn->repost_threshold;
if (unlikely(to_alloc > ISER_MAX_WCE)) {
pr_err("QueuedCommands larger than %d not supported\n",
(ISER_MAX_WCE - isert_conn->repost_threshold) / 2);
PRINT_ERROR("QueuedCommands larger than %d not supported",
(ISER_MAX_WCE - isert_conn->repost_threshold) / 2);
err = -EINVAL;
goto out;
}
@@ -478,7 +478,7 @@ int isert_alloc_conn_resources(struct isert_connection *isert_conn)
err = isert_post_recv(isert_conn, &first_pdu->wr[0], to_alloc);
if (unlikely(err)) {
pr_err("Failed to post recv err:%d\n", err);
PRINT_ERROR("Failed to post recv err:%d", err);
goto clean_pdus;
}
@@ -596,8 +596,8 @@ int isert_pdu_send(struct isert_connection *isert_conn,
err = isert_post_send(isert_conn, wr, 1);
if (unlikely(err)) {
pr_err("Failed to send pdu conn:%p pdu:%p err:%d\n",
isert_conn, tx_pdu, err);
PRINT_ERROR("Failed to send pdu conn:%p pdu:%p err:%d",
isert_conn, tx_pdu, err);
}
TRACE_EXIT_RES(err);
@@ -623,8 +623,8 @@ int isert_pdu_post_rdma_write(struct isert_connection *isert_conn,
isert_link_send_pdu_wrs(isert_cmd, isert_rsp, wr_cnt);
err = isert_post_send(isert_conn, &isert_cmd->wr[0], wr_cnt + 1);
if (unlikely(err)) {
pr_err("Failed to send pdu conn:%p pdu:%p err:%d\n",
isert_conn, isert_cmd, err);
PRINT_ERROR("Failed to send pdu conn:%p pdu:%p err:%d",
isert_conn, isert_cmd, err);
}
TRACE_EXIT_RES(err);
@@ -640,8 +640,8 @@ int isert_pdu_post_rdma_read(struct isert_connection *isert_conn,
err = isert_post_send(isert_conn, &isert_cmd->wr[0], wr_cnt);
if (unlikely(err)) {
pr_err("Failed to send pdu conn:%p pdu:%p err:%d\n",
isert_conn, isert_cmd, err);
PRINT_ERROR("Failed to send pdu conn:%p pdu:%p err:%d",
isert_conn, isert_cmd, err);
}
TRACE_EXIT_RES(err);

File diff suppressed because it is too large Load Diff

View File

@@ -78,6 +78,11 @@ static void isert_mark_conn_closed(struct iscsi_conn *conn, int flags)
static void isert_close_conn(struct iscsi_conn *conn, int flags)
{
struct isert_conn_dev *dev;
dev = isert_get_priv(conn);
if (dev)
dev->state = CS_DISCONNECTED;
}
static int isert_receive_cmnd_data(struct iscsi_cmnd *cmnd)
@@ -283,7 +288,7 @@ static void isert_free_conn(struct iscsi_conn *conn)
isert_free_connection(conn);
}
int isert_handle_close_connection(struct iscsi_conn *conn)
void isert_handle_close_connection(struct iscsi_conn *conn)
{
isert_mark_conn_closed(conn, 0);
/*
@@ -295,7 +300,6 @@ int isert_handle_close_connection(struct iscsi_conn *conn)
isert_free_connection(conn);
else
start_close_conn(conn);
return 0;
}
int isert_pdu_rx(struct iscsi_cmnd *cmnd)
@@ -393,8 +397,8 @@ int isert_pdu_sent(struct iscsi_cmnd *pdu)
struct iscsi_target *target = pdu->conn->session->target;
PRINT_INFO("Closing all connections for target %x at "
"initiator's %s request", target->tid,
conn->session->initiator_name);
"initiator's %s request", target->tid,
conn->session->initiator_name);
mutex_lock(&target->target_mutex);
target_del_all_sess(target, 0);
mutex_unlock(&target->target_mutex);
@@ -492,7 +496,7 @@ static int __init isert_init_module(void)
int ret;
if (isert_nr_devs > 999) {
PRINT_ERROR("Invalid argument for isert_nr_devs provded: %d\n",
PRINT_ERROR("Invalid argument for isert_nr_devs provded: %d",
isert_nr_devs);
ret = -EINVAL;
goto out;

View File

@@ -71,7 +71,7 @@ struct isert_listener_dev {
struct cdev cdev;
dev_t devno;
wait_queue_head_t waitqueue;
spinlock_t conn_lock;
struct mutex conn_lock;
struct list_head new_conn_list;
struct list_head curr_conn_list;
struct isert_addr_info info;
@@ -129,7 +129,7 @@ int isert_conn_alloc(struct iscsi_session *session,
struct iscsi_kern_conn_info *info,
struct iscsi_conn **new_conn,
struct iscsit_transport *t);
int isert_handle_close_connection(struct iscsi_conn *conn);
void isert_handle_close_connection(struct iscsi_conn *conn);
void isert_close_all_portals(void);
void isert_del_timer(struct isert_conn_dev *dev);

View File

@@ -49,8 +49,11 @@
#include "isert_dbg.h"
#include "../iscsi.h"
#include "isert.h"
#include "iser.h"
#include "iser_datamover.h"
static DEFINE_MUTEX(conn_mgmt_mutex);
static unsigned int n_devs;
static int isert_major;
@@ -67,7 +70,7 @@ static struct isert_conn_dev *get_available_dev(struct isert_listener_dev *dev,
unsigned int i;
struct isert_conn_dev *res = NULL;
spin_lock(&dev->conn_lock);
mutex_lock(&dev->conn_lock);
for (i = 0; i < n_devs; ++i) {
if (!isert_conn_devices[i].occupied) {
res = &isert_conn_devices[i];
@@ -78,7 +81,7 @@ static struct isert_conn_dev *get_available_dev(struct isert_listener_dev *dev,
break;
}
}
spin_unlock(&dev->conn_lock);
mutex_unlock(&dev->conn_lock);
return res;
}
@@ -107,9 +110,10 @@ static void isert_kref_release_dev(struct kref *kref)
static void isert_dev_release(struct isert_conn_dev *dev)
{
spin_lock(&isert_listen_dev.conn_lock);
sBUG_ON(atomic_read(&dev->kref.refcount) == 0);
mutex_lock(&isert_listen_dev.conn_lock);
kref_put(&dev->kref, isert_kref_release_dev);
spin_unlock(&isert_listen_dev.conn_lock);
mutex_unlock(&isert_listen_dev.conn_lock);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
@@ -137,7 +141,7 @@ static void isert_conn_timer_fn(unsigned long arg)
conn_dev->timer_active = 0;
PRINT_ERROR("Timeout on connection %p\n", conn_dev->conn);
PRINT_ERROR("Timeout on connection %p", conn_dev->conn);
schedule_work(&conn->close_work);
@@ -153,7 +157,7 @@ static int add_new_connection(struct isert_listener_dev *dev,
TRACE_ENTRY();
if (!conn_dev) {
PRINT_WARNING("%s", "Unable to allocate new connection");
PRINT_WARNING("Unable to allocate new connection");
res = -ENOSPC;
goto out;
}
@@ -181,9 +185,9 @@ static bool have_new_connection(struct isert_listener_dev *dev)
{
bool ret;
spin_lock(&dev->conn_lock);
mutex_lock(&dev->conn_lock);
ret = !list_empty(&dev->new_conn_list);
spin_unlock(&dev->conn_lock);
mutex_unlock(&dev->conn_lock);
return ret;
}
@@ -203,6 +207,8 @@ int isert_conn_alloc(struct iscsi_session *session,
lockdep_assert_held(&session->target->target_mutex);
mutex_lock(&conn_mgmt_mutex);
if (unlikely(!filp)) {
res = -EBADF;
goto out;
@@ -210,6 +216,14 @@ int isert_conn_alloc(struct iscsi_session *session,
dev = filp->private_data;
if (unlikely(dev->state == CS_DISCONNECTED)) {
fput(filp);
res = -EBADF;
goto out;
}
sBUG_ON(dev->state != CS_RSP_FINISHED);
cmnd = dev->login_rsp;
sBUG_ON(cmnd == NULL);
@@ -265,6 +279,7 @@ cleanup_conn:
conn->session = NULL;
isert_close_connection(conn);
out:
mutex_unlock(&conn_mgmt_mutex);
TRACE_EXIT_RES(res);
return res;
}
@@ -304,8 +319,8 @@ static void isert_delete_conn_dev(struct isert_conn_dev *conn_dev)
isert_del_timer(conn_dev);
if (!test_and_set_bit(ISERT_CONN_PASSED, &conn_dev->flags)) {
BUG_ON(conn_dev->conn == NULL);
isert_close_connection(conn_dev->conn);
if (conn_dev->conn)
isert_close_connection(conn_dev->conn);
}
}
@@ -314,13 +329,13 @@ static int isert_listen_release(struct inode *inode, struct file *filp)
struct isert_listener_dev *dev = filp->private_data;
struct isert_conn_dev *conn_dev;
spin_lock(&isert_listen_dev.conn_lock);
mutex_lock(&isert_listen_dev.conn_lock);
list_for_each_entry(conn_dev, &dev->new_conn_list, conn_list_entry)
isert_delete_conn_dev(conn_dev);
list_for_each_entry(conn_dev, &dev->curr_conn_list, conn_list_entry)
isert_delete_conn_dev(conn_dev);
spin_unlock(&isert_listen_dev.conn_lock);
mutex_unlock(&isert_listen_dev.conn_lock);
atomic_inc(&dev->available);
return 0;
@@ -347,16 +362,16 @@ wait_for_connection:
goto out;
}
spin_lock(&dev->conn_lock);
mutex_lock(&dev->conn_lock);
if (list_empty(&dev->new_conn_list)) {
/* could happen if we got disconnect */
spin_unlock(&dev->conn_lock);
mutex_unlock(&dev->conn_lock);
goto wait_for_connection;
}
conn_dev = list_first_entry(&dev->new_conn_list, struct isert_conn_dev,
conn_list_entry);
list_move(&conn_dev->conn_list_entry, &dev->curr_conn_list);
spin_unlock(&dev->conn_lock);
mutex_unlock(&dev->conn_lock);
to_write = min_t(size_t, sizeof(k_buff), count);
res = scnprintf(k_buff, to_write, "/dev/"ISER_CONN_DEV_PREFIX"%d",
@@ -385,13 +400,13 @@ static long isert_listen_ioctl(struct file *filp, unsigned int cmd,
case SET_LISTEN_ADDR:
rc = copy_from_user(&dev->info, ptr, sizeof(dev->info));
if (unlikely(rc != 0)) {
PRINT_ERROR("Failed to copy %d user's bytes\n", rc);
PRINT_ERROR("Failed to copy %d user's bytes", rc);
res = -EFAULT;
goto out;
}
if (unlikely(dev->free_portal_idx >= ISERT_MAX_PORTALS)) {
PRINT_ERROR("Maximum number of portals exceeded: %d\n",
PRINT_ERROR("Maximum number of portals exceeded: %d",
ISERT_MAX_PORTALS);
res = -EINVAL;
goto out;
@@ -407,7 +422,7 @@ static long isert_listen_ioctl(struct file *filp, unsigned int cmd,
portal = isert_portal_add((struct sockaddr *)&dev->info.addr,
dev->info.addr_len);
if (IS_ERR(portal)) {
PRINT_ERROR("Unable to add portal of size %zu\n",
PRINT_ERROR("Unable to add portal of size %zu",
dev->info.addr_len);
res = PTR_ERR(portal);
goto out;
@@ -431,36 +446,61 @@ int isert_conn_established(struct iscsi_conn *iscsi_conn,
return add_new_connection(&isert_listen_dev, iscsi_conn);
}
int isert_connection_closed(struct iscsi_conn *iscsi_conn)
static void isert_dev_disconnect(struct iscsi_conn* iscsi_conn)
{
int res = 0;
struct isert_conn_dev* dev = isert_get_priv(iscsi_conn);
if (dev) {
isert_del_timer(dev);
dev->state = CS_DISCONNECTED;
dev->conn = NULL;
if (dev->login_req) {
isert_task_abort(dev->login_req);
spin_lock(&dev->pdu_lock);
dev->login_req = NULL;
spin_unlock(&dev->pdu_lock);
}
wake_up(&dev->waitqueue);
isert_dev_release(dev);
isert_set_priv(iscsi_conn, NULL);
}
}
void isert_connection_closed(struct iscsi_conn *iscsi_conn)
{
TRACE_ENTRY();
mutex_lock(&conn_mgmt_mutex);
if (iscsi_conn->rd_state) {
res = isert_handle_close_connection(iscsi_conn);
mutex_unlock(&conn_mgmt_mutex);
isert_handle_close_connection(iscsi_conn);
} else {
struct isert_conn_dev *dev = isert_get_priv(iscsi_conn);
if (dev) {
isert_del_timer(dev);
dev->state = CS_DISCONNECTED;
if (dev->login_req) {
res = isert_task_abort(dev->login_req);
spin_lock(&dev->pdu_lock);
dev->login_req = NULL;
spin_unlock(&dev->pdu_lock);
}
wake_up(&dev->waitqueue);
isert_dev_release(dev);
}
isert_dev_disconnect(iscsi_conn);
mutex_unlock(&conn_mgmt_mutex);
isert_free_connection(iscsi_conn);
}
TRACE_EXIT_RES(res);
return res;
TRACE_EXIT();
}
void isert_connection_abort(struct iscsi_conn *iscsi_conn)
{
struct isert_connection *isert_conn = (struct isert_connection *)iscsi_conn;
TRACE_ENTRY();
mutex_lock(&conn_mgmt_mutex);
if (!iscsi_conn->rd_state) {
if (!test_and_set_bit(ISERT_DISCON_CALLED, &isert_conn->flags)) {
isert_dev_disconnect(iscsi_conn);
isert_free_connection(iscsi_conn);
}
}
mutex_unlock(&conn_mgmt_mutex);
TRACE_EXIT();
}
static bool will_read_block(struct isert_conn_dev *dev)
@@ -492,13 +532,13 @@ static int isert_open(struct inode *inode, struct file *filp)
dev = container_of(inode->i_cdev, struct isert_conn_dev, cdev);
spin_lock(&isert_listen_dev.conn_lock);
mutex_lock(&isert_listen_dev.conn_lock);
if (unlikely(dev->occupied == 0)) {
spin_unlock(&isert_listen_dev.conn_lock);
mutex_unlock(&isert_listen_dev.conn_lock);
res = -ENODEV; /* already closed */
goto out;
}
spin_unlock(&isert_listen_dev.conn_lock);
mutex_unlock(&isert_listen_dev.conn_lock);
if (unlikely(!atomic_dec_and_test(&dev->available))) {
atomic_inc(&dev->available);
@@ -506,9 +546,9 @@ static int isert_open(struct inode *inode, struct file *filp)
goto out;
}
spin_lock(&isert_listen_dev.conn_lock);
mutex_lock(&isert_listen_dev.conn_lock);
kref_get(&dev->kref);
spin_unlock(&isert_listen_dev.conn_lock);
mutex_unlock(&isert_listen_dev.conn_lock);
filp->private_data = dev; /* for other methods */
@@ -528,13 +568,7 @@ static int isert_release(struct inode *inode, struct file *filp)
dev->sg_virt = NULL;
dev->is_discovery = 0;
if (!test_and_set_bit(ISERT_CONN_PASSED, &dev->flags)) {
BUG_ON(dev->conn == NULL);
isert_close_connection(dev->conn);
}
isert_del_timer(dev);
isert_delete_conn_dev(dev);
isert_dev_release(dev);
TRACE_EXIT_RES(res);
@@ -562,23 +596,33 @@ static ssize_t isert_read(struct file *filp, char __user *buf, size_t count,
struct isert_conn_dev *dev = filp->private_data;
size_t to_read;
if (dev->state == CS_DISCONNECTED)
mutex_lock(&conn_mgmt_mutex);
if (dev->state == CS_DISCONNECTED) {
mutex_unlock(&conn_mgmt_mutex);
return -EPIPE;
}
if (will_read_block(dev)) {
int ret;
if (filp->f_flags & O_NONBLOCK)
if (filp->f_flags & O_NONBLOCK) {
mutex_unlock(&conn_mgmt_mutex);
return -EAGAIN;
}
ret = wait_event_freezable(dev->waitqueue,
!will_read_block(dev));
if (ret < 0)
if (ret < 0) {
mutex_unlock(&conn_mgmt_mutex);
return ret;
}
}
to_read = min(count, dev->read_len);
if (copy_to_user(buf, dev->read_buf, to_read))
if (copy_to_user(buf, dev->read_buf, to_read)) {
mutex_unlock(&conn_mgmt_mutex);
return -EFAULT;
}
dev->read_len -= to_read;
dev->read_buf += to_read;
@@ -590,8 +634,10 @@ static ssize_t isert_read(struct file *filp, char __user *buf, size_t count,
dev->sg_virt = isert_vmap_sg(dev->pages,
dev->login_req->sg,
dev->login_req->sg_cnt);
if (!dev->sg_virt)
if (!dev->sg_virt) {
mutex_unlock(&conn_mgmt_mutex);
return -ENOMEM;
}
dev->read_buf = dev->sg_virt + ISER_HDRS_SZ;
dev->state = CS_REQ_DATA;
}
@@ -610,11 +656,12 @@ static ssize_t isert_read(struct file *filp, char __user *buf, size_t count,
break;
default:
PRINT_ERROR("Invalid state in %s (%d)\n", __func__,
dev->state);
PRINT_ERROR("Invalid state %d", dev->state);
to_read = 0;
}
mutex_unlock(&conn_mgmt_mutex);
return to_read;
}
@@ -624,12 +671,18 @@ static ssize_t isert_write(struct file *filp, const char __user *buf,
struct isert_conn_dev *dev = filp->private_data;
size_t to_write;
if (dev->state == CS_DISCONNECTED)
mutex_lock(&conn_mgmt_mutex);
if (dev->state == CS_DISCONNECTED) {
mutex_unlock(&conn_mgmt_mutex);
return -EPIPE;
}
to_write = min(count, dev->write_len);
if (copy_from_user(dev->write_buf, buf, to_write))
if (copy_from_user(dev->write_buf, buf, to_write)) {
mutex_unlock(&conn_mgmt_mutex);
return -EFAULT;
}
dev->write_len -= to_write;
dev->write_buf += to_write;
@@ -641,8 +694,10 @@ static ssize_t isert_write(struct file *filp, const char __user *buf,
dev->sg_virt = isert_vmap_sg(dev->pages,
dev->login_rsp->sg,
dev->login_rsp->sg_cnt);
if (!dev->sg_virt)
if (!dev->sg_virt) {
mutex_unlock(&conn_mgmt_mutex);
return -ENOMEM;
}
dev->write_buf = dev->sg_virt + ISER_HDRS_SZ;
dev->write_len = dev->login_rsp->bufflen -
sizeof(dev->login_rsp->pdu.bhs);
@@ -654,11 +709,12 @@ static ssize_t isert_write(struct file *filp, const char __user *buf,
break;
default:
PRINT_ERROR("Invalid state in %s (%d)\n", __func__,
dev->state);
PRINT_ERROR("Invalid state %d", dev->state);
to_write = 0;
}
mutex_unlock(&conn_mgmt_mutex);
return to_write;
}
@@ -678,6 +734,8 @@ static long isert_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
TRACE_ENTRY();
mutex_lock(&conn_mgmt_mutex);
if (dev->state == CS_DISCONNECTED) {
res = -EPIPE;
goto out;
@@ -764,6 +822,7 @@ static long isert_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
out:
mutex_unlock(&conn_mgmt_mutex);
TRACE_EXIT_RES(res);
return res;
}
@@ -914,7 +973,7 @@ static void __init isert_setup_listener_cdev(struct isert_listener_dev *dev)
init_waitqueue_head(&dev->waitqueue);
INIT_LIST_HEAD(&dev->new_conn_list);
INIT_LIST_HEAD(&dev->curr_conn_list);
spin_lock_init(&dev->conn_lock);
mutex_init(&dev->conn_lock);
atomic_set(&dev->available, 1);
err = cdev_add(&dev->cdev, dev->devno, 1);
/* Fail gracefully if need be */
@@ -944,7 +1003,7 @@ int __init isert_init_login_devs(unsigned int ndevs)
isert_major = MAJOR(devno);
if (unlikely(res < 0)) {
PRINT_ERROR("isert: can't get major %d\n", isert_major);
PRINT_ERROR("can't get major %d", isert_major);
goto out;
}
@@ -969,7 +1028,7 @@ int __init isert_init_login_devs(unsigned int ndevs)
res = isert_datamover_init();
if (unlikely(res)) {
PRINT_ERROR("Unable to initialize datamover: %d\n", res);
PRINT_ERROR("Unable to initialize datamover: %d", res);
goto fail;
}