1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 /* 2 /* 3 * Copyright (C) 2017 Red Hat, Inc. 3 * Copyright (C) 2017 Red Hat, Inc. 4 * Copyright (c) 2018-2021 Christoph Hellwig. !! 4 * Copyright (c) 2018 Christoph Hellwig. 5 */ 5 */ 6 #include <linux/module.h> 6 #include <linux/module.h> 7 #include <linux/compiler.h> 7 #include <linux/compiler.h> 8 #include <linux/fs.h> 8 #include <linux/fs.h> 9 #include <linux/iomap.h> 9 #include <linux/iomap.h> 10 #include <linux/pagemap.h> 10 #include <linux/pagemap.h> 11 #include <linux/pagevec.h> 11 #include <linux/pagevec.h> 12 12 13 static loff_t iomap_seek_hole_iter(const struc !! 13 static loff_t 14 loff_t *hole_pos) !! 14 iomap_seek_hole_actor(struct inode *inode, loff_t start, loff_t length, >> 15 void *data, struct iomap *iomap, struct iomap *srcmap) 15 { 16 { 16 loff_t length = iomap_length(iter); !! 17 loff_t offset = start; 17 18 18 switch (iter->iomap.type) { !! 19 switch (iomap->type) { 19 case IOMAP_UNWRITTEN: 20 case IOMAP_UNWRITTEN: 20 *hole_pos = mapping_seek_hole_ !! 21 offset = mapping_seek_hole_data(inode->i_mapping, start, 21 iter->pos, ite !! 22 start + length, SEEK_HOLE); 22 if (*hole_pos == iter->pos + l !! 23 if (offset == start + length) 23 return length; 24 return length; 24 return 0; !! 25 fallthrough; 25 case IOMAP_HOLE: 26 case IOMAP_HOLE: 26 *hole_pos = iter->pos; !! 27 *(loff_t *)data = offset; 27 return 0; 28 return 0; 28 default: 29 default: 29 return length; 30 return length; 30 } 31 } 31 } 32 } 32 33 33 loff_t 34 loff_t 34 iomap_seek_hole(struct inode *inode, loff_t po !! 35 iomap_seek_hole(struct inode *inode, loff_t offset, const struct iomap_ops *ops) 35 { 36 { 36 loff_t size = i_size_read(inode); 37 loff_t size = i_size_read(inode); 37 struct iomap_iter iter = { !! 38 loff_t length = size - offset; 38 .inode = inode, !! 39 loff_t ret; 39 .pos = pos, << 40 .flags = IOMAP_REPORT, << 41 }; << 42 int ret; << 43 40 44 /* Nothing to be found before or beyon 41 /* Nothing to be found before or beyond the end of the file. */ 45 if (pos < 0 || pos >= size) !! 42 if (offset < 0 || offset >= size) 46 return -ENXIO; 43 return -ENXIO; 47 44 48 iter.len = size - pos; !! 45 while (length > 0) { 49 while ((ret = iomap_iter(&iter, ops)) !! 46 ret = iomap_apply(inode, offset, length, IOMAP_REPORT, ops, 50 iter.processed = iomap_seek_ho !! 47 &offset, iomap_seek_hole_actor); 51 if (ret < 0) !! 48 if (ret < 0) 52 return ret; !! 49 return ret; 53 if (iter.len) /* found hole before EOF !! 50 if (ret == 0) 54 return pos; !! 51 break; 55 return size; !! 52 >> 53 offset += ret; >> 54 length -= ret; >> 55 } >> 56 >> 57 return offset; 56 } 58 } 57 EXPORT_SYMBOL_GPL(iomap_seek_hole); 59 EXPORT_SYMBOL_GPL(iomap_seek_hole); 58 60 59 static loff_t iomap_seek_data_iter(const struc !! 61 static loff_t 60 loff_t *hole_pos) !! 62 iomap_seek_data_actor(struct inode *inode, loff_t start, loff_t length, >> 63 void *data, struct iomap *iomap, struct iomap *srcmap) 61 { 64 { 62 loff_t length = iomap_length(iter); !! 65 loff_t offset = start; 63 66 64 switch (iter->iomap.type) { !! 67 switch (iomap->type) { 65 case IOMAP_HOLE: 68 case IOMAP_HOLE: 66 return length; 69 return length; 67 case IOMAP_UNWRITTEN: 70 case IOMAP_UNWRITTEN: 68 *hole_pos = mapping_seek_hole_ !! 71 offset = mapping_seek_hole_data(inode->i_mapping, start, 69 iter->pos, ite !! 72 start + length, SEEK_DATA); 70 if (*hole_pos < 0) !! 73 if (offset < 0) 71 return length; 74 return length; 72 return 0; !! 75 fallthrough; 73 default: 76 default: 74 *hole_pos = iter->pos; !! 77 *(loff_t *)data = offset; 75 return 0; 78 return 0; 76 } 79 } 77 } 80 } 78 81 79 loff_t 82 loff_t 80 iomap_seek_data(struct inode *inode, loff_t po !! 83 iomap_seek_data(struct inode *inode, loff_t offset, const struct iomap_ops *ops) 81 { 84 { 82 loff_t size = i_size_read(inode); 85 loff_t size = i_size_read(inode); 83 struct iomap_iter iter = { !! 86 loff_t length = size - offset; 84 .inode = inode, !! 87 loff_t ret; 85 .pos = pos, << 86 .flags = IOMAP_REPORT, << 87 }; << 88 int ret; << 89 88 90 /* Nothing to be found before or beyon 89 /* Nothing to be found before or beyond the end of the file. */ 91 if (pos < 0 || pos >= size) !! 90 if (offset < 0 || offset >= size) 92 return -ENXIO; 91 return -ENXIO; 93 92 94 iter.len = size - pos; !! 93 while (length > 0) { 95 while ((ret = iomap_iter(&iter, ops)) !! 94 ret = iomap_apply(inode, offset, length, IOMAP_REPORT, ops, 96 iter.processed = iomap_seek_da !! 95 &offset, iomap_seek_data_actor); 97 if (ret < 0) !! 96 if (ret < 0) 98 return ret; !! 97 return ret; 99 if (iter.len) /* found data before EOF !! 98 if (ret == 0) 100 return pos; !! 99 break; 101 /* We've reached the end of the file w !! 100 102 return -ENXIO; !! 101 offset += ret; >> 102 length -= ret; >> 103 } >> 104 >> 105 if (length <= 0) >> 106 return -ENXIO; >> 107 return offset; 103 } 108 } 104 EXPORT_SYMBOL_GPL(iomap_seek_data); 109 EXPORT_SYMBOL_GPL(iomap_seek_data); 105 110
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.