diff --git a/documentation/history.doc b/documentation/history.doc index 4f74afd..afc4fd8 100644 --- a/documentation/history.doc +++ b/documentation/history.doc @@ -2772,3 +2772,10 @@ smbfs 2.8 (19.12.2018) - Added more debug log output to the code which now performs the file and lock name/address lookups instead of walking through the entire file/lock lists. + + +smbfs 2.9 (24.12.2018) + +- Added the TCP_NODELAY, SO_RCVBUF and SO_SNDBUF tuning options + which serve the same purposes as their Samba configuration option + counterparts. diff --git a/source_code/include/smb/smb_fs_sb.h b/source_code/include/smb/smb_fs_sb.h index 0aa8fe9..891f16c 100644 --- a/source_code/include/smb/smb_fs_sb.h +++ b/source_code/include/smb/smb_fs_sb.h @@ -33,6 +33,9 @@ struct smb_server both in a single combined send() operation rather than separately. */ dword smb_read_threshold; /* Same as above, but for recv() operations. */ + int tcp_no_delay; /* Disable the Nagle algorithm for send()? */ + int socket_receive_buffer_size; /* Desired socket receive buffer size, if > 0. */ + int socket_send_buffer_size; /* Desired socket transmit buffer size, if > 0. */ int max_recv; /* added by CS */ word server_uid; word tid; diff --git a/source_code/main.c b/source_code/main.c index 1ae20a9..e8a994d 100644 --- a/source_code/main.c +++ b/source_code/main.c @@ -261,7 +261,7 @@ static ULONG stack_usage_exit(const struct StackSwapStruct * stk); static LONG CVSPrintf(const TEXT * format_string, APTR args); static int LocalVSNPrintf(STRPTR buffer, int limit, const TEXT * formatString, APTR args); static void cleanup(void); -static BOOL setup(const TEXT * program_name, const TEXT * service, const TEXT * workgroup, STRPTR username, STRPTR opt_password, BOOL opt_change_username_case, BOOL opt_change_password_case, const TEXT * opt_clientname, const TEXT * opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_unicode, BOOL opt_prefer_core_protocol, BOOL opt_session_setup_delay_unicode, BOOL opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, const TEXT * device_name, const TEXT * volume_name, BOOL add_volume, const TEXT * translation_file); +static BOOL setup(const TEXT * program_name, const TEXT * service, const TEXT * workgroup, STRPTR username, STRPTR opt_password, BOOL opt_change_username_case, BOOL opt_change_password_case, const TEXT * opt_clientname, const TEXT * opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_unicode, BOOL opt_prefer_core_protocol, BOOL opt_session_setup_delay_unicode, BOOL opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, BOOL tcp_no_delay, int socket_receive_buffer_size, int socket_send_buffer_size, const TEXT * device_name, const TEXT * volume_name, BOOL add_volume, const TEXT * translation_file); static void file_system_handler(BOOL raise_priority, const TEXT * device_name, const TEXT * volume_name, const TEXT * service_name); /****************************************************************************/ @@ -760,6 +760,9 @@ main(void) SWITCH WriteBehind; NUMBER WriteThreshold; NUMBER ReadThreshold; + SWITCH TCPNoDelay; + NUMBER SocketReceiveBuf; + NUMBER SocketSendBuf; KEY SessionSetup; KEY Unicode; SWITCH CP437; @@ -802,6 +805,9 @@ main(void) "WRITEBEHIND/S," "WRITETHRESHOLD/N/K," "READTHRESHOLD/N/K," + "TCP_NODELAY=TCPNODELAY/S," + "SO_RCVBUF=SOCKETRECEIVEBUFFER/N/K," + "SO_SNDBUF=SOCKETSENDBUFER/N/K," "SESSIONSETUP/K," "UNICODE/K," "CP437/S," @@ -824,6 +830,8 @@ main(void) LONG smb_write_threshold = 0; LONG smb_read_threshold = 0; LONG timeout = 0; + LONG socket_receive_buffer = 0; + LONG socket_send_buffer = 0; TEXT env_protocol[8]; TEXT env_workgroup_name[17]; TEXT env_user_name[64]; @@ -1000,6 +1008,7 @@ main(void) args.CaseSensitive = get_icon_tool_type_value("CASE", "CASESENSITIVE") != NULL; args.NetBIOSTransport = get_icon_tool_type_value("NETBIOS", NULL) != NULL; args.WriteBehind = get_icon_tool_type_value("WRITEBEHIND", NULL) != NULL; + args.TCPNoDelay = get_icon_tool_type_value("TCPNODELAY", "TCP_NODELAY") != NULL; args.ClientName = get_icon_tool_type_value("CLIENT", "CLIENTNAME"); args.ServerName = get_icon_tool_type_value("SERVER", "SERVERNAME"); @@ -1112,6 +1121,30 @@ main(void) args.Timeout = &timeout; } + + str = get_icon_tool_type_value("SOCKETRECEIVEBUFFER", "SO_RCVBUF"); + if(str != NULL) + { + if(StrToLong(str,&socket_receive_buffer) == -1) + { + report_error("Invalid number '%s' for 'SOCKETRECEIVEBUFFER' parameter.",str); + goto out; + } + + args.SocketReceiveBuf = &socket_receive_buffer; + } + + str = get_icon_tool_type_value("SOCKETSENDBUFFER", "SO_SENDBUF"); + if(str != NULL) + { + if(StrToLong(str,&socket_send_buffer) == -1) + { + report_error("Invalid number '%s' for 'SOCKETSENDBUFFER' parameter.",str); + goto out; + } + + args.SocketSendBuf = &socket_send_buffer; + } } else { @@ -1421,6 +1454,18 @@ main(void) D(("read threshold = %ld", (*args.ReadThreshold))); + D(("tcp no delay = %s", args.TCPNoDelay ? "requested" : "not requested")); + + if(args.SocketReceiveBuf == NULL) + args.SocketReceiveBuf = &socket_receive_buffer; + + D(("socket receive buffer size = %ld", (*args.SocketReceiveBuf))); + + if(args.SocketSendBuf == NULL) + args.SocketSendBuf = &socket_send_buffer; + + D(("socket send buffer size = %ld", (*args.SocketSendBuf))); + DisableExAll = (BOOL)(args.DisableExAll != 0); CaseSensitive = (BOOL)(args.CaseSensitive != 0); OmitHidden = (BOOL)(args.OmitHidden != 0); @@ -1534,6 +1579,9 @@ main(void) args.WriteBehind, (*args.WriteThreshold), (*args.ReadThreshold), + args.TCPNoDelay, + (*args.SocketReceiveBuf), + (*args.SocketSendBuf), args.DeviceName, args.VolumeName, get_switch_status(args.AddVolume, TRUE), @@ -3761,6 +3809,9 @@ setup( BOOL opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, + BOOL opt_tcp_no_delay, + int opt_socket_receive_buffer_size, + int opt_socket_send_buffer_size, const TEXT * device_name, const TEXT * volume_name, BOOL opt_add_volume, @@ -4002,6 +4053,9 @@ setup( opt_write_behind, opt_smb_request_write_threshold, opt_smb_request_read_threshold, + opt_tcp_no_delay, + opt_socket_receive_buffer_size, + opt_socket_send_buffer_size, &error, &smb_error_class, &smb_error, diff --git a/source_code/smb_abstraction.c b/source_code/smb_abstraction.c index b0279f4..d138263 100644 --- a/source_code/smb_abstraction.c +++ b/source_code/smb_abstraction.c @@ -97,6 +97,9 @@ smba_connect ( int opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, + int opt_tcp_no_delay, + int opt_socket_receive_buffer_size, + int opt_socket_send_buffer_size, int * error_ptr, int * smb_error_class_ptr, int * smb_error_ptr, @@ -170,6 +173,17 @@ smba_connect ( LOG(("SMB read request threshold size = %ld bytes\n", res->server.smb_read_threshold)); + /* Disable the Nagle algorithm, causing send() to immediately + * result in the data being transmitted? + */ + res->server.tcp_no_delay = opt_tcp_no_delay; + + /* Try to get the TCP/IP stack to use a specific + * receive/transmit buffer size? + */ + res->server.socket_receive_buffer_size = opt_socket_receive_buffer_size; + res->server.socket_send_buffer_size = opt_socket_send_buffer_size; + /* Enable asynchronous SMB_COM_WRITE_RAW operations? */ res->server.write_behind = opt_write_behind; @@ -2018,6 +2032,9 @@ smba_start( int opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, + int opt_tcp_no_delay, + int opt_socket_receive_buffer_size, + int opt_socket_send_buffer_size, int * error_ptr, int * smb_error_class_ptr, int * smb_error_ptr, @@ -2271,6 +2288,9 @@ smba_start( opt_write_behind, opt_smb_request_write_threshold, opt_smb_request_read_threshold, + opt_tcp_no_delay, + opt_socket_receive_buffer_size, + opt_socket_send_buffer_size, error_ptr, smb_error_class_ptr, smb_error_ptr, diff --git a/source_code/smb_abstraction.h b/source_code/smb_abstraction.h index c8cf7f7..0463bf0 100644 --- a/source_code/smb_abstraction.h +++ b/source_code/smb_abstraction.h @@ -162,7 +162,7 @@ int smba_rmdir(smba_server_t *s, const char *path, int *error_ptr); int smba_rename(smba_server_t *s, const char *from, const char *to, int *error_ptr); int smba_statfs(smba_server_t *s, long *bsize, long *blocks, long *bfree, int *error_ptr); void smb_invalidate_all_inodes(struct smb_server *server); -int smba_start(const char *service, const char *opt_workgroup, const char *opt_username, const char *opt_password, const char *opt_clientname, const char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_unicode, int opt_prefer_core_protocol, int opt_case_sensitive, int opt_session_setup_delay_unicode, int opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, int *error_ptr, int *smb_error_class_ptr, int *smb_error_ptr, smba_connect_parameters_t *smba_connect_par, smba_server_t **smba_server_ptr); +int smba_start(const char *service, const char *opt_workgroup, const char *opt_username, const char *opt_password, const char *opt_clientname, const char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_unicode, int opt_prefer_core_protocol, int opt_case_sensitive, int opt_session_setup_delay_unicode, int opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, int opt_tcp_no_delay, int opt_socket_receive_buffer_size, int opt_socket_send_buffer_size, int *error_ptr, int *smb_error_class_ptr, int *smb_error_ptr, smba_connect_parameters_t *smba_connect_par, smba_server_t **smba_server_ptr); int smba_get_dircache_size(struct smba_server *server); int smba_change_dircache_size(struct smba_server *server, int cache_size); diff --git a/source_code/smbfs_rev.h b/source_code/smbfs_rev.h index 7e94b91..245492c 100644 --- a/source_code/smbfs_rev.h +++ b/source_code/smbfs_rev.h @@ -1,6 +1,6 @@ #define VERSION 2 -#define REVISION 8 -#define DATE "19.12.2018" -#define VERS "smbfs 2.8" -#define VSTRING "smbfs 2.8 (19.12.2018)\r\n" -#define VERSTAG "\0$VER: smbfs 2.8 (19.12.2018)" +#define REVISION 9 +#define DATE "24.12.2018" +#define VERS "smbfs 2.9" +#define VSTRING "smbfs 2.9 (24.12.2018)\r\n" +#define VERSTAG "\0$VER: smbfs 2.9 (24.12.2018)" diff --git a/source_code/smbfs_rev.rev b/source_code/smbfs_rev.rev index 45a4fb7..ec63514 100644 --- a/source_code/smbfs_rev.rev +++ b/source_code/smbfs_rev.rev @@ -1 +1 @@ -8 +9 diff --git a/source_code/sock.c b/source_code/sock.c index f710aad..6f17aef 100644 --- a/source_code/sock.c +++ b/source_code/sock.c @@ -1229,6 +1229,23 @@ smb_connect (struct smb_server *server, int * error_ptr) /* Enable socket keepalives, for good measure. */ setsockopt(server->mount_data.fd, SOL_SOCKET, SO_KEEPALIVE, &enabled, sizeof(enabled)); + /* Disable the Nagle algorithm for send() operations, causing the + * data to be sent as soon as possible, rather than being subjected + * to traffic control/smoothing? + */ + if(server->tcp_no_delay) + setsockopt(server->mount_data.fd, IPPROTO_TCP, TCP_NODELAY, &enabled, sizeof(enabled)); + + /* Request specific socket receive/transmit buffer sizes? Note that + * this is a request, not a figure which the TCP/IP stack has to + * honour. + */ + if(server->socket_receive_buffer_size > 0) + setsockopt(server->mount_data.fd, SOL_SOCKET, SO_RCVBUF, &server->socket_receive_buffer_size, sizeof(server->socket_receive_buffer_size)); + + if(server->socket_send_buffer_size > 0) + setsockopt(server->mount_data.fd, SOL_SOCKET, SO_SNDBUF, &server->socket_send_buffer_size, sizeof(server->socket_send_buffer_size)); + /* Configure the send/receive timeout (in seconds)? */ if(server->timeout > 0) {