// SPDX-License-Identifier: LGPL-2.1 /* * * Copyright (C) International Business Machines Corp., 2002,2008 * Author(s): Steve French (sfrench@us.ibm.com) * Jeremy Allison (jra@samba.org) 2006. *
*/
temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
memset(temp, 0, sizeof(struct mid_q_entry));
kref_init(&temp->refcount);
spin_lock_init(&temp->mid_lock);
temp->mid = get_mid(smb_buffer);
temp->pid = current->pid;
temp->command = cpu_to_le16(smb_buffer->Command);
cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); /* easier to use jiffies */ /* when mid allocated can be before when sent */
temp->when_alloc = jiffies;
temp->server = server;
/* * The default is for the mid to be synchronous, so the * default callback just wakes up the current task.
*/
get_task_struct(current);
temp->creator = current;
temp->callback = cifs_wake_up_task;
temp->callback_data = current;
staticint allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, struct mid_q_entry **ppmidQ)
{
spin_lock(&ses->ses_lock); if (ses->ses_status == SES_NEW) { if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) {
spin_unlock(&ses->ses_lock); return -EAGAIN;
} /* else ok - we are setting up session */
}
if (ses->ses_status == SES_EXITING) { /* check if SMB session is bad because we are setting it up */ if (in_buf->Command != SMB_COM_LOGOFF_ANDX) {
spin_unlock(&ses->ses_lock); return -EAGAIN;
} /* else ok - we are shutting down session */
}
spin_unlock(&ses->ses_lock);
/* * * Send an SMB Request. No response info (other than return code) * needs to be parsed. * * flags indicate the type of request buffer and how long to wait * and whether to log NT STATUS code (error) before mapping it to POSIX error *
*/ int
SendReceiveNoRsp(constunsignedint xid, struct cifs_ses *ses, char *in_buf, int flags)
{ int rc; struct kvec iov[1]; struct kvec rsp_iov; int resp_buf_type;
int
cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error)
{ unsignedint len = get_rfc1002_length(mid->resp_buf) + 4;
dump_smb(mid->resp_buf, min_t(u32, 92, len));
/* convert the length into a more usable form */ if (server->sign) { struct kvec iov[2]; int rc = 0; struct smb_rqst rqst = { .rq_iov = iov,
.rq_nvec = 2 };
/* 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_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
len); return -EIO;
}
rc = wait_for_free_request(server, flags, &credits.instance); 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 */
cifs_server_lock(server);
rc = allocate_mid(ses, in_buf, &midQ); if (rc) {
cifs_server_unlock(server); /* Update # of requests on wire to server */
add_credits(server, &credits, 0); return rc;
}
/* 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. */
/* 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_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
len); return -EIO;
}
rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance); 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 */
/* Wait for a reply - allow signals to interrupt. */
rc = wait_event_interruptible(server->response_q,
(!(midQ->mid_state == MID_REQUEST_SUBMITTED ||
midQ->mid_state == MID_RESPONSE_RECEIVED)) ||
((server->tcpStatus != CifsGood) &&
(server->tcpStatus != CifsNew)));
/* Were we interrupted by a signal ? */
spin_lock(&server->srv_lock); if ((rc == -ERESTARTSYS) &&
(midQ->mid_state == MID_REQUEST_SUBMITTED ||
midQ->mid_state == MID_RESPONSE_RECEIVED) &&
((server->tcpStatus == CifsGood) ||
(server->tcpStatus == CifsNew))) {
spin_unlock(&server->srv_lock);
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(server, &rqst, midQ); if (rc) {
delete_mid(midQ); return rc;
}
} else { /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
to cause the blocking lock to return. */
/* If we get -ENOLCK back the lock may have
already been removed. Don't exit in this case. */ if (rc && rc != -ENOLCK) {
delete_mid(midQ); return rc;
}
}
rc = wait_for_response(server, midQ); if (rc) {
send_cancel(server, &rqst, midQ);
spin_lock(&midQ->mid_lock); if (midQ->callback) { /* no longer considered to be "in-flight" */
midQ->callback = release_mid;
spin_unlock(&midQ->mid_lock); return rc;
}
spin_unlock(&midQ->mid_lock);
}
/* We got the response - restart system call. */
rstart = 1;
spin_lock(&server->srv_lock);
}
spin_unlock(&server->srv_lock);
rc = cifs_sync_mid_result(midQ, server); if (rc != 0) return rc;
/* rcvd frame is ok */ if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) {
rc = -EIO;
cifs_tcon_dbg(VFS, "Bad MID state?\n"); goto out;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.