Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: mark all internal workqueues as freezable

Workqueues must be explicitly set as freezable to ensure they are frozen
in the assocated part of the hibernation/suspend sequence. Freezing of
workqueues and kernel threads is important to ensure that modifications
are not made on-disk after the hibernation image has been created.
Otherwise, the in-memory state can become inconsistent with what is on
disk and eventually lead to filesystem corruption. We have reports of
free space btree corruptions that occur immediately after restore from
hibernate that suggest the xfs-eofblocks workqueue could be causing
such problems if it races with hibernation.

Mark all of the internal XFS workqueues as freezable to ensure nothing
changes on-disk once the freezer infrastructure freezes kernel threads
and creates the hibernation image.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reported-by: Carlos E. R. <carlos.e.r@opensuse.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>

authored by

Brian Foster and committed by
Dave Chinner
8018ec08 52addcf9

+11 -9
+1 -1
fs/xfs/xfs_buf.c
··· 1884 1884 goto out; 1885 1885 1886 1886 xfslogd_workqueue = alloc_workqueue("xfslogd", 1887 - WQ_MEM_RECLAIM | WQ_HIGHPRI, 1); 1887 + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE, 1); 1888 1888 if (!xfslogd_workqueue) 1889 1889 goto out_free_buf_zone; 1890 1890
+2 -1
fs/xfs/xfs_mru_cache.c
··· 304 304 int 305 305 xfs_mru_cache_init(void) 306 306 { 307 - xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", WQ_MEM_RECLAIM, 1); 307 + xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", 308 + WQ_MEM_RECLAIM|WQ_FREEZABLE, 1); 308 309 if (!xfs_mru_reap_wq) 309 310 return -ENOMEM; 310 311 return 0;
+8 -7
fs/xfs/xfs_super.c
··· 838 838 struct xfs_mount *mp) 839 839 { 840 840 mp->m_data_workqueue = alloc_workqueue("xfs-data/%s", 841 - WQ_MEM_RECLAIM, 0, mp->m_fsname); 841 + WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname); 842 842 if (!mp->m_data_workqueue) 843 843 goto out; 844 844 845 845 mp->m_unwritten_workqueue = alloc_workqueue("xfs-conv/%s", 846 - WQ_MEM_RECLAIM, 0, mp->m_fsname); 846 + WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname); 847 847 if (!mp->m_unwritten_workqueue) 848 848 goto out_destroy_data_iodone_queue; 849 849 850 850 mp->m_cil_workqueue = alloc_workqueue("xfs-cil/%s", 851 - WQ_MEM_RECLAIM, 0, mp->m_fsname); 851 + WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname); 852 852 if (!mp->m_cil_workqueue) 853 853 goto out_destroy_unwritten; 854 854 855 855 mp->m_reclaim_workqueue = alloc_workqueue("xfs-reclaim/%s", 856 - 0, 0, mp->m_fsname); 856 + WQ_FREEZABLE, 0, mp->m_fsname); 857 857 if (!mp->m_reclaim_workqueue) 858 858 goto out_destroy_cil; 859 859 860 860 mp->m_log_workqueue = alloc_workqueue("xfs-log/%s", 861 - 0, 0, mp->m_fsname); 861 + WQ_FREEZABLE, 0, mp->m_fsname); 862 862 if (!mp->m_log_workqueue) 863 863 goto out_destroy_reclaim; 864 864 865 865 mp->m_eofblocks_workqueue = alloc_workqueue("xfs-eofblocks/%s", 866 - 0, 0, mp->m_fsname); 866 + WQ_FREEZABLE, 0, mp->m_fsname); 867 867 if (!mp->m_eofblocks_workqueue) 868 868 goto out_destroy_log; 869 869 ··· 1715 1715 * AGs in all the filesystems mounted. Hence use the default large 1716 1716 * max_active value for this workqueue. 1717 1717 */ 1718 - xfs_alloc_wq = alloc_workqueue("xfsalloc", WQ_MEM_RECLAIM, 0); 1718 + xfs_alloc_wq = alloc_workqueue("xfsalloc", 1719 + WQ_MEM_RECLAIM|WQ_FREEZABLE, 0); 1719 1720 if (!xfs_alloc_wq) 1720 1721 return -ENOMEM; 1721 1722