* [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small
@ 2022-05-16 7:41 Namjae Jeon
2022-05-16 7:41 ` [PATCH 2/3] ksmbd: add smbd max io size parameter Namjae Jeon
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Namjae Jeon @ 2022-05-16 7:41 UTC (permalink / raw)
To: linux-cifs; +Cc: smfrench, hyc.lee, senozhatsky, Namjae Jeon
We found the issue that ksmbd return STATUS_NO_MORE_FILES response
even though there are still dentries that needs to be read while
file read/write test using framtest utils.
windows client send smb2 query dir request included
OutputBufferLength(128) that is too small to contain even one entry.
This patch make ksmbd immediately returns OutputBufferLength of response
as zero to client.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/ksmbd/smb2pdu.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 10b7052e382f..eb7ca5f24a3b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3938,6 +3938,12 @@ int smb2_query_dir(struct ksmbd_work *work)
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
+ /*
+ * req->OutputBufferLength is too small to contain even one entry.
+ * In this case, it immediately returns OutputBufferLength 0 to client.
+ */
+ if (!d_info.out_buf_len && !d_info.num_entry)
+ goto no_buf_len;
if (rc == 0)
restart_ctx(&dir_fp->readdir_data.ctx);
if (rc == -ENOSPC)
@@ -3964,10 +3970,12 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->Buffer[0] = 0;
inc_rfc1001_len(work->response_buf, 9);
} else {
+no_buf_len:
((struct file_directory_info *)
((char *)rsp->Buffer + d_info.last_entry_offset))
->NextEntryOffset = 0;
- d_info.data_count -= d_info.last_entry_off_align;
+ if (d_info.data_count >= d_info.last_entry_off_align)
+ d_info.data_count -= d_info.last_entry_off_align;
rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72);
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] ksmbd: add smbd max io size parameter
2022-05-16 7:41 [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small Namjae Jeon
@ 2022-05-16 7:41 ` Namjae Jeon
2022-05-17 8:06 ` Hyunchul Lee
2022-05-16 7:41 ` [PATCH 3/3] ksmbd: fix wrong smbd max read/write size check Namjae Jeon
2022-05-17 8:05 ` [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small Hyunchul Lee
2 siblings, 1 reply; 6+ messages in thread
From: Namjae Jeon @ 2022-05-16 7:41 UTC (permalink / raw)
To: linux-cifs; +Cc: smfrench, hyc.lee, senozhatsky, Namjae Jeon
Add 'smbd max io size' parameter to adjust smbd-direct max read/write
size.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/ksmbd/ksmbd_netlink.h | 3 ++-
fs/ksmbd/transport_ipc.c | 3 +++
fs/ksmbd/transport_rdma.c | 8 +++++++-
fs/ksmbd/transport_rdma.h | 6 ++++++
4 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
index ebe6ca08467a..52aa0adeb951 100644
--- a/fs/ksmbd/ksmbd_netlink.h
+++ b/fs/ksmbd/ksmbd_netlink.h
@@ -104,7 +104,8 @@ struct ksmbd_startup_request {
*/
__u32 sub_auth[3]; /* Subauth value for Security ID */
__u32 smb2_max_credits; /* MAX credits */
- __u32 reserved[128]; /* Reserved room */
+ __u32 smbd_max_io_size; /* smbd read write size */
+ __u32 reserved[127]; /* Reserved room */
__u32 ifc_list_sz; /* interfaces list size */
__s8 ____payload[];
};
diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
index 3ad6881e0f7e..7cb0eeb07c80 100644
--- a/fs/ksmbd/transport_ipc.c
+++ b/fs/ksmbd/transport_ipc.c
@@ -26,6 +26,7 @@
#include "mgmt/ksmbd_ida.h"
#include "connection.h"
#include "transport_tcp.h"
+#include "transport_rdma.h"
#define IPC_WAIT_TIMEOUT (2 * HZ)
@@ -303,6 +304,8 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
init_smb2_max_trans_size(req->smb2_max_trans);
if (req->smb2_max_credits)
init_smb2_max_credits(req->smb2_max_credits);
+ if (req->smbd_max_io_size)
+ init_smbd_max_io_size(req->smbd_max_io_size);
ret = ksmbd_set_netbios_name(req->netbios_name);
ret |= ksmbd_set_server_string(req->server_string);
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 19a605fd46ff..6d652ff38b82 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -80,7 +80,7 @@ static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
/* The maximum single-message size which can be received */
static int smb_direct_max_receive_size = 8192;
-static int smb_direct_max_read_write_size = 8 * 1024 * 1024;
+static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
static LIST_HEAD(smb_direct_device_list);
static DEFINE_RWLOCK(smb_direct_device_lock);
@@ -214,6 +214,12 @@ struct smb_direct_rdma_rw_msg {
struct scatterlist sg_list[];
};
+void init_smbd_max_io_size(unsigned int sz)
+{
+ sz = clamp_val(sz, SMBD_MIN_IOSIZE, SMBD_MAX_IOSIZE);
+ smb_direct_max_read_write_size = sz;
+}
+
static inline int get_buf_page_count(void *buf, int size)
{
return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
index 5567d93a6f96..e7b4e6790fab 100644
--- a/fs/ksmbd/transport_rdma.h
+++ b/fs/ksmbd/transport_rdma.h
@@ -7,6 +7,10 @@
#ifndef __KSMBD_TRANSPORT_RDMA_H__
#define __KSMBD_TRANSPORT_RDMA_H__
+#define SMBD_DEFAULT_IOSIZE (8 * 1024 * 1024)
+#define SMBD_MIN_IOSIZE (512 * 1024)
+#define SMBD_MAX_IOSIZE (16 * 1024 * 1024)
+
/* SMB DIRECT negotiation request packet [MS-SMBD] 2.2.1 */
struct smb_direct_negotiate_req {
__le16 min_version;
@@ -52,10 +56,12 @@ struct smb_direct_data_transfer {
int ksmbd_rdma_init(void);
void ksmbd_rdma_destroy(void);
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
+void init_smbd_max_io_size(unsigned int sz);
#else
static inline int ksmbd_rdma_init(void) { return 0; }
static inline int ksmbd_rdma_destroy(void) { return 0; }
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
+static inline void init_smbd_max_io_size(unsigned int sz) { }
#endif
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] ksmbd: fix wrong smbd max read/write size check
2022-05-16 7:41 [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small Namjae Jeon
2022-05-16 7:41 ` [PATCH 2/3] ksmbd: add smbd max io size parameter Namjae Jeon
@ 2022-05-16 7:41 ` Namjae Jeon
2022-05-17 8:07 ` Hyunchul Lee
2022-05-17 8:05 ` [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small Hyunchul Lee
2 siblings, 1 reply; 6+ messages in thread
From: Namjae Jeon @ 2022-05-16 7:41 UTC (permalink / raw)
To: linux-cifs; +Cc: smfrench, hyc.lee, senozhatsky, Namjae Jeon
smb-direct max read/write size can be different with smb2 max read/write
size. So smb2_read() can return error by wrong max read/write size check.
This patch use smb_direct_max_read_write_size for this check in
smb-direct read/write().
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/ksmbd/smb2pdu.c | 39 +++++++++++++++++++++++++--------------
fs/ksmbd/transport_rdma.c | 5 +++++
fs/ksmbd/transport_rdma.h | 2 ++
3 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index eb7ca5f24a3b..937f9760f181 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6098,6 +6098,8 @@ int smb2_read(struct ksmbd_work *work)
size_t length, mincount;
ssize_t nbytes = 0, remain_bytes = 0;
int err = 0;
+ bool is_rdma_channel = false;
+ unsigned int max_read_size = conn->vals->max_read_size;
WORK_BUFFERS(work, req, rsp);
@@ -6109,6 +6111,11 @@ int smb2_read(struct ksmbd_work *work)
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
+ is_rdma_channel = true;
+ max_read_size = get_smbd_max_read_write_size();
+ }
+
+ if (is_rdma_channel == true) {
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
@@ -6140,9 +6147,9 @@ int smb2_read(struct ksmbd_work *work)
length = le32_to_cpu(req->Length);
mincount = le32_to_cpu(req->MinimumCount);
- if (length > conn->vals->max_read_size) {
+ if (length > max_read_size) {
ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
- conn->vals->max_read_size);
+ max_read_size);
err = -EINVAL;
goto out;
}
@@ -6174,8 +6181,7 @@ int smb2_read(struct ksmbd_work *work)
ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
nbytes, offset, mincount);
- if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
- req->Channel == SMB2_CHANNEL_RDMA_V1) {
+ if (is_rdma_channel == true) {
/* write data to the client using rdma channel */
remain_bytes = smb2_read_rdma_channel(work, req,
work->aux_payload_buf,
@@ -6336,8 +6342,9 @@ int smb2_write(struct ksmbd_work *work)
size_t length;
ssize_t nbytes;
char *data_buf;
- bool writethrough = false;
+ bool writethrough = false, is_rdma_channel = false;
int err = 0;
+ unsigned int max_write_size = work->conn->vals->max_write_size;
WORK_BUFFERS(work, req, rsp);
@@ -6346,8 +6353,17 @@ int smb2_write(struct ksmbd_work *work)
return smb2_write_pipe(work);
}
+ offset = le64_to_cpu(req->Offset);
+ length = le32_to_cpu(req->Length);
+
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
+ is_rdma_channel = true;
+ max_write_size = get_smbd_max_read_write_size();
+ length = le32_to_cpu(req->RemainingBytes);
+ }
+
+ if (is_rdma_channel == true) {
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
if (req->Length != 0 || req->DataOffset != 0 ||
@@ -6382,12 +6398,9 @@ int smb2_write(struct ksmbd_work *work)
goto out;
}
- offset = le64_to_cpu(req->Offset);
- length = le32_to_cpu(req->Length);
-
- if (length > work->conn->vals->max_write_size) {
+ if (length > max_write_size) {
ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
- work->conn->vals->max_write_size);
+ max_write_size);
err = -EINVAL;
goto out;
}
@@ -6395,8 +6408,7 @@ int smb2_write(struct ksmbd_work *work)
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
writethrough = true;
- if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
- req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
+ if (is_rdma_channel == false) {
if ((u64)le16_to_cpu(req->DataOffset) + length >
get_rfc1002_len(work->request_buf)) {
pr_err("invalid write data offset %u, smb_len %u\n",
@@ -6422,8 +6434,7 @@ int smb2_write(struct ksmbd_work *work)
/* read data from the client using rdma channel, and
* write the data.
*/
- nbytes = smb2_write_rdma_channel(work, req, fp, offset,
- le32_to_cpu(req->RemainingBytes),
+ nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
writethrough);
if (nbytes < 0) {
err = (int)nbytes;
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 6d652ff38b82..0741fd129d16 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -220,6 +220,11 @@ void init_smbd_max_io_size(unsigned int sz)
smb_direct_max_read_write_size = sz;
}
+unsigned int get_smbd_max_read_write_size(void)
+{
+ return smb_direct_max_read_write_size;
+}
+
static inline int get_buf_page_count(void *buf, int size)
{
return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
index e7b4e6790fab..77aee4e5c9dc 100644
--- a/fs/ksmbd/transport_rdma.h
+++ b/fs/ksmbd/transport_rdma.h
@@ -57,11 +57,13 @@ int ksmbd_rdma_init(void);
void ksmbd_rdma_destroy(void);
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
void init_smbd_max_io_size(unsigned int sz);
+unsigned int get_smbd_max_read_write_size(void);
#else
static inline int ksmbd_rdma_init(void) { return 0; }
static inline int ksmbd_rdma_destroy(void) { return 0; }
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
static inline void init_smbd_max_io_size(unsigned int sz) { }
+static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
#endif
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small
2022-05-16 7:41 [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small Namjae Jeon
2022-05-16 7:41 ` [PATCH 2/3] ksmbd: add smbd max io size parameter Namjae Jeon
2022-05-16 7:41 ` [PATCH 3/3] ksmbd: fix wrong smbd max read/write size check Namjae Jeon
@ 2022-05-17 8:05 ` Hyunchul Lee
2 siblings, 0 replies; 6+ messages in thread
From: Hyunchul Lee @ 2022-05-17 8:05 UTC (permalink / raw)
To: Namjae Jeon; +Cc: linux-cifs, Steve French, Sergey Senozhatsky
2022년 5월 16일 (월) 오후 4:42, Namjae Jeon <linkinjeon@kernel.org>님이 작성:
>
> We found the issue that ksmbd return STATUS_NO_MORE_FILES response
> even though there are still dentries that needs to be read while
> file read/write test using framtest utils.
> windows client send smb2 query dir request included
> OutputBufferLength(128) that is too small to contain even one entry.
> This patch make ksmbd immediately returns OutputBufferLength of response
> as zero to client.
>
> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
> ---
Looks good to me.
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
> fs/ksmbd/smb2pdu.c | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
> index 10b7052e382f..eb7ca5f24a3b 100644
> --- a/fs/ksmbd/smb2pdu.c
> +++ b/fs/ksmbd/smb2pdu.c
> @@ -3938,6 +3938,12 @@ int smb2_query_dir(struct ksmbd_work *work)
> set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
>
> rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
> + /*
> + * req->OutputBufferLength is too small to contain even one entry.
> + * In this case, it immediately returns OutputBufferLength 0 to client.
> + */
> + if (!d_info.out_buf_len && !d_info.num_entry)
> + goto no_buf_len;
> if (rc == 0)
> restart_ctx(&dir_fp->readdir_data.ctx);
> if (rc == -ENOSPC)
> @@ -3964,10 +3970,12 @@ int smb2_query_dir(struct ksmbd_work *work)
> rsp->Buffer[0] = 0;
> inc_rfc1001_len(work->response_buf, 9);
> } else {
> +no_buf_len:
> ((struct file_directory_info *)
> ((char *)rsp->Buffer + d_info.last_entry_offset))
> ->NextEntryOffset = 0;
> - d_info.data_count -= d_info.last_entry_off_align;
> + if (d_info.data_count >= d_info.last_entry_off_align)
> + d_info.data_count -= d_info.last_entry_off_align;
>
> rsp->StructureSize = cpu_to_le16(9);
> rsp->OutputBufferOffset = cpu_to_le16(72);
> --
> 2.25.1
>
--
Thanks,
Hyunchul
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] ksmbd: add smbd max io size parameter
2022-05-16 7:41 ` [PATCH 2/3] ksmbd: add smbd max io size parameter Namjae Jeon
@ 2022-05-17 8:06 ` Hyunchul Lee
0 siblings, 0 replies; 6+ messages in thread
From: Hyunchul Lee @ 2022-05-17 8:06 UTC (permalink / raw)
To: Namjae Jeon; +Cc: linux-cifs, Steve French, Sergey Senozhatsky
2022년 5월 16일 (월) 오후 4:42, Namjae Jeon <linkinjeon@kernel.org>님이 작성:
>
> Add 'smbd max io size' parameter to adjust smbd-direct max read/write
> size.
>
> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
> ---
Looks good to me.
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
> fs/ksmbd/ksmbd_netlink.h | 3 ++-
> fs/ksmbd/transport_ipc.c | 3 +++
> fs/ksmbd/transport_rdma.c | 8 +++++++-
> fs/ksmbd/transport_rdma.h | 6 ++++++
> 4 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
> index ebe6ca08467a..52aa0adeb951 100644
> --- a/fs/ksmbd/ksmbd_netlink.h
> +++ b/fs/ksmbd/ksmbd_netlink.h
> @@ -104,7 +104,8 @@ struct ksmbd_startup_request {
> */
> __u32 sub_auth[3]; /* Subauth value for Security ID */
> __u32 smb2_max_credits; /* MAX credits */
> - __u32 reserved[128]; /* Reserved room */
> + __u32 smbd_max_io_size; /* smbd read write size */
> + __u32 reserved[127]; /* Reserved room */
> __u32 ifc_list_sz; /* interfaces list size */
> __s8 ____payload[];
> };
> diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
> index 3ad6881e0f7e..7cb0eeb07c80 100644
> --- a/fs/ksmbd/transport_ipc.c
> +++ b/fs/ksmbd/transport_ipc.c
> @@ -26,6 +26,7 @@
> #include "mgmt/ksmbd_ida.h"
> #include "connection.h"
> #include "transport_tcp.h"
> +#include "transport_rdma.h"
>
> #define IPC_WAIT_TIMEOUT (2 * HZ)
>
> @@ -303,6 +304,8 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
> init_smb2_max_trans_size(req->smb2_max_trans);
> if (req->smb2_max_credits)
> init_smb2_max_credits(req->smb2_max_credits);
> + if (req->smbd_max_io_size)
> + init_smbd_max_io_size(req->smbd_max_io_size);
>
> ret = ksmbd_set_netbios_name(req->netbios_name);
> ret |= ksmbd_set_server_string(req->server_string);
> diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
> index 19a605fd46ff..6d652ff38b82 100644
> --- a/fs/ksmbd/transport_rdma.c
> +++ b/fs/ksmbd/transport_rdma.c
> @@ -80,7 +80,7 @@ static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
> /* The maximum single-message size which can be received */
> static int smb_direct_max_receive_size = 8192;
>
> -static int smb_direct_max_read_write_size = 8 * 1024 * 1024;
> +static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
>
> static LIST_HEAD(smb_direct_device_list);
> static DEFINE_RWLOCK(smb_direct_device_lock);
> @@ -214,6 +214,12 @@ struct smb_direct_rdma_rw_msg {
> struct scatterlist sg_list[];
> };
>
> +void init_smbd_max_io_size(unsigned int sz)
> +{
> + sz = clamp_val(sz, SMBD_MIN_IOSIZE, SMBD_MAX_IOSIZE);
> + smb_direct_max_read_write_size = sz;
> +}
> +
> static inline int get_buf_page_count(void *buf, int size)
> {
> return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
> diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
> index 5567d93a6f96..e7b4e6790fab 100644
> --- a/fs/ksmbd/transport_rdma.h
> +++ b/fs/ksmbd/transport_rdma.h
> @@ -7,6 +7,10 @@
> #ifndef __KSMBD_TRANSPORT_RDMA_H__
> #define __KSMBD_TRANSPORT_RDMA_H__
>
> +#define SMBD_DEFAULT_IOSIZE (8 * 1024 * 1024)
> +#define SMBD_MIN_IOSIZE (512 * 1024)
> +#define SMBD_MAX_IOSIZE (16 * 1024 * 1024)
> +
> /* SMB DIRECT negotiation request packet [MS-SMBD] 2.2.1 */
> struct smb_direct_negotiate_req {
> __le16 min_version;
> @@ -52,10 +56,12 @@ struct smb_direct_data_transfer {
> int ksmbd_rdma_init(void);
> void ksmbd_rdma_destroy(void);
> bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
> +void init_smbd_max_io_size(unsigned int sz);
> #else
> static inline int ksmbd_rdma_init(void) { return 0; }
> static inline int ksmbd_rdma_destroy(void) { return 0; }
> static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
> +static inline void init_smbd_max_io_size(unsigned int sz) { }
> #endif
>
> #endif /* __KSMBD_TRANSPORT_RDMA_H__ */
> --
> 2.25.1
>
--
Thanks,
Hyunchul
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] ksmbd: fix wrong smbd max read/write size check
2022-05-16 7:41 ` [PATCH 3/3] ksmbd: fix wrong smbd max read/write size check Namjae Jeon
@ 2022-05-17 8:07 ` Hyunchul Lee
0 siblings, 0 replies; 6+ messages in thread
From: Hyunchul Lee @ 2022-05-17 8:07 UTC (permalink / raw)
To: Namjae Jeon; +Cc: linux-cifs, Steve French, Sergey Senozhatsky
2022년 5월 16일 (월) 오후 4:42, Namjae Jeon <linkinjeon@kernel.org>님이 작성:
>
> smb-direct max read/write size can be different with smb2 max read/write
> size. So smb2_read() can return error by wrong max read/write size check.
> This patch use smb_direct_max_read_write_size for this check in
> smb-direct read/write().
>
> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Looks good to me.
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
> ---
> fs/ksmbd/smb2pdu.c | 39 +++++++++++++++++++++++++--------------
> fs/ksmbd/transport_rdma.c | 5 +++++
> fs/ksmbd/transport_rdma.h | 2 ++
> 3 files changed, 32 insertions(+), 14 deletions(-)
>
> diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
> index eb7ca5f24a3b..937f9760f181 100644
> --- a/fs/ksmbd/smb2pdu.c
> +++ b/fs/ksmbd/smb2pdu.c
> @@ -6098,6 +6098,8 @@ int smb2_read(struct ksmbd_work *work)
> size_t length, mincount;
> ssize_t nbytes = 0, remain_bytes = 0;
> int err = 0;
> + bool is_rdma_channel = false;
> + unsigned int max_read_size = conn->vals->max_read_size;
>
> WORK_BUFFERS(work, req, rsp);
>
> @@ -6109,6 +6111,11 @@ int smb2_read(struct ksmbd_work *work)
>
> if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
> req->Channel == SMB2_CHANNEL_RDMA_V1) {
> + is_rdma_channel = true;
> + max_read_size = get_smbd_max_read_write_size();
> + }
> +
> + if (is_rdma_channel == true) {
> unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
>
> if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
> @@ -6140,9 +6147,9 @@ int smb2_read(struct ksmbd_work *work)
> length = le32_to_cpu(req->Length);
> mincount = le32_to_cpu(req->MinimumCount);
>
> - if (length > conn->vals->max_read_size) {
> + if (length > max_read_size) {
> ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
> - conn->vals->max_read_size);
> + max_read_size);
> err = -EINVAL;
> goto out;
> }
> @@ -6174,8 +6181,7 @@ int smb2_read(struct ksmbd_work *work)
> ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
> nbytes, offset, mincount);
>
> - if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
> - req->Channel == SMB2_CHANNEL_RDMA_V1) {
> + if (is_rdma_channel == true) {
> /* write data to the client using rdma channel */
> remain_bytes = smb2_read_rdma_channel(work, req,
> work->aux_payload_buf,
> @@ -6336,8 +6342,9 @@ int smb2_write(struct ksmbd_work *work)
> size_t length;
> ssize_t nbytes;
> char *data_buf;
> - bool writethrough = false;
> + bool writethrough = false, is_rdma_channel = false;
> int err = 0;
> + unsigned int max_write_size = work->conn->vals->max_write_size;
>
> WORK_BUFFERS(work, req, rsp);
>
> @@ -6346,8 +6353,17 @@ int smb2_write(struct ksmbd_work *work)
> return smb2_write_pipe(work);
> }
>
> + offset = le64_to_cpu(req->Offset);
> + length = le32_to_cpu(req->Length);
> +
> if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
> req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
> + is_rdma_channel = true;
> + max_write_size = get_smbd_max_read_write_size();
> + length = le32_to_cpu(req->RemainingBytes);
> + }
> +
> + if (is_rdma_channel == true) {
> unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
>
> if (req->Length != 0 || req->DataOffset != 0 ||
> @@ -6382,12 +6398,9 @@ int smb2_write(struct ksmbd_work *work)
> goto out;
> }
>
> - offset = le64_to_cpu(req->Offset);
> - length = le32_to_cpu(req->Length);
> -
> - if (length > work->conn->vals->max_write_size) {
> + if (length > max_write_size) {
> ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
> - work->conn->vals->max_write_size);
> + max_write_size);
> err = -EINVAL;
> goto out;
> }
> @@ -6395,8 +6408,7 @@ int smb2_write(struct ksmbd_work *work)
> if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
> writethrough = true;
>
> - if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
> - req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
> + if (is_rdma_channel == false) {
> if ((u64)le16_to_cpu(req->DataOffset) + length >
> get_rfc1002_len(work->request_buf)) {
> pr_err("invalid write data offset %u, smb_len %u\n",
> @@ -6422,8 +6434,7 @@ int smb2_write(struct ksmbd_work *work)
> /* read data from the client using rdma channel, and
> * write the data.
> */
> - nbytes = smb2_write_rdma_channel(work, req, fp, offset,
> - le32_to_cpu(req->RemainingBytes),
> + nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
> writethrough);
> if (nbytes < 0) {
> err = (int)nbytes;
> diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
> index 6d652ff38b82..0741fd129d16 100644
> --- a/fs/ksmbd/transport_rdma.c
> +++ b/fs/ksmbd/transport_rdma.c
> @@ -220,6 +220,11 @@ void init_smbd_max_io_size(unsigned int sz)
> smb_direct_max_read_write_size = sz;
> }
>
> +unsigned int get_smbd_max_read_write_size(void)
> +{
> + return smb_direct_max_read_write_size;
> +}
> +
> static inline int get_buf_page_count(void *buf, int size)
> {
> return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
> diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
> index e7b4e6790fab..77aee4e5c9dc 100644
> --- a/fs/ksmbd/transport_rdma.h
> +++ b/fs/ksmbd/transport_rdma.h
> @@ -57,11 +57,13 @@ int ksmbd_rdma_init(void);
> void ksmbd_rdma_destroy(void);
> bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
> void init_smbd_max_io_size(unsigned int sz);
> +unsigned int get_smbd_max_read_write_size(void);
> #else
> static inline int ksmbd_rdma_init(void) { return 0; }
> static inline int ksmbd_rdma_destroy(void) { return 0; }
> static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
> static inline void init_smbd_max_io_size(unsigned int sz) { }
> +static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
> #endif
>
> #endif /* __KSMBD_TRANSPORT_RDMA_H__ */
> --
> 2.25.1
>
--
Thanks,
Hyunchul
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-05-17 8:07 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-05-16 7:41 [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small Namjae Jeon
2022-05-16 7:41 ` [PATCH 2/3] ksmbd: add smbd max io size parameter Namjae Jeon
2022-05-17 8:06 ` Hyunchul Lee
2022-05-16 7:41 ` [PATCH 3/3] ksmbd: fix wrong smbd max read/write size check Namjae Jeon
2022-05-17 8:07 ` Hyunchul Lee
2022-05-17 8:05 ` [PATCH 1/3] ksmbd: handle smb2 query dir request for OutputBufferLength that is too small Hyunchul Lee
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox