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