int do_cancel(int fd) { int r; r = send_cancel(fd); if(r < 0) { return -EPROTO; } r = get_tf_packet(fd, &reply); if(r < 0) { return -EPROTO; } switch (get_u32(&reply.cmd)) { case SUCCESS: printf("In progress operation cancelled\n"); return 0; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); } return -EPROTO; }
static int do_cancel(Camera *camera, GPContext *context) { int r; struct tf_packet reply; r = send_cancel(camera,context); if(r < 0) return r; r = get_tf_packet(camera, &reply, context); if(r < 0) return r; switch (get_u32(&reply.cmd)) { case SUCCESS: gp_log (GP_LOG_DEBUG, "topfield", "In progress operation cancelled\n"); return GP_OK; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet\n"); break; } return GP_ERROR_IO; }
void Inbound::send_error(Net::PTP::ServerDevice *ptp) { Net::PTP::Result result(serv_func,error_id); auto len=SaveLen(result); if( packet.checkDataLen(len) ) { PtrLen<uint8> info=packet.setDataLen(len); BufPutDev dev(info.ptr); dev(result); ptp->send_info(idx,Replace_null(packet),info); } else { send_cancel(ptp); } }
void Outbound::send_error(PacketList &complete_list,Net::PTP::ServerDevice *ptp,ErrorIdType error_id) { Net::PTP::Result result(serv_func,error_id); auto len=SaveLen(result); if( packet.checkDataLen(len) ) { PtrLen<uint8> info=packet.setDataLen(len); BufPutDev dev(info.ptr); dev(result); send_info(complete_list,ptp,info); } else { send_cancel(complete_list,ptp); } }
int SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, struct smb_hdr *in_buf, struct smb_hdr *out_buf, int *pbytes_returned) { int rc = 0; int rstart = 0; struct mid_q_entry *midQ; struct cifs_ses *ses; if (tcon == NULL || tcon->ses == NULL) { cifs_dbg(VFS, "Null smb session\n"); return -EIO; } ses = tcon->ses; if (ses->server == NULL) { cifs_dbg(VFS, "Null tcp session\n"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) return -ENOENT; /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", be32_to_cpu(in_buf->smb_buf_length)); return -EIO; } rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0); if (rc) return rc; /* make sure that we sign in the same order that we send on this socket and avoid races inside tcp sendmsg code that could cause corruption of smb data */ mutex_lock(&ses->server->srv_mutex); rc = allocate_mid(ses, in_buf, &midQ); if (rc) { mutex_unlock(&ses->server->srv_mutex); return rc; } rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); if (rc) { cifs_delete_mid(midQ); mutex_unlock(&ses->server->srv_mutex); return rc; } midQ->mid_state = MID_REQUEST_SUBMITTED; cifs_in_send_inc(ses->server); rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); cifs_in_send_dec(ses->server); cifs_save_when_sent(midQ); if (rc < 0) ses->server->sequence_number -= 2; mutex_unlock(&ses->server->srv_mutex); if (rc < 0) { cifs_delete_mid(midQ); return rc; } /* Wait for a reply - allow signals to interrupt. */ rc = wait_event_interruptible(ses->server->response_q, (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || ((ses->server->tcpStatus != CifsGood) && (ses->server->tcpStatus != CifsNew))); /* Were we interrupted by a signal ? */ if ((rc == -ERESTARTSYS) && (midQ->mid_state == MID_REQUEST_SUBMITTED) && ((ses->server->tcpStatus == CifsGood) || (ses->server->tcpStatus == CifsNew))) { if (in_buf->Command == SMB_COM_TRANSACTION2) { /* POSIX lock. We send a NT_CANCEL SMB to cause the blocking lock to return. */ rc = send_cancel(ses->server, in_buf, midQ); if (rc) { cifs_delete_mid(midQ); return rc; } } else { /* Windows lock. We send a LOCKINGX_CANCEL_LOCK to cause the blocking lock to return. */ rc = send_lock_cancel(xid, tcon, in_buf, out_buf); /* If we get -ENOLCK back the lock may have already been removed. Don't exit in this case. */ if (rc && rc != -ENOLCK) { cifs_delete_mid(midQ); return rc; } } rc = wait_for_response(ses->server, midQ); if (rc) { send_cancel(ses->server, in_buf, midQ); spin_lock(&GlobalMid_Lock); if (midQ->mid_state == MID_REQUEST_SUBMITTED) { /* no longer considered to be "in-flight" */ midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); return rc; } spin_unlock(&GlobalMid_Lock); } /* We got the response - restart system call. */ rstart = 1; } rc = cifs_sync_mid_result(midQ, ses->server); if (rc != 0) return rc; /* rcvd frame is ok */ if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { rc = -EIO; cifs_dbg(VFS, "Bad MID state?\n"); goto out; } *pbytes_returned = get_rfc1002_length(midQ->resp_buf); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); rc = cifs_check_receive(midQ, ses->server, 0); out: cifs_delete_mid(midQ); if (rstart && rc == -EACCES) return -ERESTARTSYS; return rc; }
int SendReceive(const unsigned int xid, struct cifs_ses *ses, struct smb_hdr *in_buf, struct smb_hdr *out_buf, int *pbytes_returned, const int timeout) { int rc = 0; struct mid_q_entry *midQ; if (ses == NULL) { cifs_dbg(VFS, "Null smb session\n"); return -EIO; } if (ses->server == NULL) { cifs_dbg(VFS, "Null tcp session\n"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) return -ENOENT; /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", be32_to_cpu(in_buf->smb_buf_length)); return -EIO; } rc = wait_for_free_request(ses->server, timeout, 0); if (rc) return rc; /* make sure that we sign in the same order that we send on this socket and avoid races inside tcp sendmsg code that could cause corruption of smb data */ mutex_lock(&ses->server->srv_mutex); rc = allocate_mid(ses, in_buf, &midQ); if (rc) { mutex_unlock(&ses->server->srv_mutex); /* Update # of requests on wire to server */ add_credits(ses->server, 1, 0); return rc; } rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); if (rc) { mutex_unlock(&ses->server->srv_mutex); goto out; } midQ->mid_state = MID_REQUEST_SUBMITTED; cifs_in_send_inc(ses->server); rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); cifs_in_send_dec(ses->server); cifs_save_when_sent(midQ); if (rc < 0) ses->server->sequence_number -= 2; mutex_unlock(&ses->server->srv_mutex); if (rc < 0) goto out; if (timeout == CIFS_ASYNC_OP) goto out; rc = wait_for_response(ses->server, midQ); if (rc != 0) { send_cancel(ses->server, in_buf, midQ); spin_lock(&GlobalMid_Lock); if (midQ->mid_state == MID_REQUEST_SUBMITTED) { /* no longer considered to be "in-flight" */ midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); add_credits(ses->server, 1, 0); return rc; } spin_unlock(&GlobalMid_Lock); } rc = cifs_sync_mid_result(midQ, ses->server); if (rc != 0) { add_credits(ses->server, 1, 0); return rc; } if (!midQ->resp_buf || !out_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) { rc = -EIO; cifs_dbg(VFS, "Bad MID state?\n"); goto out; } *pbytes_returned = get_rfc1002_length(midQ->resp_buf); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); rc = cifs_check_receive(midQ, ses->server, 0); out: cifs_delete_mid(midQ); add_credits(ses->server, 1, 0); return rc; }
int SendReceive2(const unsigned int xid, struct cifs_ses *ses, struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, const int flags) { int rc = 0; int timeout, optype; struct mid_q_entry *midQ; char *buf = iov[0].iov_base; unsigned int credits = 1; struct smb_rqst rqst = { .rq_iov = iov, .rq_nvec = n_vec }; timeout = flags & CIFS_TIMEOUT_MASK; optype = flags & CIFS_OP_MASK; *resp_buf_type = CIFS_NO_BUFFER; /* no response buf yet */ if ((ses == NULL) || (ses->server == NULL)) { cifs_small_buf_release(buf); cifs_dbg(VFS, "Null session\n"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) { cifs_small_buf_release(buf); return -ENOENT; } /* * Ensure that we do not send more than 50 overlapping requests * to the same server. We may make this configurable later or * use ses->maxReq. */ rc = wait_for_free_request(ses->server, timeout, optype); if (rc) { cifs_small_buf_release(buf); return rc; } /* * Make sure that we sign in the same order that we send on this socket * and avoid races inside tcp sendmsg code that could cause corruption * of smb data. */ mutex_lock(&ses->server->srv_mutex); midQ = ses->server->ops->setup_request(ses, &rqst); if (IS_ERR(midQ)) { mutex_unlock(&ses->server->srv_mutex); cifs_small_buf_release(buf); /* Update # of requests on wire to server */ add_credits(ses->server, 1, optype); return PTR_ERR(midQ); } midQ->mid_state = MID_REQUEST_SUBMITTED; cifs_in_send_inc(ses->server); rc = smb_sendv(ses->server, iov, n_vec); cifs_in_send_dec(ses->server); cifs_save_when_sent(midQ); if (rc < 0) ses->server->sequence_number -= 2; mutex_unlock(&ses->server->srv_mutex); if (rc < 0) { cifs_small_buf_release(buf); goto out; } if (timeout == CIFS_ASYNC_OP) { cifs_small_buf_release(buf); goto out; } rc = wait_for_response(ses->server, midQ); if (rc != 0) { send_cancel(ses->server, buf, midQ); spin_lock(&GlobalMid_Lock); if (midQ->mid_state == MID_REQUEST_SUBMITTED) { midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); cifs_small_buf_release(buf); add_credits(ses->server, 1, optype); return rc; } spin_unlock(&GlobalMid_Lock); } cifs_small_buf_release(buf); rc = cifs_sync_mid_result(midQ, ses->server); if (rc != 0) { add_credits(ses->server, 1, optype); return rc; } if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) { rc = -EIO; cifs_dbg(FYI, "Bad MID state?\n"); goto out; } buf = (char *)midQ->resp_buf; iov[0].iov_base = buf; iov[0].iov_len = get_rfc1002_length(buf) + 4; if (midQ->large_buf) *resp_buf_type = CIFS_LARGE_BUFFER; else *resp_buf_type = CIFS_SMALL_BUFFER; credits = ses->server->ops->get_credits(midQ); rc = ses->server->ops->check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR); /* mark it so buf will not be freed by cifs_delete_mid */ if ((flags & CIFS_NO_RESP) == 0) midQ->resp_buf = NULL; out: cifs_delete_mid(midQ); add_credits(ses->server, credits, optype); return rc; }
static int get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *data, GPContext *context) { Camera *camera = data; int result = GP_ERROR_IO; enum { START, DATA, ABORT } state; int r, pid = 0, update = 0; uint64_t byteCount = 0; struct utimbuf mod_utime_buf = { 0, 0 }; char *path; struct tf_packet reply; if (type != GP_FILE_TYPE_NORMAL) return GP_ERROR_NOT_SUPPORTED; do_cmd_turbo (camera, "ON", context); path = get_path(camera, folder, filename); r = send_cmd_hdd_file_send(camera, GET, path, context); free (path); if(r < 0) goto out; state = START; while(0 < (r = get_tf_packet(camera, &reply, context))) { update = (update + 1) % 4; switch (get_u32(&reply.cmd)) { case DATA_HDD_FILE_START: if(state == START) { struct typefile *tf = (struct typefile *) reply.data; byteCount = get_u64(&tf->size); pid = gp_context_progress_start (context, byteCount, _("Downloading %s..."), filename); mod_utime_buf.actime = mod_utime_buf.modtime = tfdt_to_time(&tf->stamp); send_success(camera,context); state = DATA; } else { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_START packet in state %d\n", state); send_cancel(camera,context); state = ABORT; } break; case DATA_HDD_FILE_DATA: if(state == DATA) { uint64_t offset = get_u64(reply.data); uint16_t dataLen = get_u16(&reply.length) - (PACKET_HEAD_SIZE + 8); int w; if (!update) { /* avoid doing it too often */ gp_context_progress_update (context, pid, offset + dataLen); if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) { send_cancel(camera,context); state = ABORT; } } if(r < get_u16(&reply.length)) { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Short packet %d instead of %d\n", r, get_u16(&reply.length)); /* TODO: Fetch the rest of the packet */ } w = gp_file_append (file, (char*)&reply.data[8], dataLen); if(w < GP_OK) { /* Can't write data - abort transfer */ gp_log (GP_LOG_ERROR, "topfield", "ERROR: Can not write data: %d\n", w); send_cancel(camera,context); state = ABORT; } } else { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_DATA packet in state %d\n", state); send_cancel(camera,context); state = ABORT; } break; case DATA_HDD_FILE_END: send_success(camera,context); result = GP_OK; goto out; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); send_cancel(camera,context); state = ABORT; break; case SUCCESS: goto out; break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet (cmd 0x%x)\n", get_u32(&reply.cmd)); break; } } if (pid) gp_context_progress_stop (context, pid); out: do_cmd_turbo (camera, "OFF", context); return result; }
void Touch::sendCancel() { if (m_focusResource) send_cancel(m_focusResource->handle); }
//return REACHED if position reached, OBSTACLE if stopped because of obstacle A CUSTOM STOP MESSAGE MUST BE SENT, CUSTOM_STOP_MESSAGE if stopped because a custom message was sent //robot position is updated //position is reached running for distance in steps <=200 (first the dist%200 than n steps dist/200) //it sleeps 1s after each step int go_to_position(pos_t target_pos, int margin, int speed){ int32_t tacho_dist, start_tacho, end_tacho; int angle, dist; int i; if(robot_rank == 0) while(wait); compute_polar_coord(target_pos, &dist, &angle,margin); target_pos.x = robot.x + dist*sin(angle*M_PI/180); target_pos.y = robot.y + dist*cos(angle*M_PI/180); //start movement, in two steps if bigger than 200 int div = dist/200; int mod = dist%200; int step; for(i = 0; i < div+1 ; i++){ if(i == div) step = mod; else step = 200; if(robot_rank == 0 && send_action_flag) send_action(next, angle, step, speed/2); //vado alla posizione set_motors_speed(SLOW_SPEED); turn_absolute_fb(angle, get_cal_location(robot.x,robot.y)); //aggiorno posizione final; robot.t = angle;//get_gyro_value(); printf("robot.t = %d\n",robot.t); //save initial tacho counts start_tacho=get_motorR_position(); set_motors_speed(speed); run_relative((int)(step*360.0/18)); while(!command_finish()){ if(cancel){ //cancel = 0; run_relative(0); end_tacho = get_motorR_position(); tacho_dist = end_tacho-start_tacho; dist = tacho_dist/20.0; robot.x = robot.x + dist*sin(robot.t*M_PI/180); robot.y = robot.y + dist*cos(robot.t*M_PI/180); printf("\n\n>>>>>>>>pos %d %d %d\n\n",robot.x,robot.y,robot.t); if(send_action_flag) send_cancel(next, dist); // Send to ourself an action in order came closer act_val.dist = cancel - dist; act_val.angle = robot.t; act++; return CUSTOM_STOP_MESSAGE; } if(obstacle()){ run_relative(0); end_tacho = get_motorR_position(); tacho_dist = end_tacho-start_tacho; dist = tacho_dist/20.0; printf("step %d dist %d\n",step,dist); if(step-dist < STOP_DIST*18/360.0){ set_motors_speed(speed); run_relative((int)((step-dist)*360.0/18)); return REACHED; } printf("tacho dist %ld dist %ld\n",tacho_dist,dist); robot.x = robot.x + dist*sin(robot.t*M_PI/180); robot.y = robot.y + dist*cos(robot.t*M_PI/180); printf("\n\n>>>>>>>>pos %d %d %d\n\n",robot.x,robot.y,robot.t); if(send_action_flag) send_cancel(next,dist); // HERE WE MUST SEND A CUSTOM MESSAGE STOP TO FOLLOWING ROBOT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // HERE WE MUST SEND A CUSTOM MESSAGE STOP TO FOLLOWING ROBOT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! return OBSTACLE; } } sleep(1); } //update pos robot.x = target_pos.x; robot.y = target_pos.y; printf("\n\n>>>>>>>>pos %d %d %d\n\n",robot.x,robot.y,robot.t); return REACHED; }
int compound_send_recv(const unsigned int xid, struct cifs_ses *ses, const int flags, const int num_rqst, struct smb_rqst *rqst, int *resp_buf_type, struct kvec *resp_iov) { int i, j, rc = 0; int timeout, optype; struct mid_q_entry *midQ[MAX_COMPOUND]; bool cancelled_mid[MAX_COMPOUND] = {false}; unsigned int credits[MAX_COMPOUND] = {0}; char *buf; timeout = flags & CIFS_TIMEOUT_MASK; optype = flags & CIFS_OP_MASK; for (i = 0; i < num_rqst; i++) resp_buf_type[i] = CIFS_NO_BUFFER; /* no response buf yet */ if ((ses == NULL) || (ses->server == NULL)) { cifs_dbg(VFS, "Null session\n"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) return -ENOENT; /* * Ensure we obtain 1 credit per request in the compound chain. * It can be optimized further by waiting for all the credits * at once but this can wait long enough if we don't have enough * credits due to some heavy operations in progress or the server * not granting us much, so a fallback to the current approach is * needed anyway. */ for (i = 0; i < num_rqst; i++) { rc = wait_for_free_request(ses->server, timeout, optype); if (rc) { /* * We haven't sent an SMB packet to the server yet but * we already obtained credits for i requests in the * compound chain - need to return those credits back * for future use. Note that we need to call add_credits * multiple times to match the way we obtained credits * in the first place and to account for in flight * requests correctly. */ for (j = 0; j < i; j++) add_credits(ses->server, 1, optype); return rc; } credits[i] = 1; } /* * Make sure that we sign in the same order that we send on this socket * and avoid races inside tcp sendmsg code that could cause corruption * of smb data. */ mutex_lock(&ses->server->srv_mutex); for (i = 0; i < num_rqst; i++) { midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]); if (IS_ERR(midQ[i])) { for (j = 0; j < i; j++) cifs_delete_mid(midQ[j]); mutex_unlock(&ses->server->srv_mutex); /* Update # of requests on wire to server */ for (j = 0; j < num_rqst; j++) add_credits(ses->server, credits[j], optype); return PTR_ERR(midQ[i]); } midQ[i]->mid_state = MID_REQUEST_SUBMITTED; midQ[i]->optype = optype; /* * Invoke callback for every part of the compound chain * to calculate credits properly. Wake up this thread only when * the last element is received. */ if (i < num_rqst - 1) midQ[i]->callback = cifs_compound_callback; else midQ[i]->callback = cifs_compound_last_callback; } cifs_in_send_inc(ses->server); rc = smb_send_rqst(ses->server, num_rqst, rqst, flags); cifs_in_send_dec(ses->server); for (i = 0; i < num_rqst; i++) cifs_save_when_sent(midQ[i]); if (rc < 0) ses->server->sequence_number -= 2; mutex_unlock(&ses->server->srv_mutex); if (rc < 0) { /* Sending failed for some reason - return credits back */ for (i = 0; i < num_rqst; i++) add_credits(ses->server, credits[i], optype); goto out; } /* * At this point the request is passed to the network stack - we assume * that any credits taken from the server structure on the client have * been spent and we can't return them back. Once we receive responses * we will collect credits granted by the server in the mid callbacks * and add those credits to the server structure. */ /* * Compounding is never used during session establish. */ if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) smb311_update_preauth_hash(ses, rqst[0].rq_iov, rqst[0].rq_nvec); if (timeout == CIFS_ASYNC_OP) goto out; for (i = 0; i < num_rqst; i++) { rc = wait_for_response(ses->server, midQ[i]); if (rc != 0) break; } if (rc != 0) { for (; i < num_rqst; i++) { cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n", midQ[i]->mid, le16_to_cpu(midQ[i]->command)); send_cancel(ses->server, &rqst[i], midQ[i]); spin_lock(&GlobalMid_Lock); if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { midQ[i]->mid_flags |= MID_WAIT_CANCELLED; midQ[i]->callback = cifs_cancelled_callback; cancelled_mid[i] = true; credits[i] = 0; } spin_unlock(&GlobalMid_Lock); } } for (i = 0; i < num_rqst; i++) { if (rc < 0) goto out; rc = cifs_sync_mid_result(midQ[i], ses->server); if (rc != 0) { /* mark this mid as cancelled to not free it below */ cancelled_mid[i] = true; goto out; } if (!midQ[i]->resp_buf || midQ[i]->mid_state != MID_RESPONSE_RECEIVED) { rc = -EIO; cifs_dbg(FYI, "Bad MID state?\n"); goto out; } buf = (char *)midQ[i]->resp_buf; resp_iov[i].iov_base = buf; resp_iov[i].iov_len = midQ[i]->resp_buf_size + ses->server->vals->header_preamble_size; if (midQ[i]->large_buf) resp_buf_type[i] = CIFS_LARGE_BUFFER; else resp_buf_type[i] = CIFS_SMALL_BUFFER; rc = ses->server->ops->check_receive(midQ[i], ses->server, flags & CIFS_LOG_ERROR); /* mark it so buf will not be freed by cifs_delete_mid */ if ((flags & CIFS_NO_RESP) == 0) midQ[i]->resp_buf = NULL; } /* * Compounding is never used during session establish. */ if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { struct kvec iov = { .iov_base = resp_iov[0].iov_base, .iov_len = resp_iov[0].iov_len }; smb311_update_preauth_hash(ses, &iov, 1); } out: /* * This will dequeue all mids. After this it is important that the * demultiplex_thread will not process any of these mids any futher. * This is prevented above by using a noop callback that will not * wake this thread except for the very last PDU. */ for (i = 0; i < num_rqst; i++) { if (!cancelled_mid[i]) cifs_delete_mid(midQ[i]); } return rc; } int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, struct smb_rqst *rqst, int *resp_buf_type, const int flags, struct kvec *resp_iov) { return compound_send_recv(xid, ses, flags, 1, rqst, resp_buf_type, resp_iov); } int SendReceive2(const unsigned int xid, struct cifs_ses *ses, struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, const int flags, struct kvec *resp_iov) { struct smb_rqst rqst; struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov; int rc; if (n_vec + 1 > CIFS_MAX_IOV_SIZE) { new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec), GFP_KERNEL); if (!new_iov) { /* otherwise cifs_send_recv below sets resp_buf_type */ *resp_buf_type = CIFS_NO_BUFFER; return -ENOMEM; } } else new_iov = s_iov; /* 1st iov is a RFC1001 length followed by the rest of the packet */ memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); new_iov[0].iov_base = new_iov[1].iov_base; new_iov[0].iov_len = 4; new_iov[1].iov_base += 4; new_iov[1].iov_len -= 4; memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = new_iov; rqst.rq_nvec = n_vec + 1; rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov); if (n_vec + 1 > CIFS_MAX_IOV_SIZE) kfree(new_iov); return rc; } int SendReceive(const unsigned int xid, struct cifs_ses *ses, struct smb_hdr *in_buf, struct smb_hdr *out_buf, int *pbytes_returned, const int timeout) { int rc = 0; struct mid_q_entry *midQ; unsigned int len = be32_to_cpu(in_buf->smb_buf_length); struct kvec iov = { .iov_base = in_buf, .iov_len = len }; struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; if (ses == NULL) { cifs_dbg(VFS, "Null smb session\n"); return -EIO; } if (ses->server == NULL) { cifs_dbg(VFS, "Null tcp session\n"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) return -ENOENT; /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", len); return -EIO; } rc = wait_for_free_request(ses->server, timeout, 0); if (rc) return rc; /* make sure that we sign in the same order that we send on this socket and avoid races inside tcp sendmsg code that could cause corruption of smb data */ mutex_lock(&ses->server->srv_mutex); rc = allocate_mid(ses, in_buf, &midQ); if (rc) { mutex_unlock(&ses->server->srv_mutex); /* Update # of requests on wire to server */ add_credits(ses->server, 1, 0); return rc; } rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); if (rc) { mutex_unlock(&ses->server->srv_mutex); goto out; } midQ->mid_state = MID_REQUEST_SUBMITTED; cifs_in_send_inc(ses->server); rc = smb_send(ses->server, in_buf, len); cifs_in_send_dec(ses->server); cifs_save_when_sent(midQ); if (rc < 0) ses->server->sequence_number -= 2; mutex_unlock(&ses->server->srv_mutex); if (rc < 0) goto out; if (timeout == CIFS_ASYNC_OP) goto out; rc = wait_for_response(ses->server, midQ); if (rc != 0) { send_cancel(ses->server, &rqst, midQ); spin_lock(&GlobalMid_Lock); if (midQ->mid_state == MID_REQUEST_SUBMITTED) { /* no longer considered to be "in-flight" */ midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); add_credits(ses->server, 1, 0); return rc; } spin_unlock(&GlobalMid_Lock); } rc = cifs_sync_mid_result(midQ, ses->server); if (rc != 0) { add_credits(ses->server, 1, 0); return rc; } if (!midQ->resp_buf || !out_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) { rc = -EIO; cifs_dbg(VFS, "Bad MID state?\n"); goto out; } *pbytes_returned = get_rfc1002_length(midQ->resp_buf); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); rc = cifs_check_receive(midQ, ses->server, 0); out: cifs_delete_mid(midQ); add_credits(ses->server, 1, 0); return rc; } /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows blocking lock to return. */ static int send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, struct smb_hdr *in_buf, struct smb_hdr *out_buf) { int bytes_returned; struct cifs_ses *ses = tcon->ses; LOCK_REQ *pSMB = (LOCK_REQ *)in_buf; /* We just modify the current in_buf to change the type of lock from LOCKING_ANDX_SHARED_LOCK or LOCKING_ANDX_EXCLUSIVE_LOCK to LOCKING_ANDX_CANCEL_LOCK. */ pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; pSMB->Timeout = 0; pSMB->hdr.Mid = get_next_mid(ses->server); return SendReceive(xid, ses, in_buf, out_buf, &bytes_returned, 0); }
/* message handling routine */ void p_handle(int b) { int i,k,len,tid,tag; jobinfo *j; jobinfo tj; pvm_bufinfo(b,&len,&tag,&tid); switch (tag) { case TAG_HELLO: if (master) { wtid = realloc(wtid,sizeof(int) * ++nw); wtid[nw-1] = tid; for (i=1;i<nw;i++) { pvm_initsend(0); k = i << BASE_SHIFT; pvm_pkint(&k,1,1); pvm_pkint(&nw,1,1); pvm_pkint(wtid,nw,1); pvm_send(wtid[i],TAG_WORKERS); } } break; case TAG_WORKERS: pvm_upkint(&nextjid,1,1); nextjid <<= BASE_SHIFT; pvm_upkint(&nw,1,1); free(wtid); wtid = malloc(sizeof(int) * nw); pvm_upkint(wtid,nw,1); break; case TAG_KILL: die("Received TAG_KILL. Too lazy to do anything useful.\n"); case TAG_REQUEST: if (j = freejob()) { pvm_initsend(0); pkjobinfo_active(j); pvm_send(tid,TAG_JOB); add_stolen(tid,j->jid); free(j); } else if (!victim(tid)) { pvm_initsend(0); pvm_send(tid,TAG_NO_JOB); } break; case TAG_DONE: upkjobinfo_done(&tj); if (cj && cj->jid == tj.pjid) slow_absorb(cj,&tj.s); else if (!tj.jid && master) { j = malloc(sizeof(jobinfo)); *j = tj; add_jobarray(j); } else if ((i = find_jobarray(tj.pjid)) >= 0) { slow_absorb(ja[i],&tj.s); if (ja[i]->status == JOB_DONE && !(!ja[i]->jid && master)) { send_done(ja[i]); free(ja[i]); del_jobarray(i); } } else if (tj.tid = find_stolen(tj.pjid)) // if 0, job was cancelled send_done(&tj); break; case TAG_CANCEL: pvm_upkint(&k,1,1); if (cj && cj->jid == k) { cj->status = JOB_CANCELLED; if (p_head > 0) cancel_children(cj); p_head = 1000; add_stolen(0,cj->jid); } else if ((i = find_jobarray(k)) >= 0) { cancel_children(ja[i]); add_stolen(0,ja[i]->jid); free(ja[i]); del_jobarray(i); } else if (tid = find_stolen(k)) send_cancel(tid,k); break; case TAG_STAT: default: die("Warning: ignoring invalid message\n"); } }
/* cancel all active children of a process */ void cancel_children(jobinfo *j) { for (i=0;i<j->n;i++) // abort child jobs if (j->js[i] == JOB_TAKEN) send_cancel(j->ctid[i],j->cjid[i]); }
int compound_send_recv(const unsigned int xid, struct cifs_ses *ses, const int flags, const int num_rqst, struct smb_rqst *rqst, int *resp_buf_type, struct kvec *resp_iov) { int i, j, rc = 0; int timeout, optype; struct mid_q_entry *midQ[MAX_COMPOUND]; unsigned int credits = 1; char *buf; timeout = flags & CIFS_TIMEOUT_MASK; optype = flags & CIFS_OP_MASK; for (i = 0; i < num_rqst; i++) resp_buf_type[i] = CIFS_NO_BUFFER; /* no response buf yet */ if ((ses == NULL) || (ses->server == NULL)) { cifs_dbg(VFS, "Null session\n"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) return -ENOENT; /* * Ensure that we do not send more than 50 overlapping requests * to the same server. We may make this configurable later or * use ses->maxReq. */ rc = wait_for_free_request(ses->server, timeout, optype); if (rc) return rc; /* * Make sure that we sign in the same order that we send on this socket * and avoid races inside tcp sendmsg code that could cause corruption * of smb data. */ mutex_lock(&ses->server->srv_mutex); for (i = 0; i < num_rqst; i++) { midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]); if (IS_ERR(midQ[i])) { for (j = 0; j < i; j++) cifs_delete_mid(midQ[j]); mutex_unlock(&ses->server->srv_mutex); /* Update # of requests on wire to server */ add_credits(ses->server, 1, optype); return PTR_ERR(midQ[i]); } midQ[i]->mid_state = MID_REQUEST_SUBMITTED; /* * We don't invoke the callback compounds unless it is the last * request. */ if (i < num_rqst - 1) midQ[i]->callback = cifs_noop_callback; } cifs_in_send_inc(ses->server); rc = smb_send_rqst(ses->server, num_rqst, rqst, flags); cifs_in_send_dec(ses->server); for (i = 0; i < num_rqst; i++) cifs_save_when_sent(midQ[i]); if (rc < 0) ses->server->sequence_number -= 2; mutex_unlock(&ses->server->srv_mutex); for (i = 0; i < num_rqst; i++) { if (rc < 0) goto out; if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) smb311_update_preauth_hash(ses, rqst[i].rq_iov, rqst[i].rq_nvec); if (timeout == CIFS_ASYNC_OP) goto out; rc = wait_for_response(ses->server, midQ[i]); if (rc != 0) { cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ[i]->mid); send_cancel(ses->server, &rqst[i], midQ[i]); spin_lock(&GlobalMid_Lock); if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { midQ[i]->mid_flags |= MID_WAIT_CANCELLED; midQ[i]->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); add_credits(ses->server, 1, optype); return rc; } spin_unlock(&GlobalMid_Lock); } rc = cifs_sync_mid_result(midQ[i], ses->server); if (rc != 0) { add_credits(ses->server, 1, optype); return rc; } if (!midQ[i]->resp_buf || midQ[i]->mid_state != MID_RESPONSE_RECEIVED) { rc = -EIO; cifs_dbg(FYI, "Bad MID state?\n"); goto out; } buf = (char *)midQ[i]->resp_buf; resp_iov[i].iov_base = buf; resp_iov[i].iov_len = midQ[i]->resp_buf_size + ses->server->vals->header_preamble_size; if (midQ[i]->large_buf) resp_buf_type[i] = CIFS_LARGE_BUFFER; else resp_buf_type[i] = CIFS_SMALL_BUFFER; if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { struct kvec iov = { .iov_base = resp_iov[i].iov_base, .iov_len = resp_iov[i].iov_len }; smb311_update_preauth_hash(ses, &iov, 1); } credits = ses->server->ops->get_credits(midQ[i]); rc = ses->server->ops->check_receive(midQ[i], ses->server, flags & CIFS_LOG_ERROR); /* mark it so buf will not be freed by cifs_delete_mid */ if ((flags & CIFS_NO_RESP) == 0) midQ[i]->resp_buf = NULL; } out: /* * This will dequeue all mids. After this it is important that the * demultiplex_thread will not process any of these mids any futher. * This is prevented above by using a noop callback that will not * wake this thread except for the very last PDU. */ for (i = 0; i < num_rqst; i++) cifs_delete_mid(midQ[i]); add_credits(ses->server, credits, optype); return rc; } int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, struct smb_rqst *rqst, int *resp_buf_type, const int flags, struct kvec *resp_iov) { return compound_send_recv(xid, ses, flags, 1, rqst, resp_buf_type, resp_iov); } int SendReceive2(const unsigned int xid, struct cifs_ses *ses, struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, const int flags, struct kvec *resp_iov) { struct smb_rqst rqst; struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov; int rc; if (n_vec + 1 > CIFS_MAX_IOV_SIZE) { new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec), GFP_KERNEL); if (!new_iov) { /* otherwise cifs_send_recv below sets resp_buf_type */ *resp_buf_type = CIFS_NO_BUFFER; return -ENOMEM; } } else new_iov = s_iov; /* 1st iov is a RFC1001 length followed by the rest of the packet */ memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); new_iov[0].iov_base = new_iov[1].iov_base; new_iov[0].iov_len = 4; new_iov[1].iov_base += 4; new_iov[1].iov_len -= 4; memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = new_iov; rqst.rq_nvec = n_vec + 1; rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov); if (n_vec + 1 > CIFS_MAX_IOV_SIZE) kfree(new_iov); return rc; } int SendReceive(const unsigned int xid, struct cifs_ses *ses, struct smb_hdr *in_buf, struct smb_hdr *out_buf, int *pbytes_returned, const int timeout) { int rc = 0; struct mid_q_entry *midQ; unsigned int len = be32_to_cpu(in_buf->smb_buf_length); struct kvec iov = { .iov_base = in_buf, .iov_len = len }; struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; if (ses == NULL) { cifs_dbg(VFS, "Null smb session\n"); return -EIO; } if (ses->server == NULL) { cifs_dbg(VFS, "Null tcp session\n"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) return -ENOENT; /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", len); return -EIO; } rc = wait_for_free_request(ses->server, timeout, 0); if (rc) return rc; /* make sure that we sign in the same order that we send on this socket and avoid races inside tcp sendmsg code that could cause corruption of smb data */ mutex_lock(&ses->server->srv_mutex); rc = allocate_mid(ses, in_buf, &midQ); if (rc) { mutex_unlock(&ses->server->srv_mutex); /* Update # of requests on wire to server */ add_credits(ses->server, 1, 0); return rc; } rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); if (rc) { mutex_unlock(&ses->server->srv_mutex); goto out; } midQ->mid_state = MID_REQUEST_SUBMITTED; cifs_in_send_inc(ses->server); rc = smb_send(ses->server, in_buf, len); cifs_in_send_dec(ses->server); cifs_save_when_sent(midQ); if (rc < 0) ses->server->sequence_number -= 2; mutex_unlock(&ses->server->srv_mutex); if (rc < 0) goto out; if (timeout == CIFS_ASYNC_OP) goto out; rc = wait_for_response(ses->server, midQ); if (rc != 0) { send_cancel(ses->server, &rqst, midQ); spin_lock(&GlobalMid_Lock); if (midQ->mid_state == MID_REQUEST_SUBMITTED) { /* no longer considered to be "in-flight" */ midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); add_credits(ses->server, 1, 0); return rc; } spin_unlock(&GlobalMid_Lock); } rc = cifs_sync_mid_result(midQ, ses->server); if (rc != 0) { add_credits(ses->server, 1, 0); return rc; } if (!midQ->resp_buf || !out_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) { rc = -EIO; cifs_dbg(VFS, "Bad MID state?\n"); goto out; } *pbytes_returned = get_rfc1002_length(midQ->resp_buf); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); rc = cifs_check_receive(midQ, ses->server, 0); out: cifs_delete_mid(midQ); add_credits(ses->server, 1, 0); return rc; } /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows blocking lock to return. */ static int send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, struct smb_hdr *in_buf, struct smb_hdr *out_buf) { int bytes_returned; struct cifs_ses *ses = tcon->ses; LOCK_REQ *pSMB = (LOCK_REQ *)in_buf; /* We just modify the current in_buf to change the type of lock from LOCKING_ANDX_SHARED_LOCK or LOCKING_ANDX_EXCLUSIVE_LOCK to LOCKING_ANDX_CANCEL_LOCK. */ pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; pSMB->Timeout = 0; pSMB->hdr.Mid = get_next_mid(ses->server); return SendReceive(xid, ses, in_buf, out_buf, &bytes_returned, 0); }
int do_hdd_file_get(int fd, char *srcPath, char *dstPath) { int result = -EPROTO; time_t startTime = time(NULL); enum { START, DATA, ABORT } state; int dst = -1; int r; int update = 0; __u64 byteCount = 0; struct utimbuf mod_utime_buf = { 0, 0 }; dst = open64(dstPath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if(dst < 0) { fprintf(stderr, "ERROR: Can not open destination file: %s\n", strerror(errno)); return errno; } r = send_cmd_hdd_file_send(fd, GET, srcPath); if(r < 0) { goto out; } state = START; while(0 < (r = get_tf_packet(fd, &reply))) { update = (update + 1) % 16; switch (get_u32(&reply.cmd)) { case DATA_HDD_FILE_START: if(state == START) { struct typefile *tf = (struct typefile *) reply.data; byteCount = get_u64(&tf->size); mod_utime_buf.actime = mod_utime_buf.modtime = tfdt_to_time(&tf->stamp); send_success(fd); state = DATA; } else { fprintf(stderr, "ERROR: Unexpected DATA_HDD_FILE_START packet in state %d\n", state); send_cancel(fd); state = ABORT; } break; case DATA_HDD_FILE_DATA: if(state == DATA) { __u64 offset = get_u64(reply.data); __u16 dataLen = get_u16(&reply.length) - (PACKET_HEAD_SIZE + 8); ssize_t w; if(!update && !quiet) { progressStats(byteCount, offset + dataLen, startTime); } if(r < get_u16(&reply.length)) { fprintf(stderr, "ERROR: Short packet %d instead of %d\n", r, get_u16(&reply.length)); /* TODO: Fetch the rest of the packet */ } w = write(dst, &reply.data[8], dataLen); if(w < dataLen) { /* Can't write data - abort transfer */ fprintf(stderr, "ERROR: Can not write data: %s\n", strerror(errno)); send_cancel(fd); state = ABORT; } } else { fprintf(stderr, "ERROR: Unexpected DATA_HDD_FILE_DATA packet in state %d\n", state); send_cancel(fd); state = ABORT; } break; case DATA_HDD_FILE_END: send_success(fd); result = 0; goto out; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); send_cancel(fd); state = ABORT; break; case SUCCESS: goto out; break; default: fprintf(stderr, "ERROR: Unhandled packet (cmd 0x%x)\n", get_u32(&reply.cmd)); } } utime(dstPath, &mod_utime_buf); finalStats(byteCount, startTime); out: close(dst); return result; }