@@ -157,13 +157,42 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
157157 rcu_read_lock ();
158158 opinfo = list_first_or_null_rcu (& ci -> m_op_list , struct oplock_info ,
159159 op_entry );
160- if (opinfo && !atomic_inc_not_zero (& opinfo -> refcount ))
161- opinfo = NULL ;
160+ if (opinfo ) {
161+ if (!atomic_inc_not_zero (& opinfo -> refcount ))
162+ opinfo = NULL ;
163+ else {
164+ atomic_inc (& opinfo -> conn -> r_count );
165+ if (ksmbd_conn_releasing (opinfo -> conn )) {
166+ atomic_dec (& opinfo -> conn -> r_count );
167+ atomic_dec (& opinfo -> refcount );
168+ opinfo = NULL ;
169+ }
170+ }
171+ }
172+
162173 rcu_read_unlock ();
163174
164175 return opinfo ;
165176}
166177
178+ static void opinfo_conn_put (struct oplock_info * opinfo )
179+ {
180+ struct ksmbd_conn * conn ;
181+
182+ if (!opinfo )
183+ return ;
184+
185+ conn = opinfo -> conn ;
186+ /*
187+ * Checking waitqueue to dropping pending requests on
188+ * disconnection. waitqueue_active is safe because it
189+ * uses atomic operation for condition.
190+ */
191+ if (!atomic_dec_return (& conn -> r_count ) && waitqueue_active (& conn -> r_count_q ))
192+ wake_up (& conn -> r_count_q );
193+ opinfo_put (opinfo );
194+ }
195+
167196void opinfo_put (struct oplock_info * opinfo )
168197{
169198 if (!atomic_dec_and_test (& opinfo -> refcount ))
@@ -666,13 +695,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
666695
667696out :
668697 ksmbd_free_work_struct (work );
669- /*
670- * Checking waitqueue to dropping pending requests on
671- * disconnection. waitqueue_active is safe because it
672- * uses atomic operation for condition.
673- */
674- if (!atomic_dec_return (& conn -> r_count ) && waitqueue_active (& conn -> r_count_q ))
675- wake_up (& conn -> r_count_q );
676698}
677699
678700/**
@@ -706,7 +728,6 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
706728 work -> conn = conn ;
707729 work -> sess = opinfo -> sess ;
708730
709- atomic_inc (& conn -> r_count );
710731 if (opinfo -> op_state == OPLOCK_ACK_WAIT ) {
711732 INIT_WORK (& work -> work , __smb2_oplock_break_noti );
712733 ksmbd_queue_work (work );
@@ -776,13 +797,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
776797
777798out :
778799 ksmbd_free_work_struct (work );
779- /*
780- * Checking waitqueue to dropping pending requests on
781- * disconnection. waitqueue_active is safe because it
782- * uses atomic operation for condition.
783- */
784- if (!atomic_dec_return (& conn -> r_count ) && waitqueue_active (& conn -> r_count_q ))
785- wake_up (& conn -> r_count_q );
786800}
787801
788802/**
@@ -822,7 +836,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
822836 work -> conn = conn ;
823837 work -> sess = opinfo -> sess ;
824838
825- atomic_inc (& conn -> r_count );
826839 if (opinfo -> op_state == OPLOCK_ACK_WAIT ) {
827840 list_for_each_safe (tmp , t , & opinfo -> interim_list ) {
828841 struct ksmbd_work * in_work ;
@@ -1144,28 +1157,30 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
11441157 }
11451158 prev_opinfo = opinfo_get_list (ci );
11461159 if (!prev_opinfo ||
1147- (prev_opinfo -> level == SMB2_OPLOCK_LEVEL_NONE && lctx ))
1160+ (prev_opinfo -> level == SMB2_OPLOCK_LEVEL_NONE && lctx )) {
1161+ opinfo_conn_put (prev_opinfo );
11481162 goto set_lev ;
1163+ }
11491164 prev_op_has_lease = prev_opinfo -> is_lease ;
11501165 if (prev_op_has_lease )
11511166 prev_op_state = prev_opinfo -> o_lease -> state ;
11521167
11531168 if (share_ret < 0 &&
11541169 prev_opinfo -> level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ) {
11551170 err = share_ret ;
1156- opinfo_put (prev_opinfo );
1171+ opinfo_conn_put (prev_opinfo );
11571172 goto err_out ;
11581173 }
11591174
11601175 if (prev_opinfo -> level != SMB2_OPLOCK_LEVEL_BATCH &&
11611176 prev_opinfo -> level != SMB2_OPLOCK_LEVEL_EXCLUSIVE ) {
1162- opinfo_put (prev_opinfo );
1177+ opinfo_conn_put (prev_opinfo );
11631178 goto op_break_not_needed ;
11641179 }
11651180
11661181 list_add (& work -> interim_entry , & prev_opinfo -> interim_list );
11671182 err = oplock_break (prev_opinfo , SMB2_OPLOCK_LEVEL_II );
1168- opinfo_put (prev_opinfo );
1183+ opinfo_conn_put (prev_opinfo );
11691184 if (err == - ENOENT )
11701185 goto set_lev ;
11711186 /* Check all oplock was freed by close */
@@ -1228,14 +1243,14 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work,
12281243 return ;
12291244 if (brk_opinfo -> level != SMB2_OPLOCK_LEVEL_BATCH &&
12301245 brk_opinfo -> level != SMB2_OPLOCK_LEVEL_EXCLUSIVE ) {
1231- opinfo_put (brk_opinfo );
1246+ opinfo_conn_put (brk_opinfo );
12321247 return ;
12331248 }
12341249
12351250 brk_opinfo -> open_trunc = is_trunc ;
12361251 list_add (& work -> interim_entry , & brk_opinfo -> interim_list );
12371252 oplock_break (brk_opinfo , SMB2_OPLOCK_LEVEL_II );
1238- opinfo_put (brk_opinfo );
1253+ opinfo_conn_put (brk_opinfo );
12391254}
12401255
12411256/**
@@ -1263,6 +1278,13 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
12631278 list_for_each_entry_rcu (brk_op , & ci -> m_op_list , op_entry ) {
12641279 if (!atomic_inc_not_zero (& brk_op -> refcount ))
12651280 continue ;
1281+
1282+ atomic_inc (& brk_op -> conn -> r_count );
1283+ if (ksmbd_conn_releasing (brk_op -> conn )) {
1284+ atomic_dec (& brk_op -> conn -> r_count );
1285+ continue ;
1286+ }
1287+
12661288 rcu_read_unlock ();
12671289 if (brk_op -> is_lease && (brk_op -> o_lease -> state &
12681290 (~(SMB2_LEASE_READ_CACHING_LE |
@@ -1292,7 +1314,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
12921314 brk_op -> open_trunc = is_trunc ;
12931315 oplock_break (brk_op , SMB2_OPLOCK_LEVEL_NONE );
12941316next :
1295- opinfo_put (brk_op );
1317+ opinfo_conn_put (brk_op );
12961318 rcu_read_lock ();
12971319 }
12981320 rcu_read_unlock ();
0 commit comments