linux/fs/xfs/xfs_dquot.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2000-2003 Silicon Graphics, Inc.
 * All Rights Reserved.
 */
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_format.h"
#include "xfs_log_format.h"
#include "xfs_shared.h"
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_bmap.h"
#include "xfs_quota.h"
#include "xfs_trans.h"
#include "xfs_buf_item.h"
#include "xfs_trans_space.h"
#include "xfs_trans_priv.h"
#include "xfs_qm.h"
#include "xfs_trace.h"
#include "xfs_log.h"
#include "xfs_bmap_btree.h"
#include "xfs_error.h"
#include "xfs_health.h"

/*
 * Lock order:
 *
 * ip->i_lock
 *   qi->qi_tree_lock
 *     dquot->q_qlock (xfs_dqlock() and friends)
 *       dquot->q_flush (xfs_dqflock() and friends)
 *       qi->qi_lru_lock
 *
 * If two dquots need to be locked the order is user before group/project,
 * otherwise by the lowest id first, see xfs_dqlock2.
 */

struct kmem_cache		*xfs_dqtrx_cache;
static struct kmem_cache	*xfs_dquot_cache;

static struct lock_class_key xfs_dquot_group_class;
static struct lock_class_key xfs_dquot_project_class;

/* Record observations of quota corruption with the health tracking system. */
static void
xfs_dquot_mark_sick(
	struct xfs_dquot	*dqp)
{}

/*
 * This is called to free all the memory associated with a dquot
 */
void
xfs_qm_dqdestroy(
	struct xfs_dquot	*dqp)
{}

/*
 * If default limits are in force, push them into the dquot now.
 * We overwrite the dquot limits only if they are zero and this
 * is not the root dquot.
 */
void
xfs_qm_adjust_dqlimits(
	struct xfs_dquot	*dq)
{}

/* Set the expiration time of a quota's grace period. */
time64_t
xfs_dquot_set_timeout(
	struct xfs_mount	*mp,
	time64_t		timeout)
{}

/* Set the length of the default grace period. */
time64_t
xfs_dquot_set_grace_period(
	time64_t		grace)
{}

/*
 * Determine if this quota counter is over either limit and set the quota
 * timers as appropriate.
 */
static inline void
xfs_qm_adjust_res_timer(
	struct xfs_mount	*mp,
	struct xfs_dquot_res	*res,
	struct xfs_quota_limits	*qlim)
{}

/*
 * Check the limits and timers of a dquot and start or reset timers
 * if necessary.
 * This gets called even when quota enforcement is OFF, which makes our
 * life a little less complicated. (We just don't reject any quota
 * reservations in that case, when enforcement is off).
 * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
 * enforcement's off.
 * In contrast, warnings are a little different in that they don't
 * 'automatically' get started when limits get exceeded.  They do
 * get reset to zero, however, when we find the count to be under
 * the soft limit (they are only ever set non-zero via userspace).
 */
void
xfs_qm_adjust_dqtimers(
	struct xfs_dquot	*dq)
{}

/*
 * initialize a buffer full of dquots and log the whole thing
 */
void
xfs_qm_init_dquot_blk(
	struct xfs_trans	*tp,
	xfs_dqid_t		id,
	xfs_dqtype_t		type,
	struct xfs_buf		*bp)
{}

/*
 * Initialize the dynamic speculative preallocation thresholds. The lo/hi
 * watermarks correspond to the soft and hard limits by default. If a soft limit
 * is not specified, we use 95% of the hard limit.
 */
void
xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
{}

/*
 * Ensure that the given in-core dquot has a buffer on disk backing it, and
 * return the buffer locked and held. This is called when the bmapi finds a
 * hole.
 */
STATIC int
xfs_dquot_disk_alloc(
	struct xfs_dquot	*dqp,
	struct xfs_buf		**bpp)
{}

/*
 * Read in the in-core dquot's on-disk metadata and return the buffer.
 * Returns ENOENT to signal a hole.
 */
STATIC int
xfs_dquot_disk_read(
	struct xfs_mount	*mp,
	struct xfs_dquot	*dqp,
	struct xfs_buf		**bpp)
{}

/* Allocate and initialize everything we need for an incore dquot. */
STATIC struct xfs_dquot *
xfs_dquot_alloc(
	struct xfs_mount	*mp,
	xfs_dqid_t		id,
	xfs_dqtype_t		type)
{}

/* Check the ondisk dquot's id and type match what the incore dquot expects. */
static bool
xfs_dquot_check_type(
	struct xfs_dquot	*dqp,
	struct xfs_disk_dquot	*ddqp)
{}

/* Copy the in-core quota fields in from the on-disk buffer. */
STATIC int
xfs_dquot_from_disk(
	struct xfs_dquot	*dqp,
	struct xfs_buf		*bp)
{}

/* Copy the in-core quota fields into the on-disk buffer. */
void
xfs_dquot_to_disk(
	struct xfs_disk_dquot	*ddqp,
	struct xfs_dquot	*dqp)
{}

/*
 * Read in the ondisk dquot using dqtobp() then copy it to an incore version,
 * and release the buffer immediately.  If @can_alloc is true, fill any
 * holes in the on-disk metadata.
 */
static int
xfs_qm_dqread(
	struct xfs_mount	*mp,
	xfs_dqid_t		id,
	xfs_dqtype_t		type,
	bool			can_alloc,
	struct xfs_dquot	**dqpp)
{}

/*
 * Advance to the next id in the current chunk, or if at the
 * end of the chunk, skip ahead to first id in next allocated chunk
 * using the SEEK_DATA interface.
 */
