Skip to content

'btrfs' command output: ERROR: cannot create subvolume: Read-only file system #923

@ErmakovDmitriy

Description

@ErmakovDmitriy

Hi!
I am sorry in advance, if this is not the correct repository to open an issue for my problem.

I am testing Elemental operator on VMs (they are not in any way controlled by Rancher, so they can be considered physical hosts, I suppose).

The initial provisioning works well.
After several (about 4 updates of the OS image), the update Pod starts failing with an error 'btrfs' command output: ERROR: cannot create subvolume: Read-only file system.

It is reproducible in a sense that as soon as it starts, it happens on all the machines in my test cluster (3 machines).

This is my UpdateGroup Elemental resource I used to update machines. Every time, I did a change in osImage field:

apiVersion: elemental.cattle.io/v1beta1
kind: ManagedOSImage
metadata:
  name: gotoleap
  namespace: fleet-default
spec:
  clusterTargets:
    - clusterName: elemental-test-2
  drain:
    deleteLocalData: true
    force: true
    ignoreDaemonSets: true
    skipWaitForDeleteTimeout: 60
  osImage: example.com/elemental/base-os/leap:master-f96725e1
status:
  conditions:
    - lastTransitionTime: '2025-07-18T11:52:27Z'
      message: ''
      reason: FleetBundleCreateSuccess
      status: 'True'
      type: FleetBundleCreation
    - lastTransitionTime: '2025-08-18T15:16:44Z'
      message: ''
      reason: UnknownReason
      status: 'True'
      type: Ready

Before the update, the machines are running Linux: Linux 6.4.0-150600.23.53-default #1 SMP PREEMPT_DYNAMIC Wed Jun 4 05:37:40 UTC 2025 (2d991ff) x86_64 x86_64 x86_64 GNU/Linux and OpenSUSE Leap 15.6.

Elemental version: 2.2.1
Elemental Operator version: 106.0.1+up1.6.9
Elemental Toolkit version: 2.2.5

Error message:

