User: | Jiri Slaby |
Error type: | Double Lock |
Error type description: | Some lock is locked twice unintentionally in a sequence |
File location: | fs/jbd/commit.c |
Line in file: | 238 |
Project: | Linux Kernel |
Project version: | 2.6.28 |
Tools: |
Stanse
(1.2)
Clang Static Analyzer (3.0) Smatch (1.59) |
Entered: | 2011-11-07 22:19:59 UTC |
208 spin_lock(&journal->j_list_lock); 209 210 while (commit_transaction->t_sync_datalist) { 211 jh = commit_transaction->t_sync_datalist; 212 bh = jh2bh(jh); 213 locked = 0; 214 215 /* Get reference just to make sure buffer does not disappear 216 * when we are forced to drop various locks */ 217 get_bh(bh); 218 /* If the buffer is dirty, we need to submit IO and hence 219 * we need the buffer lock. We try to lock the buffer without 220 * blocking. If we fail, we need to drop j_list_lock and do 221 * blocking lock_buffer(). 222 */ 223 if (buffer_dirty(bh)) { 224 if (!trylock_buffer(bh)) { 225 BUFFER_TRACE(bh, "needs blocking lock"); 226 spin_unlock(&journal->j_list_lock); 227 /* Write out all data to prevent deadlocks */ 228 journal_do_submit_data(wbuf, bufs); 229 bufs = 0; 230 lock_buffer(bh); 231 spin_lock(&journal->j_list_lock); 232 } 233 locked = 1; 234 } 235 /* We have to get bh_state lock. Again out of order, sigh. */ 236 if (!inverted_lock(journal, bh)) { 237 jbd_lock_bh_state(bh); 238 spin_lock(&journal->j_list_lock); 239 } 240 /* Someone already cleaned up the buffer? */ 241 if (!buffer_jbd(bh) 242 || jh->b_transaction != commit_transaction 243 || jh->b_jlist != BJ_SyncData) { 244 jbd_unlock_bh_state(bh); 245 if (locked) 246 unlock_buffer(bh); 247 BUFFER_TRACE(bh, "already cleaned up"); 248 release_data_buffer(bh);