@@ -1108,7 +1108,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
1108
1108
{
1109
1109
struct smb2_compound_vars * vars ;
1110
1110
struct cifs_ses * ses = tcon -> ses ;
1111
- struct TCP_Server_Info * server = cifs_pick_channel ( ses ) ;
1111
+ struct TCP_Server_Info * server ;
1112
1112
struct smb_rqst * rqst ;
1113
1113
struct kvec * rsp_iov ;
1114
1114
__le16 * utf16_path = NULL ;
@@ -1124,6 +1124,13 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
1124
1124
struct smb2_file_full_ea_info * ea = NULL ;
1125
1125
struct smb2_query_info_rsp * rsp ;
1126
1126
int rc , used_len = 0 ;
1127
+ int retries = 0 , cur_sleep = 1 ;
1128
+
1129
+ replay_again :
1130
+ /* reinitialize for possible replay */
1131
+ flags = CIFS_CP_CREATE_CLOSE_OP ;
1132
+ oplock = SMB2_OPLOCK_LEVEL_NONE ;
1133
+ server = cifs_pick_channel (ses );
1127
1134
1128
1135
if (smb3_encryption_required (tcon ))
1129
1136
flags |= CIFS_TRANSFORM_REQ ;
@@ -1244,6 +1251,12 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
1244
1251
goto sea_exit ;
1245
1252
smb2_set_related (& rqst [2 ]);
1246
1253
1254
+ if (retries ) {
1255
+ smb2_set_replay (server , & rqst [0 ]);
1256
+ smb2_set_replay (server , & rqst [1 ]);
1257
+ smb2_set_replay (server , & rqst [2 ]);
1258
+ }
1259
+
1247
1260
rc = compound_send_recv (xid , ses , server ,
1248
1261
flags , 3 , rqst ,
1249
1262
resp_buftype , rsp_iov );
@@ -1260,6 +1273,11 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
1260
1273
kfree (vars );
1261
1274
out_free_path :
1262
1275
kfree (utf16_path );
1276
+
1277
+ if (is_replayable_error (rc ) &&
1278
+ smb2_should_replay (tcon , & retries , & cur_sleep ))
1279
+ goto replay_again ;
1280
+
1263
1281
return rc ;
1264
1282
}
1265
1283
#endif
@@ -1484,7 +1502,7 @@ smb2_ioctl_query_info(const unsigned int xid,
1484
1502
struct smb_rqst * rqst ;
1485
1503
struct kvec * rsp_iov ;
1486
1504
struct cifs_ses * ses = tcon -> ses ;
1487
- struct TCP_Server_Info * server = cifs_pick_channel ( ses ) ;
1505
+ struct TCP_Server_Info * server ;
1488
1506
char __user * arg = (char __user * )p ;
1489
1507
struct smb_query_info qi ;
1490
1508
struct smb_query_info __user * pqi ;
@@ -1501,6 +1519,13 @@ smb2_ioctl_query_info(const unsigned int xid,
1501
1519
void * data [2 ];
1502
1520
int create_options = is_dir ? CREATE_NOT_FILE : CREATE_NOT_DIR ;
1503
1521
void (* free_req1_func )(struct smb_rqst * r );
1522
+ int retries = 0 , cur_sleep = 1 ;
1523
+
1524
+ replay_again :
1525
+ /* reinitialize for possible replay */
1526
+ flags = CIFS_CP_CREATE_CLOSE_OP ;
1527
+ oplock = SMB2_OPLOCK_LEVEL_NONE ;
1528
+ server = cifs_pick_channel (ses );
1504
1529
1505
1530
vars = kzalloc (sizeof (* vars ), GFP_ATOMIC );
1506
1531
if (vars == NULL )
@@ -1641,6 +1666,12 @@ smb2_ioctl_query_info(const unsigned int xid,
1641
1666
goto free_req_1 ;
1642
1667
smb2_set_related (& rqst [2 ]);
1643
1668
1669
+ if (retries ) {
1670
+ smb2_set_replay (server , & rqst [0 ]);
1671
+ smb2_set_replay (server , & rqst [1 ]);
1672
+ smb2_set_replay (server , & rqst [2 ]);
1673
+ }
1674
+
1644
1675
rc = compound_send_recv (xid , ses , server ,
1645
1676
flags , 3 , rqst ,
1646
1677
resp_buftype , rsp_iov );
@@ -1701,6 +1732,11 @@ smb2_ioctl_query_info(const unsigned int xid,
1701
1732
kfree (buffer );
1702
1733
free_vars :
1703
1734
kfree (vars );
1735
+
1736
+ if (is_replayable_error (rc ) &&
1737
+ smb2_should_replay (tcon , & retries , & cur_sleep ))
1738
+ goto replay_again ;
1739
+
1704
1740
return rc ;
1705
1741
}
1706
1742
@@ -2227,8 +2263,14 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
2227
2263
struct cifs_open_parms oparms ;
2228
2264
struct smb2_query_directory_rsp * qd_rsp = NULL ;
2229
2265
struct smb2_create_rsp * op_rsp = NULL ;
2230
- struct TCP_Server_Info * server = cifs_pick_channel (tcon -> ses );
2231
- int retry_count = 0 ;
2266
+ struct TCP_Server_Info * server ;
2267
+ int retries = 0 , cur_sleep = 1 ;
2268
+
2269
+ replay_again :
2270
+ /* reinitialize for possible replay */
2271
+ flags = 0 ;
2272
+ oplock = SMB2_OPLOCK_LEVEL_NONE ;
2273
+ server = cifs_pick_channel (tcon -> ses );
2232
2274
2233
2275
utf16_path = cifs_convert_path_to_utf16 (path , cifs_sb );
2234
2276
if (!utf16_path )
@@ -2278,14 +2320,15 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
2278
2320
2279
2321
smb2_set_related (& rqst [1 ]);
2280
2322
2281
- again :
2323
+ if (retries ) {
2324
+ smb2_set_replay (server , & rqst [0 ]);
2325
+ smb2_set_replay (server , & rqst [1 ]);
2326
+ }
2327
+
2282
2328
rc = compound_send_recv (xid , tcon -> ses , server ,
2283
2329
flags , 2 , rqst ,
2284
2330
resp_buftype , rsp_iov );
2285
2331
2286
- if (rc == - EAGAIN && retry_count ++ < 10 )
2287
- goto again ;
2288
-
2289
2332
/* If the open failed there is nothing to do */
2290
2333
op_rsp = (struct smb2_create_rsp * )rsp_iov [0 ].iov_base ;
2291
2334
if (op_rsp == NULL || op_rsp -> hdr .Status != STATUS_SUCCESS ) {
@@ -2333,6 +2376,11 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
2333
2376
SMB2_query_directory_free (& rqst [1 ]);
2334
2377
free_rsp_buf (resp_buftype [0 ], rsp_iov [0 ].iov_base );
2335
2378
free_rsp_buf (resp_buftype [1 ], rsp_iov [1 ].iov_base );
2379
+
2380
+ if (is_replayable_error (rc ) &&
2381
+ smb2_should_replay (tcon , & retries , & cur_sleep ))
2382
+ goto replay_again ;
2383
+
2336
2384
return rc ;
2337
2385
}
2338
2386
@@ -2457,6 +2505,22 @@ smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
2457
2505
CIFS_CACHE_READ (cinode ) ? 1 : 0 );
2458
2506
}
2459
2507
2508
+ void
2509
+ smb2_set_replay (struct TCP_Server_Info * server , struct smb_rqst * rqst )
2510
+ {
2511
+ struct smb2_hdr * shdr ;
2512
+
2513
+ if (server -> dialect < SMB30_PROT_ID )
2514
+ return ;
2515
+
2516
+ shdr = (struct smb2_hdr * )(rqst -> rq_iov [0 ].iov_base );
2517
+ if (shdr == NULL ) {
2518
+ cifs_dbg (FYI , "shdr NULL in smb2_set_related\n" );
2519
+ return ;
2520
+ }
2521
+ shdr -> Flags |= SMB2_FLAGS_REPLAY_OPERATION ;
2522
+ }
2523
+
2460
2524
void
2461
2525
smb2_set_related (struct smb_rqst * rqst )
2462
2526
{
@@ -2529,6 +2593,27 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
2529
2593
shdr -> NextCommand = cpu_to_le32 (len );
2530
2594
}
2531
2595
2596
+ /*
2597
+ * helper function for exponential backoff and check if replayable
2598
+ */
2599
+ bool smb2_should_replay (struct cifs_tcon * tcon ,
2600
+ int * pretries ,
2601
+ int * pcur_sleep )
2602
+ {
2603
+ if (!pretries || !pcur_sleep )
2604
+ return false;
2605
+
2606
+ if (tcon -> retry || (* pretries )++ < tcon -> ses -> server -> retrans ) {
2607
+ msleep (* pcur_sleep );
2608
+ (* pcur_sleep ) = ((* pcur_sleep ) << 1 );
2609
+ if ((* pcur_sleep ) > CIFS_MAX_SLEEP )
2610
+ (* pcur_sleep ) = CIFS_MAX_SLEEP ;
2611
+ return true;
2612
+ }
2613
+
2614
+ return false;
2615
+ }
2616
+
2532
2617
/*
2533
2618
* Passes the query info response back to the caller on success.
2534
2619
* Caller need to free this with free_rsp_buf().
@@ -2542,7 +2627,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
2542
2627
{
2543
2628
struct smb2_compound_vars * vars ;
2544
2629
struct cifs_ses * ses = tcon -> ses ;
2545
- struct TCP_Server_Info * server = cifs_pick_channel ( ses ) ;
2630
+ struct TCP_Server_Info * server ;
2546
2631
int flags = CIFS_CP_CREATE_CLOSE_OP ;
2547
2632
struct smb_rqst * rqst ;
2548
2633
int resp_buftype [3 ];
@@ -2553,6 +2638,13 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
2553
2638
int rc ;
2554
2639
__le16 * utf16_path ;
2555
2640
struct cached_fid * cfid = NULL ;
2641
+ int retries = 0 , cur_sleep = 1 ;
2642
+
2643
+ replay_again :
2644
+ /* reinitialize for possible replay */
2645
+ flags = CIFS_CP_CREATE_CLOSE_OP ;
2646
+ oplock = SMB2_OPLOCK_LEVEL_NONE ;
2647
+ server = cifs_pick_channel (ses );
2556
2648
2557
2649
if (!path )
2558
2650
path = "" ;
@@ -2633,6 +2725,14 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
2633
2725
goto qic_exit ;
2634
2726
smb2_set_related (& rqst [2 ]);
2635
2727
2728
+ if (retries ) {
2729
+ if (!cfid ) {
2730
+ smb2_set_replay (server , & rqst [0 ]);
2731
+ smb2_set_replay (server , & rqst [2 ]);
2732
+ }
2733
+ smb2_set_replay (server , & rqst [1 ]);
2734
+ }
2735
+
2636
2736
if (cfid ) {
2637
2737
rc = compound_send_recv (xid , ses , server ,
2638
2738
flags , 1 , & rqst [1 ],
@@ -2665,6 +2765,11 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
2665
2765
kfree (vars );
2666
2766
out_free_path :
2667
2767
kfree (utf16_path );
2768
+
2769
+ if (is_replayable_error (rc ) &&
2770
+ smb2_should_replay (tcon , & retries , & cur_sleep ))
2771
+ goto replay_again ;
2772
+
2668
2773
return rc ;
2669
2774
}
2670
2775
0 commit comments