linux/fs/gfs2/quota.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
 * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 */

/*
 * Quota change tags are associated with each transaction that allocates or
 * deallocates space.  Those changes are accumulated locally to each node (in a
 * per-node file) and then are periodically synced to the quota file.  This
 * avoids the bottleneck of constantly touching the quota file, but introduces
 * fuzziness in the current usage value of IDs that are being used on different
 * nodes in the cluster simultaneously.  So, it is possible for a user on
 * multiple nodes to overrun their quota, but that overrun is controlable.
 * Since quota tags are part of transactions, there is no need for a quota check
 * program to be run on node crashes or anything like that.
 *
 * There are couple of knobs that let the administrator manage the quota
 * fuzziness.  "quota_quantum" sets the maximum time a quota change can be
 * sitting on one node before being synced to the quota file.  (The default is
 * 60 seconds.)  Another knob, "quota_scale" controls how quickly the frequency
 * of quota file syncs increases as the user moves closer to their limit.  The
 * more frequent the syncs, the more accurate the quota enforcement, but that
 * means that there is more contention between the nodes for the quota file.
 * The default value is one.  This sets the maximum theoretical quota overrun
 * (with infinite node with infinite bandwidth) to twice the user's limit.  (In
 * practice, the maximum overrun you see should be much less.)  A "quota_scale"
 * number greater than one makes quota syncs more frequent and reduces the
 * maximum overrun.  Numbers less than one (but greater than zero) make quota
 * syncs less frequent.
 *
 * GFS quotas also use per-ID Lock Value Blocks (LVBs) to cache the contents of
 * the quota file, so it is not being constantly read.
 */

#define pr_fmt(fmt)

#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/sort.h>
#include <linux/fs.h>
#include <linux/bio.h>
#include <linux/gfs2_ondisk.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/quota.h>
#include <linux/dqblk_xfs.h>
#include <linux/lockref.h>
#include <linux/list_lru.h>
#include <linux/rcupdate.h>
#include <linux/rculist_bl.h>
#include <linux/bit_spinlock.h>
#include <linux/jhash.h>
#include <linux/vmalloc.h>

#include "gfs2.h"
#include "incore.h"
#include "bmap.h"
#include "glock.h"
#include "glops.h"
#include "log.h"
#include "meta_io.h"
#include "quota.h"
#include "rgrp.h"
#include "super.h"
#include "trans.h"
#include "inode.h"
#include "util.h"

#define GFS2_QD_HASH_SHIFT
#define GFS2_QD_HASH_SIZE
#define GFS2_QD_HASH_MASK

/* Lock order: qd_lock -> bucket lock -> qd->lockref.lock -> lru lock */
/*                     -> sd_bitmap_lock                              */
static DEFINE_SPINLOCK(qd_lock);
struct list_lru gfs2_qd_lru;

static struct hlist_bl_head qd_hash_table[GFS2_QD_HASH_SIZE];

static unsigned int gfs2_qd_hash(const struct gfs2_sbd *sdp,
				 const struct kqid qid)
{}

static inline void spin_lock_bucket(unsigned int hash)
{}

static inline void spin_unlock_bucket(unsigned int hash)
{}

static void gfs2_qd_dealloc(struct rcu_head *rcu)
{}

static void gfs2_qd_dispose(struct gfs2_quota_data *qd)
{}

static void gfs2_qd_list_dispose(struct list_head *list)
{}


static enum lru_status gfs2_qd_isolate(struct list_head *item,
		struct list_lru_one *lru, spinlock_t *lru_lock, void *arg)
{}

static unsigned long gfs2_qd_shrink_scan(struct shrinker *shrink,
					 struct shrink_control *sc)
{}

static unsigned long gfs2_qd_shrink_count(struct shrinker *shrink,
					  struct shrink_control *sc)
{}

static struct shrinker *gfs2_qd_shrinker;

int __init gfs2_qd_shrinker_init(void)
{}

void gfs2_qd_shrinker_exit(void)
{}

static u64 qd2index(struct gfs2_quota_data *qd)
{}

static u64 qd2offset(struct gfs2_quota_data *qd)
{}

static struct gfs2_quota_data *qd_alloc(unsigned hash, struct gfs2_sbd *sdp, struct kqid qid)
{}

static struct gfs2_quota_data *gfs2_qd_search_bucket(unsigned int hash,
						     const struct gfs2_sbd *sdp,
						     struct kqid qid)
{}


static int qd_get(struct gfs2_sbd *sdp, struct kqid qid,
		  struct gfs2_quota_data **qdp)
{}


