  Disk quota system for Linux
  Jan Kara jack@suse.cz
  2000-2004

  This document contains documentation of Linux quota disk formats and
  appropriate quota utilities (currently in version 3.12).
  ______________________________________________________________________

  Table of Contents


  1. Introduction
  2. Configuration
     2.1 Setting up new quota
     2.2 Converting quota formats
     2.3 Setting user limits

  3. Quota formats
     3.1 Original quota format
     3.2 V0 quota format

  4. Utilities


  ______________________________________________________________________

  1.  Introduction

  Quota subsystem allows system administrator to set limits on used
  space and number of used inodes (inode is a filesystem structure which
  is associated which each file or directory) for users and/or groups.
  For both used space and number of used inodes there are actually two
  limits. The first one is called softlimit and the second one
  hardlimit. An user can never exceed a hardlimit for any resource. When
  an user exceeds a softlimit (s)he is warned that (s)he uses more space
  than (s)he should but space/inode is allocated (of course only if an
  user also does not exceed the hardlimit). If an user is exceeding
  softlimit for specified period of time (this period is called grace
  time) (s)he is not allowed to allocate more resources (so (s)he must
  free some space/inodes to get under softlimit).

  Quota limits are set independently for each filesystem. Currently
  following filesystems are supporting quota: Ext2, Ext3, ReiserFS, XFS.


  2.  Configuration

  2.1.  Setting up new quota

  In order for quota subsystem to work you have to have quota compiled
  in a kernel and configured appropriately. That means that the
  filesystem on which you want to use quotas must be mounted with quota
  options so that quota tools recognize the filesystems to work with
  (and also a filesystem itself might use the information). Currently
  there are following quota options (note that XFS uses completely
  different quota system and these information does not apply to it):

  o  usrquota or quota or usrjquota=filename if you want to use limits
     for users

  o  grpquota or grpjquota=filename if you want to use limits for groups

     The usrquota and grpquota options have also alternative with
     =filename appended. filename is then used as a name (together with
     path) of quota file to use. But note that by this you prevent quota
     utilities to do some useful autodetection. jquota mount options
     tell the tools and also the filesystem that it should journal the
     quota. That basically means that quota on disk is updated together
     with filesystem's metadata and hence you do not need to run
     quotacheck(8) after an unclean shutdown. For these options
     specifying of filename is mandatory (because filesystem also needs
     to know the file with quota information) and filename must specify
     a file in the root directory of a filesystem. When any of jquota
     options is specified additional option jqfmt=format must be also
     specified where format is a format of quota files. As journaled
     quota is currently supported only for vfsv0 format the value of
     format must be vfsv0. Journaled quota is currently (as of July
     2005) supported for Ext3 and Reiserfs filesystems and you need to
     have at least 2.6.11 kernel.

  For each filesystem with quotas you have to have files with quota
  data. The name of these quota files depends on ``quota format'' and
  you can even specify the filenames by yourself by adding =filename to
  usrquota or grpquota options -- e.g.  usrquota=file.quota. But note
  that by this you prevent quota utilities to do some useful
  autodetection. The quota files can be created by quotacheck(8)
  utility. When you have successfully created quota files you can turn
  quotas on (ie. system will start tracking how much each user uses and
  will check set limits). This is done by quotaon(8) program.

  2.2.  Converting quota formats

  When you already have working quota subsystem but you want to use
  newer quota format you have to convert quota files. This can be done
  by convertquota(8) utility.

  2.3.  Setting user limits

  You can edit user (group) limits by edquota(8) or setquota(8)
  programs.  By these programs you can also set grace times.


  3.  Quota formats

  3.1.  Original quota format

  Original quota format was the only one available in kernels up to
  2.4.21 Linux kernels (note that vendors such as RedHat or SuSE have
  included quota format patches into their kernels earlier and use
  ``newer quota format''). This quota format is in manpages and quota
  utils called vfsold.

  Data for this format are usually stored in files quota.user (for user
  quotas) and quota.group (for group quotas). Both files have the same
  structure. They are just the arrays of following structures:

  ______________________________________________________________________
  struct v1_disk_dqblk {
   u_int32_t dqb_bhardlimit; /* Absolute limit on disk blks alloc */
   u_int32_t dqb_bsoftlimit; /* Preferred limit on disk blks */
   u_int32_t dqb_curblocks; /* Current block count */
   u_int32_t dqb_ihardlimit; /* Maximum # allocated inodes */
   u_int32_t dqb_isoftlimit; /* Preferred limit on inodes */
   u_int32_t dqb_curinodes; /* Current # allocated inodes */
   time_t dqb_btime; /* Time limit for excessive disk use */
   time_t dqb_itime; /* Time limit for excessive files */
  };
  ______________________________________________________________________


  Structure for user (group) with id N is stored as N-th structure in
  file.  In fields dqb_btime and dqb_itime of first structure (id = 0)
  are stored grace times for this filesystem.

  3.2.  V0 quota format

  This quota format is currently available in 2.4.22 and newer kernels.
  Also kernels distributed by RedHat (>= 7.1) and SuSE (>= 7.2) contain
  support for this quota format. This format is called vfsv0 in manpages
  and utilities and quota files are usually called aquota.user and
  aquota.group.

  This quota format has following advantages against old quota format:

  o  It allows 32-bit UIDs/GIDs.

  o  Used space is stored in bytes and so ReiserFS can do precise
     accounting.

  o  UID/GID 0 is no longer special (grace times are stored
     independently).

  o  Header which allows quota format and version detection was added.

  Format of quota file is the following: In the beginning of quota file
  there is a generic header which is intended to be present in every
  quota file in future. The header has the following structure:

  ______________________________________________________________________
  struct disk_dqheader {
   __u32 dqh_magic; /* Magic number identifying file */
   __u32 dqh_version; /* File version */
  };
  ______________________________________________________________________


  From this header any utility or a kernel code should be able to recog-
  nize whether they understand a format of file and eventually refuse to
  continue.

  Following header might be specific for quota type and version
  (currently this header is the same for user and group quota and there
  is only one version of quota file format).

  ______________________________________________________________________
  struct disk_dqinfo {
   __u32 dqi_bgrace; /* Time before block soft limit becomes hard limit - in seconds */
   __u32 dqi_igrace; /* Time before inode soft limit becomes hard limit - in seconds */
   __u32 dqi_flags; /* Flags for quota file (DQF_*) (currently there are no ondisk flags) */
   __u32 dqi_blocks; /* Number of blocks in file */
   __u32 dqi_free_blk; /* Number of first free block in the list */
   __u32 dqi_free_entry; /* Number of block with at least one free entry */
  };
  ______________________________________________________________________


  There are two linked lists of blocks in a quota file. The first linked
  list is used to link all blocks that are completely unused
  (dqi_free_blk points to the first element of this list). The second
  linked list is used to link all data blocks which have at least one
  entry free and which also have at least one used entry. The beginning
  of the list is pointed by dqi_free_entry.

  The rest of a file (starting at 1KB) is divided into 1KB blocks. In
  these blocks is stored a radix tree with quotas. The key for the radix
  tree is UID or GID (I will use just ID in the following text)
  depending on a quota file type.  One node of the tree is 1KB block so
  there are up to 256 references to the sons.  At each level we choose
  reference corresponding to one byte of ID so having four-level radix
  tree we can support 32-bit IDs. Reference from the last level points
  to data block which contains quota structure for proper ID.

  Data block has following structure: In the beginning there is a header
  with the following structure:

  ______________________________________________________________________
  struct disk_dqdbheader {
   __u32 dqdh_next_free; /* Number of next block with free entry */
   __u32 dqdh_prev_free; /* Number of previous block with free entry */
   __u16 dqdh_entries; /* Number of valid entries in block */
   __u16 dqdh_pad1;
   __u32 dqdh_pad2;
  };
  ______________________________________________________________________


  Entries dqdh_next_free and dqdh_prev_free are used only if the block
  has at least one free and one used entry. If it has no free entry
  these references are set to 0. When block is completely free only
  dqdh_next_free is used for linked list of free blocks.

  The rest of the block is divided into 21 quota entries. Unused entry
  is entry that contains only zeros. Note that used entries might be
  freely scattered in the block. Quota entry has the following
  structure:

  ______________________________________________________________________
  struct disk_dqblk {
   __u32 dqb_id; /* id this quota applies to */
   __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */
   __u32 dqb_isoftlimit; /* preferred inode limit */
   __u32 dqb_curinodes; /* current # allocated inodes */
   __u32 dqb_bhardlimit; /* absolute limit on disk space (in kb) */
   __u32 dqb_bsoftlimit; /* preferred limit on disk space (in kb) */
   __u64 dqb_curspace; /* current space occupied (in bytes) */
   __u64 dqb_btime; /* time limit for excessive disk use */
   __u64 dqb_itime; /* time limit for excessive inode use */
  };
  ______________________________________________________________________



  4.  Utilities

  As of version 3.01 quota utilities support original, vfsv0 and xfs
  quota format.  You can download latest version of utils from
  http://www.sf.net/projects/linuxquota/.

  Utils try to do autodetection of currently used quota format (i.e.
  they detect which format is compiled into kernel and they try to use
  this one). Anytime you can force utils to use different format by
  specifying -F <format>. More information about quota utils can be
  found in appropriate manpages.



