mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Since commit0a77d947f5
("ksmbd: check outstanding simultaneous SMB operations"), ksmbd enforces a maximum number of simultaneous operations for a connection. The problem is that reaching the limit causes ksmbd to close the socket, and the client has no indication that it should have slowed down. This behaviour can be reproduced by setting "smb2 max credits = 128" (or lower), and transferring a large file (25GB). smbclient fails as below: $ smbclient //192.168.1.254/testshare -U user%pass smb: \> put file.bin cli_push returned NT_STATUS_USER_SESSION_DELETED putting file file.bin as \file.bin smb2cli_req_compound_submit: Insufficient credits. 0 available, 1 needed NT_STATUS_INTERNAL_ERROR closing remote file \file.bin smb: \> smb2cli_req_compound_submit: Insufficient credits. 0 available, 1 needed Windows clients fail with 0x8007003b (with smaller files even). Fix this by delaying reading from the socket until there's room to allocate a request. This effectively applies backpressure on the client, so the transfer completes, albeit at a slower rate. Fixes:0a77d947f5
("ksmbd: check outstanding simultaneous SMB operations") Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
73 lines
1.5 KiB
C
73 lines
1.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
|
|
*/
|
|
|
|
#ifndef __SERVER_H__
|
|
#define __SERVER_H__
|
|
|
|
#include "smbacl.h"
|
|
|
|
/*
|
|
* Server state type
|
|
*/
|
|
enum {
|
|
SERVER_STATE_STARTING_UP,
|
|
SERVER_STATE_RUNNING,
|
|
SERVER_STATE_RESETTING,
|
|
SERVER_STATE_SHUTTING_DOWN,
|
|
};
|
|
|
|
/*
|
|
* Server global config string index
|
|
*/
|
|
enum {
|
|
SERVER_CONF_NETBIOS_NAME,
|
|
SERVER_CONF_SERVER_STRING,
|
|
SERVER_CONF_WORK_GROUP,
|
|
};
|
|
|
|
struct ksmbd_server_config {
|
|
unsigned int flags;
|
|
unsigned int state;
|
|
short signing;
|
|
short enforced_signing;
|
|
short min_protocol;
|
|
short max_protocol;
|
|
unsigned short tcp_port;
|
|
unsigned short ipc_timeout;
|
|
unsigned long ipc_last_active;
|
|
unsigned long deadtime;
|
|
unsigned int share_fake_fscaps;
|
|
struct smb_sid domain_sid;
|
|
unsigned int auth_mechs;
|
|
unsigned int max_connections;
|
|
unsigned int max_inflight_req;
|
|
|
|
char *conf[SERVER_CONF_WORK_GROUP + 1];
|
|
struct task_struct *dh_task;
|
|
};
|
|
|
|
extern struct ksmbd_server_config server_conf;
|
|
|
|
int ksmbd_set_netbios_name(char *v);
|
|
int ksmbd_set_server_string(char *v);
|
|
int ksmbd_set_work_group(char *v);
|
|
|
|
char *ksmbd_netbios_name(void);
|
|
char *ksmbd_server_string(void);
|
|
char *ksmbd_work_group(void);
|
|
|
|
static inline int ksmbd_server_running(void)
|
|
{
|
|
return READ_ONCE(server_conf.state) == SERVER_STATE_RUNNING;
|
|
}
|
|
|
|
static inline int ksmbd_server_configurable(void)
|
|
{
|
|
return READ_ONCE(server_conf.state) < SERVER_STATE_RESETTING;
|
|
}
|
|
|
|
int server_queue_ctrl_init_work(void);
|
|
int server_queue_ctrl_reset_work(void);
|
|
#endif /* __SERVER_H__ */
|