mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-23 20:24:26 +08:00
fs: btrfs: Add U-Boot fs handlers.
Signed-off-by: Marek Behun <marek.behun@nic.cz> create mode 100644 fs/btrfs/Kconfig create mode 100644 fs/btrfs/Makefile create mode 100644 fs/btrfs/btrfs.c create mode 100644 include/btrfs.h
This commit is contained in:
parent
21a14facb1
commit
0c936ee319
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
menu "File systems"
|
menu "File systems"
|
||||||
|
|
||||||
|
source "fs/btrfs/Kconfig"
|
||||||
|
|
||||||
source "fs/cbfs/Kconfig"
|
source "fs/cbfs/Kconfig"
|
||||||
|
|
||||||
source "fs/ext4/Kconfig"
|
source "fs/ext4/Kconfig"
|
||||||
|
@ -12,6 +12,7 @@ obj-$(CONFIG_SPL_EXT_SUPPORT) += ext4/
|
|||||||
else
|
else
|
||||||
obj-y += fs.o
|
obj-y += fs.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_FS_BTRFS) += btrfs/
|
||||||
obj-$(CONFIG_FS_CBFS) += cbfs/
|
obj-$(CONFIG_FS_CBFS) += cbfs/
|
||||||
obj-$(CONFIG_CMD_CRAMFS) += cramfs/
|
obj-$(CONFIG_CMD_CRAMFS) += cramfs/
|
||||||
obj-$(CONFIG_FS_EXT4) += ext4/
|
obj-$(CONFIG_FS_EXT4) += ext4/
|
||||||
|
9
fs/btrfs/Kconfig
Normal file
9
fs/btrfs/Kconfig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
config FS_BTRFS
|
||||||
|
bool "Enable BTRFS filesystem support"
|
||||||
|
select CRC32C
|
||||||
|
select LZO
|
||||||
|
select RBTREE
|
||||||
|
help
|
||||||
|
This provides a single-device read-only BTRFS support. BTRFS is a
|
||||||
|
next-generation Linux file system based on the copy-on-write
|
||||||
|
principle.
|
8
fs/btrfs/Makefile
Normal file
8
fs/btrfs/Makefile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
# 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-y := btrfs.o chunk-map.o compression.o ctree.o dev.o dir-item.o \
|
||||||
|
extent-io.o hash.o inode.o root.o subvolume.o super.o
|
227
fs/btrfs/btrfs.c
Normal file
227
fs/btrfs/btrfs.c
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* 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 <config.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
|
||||||
|
struct btrfs_info btrfs_info;
|
||||||
|
|
||||||
|
static int readdir_callback(const struct btrfs_root *root,
|
||||||
|
struct btrfs_dir_item *item)
|
||||||
|
{
|
||||||
|
static const char typestr[BTRFS_FT_MAX][4] = {
|
||||||
|
[BTRFS_FT_UNKNOWN] = " ? ",
|
||||||
|
[BTRFS_FT_REG_FILE] = " ",
|
||||||
|
[BTRFS_FT_DIR] = "DIR",
|
||||||
|
[BTRFS_FT_CHRDEV] = "CHR",
|
||||||
|
[BTRFS_FT_BLKDEV] = "BLK",
|
||||||
|
[BTRFS_FT_FIFO] = "FIF",
|
||||||
|
[BTRFS_FT_SOCK] = "SCK",
|
||||||
|
[BTRFS_FT_SYMLINK] = "SYM",
|
||||||
|
[BTRFS_FT_XATTR] = " ? ",
|
||||||
|
};
|
||||||
|
struct btrfs_inode_item inode;
|
||||||
|
const char *name = (const char *) (item + 1);
|
||||||
|
char filetime[32], *target = NULL;
|
||||||
|
time_t mtime;
|
||||||
|
|
||||||
|
if (btrfs_lookup_inode(root, &item->location, &inode, NULL)) {
|
||||||
|
printf("%s: Cannot find inode item for directory entry %.*s!\n",
|
||||||
|
__func__, item->name_len, name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mtime = inode.mtime.sec;
|
||||||
|
ctime_r(&mtime, filetime);
|
||||||
|
|
||||||
|
if (item->type == BTRFS_FT_SYMLINK) {
|
||||||
|
target = malloc(min(inode.size + 1,
|
||||||
|
(u64) btrfs_info.sb.sectorsize));
|
||||||
|
|
||||||
|
if (target && btrfs_readlink(root, item->location.objectid,
|
||||||
|
target)) {
|
||||||
|
free(target);
|
||||||
|
target = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target)
|
||||||
|
printf("%s: Cannot read symlink target!\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("<%s> ", typestr[item->type]);
|
||||||
|
if (item->type == BTRFS_FT_CHRDEV || item->type == BTRFS_FT_BLKDEV)
|
||||||
|
printf("%4u,%5u ", (unsigned int) (inode.rdev >> 20),
|
||||||
|
(unsigned int) (inode.rdev & 0xfffff));
|
||||||
|
else
|
||||||
|
printf("%10llu ", inode.size);
|
||||||
|
|
||||||
|
printf("%24.24s %.*s", filetime, item->name_len, name);
|
||||||
|
|
||||||
|
if (item->type == BTRFS_FT_SYMLINK) {
|
||||||
|
printf(" -> %s", target ? target : "?");
|
||||||
|
if (target)
|
||||||
|
free(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_probe(struct blk_desc *fs_dev_desc, disk_partition_t *fs_partition)
|
||||||
|
{
|
||||||
|
btrfs_blk_desc = fs_dev_desc;
|
||||||
|
btrfs_part_info = fs_partition;
|
||||||
|
|
||||||
|
memset(&btrfs_info, 0, sizeof(btrfs_info));
|
||||||
|
|
||||||
|
btrfs_hash_init();
|
||||||
|
if (btrfs_read_superblock())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (btrfs_chunk_map_init()) {
|
||||||
|
printf("%s: failed to init chunk map\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
btrfs_info.tree_root.objectid = 0;
|
||||||
|
btrfs_info.tree_root.bytenr = btrfs_info.sb.root;
|
||||||
|
btrfs_info.chunk_root.objectid = 0;
|
||||||
|
btrfs_info.chunk_root.bytenr = btrfs_info.sb.chunk_root;
|
||||||
|
|
||||||
|
if (btrfs_read_chunk_tree()) {
|
||||||
|
printf("%s: failed to read chunk tree\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btrfs_find_root(btrfs_get_default_subvol_objectid(),
|
||||||
|
&btrfs_info.fs_root, NULL)) {
|
||||||
|
printf("%s: failed to find default subvolume\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_ls(const char *path)
|
||||||
|
{
|
||||||
|
struct btrfs_root root = btrfs_info.fs_root;
|
||||||
|
u64 inr;
|
||||||
|
u8 type;
|
||||||
|
|
||||||
|
inr = btrfs_lookup_path(&root, root.root_dirid, path, &type, NULL, 40);
|
||||||
|
|
||||||
|
if (inr == -1ULL) {
|
||||||
|
printf("Cannot lookup path %s\n", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != BTRFS_FT_DIR) {
|
||||||
|
printf("Not a directory: %s\n", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btrfs_readdir(&root, inr, readdir_callback)) {
|
||||||
|
printf("An error occured while listing directory %s\n", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_exists(const char *file)
|
||||||
|
{
|
||||||
|
struct btrfs_root root = btrfs_info.fs_root;
|
||||||
|
u64 inr;
|
||||||
|
u8 type;
|
||||||
|
|
||||||
|
inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, NULL, 40);
|
||||||
|
|
||||||
|
return (inr != -1ULL && type == BTRFS_FT_REG_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_size(const char *file, loff_t *size)
|
||||||
|
{
|
||||||
|
struct btrfs_root root = btrfs_info.fs_root;
|
||||||
|
struct btrfs_inode_item inode;
|
||||||
|
u64 inr;
|
||||||
|
u8 type;
|
||||||
|
|
||||||
|
inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
|
||||||
|
40);
|
||||||
|
|
||||||
|
if (inr == -1ULL) {
|
||||||
|
printf("Cannot lookup file %s\n", file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != BTRFS_FT_REG_FILE) {
|
||||||
|
printf("Not a regular file: %s\n", file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = inode.size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
|
||||||
|
loff_t *actread)
|
||||||
|
{
|
||||||
|
struct btrfs_root root = btrfs_info.fs_root;
|
||||||
|
struct btrfs_inode_item inode;
|
||||||
|
u64 inr, rd;
|
||||||
|
u8 type;
|
||||||
|
|
||||||
|
inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
|
||||||
|
40);
|
||||||
|
|
||||||
|
if (inr == -1ULL) {
|
||||||
|
printf("Cannot lookup file %s\n", file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != BTRFS_FT_REG_FILE) {
|
||||||
|
printf("Not a regular file: %s\n", file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
len = inode.size;
|
||||||
|
|
||||||
|
if (len > inode.size - offset)
|
||||||
|
len = inode.size - offset;
|
||||||
|
|
||||||
|
rd = btrfs_file_read(&root, inr, offset, len, buf);
|
||||||
|
if (rd == -1ULL) {
|
||||||
|
printf("An error occured while reading file %s\n", file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*actread = rd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btrfs_close(void)
|
||||||
|
{
|
||||||
|
btrfs_chunk_map_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_uuid(char *uuid_str)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LIB_UUID
|
||||||
|
uuid_bin_to_str(btrfs_info.sb.fsid, uuid_str, UUID_STR_FORMAT_STD);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
btrfs_list_subvols();
|
||||||
|
*/
|
16
fs/fs.c
16
fs/fs.c
@ -14,6 +14,7 @@
|
|||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <sandboxfs.h>
|
#include <sandboxfs.h>
|
||||||
#include <ubifs_uboot.h>
|
#include <ubifs_uboot.h>
|
||||||
|
#include <btrfs.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <div64.h>
|
#include <div64.h>
|
||||||
#include <linux/math64.h>
|
#include <linux/math64.h>
|
||||||
@ -218,6 +219,21 @@ static struct fstype_info fstypes[] = {
|
|||||||
.uuid = fs_uuid_unsupported,
|
.uuid = fs_uuid_unsupported,
|
||||||
.opendir = fs_opendir_unsupported,
|
.opendir = fs_opendir_unsupported,
|
||||||
},
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_FS_BTRFS
|
||||||
|
{
|
||||||
|
.fstype = FS_TYPE_BTRFS,
|
||||||
|
.name = "btrfs",
|
||||||
|
.null_dev_desc_ok = false,
|
||||||
|
.probe = btrfs_probe,
|
||||||
|
.close = btrfs_close,
|
||||||
|
.ls = btrfs_ls,
|
||||||
|
.exists = btrfs_exists,
|
||||||
|
.size = btrfs_size,
|
||||||
|
.read = btrfs_read,
|
||||||
|
.write = fs_write_unsupported,
|
||||||
|
.uuid = btrfs_uuid,
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
.fstype = FS_TYPE_ANY,
|
.fstype = FS_TYPE_ANY,
|
||||||
|
21
include/btrfs.h
Normal file
21
include/btrfs.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* BTRFS filesystem implementation for U-Boot
|
||||||
|
*
|
||||||
|
* 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __U_BOOT_BTRFS_H__
|
||||||
|
#define __U_BOOT_BTRFS_H__
|
||||||
|
|
||||||
|
int btrfs_probe(struct blk_desc *, disk_partition_t *);
|
||||||
|
int btrfs_ls(const char *);
|
||||||
|
int btrfs_exists(const char *);
|
||||||
|
int btrfs_size(const char *, loff_t *);
|
||||||
|
int btrfs_read(const char *, void *, loff_t, loff_t, loff_t *);
|
||||||
|
void btrfs_close(void);
|
||||||
|
int btrfs_uuid(char *);
|
||||||
|
void btrfs_list_subvols(void);
|
||||||
|
|
||||||
|
#endif /* __U_BOOT_BTRFS_H__ */
|
@ -13,6 +13,7 @@
|
|||||||
#define FS_TYPE_EXT 2
|
#define FS_TYPE_EXT 2
|
||||||
#define FS_TYPE_SANDBOX 3
|
#define FS_TYPE_SANDBOX 3
|
||||||
#define FS_TYPE_UBIFS 4
|
#define FS_TYPE_UBIFS 4
|
||||||
|
#define FS_TYPE_BTRFS 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the fs layer which block device an partition to use for future
|
* Tell the fs layer which block device an partition to use for future
|
||||||
|
Loading…
Reference in New Issue
Block a user