cifsd-team / ksmbd

ksmbd kernel server(SMB/CIFS server)
154 stars 23 forks source link

When SMBv1 is used to write files, only 512-byte data is transmitted in a datagram, resulting in poor performance. #565

Closed zztmy closed 2 years ago

zztmy commented 2 years ago

Huawei phone backs up and restores data, scans external storage, finds my NAS, and starts to back up data. The data rate of the phone is only 100 KB.

SMBv1 Write AndX Request packets carry 512 bytes each time.

image

namjaejeon commented 2 years ago

Sorry, Looks it is client issue. Client send 512byte data. can you compare it with samba ?

zztmy commented 2 years ago

Sorry, Looks it is client issue. Client send 512byte data. can you compare it with samba ?

I have compared Samba. When interacting with the Samba, It's sent large packets, 1048576betys at a time, and the transmission speed was 100 times that of ksmbd.

image

namjaejeon commented 2 years ago

Ah, Can you send each tcpdump files that capture packets with ksmbd and samba to compare ? And I need total packets between connection and write from client.

zztmy commented 2 years ago

ksmbd.zip samba.zip

namjaejeon commented 2 years ago

Could you please try to check your problem is fixed after applying the below change to ksmbd ?

diff --git a/smb1pdu.c b/smb1pdu.c
index 319642b..aa909a9 100644
--- a/smb1pdu.c
+++ b/smb1pdu.c
@@ -492,8 +492,7 @@ int smb_tree_connect_andx(struct ksmbd_work *work)
        rsp->WordCount = 7;
        rsp->OptionalSupport = 0;

-       rsp->OptionalSupport = cpu_to_le16((SMB_SUPPORT_SEARCH_BITS |
-                               SMB_CSC_NO_CACHING | SMB_UNIQUE_FILE_NAME));
+       rsp->OptionalSupport = cpu_to_le16(SMB_SUPPORT_SEARCH_BITS);

        rsp->MaximalShareAccessRights = cpu_to_le32(FILE_READ_RIGHTS |
                                        FILE_EXEC_RIGHTS);
zztmy commented 2 years ago

There's still a problem with this change!

I found that when the jcifs client uploads files,if oplocks = yes,the client sends 1048576betys at a time.

I tried to open ksmbd oplocks, But it didn't work because of this modification.(https://github.com/cifsd-team/ksmbd/commit/a83ebaa63cc7133b6dfb37e4481ead8b09093438)

I set smb1_oplocks_enable = true and add oplocks = yes to configuration.then speed is faster.but After several test, a kenerl painc occurred. [ 216.015512] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 216.017716] Mem abort info: [ 216.018412] ESR = 0x96000005 [ 216.019172] EC = 0x25: DABT (current EL), IL = 32 bits [ 216.020490] SET = 0, FnV = 0 [ 216.021255] EA = 0, S1PTW = 0 [ 216.022034] Data abort info: [ 216.022750] ISV = 0, ISS = 0x00000005 [ 216.023702] CM = 0, WnR = 0 [ 216.024440] user pgtable: 4k pages, 39-bit VAs, pgdp=000000000d374000 [ 216.026049] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 [ 216.028226] ATP_save_reboot_flag success, flag = 4 [ 216.029424] Internal error: Oops: 96000005 [#1] PREEMPT SMP [ 216.030818] Modules linked in: rpcsec_gss_krb5 auth_rpcgss cifs usb_storage galcore r8152 [ 216.032861] CPU: 2 PID: 45 Comm: kworker/2:1 Not tainted 5.10.107 #1 [ 216.034436] Hardware name: HTD286 Bleeding Edge EVB (4GB) (DT) [ 216.035891] Workqueue: ksmbd-io handle_ksmbd_work [ 216.037062] pstate: 60c00005 (nZCv daif +PAN +UAO -TCO BTYPE=--) [ 216.038554] pc : smb1_oplock_break_noti+0xa4/0x168 [ 216.039787] lr : __smb1_oplock_break_noti+0x3c/0x168 [ 216.041018] sp : ffffffc01176bb50 [ 216.041841] x29: ffffffc01176bb50 x28: 0000000000000000 [ 216.043161] x27: ffffff800d35e044 x26: ffffff8015071a00 [ 216.044482] x25: ffffffc010ea3000 x24: ffffff8015b2b800 [ 216.045803] x23: ffffffc011520000 x22: ffffff807329fd00 [ 216.047123] x21: ffffff8015071a00 x20: ffffff8015b2b800 [ 216.048443] x19: ffffff807329fd90 x18: 0000000000000000 [ 216.049763] x17: 0000000000000000 x16: 0000000000000000 [ 216.051083] x15: 0000000000000000 x14: 0000000000000001 [ 216.052403] x13: 0000000000000000 x12: ffffffffffffffff [ 216.053723] x11: 0000000000000040 x10: ffffff8016063988 [ 216.055044] x9 : 00000000424d53ff x8 : 0000000000000024 [ 216.056364] x7 : 00000000ffffc001 x6 : 0000000000000000 [ 216.057684] x5 : 000000000000ff08 x4 : 0000000000000002 [ 216.059004] x3 : 00000000ffffffff x2 : 0000000000000000 [ 216.060324] x1 : 0000000033000000 x0 : ffffff8015a82400 [ 216.061651] Call trace: [ 216.062265] smb1_oplock_break_noti+0xa4/0x168 [ 216.063417] oplock_break+0x384/0x548 [ 216.064333] smb_break_all_levII_oplock+0x124/0x250 [ 216.065548] ksmbd_vfs_write+0xb4/0x2f8 [ 216.066508] smb_write_andx+0x24c/0x3d8 [ 216.067466] handle_ksmbd_work+0x1cc/0x478 [ 216.068490] process_one_work+0x218/0x4c8 [ 216.069491] worker_thread+0x48/0x438 [ 216.070406] kthread+0x160/0x168 [ 216.071215] ret_from_fork+0x10/0x1c [ 216.072112] Code: 79001c07 11003821 5ac00821 29002401 (f94000c1)

namjaejeon commented 2 years ago

@zztmy Nice! But please don't use SMB1 oplocks because it is not tested. I hope that some developer improve it instead of me. SMB1 is deprecated on windows. So don't want to invest more about it.

Can you try to test the below change instead of changing oplocks enable ?

diff --git a/smb1pdu.h b/smb1pdu.h
index fb6c395..26cbdda 100644
--- a/smb1pdu.h
+++ b/smb1pdu.h
@@ -26,7 +26,7 @@
        (CAP_UNICODE | CAP_LARGE_FILES | CAP_EXTENDED_SECURITY |\
         CAP_NT_SMBS | CAP_STATUS32 | CAP_LOCK_AND_READ |       \
         CAP_NT_FIND | CAP_UNIX | CAP_LARGE_READ_X |            \
-        CAP_LARGE_WRITE_X | CAP_LEVEL_II_OPLOCKS)
+        CAP_LARGE_WRITE_X)
zztmy commented 2 years ago

After this modification, it's still very slow. When transferring files, CIFS determines how to send packets based onn oplocks. So I turned on oplocks.

about the kernel painc, the cause is that the__smb1_oplock_break_noti function does not assign a value to work->sess.