Linux Audio

Check our new training course

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