]> git.sur5r.net Git - u-boot/blob - fs/btrfs/extent-io.c
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / fs / btrfs / extent-io.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * BTRFS filesystem implementation for U-Boot
4  *
5  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
6  */
7
8 #include "btrfs.h"
9 #include <malloc.h>
10
11 u64 btrfs_read_extent_inline(struct btrfs_path *path,
12                              struct btrfs_file_extent_item *extent, u64 offset,
13                              u64 size, char *out)
14 {
15         u32 clen, dlen, orig_size = size, res;
16         const char *cbuf;
17         char *dbuf;
18         const int data_off = offsetof(struct btrfs_file_extent_item,
19                                       disk_bytenr);
20
21         clen = btrfs_path_item_size(path) - data_off;
22         cbuf = (const char *) extent + data_off;
23         dlen = extent->ram_bytes;
24
25         if (offset > dlen)
26                 return -1ULL;
27
28         if (size > dlen - offset)
29                 size = dlen - offset;
30
31         if (extent->compression == BTRFS_COMPRESS_NONE) {
32                 memcpy(out, cbuf + offset, size);
33                 return size;
34         }
35
36         if (dlen > orig_size) {
37                 dbuf = malloc(dlen);
38                 if (!dbuf)
39                         return -1ULL;
40         } else {
41                 dbuf = out;
42         }
43
44         res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
45         if (res == -1 || res != dlen)
46                 goto err;
47
48         if (dlen > orig_size) {
49                 memcpy(out, dbuf + offset, size);
50                 free(dbuf);
51         } else if (offset) {
52                 memmove(out, dbuf + offset, size);
53         }
54
55         return size;
56
57 err:
58         if (dlen > orig_size)
59                 free(dbuf);
60         return -1ULL;
61 }
62
63 u64 btrfs_read_extent_reg(struct btrfs_path *path,
64                           struct btrfs_file_extent_item *extent, u64 offset,
65                           u64 size, char *out)
66 {
67         u64 physical, clen, dlen, orig_size = size;
68         u32 res;
69         char *cbuf, *dbuf;
70
71         clen = extent->disk_num_bytes;
72         dlen = extent->num_bytes;
73
74         if (offset > dlen)
75                 return -1ULL;
76
77         if (size > dlen - offset)
78                 size = dlen - offset;
79
80         physical = btrfs_map_logical_to_physical(extent->disk_bytenr);
81         if (physical == -1ULL)
82                 return -1ULL;
83
84         if (extent->compression == BTRFS_COMPRESS_NONE) {
85                 physical += extent->offset + offset;
86                 if (!btrfs_devread(physical, size, out))
87                         return -1ULL;
88
89                 return size;
90         }
91
92         cbuf = malloc(dlen > size ? clen + dlen : clen);
93         if (!cbuf)
94                 return -1ULL;
95
96         if (dlen > orig_size)
97                 dbuf = cbuf + clen;
98         else
99                 dbuf = out;
100
101         if (!btrfs_devread(physical, clen, cbuf))
102                 goto err;
103
104         res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
105         if (res == -1)
106                 goto err;
107
108         if (dlen > orig_size)
109                 memcpy(out, dbuf + offset, size);
110         else
111                 memmove(out, dbuf + offset, size);
112
113         free(cbuf);
114         return res;
115
116 err:
117         free(cbuf);
118         return -1ULL;
119 }