xref: /openbmc/u-boot/fs/btrfs/extent-io.c (revision 592cd5de)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
221a14facSMarek Behún /*
321a14facSMarek Behún  * BTRFS filesystem implementation for U-Boot
421a14facSMarek Behún  *
521a14facSMarek Behún  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
621a14facSMarek Behún  */
721a14facSMarek Behún 
821a14facSMarek Behún #include "btrfs.h"
921a14facSMarek Behún #include <malloc.h>
10*c9795396SMarek Vasut #include <memalign.h>
1121a14facSMarek Behún 
btrfs_read_extent_inline(struct btrfs_path * path,struct btrfs_file_extent_item * extent,u64 offset,u64 size,char * out)1221a14facSMarek Behún u64 btrfs_read_extent_inline(struct btrfs_path *path,
1321a14facSMarek Behún 			     struct btrfs_file_extent_item *extent, u64 offset,
1421a14facSMarek Behún 			     u64 size, char *out)
1521a14facSMarek Behún {
1621a14facSMarek Behún 	u32 clen, dlen, orig_size = size, res;
1721a14facSMarek Behún 	const char *cbuf;
1821a14facSMarek Behún 	char *dbuf;
1921a14facSMarek Behún 	const int data_off = offsetof(struct btrfs_file_extent_item,
2021a14facSMarek Behún 				      disk_bytenr);
2121a14facSMarek Behún 
2221a14facSMarek Behún 	clen = btrfs_path_item_size(path) - data_off;
2321a14facSMarek Behún 	cbuf = (const char *) extent + data_off;
2421a14facSMarek Behún 	dlen = extent->ram_bytes;
2521a14facSMarek Behún 
2621a14facSMarek Behún 	if (offset > dlen)
2721a14facSMarek Behún 		return -1ULL;
2821a14facSMarek Behún 
2921a14facSMarek Behún 	if (size > dlen - offset)
3021a14facSMarek Behún 		size = dlen - offset;
3121a14facSMarek Behún 
3221a14facSMarek Behún 	if (extent->compression == BTRFS_COMPRESS_NONE) {
3321a14facSMarek Behún 		memcpy(out, cbuf + offset, size);
3421a14facSMarek Behún 		return size;
3521a14facSMarek Behún 	}
3621a14facSMarek Behún 
3721a14facSMarek Behún 	if (dlen > orig_size) {
3821a14facSMarek Behún 		dbuf = malloc(dlen);
3921a14facSMarek Behún 		if (!dbuf)
4021a14facSMarek Behún 			return -1ULL;
4121a14facSMarek Behún 	} else {
4221a14facSMarek Behún 		dbuf = out;
4321a14facSMarek Behún 	}
4421a14facSMarek Behún 
4521a14facSMarek Behún 	res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
4621a14facSMarek Behún 	if (res == -1 || res != dlen)
4721a14facSMarek Behún 		goto err;
4821a14facSMarek Behún 
4921a14facSMarek Behún 	if (dlen > orig_size) {
5021a14facSMarek Behún 		memcpy(out, dbuf + offset, size);
5121a14facSMarek Behún 		free(dbuf);
5221a14facSMarek Behún 	} else if (offset) {
5321a14facSMarek Behún 		memmove(out, dbuf + offset, size);
5421a14facSMarek Behún 	}
5521a14facSMarek Behún 
5621a14facSMarek Behún 	return size;
5721a14facSMarek Behún 
5821a14facSMarek Behún err:
5921a14facSMarek Behún 	if (dlen > orig_size)
6021a14facSMarek Behún 		free(dbuf);
6121a14facSMarek Behún 	return -1ULL;
6221a14facSMarek Behún }
6321a14facSMarek Behún 
btrfs_read_extent_reg(struct btrfs_path * path,struct btrfs_file_extent_item * extent,u64 offset,u64 size,char * out)6421a14facSMarek Behún u64 btrfs_read_extent_reg(struct btrfs_path *path,
6521a14facSMarek Behún 			  struct btrfs_file_extent_item *extent, u64 offset,
6621a14facSMarek Behún 			  u64 size, char *out)
6721a14facSMarek Behún {
6821a14facSMarek Behún 	u64 physical, clen, dlen, orig_size = size;
6921a14facSMarek Behún 	u32 res;
7021a14facSMarek Behún 	char *cbuf, *dbuf;
7121a14facSMarek Behún 
7221a14facSMarek Behún 	clen = extent->disk_num_bytes;
7321a14facSMarek Behún 	dlen = extent->num_bytes;
7421a14facSMarek Behún 
7521a14facSMarek Behún 	if (offset > dlen)
7621a14facSMarek Behún 		return -1ULL;
7721a14facSMarek Behún 
7821a14facSMarek Behún 	if (size > dlen - offset)
7921a14facSMarek Behún 		size = dlen - offset;
8021a14facSMarek Behún 
8121a14facSMarek Behún 	physical = btrfs_map_logical_to_physical(extent->disk_bytenr);
8221a14facSMarek Behún 	if (physical == -1ULL)
8321a14facSMarek Behún 		return -1ULL;
8421a14facSMarek Behún 
8521a14facSMarek Behún 	if (extent->compression == BTRFS_COMPRESS_NONE) {
8621a14facSMarek Behún 		physical += extent->offset + offset;
8721a14facSMarek Behún 		if (!btrfs_devread(physical, size, out))
8821a14facSMarek Behún 			return -1ULL;
8921a14facSMarek Behún 
9021a14facSMarek Behún 		return size;
9121a14facSMarek Behún 	}
9221a14facSMarek Behún 
93*c9795396SMarek Vasut 	cbuf = malloc_cache_aligned(dlen > size ? clen + dlen : clen);
9421a14facSMarek Behún 	if (!cbuf)
9521a14facSMarek Behún 		return -1ULL;
9621a14facSMarek Behún 
9721a14facSMarek Behún 	if (dlen > orig_size)
9821a14facSMarek Behún 		dbuf = cbuf + clen;
9921a14facSMarek Behún 	else
10021a14facSMarek Behún 		dbuf = out;
10121a14facSMarek Behún 
10221a14facSMarek Behún 	if (!btrfs_devread(physical, clen, cbuf))
10321a14facSMarek Behún 		goto err;
10421a14facSMarek Behún 
10521a14facSMarek Behún 	res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
10621a14facSMarek Behún 	if (res == -1)
10721a14facSMarek Behún 		goto err;
10821a14facSMarek Behún 
10921a14facSMarek Behún 	if (dlen > orig_size)
11021a14facSMarek Behún 		memcpy(out, dbuf + offset, size);
11121a14facSMarek Behún 	else
11221a14facSMarek Behún 		memmove(out, dbuf + offset, size);
11321a14facSMarek Behún 
11421a14facSMarek Behún 	free(cbuf);
11521a14facSMarek Behún 	return res;
11621a14facSMarek Behún 
11721a14facSMarek Behún err:
11821a14facSMarek Behún 	free(cbuf);
11921a14facSMarek Behún 	return -1ULL;
12021a14facSMarek Behún }
121