diff --git a/README.md b/README.md index b51d20c5b..b1038cc8b 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,13 @@ As noted in [GCP PD documentation](https://cloud.google.com/kubernetes-engine/do `btrfs` filesystem accepts the following "special" mount options and the sysfs paths they target: -- `btrfs-data-bg_reclaim_threshold`: `/sys/fs/btrfs/FS-UUID/allocation/data/bg_reclaim_threshold`. -- `btrfs-metadata-bg_reclaim_thresho: `/sys/fs/btrfs/FS-UUID/allocation/metadata/bg_reclaim_threshold`. -- `btrfs-bdi-read_ahead_kb`: `/sys/fs/btrfs/FS-UUID/bdi/read_ahead_kb`. +| Setting | Sysfs path | Value | Default | Supported on Linux versions | Notes | +|--------------------------------------------------|-------------------------------------------------------------------|----------------|-------------------------|-----------------------------|-------| +| `btrfs-allocation-data-bg_reclaim_threshold` | `/sys/fs/btrfs/FS-UUID/allocation/data/bg_reclaim_threshold` | 0–99 (percent) | 0 (off) | v5.19+ | Triggers background reclaim for DATA block groups when usage drops to the threshold. | +| `btrfs-allocation-metadata-bg_reclaim_threshold` | `/sys/fs/btrfs/FS-UUID/allocation/metadata/bg_reclaim_threshold` | 0–99 (percent) | 0 (off) | v5.19+ | Same as above, for METADATA block groups. | +| `btrfs-allocation-data-dynamic_reclaim` | `/sys/fs/btrfs/FS-UUID/allocation/data/dynamic_reclaim` | `0` or `1` | 0 (off) | v6.11+ | Heuristic reclaim that addresses [some concerns](https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f5ff64ccf7bb7274ed66b0d835b2f6ae10af5d7a) of `bg_reclaim_threshold`. | +| `btrfs-allocation-metadata-dynamic_reclaim` | `/sys/fs/btrfs/FS-UUID/allocation/metadata/dynamic_reclaim` | `0` or `1` | 0 (off) | v6.11+ | Same as above, for METADATA block groups. | +| `btrfs-bdi-read_ahead_kb` | `/sys/fs/btrfs/FS-UUID/bdi/read_ahead_kb` | integer kB ≥ 0 | kernel/device dependent | v5.9+ | Per-BDI readahead. Powers of two are commonly used. | See more in the [in btrfs docs](https://btrfs.readthedocs.io/en/latest/ch-sysfs.html#uuid-allocations-data-metadata-system). diff --git a/pkg/gce-pd-csi-driver/node.go b/pkg/gce-pd-csi-driver/node.go index 9c55f27fa..73c431186 100644 --- a/pkg/gce-pd-csi-driver/node.go +++ b/pkg/gce-pd-csi-driver/node.go @@ -121,19 +121,31 @@ const ( fsTypeExt3 = "ext3" fsTypeBtrfs = "btrfs" - readAheadKBMountFlagRegexPattern = "^read_ahead_kb=(.+)$" - btrfsReclaimDataRegexPattern = "^btrfs-allocation-data-bg_reclaim_threshold=(\\d{1,2})$" // 0-99 are valid, incl. 00 - btrfsReclaimMetadataRegexPattern = "^btrfs-allocation-metadata-bg_reclaim_threshold=(\\d{1,2})$" // ditto ^ - btrfsReadAheadKBRegexPattern = "^btrfs-bdi-read_ahead_kb=(\\d+)$" + readAheadKBMountFlagRegexPattern = "^read_ahead_kb=(.+)$" + btrfsReclaimDataRegexPattern = "^btrfs-allocation-data-bg_reclaim_threshold=(\\d{1,2})$" // 0-99 are valid, incl. 00 + btrfsReclaimMetadataRegexPattern = "^btrfs-allocation-metadata-bg_reclaim_threshold=(\\d{1,2})$" // ditto ^ + btrfsDynamicReclaimDataRegexPattern = "^btrfs-allocation-data-dynamic_reclaim=(0|1)$" // boolean in kernel, so accepting 0 or 1 + btrfsDynamicReclaimMetadataRegexPattern = "^btrfs-allocation-metadata-dynamic_reclaim=(0|1)$" // ditto ^ + btrfsReadAheadKBRegexPattern = "^btrfs-bdi-read_ahead_kb=(\\d+)$" ) var ( - readAheadKBMountFlagRegex = regexp.MustCompile(readAheadKBMountFlagRegexPattern) - btrfsReclaimDataRegex = regexp.MustCompile(btrfsReclaimDataRegexPattern) - btrfsReclaimMetadataRegex = regexp.MustCompile(btrfsReclaimMetadataRegexPattern) - btrfsReadAheadKBRegex = regexp.MustCompile(btrfsReadAheadKBRegexPattern) + readAheadKBMountFlagRegex = regexp.MustCompile(readAheadKBMountFlagRegexPattern) + btrfsReclaimDataRegex = regexp.MustCompile(btrfsReclaimDataRegexPattern) + btrfsReclaimMetadataRegex = regexp.MustCompile(btrfsReclaimMetadataRegexPattern) + btrfsDynamicReclaimDataRegex = regexp.MustCompile(btrfsDynamicReclaimDataRegexPattern) + btrfsDynamicReclaimMetadataRegex = regexp.MustCompile(btrfsDynamicReclaimMetadataRegexPattern) + btrfsReadAheadKBRegex = regexp.MustCompile(btrfsReadAheadKBRegexPattern) ) +type btrfsFlags struct { + reclaimData, + reclaimMetadata, + dynamicReclaimData, + dynamicReclaimMetadata, + readAheadKb string +} + func getDefaultFsType() string { if runtime.GOOS == "windows" { return defaultWindowsFsType @@ -404,7 +416,7 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage // Part 3: Mount device to stagingTargetPath fstype := getDefaultFsType() - var btrfsReclaimData, btrfsReclaimMetadata, btrfsReadAheadKb string + var btrfsFlags btrfsFlags shouldUpdateReadAhead := false var readAheadKB int64 options := []string{} @@ -420,7 +432,7 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage } if mnt.FsType == fsTypeBtrfs { - btrfsReclaimData, btrfsReclaimMetadata, btrfsReadAheadKb = extractBtrfsFlags(mnt.MountFlags) + btrfsFlags = extractBtrfsFlags(mnt.MountFlags) } } else if blk := volumeCapability.GetBlock(); blk != nil { // Noop for Block NodeStageVolume @@ -476,16 +488,22 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage btrfsSysfs := map[string]string{} - if btrfsReadAheadKb != "" { - btrfsSysfs["bdi/read_ahead_kb"] = btrfsReadAheadKb + if btrfsFlags.readAheadKb != "" { + btrfsSysfs["bdi/read_ahead_kb"] = btrfsFlags.readAheadKb } if !readonly { - if btrfsReclaimData != "" { - btrfsSysfs["allocation/data/bg_reclaim_threshold"] = btrfsReclaimData + if btrfsFlags.reclaimData != "" { + btrfsSysfs["allocation/data/bg_reclaim_threshold"] = btrfsFlags.reclaimData + } + if btrfsFlags.reclaimMetadata != "" { + btrfsSysfs["allocation/metadata/bg_reclaim_threshold"] = btrfsFlags.reclaimMetadata + } + if btrfsFlags.dynamicReclaimData != "" { + btrfsSysfs["allocation/data/dynamic_reclaim"] = btrfsFlags.dynamicReclaimData } - if btrfsReclaimMetadata != "" { - btrfsSysfs["allocation/metadata/bg_reclaim_threshold"] = btrfsReclaimMetadata + if btrfsFlags.dynamicReclaimMetadata != "" { + btrfsSysfs["allocation/metadata/dynamic_reclaim"] = btrfsFlags.dynamicReclaimMetadata } } @@ -552,18 +570,22 @@ func (ns *GCENodeServer) updateReadAhead(devicePath string, readAheadKB int64) e return nil } -func extractBtrfsFlags(mountFlags []string) (string, string, string) { - var reclaimData, reclaimMetadata, readAheadKb string +func extractBtrfsFlags(mountFlags []string) btrfsFlags { + var flags btrfsFlags for _, mountFlag := range mountFlags { if got := btrfsReclaimDataRegex.FindStringSubmatch(mountFlag); len(got) == 2 { - reclaimData = got[1] + flags.reclaimData = got[1] } else if got := btrfsReclaimMetadataRegex.FindStringSubmatch(mountFlag); len(got) == 2 { - reclaimMetadata = got[1] + flags.reclaimMetadata = got[1] } else if got := btrfsReadAheadKBRegex.FindStringSubmatch(mountFlag); len(got) == 2 { - readAheadKb = got[1] + flags.readAheadKb = got[1] + } else if got := btrfsDynamicReclaimDataRegex.FindStringSubmatch(mountFlag); len(got) == 2 { + flags.dynamicReclaimData = got[1] + } else if got := btrfsDynamicReclaimMetadataRegex.FindStringSubmatch(mountFlag); len(got) == 2 { + flags.dynamicReclaimMetadata = got[1] } } - return reclaimData, reclaimMetadata, readAheadKb + return flags } func extractReadAheadKBMountFlag(mountFlags []string) (int64, bool, error) { diff --git a/pkg/gce-pd-csi-driver/node_test.go b/pkg/gce-pd-csi-driver/node_test.go index 06d08563c..1535bcbeb 100644 --- a/pkg/gce-pd-csi-driver/node_test.go +++ b/pkg/gce-pd-csi-driver/node_test.go @@ -631,7 +631,9 @@ func TestNodeStageVolume(t *testing.T) { btrfsPrefix = fmt.Sprintf("%s/sys/fs/btrfs/%s", tempDir, btrfsUUID) btrfsFixtures = map[string]string{ "allocation/data/bg_reclaim_threshold": "0\n", + "allocation/data/dynamic_reclaim": "0\n", "allocation/metadata/bg_reclaim_threshold": "0\n", + "allocation/metadata/dynamic_reclaim": "0\n", "bdi/read_ahead_kb": "4096\n", } ) @@ -648,22 +650,24 @@ func TestNodeStageVolume(t *testing.T) { } testCases := []struct { - name string - req *csi.NodeStageVolumeRequest - deviceSize int - blockExtSize int - readonlyBit string - expResize bool - expReadAheadUpdate bool - expReadAheadKB string - expReadOnlyRemount bool - expCommandList []fakeCmd - readAheadSectors string - btrfsReclaimData string - btrfsReclaimMetadata string - btrfsReadAheadKb string - sectorSizeInBytes int - expErrCode codes.Code + name string + req *csi.NodeStageVolumeRequest + deviceSize int + blockExtSize int + readonlyBit string + expResize bool + expReadAheadUpdate bool + expReadAheadKB string + expReadOnlyRemount bool + expCommandList []fakeCmd + readAheadSectors string + btrfsReclaimData string + btrfsReclaimMetadata string + btrfsDynamicReclaimData string + btrfsDynamicReclaimMetadata string + btrfsReadAheadKb string + sectorSizeInBytes int + expErrCode codes.Code }{ { name: "Valid request, resize even though block and filesystem sizes match", @@ -927,6 +931,8 @@ func TestNodeStageVolume(t *testing.T) { MountFlags: []string{ "btrfs-allocation-data-bg_reclaim_threshold=90", "btrfs-allocation-metadata-bg_reclaim_threshold=91", + "btrfs-allocation-data-dynamic_reclaim=1", + "btrfs-allocation-metadata-dynamic_reclaim=1", "btrfs-bdi-read_ahead_kb=128", }, }, @@ -936,12 +942,14 @@ func TestNodeStageVolume(t *testing.T) { }, }, }, - deviceSize: 1, - blockExtSize: 1, - readonlyBit: "0", - btrfsReclaimData: "90", - btrfsReclaimMetadata: "91", - btrfsReadAheadKb: "128", + deviceSize: 1, + blockExtSize: 1, + readonlyBit: "0", + btrfsReclaimData: "90", + btrfsReclaimMetadata: "91", + btrfsDynamicReclaimData: "1", + btrfsDynamicReclaimMetadata: "1", + btrfsReadAheadKb: "128", expCommandList: []fakeCmd{ { cmd: "blkid", @@ -1267,13 +1275,17 @@ func TestNodeStageVolume(t *testing.T) { if tc.expReadAheadUpdate == false && readAheadUpdateCalled == true { t.Fatalf("Test updated read ahead, but it was not expected.") } - if tc.btrfsReclaimData == "" && tc.btrfsReclaimMetadata == "" && tc.btrfsReadAheadKb == "" && blkidCalled { + if tc.btrfsReclaimData == "" && tc.btrfsReclaimMetadata == "" && + tc.btrfsDynamicReclaimData == "" && tc.btrfsDynamicReclaimMetadata == "" && + tc.btrfsReadAheadKb == "" && blkidCalled { t.Fatalf("blkid was called, but was not expected.") } btrfsProps := map[string]string{ "/allocation/data/bg_reclaim_threshold": tc.btrfsReclaimData, "/allocation/metadata/bg_reclaim_threshold": tc.btrfsReclaimMetadata, + "/allocation/data/dynamic_reclaim": tc.btrfsDynamicReclaimData, + "/allocation/metadata/dynamic_reclaim": tc.btrfsDynamicReclaimMetadata, "/bdi/read_ahead_kb": tc.btrfsReadAheadKb, } diff --git a/pkg/gce-pd-csi-driver/utils.go b/pkg/gce-pd-csi-driver/utils.go index b0d3af954..dda55a6c8 100644 --- a/pkg/gce-pd-csi-driver/utils.go +++ b/pkg/gce-pd-csi-driver/utils.go @@ -317,6 +317,12 @@ func collectMountOptions(fsType string, mntFlags []string) []string { if btrfsReclaimMetadataRegex.FindString(opt) != "" { continue } + if btrfsDynamicReclaimDataRegex.FindString(opt) != "" { + continue + } + if btrfsDynamicReclaimMetadataRegex.FindString(opt) != "" { + continue + } if btrfsReadAheadKBRegex.FindString(opt) != "" { continue }