@@ -163,13 +163,42 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
163
163
rcu_read_lock ();
164
164
opinfo = list_first_or_null_rcu (& ci -> m_op_list , struct oplock_info ,
165
165
op_entry );
166
- if (opinfo && !atomic_inc_not_zero (& opinfo -> refcount ))
167
- opinfo = NULL ;
166
+ if (opinfo ) {
167
+ if (!atomic_inc_not_zero (& opinfo -> refcount ))
168
+ opinfo = NULL ;
169
+ else {
170
+ atomic_inc (& opinfo -> conn -> r_count );
171
+ if (ksmbd_conn_releasing (opinfo -> conn )) {
172
+ atomic_dec (& opinfo -> conn -> r_count );
173
+ atomic_dec (& opinfo -> refcount );
174
+ opinfo = NULL ;
175
+ }
176
+ }
177
+ }
178
+
168
179
rcu_read_unlock ();
169
180
170
181
return opinfo ;
171
182
}
172
183
184
+ static void opinfo_conn_put (struct oplock_info * opinfo )
185
+ {
186
+ struct ksmbd_conn * conn ;
187
+
188
+ if (!opinfo )
189
+ return ;
190
+
191
+ conn = opinfo -> conn ;
192
+ /*
193
+ * Checking waitqueue to dropping pending requests on
194
+ * disconnection. waitqueue_active is safe because it
195
+ * uses atomic operation for condition.
196
+ */
197
+ if (!atomic_dec_return (& conn -> r_count ) && waitqueue_active (& conn -> r_count_q ))
198
+ wake_up (& conn -> r_count_q );
199
+ opinfo_put (opinfo );
200
+ }
201
+
173
202
void opinfo_put (struct oplock_info * opinfo )
174
203
{
175
204
if (!atomic_dec_and_test (& opinfo -> refcount ))
@@ -763,13 +792,6 @@ static void __smb1_oplock_break_noti(struct work_struct *wk)
763
792
764
793
ksmbd_conn_write (work );
765
794
ksmbd_free_work_struct (work );
766
- /*
767
- * Checking waitqueue to dropping pending requests on
768
- * disconnection. waitqueue_active is safe because it
769
- * uses atomic operation for condition.
770
- */
771
- if (!atomic_dec_return (& conn -> r_count ) && waitqueue_active (& conn -> r_count_q ))
772
- wake_up (& conn -> r_count_q );
773
795
}
774
796
775
797
/**
@@ -791,7 +813,6 @@ static int smb1_oplock_break_noti(struct oplock_info *opinfo)
791
813
work -> request_buf = (char * )opinfo ;
792
814
work -> conn = conn ;
793
815
794
- atomic_inc (& conn -> r_count );
795
816
if (opinfo -> op_state == OPLOCK_ACK_WAIT ) {
796
817
INIT_WORK (& work -> work , __smb1_oplock_break_noti );
797
818
ksmbd_queue_work (work );
@@ -876,13 +897,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
876
897
877
898
out :
878
899
ksmbd_free_work_struct (work );
879
- /*
880
- * Checking waitqueue to dropping pending requests on
881
- * disconnection. waitqueue_active is safe because it
882
- * uses atomic operation for condition.
883
- */
884
- if (!atomic_dec_return (& conn -> r_count ) && waitqueue_active (& conn -> r_count_q ))
885
- wake_up (& conn -> r_count_q );
886
900
}
887
901
888
902
/**
@@ -916,7 +930,6 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
916
930
work -> conn = conn ;
917
931
work -> sess = opinfo -> sess ;
918
932
919
- atomic_inc (& conn -> r_count );
920
933
if (opinfo -> op_state == OPLOCK_ACK_WAIT ) {
921
934
INIT_WORK (& work -> work , __smb2_oplock_break_noti );
922
935
ksmbd_queue_work (work );
@@ -986,13 +999,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
986
999
987
1000
out :
988
1001
ksmbd_free_work_struct (work );
989
- /*
990
- * Checking waitqueue to dropping pending requests on
991
- * disconnection. waitqueue_active is safe because it
992
- * uses atomic operation for condition.
993
- */
994
- if (!atomic_dec_return (& conn -> r_count ) && waitqueue_active (& conn -> r_count_q ))
995
- wake_up (& conn -> r_count_q );
996
1002
}
997
1003
998
1004
/**
@@ -1032,7 +1038,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
1032
1038
work -> conn = conn ;
1033
1039
work -> sess = opinfo -> sess ;
1034
1040
1035
- atomic_inc (& conn -> r_count );
1036
1041
if (opinfo -> op_state == OPLOCK_ACK_WAIT ) {
1037
1042
list_for_each_safe (tmp , t , & opinfo -> interim_list ) {
1038
1043
struct ksmbd_work * in_work ;
@@ -1368,28 +1373,30 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
1368
1373
}
1369
1374
prev_opinfo = opinfo_get_list (ci );
1370
1375
if (!prev_opinfo ||
1371
- (prev_opinfo -> level == SMB2_OPLOCK_LEVEL_NONE && lctx ))
1376
+ (prev_opinfo -> level == SMB2_OPLOCK_LEVEL_NONE && lctx )) {
1377
+ opinfo_conn_put (prev_opinfo );
1372
1378
goto set_lev ;
1379
+ }
1373
1380
prev_op_has_lease = prev_opinfo -> is_lease ;
1374
1381
if (prev_op_has_lease )
1375
1382
prev_op_state = prev_opinfo -> o_lease -> state ;
1376
1383
1377
1384
if (share_ret < 0 &&
1378
1385
prev_opinfo -> level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ) {
1379
1386
err = share_ret ;
1380
- opinfo_put (prev_opinfo );
1387
+ opinfo_conn_put (prev_opinfo );
1381
1388
goto err_out ;
1382
1389
}
1383
1390
1384
1391
if (prev_opinfo -> level != SMB2_OPLOCK_LEVEL_BATCH &&
1385
1392
prev_opinfo -> level != SMB2_OPLOCK_LEVEL_EXCLUSIVE ) {
1386
- opinfo_put (prev_opinfo );
1393
+ opinfo_conn_put (prev_opinfo );
1387
1394
goto op_break_not_needed ;
1388
1395
}
1389
1396
1390
1397
list_add (& work -> interim_entry , & prev_opinfo -> interim_list );
1391
1398
err = oplock_break (prev_opinfo , SMB2_OPLOCK_LEVEL_II );
1392
- opinfo_put (prev_opinfo );
1399
+ opinfo_conn_put (prev_opinfo );
1393
1400
if (err == - ENOENT )
1394
1401
goto set_lev ;
1395
1402
/* Check all oplock was freed by close */
@@ -1452,14 +1459,14 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work,
1452
1459
return ;
1453
1460
if (brk_opinfo -> level != SMB2_OPLOCK_LEVEL_BATCH &&
1454
1461
brk_opinfo -> level != SMB2_OPLOCK_LEVEL_EXCLUSIVE ) {
1455
- opinfo_put (brk_opinfo );
1462
+ opinfo_conn_put (brk_opinfo );
1456
1463
return ;
1457
1464
}
1458
1465
1459
1466
brk_opinfo -> open_trunc = is_trunc ;
1460
1467
list_add (& work -> interim_entry , & brk_opinfo -> interim_list );
1461
1468
oplock_break (brk_opinfo , SMB2_OPLOCK_LEVEL_II );
1462
- opinfo_put (brk_opinfo );
1469
+ opinfo_conn_put (brk_opinfo );
1463
1470
}
1464
1471
1465
1472
/**
@@ -1487,6 +1494,13 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
1487
1494
list_for_each_entry_rcu (brk_op , & ci -> m_op_list , op_entry ) {
1488
1495
if (!atomic_inc_not_zero (& brk_op -> refcount ))
1489
1496
continue ;
1497
+
1498
+ atomic_inc (& brk_op -> conn -> r_count );
1499
+ if (ksmbd_conn_releasing (brk_op -> conn )) {
1500
+ atomic_dec (& brk_op -> conn -> r_count );
1501
+ continue ;
1502
+ }
1503
+
1490
1504
rcu_read_unlock ();
1491
1505
1492
1506
#ifdef CONFIG_SMB_INSECURE_SERVER
@@ -1547,7 +1561,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
1547
1561
brk_op -> open_trunc = is_trunc ;
1548
1562
oplock_break (brk_op , SMB2_OPLOCK_LEVEL_NONE );
1549
1563
next :
1550
- opinfo_put (brk_op );
1564
+ opinfo_conn_put (brk_op );
1551
1565
rcu_read_lock ();
1552
1566
}
1553
1567
rcu_read_unlock ();
0 commit comments