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