|
36 | 36 | #include "overlaybd/gzip/gz.h" |
37 | 37 | #include "overlaybd/gzindex/gzfile.h" |
38 | 38 | #include "overlaybd/tar/tar_file.h" |
| 39 | +#ifdef PHOTON_ENABLE_RESIZE |
| 40 | +#include <photon/fs/extfs/extfs.h> |
| 41 | +#endif |
39 | 42 |
|
40 | 43 | #define PARALLEL_LOAD_INDEX 32 |
41 | 44 | using namespace photon::fs; |
@@ -614,3 +617,53 @@ int ImageFile::create_snapshot(const char *new_config_path) { |
614 | 617 |
|
615 | 618 | return 0; |
616 | 619 | } |
| 620 | + |
| 621 | +int ImageFile::resize(uint64_t target_size, bool resize_fs, int flags) { |
| 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 | + m_file->fstat(&st); |
| 629 | + uint64_t current = (uint64_t)st.st_size; |
| 630 | + |
| 631 | + if (target_size == current && !resize_fs) { |
| 632 | + LOG_INFO("vsize already equals target (` bytes), nothing to do", target_size); |
| 633 | + return 0; |
| 634 | + } |
| 635 | + |
| 636 | + if (target_size > current) { |
| 637 | + // Expand: grow block device first, then filesystem |
| 638 | + if (rw->update_vsize(target_size) != 0) { |
| 639 | + LOG_ERROR_RETURN(0, -1, "failed to update vsize for expand"); |
| 640 | + } |
| 641 | + } |
| 642 | + |
| 643 | + if (resize_fs) { |
| 644 | +#ifdef PHOTON_ENABLE_RESIZE |
| 645 | + if (photon::fs::resize_extfs(m_file, target_size, flags) != 0) { |
| 646 | + if (target_size >= current) { |
| 647 | + LOG_ERROR("resize_extfs failed. " |
| 648 | + "Re-run to retry or use e2fsck to recover."); |
| 649 | + } else { |
| 650 | + LOG_ERROR("resize_extfs failed during shrink."); |
| 651 | + } |
| 652 | + return -1; |
| 653 | + } |
| 654 | +#else |
| 655 | + LOG_ERROR_RETURN(ENOSYS, -1, "resize_fs not supported (built without PHOTON_ENABLE_RESIZE)"); |
| 656 | +#endif |
| 657 | + } |
| 658 | + |
| 659 | + if (target_size < current) { |
| 660 | + // Shrink: update vsize after filesystem is shrunk |
| 661 | + if (rw->update_vsize(target_size) != 0) { |
| 662 | + LOG_ERROR("filesystem resized but failed to update vsize. Re-run to retry."); |
| 663 | + return -1; |
| 664 | + } |
| 665 | + } |
| 666 | + |
| 667 | + LOG_INFO("resize done: ` -> ` bytes", current, target_size); |
| 668 | + return 0; |
| 669 | +} |
0 commit comments