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-2021 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 iomap_seek_hole_iter(const struct iomap_iter *iter, 14 loff_t *hole_pos) 14 loff_t *hole_pos) 15 { 15 { 16 loff_t length = iomap_length(iter); 16 loff_t length = iomap_length(iter); 17 17 18 switch (iter->iomap.type) { 18 switch (iter->iomap.type) { 19 case IOMAP_UNWRITTEN: 19 case IOMAP_UNWRITTEN: 20 *hole_pos = mapping_seek_hole_ 20 *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping, 21 iter->pos, ite 21 iter->pos, iter->pos + length, SEEK_HOLE); 22 if (*hole_pos == iter->pos + l 22 if (*hole_pos == iter->pos + length) 23 return length; 23 return length; 24 return 0; 24 return 0; 25 case IOMAP_HOLE: 25 case IOMAP_HOLE: 26 *hole_pos = iter->pos; 26 *hole_pos = iter->pos; 27 return 0; 27 return 0; 28 default: 28 default: 29 return length; 29 return length; 30 } 30 } 31 } 31 } 32 32 33 loff_t 33 loff_t 34 iomap_seek_hole(struct inode *inode, loff_t po 34 iomap_seek_hole(struct inode *inode, loff_t pos, const struct iomap_ops *ops) 35 { 35 { 36 loff_t size = i_size_read(inode); 36 loff_t size = i_size_read(inode); 37 struct iomap_iter iter = { 37 struct iomap_iter iter = { 38 .inode = inode, 38 .inode = inode, 39 .pos = pos, 39 .pos = pos, 40 .flags = IOMAP_REPORT, 40 .flags = IOMAP_REPORT, 41 }; 41 }; 42 int ret; 42 int ret; 43 43 44 /* Nothing to be found before or beyon 44 /* Nothing to be found before or beyond the end of the file. */ 45 if (pos < 0 || pos >= size) 45 if (pos < 0 || pos >= size) 46 return -ENXIO; 46 return -ENXIO; 47 47 48 iter.len = size - pos; 48 iter.len = size - pos; 49 while ((ret = iomap_iter(&iter, ops)) 49 while ((ret = iomap_iter(&iter, ops)) > 0) 50 iter.processed = iomap_seek_ho 50 iter.processed = iomap_seek_hole_iter(&iter, &pos); 51 if (ret < 0) 51 if (ret < 0) 52 return ret; 52 return ret; 53 if (iter.len) /* found hole before EOF 53 if (iter.len) /* found hole before EOF */ 54 return pos; 54 return pos; 55 return size; 55 return size; 56 } 56 } 57 EXPORT_SYMBOL_GPL(iomap_seek_hole); 57 EXPORT_SYMBOL_GPL(iomap_seek_hole); 58 58 59 static loff_t iomap_seek_data_iter(const struc 59 static loff_t iomap_seek_data_iter(const struct iomap_iter *iter, 60 loff_t *hole_pos) 60 loff_t *hole_pos) 61 { 61 { 62 loff_t length = iomap_length(iter); 62 loff_t length = iomap_length(iter); 63 63 64 switch (iter->iomap.type) { 64 switch (iter->iomap.type) { 65 case IOMAP_HOLE: 65 case IOMAP_HOLE: 66 return length; 66 return length; 67 case IOMAP_UNWRITTEN: 67 case IOMAP_UNWRITTEN: 68 *hole_pos = mapping_seek_hole_ 68 *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping, 69 iter->pos, ite 69 iter->pos, iter->pos + length, SEEK_DATA); 70 if (*hole_pos < 0) 70 if (*hole_pos < 0) 71 return length; 71 return length; 72 return 0; 72 return 0; 73 default: 73 default: 74 *hole_pos = iter->pos; 74 *hole_pos = iter->pos; 75 return 0; 75 return 0; 76 } 76 } 77 } 77 } 78 78 79 loff_t 79 loff_t 80 iomap_seek_data(struct inode *inode, loff_t po 80 iomap_seek_data(struct inode *inode, loff_t pos, const struct iomap_ops *ops) 81 { 81 { 82 loff_t size = i_size_read(inode); 82 loff_t size = i_size_read(inode); 83 struct iomap_iter iter = { 83 struct iomap_iter iter = { 84 .inode = inode, 84 .inode = inode, 85 .pos = pos, 85 .pos = pos, 86 .flags = IOMAP_REPORT, 86 .flags = IOMAP_REPORT, 87 }; 87 }; 88 int ret; 88 int ret; 89 89 90 /* Nothing to be found before or beyon 90 /* Nothing to be found before or beyond the end of the file. */ 91 if (pos < 0 || pos >= size) 91 if (pos < 0 || pos >= size) 92 return -ENXIO; 92 return -ENXIO; 93 93 94 iter.len = size - pos; 94 iter.len = size - pos; 95 while ((ret = iomap_iter(&iter, ops)) 95 while ((ret = iomap_iter(&iter, ops)) > 0) 96 iter.processed = iomap_seek_da 96 iter.processed = iomap_seek_data_iter(&iter, &pos); 97 if (ret < 0) 97 if (ret < 0) 98 return ret; 98 return ret; 99 if (iter.len) /* found data before EOF 99 if (iter.len) /* found data before EOF */ 100 return pos; 100 return pos; 101 /* We've reached the end of the file w 101 /* We've reached the end of the file without finding data */ 102 return -ENXIO; 102 return -ENXIO; 103 } 103 } 104 EXPORT_SYMBOL_GPL(iomap_seek_data); 104 EXPORT_SYMBOL_GPL(iomap_seek_data); 105 105
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.