@@ -1751,6 +1751,7 @@ static int cleaner_kthread(void *arg)
1751
1751
{
1752
1752
struct btrfs_root * root = arg ;
1753
1753
int again ;
1754
+ struct btrfs_trans_handle * trans ;
1754
1755
1755
1756
do {
1756
1757
again = 0 ;
@@ -1798,6 +1799,34 @@ static int cleaner_kthread(void *arg)
1798
1799
__set_current_state (TASK_RUNNING );
1799
1800
}
1800
1801
} while (!kthread_should_stop ());
1802
+
1803
+ /*
1804
+ * Transaction kthread is stopped before us and wakes us up.
1805
+ * However we might have started a new transaction and COWed some
1806
+ * tree blocks when deleting unused block groups for example. So
1807
+ * make sure we commit the transaction we started to have a clean
1808
+ * shutdown when evicting the btree inode - if it has dirty pages
1809
+ * when we do the final iput() on it, eviction will trigger a
1810
+ * writeback for it which will fail with null pointer dereferences
1811
+ * since work queues and other resources were already released and
1812
+ * destroyed by the time the iput/eviction/writeback is made.
1813
+ */
1814
+ trans = btrfs_attach_transaction (root );
1815
+ if (IS_ERR (trans )) {
1816
+ if (PTR_ERR (trans ) != - ENOENT )
1817
+ btrfs_err (root -> fs_info ,
1818
+ "cleaner transaction attach returned %ld" ,
1819
+ PTR_ERR (trans ));
1820
+ } else {
1821
+ int ret ;
1822
+
1823
+ ret = btrfs_commit_transaction (trans , root );
1824
+ if (ret )
1825
+ btrfs_err (root -> fs_info ,
1826
+ "cleaner open transaction commit returned %d" ,
1827
+ ret );
1828
+ }
1829
+
1801
1830
return 0 ;
1802
1831
}
1803
1832
0 commit comments