diff --git a/internal/lvmd/command/lvm.go b/internal/lvmd/command/lvm.go index 3a2fe6271..0d71e7351 100644 --- a/internal/lvmd/command/lvm.go +++ b/internal/lvmd/command/lvm.go @@ -474,7 +474,8 @@ func (l *LogicalVolume) Origin(ctx context.Context) (*LogicalVolume, error) { // IsThin checks if the volume is thin volume or not. func (l *LogicalVolume) IsThin() bool { - return l.pool != nil + // TODO: maybe use const from lvm_lv_attr.go + return l.attr[0] == 'V' } // Pool returns thin pool if this is a thin pool, or nil if not. diff --git a/internal/lvmd/command/lvm_command_test.go b/internal/lvmd/command/lvm_command_test.go index be3b7f00b..07476af08 100644 --- a/internal/lvmd/command/lvm_command_test.go +++ b/internal/lvmd/command/lvm_command_test.go @@ -192,5 +192,39 @@ func Test_lvm_command(t *testing.T) { t.Fatalf("expected error to be %v, got %v", ErrNoMultipleOfSectorSize, err) } }) + + t.Run("create cached volume and read it", func(t *testing.T) { + // create the cachedevice + cache_vg_name := "CACHEDEVICE" + cache_loop, err := testutils.MakeLoopbackDevice(ctx, cache_vg_name) + if err != nil { + t.Fatal(err) + } + err = testutils.MakeLoopbackVG(ctx, cache_vg_name, cache_loop) + if err != nil { + t.Fatal(err) + } + // ensure cache device cleanup + defer func() { _ = testutils.CleanLoopbackVG(cache_vg_name, []string{cache_loop}, []string{cache_vg_name}) }() + vg, err := FindVolumeGroup(ctx, cache_vg_name) + if err != nil { + t.Fatal(err) + } + // create cached LV + err = vg.CreateVolume(ctx, "test1", uint64(topolvm.MinimumSectorSize), []string{"tag"}, 0, "", []string{"--type", "writecache", "--cachesize", "10M", "--cachedevice", cache_loop}) + if err != nil { + t.Fatal(err) + } + vol, err := vg.FindVolume(ctx, "test1") + if err != nil { + t.Fatal(err) + } + if vol.IsThin() { + t.Fatal("Expected test1 to not be thin (eval lv_attr instead of pool)") + } + if !strings.Contains(vol.attr, "C") { + t.Fatal("Created a LV but without writecache?") + } + }) }) } diff --git a/internal/lvmd/command/lvm_lv_attr.go b/internal/lvmd/command/lvm_lv_attr.go index 81d2f2f6c..4e2eee97b 100644 --- a/internal/lvmd/command/lvm_lv_attr.go +++ b/internal/lvmd/command/lvm_lv_attr.go @@ -32,6 +32,7 @@ var ( type VolumeType rune const ( + VolumeTypeCached VolumeType = 'C' VolumeTypeMirrored VolumeType = 'm' VolumeTypeMirroredNoInitialSync VolumeType = 'M' VolumeTypeOrigin VolumeType = 'o' @@ -114,6 +115,7 @@ const ( type OpenTarget rune const ( + OpenTargetCache OpenTarget = 'C' OpenTargetMirror OpenTarget = 'm' OpenTargetRaid OpenTarget = 'r' OpenTargetSnapshot OpenTarget = 's' diff --git a/internal/lvmd/command/lvm_lv_attr_test.go b/internal/lvmd/command/lvm_lv_attr_test.go index 04c0c47be..42518dc29 100644 --- a/internal/lvmd/command/lvm_lv_attr_test.go +++ b/internal/lvmd/command/lvm_lv_attr_test.go @@ -81,6 +81,23 @@ func TestParsedLVAttr(t *testing.T) { }, noError, }, + { + "Cache", + args{raw: "Cwi-aoC---"}, + LVAttr{ + VolumeType: VolumeTypeCached, + Permissions: PermissionsWriteable, + AllocationPolicy: AllocationPolicyInherited, + Minor: MinorFalse, + State: StateActive, + Open: OpenTrue, + OpenTarget: OpenTargetCache, + Zero: ZeroFalse, + VolumeHealth: VolumeHealthOK, + SkipActivation: SkipActivationFalse, + }, + noError, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {