table of contents
| quotactl(2) | System Calls Manual | quotactl(2) |
NOM¶
quotactl, quotactl_fd - manipulate disk quotas
BIBLIOTHÈQUE¶
Bibliothèque C standard (libc, -lc)
SYNOPSIS¶
#include <sys/quota.h> #include <xfs/xqm.h> /* Définition des constantes Q_X* et XFS_QUOTA_*
(ou <linux/dqblk_xfs.h>; voir NOTES) */
int quotactl(int op, const char *_Nullable special, int id,
caddr_t addr);
#include <sys/syscall.h> /* Definition of SYS_* constants */ #include <unistd.h>
int syscall(SYS_quotactl_fd, int fd, int op, int id, caddr_t addr);
Note: glibc provides no wrapper for quotactl_fd(), necessitating the use of syscall(2).
DESCRIPTION¶
Le système de quotas permet de définir une limite sur la quantité d'espace disque utilisée sur un système de fichiers, qui peut être mise par utilisateur, par groupe ou par projet. Pour chaque utilisateur ou groupe, une limite souple et une limite impérative peuvent être définies sur chaque système de fichiers. La limite impérative ne peut pas être dépassée. La limite souple peut être dépassée, mais des avertissements s'ensuivront. De plus, l'utilisateur ne peut pas dépasser une limite souple pendant une certaine période de grâce d’affilée (une semaine par défaut). Une fois cette durée écoulée, la limite souple devient une limite impérative.
The quotactl() and quotactl_fd() calls manipulate disk quotas. The difference between these functions is the way the filesystem being manipulated is specified, see description of the arguments below. See NOTES for why one variant might be preferred over the other.
The op argument indicates an operation to be applied to the user or group ID specified in id. To initialize the op argument, use the QCMD(subop, type) macro. The type value is either USRQUOTA, for user quotas, GRPQUOTA, for group quotas, or (since Linux 4.1) PRJQUOTA, for project quotas. The subop value is described below.
For quotactl(), the special argument is a pointer to a null-terminated string containing the pathname of the (mounted) block special device for the filesystem being manipulated.
For quotactl_fd(), the fd argument is a file descriptor (which may be opened with the O_PATH flag) referring to a file or directory on the filesystem being manipulated.
L'argument addr est l'adresse d'une structure de données optionnelle, spécifique à l'opération, qui est copiée sur ou depuis le système. L'interprétation d'addr est donnée avec chaque opération ci-dessous.
La valeur de subop vaut une des opérations suivantes :
- Q_QUOTAON
- Activer les quotas pour un système de fichiers. L'argument id est le numéro d'identification du format de quotas à utiliser. Il existe actuellement trois formats possibles de quotas :
- QFMT_VFS_OLD
- Le format original de quotas.
- QFMT_VFS_V0
- Le format standard VFS v0 de quotas, qui peut manipuler des identifiants d'utilisateur et de groupe sur 32 bits, et des limites de quotas jusqu'à 2^42 octets et 2^32 inœuds.
- QFMT_VFS_V1
- Un format de quotas qui peut manipuler des identifiants d'utilisateur et de groupe sur 32 bits, et des limites de quotas jusqu'à 2^63 octets et 2^63 inœuds.
- L'argument addr pointe sur le chemin d'un fichier contenant les quotas du système de fichiers. Le fichier de quotas doit exister ; il est habituellement créé par la commande quotacheck(8).
- Des informations de quotas peuvent également être stockées dans des inœuds cachés du système pour ext4, XFS et d'autres systèmes de fichiers s'ils sont configurés pour cela. Dans ce cas, aucun fichier de quota n'est visible et il n'est pas nécessaire d'utiliser quotacheck(8). Les informations de quotas sont toujours maintenues en cohérence par le système de fichiers et l'opération Q_QUOTAON ne sert qu'à lancer l'application des quotas. La présence d'inœuds système cachés avec des informations de quotas est indiquée par l'attribut DQF_SYS_FILE du champ dqi_flags renvoyé par l'opération Q_GETINFO.
- The quotactl_fd() variant of this system call ignores the addr and id arguments, so the Q_QUOTAON operation of quotactl_fd() is only suitable for work with hidden system inodes.
- Cette opération exige le privilège (CAP_SYS_ADMIN).
- Q_QUOTAOFF
- Désactiver les quotas pour un système de fichiers. Les arguments addr et id sont ignorés. Cette opération nécessite le privilège CAP_SYS_ADMIN.
- Q_GETQUOTA
- Obtenir les limites de quota et l’utilisation actuelle d’espace disque pour l'utilisateur ou le groupe id. L'argument addr est un pointeur sur une structure dqblk définie dans <sys/quota.h> comme ceci :
-
/* uint64_t is an unsigned 64-bit integer;
uint32_t is an unsigned 32-bit integer */ struct dqblk { /* Definition since Linux 2.4.22 */
uint64_t dqb_bhardlimit; /* Absolute limit on disk
quota blocks alloc */
uint64_t dqb_bsoftlimit; /* Preferred limit on
disk quota blocks */
uint64_t dqb_curspace; /* Current occupied space
(in bytes) */
uint64_t dqb_ihardlimit; /* Maximum number of
allocated inodes */
uint64_t dqb_isoftlimit; /* Preferred inode limit */
uint64_t dqb_curinodes; /* Current number of
allocated inodes */
uint64_t dqb_btime; /* Time limit for excessive
disk use */
uint64_t dqb_itime; /* Time limit for excessive
files */
uint32_t dqb_valid; /* Bit mask of QIF_*
constants */ }; /* Flags in dqb_valid that indicate which fields in
dqblk structure are valid. */ #define QIF_BLIMITS 1 #define QIF_SPACE 2 #define QIF_ILIMITS 4 #define QIF_INODES 8 #define QIF_BTIME 16 #define QIF_ITIME 32 #define QIF_LIMITS (QIF_BLIMITS | QIF_ILIMITS) #define QIF_USAGE (QIF_SPACE | QIF_INODES) #define QIF_TIMES (QIF_BTIME | QIF_ITIME) #define QIF_ALL (QIF_LIMITS | QIF_USAGE | QIF_TIMES)
- Le champ dqb_valid est un masque de bit qui permet d'indiquer quelles entrées de la structure dqblk sont valables. Actuellement, le noyau remplit toutes les entrées de la structure dqblk et les marque comme valables dans le champ dqb_valid. Les utilisateurs non privilégiés ne peuvent connaître que leurs propres quotas ; un utilisateur avec le privilège CAP_SYS_ADMIN peut connaître les quotas de tous les utilisateurs.
- Q_GETNEXTQUOTA (depuis Linux 4.6)
- Cette opération est la même que Q_GETQUOTA, mais elle renvoie les informations de quotas du prochain identifiant supérieur ou égal à id où un quota est positionné.
- L'argument addr est un pointeur vers une structure nextdqblk dont les champs sont identiques à dqblk, excepté un champ dqb_id supplémentaire pour renvoyer l'identifiant pour lequel les informations de quota seront renvoyées :
-
struct nextdqblk {
uint64_t dqb_bhardlimit;
uint64_t dqb_bsoftlimit;
uint64_t dqb_curspace;
uint64_t dqb_ihardlimit;
uint64_t dqb_isoftlimit;
uint64_t dqb_curinodes;
uint64_t dqb_btime;
uint64_t dqb_itime;
uint32_t dqb_valid;
uint32_t dqb_id; };
- Q_SETQUOTA
- Définir les informations de quotas pour l'utilisateur ou le groupe id, en utilisant les informations fournies par la structure dqblk dont l'adresse est contenue dans addr. Le champ dqb_valid de la structure dqblk indique quelles entrées de la structure ont été définies par l'appelant. Cette opération remplace les opérations Q_SETQLIM et Q_SETUSE de l'interface antérieure de quotas. Cette opération nécessite le privilège CAP_SYS_ADMIN.
- Q_GETINFO (depuis Linux 2.4.22)
- Obtenir les informations (comme le délai de grâce) du fichier de quotas. L'argument addr est un pointeur sur une structure dqinfo. Cette structure est définie dans <sys/quota.h> de la manière suivante :
-
/* uint64_t is an unsigned 64-bit integer;
uint32_t is an unsigned 32-bit integer */ struct dqinfo { /* Defined since Linux 2.4.22 */
uint64_t dqi_bgrace; /* Time before block soft limit
becomes hard limit */
uint64_t dqi_igrace; /* Time before inode soft limit
becomes hard limit */
uint32_t dqi_flags; /* Flags for quotafile
(DQF_*) */
uint32_t dqi_valid; }; /* Bits for dqi_flags */ /* Quota format QFMT_VFS_OLD */ #define DQF_ROOT_SQUASH (1 << 0) /* Root squash enabled */
/* Before Linux v4.0, this had been defined
privately as V1_DQF_RSQUASH */ /* Quota format QFMT_VFS_V0 / QFMT_VFS_V1 */ #define DQF_SYS_FILE (1 << 16) /* Quota stored in
a system file */ /* Flags in dqi_valid that indicate which fields in
dqinfo structure are valid. */ #define IIF_BGRACE 1 #define IIF_IGRACE 2 #define IIF_FLAGS 4 #define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS)
- Le champ dqi_valid de la structure dqinfo indique les entrées de la structure qui sont valables. Le noyau remplit actuellement toutes les entrées de la structure dqinfo et les marque comme étant valables dans le champ dqi_valid. L'argument id est ignoré.
- Q_SETINFO (depuis Linux 2.4.22)
- Définir les informations au sujet du fichier de quotas. L'argument addr devrait être un pointeur vers une structure dqinfo. Le champ dqi_valid de la structure dqinfo indique quelles entrées de la structure ont été définies par l'appelant. Cette opération remplace les opérations Q_SETGRACE et Q_SETFLAGS de l'interface antérieure de quotas. L'argument id est ignoré. Cette opération nécessite le privilège CAP_SYS_ADMIN.
- Q_GETFMT (depuis Linux 2.4.22)
- Obtenir le format de quotas utilisé sur le système de fichiers spécifié. L'argument addr est un pointeur sur un tampon de 4 octets qui contient le numéro du format.
- Q_SYNC
- Update the on-disk copy of quota usages for a filesystem. For quotactl(), if special is NULL, then all filesystems with active quotas are sync'ed. (quotactl_fd() always sync's only one filesystem.) In both cases, the addr and id arguments are ignored.
- Q_GETSTATS (pris en charge jusqu'à Linux 2.4.21)
- Récupérer des statistiques et d'autres informations génériques sur le sous-système de quotas. L'argument addr doit être un pointeur sur une structure dqstats dans laquelle les données seront stockées. Cette structure est définie dans <sys/quota.h>. Les arguments special et id sont ignorés.
- Cette opération est obsolète et a été supprimée dans Linux 2.4.22. Les fichiers dans /proc/sys/fs/quota/ contiennent désormais les informations.
Pour des systèmes de fichiers XFS qui utilisent le gestionnaire de quotas XFS (XFS Quota Manager, ou XQM), les opérations ci-dessus doivent être remplacées par les commandes suivantes :
- Q_XQUOTAON
- Activer les quotas sur un système de fichiers XFS. XFS permet d'activer et désactiver l'application des limites avec la gestion des quotas. Par conséquent, XFS attend qu'addr soit un pointeur sur un unsigned int qui contient une combinaison bit à bit des attributs suivants (définis dans <xfs/xqm.h>) :
-
XFS_QUOTA_UDQ_ACCT /* Décompte du quota de l'utilisateur */ XFS_QUOTA_UDQ_ENFD /* Application des limites du quota de l'utilisateur */ XFS_QUOTA_GDQ_ACCT /* Décompte du quota du groupe */ XFS_QUOTA_GDQ_ENFD /* Activation des limites de quota du groupe */ XFS_QUOTA_PDQ_ACCT /* Décompte du quota du projet */ XFS_QUOTA_PDQ_ENFD /* Activation des limites de quota du projet */
- Cette opération exige un privilège (CAP_SYS_ADMIN). L'argument id est ignoré.
- Q_XQUOTAOFF
- Désactiver les quotas pour un système de fichiers XFS. Comme pour Q_QUOTAON, le système de fichier XFS attend un pointeur vers un unsigned int qui spécifie si le décompte des quotas et/ou l'application des limites doit être désactivé (en utilisant les mêmes attributs que pour l'opération Q_XQUOTAON). Cette opération nécessite le privilège CAP_SYS_ADMIN. L'argument id est ignoré.
- Q_XGETQUOTA
- Obtenir les limites de quotas et l’utilisation actuelle d’espace disque pour l'utilisateur id. L'argument addr est un pointeur sur une structure fs_disk_quota définie dans <xfs/xqm.h> comme ceci :
-
/* All the blk units are in BBs (Basic Blocks) of
512 bytes. */ #define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */ #define XFS_USER_QUOTA (1<<0) /* User quota type */ #define XFS_PROJ_QUOTA (1<<1) /* Project quota type */ #define XFS_GROUP_QUOTA (1<<2) /* Group quota type */ struct fs_disk_quota {
int8_t d_version; /* Version of this structure */
int8_t d_flags; /* XFS_{USER,PROJ,GROUP}_QUOTA */
uint16_t d_fieldmask; /* Field specifier */
uint32_t d_id; /* User, project, or group ID */
uint64_t d_blk_hardlimit; /* Absolute limit on
disk blocks */
uint64_t d_blk_softlimit; /* Preferred limit on
disk blocks */
uint64_t d_ino_hardlimit; /* Maximum # allocated
inodes */
uint64_t d_ino_softlimit; /* Preferred inode limit */
uint64_t d_bcount; /* # disk blocks owned by
the user */
uint64_t d_icount; /* # inodes owned by the user */
int32_t d_itimer; /* Zero if within inode limits */
/* If not, we refuse service */
int32_t d_btimer; /* Similar to above; for
disk blocks */
uint16_t d_iwarns; /* # warnings issued with
respect to # of inodes */
uint16_t d_bwarns; /* # warnings issued with
respect to disk blocks */
int32_t d_padding2; /* Padding - for future use */
uint64_t d_rtb_hardlimit; /* Absolute limit on realtime
(RT) disk blocks */
uint64_t d_rtb_softlimit; /* Preferred limit on RT
disk blocks */
uint64_t d_rtbcount; /* # realtime blocks owned */
int32_t d_rtbtimer; /* Similar to above; for RT
disk blocks */
uint16_t d_rtbwarns; /* # warnings issued with
respect to RT disk blocks */
int16_t d_padding3; /* Padding - for future use */
char d_padding4[8]; /* Yet more padding */ };
- Les utilisateurs non privilégiés ne peuvent connaître que leurs propres quotas ; un utilisateur avec les droits CAP_SYS_ADMIN peut connaître les quotas de tous les utilisateurs.
- Q_XGETNEXTQUOTA (depuis Linux 4.6)
- Cette opération est la même que Q_XGETQUOTA mais elle renvoie (dans la structure fs_disk_quota vers laquelle pointe addr) les informations de quotas du prochain identifiant supérieur ou égal à id ayant des quotas. Remarquez que comme fs_disk_quota a déjà un champ q_id, aucun type de structure séparée n'est nécessaire (contrairement aux opérations Q_GETQUOTA et Q_GETNEXTQUOTA).
- Q_XSETQLIM
- Définir les informations de quotas pour l'utilisateur id. L'argument addr contient un pointeur vers une structure fs_disk_quota. Cette opération nécessite les privilèges CAP_SYS_ADMIN.
- Q_XGETQSTAT
- Renvoyer les informations de quotas spécifiques au système de fichiers XFS dans la structure fs_quota_stat vers laquelle pointe addr. Cela est utile pour savoir combien d'espace est utilisé pour stocker les informations sur les quotas, ainsi que pour connaître l'état activé ou non des quotas d'un système de fichiers local XFS spécifique. La structure fs_quota_stat se définit comme suit :
-
#define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */ struct fs_qfilestat {
uint64_t qfs_ino; /* Nombre d'inœuds */
uint64_t qfs_nblks; /* Nombre de BB
de 512 octets */
uint32_t qfs_nextents; /* Nombre d'extensions */ }; struct fs_quota_stat {
int8_t qs_version; /* Numéro de version pour des
futurs changements */
uint16_t qs_flags; /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
int8_t qs_pad; /* Inusité */
struct fs_qfilestat qs_uquota; /* Informations de quota utilisateur */
struct fs_qfilestat qs_gquota; /* Informations de quota groupe */
uint32_t qs_incoredqs; /* Nombre de dquots dans le fichier core */
int32_t qs_btimelimit; /* Limite du délai pour les blocs */
int32_t qs_itimelimit; /* Limite du délai pour les inœuds */
int32_t qs_rtbtimelimit;/* Limite de délai pour les blocs en
RT */
uint16_t qs_bwarnlimit; /* Limite du nombre d’avertissements */
uint16_t qs_iwarnlimit; /* Limite du nombre d’avertissements */ };
- L'argument id est ignoré.
- Q_XGETQSTATV
- Renvoyer les informations de quotas spécifiques au système de fichiers XFS dans la structure fs_quota_statv vers laquelle pointe l'argument addr. Cette version de l'opération utilise une structure gérant correctement les versions, et ayant une bonne mise en page (avec tous les champs naturellement alignés) et le remplissage pour éviter de gérer les fichiers spéciaux de compat ; elle donne aussi la possibilité d'avoir des statistiques sur le fichier de quotas du projet. La structure fs_quota_statv elle-même est définie comme suit :
-
#define FS_QSTATV_VERSION1 1 /* fs_quota_statv.qs_version */ struct fs_qfilestatv { struct fs_qfilestatv {
uint64_t qfs_ino; /* Nombre d'inœuds */
uint64_t qfs_nblks; /* Nombre de BB de
512 octets */
uint32_t qfs_nextents; /* Nombre d'extensions */
uint32_t qfs_pad; /* Remplissage aligné sur 8 octets */ }; struct fs_quota_statv {
int8_t qs_version; /* Numéro de version pour de futurs
changements */
uint8_t qs_pad1; /* Remplissage aligné sur 16 bits */
uint16_t qs_flags; /* Drapeaux XFS_QUOTA_.* */
uint32_t qs_incoredqs; /* Nombre de dquots dans le core */
struct fs_qfilestatv qs_uquota; /* Informations de quota
utilisateur */
struct fs_qfilestatv qs_gquota; /* Informations de quota de
groupe */
struct fs_qfilestatv qs_pquota; /* Informations de quota de
projet */
int32_t qs_btimelimit; /* Limite de délai pour les blocs */
int32_t qs_itimelimit; /* Limite de délai pour les inœuds */
int32_t qs_rtbtimelimit; /* Limite du délai pour les blocs en RT */
uint16_t qs_bwarnlimit; /* Limite du nombre d’avertissements */
uint16_t qs_iwarnlimit; /* Limite du nombre d’avertissements */
uint64_t qs_pad2[8]; /* Pour une future démonstration */ };
- Le champ qs_version de la structure doit être rempli avec la version de la structure prise en charge par l'appelant (pour l'instant, seul FS_QSTAT_VERSION1 est pris en charge). Le noyau remplira la structure en fonction de la version fournie. L'argument id est ignoré.
- Q_XQUOTARM (bogué jusqu'à Linux 3.16)
- Libérer l'espace disque concerné par le quota de disque. L'argument addr doit être un pointeur vers une valeur unsigned int contenant les attributs (les mêmes que dans le champ d_flags de la structure fs_disk_quota) identifiant les types de quota à supprimer (remarquez que le type de quota fourni dans l'argument op est ignoré, mais il doit être valable pour passer les contrôles préalables du gestionnaire d’appel système quotactl).
- Les quotas doivent déjà avoir été désactivés. L'argument id est ignoré.
- Q_XQUOTASYNC (depuis Linux 2.6.15 ; inutilisable depuis Linux 3.4)
- Cette opération était un équivalent à Q_SYNC des quotas XFS, mais elle n'est plus utilisable depuis Linux 3.4 car sync(1) écrit maintenant les informations de quotas sur le disque (en plus d'autres métadonnées du système de fichiers). Les arguments special, id et addr sont ignorés.
VALEUR RENVOYÉE¶
On success, quotactl() returns 0; on error, -1 is returned, and errno is set to indicate the error.
ERREURS¶
- EACCES
- op vaut Q_QUOTAON et le fichier de quotas pointé par addr existe, mais n'est pas un fichier normal ou alors n'est pas dans le système de fichiers pointé par special.
- EBUSY
- op vaut Q_QUOTAON, mais un autre Q_QUOTAON a déjà été réalisé.
- EFAULT
- addr ou special n'est pas valable.
- EINVAL
- op ou type n'est pas valable.
- EINVAL
- op vaut Q_QUOTAON mais le fichier de quotas indiqué est corrompu.
- EINVAL (depuis Linux 5.5)
- op vaut Q_XQUOTARM mais addr ne pointe pas vers des types de quota valables.
- ENOENT
- Le fichier spécifié par special ou addr n'existe pas.
- ENOSYS
- Le noyau a été compilé sans l'option CONFIG_QUOTA.
- ENOTBLK
- special n'est pas un périphérique bloc.
- EPERM
- L'appelant ne possède pas le privilège nécessaire (CAP_SYS_ADMIN) pour l'opération demandée.
- ERANGE
- op vaut Q_SETQUOTA, mais les limites spécifiées sont en dehors de l'intervalle autorisé pour le format de quotas.
- ESRCH
- Aucun quota de disque n'est imposé pour l'utilisateur spécifié. Les quotas n'ont pas été activés sur ce système de fichiers.
- ESRCH
- op vaut Q_QUOTAON, mais le format de quotas spécifié n'a pas été trouvé.
- ESRCH
- op vaut Q_GETNEXTQUOTA ou Q_XGETNEXTQUOTA mais aucun identifiant supérieur ou égal à id n'a de quota valable.
NOTES¶
Alternative XFS header¶
Vous pouvez utiliser <linux/dqblk_xfs.h> au lieu de <xfs/xqm.h>, en prenant en compte le fait qu'il y a plusieurs décalages de nommage :
- Les attributs d'activation des quotas (au format XFS_QUOTA_[UGP]DQ_{ACCT,ENFD}) sont définis sans « X » devant, comme FS_QUOTA_[UGP]DQ_{ACCT,ENFD}.
- La même chose s'applique aux attributs de type de quotas XFS_{USER,GROUP,PROJ}_QUOTA qui sont définis en tant que FS_{USER,GROUP,PROJ}_QUOTA.
- Le fichier d'en-tête dqblk_xfs.h définit ses propres constantes XQM_USRQUOTA, XQM_GRPQUOTA et XQM_PRJQUOTA pour les types de quota disponibles, mais leurs valeurs sont les mêmes que pour les constantes définies sans le préfixe XQM_.
quotactl() versus quotactl_fd()¶
The original quotactl() variant of this system call requires specifying the block device containing the filesystem to operate on. This makes it impossible to use in cases where the filesystem has no backing block device (e.g., tmpfs). Even when the block device does exist, it might be difficult to locate (requires scanning /proc/self/mounts and even some filesystem-specific parsing in the case of, for example, bcachefs). quotactl_fd() instead works on the mount point, which avoids this limitation and is simpler to use (since the filesystem to manipulate is typically specified by its mount point anyway).
STANDARDS¶
Linux.
HISTORIQUE¶
- quotactl_fd()
- Linux 5.14.
VOIR AUSSI¶
TRADUCTION¶
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Philippe MENGUAL <jpmengual@debian.org>
Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.
| 21 septembre 2025 | Pages du manuel de Linux 6.16 |