summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-io.c
diff options
context:
space:
mode:
authorMarek BehĂșn <marek.behun@nic.cz>2017-09-03 17:00:28 +0200
committerTom Rini <trini@konsulko.com>2017-10-02 21:52:17 -0400
commit21a14facb1494592c3ad4874c6a00539d15a29cf (patch)
tree96b0f5d1bfcbddff721717c6609ec401bd594ccf /fs/btrfs/extent-io.c
parent597b4aff7b5d85946d2028ab9498116f53357dbc (diff)
downloadu-boot-21a14facb1494592c3ad4874c6a00539d15a29cf.tar.gz
u-boot-21a14facb1494592c3ad4874c6a00539d15a29cf.tar.xz
u-boot-21a14facb1494592c3ad4874c6a00539d15a29cf.zip
fs: btrfs: Add single-device read-only BTRFS implementation
This adds the proper implementation for the BTRFS filesystem. The implementation currently supports only read-only mode and the filesystem can be only on a single device. Checksums of data chunks is unimplemented. Compression is implemented (ZLIB + LZO). Signed-off-by: Marek Behun <marek.behun@nic.cz> create mode 100644 fs/btrfs/btrfs.h create mode 100644 fs/btrfs/chunk-map.c create mode 100644 fs/btrfs/compression.c create mode 100644 fs/btrfs/ctree.c create mode 100644 fs/btrfs/dev.c create mode 100644 fs/btrfs/dir-item.c create mode 100644 fs/btrfs/extent-io.c create mode 100644 fs/btrfs/hash.c create mode 100644 fs/btrfs/inode.c create mode 100644 fs/btrfs/root.c create mode 100644 fs/btrfs/subvolume.c create mode 100644 fs/btrfs/super.c
Diffstat (limited to 'fs/btrfs/extent-io.c')
-rw-r--r--fs/btrfs/extent-io.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/fs/btrfs/extent-io.c b/fs/btrfs/extent-io.c
new file mode 100644
index 0000000000..feb91432e9
--- /dev/null
+++ b/fs/btrfs/extent-io.c
@@ -0,0 +1,120 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <malloc.h>
+
+u64 btrfs_read_extent_inline(struct btrfs_path *path,
+ struct btrfs_file_extent_item *extent, u64 offset,
+ u64 size, char *out)
+{
+ u32 clen, dlen, orig_size = size, res;
+ const char *cbuf;
+ char *dbuf;
+ const int data_off = offsetof(struct btrfs_file_extent_item,
+ disk_bytenr);
+
+ clen = btrfs_path_item_size(path) - data_off;
+ cbuf = (const char *) extent + data_off;
+ dlen = extent->ram_bytes;
+
+ if (offset > dlen)
+ return -1ULL;
+
+ if (size > dlen - offset)
+ size = dlen - offset;
+
+ if (extent->compression == BTRFS_COMPRESS_NONE) {
+ memcpy(out, cbuf + offset, size);
+ return size;
+ }
+
+ if (dlen > orig_size) {
+ dbuf = malloc(dlen);
+ if (!dbuf)
+ return -1ULL;
+ } else {
+ dbuf = out;
+ }
+
+ res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
+ if (res == -1 || res != dlen)
+ goto err;
+
+ if (dlen > orig_size) {
+ memcpy(out, dbuf + offset, size);
+ free(dbuf);
+ } else if (offset) {
+ memmove(out, dbuf + offset, size);
+ }
+
+ return size;
+
+err:
+ if (dlen > orig_size)
+ free(dbuf);
+ return -1ULL;
+}
+
+u64 btrfs_read_extent_reg(struct btrfs_path *path,
+ struct btrfs_file_extent_item *extent, u64 offset,
+ u64 size, char *out)
+{
+ u64 physical, clen, dlen, orig_size = size;
+ u32 res;
+ char *cbuf, *dbuf;
+
+ clen = extent->disk_num_bytes;
+ dlen = extent->num_bytes;
+
+ if (offset > dlen)
+ return -1ULL;
+
+ if (size > dlen - offset)
+ size = dlen - offset;
+
+ physical = btrfs_map_logical_to_physical(extent->disk_bytenr);
+ if (physical == -1ULL)
+ return -1ULL;
+
+ if (extent->compression == BTRFS_COMPRESS_NONE) {
+ physical += extent->offset + offset;
+ if (!btrfs_devread(physical, size, out))
+ return -1ULL;
+
+ return size;
+ }
+
+ cbuf = malloc(dlen > size ? clen + dlen : clen);
+ if (!cbuf)
+ return -1ULL;
+
+ if (dlen > orig_size)
+ dbuf = cbuf + clen;
+ else
+ dbuf = out;
+
+ if (!btrfs_devread(physical, clen, cbuf))
+ goto err;
+
+ res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
+ if (res == -1)
+ goto err;
+
+ if (dlen > orig_size)
+ memcpy(out, dbuf + offset, size);
+ else
+ memmove(out, dbuf + offset, size);
+
+ free(cbuf);
+ return res;
+
+err:
+ free(cbuf);
+ return -1ULL;
+}