Commit e2b76ab8 authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French

ksmbd: add support for read compound

MacOS sends a compound request including read to the server
(e.g. open-read-close). So far, ksmbd has not handled read as
a compound request. For compatibility between ksmbd and an OS that
supports SMB, This patch provides compound support for read requests.
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 084ba46f
...@@ -1029,11 +1029,15 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec, ...@@ -1029,11 +1029,15 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
{ {
struct scatterlist *sg; struct scatterlist *sg;
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0; int i, *nr_entries, total_entries = 0, sg_idx = 0;
if (!nvec) if (!nvec)
return NULL; return NULL;
nr_entries = kcalloc(nvec, sizeof(int), GFP_KERNEL);
if (!nr_entries)
return NULL;
for (i = 0; i < nvec - 1; i++) { for (i = 0; i < nvec - 1; i++) {
unsigned long kaddr = (unsigned long)iov[i + 1].iov_base; unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
...@@ -1051,8 +1055,10 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec, ...@@ -1051,8 +1055,10 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
total_entries += 2; total_entries += 2;
sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL); sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
if (!sg) if (!sg) {
kfree(nr_entries);
return NULL; return NULL;
}
sg_init_table(sg, total_entries); sg_init_table(sg, total_entries);
smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len); smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
...@@ -1086,6 +1092,7 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec, ...@@ -1086,6 +1092,7 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
} }
} }
smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE); smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
kfree(nr_entries);
return sg; return sg;
} }
......
...@@ -123,28 +123,22 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work) ...@@ -123,28 +123,22 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
} }
} }
int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work) void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
{ {
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
int ret = 1;
if (list_empty(&work->request_entry) && if (list_empty(&work->request_entry) &&
list_empty(&work->async_request_entry)) list_empty(&work->async_request_entry))
return 0; return;
if (!work->multiRsp)
atomic_dec(&conn->req_running); atomic_dec(&conn->req_running);
if (!work->multiRsp) {
spin_lock(&conn->request_lock); spin_lock(&conn->request_lock);
list_del_init(&work->request_entry); list_del_init(&work->request_entry);
spin_unlock(&conn->request_lock); spin_unlock(&conn->request_lock);
if (work->asynchronous) if (work->asynchronous)
release_async_work(work); release_async_work(work);
ret = 0;
}
wake_up_all(&conn->req_running_q); wake_up_all(&conn->req_running_q);
return ret;
} }
void ksmbd_conn_lock(struct ksmbd_conn *conn) void ksmbd_conn_lock(struct ksmbd_conn *conn)
...@@ -193,39 +187,20 @@ void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id) ...@@ -193,39 +187,20 @@ void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
int ksmbd_conn_write(struct ksmbd_work *work) int ksmbd_conn_write(struct ksmbd_work *work)
{ {
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
size_t len = 0;
int sent; int sent;
struct kvec iov[3];
int iov_idx = 0;
if (!work->response_buf) { if (!work->response_buf) {
pr_err("NULL response header\n"); pr_err("NULL response header\n");
return -EINVAL; return -EINVAL;
} }
if (work->tr_buf) { if (work->send_no_response)
iov[iov_idx] = (struct kvec) { work->tr_buf, return 0;
sizeof(struct smb2_transform_hdr) + 4 };
len += iov[iov_idx++].iov_len;
}
if (work->aux_payload_sz) {
iov[iov_idx] = (struct kvec) { work->response_buf, work->resp_hdr_sz };
len += iov[iov_idx++].iov_len;
iov[iov_idx] = (struct kvec) { work->aux_payload_buf, work->aux_payload_sz };
len += iov[iov_idx++].iov_len;
} else {
if (work->tr_buf)
iov[iov_idx].iov_len = work->resp_hdr_sz;
else
iov[iov_idx].iov_len = get_rfc1002_len(work->response_buf) + 4;
iov[iov_idx].iov_base = work->response_buf;
len += iov[iov_idx++].iov_len;
}
ksmbd_conn_lock(conn); ksmbd_conn_lock(conn);
sent = conn->transport->ops->writev(conn->transport, &iov[0], sent = conn->transport->ops->writev(conn->transport, work->iov,
iov_idx, len, work->iov_cnt,
get_rfc1002_len(work->iov[0].iov_base) + 4,
work->need_invalidate_rkey, work->need_invalidate_rkey,
work->remote_key); work->remote_key);
ksmbd_conn_unlock(conn); ksmbd_conn_unlock(conn);
......
...@@ -158,7 +158,7 @@ int ksmbd_conn_rdma_write(struct ksmbd_conn *conn, ...@@ -158,7 +158,7 @@ int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
struct smb2_buffer_desc_v1 *desc, struct smb2_buffer_desc_v1 *desc,
unsigned int desc_len); unsigned int desc_len);
void ksmbd_conn_enqueue_request(struct ksmbd_work *work); void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work); void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops); void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
int ksmbd_conn_handler_loop(void *p); int ksmbd_conn_handler_loop(void *p);
int ksmbd_conn_transport_init(void); int ksmbd_conn_transport_init(void);
......
...@@ -27,18 +27,35 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void) ...@@ -27,18 +27,35 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void)
INIT_LIST_HEAD(&work->async_request_entry); INIT_LIST_HEAD(&work->async_request_entry);
INIT_LIST_HEAD(&work->fp_entry); INIT_LIST_HEAD(&work->fp_entry);
INIT_LIST_HEAD(&work->interim_entry); INIT_LIST_HEAD(&work->interim_entry);
INIT_LIST_HEAD(&work->aux_read_list);
work->iov_alloc_cnt = 4;
work->iov = kcalloc(work->iov_alloc_cnt, sizeof(struct kvec),
GFP_KERNEL);
if (!work->iov) {
kmem_cache_free(work_cache, work);
work = NULL;
}
} }
return work; return work;
} }
void ksmbd_free_work_struct(struct ksmbd_work *work) void ksmbd_free_work_struct(struct ksmbd_work *work)
{ {
struct aux_read *ar, *tmp;
WARN_ON(work->saved_cred != NULL); WARN_ON(work->saved_cred != NULL);
kvfree(work->response_buf); kvfree(work->response_buf);
kvfree(work->aux_payload_buf);
list_for_each_entry_safe(ar, tmp, &work->aux_read_list, entry) {
kvfree(ar->buf);
list_del(&ar->entry);
kfree(ar);
}
kfree(work->tr_buf); kfree(work->tr_buf);
kvfree(work->request_buf); kvfree(work->request_buf);
kfree(work->iov);
if (work->async_id) if (work->async_id)
ksmbd_release_id(&work->conn->async_ida, work->async_id); ksmbd_release_id(&work->conn->async_ida, work->async_id);
kmem_cache_free(work_cache, work); kmem_cache_free(work_cache, work);
...@@ -77,3 +94,75 @@ bool ksmbd_queue_work(struct ksmbd_work *work) ...@@ -77,3 +94,75 @@ bool ksmbd_queue_work(struct ksmbd_work *work)
{ {
return queue_work(ksmbd_wq, &work->work); return queue_work(ksmbd_wq, &work->work);
} }
static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib,
unsigned int ib_len)
{
if (work->iov_alloc_cnt <= work->iov_cnt) {
struct kvec *new;
work->iov_alloc_cnt += 4;
new = krealloc(work->iov,
sizeof(struct kvec) * work->iov_alloc_cnt,
GFP_KERNEL | __GFP_ZERO);
if (!new)
return -ENOMEM;
work->iov = new;
}
work->iov[++work->iov_idx].iov_base = ib;
work->iov[work->iov_idx].iov_len = ib_len;
work->iov_cnt++;
return 0;
}
static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
void *aux_buf, unsigned int aux_size)
{
/* Plus rfc_length size on first iov */
if (!work->iov_idx) {
work->iov[work->iov_idx].iov_base = work->response_buf;
*(__be32 *)work->iov[0].iov_base = 0;
work->iov[work->iov_idx].iov_len = 4;
work->iov_cnt++;
}
ksmbd_realloc_iov_pin(work, ib, len);
inc_rfc1001_len(work->iov[0].iov_base, len);
if (aux_size) {
struct aux_read *ar;
ksmbd_realloc_iov_pin(work, aux_buf, aux_size);
inc_rfc1001_len(work->iov[0].iov_base, aux_size);
ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
if (!ar)
return -ENOMEM;
ar->buf = aux_buf;
list_add(&ar->entry, &work->aux_read_list);
}
return 0;
}
int ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len)
{
return __ksmbd_iov_pin_rsp(work, ib, len, NULL, 0);
}
int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
void *aux_buf, unsigned int aux_size)
{
return __ksmbd_iov_pin_rsp(work, ib, len, aux_buf, aux_size);
}
void ksmbd_iov_reset(struct ksmbd_work *work)
{
work->iov_idx = 0;
work->iov_cnt = 0;
*(__be32 *)work->iov[0].iov_base = 0;
}
...@@ -19,6 +19,11 @@ enum { ...@@ -19,6 +19,11 @@ enum {
KSMBD_WORK_CLOSED, KSMBD_WORK_CLOSED,
}; };
struct aux_read {
void *buf;
struct list_head entry;
};
/* one of these for every pending CIFS request at the connection */ /* one of these for every pending CIFS request at the connection */
struct ksmbd_work { struct ksmbd_work {
/* Server corresponding to this mid */ /* Server corresponding to this mid */
...@@ -31,13 +36,19 @@ struct ksmbd_work { ...@@ -31,13 +36,19 @@ struct ksmbd_work {
/* Response buffer */ /* Response buffer */
void *response_buf; void *response_buf;
/* Read data buffer */ struct list_head aux_read_list;
void *aux_payload_buf;
struct kvec *iov;
int iov_alloc_cnt;
int iov_cnt;
int iov_idx;
/* Next cmd hdr in compound req buf*/ /* Next cmd hdr in compound req buf*/
int next_smb2_rcv_hdr_off; int next_smb2_rcv_hdr_off;
/* Next cmd hdr in compound rsp buf*/ /* Next cmd hdr in compound rsp buf*/
int next_smb2_rsp_hdr_off; int next_smb2_rsp_hdr_off;
/* Current cmd hdr in compound rsp buf*/
int curr_smb2_rsp_hdr_off;
/* /*
* Current Local FID assigned compound response if SMB2 CREATE * Current Local FID assigned compound response if SMB2 CREATE
...@@ -53,16 +64,11 @@ struct ksmbd_work { ...@@ -53,16 +64,11 @@ struct ksmbd_work {
unsigned int credits_granted; unsigned int credits_granted;
/* response smb header size */ /* response smb header size */
unsigned int resp_hdr_sz;
unsigned int response_sz; unsigned int response_sz;
/* Read data count */
unsigned int aux_payload_sz;
void *tr_buf; void *tr_buf;
unsigned char state; unsigned char state;
/* Multiple responses for one request e.g. SMB ECHO */
bool multiRsp:1;
/* No response for cancelled request */ /* No response for cancelled request */
bool send_no_response:1; bool send_no_response:1;
/* Request is encrypted */ /* Request is encrypted */
...@@ -95,6 +101,15 @@ static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work) ...@@ -95,6 +101,15 @@ static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
return work->response_buf + work->next_smb2_rsp_hdr_off + 4; return work->response_buf + work->next_smb2_rsp_hdr_off + 4;
} }
/**
* ksmbd_resp_buf_curr - Get current buffer on compound response.
* @work: smb work containing response buffer
*/
static inline void *ksmbd_resp_buf_curr(struct ksmbd_work *work)
{
return work->response_buf + work->curr_smb2_rsp_hdr_off + 4;
}
/** /**
* ksmbd_req_buf_next - Get next buffer on compound request. * ksmbd_req_buf_next - Get next buffer on compound request.
* @work: smb work containing response buffer * @work: smb work containing response buffer
...@@ -113,5 +128,8 @@ int ksmbd_work_pool_init(void); ...@@ -113,5 +128,8 @@ int ksmbd_work_pool_init(void);
int ksmbd_workqueue_init(void); int ksmbd_workqueue_init(void);
void ksmbd_workqueue_destroy(void); void ksmbd_workqueue_destroy(void);
bool ksmbd_queue_work(struct ksmbd_work *work); bool ksmbd_queue_work(struct ksmbd_work *work);
int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
void *aux_buf, unsigned int aux_size);
int ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len);
void ksmbd_iov_reset(struct ksmbd_work *work);
#endif /* __KSMBD_WORK_H__ */ #endif /* __KSMBD_WORK_H__ */
...@@ -639,7 +639,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) ...@@ -639,7 +639,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
{ {
struct smb2_oplock_break *rsp = NULL; struct smb2_oplock_break *rsp = NULL;
struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work); struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
struct ksmbd_conn *conn = work->conn;
struct oplock_break_info *br_info = work->request_buf; struct oplock_break_info *br_info = work->request_buf;
struct smb2_hdr *rsp_hdr; struct smb2_hdr *rsp_hdr;
struct ksmbd_file *fp; struct ksmbd_file *fp;
...@@ -656,8 +655,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) ...@@ -656,8 +655,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp_hdr = smb2_get_msg(work->response_buf); rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2); memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER; rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0); rsp_hdr->CreditRequest = cpu_to_le16(0);
...@@ -684,13 +681,15 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) ...@@ -684,13 +681,15 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp->PersistentFid = fp->persistent_id; rsp->PersistentFid = fp->persistent_id;
rsp->VolatileFid = fp->volatile_id; rsp->VolatileFid = fp->volatile_id;
inc_rfc1001_len(work->response_buf, 24); ksmbd_fd_put(work, fp);
if (ksmbd_iov_pin_rsp(work, (void *)rsp,
sizeof(struct smb2_oplock_break)))
goto out;
ksmbd_debug(OPLOCK, ksmbd_debug(OPLOCK,
"sending oplock break v_id %llu p_id = %llu lock level = %d\n", "sending oplock break v_id %llu p_id = %llu lock level = %d\n",
rsp->VolatileFid, rsp->PersistentFid, rsp->OplockLevel); rsp->VolatileFid, rsp->PersistentFid, rsp->OplockLevel);
ksmbd_fd_put(work, fp);
ksmbd_conn_write(work); ksmbd_conn_write(work);
out: out:
...@@ -751,7 +750,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk) ...@@ -751,7 +750,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
struct smb2_lease_break *rsp = NULL; struct smb2_lease_break *rsp = NULL;
struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work); struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
struct lease_break_info *br_info = work->request_buf; struct lease_break_info *br_info = work->request_buf;
struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *rsp_hdr; struct smb2_hdr *rsp_hdr;
if (allocate_oplock_break_buf(work)) { if (allocate_oplock_break_buf(work)) {
...@@ -761,8 +759,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk) ...@@ -761,8 +759,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp_hdr = smb2_get_msg(work->response_buf); rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2); memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER; rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0); rsp_hdr->CreditRequest = cpu_to_le16(0);
...@@ -791,7 +787,9 @@ static void __smb2_lease_break_noti(struct work_struct *wk) ...@@ -791,7 +787,9 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp->AccessMaskHint = 0; rsp->AccessMaskHint = 0;
rsp->ShareMaskHint = 0; rsp->ShareMaskHint = 0;
inc_rfc1001_len(work->response_buf, 44); if (ksmbd_iov_pin_rsp(work, (void *)rsp,
sizeof(struct smb2_lease_break)))
goto out;
ksmbd_conn_write(work); ksmbd_conn_write(work);
...@@ -845,6 +843,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) ...@@ -845,6 +843,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
setup_async_work(in_work, NULL, NULL); setup_async_work(in_work, NULL, NULL);
smb2_send_interim_resp(in_work, STATUS_PENDING); smb2_send_interim_resp(in_work, STATUS_PENDING);
list_del(&in_work->interim_entry); list_del(&in_work->interim_entry);
ksmbd_iov_reset(in_work);
} }
INIT_WORK(&work->work, __smb2_lease_break_noti); INIT_WORK(&work->work, __smb2_lease_break_noti);
ksmbd_queue_work(work); ksmbd_queue_work(work);
......
...@@ -163,6 +163,7 @@ static void __handle_ksmbd_work(struct ksmbd_work *work, ...@@ -163,6 +163,7 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
{ {
u16 command = 0; u16 command = 0;
int rc; int rc;
bool is_chained = false;
if (conn->ops->allocate_rsp_buf(work)) if (conn->ops->allocate_rsp_buf(work))
return; return;
...@@ -229,14 +230,13 @@ static void __handle_ksmbd_work(struct ksmbd_work *work, ...@@ -229,14 +230,13 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
} }
} }
is_chained = is_chained_smb2_message(work);
if (work->sess && if (work->sess &&
(work->sess->sign || smb3_11_final_sess_setup_resp(work) || (work->sess->sign || smb3_11_final_sess_setup_resp(work) ||
conn->ops->is_sign_req(work, command))) conn->ops->is_sign_req(work, command)))
conn->ops->set_sign_rsp(work); conn->ops->set_sign_rsp(work);
} while (is_chained_smb2_message(work)); } while (is_chained == true);
if (work->send_no_response)
return;
send: send:
smb3_preauth_hash_rsp(work); smb3_preauth_hash_rsp(work);
......
This diff is collapsed.
...@@ -319,12 +319,6 @@ static int init_smb1_rsp_hdr(struct ksmbd_work *work) ...@@ -319,12 +319,6 @@ static int init_smb1_rsp_hdr(struct ksmbd_work *work)
struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf; struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf; struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
/*
* Remove 4 byte direct TCP header.
*/
*(__be32 *)work->response_buf =
cpu_to_be32(sizeof(struct smb_hdr) - 4);
rsp_hdr->Command = SMB_COM_NEGOTIATE; rsp_hdr->Command = SMB_COM_NEGOTIATE;
*(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER; *(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
rsp_hdr->Flags = SMBFLG_RESPONSE; rsp_hdr->Flags = SMBFLG_RESPONSE;
...@@ -560,10 +554,11 @@ static int smb_handle_negotiate(struct ksmbd_work *work) ...@@ -560,10 +554,11 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n"); ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
/* Add 2 byte bcc and 2 byte DialectIndex. */ if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp,
inc_rfc1001_len(work->response_buf, 4); sizeof(struct smb_negotiate_rsp) - 4))
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS; return -ENOMEM;
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
neg_rsp->hdr.WordCount = 1; neg_rsp->hdr.WordCount = 1;
neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect); neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
neg_rsp->ByteCount = 0; neg_rsp->ByteCount = 0;
......
...@@ -1241,14 +1241,12 @@ static int smb_direct_writev(struct ksmbd_transport *t, ...@@ -1241,14 +1241,12 @@ static int smb_direct_writev(struct ksmbd_transport *t,
//FIXME: skip RFC1002 header.. //FIXME: skip RFC1002 header..
buflen -= 4; buflen -= 4;
iov[0].iov_base += 4;
iov[0].iov_len -= 4;
remaining_data_length = buflen; remaining_data_length = buflen;
ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen); ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen);
smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key); smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key);
start = i = 0; start = i = 1;
buflen = 0; buflen = 0;
while (true) { while (true) {
buflen += iov[i].iov_len; buflen += iov[i].iov_len;
......
...@@ -367,15 +367,15 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end, ...@@ -367,15 +367,15 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end,
* @fid: file id of open file * @fid: file id of open file
* @count: read byte count * @count: read byte count
* @pos: file pos * @pos: file pos
* @rbuf: read data buffer
* *
* Return: number of read bytes on success, otherwise error * Return: number of read bytes on success, otherwise error
*/ */
int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count, int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
loff_t *pos) loff_t *pos, char *rbuf)
{ {
struct file *filp = fp->filp; struct file *filp = fp->filp;
ssize_t nbytes = 0; ssize_t nbytes = 0;
char *rbuf = work->aux_payload_buf;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
......
...@@ -76,8 +76,8 @@ void ksmbd_vfs_query_maximal_access(struct mnt_idmap *idmap, ...@@ -76,8 +76,8 @@ void ksmbd_vfs_query_maximal_access(struct mnt_idmap *idmap,
struct dentry *dentry, __le32 *daccess); struct dentry *dentry, __le32 *daccess);
int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode); int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode); int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
size_t count, loff_t *pos); loff_t *pos, char *rbuf);
int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
char *buf, size_t count, loff_t *pos, bool sync, char *buf, size_t count, loff_t *pos, bool sync,
ssize_t *written); ssize_t *written);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment