@@ -26,6 +26,7 @@
#include <linux/sched.h>
#include <linux/uio.h>
#include <linux/vmstat.h>
+#include "internal.h"
int dax_clear_blocks(struct inode *inode, sector_t block, long size)
{
@@ -549,3 +550,31 @@ int dax_truncate_page(struct inode *inode, loff_t from, get_block_t get_block)
return dax_zero_page_range(inode, from, length, get_block);
}
EXPORT_SYMBOL_GPL(dax_truncate_page);
+
+/* This is meant to be called as part of freeze_super. otherwise we might
+ * Need some extra locking before calling here.
+ */
+void dax_prepare_freeze(struct super_block *sb)
+{
+ struct inode *inode;
+
+ if (!(sb->s_bdev && sb->s_bdev->bd_disk->fops->direct_access))
+ return;
+
+ spin_lock(&inode_sb_list_lock);
+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+ /* TODO: For freezing we can actually do with write-protecting
+ * the page. But I cannot find a ready made function that does
+ * that for a giving mapping (with all the proper locking).
+ * How performance sensitive is the all sb_freeze API?
+ * For now we can just unmap the all mapping, and pay extra
+ * on read faults.
+ */
+ /* NOTE: Do not unmap private COW mapped pages it will not
+ * modify the FS.
+ */
+ if (IS_DAX(inode))
+ unmap_mapping_range(inode->i_mapping, 0, 0, 0);
+ }
+ spin_unlock(&inode_sb_list_lock);
+}
@@ -1329,6 +1329,9 @@ int freeze_super(struct super_block *sb)
/* All writers are done so after syncing there won't be dirty data */
sync_filesystem(sb);
+ /* Need to take care of DAX mmaped inodes */
+ dax_prepare_freeze(sb);
+
/* Now wait for internal filesystem counter */
sb->s_writers.frozen = SB_FREEZE_FS;
smp_wmb();
@@ -2599,6 +2599,11 @@ int dax_truncate_page(struct inode *, loff_t from, get_block_t);
int dax_fault(struct vm_area_struct *, struct vm_fault *, get_block_t);
int dax_pfn_mkwrite(struct vm_area_struct *, struct vm_fault *);
#define dax_mkwrite(vma, vmf, gb) dax_fault(vma, vmf, gb)
+#ifdef CONFIG_FS_DAX
+void dax_prepare_freeze(struct super_block *sb);
+#else /* !CONFIG_FS_DAX */
+static inline void dax_prepare_freeze(struct super_block *sb){}
+#endif /* !CONFIG_FS_DAX */
#ifdef CONFIG_BLOCK
typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode,