Commit 7892386d authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong
Browse files

iomap: switch iomap_fiemap to use iomap_iter



Rewrite the ->fiemap implementation based on iomap_iter.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent a6d3d495
Loading
Loading
Loading
Loading
+29 −41
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2016-2018 Christoph Hellwig.
 * Copyright (c) 2016-2021 Christoph Hellwig.
 */
#include <linux/module.h>
#include <linux/compiler.h>
@@ -8,13 +8,8 @@
#include <linux/iomap.h>
#include <linux/fiemap.h>

struct fiemap_ctx {
	struct fiemap_extent_info *fi;
	struct iomap prev;
};

static int iomap_to_fiemap(struct fiemap_extent_info *fi,
		struct iomap *iomap, u32 flags)
		const struct iomap *iomap, u32 flags)
{
	switch (iomap->type) {
	case IOMAP_HOLE:
@@ -43,24 +38,22 @@ static int iomap_to_fiemap(struct fiemap_extent_info *fi,
			iomap->length, flags);
}

static loff_t
iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
		struct iomap *iomap, struct iomap *srcmap)
static loff_t iomap_fiemap_iter(const struct iomap_iter *iter,
		struct fiemap_extent_info *fi, struct iomap *prev)
{
	struct fiemap_ctx *ctx = data;
	loff_t ret = length;
	int ret;

	if (iomap->type == IOMAP_HOLE)
		return length;
	if (iter->iomap.type == IOMAP_HOLE)
		return iomap_length(iter);

	ret = iomap_to_fiemap(ctx->fi, &ctx->prev, 0);
	ctx->prev = *iomap;
	ret = iomap_to_fiemap(fi, prev, 0);
	*prev = iter->iomap;
	switch (ret) {
	case 0:		/* success */
		return length;
		return iomap_length(iter);
	case 1:		/* extent array full */
		return 0;
	default:
	default:	/* error */
		return ret;
	}
}
@@ -68,38 +61,33 @@ iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
		u64 start, u64 len, const struct iomap_ops *ops)
{
	struct fiemap_ctx ctx;
	loff_t ret;

	memset(&ctx, 0, sizeof(ctx));
	ctx.fi = fi;
	ctx.prev.type = IOMAP_HOLE;
	struct iomap_iter iter = {
		.inode		= inode,
		.pos		= start,
		.len		= len,
		.flags		= IOMAP_REPORT,
	};
	struct iomap prev = {
		.type		= IOMAP_HOLE,
	};
	int ret;

	ret = fiemap_prep(inode, fi, start, &len, 0);
	ret = fiemap_prep(inode, fi, start, &iter.len, 0);
	if (ret)
		return ret;

	while (len > 0) {
		ret = iomap_apply(inode, start, len, IOMAP_REPORT, ops, &ctx,
				iomap_fiemap_actor);
		/* inode with no (attribute) mapping will give ENOENT */
		if (ret == -ENOENT)
			break;
		if (ret < 0)
			return ret;
		if (ret == 0)
			break;
	while ((ret = iomap_iter(&iter, ops)) > 0)
		iter.processed = iomap_fiemap_iter(&iter, fi, &prev);

		start += ret;
		len -= ret;
	}

	if (ctx.prev.type != IOMAP_HOLE) {
		ret = iomap_to_fiemap(fi, &ctx.prev, FIEMAP_EXTENT_LAST);
	if (prev.type != IOMAP_HOLE) {
		ret = iomap_to_fiemap(fi, &prev, FIEMAP_EXTENT_LAST);
		if (ret < 0)
			return ret;
	}

	/* inode with no (attribute) mapping will give ENOENT */
	if (ret < 0 && ret != -ENOENT)
		return ret;
	return 0;
}
EXPORT_SYMBOL_GPL(iomap_fiemap);