Skip to content

Commit 6f2d6c2

Browse files
committed
add overlaybd-resize tool for userspace ext4 resize on overlaybd images
1 parent 79981d3 commit 6f2d6c2

9 files changed

Lines changed: 608 additions & 3 deletions

File tree

CMake/Finde2fs.cmake

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ if(NOT ORIGIN_EXT2FS)
44
FetchContent_Declare(
55
e2fsprogs
66
GIT_REPOSITORY https://github.com/data-accelerator/e2fsprogs.git
7-
GIT_TAG b4cf6c751196a12b1df9a269d8e0b516b99fe6a7
7+
GIT_TAG 404deb95e6b0ed0ceb0148d289977e65bee7f8d0
88
)
99
FetchContent_GetProperties(e2fsprogs)
1010

1111
if(NOT TARGET libext2fs_build)
1212
FetchContent_MakeAvailable(e2fsprogs)
1313
set(LIBEXT2FS_INSTALL_DIR ${e2fsprogs_SOURCE_DIR}/build/libext2fs CACHE STRING "")
14+
set(E2FS_RESIZE_DIR ${e2fsprogs_SOURCE_DIR}/build/resize CACHE STRING "path to e2fsprogs resize build dir")
15+
set(E2FS_INSTALL_LIB_DIR ${LIBEXT2FS_INSTALL_DIR}/lib CACHE STRING "path to e2fsprogs install-libs output")
1416

