diff options
Diffstat (limited to 'fs/nilfs2/segment.c')
-rw-r--r-- | fs/nilfs2/segment.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 7ef18fc656c2..469086b9f99b 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -305,7 +305,6 @@ static void nilfs_transaction_lock(struct super_block *sb, | |||
305 | ti->ti_count = 0; | 305 | ti->ti_count = 0; |
306 | ti->ti_save = cur_ti; | 306 | ti->ti_save = cur_ti; |
307 | ti->ti_magic = NILFS_TI_MAGIC; | 307 | ti->ti_magic = NILFS_TI_MAGIC; |
308 | INIT_LIST_HEAD(&ti->ti_garbage); | ||
309 | current->journal_info = ti; | 308 | current->journal_info = ti; |
310 | 309 | ||
311 | for (;;) { | 310 | for (;;) { |
@@ -332,8 +331,6 @@ static void nilfs_transaction_unlock(struct super_block *sb) | |||
332 | 331 | ||
333 | up_write(&nilfs->ns_segctor_sem); | 332 | up_write(&nilfs->ns_segctor_sem); |
334 | current->journal_info = ti->ti_save; | 333 | current->journal_info = ti->ti_save; |
335 | if (!list_empty(&ti->ti_garbage)) | ||
336 | nilfs_dispose_list(nilfs, &ti->ti_garbage, 0); | ||
337 | } | 334 | } |
338 | 335 | ||
339 | static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, | 336 | static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, |
@@ -746,6 +743,15 @@ static void nilfs_dispose_list(struct the_nilfs *nilfs, | |||
746 | } | 743 | } |
747 | } | 744 | } |
748 | 745 | ||
746 | static void nilfs_iput_work_func(struct work_struct *work) | ||
747 | { | ||
748 | struct nilfs_sc_info *sci = container_of(work, struct nilfs_sc_info, | ||
749 | sc_iput_work); | ||
750 | struct the_nilfs *nilfs = sci->sc_super->s_fs_info; | ||
751 | |||
752 | nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 0); | ||
753 | } | ||
754 | |||
749 | static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs, | 755 | static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs, |
750 | struct nilfs_root *root) | 756 | struct nilfs_root *root) |
751 | { | 757 | { |
@@ -1900,8 +1906,8 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, | |||
1900 | static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, | 1906 | static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, |
1901 | struct the_nilfs *nilfs) | 1907 | struct the_nilfs *nilfs) |
1902 | { | 1908 | { |
1903 | struct nilfs_transaction_info *ti = current->journal_info; | ||
1904 | struct nilfs_inode_info *ii, *n; | 1909 | struct nilfs_inode_info *ii, *n; |
1910 | int defer_iput = false; | ||
1905 | 1911 | ||
1906 | spin_lock(&nilfs->ns_inode_lock); | 1912 | spin_lock(&nilfs->ns_inode_lock); |
1907 | list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { | 1913 | list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { |
@@ -1912,9 +1918,24 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, | |||
1912 | clear_bit(NILFS_I_BUSY, &ii->i_state); | 1918 | clear_bit(NILFS_I_BUSY, &ii->i_state); |
1913 | brelse(ii->i_bh); | 1919 | brelse(ii->i_bh); |
1914 | ii->i_bh = NULL; | 1920 | ii->i_bh = NULL; |
1915 | list_move_tail(&ii->i_dirty, &ti->ti_garbage); | 1921 | list_del_init(&ii->i_dirty); |
1922 | if (!ii->vfs_inode.i_nlink) { | ||
1923 | /* | ||
1924 | * Defer calling iput() to avoid a deadlock | ||
1925 | * over I_SYNC flag for inodes with i_nlink == 0 | ||
1926 | */ | ||
1927 | list_add_tail(&ii->i_dirty, &sci->sc_iput_queue); | ||
1928 | defer_iput = true; | ||
1929 | } else { | ||
1930 | spin_unlock(&nilfs->ns_inode_lock); | ||
1931 | iput(&ii->vfs_inode); | ||
1932 | spin_lock(&nilfs->ns_inode_lock); | ||
1933 | } | ||
1916 | } | 1934 | } |
1917 | spin_unlock(&nilfs->ns_inode_lock); | 1935 | spin_unlock(&nilfs->ns_inode_lock); |
1936 | |||
1937 | if (defer_iput) | ||
1938 | schedule_work(&sci->sc_iput_work); | ||
1918 | } | 1939 | } |
1919 | 1940 | ||
1920 | /* | 1941 | /* |
@@ -2583,6 +2604,8 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, | |||
2583 | INIT_LIST_HEAD(&sci->sc_segbufs); | 2604 | INIT_LIST_HEAD(&sci->sc_segbufs); |
2584 | INIT_LIST_HEAD(&sci->sc_write_logs); | 2605 | INIT_LIST_HEAD(&sci->sc_write_logs); |
2585 | INIT_LIST_HEAD(&sci->sc_gc_inodes); | 2606 | INIT_LIST_HEAD(&sci->sc_gc_inodes); |
2607 | INIT_LIST_HEAD(&sci->sc_iput_queue); | ||
2608 | INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func); | ||
2586 | init_timer(&sci->sc_timer); | 2609 | init_timer(&sci->sc_timer); |
2587 | 2610 | ||
2588 | sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; | 2611 | sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; |
@@ -2609,6 +2632,8 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) | |||
2609 | ret = nilfs_segctor_construct(sci, SC_LSEG_SR); | 2632 | ret = nilfs_segctor_construct(sci, SC_LSEG_SR); |
2610 | nilfs_transaction_unlock(sci->sc_super); | 2633 | nilfs_transaction_unlock(sci->sc_super); |
2611 | 2634 | ||
2635 | flush_work(&sci->sc_iput_work); | ||
2636 | |||
2612 | } while (ret && retrycount-- > 0); | 2637 | } while (ret && retrycount-- > 0); |
2613 | } | 2638 | } |
2614 | 2639 | ||
@@ -2633,6 +2658,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) | |||
2633 | || sci->sc_seq_request != sci->sc_seq_done); | 2658 | || sci->sc_seq_request != sci->sc_seq_done); |
2634 | spin_unlock(&sci->sc_state_lock); | 2659 | spin_unlock(&sci->sc_state_lock); |
2635 | 2660 | ||
2661 | if (flush_work(&sci->sc_iput_work)) | ||
2662 | flag = true; | ||
2663 | |||
2636 | if (flag || !nilfs_segctor_confirm(sci)) | 2664 | if (flag || !nilfs_segctor_confirm(sci)) |
2637 | nilfs_segctor_write_out(sci); | 2665 | nilfs_segctor_write_out(sci); |
2638 | 2666 | ||
@@ -2642,6 +2670,12 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) | |||
2642 | nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1); | 2670 | nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1); |
2643 | } | 2671 | } |
2644 | 2672 | ||
2673 | if (!list_empty(&sci->sc_iput_queue)) { | ||
2674 | nilfs_warning(sci->sc_super, __func__, | ||
2675 | "iput queue is not empty\n"); | ||
2676 | nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 1); | ||
2677 | } | ||
2678 | |||
2645 | WARN_ON(!list_empty(&sci->sc_segbufs)); | 2679 | WARN_ON(!list_empty(&sci->sc_segbufs)); |
2646 | WARN_ON(!list_empty(&sci->sc_write_logs)); | 2680 | WARN_ON(!list_empty(&sci->sc_write_logs)); |
2647 | 2681 | ||