Defaulted container "upgrade" out of: upgrade, drain (init)
+ HOST_DIR=/host
+ RELEASE_FILE=/etc/os-release
+ CONF_FILE=/run/data/cloud-config
+ LOCK_TIMEOUT=600
+ LOCK_FILE=/host/run/elemental/upgrade.lock
+ mkdir -p /host/run/elemental
+ flock -w 600 200
++ nsenter -i -m -t 1 -- systemctl is-system-running
+ SYSSTATUS=running
+ isEqualVersion
+ diff /etc/os-release /host/etc/os-release
+ return 1
+ '[' '' '!=' true ']'
+ '[' '' '!=' true ']'
+ isHigherVersion
++ . /etc/os-release
+++ NAME='openSUSE Leap'
+++ VERSION=15.6
+++ ID=opensuse-leap
+++ ID_LIKE='suse opensuse'
+++ VERSION_ID=15.6
+++ PRETTY_NAME='openSUSE Leap 15.6'
+++ ANSI_COLOR='0;32'
+++ CPE_NAME=cpe:/o:opensuse:leap:15.6
+++ BUG_REPORT_URL=https://bugs.opensuse.org
+++ HOME_URL=https://www.opensuse.org/
+++ DOCUMENTATION_URL=https://en.opensuse.org/Portal:Leap
+++ LOGO=distributor-logo-Leap
+++ TIMESTAMP=20250818145852
+++ GRUB_ENTRY_NAME='Elemental Dev'
++ printf '%s\n' ''
+ local img_ver=
++ . /etc/os-release
+++ NAME='openSUSE Leap'
+++ VERSION=15.6
+++ ID=opensuse-leap
+++ ID_LIKE='suse opensuse'
+++ VERSION_ID=15.6
+++ PRETTY_NAME='openSUSE Leap 15.6'
+++ ANSI_COLOR='0;32'
+++ CPE_NAME=cpe:/o:opensuse:leap:15.6
+++ BUG_REPORT_URL=https://bugs.opensuse.org
+++ HOME_URL=https://www.opensuse.org/
+++ DOCUMENTATION_URL=https://en.opensuse.org/Portal:Leap
+++ LOGO=distributor-logo-Leap
+++ TIMESTAMP=20250818145852
+++ GRUB_ENTRY_NAME='Elemental Dev'
++ printf '%s\n' ''
+ local img_repo=
++ . /host/etc/os-release
+++ NAME='openSUSE Leap'
+++ VERSION=15.6
+++ ID=opensuse-leap
+++ ID_LIKE='suse opensuse'
+++ VERSION_ID=15.6
+++ PRETTY_NAME='openSUSE Leap 15.6'
+++ ANSI_COLOR='0;32'
+++ CPE_NAME=cpe:/o:opensuse:leap:15.6
+++ BUG_REPORT_URL=https://bugs.opensuse.org
+++ HOME_URL=https://www.opensuse.org/
+++ DOCUMENTATION_URL=https://en.opensuse.org/Portal:Leap
+++ LOGO=distributor-logo-Leap
+++ TIMESTAMP=20250819144550
+++ GRUB_ENTRY_NAME='Elemental OpenSUSE'
++ printf '%s\n' ''
+ local host_ver=
++ . /host/etc/os-release
+++ NAME='openSUSE Leap'
+++ VERSION=15.6
+++ ID=opensuse-leap
+++ ID_LIKE='suse opensuse'
+++ VERSION_ID=15.6
+++ PRETTY_NAME='openSUSE Leap 15.6'
+++ ANSI_COLOR='0;32'
+++ CPE_NAME=cpe:/o:opensuse:leap:15.6
+++ BUG_REPORT_URL=https://bugs.opensuse.org
+++ HOME_URL=https://www.opensuse.org/
+++ DOCUMENTATION_URL=https://en.opensuse.org/Portal:Leap
+++ LOGO=distributor-logo-Leap
+++ TIMESTAMP=20250819144550
+++ GRUB_ENTRY_NAME='Elemental OpenSUSE'
++ printf '%s\n' ''
+ local host_repo=
+ local higher_ver
+ '[' '' '!=' '' ']'
+ '[' -z '' ']'
+ return 0
+ config
+ '[' '!' -s /run/data/cloud-config ']'
+ '[' -e /host/oem/90_operator.yaml ']'
+ return 0
+ mount --rbind /host/dev /dev
+ mount --rbind /host/run /run
+ '[' '' = true ']'
+ '[' '' = true ']'
+ elemental --debug upgrade --bootloader --system dir:/
DEBU[2025-08-20T06:13:03Z] Starting elemental version  on commit        
INFO[2025-08-20T06:13:03Z] Reading configuration from '/etc/elemental'  
DEBU[2025-08-20T06:13:03Z] Full config loaded: &types.RunConfig{
  Reboot: false,
  PowerOff: false,
  EjectCD: false,
  Snapshotter: types.SnapshotterConfig{
    Type: "btrfs",
    MaxSnaps: 4,
    Config: &types.BtrfsConfig{},
  },
  Config: types.Config{
    Logger: &types.logrusWrapper{ // p0
      Logger: &logrus.Logger{
        Out: &os.File{},
        Hooks: logrus.LevelHooks{},
        Formatter: &logrus.TextFormatter{
          ForceColors: true,
          DisableColors: false,
          ForceQuote: false,
          DisableQuote: false,
          EnvironmentOverrideColors: false,
          DisableTimestamp: false,
          FullTimestamp: true,
          TimestampFormat: "",
          DisableSorting: false,
          SortingFunc: ,
          DisableLevelTruncation: false,
          PadLevelText: false,
          QuoteEmptyFields: false,
          FieldMap: logrus.FieldMap(nil),
          CallerPrettyfier: ,
        },
        ReportCaller: false,
        Level: 5,
        ExitFunc: os.Exit,
        BufferPool: nil,
      },
    },
    Fs: &vfs.osfs{}, // p1
    Mounter: &mount.Mounter{},
    Runner: &types.RealRunner{ // p2
      Logger: p0,
    },
    Syscall: &types.RealSyscall{},
    CloudInitRunner: &cloudinit.YipCloudInitRunner{},
    ImageExtractor: types.OCIImageExtractor{},
    Client: &http.Client{},
    Platform: &types.Platform{
      OS: "linux",
      Arch: "x86_64",
      GolangArch: "amd64",
    },
    Cosign: false,
    Verify: false,
    TLSVerify: true,
    CosignPubKey: "",
    LocalImage: false,
    Arch: "",
    SquashFsCompressionConfig: []string{
      "-no-compression",
    },
    SquashFsNoCompression: true,
    CloudInitPaths: []string{
      "/system/oem",
      "/oem/",
      "/usr/local/cloud-config/",
    },
    Strict: false,
  },
} 
DEBU[2025-08-20T06:13:03Z] Loaded upgrade UpgradeSpec: &types.UpgradeSpec{
  RecoveryUpgrade: false,
  System: &types.ImageSource{},
  RecoverySystem: types.Image{
    File: "/run/elemental/recovery/boot-transition/recovery.img",
    Label: "",
    Size: 0,
    FS: "squashfs",
    Source: &types.ImageSource{},
    MountPoint: "/run/elemental/transition",
    LoopDevice: "",
  },
  GrubDefEntry: "",
  BootloaderUpgrade: true,
  SnapshotLabels: types.KeyValuePair(nil),
  Partitions: types.ElementalPartitions{
    BIOS: nil,
    Boot: &types.Partition{
      Name: "efi",
      FilesystemLabel: "COS_GRUB",
      Size: 64,
      FS: "vfat",
      Flags: nil,
      MountPoint: "/host/run/elemental/efi",
      Path: "/dev/sda1",
      Disk: "/dev/sda",
    },
    OEM: &types.Partition{
      Name: "oem",
      FilesystemLabel: "COS_OEM",
      Size: 64,
      FS: "ext4",
      Flags: nil,
      MountPoint: "/host/oem",
      Path: "/dev/sda2",
      Disk: "/dev/sda",
    },
    Recovery: &types.Partition{
      Name: "recovery",
      FilesystemLabel: "COS_RECOVERY",
      Size: 4096,
      FS: "ext4",
      Flags: nil,
      MountPoint: "/run/elemental/recovery",
      Path: "/dev/sda3",
      Disk: "/dev/sda",
    },
    State: &types.Partition{
      Name: "state",
      FilesystemLabel: "COS_STATE",
      Size: 8192,
      FS: "btrfs",
      Flags: nil,
      MountPoint: "/host",
      Path: "/dev/sda4",
      Disk: "/dev/sda",
    },
    Persistent: &types.Partition{
      Name: "persistent",
      FilesystemLabel: "COS_PERSISTENT",
      Size: 53118,
      FS: "ext4",
      Flags: nil,
      MountPoint: "/host/etc/iscsi",
      Path: "/dev/sda5",
      Disk: "/dev/sda",
    },
  },
  State: &types.InstallState{
    Date: "2025-08-19T14:54:16Z",
    Partitions: map[string]*types.PartitionState{
      "efi": &types.PartitionState{
        FSLabel: "COS_GRUB",
        RecoveryImage: nil,
        Snapshots: map[int]*types.SystemState(nil), // p0
      },
      "oem": &types.PartitionState{
        FSLabel: "COS_OEM",
        RecoveryImage: nil,
        Snapshots: p0,
      },
      "persistent": &types.PartitionState{
        FSLabel: "COS_PERSISTENT",
        RecoveryImage: nil,
        Snapshots: p0,
      },
      "recovery": &types.PartitionState{
        FSLabel: "COS_RECOVERY",
        RecoveryImage: &types.SystemState{
          Source: &types.ImageSource{},
          Digest: "",
          Active: false,
          Label: "",
          FS: "squashfs",
          Labels: map[string]string(nil), // p1
          Date: "",
          FromAction: "",
        },
        Snapshots: p0,
      },
      "state": &types.PartitionState{
        FSLabel: "COS_STATE",
        RecoveryImage: nil,
        Snapshots: map[int]*types.SystemState{
          1: &types.SystemState{
            Source: &types.ImageSource{},
            Digest: "",
            Active: false,
            Label: "",
            FS: "",
            Labels: p1,
            Date: "",
            FromAction: "",
          },
          2: &types.SystemState{
            Source: &types.ImageSource{},
            Digest: "",
            Active: false,
            Label: "",
            FS: "",
            Labels: p1,
            Date: "2025-08-18T18:13:29Z",
            FromAction: "upgrade",
          },
          3: &types.SystemState{
            Source: &types.ImageSource{},
            Digest: "",
            Active: false,
            Label: "",
            FS: "",
            Labels: p1,
            Date: "2025-08-19T13:29:35Z",
            FromAction: "upgrade",
          },
          4: &types.SystemState{
            Source: &types.ImageSource{},
            Digest: "",
            Active: false,
            Label: "",
            FS: "",
            Labels: p1,
            Date: "2025-08-19T14:21:04Z",
            FromAction: "upgrade",
          },
          5: &types.SystemState{
            Source: &types.ImageSource{},
            Digest: "",
            Active: true,
            Label: "",
            FS: "",
            Labels: p1,
            Date: "2025-08-19T14:54:16Z",
            FromAction: "upgrade",
          },
        },
      },
    },
    Snapshotter: types.SnapshotterConfig{
      Type: "btrfs",
      MaxSnaps: 4,
      Config: &types.BtrfsConfig{},
    },
  },
} 
INFO[2025-08-20T06:13:03Z] Upgrade called                               
DEBU[2025-08-20T06:13:03Z] Running cmd: 'findmnt -fno OPTIONS /host/run/elemental/efi' 
DEBU[2025-08-20T06:13:03Z] Mounting partition COS_GRUB                  
DEBU[2025-08-20T06:13:03Z] Mounting partition COS_RECOVERY              
DEBU[2025-08-20T06:13:03Z] Running cmd: 'findmnt -fno OPTIONS /host/etc/iscsi' 
DEBU[2025-08-20T06:13:03Z] Already RW mounted: persistent at /host/etc/iscsi 
INFO[2025-08-20T06:13:03Z] Initiate btrfs snapshotter at /host          
DEBU[2025-08-20T06:13:03Z] Checking if essential subvolumes are already created 
DEBU[2025-08-20T06:13:03Z] Running cmd: 'btrfs subvolume list --sort=path /host' 
DEBU[2025-08-20T06:13:03Z] Looking for subvolume ids 257 and 258 in subvolume list: [{@ 256} {@/.snapshots 257} {@/.snapshots/2/snapshot 259} {@/.snapshots/3/snapshot 260} {@/.snapshots/4/snapshot 261} {@/.snapshots/5/snapshot 262}] 
DEBU[2025-08-20T06:13:03Z] Running initial btrfs configuration          
DEBU[2025-08-20T06:13:03Z] Enabling btrfs quota                         
DEBU[2025-08-20T06:13:03Z] Running cmd: 'btrfs quota enable /host'      
DEBU[2025-08-20T06:13:03Z] Creating essential subvolumes                
DEBU[2025-08-20T06:13:03Z] Creating subvolume: /host/@                  
DEBU[2025-08-20T06:13:03Z] Running cmd: 'btrfs subvolume create /host/@' 
DEBU[2025-08-20T06:13:03Z] 'btrfs' command reported an error: exit status 1 
DEBU[2025-08-20T06:13:03Z] 'btrfs' command output: ERROR: cannot create subvolume: Read-only file system
Create subvolume '/host/@' 
ERRO[2025-08-20T06:13:03Z] failed creating subvolume /host/@: ERROR: cannot create subvolume: Read-only file system
Create subvolume '/host/@' 
ERRO[2025-08-20T06:13:03Z] failed initializing snapshotter              
DEBU[2025-08-20T06:13:03Z] Unmounting partition COS_RECOVERY            
DEBU[2025-08-20T06:13:03Z] Mounting partition COS_GRUB                  
ERRO[2025-08-20T06:13:03Z] upgrade command failed: 1 error occurred:
	* exit status 1

