Add support for BUSY status coide from the target and just pass this
back to the application as is (instead of converting it to _ERROR).
This allows the application to trap task->status==SCSI_STATUS_BUSY and
decide what/how to proceed.
This patch adds support for read/writev to directly read and write
from/to iovectors. Before this patch on read and write from/to socket
the operation was limited by the iovec boundaries. If there is enough
data in the buffer or enough buffer space available its now possible
to transfer the whole data in one atomic operaion.
Signed-off-by: Peter Lieven <pl@kamp.de>
We where modifying out_offset and out_len in iscsi_write_to_socket().
If the packet that was being sent before reconnect was a write command
the was a significant change that out_offset and out_len where already
touched. When requeing the packet after reconnect we where
sending garbage!
Signed-off-by: Peter Lieven <pl@kamp.de>
This patch adds the abilitiy to libiscsi to count the number
of consecutive outstanding NOPs.
With this ability its fairly easy to implement a keepalive
check with NOPs in your application.
Periodically (e.g. every 5 secs) create a NOP-Out with:
iscsi_nop_out_async(iscsi, NULL, NULL, 0, NULL);
At that time check the number of consecutive missing NOP-Ins
with
iscsi_get_nops_in_flight(iscsi) > N.
Where N is the number of missing NOP-Ins you will allow.
Please note that it is legitime for the Target to ignore
a NOP if the load is very high as those packet are mark
as IMMEDIATE.
Signed-off-by: Peter Lieven <pl@kamp.de>
Just like DATA_OUT we should just discard NOPs instead of requeueing them
on session reconnect.
Add new flag that to indicate this behaviour on reconnect and set it for
both data out and nops
In specific situation it might be useful to give up if a reconnect
is not successful or after a given number reconnect retries.
This patch adds the ability to change that. The default remains
the same: retry forever.
Signed-off-by: Peter Lieven <pl@kamp.de>
A storage might sent an R2T response for a WRITE command while
we still sending out the WRITE command PDU. This is especially
the case when the command PDU carries immediata data.
Without this patch the R2T response will get lost as
the cmdpdu for the R2T cannot be found in iscsi_process_pdu()
leading to a deadlock.
Signed-off-by: Peter Lieven <pl@kamp.de>
As part of the test also validate the PDU that libiscsi generates and verify that
1, the PDU we send has the F flag set
2, that datasegmentlength for the PDU is one block
Remove the size field as it is not used. If we would keep it
we would have to calculate it in scsi_task_set_iov_in/out which
would add unneccassry wals to the iovec array.
Signed-off-by: Peter Lieven <pl@kamp.de>
The send logic was completely broken for any cases except
ISCSI_INITIAL_R2T_NO and ISCSI_IMMEDIATE_DATA_YES.
The final flag was set wrong or no data was sent.
It was also broken if the data did not fit into the cmd_pdu as
the consecutive pdus did not have the scsi_cbdata set which
lead to a segfault in iscsi_get_user_out_buffer().
Unfortunately we need to include scsi-lowlevel.h again in iscsi-private.h.
This should be fixed asap by introduction of an iscsi_task struct
to avoid to store iscsi relevant data in the scsi_task.
Signed-off-by: Peter Lieven <pl@kamp.de>
Conflicts:
lib/iscsi-command.c
Signed-off-by: Peter Lieven <pl@kamp.de>
This patch avoid incrementing itt to 0xffffffff which is
a reserved value for immediate pdus. Avoid incrementing
it to 0xfffffff to avoid unexpected behaviour.
Signed-off-by: Peter Lieven <pl@kamp.de>
RFC3720 says that cmdsn comparison must be done using
serial32 arithmetic. This will definetly avoid a deadlock
if cmdsn wraps from 2^32-1 to 0.
Signed-off-by: Peter Lieven <pl@kamp.de>
We can simply next the iscsi_scsi_cbdata in the iscsi_pdu struct
since it is only used inside the iscsi_pdu.
This saves one malloc for each pdu.
Signed-off-by: Peter Lieven <pl@kamp.de>
Change iscsi_scsi_command_async() to write data-out using iovectors
attached to the scsi task structure instead of copying the data into
the buffer holding the header.
Still allow passing the data via an argument to the funtcion so that the
ABI does not change but then just conver the data to an iovector.
Update the write_to_socket functions to know about the iovectors and write them
as part of the pdu.
Convert write10_task to use iovectors.
This will allow 'zero-copy' writes through libiscsi.
However, as 'zero-copy writes does mean that we do more send() calls into
the kernel this may degrade performance for very small i/o.
A scsi write will not take at least 2 send() calls.
One send call for the iscsi header structure and a second send call for the
payload data.
This will be more expensive than the old memcpy() of payload data plus one send() call since the send() will be a lot more expensive than memcpy() of a small amount of data.
This patch defines an scsi_iovec struct which is guaranteed
to be POSIX compatible. It furthermore adds support for
in+out iovectors for bi-directional operations
Signed-off-by: Peter Lieven <pl@kamp.de>
If an application passes buffers to libiscsi for reading they are
currently added to a linked list one by one. This leads to a malloc
for each buffer object plus O(n) walks trough the list to add
the buffer to then end of the list. Additionally the buffer read
routine takes up to O(n) iterations to find the right buffer
for a request.
This patch introduces an scsi_iovector struct to pass buffers to
an scsi task. Adding a new buffer is in O(1) and finding the
right buffer to also. Malloc requirements are in O(log(n)).
Additionally the scsi_iovector struct is itended to be binary
compatible to an QEMUIOVector allowing to pass this structure
directly to the library.
Initial tests have been made booting an Ubuntu LTS 12.04.1
Desktop server up to the login prompt. The following observations
have been made with regards to scsi_malloc calls:
original implementation: ~11.500 mallocs
using iovector instead of list: ~ 7.500 mallocs
passing the iovector directly: 0 mallocs
To enable this feature in qemu for testing the following patch might
be used:
diff --git a/block/iscsi.c b/block/iscsi.c
index a6a819d..2809c15 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -390,11 +390,16 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
return NULL;
}
+#if defined(LIBISCSI_FEATURE_IOVECTOR)
+ assert(sizeof(struct QEMUIOVector) == sizeof(struct scsi_iovector));
+ scsi_iovector_assign(acb->task, (struct scsi_iovector*) acb->qiov);
+#else
for (i = 0; i < acb->qiov->niov; i++) {
scsi_task_add_data_in_buffer(acb->task,
acb->qiov->iov[i].iov_len,
acb->qiov->iov[i].iov_base);
}
+#endif
iscsi_set_events(iscsilun);
---
Signed-off-by: Peter Lieven <pl@kamp.de>
Split the INQUIRY data-in unmarshalling into smaller chunks, fixing some
potential memory leaks along the way.
Signed-off-by: Arne Redlich <arne.redlich@googlemail.com>