Merge pull request #150 from plieven/for_upstream

For upstream
This commit is contained in:
Ronnie Sahlberg
2015-03-31 06:48:47 -07:00
8 changed files with 133 additions and 76 deletions

View File

@@ -229,11 +229,6 @@ struct iscsi_pdu {
#define ISCSI_PDU_DROP_ON_RECONNECT 0x00000004
/* stop sending after this PDU has been sent */
#define ISCSI_PDU_CORK_WHEN_SENT 0x00000008
/* put this immediate delivery PDU in front of outqueue.
* This is currently only used for immediate logout requests
* as answer to an async logout event. */
#define ISCSI_PDU_URGENT_DELIVERY 0x00000010
uint32_t flags;
@@ -371,10 +366,6 @@ uint32_t iscsi_itt_post_increment(struct iscsi_context *iscsi);
void iscsi_timeout_scan(struct iscsi_context *iscsi);
int
iscsi_logout_async_internal(struct iscsi_context *iscsi, iscsi_command_cb cb,
void *private_data, uint32_t flags);
#ifdef __cplusplus
}
#endif

View File

@@ -115,9 +115,6 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
/* ttt */
iscsi_pdu_set_ttt(pdu, ttt);
/* exp statsn */
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);
/* data sn */
iscsi_pdu_set_datasn(pdu, cmd_pdu->datasn++);
@@ -305,13 +302,8 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
iscsi_pdu_set_expxferlen(pdu, task->expxferlen);
/* cmdsn */
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
pdu->cmdsn = iscsi->cmdsn;
iscsi->cmdsn++;
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn++);
/* exp statsn */
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);
/* cdb */
iscsi_pdu_set_cdb(pdu, task);

View File

@@ -790,6 +790,13 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
return -1;
}
/* randomize cmdsn and itt */
if (!iscsi->current_phase && !iscsi->secneg_phase) {
iscsi->itt = (u_int32_t) rand();
iscsi->cmdsn = (u_int32_t) rand();
iscsi->expcmdsn = iscsi->maxcmdsn = iscsi->cmdsn;
}
pdu = iscsi_allocate_pdu(iscsi,
ISCSI_PDU_LOGIN_REQUEST,
ISCSI_PDU_LOGIN_RESPONSE,
@@ -804,6 +811,9 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
/* login request */
iscsi_pdu_set_immediate(pdu);
/* cmdsn is not increased if Immediate delivery*/
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
if (!iscsi->user[0]) {
iscsi->current_phase = ISCSI_PDU_LOGIN_CSG_OPNEG;
}
@@ -1034,7 +1044,13 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
status = scsi_get_uint16(&in->hdr[36]);
iscsi_adjust_statsn(iscsi, in);
// Status-Class is 0
if (!(status >> 8)) {
if (!iscsi->current_phase && !iscsi->secneg_phase) {
iscsi->statsn = scsi_get_uint32(&in->hdr[24]);
}
iscsi_adjust_statsn(iscsi, in);
}
iscsi_adjust_maxexpcmdsn(iscsi, in);
/* Using bidirectional CHAP? Then we must see a chap_n and chap_r
@@ -1236,8 +1252,8 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
}
int
iscsi_logout_async_internal(struct iscsi_context *iscsi, iscsi_command_cb cb,
void *private_data, uint32_t flags)
iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
void *private_data)
{
struct iscsi_pdu *pdu;
@@ -1252,7 +1268,7 @@ iscsi_logout_async_internal(struct iscsi_context *iscsi, iscsi_command_cb cb,
ISCSI_PDU_LOGOUT_REQUEST,
ISCSI_PDU_LOGOUT_RESPONSE,
iscsi_itt_post_increment(iscsi),
ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_CORK_WHEN_SENT|flags);
ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_CORK_WHEN_SENT);
if (pdu == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
"logout pdu.");
@@ -1267,10 +1283,6 @@ iscsi_logout_async_internal(struct iscsi_context *iscsi, iscsi_command_cb cb,
/* cmdsn is not increased if Immediate delivery*/
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
pdu->cmdsn = iscsi->cmdsn;
/* exp statsn */
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);
pdu->callback = cb;
pdu->private_data = private_data;
@@ -1285,13 +1297,6 @@ iscsi_logout_async_internal(struct iscsi_context *iscsi, iscsi_command_cb cb,
return 0;
}
int
iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
void *private_data)
{
return iscsi_logout_async_internal(iscsi, cb, private_data, 0);
}
int
iscsi_process_logout_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
struct iscsi_in_pdu *in)