mounts on the host (I removed all the lines with tmpfs' and running container mounts):

w-v-suse-micro-0:~ # mount | grep -v /run/k3s/containerd/io.containerd.runtime.v2.task/
/dev/sda4 on / type btrfs (ro,relatime,space_cache=v2,subvolid=262,subvol=/@/.snapshots/5/snapshot)
/dev/sda2 on /oem type ext4 (rw,relatime)
overlay on /etc type overlay (rw,relatime,lowerdir=/sysroot/etc,upperdir=/run/elemental/overlay/etc.overlay/upper,workdir=/run/elemental/overlay/etc.overlay/work)
overlay on /var type overlay (rw,relatime,lowerdir=/sysroot/var,upperdir=/run/elemental/overlay/var.overlay/upper,workdir=/run/elemental/overlay/var.overlay/work)
overlay on /srv type overlay (rw,relatime,lowerdir=/sysroot/srv,upperdir=/run/elemental/overlay/srv.overlay/upper,workdir=/run/elemental/overlay/srv.overlay/work)
/dev/sda5 on /home type ext4 (rw,relatime)
/dev/sda5 on /root type ext4 (rw,relatime)
/dev/sda5 on /opt type ext4 (rw,relatime)
/dev/sda5 on /usr/libexec type ext4 (rw,relatime)
/dev/sda5 on /var/log type ext4 (rw,relatime)
/dev/sda5 on /etc/iscsi type ext4 (rw,relatime)
/dev/sda5 on /etc/ssh type ext4 (rw,relatime)
/dev/sda5 on /etc/rancher type ext4 (rw,relatime)
/dev/sda5 on /etc/systemd type ext4 (rw,relatime)
/dev/sda5 on /usr/local type ext4 (rw,relatime)
/dev/sda5 on /etc/cni type ext4 (rw,relatime)
/dev/sda5 on /var/lib/elemental type ext4 (rw,relatime)
/dev/sda5 on /var/lib/rancher type ext4 (rw,relatime)
/dev/sda5 on /var/lib/kubelet type ext4 (rw,relatime)
/dev/sda5 on /var/lib/NetworkManager type ext4 (rw,relatime)
/dev/sda5 on /var/lib/cni type ext4 (rw,relatime)
/dev/sda5 on /var/lib/calico type ext4 (rw,relatime)

Also, I noticed that a newly deployed system has a snapshot with ID 258 while after 4 upgrades it disappears:

After upgrades:

btrfs subvolume list /
ID 256 gen 86 top level 5 path @
ID 257 gen 91 top level 256 path @/.snapshots
ID 259 gen 34 top level 257 path @/.snapshots/2/snapshot
ID 260 gen 52 top level 257 path @/.snapshots/3/snapshot
ID 261 gen 73 top level 257 path @/.snapshots/4/snapshot
ID 262 gen 82 top level 257 path @/.snapshots/5/snapshot

New system:

ID 256 gen 99 top level 5 path @
ID 257 gen 101 top level 256 path @/.snapshots
ID 258 gen 17 top level 257 path @/.snapshots/1/snapshot

I see that there is a function which checks the snapshot ID in version 2.2.5: https://github.com/rancher/elemental-toolkit/blob/v2.2.5/pkg/snapshotter/btrfs.go#L38 and https://github.com/rancher/elemental-toolkit/blob/v2.2.5/pkg/snapshotter/btrfs.go#L526

This function is called in this context during upgrade: https://github.com/rancher/elemental-toolkit/blob/v2.2.5/pkg/snapshotter/btrfs.go#L147
and from the logs, I suspect that the absence of the snapshot 258 causes the isInitiated to return false => setBtrfsForFirstTime (https://github.com/rancher/elemental-toolkit/blob/v2.2.5/pkg/snapshotter/btrfs.go#L160) is called and fails.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions