fs: add CONFIG_BUFFER_HEAD
[linux-block.git] / block / fops.c
index 063ece37d44e44e487cf0f2b374b43b7f60e5ab4..eaa98a987213d2702f51b10cf5c4f1dc758d0149 100644 (file)
@@ -24,15 +24,6 @@ static inline struct inode *bdev_file_inode(struct file *file)
        return file->f_mapping->host;
 }
 
-static int blkdev_get_block(struct inode *inode, sector_t iblock,
-               struct buffer_head *bh, int create)
-{
-       bh->b_bdev = I_BDEV(inode);
-       bh->b_blocknr = iblock;
-       set_buffer_mapped(bh);
-       return 0;
-}
-
 static blk_opf_t dio_bio_write_op(struct kiocb *iocb)
 {
        blk_opf_t opf = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE;
@@ -400,7 +391,7 @@ static int blkdev_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
        iomap->type = IOMAP_MAPPED;
        iomap->addr = iomap->offset;
        iomap->length = isize - iomap->offset;
-       iomap->flags |= IOMAP_F_BUFFER_HEAD;
+       iomap->flags |= IOMAP_F_BUFFER_HEAD; /* noop for !CONFIG_BUFFER_HEAD */
        return 0;
 }
 
@@ -408,6 +399,16 @@ static const struct iomap_ops blkdev_iomap_ops = {
        .iomap_begin            = blkdev_iomap_begin,
 };
 
+#ifdef CONFIG_BUFFER_HEAD
+static int blkdev_get_block(struct inode *inode, sector_t iblock,
+               struct buffer_head *bh, int create)
+{
+       bh->b_bdev = I_BDEV(inode);
+       bh->b_blocknr = iblock;
+       set_buffer_mapped(bh);
+       return 0;
+}
+
 static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
 {
        return block_write_full_page(page, blkdev_get_block, wbc);
@@ -453,6 +454,55 @@ const struct address_space_operations def_blk_aops = {
        .migrate_folio  = buffer_migrate_folio_norefs,
        .is_dirty_writeback = buffer_check_dirty_writeback,
 };
+#else /* CONFIG_BUFFER_HEAD */
+static int blkdev_read_folio(struct file *file, struct folio *folio)
+{
+       return iomap_read_folio(folio, &blkdev_iomap_ops);
+}
+
+static void blkdev_readahead(struct readahead_control *rac)
+{
+       iomap_readahead(rac, &blkdev_iomap_ops);
+}
+
+static int blkdev_map_blocks(struct iomap_writepage_ctx *wpc,
+               struct inode *inode, loff_t offset)
+{
+       loff_t isize = i_size_read(inode);
+
+       if (WARN_ON_ONCE(offset >= isize))
+               return -EIO;
+       if (offset >= wpc->iomap.offset &&
+           offset < wpc->iomap.offset + wpc->iomap.length)
+               return 0;
+       return blkdev_iomap_begin(inode, offset, isize - offset,
+                                 IOMAP_WRITE, &wpc->iomap, NULL);
+}
+
+static const struct iomap_writeback_ops blkdev_writeback_ops = {
+       .map_blocks             = blkdev_map_blocks,
+};
+
+static int blkdev_writepages(struct address_space *mapping,
+               struct writeback_control *wbc)
+{
+       struct iomap_writepage_ctx wpc = { };
+
+       return iomap_writepages(mapping, wbc, &wpc, &blkdev_writeback_ops);
+}
+
+const struct address_space_operations def_blk_aops = {
+       .dirty_folio    = filemap_dirty_folio,
+       .release_folio          = iomap_release_folio,
+       .invalidate_folio       = iomap_invalidate_folio,
+       .read_folio             = blkdev_read_folio,
+       .readahead              = blkdev_readahead,
+       .writepages             = blkdev_writepages,
+       .is_partially_uptodate  = iomap_is_partially_uptodate,
+       .error_remove_page      = generic_error_remove_page,
+       .migrate_folio          = filemap_migrate_folio,
+};
+#endif /* CONFIG_BUFFER_HEAD */
 
 /*
  * for a block special file file_inode(file)->i_size is zero