5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 1) // SPDX-License-Identifier: GPL-2.0
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 2) /*
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 3) * Copyright (c) 2016-2018 Christoph Hellwig.
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 4) */
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 5) #include <linux/module.h>
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 6) #include <linux/compiler.h>
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 7) #include <linux/fs.h>
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 8) #include <linux/iomap.h>
10c5db286452b (Christoph Hellwig 2020-05-23 09:30:11 +0200 9) #include <linux/fiemap.h>
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 10)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 11) struct fiemap_ctx {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 12) struct fiemap_extent_info *fi;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 13) struct iomap prev;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 14) };
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 15)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 16) static int iomap_to_fiemap(struct fiemap_extent_info *fi,
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 17) struct iomap *iomap, u32 flags)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 18) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 19) switch (iomap->type) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 20) case IOMAP_HOLE:
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 21) /* skip holes */
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 22) return 0;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 23) case IOMAP_DELALLOC:
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 24) flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 25) break;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 26) case IOMAP_MAPPED:
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 27) break;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 28) case IOMAP_UNWRITTEN:
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 29) flags |= FIEMAP_EXTENT_UNWRITTEN;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 30) break;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 31) case IOMAP_INLINE:
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 32) flags |= FIEMAP_EXTENT_DATA_INLINE;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 33) break;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 34) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 35)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 36) if (iomap->flags & IOMAP_F_MERGED)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 37) flags |= FIEMAP_EXTENT_MERGED;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 38) if (iomap->flags & IOMAP_F_SHARED)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 39) flags |= FIEMAP_EXTENT_SHARED;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 40)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 41) return fiemap_fill_next_extent(fi, iomap->offset,
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 42) iomap->addr != IOMAP_NULL_ADDR ? iomap->addr : 0,
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 43) iomap->length, flags);
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 44) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 45)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 46) static loff_t
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 47) iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
c039b99792726 (Goldwyn Rodrigues 2019-10-18 16:44:10 -0700 48) struct iomap *iomap, struct iomap *srcmap)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 49) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 50) struct fiemap_ctx *ctx = data;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 51) loff_t ret = length;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 52)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 53) if (iomap->type == IOMAP_HOLE)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 54) return length;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 55)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 56) ret = iomap_to_fiemap(ctx->fi, &ctx->prev, 0);
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 57) ctx->prev = *iomap;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 58) switch (ret) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 59) case 0: /* success */
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 60) return length;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 61) case 1: /* extent array full */
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 62) return 0;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 63) default:
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 64) return ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 65) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 66) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 67)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 68) int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
2732881894714 (Christoph Hellwig 2020-05-23 09:30:12 +0200 69) u64 start, u64 len, const struct iomap_ops *ops)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 70) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 71) struct fiemap_ctx ctx;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 72) loff_t ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 73)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 74) memset(&ctx, 0, sizeof(ctx));
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 75) ctx.fi = fi;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 76) ctx.prev.type = IOMAP_HOLE;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 77)
45dd052e67ad1 (Christoph Hellwig 2020-05-23 09:30:14 +0200 78) ret = fiemap_prep(inode, fi, start, &len, 0);
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 79) if (ret)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 80) return ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 81)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 82) while (len > 0) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 83) ret = iomap_apply(inode, start, len, IOMAP_REPORT, ops, &ctx,
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 84) iomap_fiemap_actor);
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 85) /* inode with no (attribute) mapping will give ENOENT */
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 86) if (ret == -ENOENT)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 87) break;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 88) if (ret < 0)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 89) return ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 90) if (ret == 0)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 91) break;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 92)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 93) start += ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 94) len -= ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 95) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 96)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 97) if (ctx.prev.type != IOMAP_HOLE) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 98) ret = iomap_to_fiemap(fi, &ctx.prev, FIEMAP_EXTENT_LAST);
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 99) if (ret < 0)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 100) return ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 101) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 102)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 103) return 0;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 104) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 105) EXPORT_SYMBOL_GPL(iomap_fiemap);
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 106)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 107) static loff_t
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 108) iomap_bmap_actor(struct inode *inode, loff_t pos, loff_t length,
c039b99792726 (Goldwyn Rodrigues 2019-10-18 16:44:10 -0700 109) void *data, struct iomap *iomap, struct iomap *srcmap)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 110) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 111) sector_t *bno = data, addr;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 112)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 113) if (iomap->type == IOMAP_MAPPED) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 114) addr = (pos - iomap->offset + iomap->addr) >> inode->i_blkbits;
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 115) *bno = addr;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 116) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 117) return 0;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 118) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 119)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 120) /* legacy ->bmap interface. 0 is the error return (!) */
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 121) sector_t
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 122) iomap_bmap(struct address_space *mapping, sector_t bno,
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 123) const struct iomap_ops *ops)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 124) {
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 125) struct inode *inode = mapping->host;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 126) loff_t pos = bno << inode->i_blkbits;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 127) unsigned blocksize = i_blocksize(inode);
2b91b28e29f64 (Darrick J. Wong 2019-11-07 07:28:18 -0800 128) int ret;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 129)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 130) if (filemap_write_and_wait(mapping))
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 131) return 0;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 132)
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 133) bno = 0;
2b91b28e29f64 (Darrick J. Wong 2019-11-07 07:28:18 -0800 134) ret = iomap_apply(inode, pos, blocksize, 0, ops, &bno,
2b91b28e29f64 (Darrick J. Wong 2019-11-07 07:28:18 -0800 135) iomap_bmap_actor);
2b91b28e29f64 (Darrick J. Wong 2019-11-07 07:28:18 -0800 136) if (ret)
2b91b28e29f64 (Darrick J. Wong 2019-11-07 07:28:18 -0800 137) return 0;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 138) return bno;
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 139) }
5157fb8f5ae12 (Darrick J. Wong 2019-07-15 08:50:58 -0700 140) EXPORT_SYMBOL_GPL(iomap_bmap);