162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000-2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * All Rights Reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef __XFS_DQUOT_H__ 762306a36Sopenharmony_ci#define __XFS_DQUOT_H__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* 1062306a36Sopenharmony_ci * Dquots are structures that hold quota information about a user or a group, 1162306a36Sopenharmony_ci * much like inodes are for files. In fact, dquots share many characteristics 1262306a36Sopenharmony_ci * with inodes. However, dquots can also be a centralized resource, relative 1362306a36Sopenharmony_ci * to a collection of inodes. In this respect, dquots share some characteristics 1462306a36Sopenharmony_ci * of the superblock. 1562306a36Sopenharmony_ci * XFS dquots exploit both those in its algorithms. They make every attempt 1662306a36Sopenharmony_ci * to not be a bottleneck when quotas are on and have minimal impact, if any, 1762306a36Sopenharmony_ci * when quotas are off. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistruct xfs_mount; 2162306a36Sopenharmony_cistruct xfs_trans; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cienum { 2462306a36Sopenharmony_ci XFS_QLOWSP_1_PCNT = 0, 2562306a36Sopenharmony_ci XFS_QLOWSP_3_PCNT, 2662306a36Sopenharmony_ci XFS_QLOWSP_5_PCNT, 2762306a36Sopenharmony_ci XFS_QLOWSP_MAX 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct xfs_dquot_res { 3162306a36Sopenharmony_ci /* Total resources allocated and reserved. */ 3262306a36Sopenharmony_ci xfs_qcnt_t reserved; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci /* Total resources allocated. */ 3562306a36Sopenharmony_ci xfs_qcnt_t count; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci /* Absolute and preferred limits. */ 3862306a36Sopenharmony_ci xfs_qcnt_t hardlimit; 3962306a36Sopenharmony_ci xfs_qcnt_t softlimit; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* 4262306a36Sopenharmony_ci * For root dquots, this is the default grace period, in seconds. 4362306a36Sopenharmony_ci * Otherwise, this is when the quota grace period expires, 4462306a36Sopenharmony_ci * in seconds since the Unix epoch. 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci time64_t timer; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic inline bool 5062306a36Sopenharmony_cixfs_dquot_res_over_limits( 5162306a36Sopenharmony_ci const struct xfs_dquot_res *qres) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci if ((qres->softlimit && qres->softlimit < qres->reserved) || 5462306a36Sopenharmony_ci (qres->hardlimit && qres->hardlimit < qres->reserved)) 5562306a36Sopenharmony_ci return true; 5662306a36Sopenharmony_ci return false; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* 6062306a36Sopenharmony_ci * The incore dquot structure 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_cistruct xfs_dquot { 6362306a36Sopenharmony_ci struct list_head q_lru; 6462306a36Sopenharmony_ci struct xfs_mount *q_mount; 6562306a36Sopenharmony_ci xfs_dqtype_t q_type; 6662306a36Sopenharmony_ci uint16_t q_flags; 6762306a36Sopenharmony_ci xfs_dqid_t q_id; 6862306a36Sopenharmony_ci uint q_nrefs; 6962306a36Sopenharmony_ci int q_bufoffset; 7062306a36Sopenharmony_ci xfs_daddr_t q_blkno; 7162306a36Sopenharmony_ci xfs_fileoff_t q_fileoffset; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci struct xfs_dquot_res q_blk; /* regular blocks */ 7462306a36Sopenharmony_ci struct xfs_dquot_res q_ino; /* inodes */ 7562306a36Sopenharmony_ci struct xfs_dquot_res q_rtb; /* realtime blocks */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci struct xfs_dq_logitem q_logitem; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci xfs_qcnt_t q_prealloc_lo_wmark; 8062306a36Sopenharmony_ci xfs_qcnt_t q_prealloc_hi_wmark; 8162306a36Sopenharmony_ci int64_t q_low_space[XFS_QLOWSP_MAX]; 8262306a36Sopenharmony_ci struct mutex q_qlock; 8362306a36Sopenharmony_ci struct completion q_flush; 8462306a36Sopenharmony_ci atomic_t q_pincount; 8562306a36Sopenharmony_ci struct wait_queue_head q_pinwait; 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* 8962306a36Sopenharmony_ci * Lock hierarchy for q_qlock: 9062306a36Sopenharmony_ci * XFS_QLOCK_NORMAL is the implicit default, 9162306a36Sopenharmony_ci * XFS_QLOCK_NESTED is the dquot with the higher id in xfs_dqlock2 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_cienum { 9462306a36Sopenharmony_ci XFS_QLOCK_NORMAL = 0, 9562306a36Sopenharmony_ci XFS_QLOCK_NESTED, 9662306a36Sopenharmony_ci}; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* 9962306a36Sopenharmony_ci * Manage the q_flush completion queue embedded in the dquot. This completion 10062306a36Sopenharmony_ci * queue synchronizes processes attempting to flush the in-core dquot back to 10162306a36Sopenharmony_ci * disk. 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_cistatic inline void xfs_dqflock(struct xfs_dquot *dqp) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci wait_for_completion(&dqp->q_flush); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic inline bool xfs_dqflock_nowait(struct xfs_dquot *dqp) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci return try_wait_for_completion(&dqp->q_flush); 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic inline void xfs_dqfunlock(struct xfs_dquot *dqp) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci complete(&dqp->q_flush); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic inline int xfs_dqlock_nowait(struct xfs_dquot *dqp) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci return mutex_trylock(&dqp->q_qlock); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic inline void xfs_dqlock(struct xfs_dquot *dqp) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci mutex_lock(&dqp->q_qlock); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic inline void xfs_dqunlock(struct xfs_dquot *dqp) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci mutex_unlock(&dqp->q_qlock); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic inline int 13462306a36Sopenharmony_cixfs_dquot_type(const struct xfs_dquot *dqp) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci return dqp->q_type & XFS_DQTYPE_REC_MASK; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic inline int xfs_this_quota_on(struct xfs_mount *mp, xfs_dqtype_t type) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci switch (type) { 14262306a36Sopenharmony_ci case XFS_DQTYPE_USER: 14362306a36Sopenharmony_ci return XFS_IS_UQUOTA_ON(mp); 14462306a36Sopenharmony_ci case XFS_DQTYPE_GROUP: 14562306a36Sopenharmony_ci return XFS_IS_GQUOTA_ON(mp); 14662306a36Sopenharmony_ci case XFS_DQTYPE_PROJ: 14762306a36Sopenharmony_ci return XFS_IS_PQUOTA_ON(mp); 14862306a36Sopenharmony_ci default: 14962306a36Sopenharmony_ci return 0; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic inline struct xfs_dquot *xfs_inode_dquot( 15462306a36Sopenharmony_ci struct xfs_inode *ip, 15562306a36Sopenharmony_ci xfs_dqtype_t type) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci switch (type) { 15862306a36Sopenharmony_ci case XFS_DQTYPE_USER: 15962306a36Sopenharmony_ci return ip->i_udquot; 16062306a36Sopenharmony_ci case XFS_DQTYPE_GROUP: 16162306a36Sopenharmony_ci return ip->i_gdquot; 16262306a36Sopenharmony_ci case XFS_DQTYPE_PROJ: 16362306a36Sopenharmony_ci return ip->i_pdquot; 16462306a36Sopenharmony_ci default: 16562306a36Sopenharmony_ci return NULL; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/* Decide if the dquot's limits are actually being enforced. */ 17062306a36Sopenharmony_cistatic inline bool 17162306a36Sopenharmony_cixfs_dquot_is_enforced( 17262306a36Sopenharmony_ci const struct xfs_dquot *dqp) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci switch (xfs_dquot_type(dqp)) { 17562306a36Sopenharmony_ci case XFS_DQTYPE_USER: 17662306a36Sopenharmony_ci return XFS_IS_UQUOTA_ENFORCED(dqp->q_mount); 17762306a36Sopenharmony_ci case XFS_DQTYPE_GROUP: 17862306a36Sopenharmony_ci return XFS_IS_GQUOTA_ENFORCED(dqp->q_mount); 17962306a36Sopenharmony_ci case XFS_DQTYPE_PROJ: 18062306a36Sopenharmony_ci return XFS_IS_PQUOTA_ENFORCED(dqp->q_mount); 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci ASSERT(0); 18362306a36Sopenharmony_ci return false; 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* 18762306a36Sopenharmony_ci * Check whether a dquot is under low free space conditions. We assume the quota 18862306a36Sopenharmony_ci * is enabled and enforced. 18962306a36Sopenharmony_ci */ 19062306a36Sopenharmony_cistatic inline bool xfs_dquot_lowsp(struct xfs_dquot *dqp) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci int64_t freesp; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci freesp = dqp->q_blk.hardlimit - dqp->q_blk.reserved; 19562306a36Sopenharmony_ci if (freesp < dqp->q_low_space[XFS_QLOWSP_1_PCNT]) 19662306a36Sopenharmony_ci return true; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci return false; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_civoid xfs_dquot_to_disk(struct xfs_disk_dquot *ddqp, struct xfs_dquot *dqp); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci#define XFS_DQ_IS_LOCKED(dqp) (mutex_is_locked(&((dqp)->q_qlock))) 20462306a36Sopenharmony_ci#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->q_flags & XFS_DQFLAG_DIRTY) 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_civoid xfs_qm_dqdestroy(struct xfs_dquot *dqp); 20762306a36Sopenharmony_ciint xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf **bpp); 20862306a36Sopenharmony_civoid xfs_qm_dqunpin_wait(struct xfs_dquot *dqp); 20962306a36Sopenharmony_civoid xfs_qm_adjust_dqtimers(struct xfs_dquot *d); 21062306a36Sopenharmony_civoid xfs_qm_adjust_dqlimits(struct xfs_dquot *d); 21162306a36Sopenharmony_cixfs_dqid_t xfs_qm_id_for_quotatype(struct xfs_inode *ip, 21262306a36Sopenharmony_ci xfs_dqtype_t type); 21362306a36Sopenharmony_ciint xfs_qm_dqget(struct xfs_mount *mp, xfs_dqid_t id, 21462306a36Sopenharmony_ci xfs_dqtype_t type, bool can_alloc, 21562306a36Sopenharmony_ci struct xfs_dquot **dqpp); 21662306a36Sopenharmony_ciint xfs_qm_dqget_inode(struct xfs_inode *ip, xfs_dqtype_t type, 21762306a36Sopenharmony_ci bool can_alloc, struct xfs_dquot **dqpp); 21862306a36Sopenharmony_ciint xfs_qm_dqget_next(struct xfs_mount *mp, xfs_dqid_t id, 21962306a36Sopenharmony_ci xfs_dqtype_t type, struct xfs_dquot **dqpp); 22062306a36Sopenharmony_ciint xfs_qm_dqget_uncached(struct xfs_mount *mp, 22162306a36Sopenharmony_ci xfs_dqid_t id, xfs_dqtype_t type, 22262306a36Sopenharmony_ci struct xfs_dquot **dqpp); 22362306a36Sopenharmony_civoid xfs_qm_dqput(struct xfs_dquot *dqp); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_civoid xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_civoid xfs_dquot_set_prealloc_limits(struct xfs_dquot *); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci xfs_dqlock(dqp); 23262306a36Sopenharmony_ci dqp->q_nrefs++; 23362306a36Sopenharmony_ci xfs_dqunlock(dqp); 23462306a36Sopenharmony_ci return dqp; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_citypedef int (*xfs_qm_dqiterate_fn)(struct xfs_dquot *dq, 23862306a36Sopenharmony_ci xfs_dqtype_t type, void *priv); 23962306a36Sopenharmony_ciint xfs_qm_dqiterate(struct xfs_mount *mp, xfs_dqtype_t type, 24062306a36Sopenharmony_ci xfs_qm_dqiterate_fn iter_fn, void *priv); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_citime64_t xfs_dquot_set_timeout(struct xfs_mount *mp, time64_t timeout); 24362306a36Sopenharmony_citime64_t xfs_dquot_set_grace_period(time64_t grace); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci#endif /* __XFS_DQUOT_H__ */ 246