Skip to content

Disk (Linux): Don't mark / as read-only in Fedora Atomic #1762

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

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

ledif
Copy link

@ledif ledif commented May 17, 2025

Fedora Atomic and its derivatives such as Bazzite use a mix of composefs for the system mount and btrfs for variable read-write data. The composefs mount is correctly marked as read-only but the btrfs partition is also marked as read-only because the partition is mounted in several different places with a mix of read-write and read-only.

As an example:

/dev/nvme1n1p3 /sysroot btrfs ro,seclabel,relatime,ssd,discard=async,space_cache=v2,subvolid=258,subvol=/root 0 0
/dev/nvme1n1p3 /etc btrfs rw,seclabel,relatime,ssd,discard=async,space_cache=v2,subvolid=258,subvol=/root 0 0
/dev/nvme1n1p3 /sysroot/ostree/deploy/default/var btrfs rw,seclabel,relatime,ssd,discard=async,space_cache=v2,subvolid=258,subvol=/root 0 0
/dev/nvme1n1p3 /var btrfs rw,seclabel,noatime,ssd,discard=async,space_cache=v2,subvolid=256,subvol=/var 0 0
/dev/nvme1n1p3 /var/home btrfs rw,seclabel,noatime,ssd,discard=async,space_cache=v2,subvolid=257,subvol=/home 0 0

The main btrfs partition should not be considered read-only because it happens to contain a read-only subvolume. This PR enhances the read-only detection logic to see if any of the mounts for the same device are read-write and if so mark the whole device as read-write.

Screenshots

Current default Bazzite fastfetch:

Screenshot_20250517_093613

Bazzite's fastfetch with the read-only mounts hidden. Notice that it hides both the composefs mount (which we want to hide) and the main btrfs mount (which we do not want to hide):
Screenshot_20250517_093557

Bazzite's fastfetch with this patch and read-only mounts hidden. Notice the main btrfs mount is there as expected:

Screenshot_20250517_102653

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adjusts read-only detection for Btrfs mounts on Fedora Atomic systems by checking all mount points for a device before marking it as read-only, preventing the main Btrfs partition from being hidden when only one subvolume is ro.

  • Added isReadOnly() helper that scans /proc/mounts for R/W instances of the same Btrfs device
  • Switched detectType() to use isReadOnly() instead of a direct ro option check
Comments suppressed due to low confidence (1)

src/detection/disk/disk_linux.c:221

  • Introduce unit tests for isReadOnly(), especially to verify behavior when the same Btrfs device has both read-only and read-write mounts.
static bool isReadOnly(FFDisk* currentDisk, struct mntent* device)

return false;

// For BTRFS on Fedora Atomic, check if there are other R/W mount points for the same device
if (ffStrbufEqualS(&currentDisk->filesystem, "btrfs"))
Copy link
Preview

Copilot AI May 18, 2025

Choose a reason for hiding this comment

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

[nitpick] Avoid using the literal string "btrfs"; consider defining a constant or using an enum for filesystem types to improve readability and reduce risk of typos.

Suggested change
if (ffStrbufEqualS(&currentDisk->filesystem, "btrfs"))
if (ffStrbufEqualS(&currentDisk->filesystem, FILESYSTEM_BTRFS))

Copilot uses AI. Check for mistakes.

Comment on lines +230 to +245
FILE* mountsFile = setmntent("/proc/mounts", "r");
if (mountsFile != NULL)
{
struct mntent* otherDev;
while ((otherDev = getmntent(mountsFile)))
{
// If same device but not read-only, then this device has R/W access
if (ffStrEquals(otherDev->mnt_fsname, deviceName) &&
!hasmntopt(otherDev, MNTOPT_RO))
{
endmntent(mountsFile);
return false;
}
}
endmntent(mountsFile);
}
Copy link
Preview

Copilot AI May 18, 2025

Choose a reason for hiding this comment

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

[nitpick] Opening and scanning /proc/mounts on every call could add I/O overhead; consider caching the mounts list once per scan or reusing the open file between disk checks.

Suggested change
FILE* mountsFile = setmntent("/proc/mounts", "r");
if (mountsFile != NULL)
{
struct mntent* otherDev;
while ((otherDev = getmntent(mountsFile)))
{
// If same device but not read-only, then this device has R/W access
if (ffStrEquals(otherDev->mnt_fsname, deviceName) &&
!hasmntopt(otherDev, MNTOPT_RO))
{
endmntent(mountsFile);
return false;
}
}
endmntent(mountsFile);
}
static struct mntent** cachedMounts = NULL;
static size_t cachedMountsCount = 0;
if (cachedMounts == NULL)
{
FILE* mountsFile = setmntent("/proc/mounts", "r");
if (mountsFile != NULL)
{
struct mntent* entry;
size_t count = 0;
while ((entry = getmntent(mountsFile)))
count++;
rewind(mountsFile);
cachedMounts = malloc(count * sizeof(struct mntent*));
cachedMountsCount = count;
count = 0;
while ((entry = getmntent(mountsFile)))
{
cachedMounts[count] = malloc(sizeof(struct mntent));
*cachedMounts[count] = *entry;
count++;
}
endmntent(mountsFile);
}
}
for (size_t i = 0; i < cachedMountsCount; i++)
{
struct mntent* otherDev = cachedMounts[i];
// If same device but not read-only, then this device has R/W access
if (ffStrEquals(otherDev->mnt_fsname, deviceName) &&
!hasmntopt(otherDev, MNTOPT_RO))
{
return false;
}
}

Copilot uses AI. Check for mistakes.

@CarterLi
Copy link
Member

Please upload your /proc/mounts

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.

2 participants