Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZFS: Add log, spare & dedup vdev types, support multiple special vdevs, fix bug with mixed vdev types #883

Merged
merged 7 commits into from
Nov 20, 2024

Conversation

MaienM
Copy link
Contributor

@MaienM MaienM commented Nov 18, 2024

This adds support for the missing categories of devices: log, spare, and dedup.

log & dedup can each have multiple vdevs assigned (the workload will be load-balanced over these), so these accept a list of vdev configurations. This is actually also true for special, but the existing implementation only supported a single vdev. This has been updated to accept either a list of vdevs (like the other two), or a single vdev (for backwards compatibility).

spare (like cache) just takes a list of device names, neither type supports more complicated vdevs like mirrors.


While testing this I ran into a bug that affected all types which support having multiple vdevs (which includes the regular data vdevs). The following topology config:

{
  vdev = [
    {
      mode = "mirror";
      members = [ "data1" "data2" ];
    }
    {
      members = [ "data3" ];
    }
  ];
}

would result in the following command:

zpool create -f <name> mirror /dev/data1 /dev/data2 /dev/data3

which would result in a single vdev with a 3-way mirror, rather than a vdev with a 2-way mirror and a second vdev with a single disk. As far as I could find there is no keyword to indicate "mirror config ended, next is a vdev made up of a single disk" (which kinda makes sense given that ZFS would reject such a setup without the -f flag), so to fix this I added a sort so that the vdevs with an empty mode are moved to the start. This means the above config will now result in the following command:

zpool create -f <name> /dev/data3 mirror /dev/data1 /dev/data2

(An alternative would have been to instead generate a zpool add command for each vdev, but that would be a larger change, and we'd need to start handling partial successes so I opted not to at this point. Doing that would also be a step towards handing making changes to an existing pool such as adding a vdev, so it might be worth considering at some point.)

I extended the zfs-with-vdevs example to have this 3-device setup for each of the types that support it so that this is tested, which results in the following pool (which is also validated in the tests):

  pool: zroot
 state: ONLINE
config:

        NAME                   STATE     READ WRITE CKSUM
        zroot                  ONLINE       0     0     0
          disk-data3-zfs       ONLINE       0     0     0
          mirror-1             ONLINE       0     0     0
            disk-data1-zfs     ONLINE       0     0     0
            disk-data2-zfs     ONLINE       0     0     0
        dedup   
          disk-dedup3-zfs      ONLINE       0     0     0
          mirror-5             ONLINE       0     0     0
            disk-dedup1-zfs    ONLINE       0     0     0
            disk-dedup2-zfs    ONLINE       0     0     0
        special 
          disk-special3-zfs    ONLINE       0     0     0
          mirror-7             ONLINE       0     0     0
            disk-special1-zfs  ONLINE       0     0     0
            disk-special2-zfs  ONLINE       0     0     0
        logs    
          disk-log3-zfs        ONLINE       0     0     0
          mirror-3             ONLINE       0     0     0
            disk-log1-zfs      ONLINE       0     0     0
            disk-log2-zfs      ONLINE       0     0     0
        cache
          disk-cache-zfs       ONLINE       0     0     0
        spares
          disk-spare-zfs       AVAIL   

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
The type keyword was included before every vdev:

```shell
zpool create -f <name> /dev/sda log mirror /dev/sdb /dev/sdc log mirror /dev/sdd /dev/sde
```

but this is incorrect and should instead be:

```shell
zpool create -f <name> /dev/sda log mirror /dev/sdb /dev/sdc mirror /dev/sdd /dev/sde
```
A config like

```nix
{
  vdev = [
    {
      mode = "mirror";
      members = [ "data1" "data2" ];
    }
    {
      members = [ "data3" ];
    }
  ];
}
```

would result in the following command:

```shell
zpool create -f <name> mirror /dev/data1 /dev/data2 /dev/data3
```

which would result in a single vdev with a 3-way mirror, rather than a
vdev with a 2-way mirror and a second vdev with a single disk. By
reordering the vdevs to handle those with an empty mode first we
transform this into:

```shell
zpool create -f <name> /dev/data3 mirror /dev/data1 /dev/data2
```

which does have the desired outcome.
Copy link
Contributor

@iFreilicht iFreilicht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really good! I have a few small notes, but in general, this looks very mergeable 👍

@iFreilicht iFreilicht self-assigned this Nov 19, 2024
@iFreilicht
Copy link
Contributor

@mergify queue

Copy link
Contributor

mergify bot commented Nov 20, 2024

queue

☑️ The pull request will automatically be requeued

Merge queue reset: an external action moved the base branch head to c3b83db

@Mic92 Mic92 merged commit a0c384e into nix-community:master Nov 20, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants