Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2016-2021 Christoph Hellwig.
  4 */
  5#include <linux/module.h>
  6#include <linux/compiler.h>
  7#include <linux/fs.h>
  8#include <linux/iomap.h>
  9#include <linux/fiemap.h>
 10#include <linux/pagemap.h>
 
 
 
 
 11
 12static int iomap_to_fiemap(struct fiemap_extent_info *fi,
 13		const struct iomap *iomap, u32 flags)
 14{
 15	switch (iomap->type) {
 16	case IOMAP_HOLE:
 17		/* skip holes */
 18		return 0;
 19	case IOMAP_DELALLOC:
 20		flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN;
 21		break;
 22	case IOMAP_MAPPED:
 23		break;
 24	case IOMAP_UNWRITTEN:
 25		flags |= FIEMAP_EXTENT_UNWRITTEN;
 26		break;
 27	case IOMAP_INLINE:
 28		flags |= FIEMAP_EXTENT_DATA_INLINE;
 29		break;
 30	}
 31
 32	if (iomap->flags & IOMAP_F_MERGED)
 33		flags |= FIEMAP_EXTENT_MERGED;
 34	if (iomap->flags & IOMAP_F_SHARED)
 35		flags |= FIEMAP_EXTENT_SHARED;
 36
 37	return fiemap_fill_next_extent(fi, iomap->offset,
 38			iomap->addr != IOMAP_NULL_ADDR ? iomap->addr : 0,
 39			iomap->length, flags);
 40}
 41
 42static loff_t iomap_fiemap_iter(const struct iomap_iter *iter,
 43		struct fiemap_extent_info *fi, struct iomap *prev)
 
 44{
 45	int ret;
 
 46
 47	if (iter->iomap.type == IOMAP_HOLE)
 48		return iomap_length(iter);
 49
 50	ret = iomap_to_fiemap(fi, prev, 0);
 51	*prev = iter->iomap;
 52	switch (ret) {
 53	case 0:		/* success */
 54		return iomap_length(iter);
 55	case 1:		/* extent array full */
 56		return 0;
 57	default:	/* error */
 58		return ret;
 59	}
 60}
 61
 62int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
 63		u64 start, u64 len, const struct iomap_ops *ops)
 64{
 65	struct iomap_iter iter = {
 66		.inode		= inode,
 67		.pos		= start,
 68		.len		= len,
 69		.flags		= IOMAP_REPORT,
 70	};
 71	struct iomap prev = {
 72		.type		= IOMAP_HOLE,
 73	};
 74	int ret;
 75
 76	ret = fiemap_prep(inode, fi, start, &iter.len, 0);
 
 
 
 
 77	if (ret)
 78		return ret;
 79
 80	while ((ret = iomap_iter(&iter, ops)) > 0)
 81		iter.processed = iomap_fiemap_iter(&iter, fi, &prev);
 
 
 
 
 
 
 
 
 
 
 
 
 82
 83	if (prev.type != IOMAP_HOLE) {
 84		ret = iomap_to_fiemap(fi, &prev, FIEMAP_EXTENT_LAST);
 85		if (ret < 0)
 86			return ret;
 87	}
 88
 89	/* inode with no (attribute) mapping will give ENOENT */
 90	if (ret < 0 && ret != -ENOENT)
 91		return ret;
 92	return 0;
 93}
 94EXPORT_SYMBOL_GPL(iomap_fiemap);
 95
 
 
 
 
 
 
 
 
 
 
 
 
 
 96/* legacy ->bmap interface.  0 is the error return (!) */
 97sector_t
 98iomap_bmap(struct address_space *mapping, sector_t bno,
 99		const struct iomap_ops *ops)
100{
101	struct iomap_iter iter = {
102		.inode	= mapping->host,
103		.pos	= (loff_t)bno << mapping->host->i_blkbits,
104		.len	= i_blocksize(mapping->host),
105		.flags	= IOMAP_REPORT,
106	};
107	const unsigned int blkshift = mapping->host->i_blkbits - SECTOR_SHIFT;
108	int ret;
109
110	if (filemap_write_and_wait(mapping))
111		return 0;
112
113	bno = 0;
114	while ((ret = iomap_iter(&iter, ops)) > 0) {
115		if (iter.iomap.type == IOMAP_MAPPED)
116			bno = iomap_sector(&iter.iomap, iter.pos) >> blkshift;
117		/* leave iter.processed unset to abort loop */
118	}
119	if (ret)
120		return 0;
121
122	return bno;
123}
124EXPORT_SYMBOL_GPL(iomap_bmap);
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2016-2018 Christoph Hellwig.
  4 */
  5#include <linux/module.h>
  6#include <linux/compiler.h>
  7#include <linux/fs.h>
  8#include <linux/iomap.h>
  9#include <linux/fiemap.h>
 10
 11struct fiemap_ctx {
 12	struct fiemap_extent_info *fi;
 13	struct iomap prev;
 14};
 15
 16static int iomap_to_fiemap(struct fiemap_extent_info *fi,
 17		struct iomap *iomap, u32 flags)
 18{
 19	switch (iomap->type) {
 20	case IOMAP_HOLE:
 21		/* skip holes */
 22		return 0;
 23	case IOMAP_DELALLOC:
 24		flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN;
 25		break;
 26	case IOMAP_MAPPED:
 27		break;
 28	case IOMAP_UNWRITTEN:
 29		flags |= FIEMAP_EXTENT_UNWRITTEN;
 30		break;
 31	case IOMAP_INLINE:
 32		flags |= FIEMAP_EXTENT_DATA_INLINE;
 33		break;
 34	}
 35
 36	if (iomap->flags & IOMAP_F_MERGED)
 37		flags |= FIEMAP_EXTENT_MERGED;
 38	if (iomap->flags & IOMAP_F_SHARED)
 39		flags |= FIEMAP_EXTENT_SHARED;
 40
 41	return fiemap_fill_next_extent(fi, iomap->offset,
 42			iomap->addr != IOMAP_NULL_ADDR ? iomap->addr : 0,
 43			iomap->length, flags);
 44}
 45
 46static loff_t
 47iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 48		struct iomap *iomap, struct iomap *srcmap)
 49{
 50	struct fiemap_ctx *ctx = data;
 51	loff_t ret = length;
 52
 53	if (iomap->type == IOMAP_HOLE)
 54		return length;
 55
 56	ret = iomap_to_fiemap(ctx->fi, &ctx->prev, 0);
 57	ctx->prev = *iomap;
 58	switch (ret) {
 59	case 0:		/* success */
 60		return length;
 61	case 1:		/* extent array full */
 62		return 0;
 63	default:
 64		return ret;
 65	}
 66}
 67
 68int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
 69		u64 start, u64 len, const struct iomap_ops *ops)
 70{
 71	struct fiemap_ctx ctx;
 72	loff_t ret;
 
 
 
 
 
 
 
 
 73
 74	memset(&ctx, 0, sizeof(ctx));
 75	ctx.fi = fi;
 76	ctx.prev.type = IOMAP_HOLE;
 77
 78	ret = fiemap_prep(inode, fi, start, &len, 0);
 79	if (ret)
 80		return ret;
 81
 82	while (len > 0) {
 83		ret = iomap_apply(inode, start, len, IOMAP_REPORT, ops, &ctx,
 84				iomap_fiemap_actor);
 85		/* inode with no (attribute) mapping will give ENOENT */
 86		if (ret == -ENOENT)
 87			break;
 88		if (ret < 0)
 89			return ret;
 90		if (ret == 0)
 91			break;
 92
 93		start += ret;
 94		len -= ret;
 95	}
 96
 97	if (ctx.prev.type != IOMAP_HOLE) {
 98		ret = iomap_to_fiemap(fi, &ctx.prev, FIEMAP_EXTENT_LAST);
 99		if (ret < 0)
100			return ret;
101	}
102
 
 
 
103	return 0;
104}
105EXPORT_SYMBOL_GPL(iomap_fiemap);
106
107static loff_t
108iomap_bmap_actor(struct inode *inode, loff_t pos, loff_t length,
109		void *data, struct iomap *iomap, struct iomap *srcmap)
110{
111	sector_t *bno = data, addr;
112
113	if (iomap->type == IOMAP_MAPPED) {
114		addr = (pos - iomap->offset + iomap->addr) >> inode->i_blkbits;
115		*bno = addr;
116	}
117	return 0;
118}
119
120/* legacy ->bmap interface.  0 is the error return (!) */
121sector_t
122iomap_bmap(struct address_space *mapping, sector_t bno,
123		const struct iomap_ops *ops)
124{
125	struct inode *inode = mapping->host;
126	loff_t pos = bno << inode->i_blkbits;
127	unsigned blocksize = i_blocksize(inode);
 
 
 
 
128	int ret;
129
130	if (filemap_write_and_wait(mapping))
131		return 0;
132
133	bno = 0;
134	ret = iomap_apply(inode, pos, blocksize, 0, ops, &bno,
135			  iomap_bmap_actor);
 
 
 
136	if (ret)
137		return 0;
 
138	return bno;
139}
140EXPORT_SYMBOL_GPL(iomap_bmap);