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

Implement default user/group/project quotas including object quotas #17130

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

ixhamza
Copy link
Member

@ixhamza ixhamza commented Mar 10, 2025

Motivation and Context

This change implements default quotas for users, groups, and projects (including object quotas) by extending concepts from Solaris' Default Quotas feature. These defaults guarantee consistent quota enforcement when no per-ID limits are set while ensuring compatibility with existing tools and workflows. This PR is inspired by enhancements proposed in PR #16283.
Fixes: #5431.

Description

This change adds default quota properties to MASTER_NODE_OBJ, similar to per-ID specific quotas. The functions zfs_id_overobjquota() and zfs_id_overblockquota() have been updated to enforce default limits when no specific per-ID quotas are set. Kernel interfaces for FreeBSD (user/group quotas) and Linux (project quotas) now reflect default quotas to maintain consistency between visibility and configured limits. The zfs userspace, zfs groupspace, and zfs projectspace commands display default quotas when no per-ID quotas exist. Newly added tests take motivation from existing per-ID quota tests.

How Has This Been Tested?

  • CI Testing.
  • All newly added tests for default quota enforcement and visibility pass successfully.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

@amotin amotin added the Status: Code Review Needed Ready for review and testing label Mar 10, 2025
@ixhamza ixhamza force-pushed the NAS-131289 branch 2 times, most recently from 824f8e8 to 1a5b6e9 Compare March 10, 2025 18:15
@tonyhutter
Copy link
Contributor

@ixhamza sorry I've dropped the ball on reviewing this. I'll take a look at it this week.

@tonyhutter
Copy link
Contributor

I did a test where I set defaultuserquota=150M on my pool and tried filling it up and emptying it:

$ for i in {1..20} ; do echo "### $i ###" && dd if=/dev/zero of=/tank2/bigfile bs=128k || true && rm /tank2/bigfile || true && sleep 1 ; done
### 1 ###
dd: error writing '/tank2/bigfile': Disk quota exceeded
1288+0 records in
1287+0 records out
168689664 bytes (169 MB, 161 MiB) copied, 0.255531 s, 660 MB/s
### 2 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 3 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 4 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 5 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 6 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 7 ###
dd: error writing '/tank2/bigfile': Disk quota exceeded
1424+0 records in
1423+0 records out
186515456 bytes (187 MB, 178 MiB) copied, 0.272697 s, 684 MB/s
### 8 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 9 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 10 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 11 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 12 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 13 ###
dd: error writing '/tank2/bigfile': Disk quota exceeded
1413+0 records in
1412+0 records out
185073664 bytes (185 MB, 176 MiB) copied, 0.260325 s, 711 MB/s
### 14 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 15 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 16 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 17 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 18 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory
### 19 ###
dd: error writing '/tank2/bigfile': Disk quota exceeded
1413+0 records in
1412+0 records out
185073664 bytes (185 MB, 176 MiB) copied, 0.279114 s, 663 MB/s
### 20 ###
dd: failed to open '/tank2/bigfile': Disk quota exceeded
rm: cannot remove '/tank2/bigfile': No such file or directory

It appears that if you delete a file, it doesn't adjust your quota until a few seconds later when the TXG finishes.

The 150MB quota I set was exceeded in all my test runs:
168689664 bytes (169 MB, 161 MiB) copied, 0.262633 s, 642 MB/s
186515456 bytes (187 MB, 178 MiB) copied, 0.29219 s, 638 MB/s
185073664 bytes (185 MB, 176 MiB) copied, 0.295984 s, 625 MB/s
161873920 bytes (162 MB, 154 MiB) copied, 0.205296 s, 788 MB/s

Setting a defaultuserquota=1M was also exceeded:
37355520 bytes (37 MB, 36 MiB) copied, 0.067977 s, 550 MB/s
35258368 bytes (35 MB, 34 MiB) copied, 0.073229 s, 481 MB/s
35389440 bytes (35 MB, 34 MiB) copied, 0.073754 s, 480 MB/s

So quotas seem to be best effort rather than 100% strict, which is probably fine.

Setting defaultuserquota=0 seemed to disable quotas. This should be documented in the man pages.

Setting copies=2 was correctly accounted for in the quota. 👍

Writing huge xattrs to lots of zero byte files was correctly accounted for in the quota. 👍

@ixhamza
Copy link
Member Author

ixhamza commented Mar 27, 2025

So quotas seem to be best effort rather than 100% strict, which is probably fine.

Yeah, I observed similar behaviour for non-default user quotas as well.

ixhamza and others added 7 commits March 28, 2025 01:36
This adds default userquota, groupquota, and projectquota properties to
MASTER_NODE_OBJ to make them accessible during zfsvfs_init() (regular
DSL properties require dsl_config_lock, which cannot be safely acquired
in this context). The zfs_fill_zplprops_impl() logic is updated to read
these default properties directly from MASTER_NODE_OBJ.

Signed-off-by: Ameer Hamza <[email protected]>
Update zfs_id_overobjquota() and zfs_id_overblockquota() to enforce
default user/group/project quotas (block and object-based) when no
per-user, per-group, or per-project quota exists. If a specific quota
is not configured for an ID, the default quota value is applied.

Signed-off-by: Ameer Hamza <[email protected]>
Ensure default user/group/project quotas are visible through quota
tools and filesystem stats when no per-ID quota is configured. This
maintains consistency between quota visibility and configured defaults.

Signed-off-by: Ameer Hamza <[email protected]>
Update zfs userspace, groupspace, and projectspace to display the
default quotas when no per-ID specific quota is configured. This
ensures tool outputs align with enforced limits.

Signed-off-by: Ameer Hamza <[email protected]>
Extend test coverage to verify default user and group quota
functionality. These build on existing user/group quota tests with
additional cases specific to default quotas functionality.
Added on top of: openzfs@e08cd97

Signed-off-by: Todd Seidelmann <[email protected]>
Signed-off-by: Ameer Hamza <[email protected]>
Extend project quota test coverage to verify defaultprojectquota
behavior. These build on existing project quota tests with additional
cases specific to defaultprojectquota functionality.

Signed-off-by: Ameer Hamza <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Code Review Needed Ready for review and testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

defaultuserquota and defaultgroupquota
4 participants