1517
add_custom_command(
1618
OUTPUT ${LIBEXT2FS_INSTALL_DIR}/lib
@@ -22,7 +24,8 @@ if(NOT ORIGIN_EXT2FS)
2224

2325
set(E2FS_FOUND yes)
2426
set(E2FS_LIBRARY ${LIBEXT2FS_INSTALL_DIR}/lib/libext2fs.so)
25-
set(E2FS_LIBRARIES ${E2FS_LIBRARY})
27+
set(E2FS_COM_ERR_LIBRARY ${e2fsprogs_SOURCE_DIR}/build/lib/libcom_err.a)
28+
set(E2FS_LIBRARIES ${E2FS_LIBRARY} ${E2FS_COM_ERR_LIBRARY})
2629
set(E2FS_INCLUDE_DIR ${LIBEXT2FS_INSTALL_DIR}/include)
2730
set(E2FS_INCLUDE_DIRS ${E2FS_INCLUDE_DIR})
2831

CMake/Findphoton.cmake

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
include(FetchContent)
22
set(FETCHCONTENT_QUIET false)
33
set(PHOTON_ENABLE_EXTFS ON)
4+
set(PHOTON_ENABLE_RESIZE ON)
5+
add_definitions(-DPHOTON_ENABLE_RESIZE)
46

57
FetchContent_Declare(
68
photon
79
GIT_REPOSITORY https://github.com/alibaba/PhotonLibOS.git
8-
GIT_TAG v0.6.17
10+
GIT_TAG 0178d14499d8639759a81e32ad58da5226df5e9b
911
)
1012

1113
if(BUILD_TESTING)

src/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ target_link_libraries(overlaybd_image_lib
3333
${AIO_LIBRARIES}
3434
)
3535

36+
# Propagate resize .o files to all consumers of overlaybd_image_lib.
37+
# These provide the resize_fs() symbol needed by photon's resize_extfs().
38+
if (NOT ORIGIN_EXT2FS)
39+
target_link_libraries(overlaybd_image_lib
40+
${E2FS_RESIZE_DIR}/resize2fs.o
41+
${E2FS_RESIZE_DIR}/extent.o
42+
${E2FS_RESIZE_DIR}/resource_track.o
43+
${E2FS_LIBRARIES}
44+
)
45+
add_dependencies(overlaybd_image_lib libext2fs_build)
46+
endif()
47+
3648
add_executable(overlaybd-tcmu
3749
main.cpp
3850
)

src/image_file.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
#include "overlaybd/gzip/gz.h"
3737
#include "overlaybd/gzindex/gzfile.h"
3838
#include "overlaybd/tar/tar_file.h"
39+
#ifdef PHOTON_ENABLE_RESIZE
40+
#include <photon/fs/extfs/extfs.h>
41+
#endif
3942

4043
#define PARALLEL_LOAD_INDEX 32
4144
using namespace photon::fs;
@@ -614,3 +617,59 @@ int ImageFile::create_snapshot(const char *new_config_path) {
614617

615618
return 0;
616619
}
620+
621+
int ImageFile::resize(uint64_t target_size, bool resize_fs) {
622+
if (read_only) {
623+
LOG_ERROR_RETURN(EROFS, -1, "cannot resize a read-only image (no upper layer)");
624+
}
625+
626+
auto rw = (LSMT::IFileRW *)m_file;
627+
struct stat st;
628+
if (m_file->fstat(&st) != 0) {
629+
LOG_ERRNO_RETURN(0, -1, "fstat failed");
630+
}
631+
uint64_t current = (uint64_t)st.st_size;
632+
633+
if (target_size == current && !resize_fs) {
634+
LOG_INFO("vsize already equals target (` bytes), nothing to do", target_size);
635+
return 0;
636+
}
637+
638+
if (target_size > current) {
639+
// Expand: grow block device first, then filesystem
640+
if (rw->update_vsize(target_size) != 0) {
641+
LOG_ERROR_RETURN(0, -1, "failed to update vsize for expand");
642+
}
643+
}
644+
645+
if (resize_fs) {
646+
#ifdef PHOTON_ENABLE_RESIZE
647+
if (photon::fs::resize_extfs(m_file, target_size, 0) != 0) {
648+
if (target_size >= current) {
649+
LOG_ERROR("resize_extfs failed. "
650+
"Re-run to retry or use e2fsck to recover.");
651+
} else {
652+
LOG_ERROR("resize_extfs failed during shrink.");
653+
}
654+
return -1;
655+
}
656+
#else
657+
LOG_ERROR_RETURN(ENOSYS, -1, "resize_fs not supported (built without PHOTON_ENABLE_RESIZE)");
658+
#endif
659+
}
660+
661+
if (target_size < current) {
662+
// Shrink: shrinking without resizing the filesystem is unsafe.
663+
if (!resize_fs) {
664+
LOG_ERROR_RETURN(EINVAL, -1, "cannot shrink without resizing filesystem");
665+
}
666+
// Shrink: update vsize after filesystem is shrunk
667+
if (rw->update_vsize(target_size) != 0) {
668+
LOG_ERROR("filesystem resized but failed to update vsize. Re-run to retry.");
669+
return -1;
670+
}
671+
}
672+
673+
LOG_INFO("resize done: ` -> ` bytes", current, target_size);
674+
return 0;
675+
}

src/image_file.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ class ImageFile : public photon::fs::ForwardFile {
121121

122122
int create_snapshot(const char *new_config_path);
123123

124+
// Resize the block device (and optionally the ext4 filesystem).
125+
// target_size: new block device size in bytes.
126+
// resize_fs: if true, also resize the ext4 filesystem to match.
127+
int resize(uint64_t target_size, bool resize_fs = false);
128+
124129
private:
125130
Prefetcher *m_prefetcher = nullptr;
126131
ImageConfigNS::ImageConfig conf;

src/test/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,28 @@ add_test(
4949
NAME trace_test
5050
COMMAND ${EXECUTABLE_OUTPUT_PATH}/trace_test
5151
)
52+
53+
if (NOT ORIGIN_EXT2FS)
54+
set_source_files_properties(
55+
${E2FS_RESIZE_DIR}/resize2fs.o
56+
${E2FS_RESIZE_DIR}/extent.o
57+
${E2FS_RESIZE_DIR}/resource_track.o
58+
PROPERTIES GENERATED TRUE EXTERNAL_OBJECT TRUE)
59+
add_executable(resize_test
60+
resize_test.cpp
61+
${E2FS_RESIZE_DIR}/resize2fs.o
62+
${E2FS_RESIZE_DIR}/extent.o
63+
${E2FS_RESIZE_DIR}/resource_track.o
64+
)
65+
target_include_directories(resize_test PUBLIC
66+
${PHOTON_INCLUDE_DIR}
67+
${E2FS_INCLUDE_DIRS}
68+
${E2FS_RESIZE_DIR}
69+
)
70+
target_link_libraries(resize_test gtest pthread photon_static ${E2FS_LIBRARIES})
71+
add_dependencies(resize_test libext2fs_build)
72+
add_test(
73+
NAME resize_test
74+
COMMAND ${EXECUTABLE_OUTPUT_PATH}/resize_test
75+
)
76+
endif()

0 commit comments

Comments
 (0)