How to set or edit quota limit for a user or file-system, assign or modify grace period with examples in Linux

The setquota command sets and changes the quota limits for a user, a group, or a file set.. Quota Implementation is done in Linux to limit the storage consumption per user/group.

Features:
Limit storage consumption per user/group
Based on disk block usage or inode usage
Imposed in 2 stages (thresholds) : soft and hard

Soft limit: may be exceeded for up to the provided grace period
Hard limit: may never be exceeded under any circumstance. Once this is reached then the disk will not allow to write any more data

Pre-requisite:
quota rpm must be installed
quota must be enabled on the filesystem/partition on which you desire to implement the functionality.

Enable quota on the partition

For the sake of this article I will only enable userquota on /tmp partition.

Append "usrquota" as shown below for the respective partition. If you also wish to implement quota for a particular group then also append "grpquota"

# vim /etc/fstab
/dev/mapper/system-tmp  /tmp                    ext4    defaults,nodev,usrquota        1 2

Next remount your filesystem to take the changes affect

# mount -o remount /tmp/

Validate the changes

# mount | grep quota
/dev/mapper/system-tmp on /tmp type ext4 (rw,nodev,relatime,quota,usrquota,stripe=64,data=ordered)

As you see now my /tmp partition is re-mounted with usrquota.

Next you must create the user quota file under the respective partition.

# quotacheck -vcum /tmp/
quotacheck: Scanning /dev/mapper/system-tmp [/tmp] done
quotacheck: Cannot stat old user quota file /tmp/aquota.user: No such file or directory. Usage will not be subtracted.
quotacheck: Old group file name could not been determined. Usage will not be subtracted.
quotacheck: Checked 37 directories and 63 files
quotacheck: Old file not found.

This will create 'aquota.user' file under /tmp. Since we are running this command for the first time hence we get the error "No such file or directory". I am using "-m" because the command is being executed on a running node where the partition is in mounted state hence I do not want to be re-mounted. If you are in a single user mode then use can exclude "-m" from the above command.

Check the quota report

To check the existing usage of quota on your Linux machine execute the below command

# repquota -a
*** Report for user quotas on device /dev/mapper/system-tmp
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --   21912       0       0             79     0     0
ankit     --      68       0       0             21     0     0

This will give you a brief report of the current block and inode usage of the filesystem. Here for our case wince we only enabled quota but have not assigned any soft or hard limit hence most of the sections are null.

Assign/Edit Quota block limit

To assign a block limit for the first time you can either use 'setquota' or you can also use 'edquota'. Using "setquota" you can directly set the quota while with "edquota" you will be editing the existing quota value, so either can be used

How to check the total block and inode count available on my node?
Before I start explaining the steps to set or assign quota, how will someone know the inode limit or the block limit which is available with the respective partition?. To check this you can use tune2fs tool.

On RHEL 7, tune2fs is provided by "e2fsprogs" rpm so you can install this using "yum"

# yum install e2fsprogs

Next use the below syntax along with the filesystem name for which you want to get the details. In our case it is "/dev/mapper/system-tmp"

# tune2fs -l /dev/mapper/system-tmp

This will give you a long list of details, but for the sake of this article we will stick to the block and inode count for which you can execute the below command

# tune2fs -l  /dev/dm-7 | grep -e "Inode count|Block count"
Inode count:              2621440
Block count:              10485760

As you see this filesystem will allow a total inode count of 2621440 and 10485760 block.

To get the size of the partition you can use below formula

10485760 * 4096 = 42949672960/1024 = 41943040/1024 = 40960/1024 = 40GB

So our /tmp partition is of 40GB.

Method 1: Using setquota
Below is the syntax to be used

setquota [-u|-g] <user|group> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit>

In the below command I am setting a soft limit of 8GB and hard limit of 10GB for the block limit of /tmp partition for "deepak" user.

# setquota -u deepak 8388608 10485760 0 0 /tmp/

8388608/1024 = 8192/1024 = 8GB
10485760/1024 = 10240/1024 = 10GB

If you wish to also restrict inode count limit then you can modify the above command as below

# setquota -u deepak 8388608 10485760 100 120 /tmp/

Method 2: Using edquota
Accodingly if you wish to use "edquota" then run the command with "-u" argument as shown below

# edquota -u deepak
Disk quotas for user deepak (uid 1005):
  Filesystem                   blocks       soft       hard     inodes     soft     hard
  /dev/mapper/system-tmp            0    8388608   10485760          0        0        0

This will show you the currently set quota limits for the user "deepak". Here you can make you modification, after which save and exit the file using "wq!"

Next you can check the report of the currently allocated quota

# repquota /tmp/
*** Report for user quotas on device /dev/mapper/system-tmp
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --   25824       0       0             80     0     0
ankit     --      68       0       0             21     0     0

Why my "deepak" user is not shown in the repquota command above?

