Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2017 Red Hat, Inc.
0004  * Copyright (c) 2018-2021 Christoph Hellwig.
0005  */
0006 #include <linux/module.h>
0007 #include <linux/compiler.h>
0008 #include <linux/fs.h>
0009 #include <linux/iomap.h>
0010 #include <linux/pagemap.h>
0011 #include <linux/pagevec.h>
0012 
0013 static loff_t iomap_seek_hole_iter(const struct iomap_iter *iter,
0014         loff_t *hole_pos)
0015 {
0016     loff_t length = iomap_length(iter);
0017 
0018     switch (iter->iomap.type) {
0019     case IOMAP_UNWRITTEN:
0020         *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping,
0021                 iter->pos, iter->pos + length, SEEK_HOLE);
0022         if (*hole_pos == iter->pos + length)
0023             return length;
0024         return 0;
0025     case IOMAP_HOLE:
0026         *hole_pos = iter->pos;
0027         return 0;
0028     default:
0029         return length;
0030     }
0031 }
0032 
0033 loff_t
0034 iomap_seek_hole(struct inode *inode, loff_t pos, const struct iomap_ops *ops)
0035 {
0036     loff_t size = i_size_read(inode);
0037     struct iomap_iter iter = {
0038         .inode  = inode,
0039         .pos    = pos,
0040         .flags  = IOMAP_REPORT,
0041     };
0042     int ret;
0043 
0044     /* Nothing to be found before or beyond the end of the file. */
0045     if (pos < 0 || pos >= size)
0046         return -ENXIO;
0047 
0048     iter.len = size - pos;
0049     while ((ret = iomap_iter(&iter, ops)) > 0)
0050         iter.processed = iomap_seek_hole_iter(&iter, &pos);
0051     if (ret < 0)
0052         return ret;
0053     if (iter.len) /* found hole before EOF */
0054         return pos;
0055     return size;
0056 }
0057 EXPORT_SYMBOL_GPL(iomap_seek_hole);
0058 
0059 static loff_t iomap_seek_data_iter(const struct iomap_iter *iter,
0060         loff_t *hole_pos)
0061 {
0062     loff_t length = iomap_length(iter);
0063 
0064     switch (iter->iomap.type) {
0065     case IOMAP_HOLE:
0066         return length;
0067     case IOMAP_UNWRITTEN:
0068         *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping,
0069                 iter->pos, iter->pos + length, SEEK_DATA);
0070         if (*hole_pos < 0)
0071             return length;
0072         return 0;
0073     default:
0074         *hole_pos = iter->pos;
0075         return 0;
0076     }
0077 }
0078 
0079 loff_t
0080 iomap_seek_data(struct inode *inode, loff_t pos, const struct iomap_ops *ops)
0081 {
0082     loff_t size = i_size_read(inode);
0083     struct iomap_iter iter = {
0084         .inode  = inode,
0085         .pos    = pos,
0086         .flags  = IOMAP_REPORT,
0087     };
0088     int ret;
0089 
0090     /* Nothing to be found before or beyond the end of the file. */
0091     if (pos < 0 || pos >= size)
0092         return -ENXIO;
0093 
0094     iter.len = size - pos;
0095     while ((ret = iomap_iter(&iter, ops)) > 0)
0096         iter.processed = iomap_seek_data_iter(&iter, &pos);
0097     if (ret < 0)
0098         return ret;
0099     if (iter.len) /* found data before EOF */
0100         return pos;
0101     /* We've reached the end of the file without finding data */
0102     return -ENXIO;
0103 }
0104 EXPORT_SYMBOL_GPL(iomap_seek_data);