|
| 1 | +/* |
| 2 | + Copyright The Overlaybd Authors |
| 3 | +
|
| 4 | + Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + you may not use this file except in compliance with the License. |
| 6 | + You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | + Unless required by applicable law or agreed to in writing, software |
| 11 | + distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + See the License for the specific language governing permissions and |
| 14 | + limitations under the License. |
| 15 | +*/ |
| 16 | +#include "extfs.h" |
| 17 | +#include <limits.h> |
| 18 | +#include <ext2fs/ext2_fs.h> |
| 19 | +#include <ext2fs/ext2fs.h> |
| 20 | +#include <photon/photon.h> |
| 21 | +#include <photon/fs/filesystem.h> |
| 22 | +#include <photon/fs/localfs.h> |
| 23 | +#include <photon/common/alog.h> |
| 24 | +#include <photon/common/uuid4.h> |
| 25 | +#include <string> |
| 26 | +#include <fcntl.h> |
| 27 | + |
| 28 | +int mkdir_lost_found(ext2_filsys fs) { |
| 29 | + std::string name = "lost+found"; |
| 30 | + fs->umask = 077; |
| 31 | + ext2_ino_t ret = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name.c_str()); |
| 32 | + if (ret) { |
| 33 | + LOG_ERRNO_RETURN(0, -1, "error mkdir for /lost+found ", VALUE(ret)); |
| 34 | + } |
| 35 | + ext2_ino_t ino; |
| 36 | + ret = ext2fs_lookup(fs, EXT2_ROOT_INO, name.c_str(), name.length(), 0, &ino); |
| 37 | + if (ret) { |
| 38 | + LOG_ERRNO_RETURN(0, -1, "error looking up for /lost+found ", VALUE(ret)); |
| 39 | + } |
| 40 | + // expand twice ensure at least 2 blocks |
| 41 | + for (int i = 0; i < 2; i++) { |
| 42 | + ret = ext2fs_expand_dir(fs, ino); |
| 43 | + if (ret) { |
| 44 | + LOG_ERRNO_RETURN(0, -1, "error expanding dir for /lost+found ", VALUE(ret)); |
| 45 | + } |
| 46 | + } |
| 47 | + return 0; |
| 48 | +} |
| 49 | + |
| 50 | +int do_mkfs(io_manager manager, size_t size) { |
| 51 | + int blocksize = 4096; |
| 52 | + blk64_t blocks_count = size / blocksize; |
| 53 | + int inode_ratio = 16384; |
| 54 | + int inode_size = 256; |
| 55 | + double reserved_ratio = 0.05; |
| 56 | + std::string uuid = "bdf7bb2e-c231-43ce-87c2-overlaybddev"; |
| 57 | + |
| 58 | + struct ext2_super_block fs_param; |
| 59 | + memset(&fs_param, 0, sizeof(struct ext2_super_block)); |
| 60 | + fs_param.s_rev_level = 1; |
| 61 | + |
| 62 | + ext2fs_set_feature_64bit(&fs_param); |
| 63 | + ext2fs_set_feature_sparse_super(&fs_param); |
| 64 | + ext2fs_set_feature_sparse_super2(&fs_param); |
| 65 | + ext2fs_set_feature_filetype(&fs_param); |
| 66 | + ext2fs_set_feature_resize_inode(&fs_param); |
| 67 | + ext2fs_set_feature_dir_index(&fs_param); |
| 68 | + ext2fs_set_feature_xattr(&fs_param); |
| 69 | + ext2fs_set_feature_dir_nlink(&fs_param); |
| 70 | + ext2fs_set_feature_large_file(&fs_param); |
| 71 | + ext2fs_set_feature_huge_file(&fs_param); |
| 72 | + ext2fs_set_feature_flex_bg(&fs_param); |
| 73 | + ext2fs_set_feature_extents(&fs_param); |
| 74 | + ext2fs_set_feature_extra_isize(&fs_param); |
| 75 | + |
| 76 | + fs_param.s_log_cluster_size = fs_param.s_log_block_size = 2; |
| 77 | + fs_param.s_desc_size = EXT2_MIN_DESC_SIZE_64BIT; |
| 78 | + fs_param.s_log_groups_per_flex = 0; |
| 79 | + fs_param.s_inode_size = inode_size; |
| 80 | + |
| 81 | + ext2fs_blocks_count_set(&fs_param, blocks_count); |
| 82 | + unsigned long long n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio; |
| 83 | + fs_param.s_inodes_count = (n > UINT_MAX) ? UINT_MAX : n; |
| 84 | + |
| 85 | + ext2fs_r_blocks_count_set(&fs_param, reserved_ratio * ext2fs_blocks_count(&fs_param)); |
| 86 | + fs_param.s_backup_bgs[0] = 1; |
| 87 | + fs_param.s_backup_bgs[1] = ~0; |
| 88 | + |
| 89 | + ext2_filsys fs; |
| 90 | + // init superblock |
| 91 | + errcode_t ret = ext2fs_initialize("virtual-dev", 0, &fs_param, manager, &fs); |
| 92 | + if (ret) { |
| 93 | + LOG_ERRNO_RETURN(0, -1, "error while setting up superblock ", VALUE(ret)); |
| 94 | + } |
| 95 | + |
| 96 | + uuid4_parse((char*)uuid.c_str(), (char*)(fs->super->s_uuid)); |
| 97 | + uuid4_parse((char*)uuid.c_str(), (char*)(fs_param.s_hash_seed)); |
| 98 | + fs->super->s_kbytes_written = 1; |
| 99 | + fs->super->s_def_hash_version = EXT2_HASH_HALF_MD4; |
| 100 | + fs->super->s_max_mnt_count = -1; |
| 101 | + fs->stride = fs->super->s_raid_stride; |
| 102 | + // alloc tables |
| 103 | + ret = ext2fs_allocate_tables(fs); |
| 104 | + if (ret) { |
| 105 | + LOG_ERRNO_RETURN(0, -1, "error while allocating tables ", VALUE(ret)); |
| 106 | + } |
| 107 | + // create root dir |
| 108 | + ret = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0); |
| 109 | + if (ret) { |
| 110 | + LOG_ERRNO_RETURN(0, -1, "error make root dir ", VALUE(ret)); |
| 111 | + } |
| 112 | + // mkdir for lost+found |
| 113 | + ret = mkdir_lost_found(fs); |
| 114 | + if (ret) { |
| 115 | + return ret; |
| 116 | + } |
| 117 | + // reserve inodes |
| 118 | + for (ext2_ino_t i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) |
| 119 | + ext2fs_inode_alloc_stats2(fs, i, +1, 0); |
| 120 | + ext2fs_mark_ib_dirty(fs); |
| 121 | + // create resize inode |
| 122 | + ret = ext2fs_create_resize_inode(fs); |
| 123 | + if (ret) { |
| 124 | + LOG_ERRNO_RETURN(0, -1, "error creating resize inode ", VALUE(ret)); |
| 125 | + } |
| 126 | + |
| 127 | + ret = ext2fs_close_free(&fs); |
| 128 | + if (ret) { |
| 129 | + LOG_ERRNO_RETURN(0, -1, "error closing fs ", VALUE(ret)); |
| 130 | + } |
| 131 | + return 0; |
| 132 | +} |
| 133 | + |
| 134 | +int make_extfs(photon::fs::IFile *file) { |
| 135 | + struct stat st; |
| 136 | + auto ret = file->fstat(&st); |
| 137 | + if (ret) return ret; |
| 138 | + auto manager = new_io_manager(file); |
| 139 | + DEFER(delete manager); |
| 140 | + ret = do_mkfs(manager->get_io_manager(), st.st_size); |
| 141 | + return ret; |
| 142 | +} |
0 commit comments