As you may have noticed the above repquota is showing the status only for "root" and "ankit" user but not for "deepak" user. It is because currently user "deepak" has not created any file under /tmp so there is nothing to show.

You can get more details output of repquota using below command

# repquota -sv /tmp/
*** Report for user quotas on device /dev/mapper/system-tmp
Block grace time: 7days; Inode grace time: 7days
                        Space limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --  25824K      0K      0K             80     0     0
ankit     --     68K      0K      0K             21     0     0
deepak    --      0K   8192M  10240M              0     0     0

Statistics:
Total blocks: 7
Data blocks: 1
Entries: 3
Used average: 3.000000

As you see since currently the used block limit and inode limit is "0" hence repquota will not show any detail about this user by default unless there are any file present which is owned by the respective user under the provided filesystem.

Once I created a dummy file using "deepak" user under /tmp, I was able to get the quota report as shown below

# repquota /tmp/
*** Report for user quotas on device /dev/mapper/system-tmp
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --   25824       0       0             80     0     0
ankit     --      68       0       0             21     0     0
deepak    --    3912 8388608 10485760             1     0     0

Add/Set Grace Period

A grace period starts when you reach the soft quota limit. You can write up until the grace period expires, or until you reach the hard quota limit. Hard limits are enforced by the file system and when you reach a hard quota limit, you cannot store any additional data until you drop back below your quota limits.

If you are not assigning any grace period while setting the quota limit then by default a grace period of 7 days is considered for both block and inode limit.

You can assign grace period using "setquota" or "edquota"

Method 1: Using setquota
To assign grace period using setquota use the below syntax

setquota [-u|-g] <user|group> -t <blockgrace> <inodegrace>

For example I would like to give a grace period of 5 days

5* 24 (hours) * 60 (minutes) *60 (seconds) = 432000 seconds

So the command to set a grace period of 5 days for block and inode limit would be

# setquota -t 432000 432000 /tmp/

Check the quota report

# repquota -s /tmp/
*** Report for user quotas on device /dev/mapper/system-tmp
Block grace time: 5days; Inode grace time: 5days
                        Space limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --  25824K      0K      0K             80     0     0
ankit     --     68K      0K      0K             21     0     0
deepak    --   3912K   8192M  10240M              1     0     0

So all looks fine.

Method 2: Using edquota
You can also use "edquota" to edit the quota for respective filesystem to modify the grace period using below command

# edquota -t
Grace period before enforcing soft limits for users:
Time units may be: days, hours, minutes, or seconds
  Filesystem             Block grace period     Inode grace period
  /dev/mapper/system-tmp                  5days                  5days

The added advantage with this method is that here you can use values like "days, hours, minutes, or seconds" for assigning grace period unlike with setquota where you must provide the value only in seconds.

Once your changes are done you can save and exit the file using "wq!"

Turn Quota ON or OFF

Now here we were assigning and modifying the quota limits for user and file systems but do we know if the quota is enabled in the first place?
As if the quota is not in enabled state then there is no point in assigning these restrictions.

To check the current status of quota

# quotaon -ap
group quota on /tmp (/dev/mapper/system-tmp) is off
user quota on /tmp (/dev/mapper/system-tmp) is off

Here as you see both user and group quota is disabled for /tmp partition. Since in this article we are only using user quota so I will not enable groupquota

To enable user quota

# quotaon -u /tmp/

If you also wish to enable group quota then you can either combine both arguments "-ug" or you can execute the commands separately.

# quotaon -g /tmp/

Next check the status again

# quotaon -ap
group quota on /tmp (/dev/mapper/system-tmp) is off
user quota on /tmp (/dev/mapper/system-tmp) is on

So now quota is enabled on our filesystem for user.

To turn off the quota for both user and group on /tmp partition use below command

# quotaoff -ug /tmp

Validate the quota limit

I will write some dummy data on /tmp partition and will monitor my quota limit

$ dd if=/dev/urandom of=file.txt bs=10485762121 count=10000
dd: warning: partial read (33554431 bytes); suggest iflag=fullblock
dm-7: warning, user block quota exceeded.
dm-7: write failed, user block limit reached.
dd: error writing âfile.txtâ: Disk quota exceeded
0+320 records in
0+319 records out
10733408256 bytes (11 GB) copied, 68.281 s, 157 MB/s

As you see once the soft limit was reached a warning message was printed, but the writing continued. Once the hard limit was reached then write failed for "dd" command

Below is the quota report

# repquota /tmp/
*** Report for user quotas on device /dev/mapper/system-tmp
Block grace time: 5days; Inode grace time: 5days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --   25824       0       0             80     0     0
ankit     --      68       0       0             21     0     0
deepak    +- 10485760 8388608 10485760  4days       2     0     0

As you see a "+" (plus) sign has appeared after the uername which means that quota limit has reached and the grace period value is reflected, which means now I have 4 days left to clear the data. But anyhow I have already reached hard limit.

I hope the article was useful.