View File

@@ -46,9 +46,6 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
return -1;
}
/* immediate flag */
iscsi_pdu_set_immediate(pdu);
/* flags */
iscsi_pdu_set_pduflags(pdu, 0x80);
@@ -58,12 +55,8 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
/* lun */
iscsi_pdu_set_lun(pdu, 0);
/* cmdsn is not increased if Immediate delivery*/
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
pdu->cmdsn = iscsi->cmdsn;
/* exp statsn */
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);
/* cmdsn */
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn++);
pdu->callback = cb;
pdu->private_data = private_data;
@@ -83,7 +76,9 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
}
iscsi->nops_in_flight++;
ISCSI_LOG(iscsi, 6, "NOP Out Send (nops_in_flight: %d)", iscsi->nops_in_flight);
ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6,
"NOP Out Send (nops_in_flight: %d, pdu->cmdsn %08x, pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x)",
iscsi->nops_in_flight, pdu->cmdsn, pdu->itt, 0xffffffff, iscsi->maxcmdsn, iscsi->expcmdsn);
return 0;
}
@@ -117,10 +112,6 @@ iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt)
/* cmdsn is not increased if Immediate delivery*/
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
pdu->cmdsn = iscsi->cmdsn;
/* exp statsn */
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);
if (iscsi_queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "failed to queue iscsi nop-out pdu");
@@ -128,6 +119,10 @@ iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt)
return -1;
}
ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6,
"NOP Out Send (nops_in_flight: %d, pdu->cmdsn %08x, pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x)",
iscsi->nops_in_flight, pdu->cmdsn, 0xffffffff, ttt, iscsi->maxcmdsn, iscsi->expcmdsn);
return 0;
}
@@ -137,9 +132,14 @@ iscsi_process_nop_out_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
{
struct iscsi_data data;
iscsi->nops_in_flight = 0;
iscsi_adjust_maxexpcmdsn(iscsi, in);
iscsi_adjust_statsn(iscsi, in);
ISCSI_LOG(iscsi, 6, "NOP Out Reply received");
ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6,
"NOP-In received (pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x, iscsi->statsn %08x)",
pdu->itt, 0xffffffff, iscsi->maxcmdsn, iscsi->expcmdsn, iscsi->statsn);
iscsi->nops_in_flight = 0;
if (pdu->callback == NULL) {
return 0;

View File

@@ -319,11 +319,15 @@ static const char *iscsi_reject_reason_str(enum iscsi_reject_reason reason)
int iscsi_process_target_nop_in(struct iscsi_context *iscsi,
struct iscsi_in_pdu *in)
{
uint32_t ttt;
ttt = scsi_get_uint32(&in->hdr[20]);
uint32_t ttt = scsi_get_uint32(&in->hdr[20]);
uint32_t itt = scsi_get_uint32(&in->hdr[16]);
iscsi_adjust_statsn(iscsi, in);
iscsi_adjust_maxexpcmdsn(iscsi, in);
ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6,
"NOP-In received (pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x, iscsi->statsn %08x)",
itt, ttt, iscsi->maxcmdsn, iscsi->expcmdsn, iscsi->statsn);
/* if the server does not want a response */
if (ttt == 0xffffffff) {
@@ -365,7 +369,7 @@ int iscsi_process_reject(struct iscsi_context *iscsi,
if (reason == ISCSI_REJECT_WAITING_FOR_LOGOUT) {
ISCSI_LOG(iscsi, 1, "target rejects request with reason: %s", iscsi_reject_reason_str(reason));
iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_URGENT_DELIVERY);
iscsi_logout_async(iscsi, iscsi_reconnect_after_logout, NULL);
return 0;
}
@@ -435,7 +439,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
ISCSI_LOG(iscsi, 2, "dropping connection to fix errors with broken DELL Equallogic firmware 7.x");
return -1;
}
iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_URGENT_DELIVERY);
iscsi_logout_async(iscsi, iscsi_reconnect_after_logout, NULL);
return 0;
case 0x2:
ISCSI_LOG(iscsi, 2, "target will drop this connection. Time2Wait is %u seconds", param2);
@@ -447,7 +451,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
return 0;
case 0x4:
ISCSI_LOG(iscsi, 2, "target requests parameter renogitiation.");
iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_DROP_ON_RECONNECT);
iscsi_logout_async(iscsi, iscsi_reconnect_after_logout, NULL);
return 0;
default:
ISCSI_LOG(iscsi, 1, "unhandled async event %u: param1 %u param2 %u param3 %u", event, param1, param2, param3);
@@ -621,6 +625,7 @@ void
iscsi_pdu_set_cmdsn(struct iscsi_pdu *pdu, uint32_t cmdsn)
{
scsi_set_uint32(&pdu->outdata.data[24], cmdsn);
pdu->cmdsn = cmdsn;
}
void

