@@ -120,6 +120,7 @@ static bool inode_io_list_move_locked(struct inode *inode,
120120 struct list_head * head )
121121{
122122 assert_spin_locked (& wb -> list_lock );
123+ assert_spin_locked (& inode -> i_lock );
123124
124125 list_move (& inode -> i_io_list , head );
125126
@@ -1365,9 +1366,9 @@ static int move_expired_inodes(struct list_head *delaying_queue,
13651366 inode = wb_inode (delaying_queue -> prev );
13661367 if (inode_dirtied_after (inode , dirtied_before ))
13671368 break ;
1369+ spin_lock (& inode -> i_lock );
13681370 list_move (& inode -> i_io_list , & tmp );
13691371 moved ++ ;
1370- spin_lock (& inode -> i_lock );
13711372 inode -> i_state |= I_SYNC_QUEUED ;
13721373 spin_unlock (& inode -> i_lock );
13731374 if (sb_is_blkdev_sb (inode -> i_sb ))
@@ -1383,7 +1384,12 @@ static int move_expired_inodes(struct list_head *delaying_queue,
13831384 goto out ;
13841385 }
13851386
1386- /* Move inodes from one superblock together */
1387+ /*
1388+ * Although inode's i_io_list is moved from 'tmp' to 'dispatch_queue',
1389+ * we don't take inode->i_lock here because it is just a pointless overhead.
1390+ * Inode is already marked as I_SYNC_QUEUED so writeback list handling is
1391+ * fully under our control.
1392+ */
13871393 while (!list_empty (& tmp )) {
13881394 sb = wb_inode (tmp .prev )-> i_sb ;
13891395 list_for_each_prev_safe (pos , node , & tmp ) {
@@ -1826,8 +1832,8 @@ static long writeback_sb_inodes(struct super_block *sb,
18261832 * We'll have another go at writing back this inode
18271833 * when we completed a full scan of b_io.
18281834 */
1829- spin_unlock (& inode -> i_lock );
18301835 requeue_io (inode , wb );
1836+ spin_unlock (& inode -> i_lock );
18311837 trace_writeback_sb_inodes_requeue (inode );
18321838 continue ;
18331839 }
@@ -2358,6 +2364,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
23582364{
23592365 struct super_block * sb = inode -> i_sb ;
23602366 int dirtytime = 0 ;
2367+ struct bdi_writeback * wb = NULL ;
23612368
23622369 trace_writeback_mark_inode_dirty (inode , flags );
23632370
@@ -2409,37 +2416,45 @@ void __mark_inode_dirty(struct inode *inode, int flags)
24092416 inode -> i_state &= ~I_DIRTY_TIME ;
24102417 inode -> i_state |= flags ;
24112418
2419+ /*
2420+ * Grab inode's wb early because it requires dropping i_lock and we
2421+ * need to make sure following checks happen atomically with dirty
2422+ * list handling so that we don't move inodes under flush worker's
2423+ * hands.
2424+ */
2425+ if (!was_dirty ) {
2426+ wb = locked_inode_to_wb_and_lock_list (inode );
2427+ spin_lock (& inode -> i_lock );
2428+ }
2429+
24122430 /*
24132431 * If the inode is queued for writeback by flush worker, just
24142432 * update its dirty state. Once the flush worker is done with
24152433 * the inode it will place it on the appropriate superblock
24162434 * list, based upon its state.
24172435 */
24182436 if (inode -> i_state & I_SYNC_QUEUED )
2419- goto out_unlock_inode ;
2437+ goto out_unlock ;
24202438
24212439 /*
24222440 * Only add valid (hashed) inodes to the superblock's
24232441 * dirty list. Add blockdev inodes as well.
24242442 */
24252443 if (!S_ISBLK (inode -> i_mode )) {
24262444 if (inode_unhashed (inode ))
2427- goto out_unlock_inode ;
2445+ goto out_unlock ;
24282446 }
24292447 if (inode -> i_state & I_FREEING )
2430- goto out_unlock_inode ;
2448+ goto out_unlock ;
24312449
24322450 /*
24332451 * If the inode was already on b_dirty/b_io/b_more_io, don't
24342452 * reposition it (that would break b_dirty time-ordering).
24352453 */
24362454 if (!was_dirty ) {
2437- struct bdi_writeback * wb ;
24382455 struct list_head * dirty_list ;
24392456 bool wakeup_bdi = false;
24402457
2441- wb = locked_inode_to_wb_and_lock_list (inode );
2442-
24432458 inode -> dirtied_when = jiffies ;
24442459 if (dirtytime )
24452460 inode -> dirtied_time_when = jiffies ;
@@ -2453,6 +2468,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
24532468 dirty_list );
24542469
24552470 spin_unlock (& wb -> list_lock );
2471+ spin_unlock (& inode -> i_lock );
24562472 trace_writeback_dirty_inode_enqueue (inode );
24572473
24582474 /*
@@ -2467,6 +2483,9 @@ void __mark_inode_dirty(struct inode *inode, int flags)
24672483 return ;
24682484 }
24692485 }
2486+ out_unlock :
2487+ if (wb )
2488+ spin_unlock (& wb -> list_lock );
24702489out_unlock_inode :
24712490 spin_unlock (& inode -> i_lock );
24722491}
0 commit comments