static int
xfs_dq_get_next_id(
	struct xfs_mount	*mp,
	xfs_dqtype_t		type,
	xfs_dqid_t		*id)
{}

/*
 * Look up the dquot in the in-core cache.  If found, the dquot is returned
 * locked and ready to go.
 */
static struct xfs_dquot *
xfs_qm_dqget_cache_lookup(
	struct xfs_mount	*mp,
	struct xfs_quotainfo	*qi,
	struct radix_tree_root	*tree,
	xfs_dqid_t		id)
{}

/*
 * Try to insert a new dquot into the in-core cache.  If an error occurs the
 * caller should throw away the dquot and start over.  Otherwise, the dquot
 * is returned locked (and held by the cache) as if there had been a cache
 * hit.
 *
 * The insert needs to be done under memalloc_nofs context because the radix
 * tree can do memory allocation during insert. The qi->qi_tree_lock is taken in
 * memory reclaim when freeing unused dquots, so we cannot have the radix tree
 * node allocation recursing into filesystem reclaim whilst we hold the
 * qi_tree_lock.
 */
static int
xfs_qm_dqget_cache_insert(
	struct xfs_mount	*mp,
	struct xfs_quotainfo	*qi,
	struct radix_tree_root	*tree,
	xfs_dqid_t		id,
	struct xfs_dquot	*dqp)
{}

/* Check our input parameters. */
static int
xfs_qm_dqget_checks(
	struct xfs_mount	*mp,
	xfs_dqtype_t		type)
{}

/*
 * Given the file system, id, and type (UDQUOT/GDQUOT/PDQUOT), return a
 * locked dquot, doing an allocation (if requested) as needed.
 */
int
xfs_qm_dqget(
	struct xfs_mount	*mp,
	xfs_dqid_t		id,
	xfs_dqtype_t		type,
	bool			can_alloc,
	struct xfs_dquot	**O_dqpp)
{}

/*
 * Given a dquot id and type, read and initialize a dquot from the on-disk
 * metadata.  This function is only for use during quota initialization so
 * it ignores the dquot cache assuming that the dquot shrinker isn't set up.
 * The caller is responsible for _qm_dqdestroy'ing the returned dquot.
 */
int
xfs_qm_dqget_uncached(
	struct xfs_mount	*mp,
	xfs_dqid_t		id,
	xfs_dqtype_t		type,
	struct xfs_dquot	**dqpp)
{}

/* Return the quota id for a given inode and type. */
xfs_dqid_t
xfs_qm_id_for_quotatype(
	struct xfs_inode	*ip,
	xfs_dqtype_t		type)
{}

/*
 * Return the dquot for a given inode and type.  If @can_alloc is true, then
 * allocate blocks if needed.  The inode's ILOCK must be held and it must not
 * have already had an inode attached.
 */
int
xfs_qm_dqget_inode(
	struct xfs_inode	*ip,
	xfs_dqtype_t		type,
	bool			can_alloc,
	struct xfs_dquot	**O_dqpp)
{}

/*
 * Starting at @id and progressing upwards, look for an initialized incore
 * dquot, lock it, and return it.
 */
int
xfs_qm_dqget_next(
	struct xfs_mount	*mp,
	xfs_dqid_t		id,
	xfs_dqtype_t		type,
	struct xfs_dquot	**dqpp)
{}

/*
 * Release a reference to the dquot (decrement ref-count) and unlock it.
 *
 * If there is a group quota attached to this dquot, carefully release that
 * too without tripping over deadlocks'n'stuff.
 */
void
xfs_qm_dqput(
	struct xfs_dquot	*dqp)
{}

/*
 * Release a dquot. Flush it if dirty, then dqput() it.
 * dquot must not be locked.
 */
void
xfs_qm_dqrele(
	struct xfs_dquot	*dqp)
{}

/*
 * This is the dquot flushing I/O completion routine.  It is called
 * from interrupt level when the buffer containing the dquot is
 * flushed to disk.  It is responsible for removing the dquot logitem
 * from the AIL if it has not been re-logged, and unlocking the dquot's
 * flush lock. This behavior is very similar to that of inodes..
 */
static void
xfs_qm_dqflush_done(
	struct xfs_log_item	*lip)
{}

void
xfs_buf_dquot_iodone(
	struct xfs_buf		*bp)
{}

void
xfs_buf_dquot_io_fail(
	struct xfs_buf		*bp)
{}

/* Check incore dquot for errors before we flush. */
static xfs_failaddr_t
xfs_qm_dqflush_check(
	struct xfs_dquot	*dqp)
{}

/*
 * Write a modified dquot to disk.
 * The dquot must be locked and the flush lock too taken by caller.
 * The flush lock will not be unlocked until the dquot reaches the disk,
 * but the dquot is free to be unlocked and modified by the caller
 * in the interim. Dquot is still locked on return. This behavior is
 * identical to that of inodes.
 */
int
xfs_qm_dqflush(
	struct xfs_dquot	*dqp,
	struct xfs_buf		**bpp)
{}

/*
 * Lock two xfs_dquot structures.
 *
 * To avoid deadlocks we always lock the quota structure with
 * the lowerd id first.
 */
void
xfs_dqlock2(
	struct xfs_dquot	*d1,
	struct xfs_dquot	*d2)
{}

static int
xfs_dqtrx_cmp(
	const void		*a,
	const void		*b)
{}

void
xfs_dqlockn(
	struct xfs_dqtrx	*q)
{}

int __init
xfs_qm_init(void)
{}

void
xfs_qm_exit(void)
{}