56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 1) // SPDX-License-Identifier: GPL-2.0
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 2) /*
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 3) * Copyright (C) 2017 Red Hat, Inc.
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 4) * Copyright (c) 2018 Christoph Hellwig.
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 5) */
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 6) #include <linux/module.h>
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 7) #include <linux/compiler.h>
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 8) #include <linux/fs.h>
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 9) #include <linux/iomap.h>
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 10) #include <linux/pagemap.h>
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 11) #include <linux/pagevec.h>
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 12)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 13) static loff_t
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 14) iomap_seek_hole_actor(struct inode *inode, loff_t start, loff_t length,
c039b99792726 (Goldwyn Rodrigues 2019-10-18 16:44:10 -0700 15) void *data, struct iomap *iomap, struct iomap *srcmap)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 16) {
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 17) loff_t offset = start;
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 18)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 19) switch (iomap->type) {
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 20) case IOMAP_UNWRITTEN:
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 21) offset = mapping_seek_hole_data(inode->i_mapping, start,
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 22) start + length, SEEK_HOLE);
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 23) if (offset == start + length)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 24) return length;
df561f6688fef (Gustavo A. R. Silva 2020-08-23 17:36:59 -0500 25) fallthrough;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 26) case IOMAP_HOLE:
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 27) *(loff_t *)data = offset;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 28) return 0;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 29) default:
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 30) return length;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 31) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 32) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 33)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 34) loff_t
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 35) iomap_seek_hole(struct inode *inode, loff_t offset, const struct iomap_ops *ops)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 36) {
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 37) loff_t size = i_size_read(inode);
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 38) loff_t ret;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 39)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 40) /* Nothing to be found before or beyond the end of the file. */
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 41) if (offset < 0 || offset >= size)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 42) return -ENXIO;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 43)
0ad0e62e74cec (Christoph Hellwig 2021-07-15 09:58:04 -0700 44) while (offset < size) {
0ad0e62e74cec (Christoph Hellwig 2021-07-15 09:58:04 -0700 45) ret = iomap_apply(inode, offset, size - offset, IOMAP_REPORT,
0ad0e62e74cec (Christoph Hellwig 2021-07-15 09:58:04 -0700 46) ops, &offset, iomap_seek_hole_actor);
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 47) if (ret < 0)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 48) return ret;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 49) if (ret == 0)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 50) break;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 51) offset += ret;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 52) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 53)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 54) return offset;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 55) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 56) EXPORT_SYMBOL_GPL(iomap_seek_hole);
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 57)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 58) static loff_t
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 59) iomap_seek_data_actor(struct inode *inode, loff_t start, loff_t length,
c039b99792726 (Goldwyn Rodrigues 2019-10-18 16:44:10 -0700 60) void *data, struct iomap *iomap, struct iomap *srcmap)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 61) {
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 62) loff_t offset = start;
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 63)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 64) switch (iomap->type) {
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 65) case IOMAP_HOLE:
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 66) return length;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 67) case IOMAP_UNWRITTEN:
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 68) offset = mapping_seek_hole_data(inode->i_mapping, start,
54fa39ac2e00b (Matthew Wilcox (Oracle) 2021-02-25 17:15:52 -0800 69) start + length, SEEK_DATA);
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 70) if (offset < 0)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 71) return length;
df561f6688fef (Gustavo A. R. Silva 2020-08-23 17:36:59 -0500 72) fallthrough;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 73) default:
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 74) *(loff_t *)data = offset;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 75) return 0;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 76) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 77) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 78)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 79) loff_t
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 80) iomap_seek_data(struct inode *inode, loff_t offset, const struct iomap_ops *ops)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 81) {
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 82) loff_t size = i_size_read(inode);
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 83) loff_t ret;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 84)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 85) /* Nothing to be found before or beyond the end of the file. */
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 86) if (offset < 0 || offset >= size)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 87) return -ENXIO;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 88)
521168b44c085 (Christoph Hellwig 2021-07-15 09:58:04 -0700 89) while (offset < size) {
521168b44c085 (Christoph Hellwig 2021-07-15 09:58:04 -0700 90) ret = iomap_apply(inode, offset, size - offset, IOMAP_REPORT,
521168b44c085 (Christoph Hellwig 2021-07-15 09:58:04 -0700 91) ops, &offset, iomap_seek_data_actor);
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 92) if (ret < 0)
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 93) return ret;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 94) if (ret == 0)
521168b44c085 (Christoph Hellwig 2021-07-15 09:58:04 -0700 95) return offset;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 96) offset += ret;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 97) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 98)
521168b44c085 (Christoph Hellwig 2021-07-15 09:58:04 -0700 99) /* We've reached the end of the file without finding data */
521168b44c085 (Christoph Hellwig 2021-07-15 09:58:04 -0700 100) return -ENXIO;
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 101) }
56a178981d470 (Darrick J. Wong 2019-07-15 08:50:58 -0700 102) EXPORT_SYMBOL_GPL(iomap_seek_data);