static void __qd_hold(struct gfs2_quota_data *qd)
{}

static void qd_put(struct gfs2_quota_data *qd)
{}

static int slot_get(struct gfs2_quota_data *qd)
{}

static void slot_hold(struct gfs2_quota_data *qd)
{}

static void slot_put(struct gfs2_quota_data *qd)
{}

static int bh_get(struct gfs2_quota_data *qd)
{}

static void bh_put(struct gfs2_quota_data *qd)
{}

static bool qd_grab_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd,
			 u64 sync_gen)
{}

static void qd_ungrab_sync(struct gfs2_quota_data *qd)
{}

static void qdsb_put(struct gfs2_quota_data *qd)
{}

static void qd_unlock(struct gfs2_quota_data *qd)
{}

static int qdsb_get(struct gfs2_sbd *sdp, struct kqid qid,
		    struct gfs2_quota_data **qdp)
{}

/**
 * gfs2_qa_get - make sure we have a quota allocations data structure,
 *               if necessary
 * @ip: the inode for this reservation
 */
int gfs2_qa_get(struct gfs2_inode *ip)
{}

void gfs2_qa_put(struct gfs2_inode *ip)
{}

int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
{}

void gfs2_quota_unhold(struct gfs2_inode *ip)
{}

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

static void do_qc(struct gfs2_quota_data *qd, s64 change)
{}

static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index,
				  unsigned off, void *buf, unsigned bytes)
{}

static int gfs2_write_disk_quota(struct gfs2_sbd *sdp, struct gfs2_quota *qp,
				 loff_t loc)
{}

/**
 * gfs2_adjust_quota - adjust record of current block usage
 * @sdp: The superblock
 * @loc: Offset of the entry in the quota file
 * @change: The amount of usage change to record
 * @qd: The quota data
 * @fdq: The updated limits to record
 *
 * This function was mostly borrowed from gfs2_block_truncate_page which was
 * in turn mostly borrowed from ext3
 *
 * Returns: 0 or -ve on error
 */

static int gfs2_adjust_quota(struct gfs2_sbd *sdp, loff_t loc,
			     s64 change, struct gfs2_quota_data *qd,
			     struct qc_dqblk *fdq)
{}

static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda,
		   u64 sync_gen)
{}

static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
{}

static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
		    struct gfs2_holder *q_gh)
{}

int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
{}

static bool need_sync(struct gfs2_quota_data *qd)
{}

void gfs2_quota_unlock(struct gfs2_inode *ip)
{}

#define MAX_LINE

static void print_message(struct gfs2_quota_data *qd, char *type)
{}

/**
 * gfs2_quota_check - check if allocating new blocks will exceed quota
 * @ip:  The inode for which this check is being performed
 * @uid: The uid to check against
 * @gid: The gid to check against
 * @ap:  The allocation parameters. ap->target contains the requested
 *       blocks. ap->min_target, if set, contains the minimum blks
 *       requested.
 *
 * Returns: 0 on success.
 *                  min_req = ap->min_target ? ap->min_target : ap->target;
 *                  quota must allow at least min_req blks for success and
 *                  ap->allowed is set to the number of blocks allowed
 *
 *          -EDQUOT otherwise, quota violation. ap->allowed is set to number
 *                  of blocks available.
 */
int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
		     struct gfs2_alloc_parms *ap)
{}

void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
		       kuid_t uid, kgid_t gid)
{}

int gfs2_quota_sync(struct super_block *sb, int type)
{}

int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid)
{}

int gfs2_quota_init(struct gfs2_sbd *sdp)
{}

void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
{}

static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error)
{}

static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg,
			       int (*fxn)(struct super_block *sb, int type),
			       unsigned long t, unsigned long *timeo,
			       unsigned int *new_timeo)
{}

void gfs2_wake_up_statfs(struct gfs2_sbd *sdp) {}


/**
 * gfs2_quotad - Write cached quota changes into the quota file
 * @data: Pointer to GFS2 superblock
 *
 */

int gfs2_quotad(void *data)
{}

static int gfs2_quota_get_state(struct super_block *sb, struct qc_state *state)
{}

static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
			  struct qc_dqblk *fdq)
{}

/* GFS2 only supports a subset of the XFS fields */
#define GFS2_FIELDMASK

static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
			  struct qc_dqblk *fdq)
{}

const struct quotactl_ops gfs2_quotactl_ops =;

void __init gfs2_quota_hash_init(void)
{}