@@ -120,6 +120,7 @@ static bool inode_io_list_move_locked(struct inode *inode,
120
120
struct list_head * head )
121
121
{
122
122
assert_spin_locked (& wb -> list_lock );
123
+ assert_spin_locked (& inode -> i_lock );
123
124
124
125
list_move (& inode -> i_io_list , head );
125
126
@@ -1365,9 +1366,9 @@ static int move_expired_inodes(struct list_head *delaying_queue,
1365
1366
inode = wb_inode (delaying_queue -> prev );
1366
1367
if (inode_dirtied_after (inode , dirtied_before ))
1367
1368
break ;
1369
+ spin_lock (& inode -> i_lock );
1368
1370
list_move (& inode -> i_io_list , & tmp );
1369
1371
moved ++ ;
1370
- spin_lock (& inode -> i_lock );
1371
1372
inode -> i_state |= I_SYNC_QUEUED ;
1372
1373
spin_unlock (& inode -> i_lock );
1373
1374
if (sb_is_blkdev_sb (inode -> i_sb ))
@@ -1383,7 +1384,12 @@ static int move_expired_inodes(struct list_head *delaying_queue,
1383
1384
goto out ;
1384
1385
}
1385
1386
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
+ */
1387
1393
while (!list_empty (& tmp )) {
1388
1394
sb = wb_inode (tmp .prev )-> i_sb ;
1389
1395
list_for_each_prev_safe (pos , node , & tmp ) {
@@ -1826,8 +1832,8 @@ static long writeback_sb_inodes(struct super_block *sb,
1826
1832
* We'll have another go at writing back this inode
1827
1833
* when we completed a full scan of b_io.
1828
1834
*/
1829
- spin_unlock (& inode -> i_lock );
1830
1835
requeue_io (inode , wb );
1836
+ spin_unlock (& inode -> i_lock );
1831
1837
trace_writeback_sb_inodes_requeue (inode );
1832
1838
continue ;
1833
1839
}
@@ -2358,6 +2364,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
2358
2364
{
2359
2365
struct super_block * sb = inode -> i_sb ;
2360
2366
int dirtytime = 0 ;
2367
+ struct bdi_writeback * wb = NULL ;
2361
2368
2362
2369
trace_writeback_mark_inode_dirty (inode , flags );
2363
2370
@@ -2409,37 +2416,45 @@ void __mark_inode_dirty(struct inode *inode, int flags)
2409
2416
inode -> i_state &= ~I_DIRTY_TIME ;
2410
2417
inode -> i_state |= flags ;
2411
2418
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
+
2412
2430
/*
2413
2431
* If the inode is queued for writeback by flush worker, just
2414
2432
* update its dirty state. Once the flush worker is done with
2415
2433
* the inode it will place it on the appropriate superblock
2416
2434
* list, based upon its state.
2417
2435
*/
2418
2436
if (inode -> i_state & I_SYNC_QUEUED )
2419
- goto out_unlock_inode ;
2437
+ goto out_unlock ;
2420
2438
2421
2439
/*
2422
2440
* Only add valid (hashed) inodes to the superblock's
2423
2441
* dirty list. Add blockdev inodes as well.
2424
2442
*/
2425
2443
if (!S_ISBLK (inode -> i_mode )) {
2426
2444
if (inode_unhashed (inode ))
2427
- goto out_unlock_inode ;
2445
+ goto out_unlock ;
2428
2446
}
2429
2447
if (inode -> i_state & I_FREEING )
2430
- goto out_unlock_inode ;
2448
+ goto out_unlock ;
2431
2449
2432
2450
/*
2433
2451
* If the inode was already on b_dirty/b_io/b_more_io, don't
2434
2452
* reposition it (that would break b_dirty time-ordering).
2435
2453
*/
2436
2454
if (!was_dirty ) {
2437
- struct bdi_writeback * wb ;
2438
2455
struct list_head * dirty_list ;
2439
2456
bool wakeup_bdi = false;
2440
2457
2441
- wb = locked_inode_to_wb_and_lock_list (inode );
2442
-
2443
2458
inode -> dirtied_when = jiffies ;
2444
2459
if (dirtytime )
2445
2460
inode -> dirtied_time_when = jiffies ;
@@ -2453,6 +2468,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
2453
2468
dirty_list );
2454
2469
2455
2470
spin_unlock (& wb -> list_lock );
2471
+ spin_unlock (& inode -> i_lock );
2456
2472
trace_writeback_dirty_inode_enqueue (inode );
2457
2473
2458
2474
/*
@@ -2467,6 +2483,9 @@ void __mark_inode_dirty(struct inode *inode, int flags)
2467
2483
return ;
2468
2484
}
2469
2485
}
2486
+ out_unlock :
2487
+ if (wb )
2488
+ spin_unlock (& wb -> list_lock );
2470
2489
out_unlock_inode :
2471
2490
spin_unlock (& inode -> i_lock );
2472
2491
}
0 commit comments