[RFC] isofs iomap conversion
diff mbox series

Message ID 20200223164848.GK24185@bombadil.infradead.org
State New
Headers show
Series
  • [RFC] isofs iomap conversion
Related show

Commit Message

Matthew Wilcox Feb. 23, 2020, 4:48 p.m. UTC
This is just a toy, not intended for inclusion.  A real conversion would
strip buffer_heads entirely from isofs, and convert zisofs.

I decided I wanted to know more about how iomap works, and the easiest
way to do that is to convert a filesystem.  isofs recommended itself to
me as being read-only and pretty simple.

I like how it worked out; it's simpler than the isofs_get_blocks()
routine that it mostly replaces.  It's probably buggy; it compiles, but
I haven't tried it against an actual iso9660 filesystem.  I'd probably
want to copy some of the error printks over from isofs_get_blocks()
if this were anything other than a toy.

Patch
diff mbox series

diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 95b1f377ad09..61b14f359804 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -26,6 +26,7 @@ 
 #include <linux/user_namespace.h>
 #include <linux/seq_file.h>
 #include <linux/blkdev.h>
+#include <linux/iomap.h>
 
 #include "isofs.h"
 #include "zisofs.h"
@@ -1142,31 +1143,63 @@  int isofs_get_blocks(struct inode *inode, sector_t iblock,
 	return rv != 0 ? rv : error;
 }
 
-/*
- * Used by the standard interfaces.
- */
-static int isofs_get_block(struct inode *inode, sector_t iblock,
-		    struct buffer_head *bh_result, int create)
+static int isofs_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
+		unsigned flags, struct iomap *iomap, struct iomap *srcmap)
 {
-	int ret;
+	struct inode *ninode = inode;
+	int section = 0;
+	loff_t start = 0;
+	int err = -EIO;
+	struct iso_inode_info *ei;
 
-	if (create) {
-		printk(KERN_DEBUG "%s: Kernel tries to allocate a block\n", __func__);
-		return -EROFS;
+	for (;;) {
+		unsigned long nextblk, nextoff;
+
+		ei = ISOFS_I(ninode);
+		if (pos < start + ei->i_section_size)
+			break;
+		start += ei->i_section_size;
+		if (++section > 100)
+			goto abort;
+		nextblk = ei->i_next_section_block;
+		if (!nextblk)
+			goto abort;
+		nextoff = ei->i_next_section_offset;
+		if (ninode != inode)
+			iput(ninode);
+		ninode = isofs_iget(inode->i_sb, nextblk, nextoff);
+		if (IS_ERR(ninode)) {
+			err = PTR_ERR(ninode);
+			goto abort;
+		}
 	}
 
-	ret = isofs_get_blocks(inode, iblock, &bh_result, 1);
-	return ret < 0 ? ret : 0;
+	iomap->addr = (u64)ei->i_first_extent << inode->i_blkbits;
+	iomap->offset = start;
+	iomap->length = ei->i_section_size;
+	iomap->type = IOMAP_MAPPED;
+	iomap->flags = 0;
+	iomap->bdev = inode->i_bdev;
+	err = 0;
+abort:
+	if (ninode != inode)
+		iput(ninode);
+	return err;
 }
 
+const struct iomap_ops isofs_iomap_ops = {
+	.iomap_begin		= isofs_iomap_begin,
+};
+
 static int isofs_bmap(struct inode *inode, sector_t block)
 {
 	struct buffer_head dummy;
+	struct buffer_head *bhp = &dummy;
 	int error;
 
 	dummy.b_state = 0;
 	dummy.b_blocknr = -1000;
-	error = isofs_get_block(inode, block, &dummy, 0);
+	error = isofs_get_blocks(inode, block, &bhp, 1);
 	if (!error)
 		return dummy.b_blocknr;
 	return 0;
@@ -1182,17 +1215,17 @@  struct buffer_head *isofs_bread(struct inode *inode, sector_t block)
 
 static int isofs_readpage(struct file *file, struct page *page)
 {
-	return mpage_readpage(page, isofs_get_block);
+	return iomap_readpage(page, &isofs_iomap_ops);
 }
 
 static void isofs_readahead(struct readahead_control *rac)
 {
-	mpage_readahead(rac, isofs_get_block);
+	iomap_readahead(rac, &isofs_iomap_ops);
 }
 
 static sector_t _isofs_bmap(struct address_space *mapping, sector_t block)
 {
-	return generic_block_bmap(mapping,block,isofs_get_block);
+	return iomap_bmap(mapping, block, &isofs_iomap_ops);
 }
 
 static const struct address_space_operations isofs_aops = {