1. Introduction
In Linux system administration, effectively managing storage, i.e., disk space, is crucial, especially in shared environments where multiple users or groups coexist. To ensure fair resource allocation and prevent one user or group from monopolizing disk space, setting limits on directory sizes through disk quotas can be essential.
In this tutorial, we’ll explore the process of creating a simulated filesystem in a file, imposing directory size restrictions, and enforcing those limits using quotas.
2. Creating Directories and Files
First, we create a directory that will serve as the point where we access and manage the virtual filesystem we’ll create.
So, let’s make an empty directory via mkdir:
$ mkdir /point
To provide storage for our new virtual filesystem, we’ll create a file filled with zeros. This file will have a maximum size we want to reserve for the virtual filesystem.
Now, we’ll use dd to create the file:
$ dd if=/dev/zero of=~/mydatafile bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.39109 s, 772 MB/s
Let’s break down this example:
- if=/dev/zero reads from the /dev/zero special file, which provides an endless stream of null (zero) bytes
- of=~/mydatafile writes the output to a file named mydatafile in the home directory
- bs=1M sets the block size to one megabyte
- count=1024 sets the number of blocks to copy, creating a 1GB file (1024 times one megabyte)
Furthermore, the output provides information about the number of data blocks processed, the amount of data transferred, the time taken, and the speed of the operation when creating the file.
3. Creating a Virtual Filesystem
Next, let’s format the mydatafile with an ext4 filesystem, effectively turning it into a virtual disk within a file:
$ mkfs.ext4 ~/mydatafile
mke2fs 1.46.5 (30-Dec-2021)
Discarding device blocks: done
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: fc801409-d5ee-488d-a7d9-2ea6a5c3f13c
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
Here, the output shows the various stages of creating an ext4 filesystem on the specified file ~/mydatafile and provides information about the filesystem’s characteristics and metadata.
Then, we’ll mount the virtual filesystem we just created to the mount point directory using mount with the loopback option:
$ sudo mount -o loop,rw,usrquota,grpquota ~/mydatafile /point
Here, we used -o to include the following options:
- loop treats mydatafile as a loopback device, enables mount like a regular block device or disk partition
- rw filesystem should be mounted in read-write mode, enabling both reading from and writing to it
- usrquota, grpquota enable user and group quotas on the mounted filesystem
At this point, we have a virtual filesystem mounted in the specified directory with size limits.
After mounting, we can check the contents of /point via ls:
$ ls /point
lost+found
As we can see, a lost+found directory has been created. It’s a repository for orphaned or recovered data resulting from filesystem issues, facilitating data recovery and repair operations. Moreover, the existence of this directory serves as a safeguard for preserving potentially lost or corrupted files.
Now, to make these settings persistent after a reboot, we can create an entry in the /etc/fstab:
$ cat /etc/fstab
...
/home/amir/mydatafile /point ext4 loop,rw,usrquota,grpquota 0 0
In this case, we specify that the filesystem within mydatafile should be mounted at the directory /point as ext4. The first zero indicates that the filesystem shouldn’t be automatically checked during boot. Next, the second zero means that the filesystem shouldn’t be included in automatic backup operations.
4. Adding User and Group Quotas
Now, we’ll set disk space limits on a directory for specific users or groups within the filesystem.
4.1. Prepare Environment
Firstly, we install quota via apt-get with sudo privileges:
$ sudo apt-get install quota
Secondly, we create a group for the quota:
$ sudo groupadd grpQuota
Thirdly, we assign the desired user to this group:
$ sudo usermod -G grpQuota amir
Then, we create a directory in the new filesystem we mounted and set the access rights via a recursive chown operation:
$ sudo mkdir /point/share
$ sudo chown -R root.grpQuota /point/share
Here, we created a directory named share, then set root as the owner and grpQuota as the owner group.
4.2. Initialize Quota Mechanism
At this point, we check and initialize disk quotas:
$ sudo quotacheck -cug /point
In this instance, we initialize and create the necessary database files for implementing disk quotas over /point. The -c option generates the initial quota database files, and -u checks and initializes user quotas. Lastly, -g checks and initializes group quotas.
At this point, we can list /point:
$ ls -l /point
total 36
-rw------- 1 root root 7168 Sep 22 13:56 aquota.group
-rw------- 1 root root 7168 Sep 22 15:37 aquota.user
drwx------ 2 root root 16384 Sep 22 11:00 lost+found
drwxr-xr-x 2 root grpQuota 4096 Sep 22 13:49 share
As we can see, two files, aquota.group and aquota.user, have been created in the /point path.
5. Set User Quotas
Initially, we set disk quotas for the user name via edquota:
$ sudo edquota -f /point amir
In this case, we used -f to specify the filesystem, while amir is the username.
Consequently, our default editor opens with the contents of the default quota settings:
Disk quotas for user amir (uid 1000):
Filesystem blocks soft hard inodes soft hard
/dev/loop8 0 0 0 0 0 0
Using the editor, we can change these settings:
Disk quotas for user amir (uid 1000):
Filesystem blocks soft hard inodes soft hard
/dev/loop8 0 500000 600000 0 90 100
In this case, the numbers represent soft and hard limits and are used to control the amount of disk space and the number of inodes (data structures that represent files and directories) that the user is allowed to use.
To demonstrate, let’s look at the quota limits:
- soft block 500,000: the user uses up to roughly 500MB (500,000 KB) of disk space with a warning issued when reaching that limit
- hard block 600,000: absolute maximum amount of disk space (roughly 600MB) that the user is allowed to use on this filesystem
- soft inode 90: the user can create up to 90 files or directories without receiving warnings
- hard inode 100: exact maximum number of inodes that the user can create files or directories
Notably, the numbers under blocks and inodes that indicate the current usage cannot be edited, as they’re read-only, and provided just as reference. These numbers ensure that the user doesn’t consume excessive disk space or create an excessive number of files and directories on the specified filesystem.
Alternatively, we can use the setquota command for this operation:
$ setquota -u amir 500000 600000 90 100 -a /dev/loop8
Now, we can turn the quota on:
$ sudo quotaon /point
Here, we used quotaon to activate disk quotas on the specific filesystem.
6. Set Group Quotas
We set group quotas similar to user quotas.
In essence, we first set the quota values for the group:
$ sudo edquota -g grpQuota
Just like before, we edit the settings file:
Disk quotas for group grpQuota (gid 1001):
Filesystem blocks soft hard inodes soft hard
/dev/loop8 4 700000 800000 1 380 400
Alternatively, we can use setquota:
$ sudo setquota -g grpQuota 700000 800000 380 400 -a /dev/loop8
Now, let’s break down this group quota limits:
- soft block 700000: the group can collectively use up to roughly 700MB of disk space
- hard block 800000: absolute maximum amount of disk space the group can use
- soft inode 380: maximum number of files and directories that the group can create on the filesystem
- hard inode 400: strict maximum number of files and directories that the group can create on the filesystem
Overall, these quotas help ensure that the group grpQuota doesn’t exceed the specified resource limits on this filesystem.
7. Reporting
repquota displays information about user and group quotas on filesystems. Thus, this enables system administrators to monitor and manage resource usage effectively.
So, let’s use repquota to show reports:
$ sudo repquota -ug /point
*** Report for user quotas on device /dev/loop8
Block grace time: 7days; Inode grace time: 7days
Block limits File limits
User used soft hard grace used soft hard grace
----------------------------------------------------------------------
root -- 24 0 0 3 0 0
amir -- 24 500000 600000 3 90 100
*** Report for group quotas on device /dev/loop8
Block grace time: 7days; Inode grace time: 7days
Block limits File limits
Group used soft hard grace used soft hard grace
----------------------------------------------------------------------
root -- 20 0 0 2 0 0
grpQuota -- 4 700000 800000 1 380 400
The output displays disk quota information for users and groups on the filesystem. It includes details like the amount of disk space used (blocks), the soft quota limit, the hard quota limit, and the number of inodes (file entries) used.
8. Conclusion
In this article, we’ve explored the essential practice of implementing directory size limits with disk quotas in Linux to maintain fairness and stability in shared systems.
By creating simulated filesystems, setting restrictions, and enforcing limits, we can effectively regulate space usage for users and groups within specific directories, preventing resource conflicts and promoting equitable access.