View File

@@ -92,10 +92,17 @@ iscsi_add_to_outqueue(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
/* queue pdus in ascending order of CmdSN.
* ensure that pakets with the same CmdSN are kept in FIFO order.
* immediate PDUs are queued in front of queue with the CmdSN
* of the first element in the outqueue.
*/
if (pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE) {
iscsi_pdu_set_cmdsn(pdu, current->cmdsn);
}
do {
if (iscsi_serial32_compare(pdu->cmdsn, current->cmdsn) < 0 ||
pdu->flags & ISCSI_PDU_URGENT_DELIVERY) {
(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE && !(current->outdata.data[0] & ISCSI_PDU_IMMEDIATE))) {
/* insert PDU before the current */
if (last != NULL) {
last->next=pdu;
@@ -386,7 +393,10 @@ iscsi_which_events(struct iscsi_context *iscsi)
if (iscsi->outqueue_current != NULL ||
(iscsi->outqueue != NULL && !iscsi->is_corked &&
iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) <= 0)) {
(iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) <= 0 ||
iscsi->outqueue->outdata.data[0] & ISCSI_PDU_IMMEDIATE)
)
) {
events |= POLLOUT;
}
return events;
@@ -639,13 +649,19 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
iscsi->outqueue->cmdsn, iscsi->maxcmdsn);
return 0;
}
/* pop first element of the outqueue */
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->expcmdsn) < 0) {
iscsi_set_error(iscsi, "iscsi_write_to_scoket: outqueue[0]->cmdsn < expcmdsn (%08x < %08x)",
iscsi->outqueue->cmdsn, iscsi->expcmdsn);
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->expcmdsn) < 0 &&
(iscsi->outqueue->outdata.data[0] & 0x3f) != ISCSI_PDU_DATA_OUT) {
iscsi_set_error(iscsi, "iscsi_write_to_scoket: outqueue[0]->cmdsn < expcmdsn (%08x < %08x) opcode %02x",
iscsi->outqueue->cmdsn, iscsi->expcmdsn, iscsi->outqueue->outdata.data[0] & 0x3f);
return -1;
}
iscsi->outqueue_current = iscsi->outqueue;
/* set exp statsn */
iscsi_pdu_set_expstatsn(iscsi->outqueue_current, iscsi->statsn + 1);
ISCSI_LIST_REMOVE(&iscsi->outqueue, iscsi->outqueue_current);
if (!(iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT)) {
/* we have to add the pdu to the waitqueue already here

View File

@@ -73,7 +73,6 @@ iscsi_task_mgmt_async(struct iscsi_context *iscsi,
/* cmdsn is not increased if Immediate delivery*/
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
pdu->cmdsn = iscsi->cmdsn;
/* rcmdsn */
iscsi_pdu_set_rcmdsn(pdu, rcmdsn);

View File

@@ -24,6 +24,7 @@
#include <getopt.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include "iscsi.h"
#include "scsi-lowlevel.h"
@@ -33,7 +34,11 @@
#define VERSION "0.1"
#define NOP_INTERVAL 5
#define MAX_NOP_FAILURES 3
const char *initiator = "iqn.2010-11.libiscsi:iscsi-perf";
int proc_alarm = 0;
int max_in_flight = 32;
int blocks_per_io = 8;
uint64_t runtime = 0;
@@ -43,6 +48,7 @@ struct client {
int finished;
int in_flight;
int random;
int random_blocks;
struct iscsi_context *iscsi;
struct scsi_iovec perf_iov;
@@ -55,6 +61,8 @@ struct client {
uint64_t first_ns;
uint64_t iops;
uint64_t last_iops;
uint64_t bytes;
uint64_t last_bytes;
int ignore_errors;
int busy_cnt;
@@ -92,40 +100,44 @@ void progress(struct client *client) {
if (runtime) _runtime = runtime - _runtime;
printf ("\r");
uint64_t aiops = 1000000000UL * (client->iops) / (now - client->first_ns);
uint64_t aiops = 1000000000.0 * (client->iops) / (now - client->first_ns);
uint64_t ambps = 1000000000.0 * (client->bytes) / (now - client->first_ns);
if (!_runtime) {
finished = 1;
printf ("iops average %" PRIu64 " (%" PRIu64 " MB/s) ", aiops, (aiops * blocks_per_io * client->blocksize) >> 20);
} else {
uint64_t iops = 1000000000UL * (client->iops - client->last_iops) / (now - client->last_ns);
uint64_t mbps = 1000000000UL * (client->bytes - client->last_bytes) / (now - client->last_ns);
printf ("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 " - ", _runtime / 3600, (_runtime % 3600) / 60, _runtime % 60);
printf ("lba %" PRIu64 ", iops current %" PRIu64 " (%" PRIu64 " MB/s), ", client->pos, iops, (iops * blocks_per_io * client->blocksize) >> 20);
printf ("iops average %" PRIu64 " (%" PRIu64 " MB/s), in_flight %d, busy %d ", aiops, (aiops * blocks_per_io * client->blocksize) >> 20, client->in_flight, client->busy_cnt);
printf ("lba %" PRIu64 ", iops current %" PRIu64 " (%" PRIu64 " MB/s), ", client->pos, iops, mbps >> 20);
printf ("iops average %" PRIu64 " (%" PRIu64 " MB/s), in_flight %d, busy %d ", aiops, ambps >> 20, client->in_flight, client->busy_cnt);
}
fflush(stdout);
client->last_ns = now;
client->last_iops = client->iops;
client->last_bytes = client->bytes;
}
void cb(struct iscsi_context *iscsi _U_, int status, void *command_data, void *private_data)
{
struct client *client = (struct client *)private_data;
struct scsi_task *task = command_data, *task2 = NULL;
struct scsi_read16_cdb *read16_cdb = NULL;
read16_cdb = scsi_cdb_unmarshall(task, SCSI_OPCODE_READ16);
if (read16_cdb == NULL) {
fprintf(stderr, "Failed to unmarshall READ16 CDB.\n");
client->err_cnt++;
goto out;
}
if (status == SCSI_STATUS_BUSY ||
(status == SCSI_STATUS_CHECK_CONDITION && task->sense.key == SCSI_SENSE_UNIT_ATTENTION)) {
struct scsi_read16_cdb *read16_cdb = NULL;
if (client->retry_cnt++ > 4 * max_in_flight) {
fprintf(stderr, "maxium number of command retries reached...\n");
client->err_cnt++;
goto out;
}
read16_cdb = scsi_cdb_unmarshall(task, SCSI_OPCODE_READ16);
if (read16_cdb == NULL) {
fprintf(stderr, "Failed to unmarshall READ16 CDB.\n");
client->err_cnt++;
goto out;
}
task2 = iscsi_read16_task(client->iscsi,
client->lun, read16_cdb->lba,
read16_cdb->transfer_length * client->blocksize,
@@ -143,6 +155,7 @@ void cb(struct iscsi_context *iscsi _U_, int status, void *command_data, void *p
client->err_cnt++;
} else if (status == SCSI_STATUS_GOOD) {
client->retry_cnt = 0;
client->bytes += read16_cdb->transfer_length * client->blocksize;
} else {
fprintf(stderr, "Read16 failed with %s\n", iscsi_get_error(iscsi));
if (!client->ignore_errors) {
@@ -181,6 +194,10 @@ void fill_read_queue(struct client *client)
if (num_blocks > blocks_per_io) {
num_blocks = blocks_per_io;
}
if (client->random_blocks) {
num_blocks = rand() % num_blocks + 1;
}
task = iscsi_read16_task(client->iscsi,
client->lun, client->pos,
@@ -202,8 +219,17 @@ void usage(void) {
exit(1);
}
void sig_handler (int signum _U_) {
finished = 1;
void sig_handler (int signum ) {
if (signum == SIGALRM) {
if (proc_alarm) {
fprintf(stderr, "\n\nABORT: Last alarm was not processed.\n");
exit(10);
}
proc_alarm = 1;
alarm(NOP_INTERVAL);
} else {
finished = 1;
}
}
int main(int argc, char *argv[])
@@ -222,6 +248,7 @@ int main(int argc, char *argv[])
{"blocks", required_argument, NULL, 'b'},
{"runtime", required_argument, NULL, 't'},
{"random", no_argument, NULL, 'r'},
{"random-blocks", no_argument, NULL, 'R'},
{"ignore-errors", no_argument, NULL, 'n'},
{0, 0, 0, 0}
};
@@ -233,7 +260,7 @@ int main(int argc, char *argv[])
printf("iscsi-perf version %s - (c) 2014-2015 by Peter Lieven <pl@ĸamp.de>\n\n", VERSION);
while ((c = getopt_long(argc, argv, "i:m:b:t:nr", long_options,
while ((c = getopt_long(argc, argv, "i:m:b:t:nrR", long_options,
&option_index)) != -1) {
switch (c) {
case 'i':
@@ -254,6 +281,9 @@ int main(int argc, char *argv[])
case 'r':
client.random = 1;
break;
case 'R':
client.random_blocks = 1;
break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
usage();
@@ -324,8 +354,13 @@ int main(int argc, char *argv[])
printf("capacity is %" PRIu64 " blocks or %" PRIu64 " byte (%" PRIu64 " MB)\n", client.num_blocks, client.num_blocks * client.blocksize,
(client.num_blocks * client.blocksize) >> 20);
printf("performing %s READ with %d parallel requests\nfixed transfer size of %d blocks (%d byte)\n",
client.random ? "random" : "sequential", max_in_flight, blocks_per_io, blocks_per_io * client.blocksize);
printf("performing %s READ with %d parallel requests\n", client.random ? "RANDOM" : "SEQUENTIAL", max_in_flight);
if (client.random_blocks) {
printf("RANDOM transfer size of 1 - %d blocks (%d - %d byte)\n", blocks_per_io, client.blocksize, blocks_per_io * client.blocksize);
} else {
printf("FIXED transfer size of %d blocks (%d byte)\n", blocks_per_io, blocks_per_io * client.blocksize);
}
if (runtime) {
printf("will run for %" PRIu64 " seconds.\n", runtime);
@@ -340,6 +375,7 @@ int main(int argc, char *argv[])
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGALRM, &sa, NULL);
printf("\n");
@@ -347,10 +383,21 @@ int main(int argc, char *argv[])
fill_read_queue(&client);
alarm(NOP_INTERVAL);
while (client.in_flight && !client.err_cnt) {
pfd[0].fd = iscsi_get_fd(client.iscsi);
pfd[0].events = iscsi_which_events(client.iscsi);
if (proc_alarm) {
if (iscsi_get_nops_in_flight(client.iscsi) > MAX_NOP_FAILURES) {
fprintf(stderr, "\n\nABORT: NOP timeout.\n");
exit(10);
}
iscsi_nop_out_async(client.iscsi, NULL, NULL, 0, NULL);
proc_alarm = 0;
}
if (poll(&pfd[0], 1, -1) < 0) {
continue;
}
@@ -359,6 +406,8 @@ int main(int argc, char *argv[])
break;
}
}
alarm(0);
progress(&client);