fs, dax: prepare for dax-specific address_space_operations
authorDan Williams <dan.j.williams@intel.com>
Wed, 7 Mar 2018 23:26:44 +0000 (15:26 -0800)
committerDan Williams <dan.j.williams@intel.com>
Fri, 30 Mar 2018 18:34:55 +0000 (11:34 -0700)
In preparation for the dax implementation to start associating dax pages
to inodes via page->mapping, we need to provide a 'struct
address_space_operations' instance for dax. Define some generic VFS aops
helpers for dax. These noop implementations are there in the dax case to
prevent the VFS from falling back to operations with page-cache
assumptions, dax_writeback_mapping_range() may not be referenced in the
FS_DAX=n case.

Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Suggested-by: Matthew Wilcox <mawilcox@microsoft.com>
Suggested-by: Jan Kara <jack@suse.cz>
Suggested-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Suggested-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
fs/libfs.c
include/linux/dax.h
include/linux/fs.h

index 7ff3cb904acdf8042c7c169dc9816764f0319629..0fb590d79f30ed78d0626fd79f24cacf9e1a72b8 100644 (file)
@@ -1060,6 +1060,45 @@ int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 }
 EXPORT_SYMBOL(noop_fsync);
 
+int noop_set_page_dirty(struct page *page)
+{
+       /*
+        * Unlike __set_page_dirty_no_writeback that handles dirty page
+        * tracking in the page object, dax does all dirty tracking in
+        * the inode address_space in response to mkwrite faults. In the
+        * dax case we only need to worry about potentially dirty CPU
+        * caches, not dirty page cache pages to write back.
+        *
+        * This callback is defined to prevent fallback to
+        * __set_page_dirty_buffers() in set_page_dirty().
+        */
+       return 0;
+}
+EXPORT_SYMBOL_GPL(noop_set_page_dirty);
+
+void noop_invalidatepage(struct page *page, unsigned int offset,
+               unsigned int length)
+{
+       /*
+        * There is no page cache to invalidate in the dax case, however
+        * we need this callback defined to prevent falling back to
+        * block_invalidatepage() in do_invalidatepage().
+        */
+}
+EXPORT_SYMBOL_GPL(noop_invalidatepage);
+
+ssize_t noop_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+{
+       /*
+        * iomap based filesystems support direct I/O without need for
+        * this callback. However, it still needs to be set in
+        * inode->a_ops so that open/fcntl know that direct I/O is
+        * generally supported.
+        */
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(noop_direct_IO);
+
 /* Because kfree isn't assignment-compatible with void(void*) ;-/ */
 void kfree_link(void *p)
 {
index 0185ecdae1352d53f073d398b239c543c4d367d5..ae27a7efe7ab515f9f11e67e592a949cd4c978c2 100644 (file)
@@ -38,6 +38,7 @@ static inline void put_dax(struct dax_device *dax_dev)
 }
 #endif
 
+struct writeback_control;
 int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
 #if IS_ENABLED(CONFIG_FS_DAX)
 int __bdev_dax_supported(struct super_block *sb, int blocksize);
@@ -57,6 +58,8 @@ static inline void fs_put_dax(struct dax_device *dax_dev)
 }
 
 struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev);
+int dax_writeback_mapping_range(struct address_space *mapping,
+               struct block_device *bdev, struct writeback_control *wbc);
 #else
 static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
 {
@@ -76,6 +79,12 @@ static inline struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev)
 {
        return NULL;
 }
+
+static inline int dax_writeback_mapping_range(struct address_space *mapping,
+               struct block_device *bdev, struct writeback_control *wbc)
+{
+       return -EOPNOTSUPP;
+}
 #endif
 
 int dax_read_lock(void);
@@ -121,7 +130,4 @@ static inline bool dax_mapping(struct address_space *mapping)
        return mapping->host && IS_DAX(mapping->host);
 }
 
-struct writeback_control;
-int dax_writeback_mapping_range(struct address_space *mapping,
-               struct block_device *bdev, struct writeback_control *wbc);
 #endif
index 79c4139853057ed8de863a074e1a34a13bfa9b4f..44f7f7080faa0c6c752695f74f1cecc57fc52f31 100644 (file)
@@ -3129,6 +3129,10 @@ extern int simple_rmdir(struct inode *, struct dentry *);
 extern int simple_rename(struct inode *, struct dentry *,
                         struct inode *, struct dentry *, unsigned int);
 extern int noop_fsync(struct file *, loff_t, loff_t, int);
+extern int noop_set_page_dirty(struct page *page);
+extern void noop_invalidatepage(struct page *page, unsigned int offset,
+               unsigned int length);
+extern ssize_t noop_direct_IO(struct kiocb *iocb, struct iov_iter *iter);
 extern int simple_empty(struct dentry *);
 extern int simple_readpage(struct file *file, struct page *page);
 extern int simple_write_begin(struct file *file, struct address_space *mapping,