Skip to content

Preserve XFS quota options in temporary mounts #1132

Merged
vojtechtrefny merged 2 commits into
storaged-project:masterfrom
vojtechtrefny:master_xfs-mount-quota
Oct 8, 2025
Merged

Preserve XFS quota options in temporary mounts #1132
vojtechtrefny merged 2 commits into
storaged-project:masterfrom
vojtechtrefny:master_xfs-mount-quota

Conversation

@vojtechtrefny
Copy link
Copy Markdown
Member

Originally reported against LVM and their fsresize helper script: lvmteam/lvm2#182

libmount logs only when debug is enabled so we get no logs for
mount and unmount calls.
We are now using FS plugin in blivet and having the mounting
logged is useful for debugging.
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @vojtechtrefny, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue where XFS quota settings were not maintained during temporary filesystem mounts, which could lead to unexpected behavior, especially during operations like resizing. It implements a mechanism to dynamically read existing XFS quota configurations and apply them to temporary mounts, ensuring consistent filesystem behavior. The changes also include improved logging for mount operations and updated tests to validate the new functionality.

Highlights

  • XFS Quota Preservation: Introduced logic to detect and preserve XFS quota mount options (user, group, project quotas, and their enforcement status) when performing temporary mounts, addressing an issue where these options were lost.
  • New xfs_quota_mount_options Function: Added a new static function xfs_quota_mount_options in src/plugins/fs/generic.c that uses xfs_db to read the quota flags from an XFS filesystem's superblock and construct the appropriate mount options string.
  • Enhanced Mount Logging: Added detailed logging for mount and unmount operations in src/plugins/fs/mount.c, including the device, filesystem type, mountpoint, and the specific options used for mounting, which aids in debugging and verification.
  • Updated Test Suite: Modified the Python test suite to support passing custom mount options to the mounted context manager and added a new test case for XFS resize operations that verifies the preservation of quota options by checking the log output.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adds functionality to preserve XFS quota options during temporary mounts, which is a valuable improvement. The implementation is mostly solid, and the accompanying tests cover the new functionality well. I've identified a few areas for improvement regarding code style, test correctness, and security best practices in the test suite. My comments are detailed below.

self.assertEqual(fi.block_size * fi.block_count, 450 * 1024**2)

# quota options should be preserved during temp mount
self.assertIn("with options: uquota,gquota,pquota", self.log)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

This assertion is likely to fail. The log message will include other mount options like nosuid and nodev appended to the quota options, so the full string will be something like ... with options: uquota,gquota,pquota,nosuid,nodev. The substring you're checking for won't be found.

To make the test more robust and accurate, you should check for the presence of each quota option individually.

Suggested change
self.assertIn("with options: uquota,gquota,pquota", self.log)
self.assertIn("with options:", self.log)
self.assertIn("uquota", self.log)
self.assertIn("gquota", self.log)
self.assertIn("pquota", self.log)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Well, almost ;-)

Comment thread src/plugins/fs/generic.c Outdated
Comment thread tests/utils.py
Comment on lines +759 to 772
def mount(device, where, ro=False, options=None):
if not os.path.isdir(where):
os.makedirs(where)

if ro:
os.system("mount -oro %s %s" % (device, where))
if options:
options += ",ro"
else:
options = "ro"

if options:
os.system("mount -o %s %s %s" % (options, device, where))
else:
os.system("mount %s %s" % (device, where))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using os.system with string formatting is vulnerable to shell injection. While this is test code, it's a good practice to use safer alternatives. I recommend refactoring this function to use subprocess.run with a list of arguments, which avoids the shell and is more secure.

def mount(device, where, ro=False, options=None):
    if not os.path.isdir(where):
        os.makedirs(where)

    mount_cmd = ["mount"]
    if ro:
        if options:
            options += ",ro"
        else:
            options = "ro"

    if options:
        mount_cmd.extend(["-o", options])

    mount_cmd.extend([device, where])
    # Using subprocess.run is safer than os.system with string formatting.
    # The original implementation ignored the return code, so we do the same.
    subprocess.run(mount_cmd)

If XFS was previously mounted with the quota options and then
we are mounting it for resize, the quota mount options need to be
preserved or XFS would need to recheck the quotas during the next
mount which may take a long time, depending on filesystem size.
@vojtechtrefny vojtechtrefny force-pushed the master_xfs-mount-quota branch from 9c530e1 to 10b3cdf Compare October 8, 2025 05:48
Copy link
Copy Markdown
Member

@tbzatek tbzatek left a comment

Choose a reason for hiding this comment

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

Sounds rather complex

@vojtechtrefny
Copy link
Copy Markdown
Member Author

Sounds rather complex

Sounds like a really bad design in XFS, but we can't do anything about that...

@vojtechtrefny vojtechtrefny merged commit 6ada640 into storaged-project:master Oct 8, 2025
44 of 46 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.

2 participants