diff --git a/staging/src/k8s.io/mount-utils/resizefs_linux.go b/staging/src/k8s.io/mount-utils/resizefs_linux.go index b92ce118200..929d061e52b 100644 --- a/staging/src/k8s.io/mount-utils/resizefs_linux.go +++ b/staging/src/k8s.io/mount-utils/resizefs_linux.go @@ -129,6 +129,9 @@ func (resizefs *ResizeFs) NeedResize(devicePath string, deviceMountPath string) case "xfs": blockSize, fsSize, err = resizefs.getXFSSize(deviceMountPath) klog.V(5).Infof("Xfs size: filesystem size=%d, block size=%d, err=%v", fsSize, blockSize, err) + case "btrfs": + blockSize, fsSize, err = resizefs.getBtrfsSize(devicePath) + klog.V(5).Infof("Btrfs size: filesystem size=%d, block size=%d, err=%v", fsSize, blockSize, err) default: klog.Errorf("Not able to parse given filesystem info. fsType: %s, will not resize", format) return false, fmt.Errorf("Could not parse fs info on given filesystem format: %s. Supported fs types are: xfs, ext3, ext4", format) @@ -190,6 +193,51 @@ func (resizefs *ResizeFs) getXFSSize(devicePath string) (uint64, uint64, error) return blockSize, blockSize * blockCount, nil } +func (resizefs *ResizeFs) getBtrfsSize(devicePath string) (uint64, uint64, error) { + output, err := resizefs.exec.Command("btrfs", "inspect-internal", "dump-super", "-f", devicePath).CombinedOutput() + if err != nil { + return 0, 0, fmt.Errorf("failed to read size of filesystem on %s: %s: %s", devicePath, err, string(output)) + } + + blockSize, totalBytes, _ := resizefs.parseBtrfsInfoOutput(string(output), "sectorsize", "total_bytes") + + if blockSize == 0 { + return 0, 0, fmt.Errorf("could not find block size of device %s", devicePath) + } + if totalBytes == 0 { + return 0, 0, fmt.Errorf("could not find total size of device %s", devicePath) + } + return blockSize, totalBytes, nil +} + +func (resizefs *ResizeFs) parseBtrfsInfoOutput(cmdOutput string, blockSizeKey string, totalBytesKey string) (uint64, uint64, error) { + lines := strings.Split(cmdOutput, "\n") + var blockSize, blockCount uint64 + var err error + + for _, line := range lines { + tokens := strings.Fields(line) + if len(tokens) != 2 { + continue + } + key, value := strings.ToLower(strings.TrimSpace(tokens[0])), strings.ToLower(strings.TrimSpace(tokens[1])) + + if key == blockSizeKey { + blockSize, err = strconv.ParseUint(value, 10, 64) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse block size %s: %s", value, err) + } + } + if key == totalBytesKey { + blockCount, err = strconv.ParseUint(value, 10, 64) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse total size %s: %s", value, err) + } + } + } + return blockSize, blockCount, err +} + func (resizefs *ResizeFs) parseFsInfoOutput(cmdOutput string, spliter string, blockSizeKey string, blockCountKey string) (uint64, uint64, error) { lines := strings.Split(cmdOutput, "\n") var blockSize, blockCount uint64 diff --git a/staging/src/k8s.io/mount-utils/resizefs_linux_test.go b/staging/src/k8s.io/mount-utils/resizefs_linux_test.go index 601598c4019..1b0b435fbf2 100644 --- a/staging/src/k8s.io/mount-utils/resizefs_linux_test.go +++ b/staging/src/k8s.io/mount-utils/resizefs_linux_test.go @@ -166,6 +166,224 @@ Journal sequence: 0x00037109 Journal start: 1 Journal checksum type: crc32c Journal checksum: 0xb7df3c6e +` + cmdOutputSuccessBtrfs := + `superblock: bytenr=65536, device=/dev/loop0 +--------------------------------------------------------- +csum_type 0 (crc32c) +csum_size 4 +csum 0x31693b11 [match] +bytenr 65536 +flags 0x1 + ( WRITTEN ) +magic _BHRfS_M [match] +fsid 3f53c8f7-3c57-4185-bf1d-b305b42cce97 +metadata_uuid 3f53c8f7-3c57-4185-bf1d-b305b42cce97 +label +generation 7 +root 30441472 +sys_array_size 129 +chunk_root_generation 6 +root_level 0 +chunk_root 22036480 +chunk_root_level 0 +log_root 0 +log_root_transid 0 +log_root_level 0 +total_bytes 1048576000 +bytes_used 147456 +sectorsize 4096 +nodesize 16384 +leafsize (deprecated) 16384 +stripesize 4096 +root_dir 6 +num_devices 1 +compat_flags 0x0 +compat_ro_flags 0x3 + ( FREE_SPACE_TREE | + FREE_SPACE_TREE_VALID ) +incompat_flags 0x341 + ( MIXED_BACKREF | + EXTENDED_IREF | + SKINNY_METADATA | + NO_HOLES ) +cache_generation 0 +uuid_tree_generation 7 +dev_item.uuid 987c8423-fba3-4168-9892-560a116feb81 +dev_item.fsid 3f53c8f7-3c57-4185-bf1d-b305b42cce97 [match] +dev_item.type 0 +dev_item.total_bytes 1048576000 +dev_item.bytes_used 130023424 +dev_item.io_align 4096 +dev_item.io_width 4096 +dev_item.sector_size 4096 +dev_item.devid 1 +dev_item.dev_group 0 +dev_item.seek_speed 0 +dev_item.bandwidth 0 +dev_item.generation 0 +sys_chunk_array[2048]: + item 0 key (FIRST_CHUNK_TREE CHUNK_ITEM 22020096) + length 8388608 owner 2 stripe_len 65536 type SYSTEM|DUP + io_align 65536 io_width 65536 sector_size 4096 + num_stripes 2 sub_stripes 1 + stripe 0 devid 1 offset 22020096 + dev_uuid 987c8423-fba3-4168-9892-560a116feb81 + stripe 1 devid 1 offset 30408704 + dev_uuid 987c8423-fba3-4168-9892-560a116feb81 +backup_roots[4]: + backup 0: + backup_tree_root: 30441472 gen: 5 level: 0 + backup_chunk_root: 22020096 gen: 5 level: 0 + backup_extent_root: 30474240 gen: 5 level: 0 + backup_fs_root: 30425088 gen: 5 level: 0 + backup_dev_root: 30457856 gen: 5 level: 0 + backup_csum_root: 30490624 gen: 5 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 147456 + backup_num_devices: 1 + + backup 1: + backup_tree_root: 30588928 gen: 6 level: 0 + backup_chunk_root: 22036480 gen: 6 level: 0 + backup_extent_root: 30408704 gen: 6 level: 0 + backup_fs_root: 30425088 gen: 5 level: 0 + backup_dev_root: 30556160 gen: 6 level: 0 + backup_csum_root: 30490624 gen: 5 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 147456 + backup_num_devices: 1 + + backup 2: + backup_tree_root: 30441472 gen: 7 level: 0 + backup_chunk_root: 22036480 gen: 6 level: 0 + backup_extent_root: 30474240 gen: 7 level: 0 + backup_fs_root: 30425088 gen: 5 level: 0 + backup_dev_root: 30457856 gen: 7 level: 0 + backup_csum_root: 30490624 gen: 5 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 147456 + backup_num_devices: 1 + + backup 3: + backup_tree_root: 30408704 gen: 4 level: 0 + backup_chunk_root: 1064960 gen: 4 level: 0 + backup_extent_root: 5341184 gen: 4 level: 0 + backup_fs_root: 5324800 gen: 3 level: 0 + backup_dev_root: 5242880 gen: 4 level: 0 + backup_csum_root: 1130496 gen: 1 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 114688 + backup_num_devices: 1 + +` + cmdOutputNoDataBtrfs := + `superblock: bytenr=65536, device=/dev/loop0 +--------------------------------------------------------- +csum_type 0 (crc32c) +csum_size 4 +csum 0x31693b11 [match] +bytenr 65536 +flags 0x1 + ( WRITTEN ) +magic _BHRfS_M [match] +fsid 3f53c8f7-3c57-4185-bf1d-b305b42cce97 +metadata_uuid 3f53c8f7-3c57-4185-bf1d-b305b42cce97 +label +generation 7 +root 30441472 +sys_array_size 129 +chunk_root_generation 6 +root_level 0 +chunk_root 22036480 +chunk_root_level 0 +log_root 0 +log_root_transid 0 +log_root_level 0 +bytes_used 147456 +nodesize 16384 +leafsize (deprecated) 16384 +stripesize 4096 +root_dir 6 +num_devices 1 +compat_flags 0x0 +compat_ro_flags 0x3 + ( FREE_SPACE_TREE | + FREE_SPACE_TREE_VALID ) +incompat_flags 0x341 + ( MIXED_BACKREF | + EXTENDED_IREF | + SKINNY_METADATA | + NO_HOLES ) +cache_generation 0 +uuid_tree_generation 7 +dev_item.uuid 987c8423-fba3-4168-9892-560a116feb81 +dev_item.fsid 3f53c8f7-3c57-4185-bf1d-b305b42cce97 [match] +dev_item.type 0 +dev_item.total_bytes 1048576000 +dev_item.bytes_used 130023424 +dev_item.io_align 4096 +dev_item.io_width 4096 +dev_item.sector_size 4096 +dev_item.devid 1 +dev_item.dev_group 0 +dev_item.seek_speed 0 +dev_item.bandwidth 0 +dev_item.generation 0 +sys_chunk_array[2048]: + item 0 key (FIRST_CHUNK_TREE CHUNK_ITEM 22020096) + length 8388608 owner 2 stripe_len 65536 type SYSTEM|DUP + io_align 65536 io_width 65536 sector_size 4096 + num_stripes 2 sub_stripes 1 + stripe 0 devid 1 offset 22020096 + dev_uuid 987c8423-fba3-4168-9892-560a116feb81 + stripe 1 devid 1 offset 30408704 + dev_uuid 987c8423-fba3-4168-9892-560a116feb81 +backup_roots[4]: + backup 0: + backup_tree_root: 30441472 gen: 5 level: 0 + backup_chunk_root: 22020096 gen: 5 level: 0 + backup_extent_root: 30474240 gen: 5 level: 0 + backup_fs_root: 30425088 gen: 5 level: 0 + backup_dev_root: 30457856 gen: 5 level: 0 + backup_csum_root: 30490624 gen: 5 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 147456 + backup_num_devices: 1 + + backup 1: + backup_tree_root: 30588928 gen: 6 level: 0 + backup_chunk_root: 22036480 gen: 6 level: 0 + backup_extent_root: 30408704 gen: 6 level: 0 + backup_fs_root: 30425088 gen: 5 level: 0 + backup_dev_root: 30556160 gen: 6 level: 0 + backup_csum_root: 30490624 gen: 5 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 147456 + backup_num_devices: 1 + + backup 2: + backup_tree_root: 30441472 gen: 7 level: 0 + backup_chunk_root: 22036480 gen: 6 level: 0 + backup_extent_root: 30474240 gen: 7 level: 0 + backup_fs_root: 30425088 gen: 5 level: 0 + backup_dev_root: 30457856 gen: 7 level: 0 + backup_csum_root: 30490624 gen: 5 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 147456 + backup_num_devices: 1 + + backup 3: + backup_tree_root: 30408704 gen: 4 level: 0 + backup_chunk_root: 1064960 gen: 4 level: 0 + backup_extent_root: 5341184 gen: 4 level: 0 + backup_fs_root: 5324800 gen: 3 level: 0 + backup_dev_root: 5242880 gen: 4 level: 0 + backup_csum_root: 1130496 gen: 1 level: 0 + backup_total_bytes: 1048576000 + backup_bytes_used: 114688 + backup_num_devices: 1 + ` testcases := []struct { name string @@ -212,6 +430,24 @@ Journal checksum: 0xb7df3c6e expectError: true, fsType: "ext4", }, + { + name: "success parse btrfs info", + devicePath: "/dev/test1", + blocksize: 4096, + blockCount: 256000, + cmdOutput: cmdOutputSuccessBtrfs, + expectError: false, + fsType: "btrfs", + }, + { + name: "block size not present - btrfs", + devicePath: "/dev/test1", + blocksize: 0, + blockCount: 0, + cmdOutput: cmdOutputNoDataBtrfs, + expectError: true, + fsType: "btrfs", + }, } for _, test := range testcases { @@ -238,6 +474,8 @@ Journal checksum: 0xb7df3c6e blockSize, fsSize, err = resizefs.getXFSSize(test.devicePath) case "ext4": blockSize, fsSize, err = resizefs.getExtSize(test.devicePath) + case "btrfs": + blockSize, fsSize, err = resizefs.getBtrfsSize(test.devicePath) } if blockSize != test.blocksize {