diff --git a/app/cmd/basic/bdev_raid.go b/app/cmd/basic/bdev_raid.go index 7ac8d60..a2efdc5 100644 --- a/app/cmd/basic/bdev_raid.go +++ b/app/cmd/basic/bdev_raid.go @@ -21,6 +21,9 @@ func BdevRaidCmd() cli.Command { BdevRaidGetCmd(), BdevRaidRemoveBaseBdevCmd(), BdevRaidGrowBaseBdevCmd(), + BdevRaidGetBaseBdevDeltaMapCmd(), + BdevRaidStopBaseBdevDeltaMapCmd(), + BdevRaidClearBaseBdevFaultyStateCmd(), }, } } @@ -50,6 +53,21 @@ func BdevRaidCreateCmd() cli.Command { Usage: "Names of Nvme bdevs, the input is like \"--base-devs Nvme0n1 --base-devs Nvme1n1\"", Required: true, }, + cli.StringFlag{ + Name: "UUID", + Usage: "UUID for this raid bdev", + Required: false, + }, + cli.BoolFlag{ + Name: "superblock", + Usage: "Raid bdev info will be stored in superblock on each base bdev", + Required: false, + }, + cli.BoolFlag{ + Name: "delta-bitmap", + Usage: "A delta bitmap for faulty base bdevs will be recorded", + Required: false, + }, }, Action: func(c *cli.Context) { if err := bdevRaidCreate(c); err != nil { @@ -65,7 +83,8 @@ func bdevRaidCreate(c *cli.Context) error { return err } - created, err := spdkCli.BdevRaidCreate(c.String("name"), spdktypes.BdevRaidLevel(c.String("level")), uint32(c.Uint64("strip-size-kb")), c.StringSlice("base-bdevs")) + created, err := spdkCli.BdevRaidCreate(c.String("name"), spdktypes.BdevRaidLevel(c.String("level")), uint32(c.Uint64("strip-size-kb")), c.StringSlice("base-bdevs"), + c.String("UUID"), c.Bool("superblock"), c.Bool("delta-bitmap")) if err != nil { return err } @@ -193,3 +212,93 @@ func bdevRaidGrowBaseBdev(c *cli.Context) error { return util.PrintObject(growed) } + +func BdevRaidGetBaseBdevDeltaMapCmd() cli.Command { + return cli.Command{ + Name: "get-base-bdev-delta-map", + Usage: "get the delta bitmap of a faulty base bdev", + ArgsUsage: "", + Action: func(c *cli.Context) { + if c.NArg() != 1 { + logrus.Fatal("BASE BDEV NAME argument required") + } + if err := bdevRaidGetBaseBdevDeltaMap(c); err != nil { + logrus.WithError(err).Fatalf("Failed to run get base bdev delta map to raid command") + } + }, + } +} + +func bdevRaidGetBaseBdevDeltaMap(c *cli.Context) error { + spdkCli, err := client.NewClient(context.Background()) + if err != nil { + return err + } + + deltaMap, err := spdkCli.BdevRaidGetBaseBdevDeltaMap(c.Args().First()) + if err != nil { + return err + } + + return util.PrintObject(deltaMap) +} + +func BdevRaidStopBaseBdevDeltaMapCmd() cli.Command { + return cli.Command{ + Name: "stop-base-bdev-delta-map", + Usage: "stop the updating of the delta bitmap of a faulty base bdev", + ArgsUsage: "", + Action: func(c *cli.Context) { + if c.NArg() != 1 { + logrus.Fatal("BASE BDEV NAME argument required") + } + if err := bdevRaidStopBaseBdevDeltaMap(c); err != nil { + logrus.WithError(err).Fatalf("Failed to run stop base bdev delta map to raid command") + } + }, + } +} + +func bdevRaidStopBaseBdevDeltaMap(c *cli.Context) error { + spdkCli, err := client.NewClient(context.Background()) + if err != nil { + return err + } + + stopped, err := spdkCli.BdevRaidStopBaseBdevDeltaMap(c.Args().First()) + if err != nil { + return err + } + + return util.PrintObject(stopped) +} + +func BdevRaidClearBaseBdevFaultyStateCmd() cli.Command { + return cli.Command{ + Name: "clear-base-bdev-faulty-state", + Usage: "clear the faulty state of a base bdev", + ArgsUsage: "", + Action: func(c *cli.Context) { + if c.NArg() != 1 { + logrus.Fatal("BASE BDEV NAME argument required") + } + if err := bdevRaidClearBaseBdevFaultyState(c); err != nil { + logrus.WithError(err).Fatalf("Failed to run clear base bdev faulty state to raid command") + } + }, + } +} + +func bdevRaidClearBaseBdevFaultyState(c *cli.Context) error { + spdkCli, err := client.NewClient(context.Background()) + if err != nil { + return err + } + + cleared, err := spdkCli.BdevRaidClearBaseBdevFaultyState(c.Args().First()) + if err != nil { + return err + } + + return util.PrintObject(cleared) +} diff --git a/pkg/spdk/client/basic.go b/pkg/spdk/client/basic.go index e257dab..12b139d 100644 --- a/pkg/spdk/client/basic.go +++ b/pkg/spdk/client/basic.go @@ -531,7 +531,14 @@ func (c *Client) BdevLvolRename(oldName, newName string) (renamed bool, err erro // "stripSizeKb": Required. Strip size in KB. It's valid for raid0 and raid5f only. For other raid levels, this would be modified to 0. // // "baseBdevs": Required. The bdev list used as the underlying disk of the RAID. -func (c *Client) BdevRaidCreate(name string, raidLevel spdktypes.BdevRaidLevel, stripSizeKb uint32, baseBdevs []string) (created bool, err error) { +// +// "uuid": Optional. UUID for this raid bdev. Empty value will be ignored. +// +// "superblock": Optional. Raid bdev info will be stored in superblock on each base bdev. Default false. +// +// "delta_bitmap": Optional. A delta bitmap for faulty base bdevs will be recorded. Default false. +func (c *Client) BdevRaidCreate(name string, raidLevel spdktypes.BdevRaidLevel, stripSizeKb uint32, baseBdevs []string, + uuid string, superBlock bool, deltaBitmap bool) (created bool, err error) { if raidLevel != spdktypes.BdevRaidLevel0 && raidLevel != spdktypes.BdevRaidLevelRaid0 && raidLevel != spdktypes.BdevRaidLevel5f && raidLevel != spdktypes.BdevRaidLevelRaid5f { stripSizeKb = 0 } @@ -540,6 +547,9 @@ func (c *Client) BdevRaidCreate(name string, raidLevel spdktypes.BdevRaidLevel, RaidLevel: raidLevel, StripSizeKb: stripSizeKb, BaseBdevs: baseBdevs, + UUID: uuid, + SuperBlock: superBlock, + DeltaBitmap: deltaBitmap, } cmdOutput, err := c.jsonCli.SendCommand("bdev_raid_create", req) @@ -686,6 +696,60 @@ func (c *Client) BdevRaidGrowBaseBdev(raidName, baseBdevName string) (growed boo return growed, json.Unmarshal(cmdOutput, &growed) } +// BdevRaidGetBaseBdevDeltaMap get the delta bitmap of a faulty base bdev +// +// "baseBdevName": Required. The faulty base bdev name to get the delta bitmap of. +func (c *Client) BdevRaidGetBaseBdevDeltaMap(baseBdevName string) (deltaMap *spdktypes.BdevRaidBaseBdevDeltaMap, err error) { + req := spdktypes.BdevRaidGetBaseBdevDeltaMapRequest{ + BaseName: baseBdevName, + } + + cmdOutput, err := c.jsonCli.SendCommand("bdev_raid_get_base_bdev_delta_bitmap", req) + if err != nil { + return nil, err + } + + deltaMap = &spdktypes.BdevRaidBaseBdevDeltaMap{} + err = json.Unmarshal(cmdOutput, deltaMap) + if err != nil { + return nil, err + } + + return deltaMap, nil +} + +// BdevRaidStopBaseBdevDeltaMap stop the updating of the delta bitmap of a faulty base bdev +// +// "baseBdevName": Required. The faulty base bdev name to stop the delta bitmap of. +func (c *Client) BdevRaidStopBaseBdevDeltaMap(baseBdevName string) (stopped bool, err error) { + req := spdktypes.BdevRaidStopBaseBdevDeltaMapRequest{ + BaseName: baseBdevName, + } + + cmdOutput, err := c.jsonCli.SendCommand("bdev_raid_stop_base_bdev_delta_bitmap", req) + if err != nil { + return false, err + } + + return stopped, json.Unmarshal(cmdOutput, &stopped) +} + +// BdevRaidClearBaseBdevFaultyState clear the faulty state of a base bdev +// +// "baseBdevName": Required. The faulty base bdev name to clear the faulty state of. +func (c *Client) BdevRaidClearBaseBdevFaultyState(baseBdevName string) (cleared bool, err error) { + req := spdktypes.BdevRaidClearBaseBdevFaultyStateRequest{ + BaseName: baseBdevName, + } + + cmdOutput, err := c.jsonCli.SendCommand("bdev_raid_clear_base_bdev_faulty_state", req) + if err != nil { + return false, err + } + + return cleared, json.Unmarshal(cmdOutput, &cleared) +} + // BdevNvmeAttachController constructs NVMe bdev. // // "name": Name of the NVMe controller. And the corresponding bdev nvme name are same as the nvme namespace name, which is `{ControllerName}n1` diff --git a/pkg/spdk/spdk_test.go b/pkg/spdk/spdk_test.go index 9a43349..5cebc83 100644 --- a/pkg/spdk/spdk_test.go +++ b/pkg/spdk/spdk_test.go @@ -302,7 +302,8 @@ func (s *TestSuite) TestSPDKBasic(c *C) { c.Assert(time.Since(start) < time.Minute, Equals, true) raidName := "test-raid" - created, err := spdkCli.BdevRaidCreate(raidName, spdktypes.BdevRaidLevelRaid1, 0, []string{lvolUUID1, lvolUUID2}) + created, err := spdkCli.BdevRaidCreate(raidName, spdktypes.BdevRaidLevelRaid1, 0, []string{lvolUUID1, lvolUUID2}, + "", false, false) c.Assert(err, IsNil) c.Assert(created, Equals, true) defer func() { @@ -562,7 +563,8 @@ func (s *TestSuite) TestSPDKEngineSuspend(c *C) { c.Assert(len(lvolList), Equals, 2) raidName := "test-raid" - created, err := spdkCli.BdevRaidCreate(raidName, spdktypes.BdevRaidLevelRaid1, 0, []string{lvolUUID1, lvolUUID2}) + created, err := spdkCli.BdevRaidCreate(raidName, spdktypes.BdevRaidLevelRaid1, 0, []string{lvolUUID1, lvolUUID2}, + "", false, false) c.Assert(err, IsNil) c.Assert(created, Equals, true) defer func() { diff --git a/pkg/spdk/types/raid.go b/pkg/spdk/types/raid.go index 2645929..def446a 100644 --- a/pkg/spdk/types/raid.go +++ b/pkg/spdk/types/raid.go @@ -37,6 +37,9 @@ type BdevRaidCreateRequest struct { RaidLevel BdevRaidLevel `json:"raid_level"` StripSizeKb uint32 `json:"strip_size_kb"` BaseBdevs []string `json:"base_bdevs"` + UUID string `json:"uuid,omitempty"` + SuperBlock bool `json:"superblock,omitempty"` + DeltaBitmap bool `json:"delta_bitmap,omitempty"` } type BdevRaidDeleteRequest struct { @@ -64,3 +67,20 @@ type BdevRaidGrowBaseBdevRequest struct { RaidName string `json:"raid_name"` BaseName string `json:"base_name"` } + +type BdevRaidGetBaseBdevDeltaMapRequest struct { + BaseName string `json:"base_bdev_name"` +} + +type BdevRaidBaseBdevDeltaMap struct { + RegionSize uint64 `json:"region_size"` + DeltaBitmap string `json:"delta_bitmap"` +} + +type BdevRaidStopBaseBdevDeltaMapRequest struct { + BaseName string `json:"base_bdev_name"` +} + +type BdevRaidClearBaseBdevFaultyStateRequest struct { + BaseName string `json:"base_bdev_name"` +}