xref: /kernel/linux/linux-5.10/fs/quota/dquot.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Implementation of the diskquota system for the LINUX operating system. QUOTA
48c2ecf20Sopenharmony_ci * is implemented using the BSD system call interface as the means of
58c2ecf20Sopenharmony_ci * communication with the user level. This file contains the generic routines
68c2ecf20Sopenharmony_ci * called by the different filesystems on allocation of an inode or block.
78c2ecf20Sopenharmony_ci * These routines take care of the administration needed to have a consistent
88c2ecf20Sopenharmony_ci * diskquota tracking system. The ideas of both user and group quotas are based
98c2ecf20Sopenharmony_ci * on the Melbourne quota system as used on BSD derived systems. The internal
108c2ecf20Sopenharmony_ci * implementation is based on one of the several variants of the LINUX
118c2ecf20Sopenharmony_ci * inode-subsystem with added complexity of the diskquota system.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * Author:	Marco van Wieringen <mvw@planets.elm.net>
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * Fixes:   Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *		Revised list management to avoid races
188c2ecf20Sopenharmony_ci *		-- Bill Hawes, <whawes@star.net>, 9/98
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci *		Fixed races in dquot_transfer(), dqget() and dquot_alloc_...().
218c2ecf20Sopenharmony_ci *		As the consequence the locking was moved from dquot_decr_...(),
228c2ecf20Sopenharmony_ci *		dquot_incr_...() to calling functions.
238c2ecf20Sopenharmony_ci *		invalidate_dquots() now writes modified dquots.
248c2ecf20Sopenharmony_ci *		Serialized quota_off() and quota_on() for mount point.
258c2ecf20Sopenharmony_ci *		Fixed a few bugs in grow_dquots().
268c2ecf20Sopenharmony_ci *		Fixed deadlock in write_dquot() - we no longer account quotas on
278c2ecf20Sopenharmony_ci *		quota files
288c2ecf20Sopenharmony_ci *		remove_dquot_ref() moved to inode.c - it now traverses through inodes
298c2ecf20Sopenharmony_ci *		add_dquot_ref() restarts after blocking
308c2ecf20Sopenharmony_ci *		Added check for bogus uid and fixed check for group in quotactl.
318c2ecf20Sopenharmony_ci *		Jan Kara, <jack@suse.cz>, sponsored by SuSE CR, 10-11/99
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci *		Used struct list_head instead of own list struct
348c2ecf20Sopenharmony_ci *		Invalidation of referenced dquots is no longer possible
358c2ecf20Sopenharmony_ci *		Improved free_dquots list management
368c2ecf20Sopenharmony_ci *		Quota and i_blocks are now updated in one place to avoid races
378c2ecf20Sopenharmony_ci *		Warnings are now delayed so we won't block in critical section
388c2ecf20Sopenharmony_ci *		Write updated not to require dquot lock
398c2ecf20Sopenharmony_ci *		Jan Kara, <jack@suse.cz>, 9/2000
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci *		Added dynamic quota structure allocation
428c2ecf20Sopenharmony_ci *		Jan Kara <jack@suse.cz> 12/2000
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci *		Rewritten quota interface. Implemented new quota format and
458c2ecf20Sopenharmony_ci *		formats registering.
468c2ecf20Sopenharmony_ci *		Jan Kara, <jack@suse.cz>, 2001,2002
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci *		New SMP locking.
498c2ecf20Sopenharmony_ci *		Jan Kara, <jack@suse.cz>, 10/2002
508c2ecf20Sopenharmony_ci *
518c2ecf20Sopenharmony_ci *		Added journalled quota support, fix lock inversion problems
528c2ecf20Sopenharmony_ci *		Jan Kara, <jack@suse.cz>, 2003,2004
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * (C) Copyright 1994 - 1997 Marco van Wieringen
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#include <linux/errno.h>
588c2ecf20Sopenharmony_ci#include <linux/kernel.h>
598c2ecf20Sopenharmony_ci#include <linux/fs.h>
608c2ecf20Sopenharmony_ci#include <linux/mount.h>
618c2ecf20Sopenharmony_ci#include <linux/mm.h>
628c2ecf20Sopenharmony_ci#include <linux/time.h>
638c2ecf20Sopenharmony_ci#include <linux/types.h>
648c2ecf20Sopenharmony_ci#include <linux/string.h>
658c2ecf20Sopenharmony_ci#include <linux/fcntl.h>
668c2ecf20Sopenharmony_ci#include <linux/stat.h>
678c2ecf20Sopenharmony_ci#include <linux/tty.h>
688c2ecf20Sopenharmony_ci#include <linux/file.h>
698c2ecf20Sopenharmony_ci#include <linux/slab.h>
708c2ecf20Sopenharmony_ci#include <linux/sysctl.h>
718c2ecf20Sopenharmony_ci#include <linux/init.h>
728c2ecf20Sopenharmony_ci#include <linux/module.h>
738c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
748c2ecf20Sopenharmony_ci#include <linux/security.h>
758c2ecf20Sopenharmony_ci#include <linux/sched.h>
768c2ecf20Sopenharmony_ci#include <linux/cred.h>
778c2ecf20Sopenharmony_ci#include <linux/kmod.h>
788c2ecf20Sopenharmony_ci#include <linux/namei.h>
798c2ecf20Sopenharmony_ci#include <linux/capability.h>
808c2ecf20Sopenharmony_ci#include <linux/quotaops.h>
818c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
828c2ecf20Sopenharmony_ci#include <linux/sched/mm.h>
838c2ecf20Sopenharmony_ci#include "../internal.h" /* ugh */
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/*
888c2ecf20Sopenharmony_ci * There are five quota SMP locks:
898c2ecf20Sopenharmony_ci * * dq_list_lock protects all lists with quotas and quota formats.
908c2ecf20Sopenharmony_ci * * dquot->dq_dqb_lock protects data from dq_dqb
918c2ecf20Sopenharmony_ci * * inode->i_lock protects inode->i_blocks, i_bytes and also guards
928c2ecf20Sopenharmony_ci *   consistency of dquot->dq_dqb with inode->i_blocks, i_bytes so that
938c2ecf20Sopenharmony_ci *   dquot_transfer() can stabilize amount it transfers
948c2ecf20Sopenharmony_ci * * dq_data_lock protects mem_dqinfo structures and modifications of dquot
958c2ecf20Sopenharmony_ci *   pointers in the inode
968c2ecf20Sopenharmony_ci * * dq_state_lock protects modifications of quota state (on quotaon and
978c2ecf20Sopenharmony_ci *   quotaoff) and readers who care about latest values take it as well.
988c2ecf20Sopenharmony_ci *
998c2ecf20Sopenharmony_ci * The spinlock ordering is hence:
1008c2ecf20Sopenharmony_ci *   dq_data_lock > dq_list_lock > i_lock > dquot->dq_dqb_lock,
1018c2ecf20Sopenharmony_ci *   dq_list_lock > dq_state_lock
1028c2ecf20Sopenharmony_ci *
1038c2ecf20Sopenharmony_ci * Note that some things (eg. sb pointer, type, id) doesn't change during
1048c2ecf20Sopenharmony_ci * the life of the dquot structure and so needn't to be protected by a lock
1058c2ecf20Sopenharmony_ci *
1068c2ecf20Sopenharmony_ci * Operation accessing dquots via inode pointers are protected by dquot_srcu.
1078c2ecf20Sopenharmony_ci * Operation of reading pointer needs srcu_read_lock(&dquot_srcu), and
1088c2ecf20Sopenharmony_ci * synchronize_srcu(&dquot_srcu) is called after clearing pointers from
1098c2ecf20Sopenharmony_ci * inode and before dropping dquot references to avoid use of dquots after
1108c2ecf20Sopenharmony_ci * they are freed. dq_data_lock is used to serialize the pointer setting and
1118c2ecf20Sopenharmony_ci * clearing operations.
1128c2ecf20Sopenharmony_ci * Special care needs to be taken about S_NOQUOTA inode flag (marking that
1138c2ecf20Sopenharmony_ci * inode is a quota file). Functions adding pointers from inode to dquots have
1148c2ecf20Sopenharmony_ci * to check this flag under dq_data_lock and then (if S_NOQUOTA is not set) they
1158c2ecf20Sopenharmony_ci * have to do all pointer modifications before dropping dq_data_lock. This makes
1168c2ecf20Sopenharmony_ci * sure they cannot race with quotaon which first sets S_NOQUOTA flag and
1178c2ecf20Sopenharmony_ci * then drops all pointers to dquots from an inode.
1188c2ecf20Sopenharmony_ci *
1198c2ecf20Sopenharmony_ci * Each dquot has its dq_lock mutex.  Dquot is locked when it is being read to
1208c2ecf20Sopenharmony_ci * memory (or space for it is being allocated) on the first dqget(), when it is
1218c2ecf20Sopenharmony_ci * being written out, and when it is being released on the last dqput(). The
1228c2ecf20Sopenharmony_ci * allocation and release operations are serialized by the dq_lock and by
1238c2ecf20Sopenharmony_ci * checking the use count in dquot_release().
1248c2ecf20Sopenharmony_ci *
1258c2ecf20Sopenharmony_ci * Lock ordering (including related VFS locks) is the following:
1268c2ecf20Sopenharmony_ci *   s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_sem
1278c2ecf20Sopenharmony_ci */
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
1308c2ecf20Sopenharmony_cistatic __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_state_lock);
1318c2ecf20Sopenharmony_ci__cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_data_lock);
1328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dq_data_lock);
1338c2ecf20Sopenharmony_ciDEFINE_STATIC_SRCU(dquot_srcu);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(dquot_ref_wq);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_civoid __quota_error(struct super_block *sb, const char *func,
1388c2ecf20Sopenharmony_ci		   const char *fmt, ...)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	if (printk_ratelimit()) {
1418c2ecf20Sopenharmony_ci		va_list args;
1428c2ecf20Sopenharmony_ci		struct va_format vaf;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci		va_start(args, fmt);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci		vaf.fmt = fmt;
1478c2ecf20Sopenharmony_ci		vaf.va = &args;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci		printk(KERN_ERR "Quota error (device %s): %s: %pV\n",
1508c2ecf20Sopenharmony_ci		       sb->s_id, func, &vaf);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci		va_end(args);
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__quota_error);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci#if defined(CONFIG_QUOTA_DEBUG) || defined(CONFIG_PRINT_QUOTA_WARNING)
1588c2ecf20Sopenharmony_cistatic char *quotatypes[] = INITQFNAMES;
1598c2ecf20Sopenharmony_ci#endif
1608c2ecf20Sopenharmony_cistatic struct quota_format_type *quota_formats;	/* List of registered formats */
1618c2ecf20Sopenharmony_cistatic struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci/* SLAB cache for dquot structures */
1648c2ecf20Sopenharmony_cistatic struct kmem_cache *dquot_cachep;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ciint register_quota_format(struct quota_format_type *fmt)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
1698c2ecf20Sopenharmony_ci	fmt->qf_next = quota_formats;
1708c2ecf20Sopenharmony_ci	quota_formats = fmt;
1718c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
1728c2ecf20Sopenharmony_ci	return 0;
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ciEXPORT_SYMBOL(register_quota_format);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_civoid unregister_quota_format(struct quota_format_type *fmt)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	struct quota_format_type **actqf;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
1818c2ecf20Sopenharmony_ci	for (actqf = &quota_formats; *actqf && *actqf != fmt;
1828c2ecf20Sopenharmony_ci	     actqf = &(*actqf)->qf_next)
1838c2ecf20Sopenharmony_ci		;
1848c2ecf20Sopenharmony_ci	if (*actqf)
1858c2ecf20Sopenharmony_ci		*actqf = (*actqf)->qf_next;
1868c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(unregister_quota_format);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic struct quota_format_type *find_quota_format(int id)
1918c2ecf20Sopenharmony_ci{
1928c2ecf20Sopenharmony_ci	struct quota_format_type *actqf;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
1958c2ecf20Sopenharmony_ci	for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id;
1968c2ecf20Sopenharmony_ci	     actqf = actqf->qf_next)
1978c2ecf20Sopenharmony_ci		;
1988c2ecf20Sopenharmony_ci	if (!actqf || !try_module_get(actqf->qf_owner)) {
1998c2ecf20Sopenharmony_ci		int qm;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci		for (qm = 0; module_names[qm].qm_fmt_id &&
2048c2ecf20Sopenharmony_ci			     module_names[qm].qm_fmt_id != id; qm++)
2058c2ecf20Sopenharmony_ci			;
2068c2ecf20Sopenharmony_ci		if (!module_names[qm].qm_fmt_id ||
2078c2ecf20Sopenharmony_ci		    request_module(module_names[qm].qm_mod_name))
2088c2ecf20Sopenharmony_ci			return NULL;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci		spin_lock(&dq_list_lock);
2118c2ecf20Sopenharmony_ci		for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id;
2128c2ecf20Sopenharmony_ci		     actqf = actqf->qf_next)
2138c2ecf20Sopenharmony_ci			;
2148c2ecf20Sopenharmony_ci		if (actqf && !try_module_get(actqf->qf_owner))
2158c2ecf20Sopenharmony_ci			actqf = NULL;
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
2188c2ecf20Sopenharmony_ci	return actqf;
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic void put_quota_format(struct quota_format_type *fmt)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	module_put(fmt->qf_owner);
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci/*
2278c2ecf20Sopenharmony_ci * Dquot List Management:
2288c2ecf20Sopenharmony_ci * The quota code uses five lists for dquot management: the inuse_list,
2298c2ecf20Sopenharmony_ci * releasing_dquots, free_dquots, dqi_dirty_list, and dquot_hash[] array.
2308c2ecf20Sopenharmony_ci * A single dquot structure may be on some of those lists, depending on
2318c2ecf20Sopenharmony_ci * its current state.
2328c2ecf20Sopenharmony_ci *
2338c2ecf20Sopenharmony_ci * All dquots are placed to the end of inuse_list when first created, and this
2348c2ecf20Sopenharmony_ci * list is used for invalidate operation, which must look at every dquot.
2358c2ecf20Sopenharmony_ci *
2368c2ecf20Sopenharmony_ci * When the last reference of a dquot is dropped, the dquot is added to
2378c2ecf20Sopenharmony_ci * releasing_dquots. We'll then queue work item which will call
2388c2ecf20Sopenharmony_ci * synchronize_srcu() and after that perform the final cleanup of all the
2398c2ecf20Sopenharmony_ci * dquots on the list. Each cleaned up dquot is moved to free_dquots list.
2408c2ecf20Sopenharmony_ci * Both releasing_dquots and free_dquots use the dq_free list_head in the dquot
2418c2ecf20Sopenharmony_ci * struct.
2428c2ecf20Sopenharmony_ci *
2438c2ecf20Sopenharmony_ci * Unused and cleaned up dquots are in the free_dquots list and this list is
2448c2ecf20Sopenharmony_ci * searched whenever we need an available dquot. Dquots are removed from the
2458c2ecf20Sopenharmony_ci * list as soon as they are used again and dqstats.free_dquots gives the number
2468c2ecf20Sopenharmony_ci * of dquots on the list. When dquot is invalidated it's completely released
2478c2ecf20Sopenharmony_ci * from memory.
2488c2ecf20Sopenharmony_ci *
2498c2ecf20Sopenharmony_ci * Dirty dquots are added to the dqi_dirty_list of quota_info when mark
2508c2ecf20Sopenharmony_ci * dirtied, and this list is searched when writing dirty dquots back to
2518c2ecf20Sopenharmony_ci * quota file. Note that some filesystems do dirty dquot tracking on their
2528c2ecf20Sopenharmony_ci * own (e.g. in a journal) and thus don't use dqi_dirty_list.
2538c2ecf20Sopenharmony_ci *
2548c2ecf20Sopenharmony_ci * Dquots with a specific identity (device, type and id) are placed on
2558c2ecf20Sopenharmony_ci * one of the dquot_hash[] hash chains. The provides an efficient search
2568c2ecf20Sopenharmony_ci * mechanism to locate a specific dquot.
2578c2ecf20Sopenharmony_ci */
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_cistatic LIST_HEAD(inuse_list);
2608c2ecf20Sopenharmony_cistatic LIST_HEAD(free_dquots);
2618c2ecf20Sopenharmony_cistatic LIST_HEAD(releasing_dquots);
2628c2ecf20Sopenharmony_cistatic unsigned int dq_hash_bits, dq_hash_mask;
2638c2ecf20Sopenharmony_cistatic struct hlist_head *dquot_hash;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistruct dqstats dqstats;
2668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dqstats);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic qsize_t inode_get_rsv_space(struct inode *inode);
2698c2ecf20Sopenharmony_cistatic qsize_t __inode_get_rsv_space(struct inode *inode);
2708c2ecf20Sopenharmony_cistatic int __dquot_initialize(struct inode *inode, int type);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic void quota_release_workfn(struct work_struct *work);
2738c2ecf20Sopenharmony_cistatic DECLARE_DELAYED_WORK(quota_release_work, quota_release_workfn);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic inline unsigned int
2768c2ecf20Sopenharmony_cihashfn(const struct super_block *sb, struct kqid qid)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	unsigned int id = from_kqid(&init_user_ns, qid);
2798c2ecf20Sopenharmony_ci	int type = qid.type;
2808c2ecf20Sopenharmony_ci	unsigned long tmp;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	tmp = (((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type);
2838c2ecf20Sopenharmony_ci	return (tmp + (tmp >> dq_hash_bits)) & dq_hash_mask;
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci/*
2878c2ecf20Sopenharmony_ci * Following list functions expect dq_list_lock to be held
2888c2ecf20Sopenharmony_ci */
2898c2ecf20Sopenharmony_cistatic inline void insert_dquot_hash(struct dquot *dquot)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct hlist_head *head;
2928c2ecf20Sopenharmony_ci	head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id);
2938c2ecf20Sopenharmony_ci	hlist_add_head(&dquot->dq_hash, head);
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic inline void remove_dquot_hash(struct dquot *dquot)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	hlist_del_init(&dquot->dq_hash);
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_cistatic struct dquot *find_dquot(unsigned int hashent, struct super_block *sb,
3028c2ecf20Sopenharmony_ci				struct kqid qid)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	struct hlist_node *node;
3058c2ecf20Sopenharmony_ci	struct dquot *dquot;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	hlist_for_each (node, dquot_hash+hashent) {
3088c2ecf20Sopenharmony_ci		dquot = hlist_entry(node, struct dquot, dq_hash);
3098c2ecf20Sopenharmony_ci		if (dquot->dq_sb == sb && qid_eq(dquot->dq_id, qid))
3108c2ecf20Sopenharmony_ci			return dquot;
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci	return NULL;
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci/* Add a dquot to the tail of the free list */
3168c2ecf20Sopenharmony_cistatic inline void put_dquot_last(struct dquot *dquot)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	list_add_tail(&dquot->dq_free, &free_dquots);
3198c2ecf20Sopenharmony_ci	dqstats_inc(DQST_FREE_DQUOTS);
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic inline void put_releasing_dquots(struct dquot *dquot)
3238c2ecf20Sopenharmony_ci{
3248c2ecf20Sopenharmony_ci	list_add_tail(&dquot->dq_free, &releasing_dquots);
3258c2ecf20Sopenharmony_ci	set_bit(DQ_RELEASING_B, &dquot->dq_flags);
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic inline void remove_free_dquot(struct dquot *dquot)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	if (list_empty(&dquot->dq_free))
3318c2ecf20Sopenharmony_ci		return;
3328c2ecf20Sopenharmony_ci	list_del_init(&dquot->dq_free);
3338c2ecf20Sopenharmony_ci	if (!test_bit(DQ_RELEASING_B, &dquot->dq_flags))
3348c2ecf20Sopenharmony_ci		dqstats_dec(DQST_FREE_DQUOTS);
3358c2ecf20Sopenharmony_ci	else
3368c2ecf20Sopenharmony_ci		clear_bit(DQ_RELEASING_B, &dquot->dq_flags);
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic inline void put_inuse(struct dquot *dquot)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	/* We add to the back of inuse list so we don't have to restart
3428c2ecf20Sopenharmony_ci	 * when traversing this list and we block */
3438c2ecf20Sopenharmony_ci	list_add_tail(&dquot->dq_inuse, &inuse_list);
3448c2ecf20Sopenharmony_ci	dqstats_inc(DQST_ALLOC_DQUOTS);
3458c2ecf20Sopenharmony_ci}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_cistatic inline void remove_inuse(struct dquot *dquot)
3488c2ecf20Sopenharmony_ci{
3498c2ecf20Sopenharmony_ci	dqstats_dec(DQST_ALLOC_DQUOTS);
3508c2ecf20Sopenharmony_ci	list_del(&dquot->dq_inuse);
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci/*
3538c2ecf20Sopenharmony_ci * End of list functions needing dq_list_lock
3548c2ecf20Sopenharmony_ci */
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic void wait_on_dquot(struct dquot *dquot)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	mutex_lock(&dquot->dq_lock);
3598c2ecf20Sopenharmony_ci	mutex_unlock(&dquot->dq_lock);
3608c2ecf20Sopenharmony_ci}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_cistatic inline int dquot_active(struct dquot *dquot)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	return test_bit(DQ_ACTIVE_B, &dquot->dq_flags);
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic inline int dquot_dirty(struct dquot *dquot)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	return test_bit(DQ_MOD_B, &dquot->dq_flags);
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistatic inline int mark_dquot_dirty(struct dquot *dquot)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	return dquot->dq_sb->dq_op->mark_dirty(dquot);
3758c2ecf20Sopenharmony_ci}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci/* Mark dquot dirty in atomic manner, and return it's old dirty flag state */
3788c2ecf20Sopenharmony_ciint dquot_mark_dquot_dirty(struct dquot *dquot)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	int ret = 1;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	if (!dquot_active(dquot))
3838c2ecf20Sopenharmony_ci		return 0;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NOLIST_DIRTY)
3868c2ecf20Sopenharmony_ci		return test_and_set_bit(DQ_MOD_B, &dquot->dq_flags);
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	/* If quota is dirty already, we don't have to acquire dq_list_lock */
3898c2ecf20Sopenharmony_ci	if (dquot_dirty(dquot))
3908c2ecf20Sopenharmony_ci		return 1;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
3938c2ecf20Sopenharmony_ci	if (!test_and_set_bit(DQ_MOD_B, &dquot->dq_flags)) {
3948c2ecf20Sopenharmony_ci		list_add(&dquot->dq_dirty, &sb_dqopt(dquot->dq_sb)->
3958c2ecf20Sopenharmony_ci				info[dquot->dq_id.type].dqi_dirty_list);
3968c2ecf20Sopenharmony_ci		ret = 0;
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
3998c2ecf20Sopenharmony_ci	return ret;
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_mark_dquot_dirty);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci/* Dirtify all the dquots - this can block when journalling */
4048c2ecf20Sopenharmony_cistatic inline int mark_all_dquot_dirty(struct dquot * const *dquots)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	int ret, err, cnt;
4078c2ecf20Sopenharmony_ci	struct dquot *dquot;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	ret = err = 0;
4108c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
4118c2ecf20Sopenharmony_ci		dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
4128c2ecf20Sopenharmony_ci		if (dquot)
4138c2ecf20Sopenharmony_ci			/* Even in case of error we have to continue */
4148c2ecf20Sopenharmony_ci			ret = mark_dquot_dirty(dquot);
4158c2ecf20Sopenharmony_ci		if (!err)
4168c2ecf20Sopenharmony_ci			err = ret;
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci	return err;
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic inline void dqput_all(struct dquot **dquot)
4228c2ecf20Sopenharmony_ci{
4238c2ecf20Sopenharmony_ci	unsigned int cnt;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
4268c2ecf20Sopenharmony_ci		dqput(dquot[cnt]);
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic inline int clear_dquot_dirty(struct dquot *dquot)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NOLIST_DIRTY)
4328c2ecf20Sopenharmony_ci		return test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
4358c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags)) {
4368c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
4378c2ecf20Sopenharmony_ci		return 0;
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci	list_del_init(&dquot->dq_dirty);
4408c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
4418c2ecf20Sopenharmony_ci	return 1;
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_civoid mark_info_dirty(struct super_block *sb, int type)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	spin_lock(&dq_data_lock);
4478c2ecf20Sopenharmony_ci	sb_dqopt(sb)->info[type].dqi_flags |= DQF_INFO_DIRTY;
4488c2ecf20Sopenharmony_ci	spin_unlock(&dq_data_lock);
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mark_info_dirty);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci/*
4538c2ecf20Sopenharmony_ci *	Read dquot from disk and alloc space for it
4548c2ecf20Sopenharmony_ci */
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ciint dquot_acquire(struct dquot *dquot)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	int ret = 0, ret2 = 0;
4598c2ecf20Sopenharmony_ci	unsigned int memalloc;
4608c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	mutex_lock(&dquot->dq_lock);
4638c2ecf20Sopenharmony_ci	memalloc = memalloc_nofs_save();
4648c2ecf20Sopenharmony_ci	if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
4658c2ecf20Sopenharmony_ci		ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
4668c2ecf20Sopenharmony_ci		if (ret < 0)
4678c2ecf20Sopenharmony_ci			goto out_iolock;
4688c2ecf20Sopenharmony_ci	}
4698c2ecf20Sopenharmony_ci	/* Make sure flags update is visible after dquot has been filled */
4708c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
4718c2ecf20Sopenharmony_ci	set_bit(DQ_READ_B, &dquot->dq_flags);
4728c2ecf20Sopenharmony_ci	/* Instantiate dquot if needed */
4738c2ecf20Sopenharmony_ci	if (!dquot_active(dquot) && !dquot->dq_off) {
4748c2ecf20Sopenharmony_ci		ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
4758c2ecf20Sopenharmony_ci		/* Write the info if needed */
4768c2ecf20Sopenharmony_ci		if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
4778c2ecf20Sopenharmony_ci			ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info(
4788c2ecf20Sopenharmony_ci					dquot->dq_sb, dquot->dq_id.type);
4798c2ecf20Sopenharmony_ci		}
4808c2ecf20Sopenharmony_ci		if (ret < 0)
4818c2ecf20Sopenharmony_ci			goto out_iolock;
4828c2ecf20Sopenharmony_ci		if (ret2 < 0) {
4838c2ecf20Sopenharmony_ci			ret = ret2;
4848c2ecf20Sopenharmony_ci			goto out_iolock;
4858c2ecf20Sopenharmony_ci		}
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci	/*
4888c2ecf20Sopenharmony_ci	 * Make sure flags update is visible after on-disk struct has been
4898c2ecf20Sopenharmony_ci	 * allocated. Paired with smp_rmb() in dqget().
4908c2ecf20Sopenharmony_ci	 */
4918c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
4928c2ecf20Sopenharmony_ci	set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
4938c2ecf20Sopenharmony_ciout_iolock:
4948c2ecf20Sopenharmony_ci	memalloc_nofs_restore(memalloc);
4958c2ecf20Sopenharmony_ci	mutex_unlock(&dquot->dq_lock);
4968c2ecf20Sopenharmony_ci	return ret;
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_acquire);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci/*
5018c2ecf20Sopenharmony_ci *	Write dquot to disk
5028c2ecf20Sopenharmony_ci */
5038c2ecf20Sopenharmony_ciint dquot_commit(struct dquot *dquot)
5048c2ecf20Sopenharmony_ci{
5058c2ecf20Sopenharmony_ci	int ret = 0;
5068c2ecf20Sopenharmony_ci	unsigned int memalloc;
5078c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	mutex_lock(&dquot->dq_lock);
5108c2ecf20Sopenharmony_ci	memalloc = memalloc_nofs_save();
5118c2ecf20Sopenharmony_ci	if (!clear_dquot_dirty(dquot))
5128c2ecf20Sopenharmony_ci		goto out_lock;
5138c2ecf20Sopenharmony_ci	/* Inactive dquot can be only if there was error during read/init
5148c2ecf20Sopenharmony_ci	 * => we have better not writing it */
5158c2ecf20Sopenharmony_ci	if (dquot_active(dquot))
5168c2ecf20Sopenharmony_ci		ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
5178c2ecf20Sopenharmony_ci	else
5188c2ecf20Sopenharmony_ci		ret = -EIO;
5198c2ecf20Sopenharmony_ciout_lock:
5208c2ecf20Sopenharmony_ci	memalloc_nofs_restore(memalloc);
5218c2ecf20Sopenharmony_ci	mutex_unlock(&dquot->dq_lock);
5228c2ecf20Sopenharmony_ci	return ret;
5238c2ecf20Sopenharmony_ci}
5248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_commit);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci/*
5278c2ecf20Sopenharmony_ci *	Release dquot
5288c2ecf20Sopenharmony_ci */
5298c2ecf20Sopenharmony_ciint dquot_release(struct dquot *dquot)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	int ret = 0, ret2 = 0;
5328c2ecf20Sopenharmony_ci	unsigned int memalloc;
5338c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	mutex_lock(&dquot->dq_lock);
5368c2ecf20Sopenharmony_ci	memalloc = memalloc_nofs_save();
5378c2ecf20Sopenharmony_ci	/* Check whether we are not racing with some other dqget() */
5388c2ecf20Sopenharmony_ci	if (dquot_is_busy(dquot))
5398c2ecf20Sopenharmony_ci		goto out_dqlock;
5408c2ecf20Sopenharmony_ci	if (dqopt->ops[dquot->dq_id.type]->release_dqblk) {
5418c2ecf20Sopenharmony_ci		ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot);
5428c2ecf20Sopenharmony_ci		/* Write the info */
5438c2ecf20Sopenharmony_ci		if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
5448c2ecf20Sopenharmony_ci			ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info(
5458c2ecf20Sopenharmony_ci						dquot->dq_sb, dquot->dq_id.type);
5468c2ecf20Sopenharmony_ci		}
5478c2ecf20Sopenharmony_ci		if (ret >= 0)
5488c2ecf20Sopenharmony_ci			ret = ret2;
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci	clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
5518c2ecf20Sopenharmony_ciout_dqlock:
5528c2ecf20Sopenharmony_ci	memalloc_nofs_restore(memalloc);
5538c2ecf20Sopenharmony_ci	mutex_unlock(&dquot->dq_lock);
5548c2ecf20Sopenharmony_ci	return ret;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_release);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_civoid dquot_destroy(struct dquot *dquot)
5598c2ecf20Sopenharmony_ci{
5608c2ecf20Sopenharmony_ci	kmem_cache_free(dquot_cachep, dquot);
5618c2ecf20Sopenharmony_ci}
5628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_destroy);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_cistatic inline void do_destroy_dquot(struct dquot *dquot)
5658c2ecf20Sopenharmony_ci{
5668c2ecf20Sopenharmony_ci	dquot->dq_sb->dq_op->destroy_dquot(dquot);
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci/* Invalidate all dquots on the list. Note that this function is called after
5708c2ecf20Sopenharmony_ci * quota is disabled and pointers from inodes removed so there cannot be new
5718c2ecf20Sopenharmony_ci * quota users. There can still be some users of quotas due to inodes being
5728c2ecf20Sopenharmony_ci * just deleted or pruned by prune_icache() (those are not attached to any
5738c2ecf20Sopenharmony_ci * list) or parallel quotactl call. We have to wait for such users.
5748c2ecf20Sopenharmony_ci */
5758c2ecf20Sopenharmony_cistatic void invalidate_dquots(struct super_block *sb, int type)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	struct dquot *dquot, *tmp;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_cirestart:
5808c2ecf20Sopenharmony_ci	flush_delayed_work(&quota_release_work);
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
5838c2ecf20Sopenharmony_ci	list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) {
5848c2ecf20Sopenharmony_ci		if (dquot->dq_sb != sb)
5858c2ecf20Sopenharmony_ci			continue;
5868c2ecf20Sopenharmony_ci		if (dquot->dq_id.type != type)
5878c2ecf20Sopenharmony_ci			continue;
5888c2ecf20Sopenharmony_ci		/* Wait for dquot users */
5898c2ecf20Sopenharmony_ci		if (atomic_read(&dquot->dq_count)) {
5908c2ecf20Sopenharmony_ci			atomic_inc(&dquot->dq_count);
5918c2ecf20Sopenharmony_ci			spin_unlock(&dq_list_lock);
5928c2ecf20Sopenharmony_ci			/*
5938c2ecf20Sopenharmony_ci			 * Once dqput() wakes us up, we know it's time to free
5948c2ecf20Sopenharmony_ci			 * the dquot.
5958c2ecf20Sopenharmony_ci			 * IMPORTANT: we rely on the fact that there is always
5968c2ecf20Sopenharmony_ci			 * at most one process waiting for dquot to free.
5978c2ecf20Sopenharmony_ci			 * Otherwise dq_count would be > 1 and we would never
5988c2ecf20Sopenharmony_ci			 * wake up.
5998c2ecf20Sopenharmony_ci			 */
6008c2ecf20Sopenharmony_ci			wait_event(dquot_ref_wq,
6018c2ecf20Sopenharmony_ci				   atomic_read(&dquot->dq_count) == 1);
6028c2ecf20Sopenharmony_ci			dqput(dquot);
6038c2ecf20Sopenharmony_ci			/* At this moment dquot() need not exist (it could be
6048c2ecf20Sopenharmony_ci			 * reclaimed by prune_dqcache(). Hence we must
6058c2ecf20Sopenharmony_ci			 * restart. */
6068c2ecf20Sopenharmony_ci			goto restart;
6078c2ecf20Sopenharmony_ci		}
6088c2ecf20Sopenharmony_ci		/*
6098c2ecf20Sopenharmony_ci		 * The last user already dropped its reference but dquot didn't
6108c2ecf20Sopenharmony_ci		 * get fully cleaned up yet. Restart the scan which flushes the
6118c2ecf20Sopenharmony_ci		 * work cleaning up released dquots.
6128c2ecf20Sopenharmony_ci		 */
6138c2ecf20Sopenharmony_ci		if (test_bit(DQ_RELEASING_B, &dquot->dq_flags)) {
6148c2ecf20Sopenharmony_ci			spin_unlock(&dq_list_lock);
6158c2ecf20Sopenharmony_ci			goto restart;
6168c2ecf20Sopenharmony_ci		}
6178c2ecf20Sopenharmony_ci		/*
6188c2ecf20Sopenharmony_ci		 * Quota now has no users and it has been written on last
6198c2ecf20Sopenharmony_ci		 * dqput()
6208c2ecf20Sopenharmony_ci		 */
6218c2ecf20Sopenharmony_ci		remove_dquot_hash(dquot);
6228c2ecf20Sopenharmony_ci		remove_free_dquot(dquot);
6238c2ecf20Sopenharmony_ci		remove_inuse(dquot);
6248c2ecf20Sopenharmony_ci		do_destroy_dquot(dquot);
6258c2ecf20Sopenharmony_ci	}
6268c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci/* Call callback for every active dquot on given filesystem */
6308c2ecf20Sopenharmony_ciint dquot_scan_active(struct super_block *sb,
6318c2ecf20Sopenharmony_ci		      int (*fn)(struct dquot *dquot, unsigned long priv),
6328c2ecf20Sopenharmony_ci		      unsigned long priv)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	struct dquot *dquot, *old_dquot = NULL;
6358c2ecf20Sopenharmony_ci	int ret = 0;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	WARN_ON_ONCE(!rwsem_is_locked(&sb->s_umount));
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
6408c2ecf20Sopenharmony_ci	list_for_each_entry(dquot, &inuse_list, dq_inuse) {
6418c2ecf20Sopenharmony_ci		if (!dquot_active(dquot))
6428c2ecf20Sopenharmony_ci			continue;
6438c2ecf20Sopenharmony_ci		if (dquot->dq_sb != sb)
6448c2ecf20Sopenharmony_ci			continue;
6458c2ecf20Sopenharmony_ci		/* Now we have active dquot so we can just increase use count */
6468c2ecf20Sopenharmony_ci		atomic_inc(&dquot->dq_count);
6478c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
6488c2ecf20Sopenharmony_ci		dqput(old_dquot);
6498c2ecf20Sopenharmony_ci		old_dquot = dquot;
6508c2ecf20Sopenharmony_ci		/*
6518c2ecf20Sopenharmony_ci		 * ->release_dquot() can be racing with us. Our reference
6528c2ecf20Sopenharmony_ci		 * protects us from new calls to it so just wait for any
6538c2ecf20Sopenharmony_ci		 * outstanding call and recheck the DQ_ACTIVE_B after that.
6548c2ecf20Sopenharmony_ci		 */
6558c2ecf20Sopenharmony_ci		wait_on_dquot(dquot);
6568c2ecf20Sopenharmony_ci		if (dquot_active(dquot)) {
6578c2ecf20Sopenharmony_ci			ret = fn(dquot, priv);
6588c2ecf20Sopenharmony_ci			if (ret < 0)
6598c2ecf20Sopenharmony_ci				goto out;
6608c2ecf20Sopenharmony_ci		}
6618c2ecf20Sopenharmony_ci		spin_lock(&dq_list_lock);
6628c2ecf20Sopenharmony_ci		/* We are safe to continue now because our dquot could not
6638c2ecf20Sopenharmony_ci		 * be moved out of the inuse list while we hold the reference */
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
6668c2ecf20Sopenharmony_ciout:
6678c2ecf20Sopenharmony_ci	dqput(old_dquot);
6688c2ecf20Sopenharmony_ci	return ret;
6698c2ecf20Sopenharmony_ci}
6708c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_scan_active);
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic inline int dquot_write_dquot(struct dquot *dquot)
6738c2ecf20Sopenharmony_ci{
6748c2ecf20Sopenharmony_ci	int ret = dquot->dq_sb->dq_op->write_dquot(dquot);
6758c2ecf20Sopenharmony_ci	if (ret < 0) {
6768c2ecf20Sopenharmony_ci		quota_error(dquot->dq_sb, "Can't write quota structure "
6778c2ecf20Sopenharmony_ci			    "(error %d). Quota may get out of sync!", ret);
6788c2ecf20Sopenharmony_ci		/* Clear dirty bit anyway to avoid infinite loop. */
6798c2ecf20Sopenharmony_ci		clear_dquot_dirty(dquot);
6808c2ecf20Sopenharmony_ci	}
6818c2ecf20Sopenharmony_ci	return ret;
6828c2ecf20Sopenharmony_ci}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci/* Write all dquot structures to quota files */
6858c2ecf20Sopenharmony_ciint dquot_writeback_dquots(struct super_block *sb, int type)
6868c2ecf20Sopenharmony_ci{
6878c2ecf20Sopenharmony_ci	struct list_head dirty;
6888c2ecf20Sopenharmony_ci	struct dquot *dquot;
6898c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
6908c2ecf20Sopenharmony_ci	int cnt;
6918c2ecf20Sopenharmony_ci	int err, ret = 0;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	WARN_ON_ONCE(!rwsem_is_locked(&sb->s_umount));
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
6968c2ecf20Sopenharmony_ci		if (type != -1 && cnt != type)
6978c2ecf20Sopenharmony_ci			continue;
6988c2ecf20Sopenharmony_ci		if (!sb_has_quota_active(sb, cnt))
6998c2ecf20Sopenharmony_ci			continue;
7008c2ecf20Sopenharmony_ci		spin_lock(&dq_list_lock);
7018c2ecf20Sopenharmony_ci		/* Move list away to avoid livelock. */
7028c2ecf20Sopenharmony_ci		list_replace_init(&dqopt->info[cnt].dqi_dirty_list, &dirty);
7038c2ecf20Sopenharmony_ci		while (!list_empty(&dirty)) {
7048c2ecf20Sopenharmony_ci			dquot = list_first_entry(&dirty, struct dquot,
7058c2ecf20Sopenharmony_ci						 dq_dirty);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci			WARN_ON(!dquot_active(dquot));
7088c2ecf20Sopenharmony_ci			/* If the dquot is releasing we should not touch it */
7098c2ecf20Sopenharmony_ci			if (test_bit(DQ_RELEASING_B, &dquot->dq_flags)) {
7108c2ecf20Sopenharmony_ci				spin_unlock(&dq_list_lock);
7118c2ecf20Sopenharmony_ci				flush_delayed_work(&quota_release_work);
7128c2ecf20Sopenharmony_ci				spin_lock(&dq_list_lock);
7138c2ecf20Sopenharmony_ci				continue;
7148c2ecf20Sopenharmony_ci			}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci			/* Now we have active dquot from which someone is
7178c2ecf20Sopenharmony_ci 			 * holding reference so we can safely just increase
7188c2ecf20Sopenharmony_ci			 * use count */
7198c2ecf20Sopenharmony_ci			dqgrab(dquot);
7208c2ecf20Sopenharmony_ci			spin_unlock(&dq_list_lock);
7218c2ecf20Sopenharmony_ci			err = dquot_write_dquot(dquot);
7228c2ecf20Sopenharmony_ci			if (err && !ret)
7238c2ecf20Sopenharmony_ci				ret = err;
7248c2ecf20Sopenharmony_ci			dqput(dquot);
7258c2ecf20Sopenharmony_ci			spin_lock(&dq_list_lock);
7268c2ecf20Sopenharmony_ci		}
7278c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
7288c2ecf20Sopenharmony_ci	}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
7318c2ecf20Sopenharmony_ci		if ((cnt == type || type == -1) && sb_has_quota_active(sb, cnt)
7328c2ecf20Sopenharmony_ci		    && info_dirty(&dqopt->info[cnt]))
7338c2ecf20Sopenharmony_ci			sb->dq_op->write_info(sb, cnt);
7348c2ecf20Sopenharmony_ci	dqstats_inc(DQST_SYNCS);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	return ret;
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_writeback_dquots);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci/* Write all dquot structures to disk and make them visible from userspace */
7418c2ecf20Sopenharmony_ciint dquot_quota_sync(struct super_block *sb, int type)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
7448c2ecf20Sopenharmony_ci	int cnt;
7458c2ecf20Sopenharmony_ci	int ret;
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	ret = dquot_writeback_dquots(sb, type);
7488c2ecf20Sopenharmony_ci	if (ret)
7498c2ecf20Sopenharmony_ci		return ret;
7508c2ecf20Sopenharmony_ci	if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
7518c2ecf20Sopenharmony_ci		return 0;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	/* This is not very clever (and fast) but currently I don't know about
7548c2ecf20Sopenharmony_ci	 * any other simple way of getting quota data to disk and we must get
7558c2ecf20Sopenharmony_ci	 * them there for userspace to be visible... */
7568c2ecf20Sopenharmony_ci	if (sb->s_op->sync_fs) {
7578c2ecf20Sopenharmony_ci		ret = sb->s_op->sync_fs(sb, 1);
7588c2ecf20Sopenharmony_ci		if (ret)
7598c2ecf20Sopenharmony_ci			return ret;
7608c2ecf20Sopenharmony_ci	}
7618c2ecf20Sopenharmony_ci	ret = sync_blockdev(sb->s_bdev);
7628c2ecf20Sopenharmony_ci	if (ret)
7638c2ecf20Sopenharmony_ci		return ret;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/*
7668c2ecf20Sopenharmony_ci	 * Now when everything is written we can discard the pagecache so
7678c2ecf20Sopenharmony_ci	 * that userspace sees the changes.
7688c2ecf20Sopenharmony_ci	 */
7698c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
7708c2ecf20Sopenharmony_ci		if (type != -1 && cnt != type)
7718c2ecf20Sopenharmony_ci			continue;
7728c2ecf20Sopenharmony_ci		if (!sb_has_quota_active(sb, cnt))
7738c2ecf20Sopenharmony_ci			continue;
7748c2ecf20Sopenharmony_ci		inode_lock(dqopt->files[cnt]);
7758c2ecf20Sopenharmony_ci		truncate_inode_pages(&dqopt->files[cnt]->i_data, 0);
7768c2ecf20Sopenharmony_ci		inode_unlock(dqopt->files[cnt]);
7778c2ecf20Sopenharmony_ci	}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	return 0;
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_quota_sync);
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_cistatic unsigned long
7848c2ecf20Sopenharmony_cidqcache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct dquot *dquot;
7878c2ecf20Sopenharmony_ci	unsigned long freed = 0;
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
7908c2ecf20Sopenharmony_ci	while (!list_empty(&free_dquots) && sc->nr_to_scan) {
7918c2ecf20Sopenharmony_ci		dquot = list_first_entry(&free_dquots, struct dquot, dq_free);
7928c2ecf20Sopenharmony_ci		remove_dquot_hash(dquot);
7938c2ecf20Sopenharmony_ci		remove_free_dquot(dquot);
7948c2ecf20Sopenharmony_ci		remove_inuse(dquot);
7958c2ecf20Sopenharmony_ci		do_destroy_dquot(dquot);
7968c2ecf20Sopenharmony_ci		sc->nr_to_scan--;
7978c2ecf20Sopenharmony_ci		freed++;
7988c2ecf20Sopenharmony_ci	}
7998c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
8008c2ecf20Sopenharmony_ci	return freed;
8018c2ecf20Sopenharmony_ci}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_cistatic unsigned long
8048c2ecf20Sopenharmony_cidqcache_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
8058c2ecf20Sopenharmony_ci{
8068c2ecf20Sopenharmony_ci	return vfs_pressure_ratio(
8078c2ecf20Sopenharmony_ci	percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS]));
8088c2ecf20Sopenharmony_ci}
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_cistatic struct shrinker dqcache_shrinker = {
8118c2ecf20Sopenharmony_ci	.count_objects = dqcache_shrink_count,
8128c2ecf20Sopenharmony_ci	.scan_objects = dqcache_shrink_scan,
8138c2ecf20Sopenharmony_ci	.seeks = DEFAULT_SEEKS,
8148c2ecf20Sopenharmony_ci};
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci/*
8178c2ecf20Sopenharmony_ci * Safely release dquot and put reference to dquot.
8188c2ecf20Sopenharmony_ci */
8198c2ecf20Sopenharmony_cistatic void quota_release_workfn(struct work_struct *work)
8208c2ecf20Sopenharmony_ci{
8218c2ecf20Sopenharmony_ci	struct dquot *dquot;
8228c2ecf20Sopenharmony_ci	struct list_head rls_head;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
8258c2ecf20Sopenharmony_ci	/* Exchange the list head to avoid livelock. */
8268c2ecf20Sopenharmony_ci	list_replace_init(&releasing_dquots, &rls_head);
8278c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
8288c2ecf20Sopenharmony_ci	synchronize_srcu(&dquot_srcu);
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_cirestart:
8318c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
8328c2ecf20Sopenharmony_ci	while (!list_empty(&rls_head)) {
8338c2ecf20Sopenharmony_ci		dquot = list_first_entry(&rls_head, struct dquot, dq_free);
8348c2ecf20Sopenharmony_ci		WARN_ON_ONCE(atomic_read(&dquot->dq_count));
8358c2ecf20Sopenharmony_ci		/*
8368c2ecf20Sopenharmony_ci		 * Note that DQ_RELEASING_B protects us from racing with
8378c2ecf20Sopenharmony_ci		 * invalidate_dquots() calls so we are safe to work with the
8388c2ecf20Sopenharmony_ci		 * dquot even after we drop dq_list_lock.
8398c2ecf20Sopenharmony_ci		 */
8408c2ecf20Sopenharmony_ci		if (dquot_dirty(dquot)) {
8418c2ecf20Sopenharmony_ci			spin_unlock(&dq_list_lock);
8428c2ecf20Sopenharmony_ci			/* Commit dquot before releasing */
8438c2ecf20Sopenharmony_ci			dquot_write_dquot(dquot);
8448c2ecf20Sopenharmony_ci			goto restart;
8458c2ecf20Sopenharmony_ci		}
8468c2ecf20Sopenharmony_ci		if (dquot_active(dquot)) {
8478c2ecf20Sopenharmony_ci			spin_unlock(&dq_list_lock);
8488c2ecf20Sopenharmony_ci			dquot->dq_sb->dq_op->release_dquot(dquot);
8498c2ecf20Sopenharmony_ci			goto restart;
8508c2ecf20Sopenharmony_ci		}
8518c2ecf20Sopenharmony_ci		/* Dquot is inactive and clean, now move it to free list */
8528c2ecf20Sopenharmony_ci		remove_free_dquot(dquot);
8538c2ecf20Sopenharmony_ci		put_dquot_last(dquot);
8548c2ecf20Sopenharmony_ci	}
8558c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci/*
8598c2ecf20Sopenharmony_ci * Put reference to dquot
8608c2ecf20Sopenharmony_ci */
8618c2ecf20Sopenharmony_civoid dqput(struct dquot *dquot)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	if (!dquot)
8648c2ecf20Sopenharmony_ci		return;
8658c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
8668c2ecf20Sopenharmony_ci	if (!atomic_read(&dquot->dq_count)) {
8678c2ecf20Sopenharmony_ci		quota_error(dquot->dq_sb, "trying to free free dquot of %s %d",
8688c2ecf20Sopenharmony_ci			    quotatypes[dquot->dq_id.type],
8698c2ecf20Sopenharmony_ci			    from_kqid(&init_user_ns, dquot->dq_id));
8708c2ecf20Sopenharmony_ci		BUG();
8718c2ecf20Sopenharmony_ci	}
8728c2ecf20Sopenharmony_ci#endif
8738c2ecf20Sopenharmony_ci	dqstats_inc(DQST_DROPS);
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
8768c2ecf20Sopenharmony_ci	if (atomic_read(&dquot->dq_count) > 1) {
8778c2ecf20Sopenharmony_ci		/* We have more than one user... nothing to do */
8788c2ecf20Sopenharmony_ci		atomic_dec(&dquot->dq_count);
8798c2ecf20Sopenharmony_ci		/* Releasing dquot during quotaoff phase? */
8808c2ecf20Sopenharmony_ci		if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_id.type) &&
8818c2ecf20Sopenharmony_ci		    atomic_read(&dquot->dq_count) == 1)
8828c2ecf20Sopenharmony_ci			wake_up(&dquot_ref_wq);
8838c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
8848c2ecf20Sopenharmony_ci		return;
8858c2ecf20Sopenharmony_ci	}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	/* Need to release dquot? */
8888c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
8898c2ecf20Sopenharmony_ci	/* sanity check */
8908c2ecf20Sopenharmony_ci	BUG_ON(!list_empty(&dquot->dq_free));
8918c2ecf20Sopenharmony_ci#endif
8928c2ecf20Sopenharmony_ci	put_releasing_dquots(dquot);
8938c2ecf20Sopenharmony_ci	atomic_dec(&dquot->dq_count);
8948c2ecf20Sopenharmony_ci	spin_unlock(&dq_list_lock);
8958c2ecf20Sopenharmony_ci	queue_delayed_work(system_unbound_wq, &quota_release_work, 1);
8968c2ecf20Sopenharmony_ci}
8978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dqput);
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_cistruct dquot *dquot_alloc(struct super_block *sb, int type)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	return kmem_cache_zalloc(dquot_cachep, GFP_NOFS);
9028c2ecf20Sopenharmony_ci}
9038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_alloc);
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic struct dquot *get_empty_dquot(struct super_block *sb, int type)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	struct dquot *dquot;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	dquot = sb->dq_op->alloc_dquot(sb, type);
9108c2ecf20Sopenharmony_ci	if(!dquot)
9118c2ecf20Sopenharmony_ci		return NULL;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	mutex_init(&dquot->dq_lock);
9148c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dquot->dq_free);
9158c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dquot->dq_inuse);
9168c2ecf20Sopenharmony_ci	INIT_HLIST_NODE(&dquot->dq_hash);
9178c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dquot->dq_dirty);
9188c2ecf20Sopenharmony_ci	dquot->dq_sb = sb;
9198c2ecf20Sopenharmony_ci	dquot->dq_id = make_kqid_invalid(type);
9208c2ecf20Sopenharmony_ci	atomic_set(&dquot->dq_count, 1);
9218c2ecf20Sopenharmony_ci	spin_lock_init(&dquot->dq_dqb_lock);
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	return dquot;
9248c2ecf20Sopenharmony_ci}
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci/*
9278c2ecf20Sopenharmony_ci * Get reference to dquot
9288c2ecf20Sopenharmony_ci *
9298c2ecf20Sopenharmony_ci * Locking is slightly tricky here. We are guarded from parallel quotaoff()
9308c2ecf20Sopenharmony_ci * destroying our dquot by:
9318c2ecf20Sopenharmony_ci *   a) checking for quota flags under dq_list_lock and
9328c2ecf20Sopenharmony_ci *   b) getting a reference to dquot before we release dq_list_lock
9338c2ecf20Sopenharmony_ci */
9348c2ecf20Sopenharmony_cistruct dquot *dqget(struct super_block *sb, struct kqid qid)
9358c2ecf20Sopenharmony_ci{
9368c2ecf20Sopenharmony_ci	unsigned int hashent = hashfn(sb, qid);
9378c2ecf20Sopenharmony_ci	struct dquot *dquot, *empty = NULL;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	if (!qid_has_mapping(sb->s_user_ns, qid))
9408c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci        if (!sb_has_quota_active(sb, qid.type))
9438c2ecf20Sopenharmony_ci		return ERR_PTR(-ESRCH);
9448c2ecf20Sopenharmony_ciwe_slept:
9458c2ecf20Sopenharmony_ci	spin_lock(&dq_list_lock);
9468c2ecf20Sopenharmony_ci	spin_lock(&dq_state_lock);
9478c2ecf20Sopenharmony_ci	if (!sb_has_quota_active(sb, qid.type)) {
9488c2ecf20Sopenharmony_ci		spin_unlock(&dq_state_lock);
9498c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
9508c2ecf20Sopenharmony_ci		dquot = ERR_PTR(-ESRCH);
9518c2ecf20Sopenharmony_ci		goto out;
9528c2ecf20Sopenharmony_ci	}
9538c2ecf20Sopenharmony_ci	spin_unlock(&dq_state_lock);
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	dquot = find_dquot(hashent, sb, qid);
9568c2ecf20Sopenharmony_ci	if (!dquot) {
9578c2ecf20Sopenharmony_ci		if (!empty) {
9588c2ecf20Sopenharmony_ci			spin_unlock(&dq_list_lock);
9598c2ecf20Sopenharmony_ci			empty = get_empty_dquot(sb, qid.type);
9608c2ecf20Sopenharmony_ci			if (!empty)
9618c2ecf20Sopenharmony_ci				schedule();	/* Try to wait for a moment... */
9628c2ecf20Sopenharmony_ci			goto we_slept;
9638c2ecf20Sopenharmony_ci		}
9648c2ecf20Sopenharmony_ci		dquot = empty;
9658c2ecf20Sopenharmony_ci		empty = NULL;
9668c2ecf20Sopenharmony_ci		dquot->dq_id = qid;
9678c2ecf20Sopenharmony_ci		/* all dquots go on the inuse_list */
9688c2ecf20Sopenharmony_ci		put_inuse(dquot);
9698c2ecf20Sopenharmony_ci		/* hash it first so it can be found */
9708c2ecf20Sopenharmony_ci		insert_dquot_hash(dquot);
9718c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
9728c2ecf20Sopenharmony_ci		dqstats_inc(DQST_LOOKUPS);
9738c2ecf20Sopenharmony_ci	} else {
9748c2ecf20Sopenharmony_ci		if (!atomic_read(&dquot->dq_count))
9758c2ecf20Sopenharmony_ci			remove_free_dquot(dquot);
9768c2ecf20Sopenharmony_ci		atomic_inc(&dquot->dq_count);
9778c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
9788c2ecf20Sopenharmony_ci		dqstats_inc(DQST_CACHE_HITS);
9798c2ecf20Sopenharmony_ci		dqstats_inc(DQST_LOOKUPS);
9808c2ecf20Sopenharmony_ci	}
9818c2ecf20Sopenharmony_ci	/* Wait for dq_lock - after this we know that either dquot_release() is
9828c2ecf20Sopenharmony_ci	 * already finished or it will be canceled due to dq_count > 0 test */
9838c2ecf20Sopenharmony_ci	wait_on_dquot(dquot);
9848c2ecf20Sopenharmony_ci	/* Read the dquot / allocate space in quota file */
9858c2ecf20Sopenharmony_ci	if (!dquot_active(dquot)) {
9868c2ecf20Sopenharmony_ci		int err;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci		err = sb->dq_op->acquire_dquot(dquot);
9898c2ecf20Sopenharmony_ci		if (err < 0) {
9908c2ecf20Sopenharmony_ci			dqput(dquot);
9918c2ecf20Sopenharmony_ci			dquot = ERR_PTR(err);
9928c2ecf20Sopenharmony_ci			goto out;
9938c2ecf20Sopenharmony_ci		}
9948c2ecf20Sopenharmony_ci	}
9958c2ecf20Sopenharmony_ci	/*
9968c2ecf20Sopenharmony_ci	 * Make sure following reads see filled structure - paired with
9978c2ecf20Sopenharmony_ci	 * smp_mb__before_atomic() in dquot_acquire().
9988c2ecf20Sopenharmony_ci	 */
9998c2ecf20Sopenharmony_ci	smp_rmb();
10008c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
10018c2ecf20Sopenharmony_ci	BUG_ON(!dquot->dq_sb);	/* Has somebody invalidated entry under us? */
10028c2ecf20Sopenharmony_ci#endif
10038c2ecf20Sopenharmony_ciout:
10048c2ecf20Sopenharmony_ci	if (empty)
10058c2ecf20Sopenharmony_ci		do_destroy_dquot(empty);
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	return dquot;
10088c2ecf20Sopenharmony_ci}
10098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dqget);
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_cistatic inline struct dquot **i_dquot(struct inode *inode)
10128c2ecf20Sopenharmony_ci{
10138c2ecf20Sopenharmony_ci	return inode->i_sb->s_op->get_dquots(inode);
10148c2ecf20Sopenharmony_ci}
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_cistatic int dqinit_needed(struct inode *inode, int type)
10178c2ecf20Sopenharmony_ci{
10188c2ecf20Sopenharmony_ci	struct dquot * const *dquots;
10198c2ecf20Sopenharmony_ci	int cnt;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	if (IS_NOQUOTA(inode))
10228c2ecf20Sopenharmony_ci		return 0;
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
10258c2ecf20Sopenharmony_ci	if (type != -1)
10268c2ecf20Sopenharmony_ci		return !dquots[type];
10278c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
10288c2ecf20Sopenharmony_ci		if (!dquots[cnt])
10298c2ecf20Sopenharmony_ci			return 1;
10308c2ecf20Sopenharmony_ci	return 0;
10318c2ecf20Sopenharmony_ci}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci/* This routine is guarded by s_umount semaphore */
10348c2ecf20Sopenharmony_cistatic int add_dquot_ref(struct super_block *sb, int type)
10358c2ecf20Sopenharmony_ci{
10368c2ecf20Sopenharmony_ci	struct inode *inode, *old_inode = NULL;
10378c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
10388c2ecf20Sopenharmony_ci	int reserved = 0;
10398c2ecf20Sopenharmony_ci#endif
10408c2ecf20Sopenharmony_ci	int err = 0;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	spin_lock(&sb->s_inode_list_lock);
10438c2ecf20Sopenharmony_ci	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
10448c2ecf20Sopenharmony_ci		spin_lock(&inode->i_lock);
10458c2ecf20Sopenharmony_ci		if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
10468c2ecf20Sopenharmony_ci		    !atomic_read(&inode->i_writecount) ||
10478c2ecf20Sopenharmony_ci		    !dqinit_needed(inode, type)) {
10488c2ecf20Sopenharmony_ci			spin_unlock(&inode->i_lock);
10498c2ecf20Sopenharmony_ci			continue;
10508c2ecf20Sopenharmony_ci		}
10518c2ecf20Sopenharmony_ci		__iget(inode);
10528c2ecf20Sopenharmony_ci		spin_unlock(&inode->i_lock);
10538c2ecf20Sopenharmony_ci		spin_unlock(&sb->s_inode_list_lock);
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
10568c2ecf20Sopenharmony_ci		if (unlikely(inode_get_rsv_space(inode) > 0))
10578c2ecf20Sopenharmony_ci			reserved = 1;
10588c2ecf20Sopenharmony_ci#endif
10598c2ecf20Sopenharmony_ci		iput(old_inode);
10608c2ecf20Sopenharmony_ci		err = __dquot_initialize(inode, type);
10618c2ecf20Sopenharmony_ci		if (err) {
10628c2ecf20Sopenharmony_ci			iput(inode);
10638c2ecf20Sopenharmony_ci			goto out;
10648c2ecf20Sopenharmony_ci		}
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci		/*
10678c2ecf20Sopenharmony_ci		 * We hold a reference to 'inode' so it couldn't have been
10688c2ecf20Sopenharmony_ci		 * removed from s_inodes list while we dropped the
10698c2ecf20Sopenharmony_ci		 * s_inode_list_lock. We cannot iput the inode now as we can be
10708c2ecf20Sopenharmony_ci		 * holding the last reference and we cannot iput it under
10718c2ecf20Sopenharmony_ci		 * s_inode_list_lock. So we keep the reference and iput it
10728c2ecf20Sopenharmony_ci		 * later.
10738c2ecf20Sopenharmony_ci		 */
10748c2ecf20Sopenharmony_ci		old_inode = inode;
10758c2ecf20Sopenharmony_ci		cond_resched();
10768c2ecf20Sopenharmony_ci		spin_lock(&sb->s_inode_list_lock);
10778c2ecf20Sopenharmony_ci	}
10788c2ecf20Sopenharmony_ci	spin_unlock(&sb->s_inode_list_lock);
10798c2ecf20Sopenharmony_ci	iput(old_inode);
10808c2ecf20Sopenharmony_ciout:
10818c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
10828c2ecf20Sopenharmony_ci	if (reserved) {
10838c2ecf20Sopenharmony_ci		quota_error(sb, "Writes happened before quota was turned on "
10848c2ecf20Sopenharmony_ci			"thus quota information is probably inconsistent. "
10858c2ecf20Sopenharmony_ci			"Please run quotacheck(8)");
10868c2ecf20Sopenharmony_ci	}
10878c2ecf20Sopenharmony_ci#endif
10888c2ecf20Sopenharmony_ci	return err;
10898c2ecf20Sopenharmony_ci}
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci/*
10928c2ecf20Sopenharmony_ci * Remove references to dquots from inode and add dquot to list for freeing
10938c2ecf20Sopenharmony_ci * if we have the last reference to dquot
10948c2ecf20Sopenharmony_ci */
10958c2ecf20Sopenharmony_cistatic void remove_inode_dquot_ref(struct inode *inode, int type,
10968c2ecf20Sopenharmony_ci				   struct list_head *tofree_head)
10978c2ecf20Sopenharmony_ci{
10988c2ecf20Sopenharmony_ci	struct dquot **dquots = i_dquot(inode);
10998c2ecf20Sopenharmony_ci	struct dquot *dquot = dquots[type];
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	if (!dquot)
11028c2ecf20Sopenharmony_ci		return;
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	dquots[type] = NULL;
11058c2ecf20Sopenharmony_ci	if (list_empty(&dquot->dq_free)) {
11068c2ecf20Sopenharmony_ci		/*
11078c2ecf20Sopenharmony_ci		 * The inode still has reference to dquot so it can't be in the
11088c2ecf20Sopenharmony_ci		 * free list
11098c2ecf20Sopenharmony_ci		 */
11108c2ecf20Sopenharmony_ci		spin_lock(&dq_list_lock);
11118c2ecf20Sopenharmony_ci		list_add(&dquot->dq_free, tofree_head);
11128c2ecf20Sopenharmony_ci		spin_unlock(&dq_list_lock);
11138c2ecf20Sopenharmony_ci	} else {
11148c2ecf20Sopenharmony_ci		/*
11158c2ecf20Sopenharmony_ci		 * Dquot is already in a list to put so we won't drop the last
11168c2ecf20Sopenharmony_ci		 * reference here.
11178c2ecf20Sopenharmony_ci		 */
11188c2ecf20Sopenharmony_ci		dqput(dquot);
11198c2ecf20Sopenharmony_ci	}
11208c2ecf20Sopenharmony_ci}
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci/*
11238c2ecf20Sopenharmony_ci * Free list of dquots
11248c2ecf20Sopenharmony_ci * Dquots are removed from inodes and no new references can be got so we are
11258c2ecf20Sopenharmony_ci * the only ones holding reference
11268c2ecf20Sopenharmony_ci */
11278c2ecf20Sopenharmony_cistatic void put_dquot_list(struct list_head *tofree_head)
11288c2ecf20Sopenharmony_ci{
11298c2ecf20Sopenharmony_ci	struct list_head *act_head;
11308c2ecf20Sopenharmony_ci	struct dquot *dquot;
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	act_head = tofree_head->next;
11338c2ecf20Sopenharmony_ci	while (act_head != tofree_head) {
11348c2ecf20Sopenharmony_ci		dquot = list_entry(act_head, struct dquot, dq_free);
11358c2ecf20Sopenharmony_ci		act_head = act_head->next;
11368c2ecf20Sopenharmony_ci		/* Remove dquot from the list so we won't have problems... */
11378c2ecf20Sopenharmony_ci		list_del_init(&dquot->dq_free);
11388c2ecf20Sopenharmony_ci		dqput(dquot);
11398c2ecf20Sopenharmony_ci	}
11408c2ecf20Sopenharmony_ci}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_cistatic void remove_dquot_ref(struct super_block *sb, int type,
11438c2ecf20Sopenharmony_ci		struct list_head *tofree_head)
11448c2ecf20Sopenharmony_ci{
11458c2ecf20Sopenharmony_ci	struct inode *inode;
11468c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
11478c2ecf20Sopenharmony_ci	int reserved = 0;
11488c2ecf20Sopenharmony_ci#endif
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	spin_lock(&sb->s_inode_list_lock);
11518c2ecf20Sopenharmony_ci	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
11528c2ecf20Sopenharmony_ci		/*
11538c2ecf20Sopenharmony_ci		 *  We have to scan also I_NEW inodes because they can already
11548c2ecf20Sopenharmony_ci		 *  have quota pointer initialized. Luckily, we need to touch
11558c2ecf20Sopenharmony_ci		 *  only quota pointers and these have separate locking
11568c2ecf20Sopenharmony_ci		 *  (dq_data_lock).
11578c2ecf20Sopenharmony_ci		 */
11588c2ecf20Sopenharmony_ci		spin_lock(&dq_data_lock);
11598c2ecf20Sopenharmony_ci		if (!IS_NOQUOTA(inode)) {
11608c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
11618c2ecf20Sopenharmony_ci			if (unlikely(inode_get_rsv_space(inode) > 0))
11628c2ecf20Sopenharmony_ci				reserved = 1;
11638c2ecf20Sopenharmony_ci#endif
11648c2ecf20Sopenharmony_ci			remove_inode_dquot_ref(inode, type, tofree_head);
11658c2ecf20Sopenharmony_ci		}
11668c2ecf20Sopenharmony_ci		spin_unlock(&dq_data_lock);
11678c2ecf20Sopenharmony_ci	}
11688c2ecf20Sopenharmony_ci	spin_unlock(&sb->s_inode_list_lock);
11698c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA_DEBUG
11708c2ecf20Sopenharmony_ci	if (reserved) {
11718c2ecf20Sopenharmony_ci		printk(KERN_WARNING "VFS (%s): Writes happened after quota"
11728c2ecf20Sopenharmony_ci			" was disabled thus quota information is probably "
11738c2ecf20Sopenharmony_ci			"inconsistent. Please run quotacheck(8).\n", sb->s_id);
11748c2ecf20Sopenharmony_ci	}
11758c2ecf20Sopenharmony_ci#endif
11768c2ecf20Sopenharmony_ci}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci/* Gather all references from inodes and drop them */
11798c2ecf20Sopenharmony_cistatic void drop_dquot_ref(struct super_block *sb, int type)
11808c2ecf20Sopenharmony_ci{
11818c2ecf20Sopenharmony_ci	LIST_HEAD(tofree_head);
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	if (sb->dq_op) {
11848c2ecf20Sopenharmony_ci		remove_dquot_ref(sb, type, &tofree_head);
11858c2ecf20Sopenharmony_ci		synchronize_srcu(&dquot_srcu);
11868c2ecf20Sopenharmony_ci		put_dquot_list(&tofree_head);
11878c2ecf20Sopenharmony_ci	}
11888c2ecf20Sopenharmony_ci}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_cistatic inline
11918c2ecf20Sopenharmony_civoid dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
11928c2ecf20Sopenharmony_ci{
11938c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_rsvspace >= number)
11948c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_rsvspace -= number;
11958c2ecf20Sopenharmony_ci	else {
11968c2ecf20Sopenharmony_ci		WARN_ON_ONCE(1);
11978c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_rsvspace = 0;
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace <=
12008c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_bsoftlimit)
12018c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_btime = (time64_t) 0;
12028c2ecf20Sopenharmony_ci	clear_bit(DQ_BLKS_B, &dquot->dq_flags);
12038c2ecf20Sopenharmony_ci}
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_cistatic void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
12068c2ecf20Sopenharmony_ci{
12078c2ecf20Sopenharmony_ci	if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
12088c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_curinodes >= number)
12098c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_curinodes -= number;
12108c2ecf20Sopenharmony_ci	else
12118c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_curinodes = 0;
12128c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit)
12138c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_itime = (time64_t) 0;
12148c2ecf20Sopenharmony_ci	clear_bit(DQ_INODES_B, &dquot->dq_flags);
12158c2ecf20Sopenharmony_ci}
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_cistatic void dquot_decr_space(struct dquot *dquot, qsize_t number)
12188c2ecf20Sopenharmony_ci{
12198c2ecf20Sopenharmony_ci	if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
12208c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_curspace >= number)
12218c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_curspace -= number;
12228c2ecf20Sopenharmony_ci	else
12238c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_curspace = 0;
12248c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace <=
12258c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_bsoftlimit)
12268c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_btime = (time64_t) 0;
12278c2ecf20Sopenharmony_ci	clear_bit(DQ_BLKS_B, &dquot->dq_flags);
12288c2ecf20Sopenharmony_ci}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_cistruct dquot_warn {
12318c2ecf20Sopenharmony_ci	struct super_block *w_sb;
12328c2ecf20Sopenharmony_ci	struct kqid w_dq_id;
12338c2ecf20Sopenharmony_ci	short w_type;
12348c2ecf20Sopenharmony_ci};
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_cistatic int warning_issued(struct dquot *dquot, const int warntype)
12378c2ecf20Sopenharmony_ci{
12388c2ecf20Sopenharmony_ci	int flag = (warntype == QUOTA_NL_BHARDWARN ||
12398c2ecf20Sopenharmony_ci		warntype == QUOTA_NL_BSOFTLONGWARN) ? DQ_BLKS_B :
12408c2ecf20Sopenharmony_ci		((warntype == QUOTA_NL_IHARDWARN ||
12418c2ecf20Sopenharmony_ci		warntype == QUOTA_NL_ISOFTLONGWARN) ? DQ_INODES_B : 0);
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	if (!flag)
12448c2ecf20Sopenharmony_ci		return 0;
12458c2ecf20Sopenharmony_ci	return test_and_set_bit(flag, &dquot->dq_flags);
12468c2ecf20Sopenharmony_ci}
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci#ifdef CONFIG_PRINT_QUOTA_WARNING
12498c2ecf20Sopenharmony_cistatic int flag_print_warnings = 1;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_cistatic int need_print_warning(struct dquot_warn *warn)
12528c2ecf20Sopenharmony_ci{
12538c2ecf20Sopenharmony_ci	if (!flag_print_warnings)
12548c2ecf20Sopenharmony_ci		return 0;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	switch (warn->w_dq_id.type) {
12578c2ecf20Sopenharmony_ci		case USRQUOTA:
12588c2ecf20Sopenharmony_ci			return uid_eq(current_fsuid(), warn->w_dq_id.uid);
12598c2ecf20Sopenharmony_ci		case GRPQUOTA:
12608c2ecf20Sopenharmony_ci			return in_group_p(warn->w_dq_id.gid);
12618c2ecf20Sopenharmony_ci		case PRJQUOTA:
12628c2ecf20Sopenharmony_ci			return 1;
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci	return 0;
12658c2ecf20Sopenharmony_ci}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci/* Print warning to user which exceeded quota */
12688c2ecf20Sopenharmony_cistatic void print_warning(struct dquot_warn *warn)
12698c2ecf20Sopenharmony_ci{
12708c2ecf20Sopenharmony_ci	char *msg = NULL;
12718c2ecf20Sopenharmony_ci	struct tty_struct *tty;
12728c2ecf20Sopenharmony_ci	int warntype = warn->w_type;
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	if (warntype == QUOTA_NL_IHARDBELOW ||
12758c2ecf20Sopenharmony_ci	    warntype == QUOTA_NL_ISOFTBELOW ||
12768c2ecf20Sopenharmony_ci	    warntype == QUOTA_NL_BHARDBELOW ||
12778c2ecf20Sopenharmony_ci	    warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(warn))
12788c2ecf20Sopenharmony_ci		return;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	tty = get_current_tty();
12818c2ecf20Sopenharmony_ci	if (!tty)
12828c2ecf20Sopenharmony_ci		return;
12838c2ecf20Sopenharmony_ci	tty_write_message(tty, warn->w_sb->s_id);
12848c2ecf20Sopenharmony_ci	if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN)
12858c2ecf20Sopenharmony_ci		tty_write_message(tty, ": warning, ");
12868c2ecf20Sopenharmony_ci	else
12878c2ecf20Sopenharmony_ci		tty_write_message(tty, ": write failed, ");
12888c2ecf20Sopenharmony_ci	tty_write_message(tty, quotatypes[warn->w_dq_id.type]);
12898c2ecf20Sopenharmony_ci	switch (warntype) {
12908c2ecf20Sopenharmony_ci		case QUOTA_NL_IHARDWARN:
12918c2ecf20Sopenharmony_ci			msg = " file limit reached.\r\n";
12928c2ecf20Sopenharmony_ci			break;
12938c2ecf20Sopenharmony_ci		case QUOTA_NL_ISOFTLONGWARN:
12948c2ecf20Sopenharmony_ci			msg = " file quota exceeded too long.\r\n";
12958c2ecf20Sopenharmony_ci			break;
12968c2ecf20Sopenharmony_ci		case QUOTA_NL_ISOFTWARN:
12978c2ecf20Sopenharmony_ci			msg = " file quota exceeded.\r\n";
12988c2ecf20Sopenharmony_ci			break;
12998c2ecf20Sopenharmony_ci		case QUOTA_NL_BHARDWARN:
13008c2ecf20Sopenharmony_ci			msg = " block limit reached.\r\n";
13018c2ecf20Sopenharmony_ci			break;
13028c2ecf20Sopenharmony_ci		case QUOTA_NL_BSOFTLONGWARN:
13038c2ecf20Sopenharmony_ci			msg = " block quota exceeded too long.\r\n";
13048c2ecf20Sopenharmony_ci			break;
13058c2ecf20Sopenharmony_ci		case QUOTA_NL_BSOFTWARN:
13068c2ecf20Sopenharmony_ci			msg = " block quota exceeded.\r\n";
13078c2ecf20Sopenharmony_ci			break;
13088c2ecf20Sopenharmony_ci	}
13098c2ecf20Sopenharmony_ci	tty_write_message(tty, msg);
13108c2ecf20Sopenharmony_ci	tty_kref_put(tty);
13118c2ecf20Sopenharmony_ci}
13128c2ecf20Sopenharmony_ci#endif
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_cistatic void prepare_warning(struct dquot_warn *warn, struct dquot *dquot,
13158c2ecf20Sopenharmony_ci			    int warntype)
13168c2ecf20Sopenharmony_ci{
13178c2ecf20Sopenharmony_ci	if (warning_issued(dquot, warntype))
13188c2ecf20Sopenharmony_ci		return;
13198c2ecf20Sopenharmony_ci	warn->w_type = warntype;
13208c2ecf20Sopenharmony_ci	warn->w_sb = dquot->dq_sb;
13218c2ecf20Sopenharmony_ci	warn->w_dq_id = dquot->dq_id;
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci/*
13258c2ecf20Sopenharmony_ci * Write warnings to the console and send warning messages over netlink.
13268c2ecf20Sopenharmony_ci *
13278c2ecf20Sopenharmony_ci * Note that this function can call into tty and networking code.
13288c2ecf20Sopenharmony_ci */
13298c2ecf20Sopenharmony_cistatic void flush_warnings(struct dquot_warn *warn)
13308c2ecf20Sopenharmony_ci{
13318c2ecf20Sopenharmony_ci	int i;
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	for (i = 0; i < MAXQUOTAS; i++) {
13348c2ecf20Sopenharmony_ci		if (warn[i].w_type == QUOTA_NL_NOWARN)
13358c2ecf20Sopenharmony_ci			continue;
13368c2ecf20Sopenharmony_ci#ifdef CONFIG_PRINT_QUOTA_WARNING
13378c2ecf20Sopenharmony_ci		print_warning(&warn[i]);
13388c2ecf20Sopenharmony_ci#endif
13398c2ecf20Sopenharmony_ci		quota_send_warning(warn[i].w_dq_id,
13408c2ecf20Sopenharmony_ci				   warn[i].w_sb->s_dev, warn[i].w_type);
13418c2ecf20Sopenharmony_ci	}
13428c2ecf20Sopenharmony_ci}
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_cistatic int ignore_hardlimit(struct dquot *dquot)
13458c2ecf20Sopenharmony_ci{
13468c2ecf20Sopenharmony_ci	struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci	return capable(CAP_SYS_RESOURCE) &&
13498c2ecf20Sopenharmony_ci	       (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD ||
13508c2ecf20Sopenharmony_ci		!(info->dqi_flags & DQF_ROOT_SQUASH));
13518c2ecf20Sopenharmony_ci}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_cistatic int dquot_add_inodes(struct dquot *dquot, qsize_t inodes,
13548c2ecf20Sopenharmony_ci			    struct dquot_warn *warn)
13558c2ecf20Sopenharmony_ci{
13568c2ecf20Sopenharmony_ci	qsize_t newinodes;
13578c2ecf20Sopenharmony_ci	int ret = 0;
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	spin_lock(&dquot->dq_dqb_lock);
13608c2ecf20Sopenharmony_ci	newinodes = dquot->dq_dqb.dqb_curinodes + inodes;
13618c2ecf20Sopenharmony_ci	if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) ||
13628c2ecf20Sopenharmony_ci	    test_bit(DQ_FAKE_B, &dquot->dq_flags))
13638c2ecf20Sopenharmony_ci		goto add;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_ihardlimit &&
13668c2ecf20Sopenharmony_ci	    newinodes > dquot->dq_dqb.dqb_ihardlimit &&
13678c2ecf20Sopenharmony_ci            !ignore_hardlimit(dquot)) {
13688c2ecf20Sopenharmony_ci		prepare_warning(warn, dquot, QUOTA_NL_IHARDWARN);
13698c2ecf20Sopenharmony_ci		ret = -EDQUOT;
13708c2ecf20Sopenharmony_ci		goto out;
13718c2ecf20Sopenharmony_ci	}
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_isoftlimit &&
13748c2ecf20Sopenharmony_ci	    newinodes > dquot->dq_dqb.dqb_isoftlimit &&
13758c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_itime &&
13768c2ecf20Sopenharmony_ci	    ktime_get_real_seconds() >= dquot->dq_dqb.dqb_itime &&
13778c2ecf20Sopenharmony_ci            !ignore_hardlimit(dquot)) {
13788c2ecf20Sopenharmony_ci		prepare_warning(warn, dquot, QUOTA_NL_ISOFTLONGWARN);
13798c2ecf20Sopenharmony_ci		ret = -EDQUOT;
13808c2ecf20Sopenharmony_ci		goto out;
13818c2ecf20Sopenharmony_ci	}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_isoftlimit &&
13848c2ecf20Sopenharmony_ci	    newinodes > dquot->dq_dqb.dqb_isoftlimit &&
13858c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_itime == 0) {
13868c2ecf20Sopenharmony_ci		prepare_warning(warn, dquot, QUOTA_NL_ISOFTWARN);
13878c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_itime = ktime_get_real_seconds() +
13888c2ecf20Sopenharmony_ci		    sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace;
13898c2ecf20Sopenharmony_ci	}
13908c2ecf20Sopenharmony_ciadd:
13918c2ecf20Sopenharmony_ci	dquot->dq_dqb.dqb_curinodes = newinodes;
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ciout:
13948c2ecf20Sopenharmony_ci	spin_unlock(&dquot->dq_dqb_lock);
13958c2ecf20Sopenharmony_ci	return ret;
13968c2ecf20Sopenharmony_ci}
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_cistatic int dquot_add_space(struct dquot *dquot, qsize_t space,
13998c2ecf20Sopenharmony_ci			   qsize_t rsv_space, unsigned int flags,
14008c2ecf20Sopenharmony_ci			   struct dquot_warn *warn)
14018c2ecf20Sopenharmony_ci{
14028c2ecf20Sopenharmony_ci	qsize_t tspace;
14038c2ecf20Sopenharmony_ci	struct super_block *sb = dquot->dq_sb;
14048c2ecf20Sopenharmony_ci	int ret = 0;
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci	spin_lock(&dquot->dq_dqb_lock);
14078c2ecf20Sopenharmony_ci	if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) ||
14088c2ecf20Sopenharmony_ci	    test_bit(DQ_FAKE_B, &dquot->dq_flags))
14098c2ecf20Sopenharmony_ci		goto finish;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace
14128c2ecf20Sopenharmony_ci		+ space + rsv_space;
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_bhardlimit &&
14158c2ecf20Sopenharmony_ci	    tspace > dquot->dq_dqb.dqb_bhardlimit &&
14168c2ecf20Sopenharmony_ci            !ignore_hardlimit(dquot)) {
14178c2ecf20Sopenharmony_ci		if (flags & DQUOT_SPACE_WARN)
14188c2ecf20Sopenharmony_ci			prepare_warning(warn, dquot, QUOTA_NL_BHARDWARN);
14198c2ecf20Sopenharmony_ci		ret = -EDQUOT;
14208c2ecf20Sopenharmony_ci		goto finish;
14218c2ecf20Sopenharmony_ci	}
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_bsoftlimit &&
14248c2ecf20Sopenharmony_ci	    tspace > dquot->dq_dqb.dqb_bsoftlimit &&
14258c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_btime &&
14268c2ecf20Sopenharmony_ci	    ktime_get_real_seconds() >= dquot->dq_dqb.dqb_btime &&
14278c2ecf20Sopenharmony_ci            !ignore_hardlimit(dquot)) {
14288c2ecf20Sopenharmony_ci		if (flags & DQUOT_SPACE_WARN)
14298c2ecf20Sopenharmony_ci			prepare_warning(warn, dquot, QUOTA_NL_BSOFTLONGWARN);
14308c2ecf20Sopenharmony_ci		ret = -EDQUOT;
14318c2ecf20Sopenharmony_ci		goto finish;
14328c2ecf20Sopenharmony_ci	}
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_bsoftlimit &&
14358c2ecf20Sopenharmony_ci	    tspace > dquot->dq_dqb.dqb_bsoftlimit &&
14368c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_btime == 0) {
14378c2ecf20Sopenharmony_ci		if (flags & DQUOT_SPACE_WARN) {
14388c2ecf20Sopenharmony_ci			prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN);
14398c2ecf20Sopenharmony_ci			dquot->dq_dqb.dqb_btime = ktime_get_real_seconds() +
14408c2ecf20Sopenharmony_ci			    sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace;
14418c2ecf20Sopenharmony_ci		} else {
14428c2ecf20Sopenharmony_ci			/*
14438c2ecf20Sopenharmony_ci			 * We don't allow preallocation to exceed softlimit so exceeding will
14448c2ecf20Sopenharmony_ci			 * be always printed
14458c2ecf20Sopenharmony_ci			 */
14468c2ecf20Sopenharmony_ci			ret = -EDQUOT;
14478c2ecf20Sopenharmony_ci			goto finish;
14488c2ecf20Sopenharmony_ci		}
14498c2ecf20Sopenharmony_ci	}
14508c2ecf20Sopenharmony_cifinish:
14518c2ecf20Sopenharmony_ci	/*
14528c2ecf20Sopenharmony_ci	 * We have to be careful and go through warning generation & grace time
14538c2ecf20Sopenharmony_ci	 * setting even if DQUOT_SPACE_NOFAIL is set. That's why we check it
14548c2ecf20Sopenharmony_ci	 * only here...
14558c2ecf20Sopenharmony_ci	 */
14568c2ecf20Sopenharmony_ci	if (flags & DQUOT_SPACE_NOFAIL)
14578c2ecf20Sopenharmony_ci		ret = 0;
14588c2ecf20Sopenharmony_ci	if (!ret) {
14598c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_rsvspace += rsv_space;
14608c2ecf20Sopenharmony_ci		dquot->dq_dqb.dqb_curspace += space;
14618c2ecf20Sopenharmony_ci	}
14628c2ecf20Sopenharmony_ci	spin_unlock(&dquot->dq_dqb_lock);
14638c2ecf20Sopenharmony_ci	return ret;
14648c2ecf20Sopenharmony_ci}
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_cistatic int info_idq_free(struct dquot *dquot, qsize_t inodes)
14678c2ecf20Sopenharmony_ci{
14688c2ecf20Sopenharmony_ci	qsize_t newinodes;
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
14718c2ecf20Sopenharmony_ci	    dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit ||
14728c2ecf20Sopenharmony_ci	    !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type))
14738c2ecf20Sopenharmony_ci		return QUOTA_NL_NOWARN;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	newinodes = dquot->dq_dqb.dqb_curinodes - inodes;
14768c2ecf20Sopenharmony_ci	if (newinodes <= dquot->dq_dqb.dqb_isoftlimit)
14778c2ecf20Sopenharmony_ci		return QUOTA_NL_ISOFTBELOW;
14788c2ecf20Sopenharmony_ci	if (dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_ihardlimit &&
14798c2ecf20Sopenharmony_ci	    newinodes < dquot->dq_dqb.dqb_ihardlimit)
14808c2ecf20Sopenharmony_ci		return QUOTA_NL_IHARDBELOW;
14818c2ecf20Sopenharmony_ci	return QUOTA_NL_NOWARN;
14828c2ecf20Sopenharmony_ci}
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_cistatic int info_bdq_free(struct dquot *dquot, qsize_t space)
14858c2ecf20Sopenharmony_ci{
14868c2ecf20Sopenharmony_ci	qsize_t tspace;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace;
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
14918c2ecf20Sopenharmony_ci	    tspace <= dquot->dq_dqb.dqb_bsoftlimit)
14928c2ecf20Sopenharmony_ci		return QUOTA_NL_NOWARN;
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	if (tspace - space <= dquot->dq_dqb.dqb_bsoftlimit)
14958c2ecf20Sopenharmony_ci		return QUOTA_NL_BSOFTBELOW;
14968c2ecf20Sopenharmony_ci	if (tspace >= dquot->dq_dqb.dqb_bhardlimit &&
14978c2ecf20Sopenharmony_ci	    tspace - space < dquot->dq_dqb.dqb_bhardlimit)
14988c2ecf20Sopenharmony_ci		return QUOTA_NL_BHARDBELOW;
14998c2ecf20Sopenharmony_ci	return QUOTA_NL_NOWARN;
15008c2ecf20Sopenharmony_ci}
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_cistatic int inode_quota_active(const struct inode *inode)
15038c2ecf20Sopenharmony_ci{
15048c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	if (IS_NOQUOTA(inode))
15078c2ecf20Sopenharmony_ci		return 0;
15088c2ecf20Sopenharmony_ci	return sb_any_quota_loaded(sb) & ~sb_any_quota_suspended(sb);
15098c2ecf20Sopenharmony_ci}
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci/*
15128c2ecf20Sopenharmony_ci * Initialize quota pointers in inode
15138c2ecf20Sopenharmony_ci *
15148c2ecf20Sopenharmony_ci * It is better to call this function outside of any transaction as it
15158c2ecf20Sopenharmony_ci * might need a lot of space in journal for dquot structure allocation.
15168c2ecf20Sopenharmony_ci */
15178c2ecf20Sopenharmony_cistatic int __dquot_initialize(struct inode *inode, int type)
15188c2ecf20Sopenharmony_ci{
15198c2ecf20Sopenharmony_ci	int cnt, init_needed = 0;
15208c2ecf20Sopenharmony_ci	struct dquot **dquots, *got[MAXQUOTAS] = {};
15218c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
15228c2ecf20Sopenharmony_ci	qsize_t rsv;
15238c2ecf20Sopenharmony_ci	int ret = 0;
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode))
15268c2ecf20Sopenharmony_ci		return 0;
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	/* First get references to structures we might need. */
15318c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
15328c2ecf20Sopenharmony_ci		struct kqid qid;
15338c2ecf20Sopenharmony_ci		kprojid_t projid;
15348c2ecf20Sopenharmony_ci		int rc;
15358c2ecf20Sopenharmony_ci		struct dquot *dquot;
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci		if (type != -1 && cnt != type)
15388c2ecf20Sopenharmony_ci			continue;
15398c2ecf20Sopenharmony_ci		/*
15408c2ecf20Sopenharmony_ci		 * The i_dquot should have been initialized in most cases,
15418c2ecf20Sopenharmony_ci		 * we check it without locking here to avoid unnecessary
15428c2ecf20Sopenharmony_ci		 * dqget()/dqput() calls.
15438c2ecf20Sopenharmony_ci		 */
15448c2ecf20Sopenharmony_ci		if (dquots[cnt])
15458c2ecf20Sopenharmony_ci			continue;
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci		if (!sb_has_quota_active(sb, cnt))
15488c2ecf20Sopenharmony_ci			continue;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci		init_needed = 1;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci		switch (cnt) {
15538c2ecf20Sopenharmony_ci		case USRQUOTA:
15548c2ecf20Sopenharmony_ci			qid = make_kqid_uid(inode->i_uid);
15558c2ecf20Sopenharmony_ci			break;
15568c2ecf20Sopenharmony_ci		case GRPQUOTA:
15578c2ecf20Sopenharmony_ci			qid = make_kqid_gid(inode->i_gid);
15588c2ecf20Sopenharmony_ci			break;
15598c2ecf20Sopenharmony_ci		case PRJQUOTA:
15608c2ecf20Sopenharmony_ci			rc = inode->i_sb->dq_op->get_projid(inode, &projid);
15618c2ecf20Sopenharmony_ci			if (rc)
15628c2ecf20Sopenharmony_ci				continue;
15638c2ecf20Sopenharmony_ci			qid = make_kqid_projid(projid);
15648c2ecf20Sopenharmony_ci			break;
15658c2ecf20Sopenharmony_ci		}
15668c2ecf20Sopenharmony_ci		dquot = dqget(sb, qid);
15678c2ecf20Sopenharmony_ci		if (IS_ERR(dquot)) {
15688c2ecf20Sopenharmony_ci			/* We raced with somebody turning quotas off... */
15698c2ecf20Sopenharmony_ci			if (PTR_ERR(dquot) != -ESRCH) {
15708c2ecf20Sopenharmony_ci				ret = PTR_ERR(dquot);
15718c2ecf20Sopenharmony_ci				goto out_put;
15728c2ecf20Sopenharmony_ci			}
15738c2ecf20Sopenharmony_ci			dquot = NULL;
15748c2ecf20Sopenharmony_ci		}
15758c2ecf20Sopenharmony_ci		got[cnt] = dquot;
15768c2ecf20Sopenharmony_ci	}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	/* All required i_dquot has been initialized */
15798c2ecf20Sopenharmony_ci	if (!init_needed)
15808c2ecf20Sopenharmony_ci		return 0;
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	spin_lock(&dq_data_lock);
15838c2ecf20Sopenharmony_ci	if (IS_NOQUOTA(inode))
15848c2ecf20Sopenharmony_ci		goto out_lock;
15858c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
15868c2ecf20Sopenharmony_ci		if (type != -1 && cnt != type)
15878c2ecf20Sopenharmony_ci			continue;
15888c2ecf20Sopenharmony_ci		/* Avoid races with quotaoff() */
15898c2ecf20Sopenharmony_ci		if (!sb_has_quota_active(sb, cnt))
15908c2ecf20Sopenharmony_ci			continue;
15918c2ecf20Sopenharmony_ci		/* We could race with quotaon or dqget() could have failed */
15928c2ecf20Sopenharmony_ci		if (!got[cnt])
15938c2ecf20Sopenharmony_ci			continue;
15948c2ecf20Sopenharmony_ci		if (!dquots[cnt]) {
15958c2ecf20Sopenharmony_ci			dquots[cnt] = got[cnt];
15968c2ecf20Sopenharmony_ci			got[cnt] = NULL;
15978c2ecf20Sopenharmony_ci			/*
15988c2ecf20Sopenharmony_ci			 * Make quota reservation system happy if someone
15998c2ecf20Sopenharmony_ci			 * did a write before quota was turned on
16008c2ecf20Sopenharmony_ci			 */
16018c2ecf20Sopenharmony_ci			rsv = inode_get_rsv_space(inode);
16028c2ecf20Sopenharmony_ci			if (unlikely(rsv)) {
16038c2ecf20Sopenharmony_ci				spin_lock(&inode->i_lock);
16048c2ecf20Sopenharmony_ci				/* Get reservation again under proper lock */
16058c2ecf20Sopenharmony_ci				rsv = __inode_get_rsv_space(inode);
16068c2ecf20Sopenharmony_ci				spin_lock(&dquots[cnt]->dq_dqb_lock);
16078c2ecf20Sopenharmony_ci				dquots[cnt]->dq_dqb.dqb_rsvspace += rsv;
16088c2ecf20Sopenharmony_ci				spin_unlock(&dquots[cnt]->dq_dqb_lock);
16098c2ecf20Sopenharmony_ci				spin_unlock(&inode->i_lock);
16108c2ecf20Sopenharmony_ci			}
16118c2ecf20Sopenharmony_ci		}
16128c2ecf20Sopenharmony_ci	}
16138c2ecf20Sopenharmony_ciout_lock:
16148c2ecf20Sopenharmony_ci	spin_unlock(&dq_data_lock);
16158c2ecf20Sopenharmony_ciout_put:
16168c2ecf20Sopenharmony_ci	/* Drop unused references */
16178c2ecf20Sopenharmony_ci	dqput_all(got);
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	return ret;
16208c2ecf20Sopenharmony_ci}
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ciint dquot_initialize(struct inode *inode)
16238c2ecf20Sopenharmony_ci{
16248c2ecf20Sopenharmony_ci	return __dquot_initialize(inode, -1);
16258c2ecf20Sopenharmony_ci}
16268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_initialize);
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_cibool dquot_initialize_needed(struct inode *inode)
16298c2ecf20Sopenharmony_ci{
16308c2ecf20Sopenharmony_ci	struct dquot **dquots;
16318c2ecf20Sopenharmony_ci	int i;
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode))
16348c2ecf20Sopenharmony_ci		return false;
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
16378c2ecf20Sopenharmony_ci	for (i = 0; i < MAXQUOTAS; i++)
16388c2ecf20Sopenharmony_ci		if (!dquots[i] && sb_has_quota_active(inode->i_sb, i))
16398c2ecf20Sopenharmony_ci			return true;
16408c2ecf20Sopenharmony_ci	return false;
16418c2ecf20Sopenharmony_ci}
16428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_initialize_needed);
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci/*
16458c2ecf20Sopenharmony_ci * Release all quotas referenced by inode.
16468c2ecf20Sopenharmony_ci *
16478c2ecf20Sopenharmony_ci * This function only be called on inode free or converting
16488c2ecf20Sopenharmony_ci * a file to quota file, no other users for the i_dquot in
16498c2ecf20Sopenharmony_ci * both cases, so we needn't call synchronize_srcu() after
16508c2ecf20Sopenharmony_ci * clearing i_dquot.
16518c2ecf20Sopenharmony_ci */
16528c2ecf20Sopenharmony_cistatic void __dquot_drop(struct inode *inode)
16538c2ecf20Sopenharmony_ci{
16548c2ecf20Sopenharmony_ci	int cnt;
16558c2ecf20Sopenharmony_ci	struct dquot **dquots = i_dquot(inode);
16568c2ecf20Sopenharmony_ci	struct dquot *put[MAXQUOTAS];
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	spin_lock(&dq_data_lock);
16598c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
16608c2ecf20Sopenharmony_ci		put[cnt] = dquots[cnt];
16618c2ecf20Sopenharmony_ci		dquots[cnt] = NULL;
16628c2ecf20Sopenharmony_ci	}
16638c2ecf20Sopenharmony_ci	spin_unlock(&dq_data_lock);
16648c2ecf20Sopenharmony_ci	dqput_all(put);
16658c2ecf20Sopenharmony_ci}
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_civoid dquot_drop(struct inode *inode)
16688c2ecf20Sopenharmony_ci{
16698c2ecf20Sopenharmony_ci	struct dquot * const *dquots;
16708c2ecf20Sopenharmony_ci	int cnt;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	if (IS_NOQUOTA(inode))
16738c2ecf20Sopenharmony_ci		return;
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci	/*
16768c2ecf20Sopenharmony_ci	 * Test before calling to rule out calls from proc and such
16778c2ecf20Sopenharmony_ci	 * where we are not allowed to block. Note that this is
16788c2ecf20Sopenharmony_ci	 * actually reliable test even without the lock - the caller
16798c2ecf20Sopenharmony_ci	 * must assure that nobody can come after the DQUOT_DROP and
16808c2ecf20Sopenharmony_ci	 * add quota pointers back anyway.
16818c2ecf20Sopenharmony_ci	 */
16828c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
16838c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
16848c2ecf20Sopenharmony_ci		if (dquots[cnt])
16858c2ecf20Sopenharmony_ci			break;
16868c2ecf20Sopenharmony_ci	}
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	if (cnt < MAXQUOTAS)
16898c2ecf20Sopenharmony_ci		__dquot_drop(inode);
16908c2ecf20Sopenharmony_ci}
16918c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_drop);
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci/*
16948c2ecf20Sopenharmony_ci * inode_reserved_space is managed internally by quota, and protected by
16958c2ecf20Sopenharmony_ci * i_lock similar to i_blocks+i_bytes.
16968c2ecf20Sopenharmony_ci */
16978c2ecf20Sopenharmony_cistatic qsize_t *inode_reserved_space(struct inode * inode)
16988c2ecf20Sopenharmony_ci{
16998c2ecf20Sopenharmony_ci	/* Filesystem must explicitly define it's own method in order to use
17008c2ecf20Sopenharmony_ci	 * quota reservation interface */
17018c2ecf20Sopenharmony_ci	BUG_ON(!inode->i_sb->dq_op->get_reserved_space);
17028c2ecf20Sopenharmony_ci	return inode->i_sb->dq_op->get_reserved_space(inode);
17038c2ecf20Sopenharmony_ci}
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_cistatic qsize_t __inode_get_rsv_space(struct inode *inode)
17068c2ecf20Sopenharmony_ci{
17078c2ecf20Sopenharmony_ci	if (!inode->i_sb->dq_op->get_reserved_space)
17088c2ecf20Sopenharmony_ci		return 0;
17098c2ecf20Sopenharmony_ci	return *inode_reserved_space(inode);
17108c2ecf20Sopenharmony_ci}
17118c2ecf20Sopenharmony_ci
17128c2ecf20Sopenharmony_cistatic qsize_t inode_get_rsv_space(struct inode *inode)
17138c2ecf20Sopenharmony_ci{
17148c2ecf20Sopenharmony_ci	qsize_t ret;
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci	if (!inode->i_sb->dq_op->get_reserved_space)
17178c2ecf20Sopenharmony_ci		return 0;
17188c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
17198c2ecf20Sopenharmony_ci	ret = __inode_get_rsv_space(inode);
17208c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
17218c2ecf20Sopenharmony_ci	return ret;
17228c2ecf20Sopenharmony_ci}
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci/*
17258c2ecf20Sopenharmony_ci * This functions updates i_blocks+i_bytes fields and quota information
17268c2ecf20Sopenharmony_ci * (together with appropriate checks).
17278c2ecf20Sopenharmony_ci *
17288c2ecf20Sopenharmony_ci * NOTE: We absolutely rely on the fact that caller dirties the inode
17298c2ecf20Sopenharmony_ci * (usually helpers in quotaops.h care about this) and holds a handle for
17308c2ecf20Sopenharmony_ci * the current transaction so that dquot write and inode write go into the
17318c2ecf20Sopenharmony_ci * same transaction.
17328c2ecf20Sopenharmony_ci */
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci/*
17358c2ecf20Sopenharmony_ci * This operation can block, but only after everything is updated
17368c2ecf20Sopenharmony_ci */
17378c2ecf20Sopenharmony_ciint __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
17388c2ecf20Sopenharmony_ci{
17398c2ecf20Sopenharmony_ci	int cnt, ret = 0, index;
17408c2ecf20Sopenharmony_ci	struct dquot_warn warn[MAXQUOTAS];
17418c2ecf20Sopenharmony_ci	int reserve = flags & DQUOT_SPACE_RESERVE;
17428c2ecf20Sopenharmony_ci	struct dquot **dquots;
17438c2ecf20Sopenharmony_ci	struct dquot *dquot;
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode)) {
17468c2ecf20Sopenharmony_ci		if (reserve) {
17478c2ecf20Sopenharmony_ci			spin_lock(&inode->i_lock);
17488c2ecf20Sopenharmony_ci			*inode_reserved_space(inode) += number;
17498c2ecf20Sopenharmony_ci			spin_unlock(&inode->i_lock);
17508c2ecf20Sopenharmony_ci		} else {
17518c2ecf20Sopenharmony_ci			inode_add_bytes(inode, number);
17528c2ecf20Sopenharmony_ci		}
17538c2ecf20Sopenharmony_ci		goto out;
17548c2ecf20Sopenharmony_ci	}
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
17578c2ecf20Sopenharmony_ci		warn[cnt].w_type = QUOTA_NL_NOWARN;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
17608c2ecf20Sopenharmony_ci	index = srcu_read_lock(&dquot_srcu);
17618c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
17628c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
17638c2ecf20Sopenharmony_ci		dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
17648c2ecf20Sopenharmony_ci		if (!dquot)
17658c2ecf20Sopenharmony_ci			continue;
17668c2ecf20Sopenharmony_ci		if (reserve) {
17678c2ecf20Sopenharmony_ci			ret = dquot_add_space(dquot, 0, number, flags, &warn[cnt]);
17688c2ecf20Sopenharmony_ci		} else {
17698c2ecf20Sopenharmony_ci			ret = dquot_add_space(dquot, number, 0, flags, &warn[cnt]);
17708c2ecf20Sopenharmony_ci		}
17718c2ecf20Sopenharmony_ci		if (ret) {
17728c2ecf20Sopenharmony_ci			/* Back out changes we already did */
17738c2ecf20Sopenharmony_ci			for (cnt--; cnt >= 0; cnt--) {
17748c2ecf20Sopenharmony_ci				dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
17758c2ecf20Sopenharmony_ci				if (!dquot)
17768c2ecf20Sopenharmony_ci					continue;
17778c2ecf20Sopenharmony_ci				spin_lock(&dquot->dq_dqb_lock);
17788c2ecf20Sopenharmony_ci				if (reserve)
17798c2ecf20Sopenharmony_ci					dquot_free_reserved_space(dquot, number);
17808c2ecf20Sopenharmony_ci				else
17818c2ecf20Sopenharmony_ci					dquot_decr_space(dquot, number);
17828c2ecf20Sopenharmony_ci				spin_unlock(&dquot->dq_dqb_lock);
17838c2ecf20Sopenharmony_ci			}
17848c2ecf20Sopenharmony_ci			spin_unlock(&inode->i_lock);
17858c2ecf20Sopenharmony_ci			goto out_flush_warn;
17868c2ecf20Sopenharmony_ci		}
17878c2ecf20Sopenharmony_ci	}
17888c2ecf20Sopenharmony_ci	if (reserve)
17898c2ecf20Sopenharmony_ci		*inode_reserved_space(inode) += number;
17908c2ecf20Sopenharmony_ci	else
17918c2ecf20Sopenharmony_ci		__inode_add_bytes(inode, number);
17928c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	if (reserve)
17958c2ecf20Sopenharmony_ci		goto out_flush_warn;
17968c2ecf20Sopenharmony_ci	mark_all_dquot_dirty(dquots);
17978c2ecf20Sopenharmony_ciout_flush_warn:
17988c2ecf20Sopenharmony_ci	srcu_read_unlock(&dquot_srcu, index);
17998c2ecf20Sopenharmony_ci	flush_warnings(warn);
18008c2ecf20Sopenharmony_ciout:
18018c2ecf20Sopenharmony_ci	return ret;
18028c2ecf20Sopenharmony_ci}
18038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__dquot_alloc_space);
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci/*
18068c2ecf20Sopenharmony_ci * This operation can block, but only after everything is updated
18078c2ecf20Sopenharmony_ci */
18088c2ecf20Sopenharmony_ciint dquot_alloc_inode(struct inode *inode)
18098c2ecf20Sopenharmony_ci{
18108c2ecf20Sopenharmony_ci	int cnt, ret = 0, index;
18118c2ecf20Sopenharmony_ci	struct dquot_warn warn[MAXQUOTAS];
18128c2ecf20Sopenharmony_ci	struct dquot * const *dquots;
18138c2ecf20Sopenharmony_ci	struct dquot *dquot;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode))
18168c2ecf20Sopenharmony_ci		return 0;
18178c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
18188c2ecf20Sopenharmony_ci		warn[cnt].w_type = QUOTA_NL_NOWARN;
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
18218c2ecf20Sopenharmony_ci	index = srcu_read_lock(&dquot_srcu);
18228c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
18238c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
18248c2ecf20Sopenharmony_ci		dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
18258c2ecf20Sopenharmony_ci		if (!dquot)
18268c2ecf20Sopenharmony_ci			continue;
18278c2ecf20Sopenharmony_ci		ret = dquot_add_inodes(dquot, 1, &warn[cnt]);
18288c2ecf20Sopenharmony_ci		if (ret) {
18298c2ecf20Sopenharmony_ci			for (cnt--; cnt >= 0; cnt--) {
18308c2ecf20Sopenharmony_ci				dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
18318c2ecf20Sopenharmony_ci				if (!dquot)
18328c2ecf20Sopenharmony_ci					continue;
18338c2ecf20Sopenharmony_ci				/* Back out changes we already did */
18348c2ecf20Sopenharmony_ci				spin_lock(&dquot->dq_dqb_lock);
18358c2ecf20Sopenharmony_ci				dquot_decr_inodes(dquot, 1);
18368c2ecf20Sopenharmony_ci				spin_unlock(&dquot->dq_dqb_lock);
18378c2ecf20Sopenharmony_ci			}
18388c2ecf20Sopenharmony_ci			goto warn_put_all;
18398c2ecf20Sopenharmony_ci		}
18408c2ecf20Sopenharmony_ci	}
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ciwarn_put_all:
18438c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
18448c2ecf20Sopenharmony_ci	if (ret == 0)
18458c2ecf20Sopenharmony_ci		mark_all_dquot_dirty(dquots);
18468c2ecf20Sopenharmony_ci	srcu_read_unlock(&dquot_srcu, index);
18478c2ecf20Sopenharmony_ci	flush_warnings(warn);
18488c2ecf20Sopenharmony_ci	return ret;
18498c2ecf20Sopenharmony_ci}
18508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_alloc_inode);
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci/*
18538c2ecf20Sopenharmony_ci * Convert in-memory reserved quotas to real consumed quotas
18548c2ecf20Sopenharmony_ci */
18558c2ecf20Sopenharmony_ciint dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
18568c2ecf20Sopenharmony_ci{
18578c2ecf20Sopenharmony_ci	struct dquot **dquots;
18588c2ecf20Sopenharmony_ci	struct dquot *dquot;
18598c2ecf20Sopenharmony_ci	int cnt, index;
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode)) {
18628c2ecf20Sopenharmony_ci		spin_lock(&inode->i_lock);
18638c2ecf20Sopenharmony_ci		*inode_reserved_space(inode) -= number;
18648c2ecf20Sopenharmony_ci		__inode_add_bytes(inode, number);
18658c2ecf20Sopenharmony_ci		spin_unlock(&inode->i_lock);
18668c2ecf20Sopenharmony_ci		return 0;
18678c2ecf20Sopenharmony_ci	}
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
18708c2ecf20Sopenharmony_ci	index = srcu_read_lock(&dquot_srcu);
18718c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
18728c2ecf20Sopenharmony_ci	/* Claim reserved quotas to allocated quotas */
18738c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
18748c2ecf20Sopenharmony_ci		dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
18758c2ecf20Sopenharmony_ci		if (dquot) {
18768c2ecf20Sopenharmony_ci			spin_lock(&dquot->dq_dqb_lock);
18778c2ecf20Sopenharmony_ci			if (WARN_ON_ONCE(dquot->dq_dqb.dqb_rsvspace < number))
18788c2ecf20Sopenharmony_ci				number = dquot->dq_dqb.dqb_rsvspace;
18798c2ecf20Sopenharmony_ci			dquot->dq_dqb.dqb_curspace += number;
18808c2ecf20Sopenharmony_ci			dquot->dq_dqb.dqb_rsvspace -= number;
18818c2ecf20Sopenharmony_ci			spin_unlock(&dquot->dq_dqb_lock);
18828c2ecf20Sopenharmony_ci		}
18838c2ecf20Sopenharmony_ci	}
18848c2ecf20Sopenharmony_ci	/* Update inode bytes */
18858c2ecf20Sopenharmony_ci	*inode_reserved_space(inode) -= number;
18868c2ecf20Sopenharmony_ci	__inode_add_bytes(inode, number);
18878c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
18888c2ecf20Sopenharmony_ci	mark_all_dquot_dirty(dquots);
18898c2ecf20Sopenharmony_ci	srcu_read_unlock(&dquot_srcu, index);
18908c2ecf20Sopenharmony_ci	return 0;
18918c2ecf20Sopenharmony_ci}
18928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_claim_space_nodirty);
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_ci/*
18958c2ecf20Sopenharmony_ci * Convert allocated space back to in-memory reserved quotas
18968c2ecf20Sopenharmony_ci */
18978c2ecf20Sopenharmony_civoid dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
18988c2ecf20Sopenharmony_ci{
18998c2ecf20Sopenharmony_ci	struct dquot **dquots;
19008c2ecf20Sopenharmony_ci	struct dquot *dquot;
19018c2ecf20Sopenharmony_ci	int cnt, index;
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode)) {
19048c2ecf20Sopenharmony_ci		spin_lock(&inode->i_lock);
19058c2ecf20Sopenharmony_ci		*inode_reserved_space(inode) += number;
19068c2ecf20Sopenharmony_ci		__inode_sub_bytes(inode, number);
19078c2ecf20Sopenharmony_ci		spin_unlock(&inode->i_lock);
19088c2ecf20Sopenharmony_ci		return;
19098c2ecf20Sopenharmony_ci	}
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
19128c2ecf20Sopenharmony_ci	index = srcu_read_lock(&dquot_srcu);
19138c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
19148c2ecf20Sopenharmony_ci	/* Claim reserved quotas to allocated quotas */
19158c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
19168c2ecf20Sopenharmony_ci		dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
19178c2ecf20Sopenharmony_ci		if (dquot) {
19188c2ecf20Sopenharmony_ci			spin_lock(&dquot->dq_dqb_lock);
19198c2ecf20Sopenharmony_ci			if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number))
19208c2ecf20Sopenharmony_ci				number = dquot->dq_dqb.dqb_curspace;
19218c2ecf20Sopenharmony_ci			dquot->dq_dqb.dqb_rsvspace += number;
19228c2ecf20Sopenharmony_ci			dquot->dq_dqb.dqb_curspace -= number;
19238c2ecf20Sopenharmony_ci			spin_unlock(&dquot->dq_dqb_lock);
19248c2ecf20Sopenharmony_ci		}
19258c2ecf20Sopenharmony_ci	}
19268c2ecf20Sopenharmony_ci	/* Update inode bytes */
19278c2ecf20Sopenharmony_ci	*inode_reserved_space(inode) += number;
19288c2ecf20Sopenharmony_ci	__inode_sub_bytes(inode, number);
19298c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
19308c2ecf20Sopenharmony_ci	mark_all_dquot_dirty(dquots);
19318c2ecf20Sopenharmony_ci	srcu_read_unlock(&dquot_srcu, index);
19328c2ecf20Sopenharmony_ci	return;
19338c2ecf20Sopenharmony_ci}
19348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_reclaim_space_nodirty);
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci/*
19378c2ecf20Sopenharmony_ci * This operation can block, but only after everything is updated
19388c2ecf20Sopenharmony_ci */
19398c2ecf20Sopenharmony_civoid __dquot_free_space(struct inode *inode, qsize_t number, int flags)
19408c2ecf20Sopenharmony_ci{
19418c2ecf20Sopenharmony_ci	unsigned int cnt;
19428c2ecf20Sopenharmony_ci	struct dquot_warn warn[MAXQUOTAS];
19438c2ecf20Sopenharmony_ci	struct dquot **dquots;
19448c2ecf20Sopenharmony_ci	struct dquot *dquot;
19458c2ecf20Sopenharmony_ci	int reserve = flags & DQUOT_SPACE_RESERVE, index;
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode)) {
19488c2ecf20Sopenharmony_ci		if (reserve) {
19498c2ecf20Sopenharmony_ci			spin_lock(&inode->i_lock);
19508c2ecf20Sopenharmony_ci			*inode_reserved_space(inode) -= number;
19518c2ecf20Sopenharmony_ci			spin_unlock(&inode->i_lock);
19528c2ecf20Sopenharmony_ci		} else {
19538c2ecf20Sopenharmony_ci			inode_sub_bytes(inode, number);
19548c2ecf20Sopenharmony_ci		}
19558c2ecf20Sopenharmony_ci		return;
19568c2ecf20Sopenharmony_ci	}
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
19598c2ecf20Sopenharmony_ci	index = srcu_read_lock(&dquot_srcu);
19608c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
19618c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
19628c2ecf20Sopenharmony_ci		int wtype;
19638c2ecf20Sopenharmony_ci
19648c2ecf20Sopenharmony_ci		warn[cnt].w_type = QUOTA_NL_NOWARN;
19658c2ecf20Sopenharmony_ci		dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
19668c2ecf20Sopenharmony_ci		if (!dquot)
19678c2ecf20Sopenharmony_ci			continue;
19688c2ecf20Sopenharmony_ci		spin_lock(&dquot->dq_dqb_lock);
19698c2ecf20Sopenharmony_ci		wtype = info_bdq_free(dquot, number);
19708c2ecf20Sopenharmony_ci		if (wtype != QUOTA_NL_NOWARN)
19718c2ecf20Sopenharmony_ci			prepare_warning(&warn[cnt], dquot, wtype);
19728c2ecf20Sopenharmony_ci		if (reserve)
19738c2ecf20Sopenharmony_ci			dquot_free_reserved_space(dquot, number);
19748c2ecf20Sopenharmony_ci		else
19758c2ecf20Sopenharmony_ci			dquot_decr_space(dquot, number);
19768c2ecf20Sopenharmony_ci		spin_unlock(&dquot->dq_dqb_lock);
19778c2ecf20Sopenharmony_ci	}
19788c2ecf20Sopenharmony_ci	if (reserve)
19798c2ecf20Sopenharmony_ci		*inode_reserved_space(inode) -= number;
19808c2ecf20Sopenharmony_ci	else
19818c2ecf20Sopenharmony_ci		__inode_sub_bytes(inode, number);
19828c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	if (reserve)
19858c2ecf20Sopenharmony_ci		goto out_unlock;
19868c2ecf20Sopenharmony_ci	mark_all_dquot_dirty(dquots);
19878c2ecf20Sopenharmony_ciout_unlock:
19888c2ecf20Sopenharmony_ci	srcu_read_unlock(&dquot_srcu, index);
19898c2ecf20Sopenharmony_ci	flush_warnings(warn);
19908c2ecf20Sopenharmony_ci}
19918c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__dquot_free_space);
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci/*
19948c2ecf20Sopenharmony_ci * This operation can block, but only after everything is updated
19958c2ecf20Sopenharmony_ci */
19968c2ecf20Sopenharmony_civoid dquot_free_inode(struct inode *inode)
19978c2ecf20Sopenharmony_ci{
19988c2ecf20Sopenharmony_ci	unsigned int cnt;
19998c2ecf20Sopenharmony_ci	struct dquot_warn warn[MAXQUOTAS];
20008c2ecf20Sopenharmony_ci	struct dquot * const *dquots;
20018c2ecf20Sopenharmony_ci	struct dquot *dquot;
20028c2ecf20Sopenharmony_ci	int index;
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode))
20058c2ecf20Sopenharmony_ci		return;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	dquots = i_dquot(inode);
20088c2ecf20Sopenharmony_ci	index = srcu_read_lock(&dquot_srcu);
20098c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
20108c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
20118c2ecf20Sopenharmony_ci		int wtype;
20128c2ecf20Sopenharmony_ci		warn[cnt].w_type = QUOTA_NL_NOWARN;
20138c2ecf20Sopenharmony_ci		dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
20148c2ecf20Sopenharmony_ci		if (!dquot)
20158c2ecf20Sopenharmony_ci			continue;
20168c2ecf20Sopenharmony_ci		spin_lock(&dquot->dq_dqb_lock);
20178c2ecf20Sopenharmony_ci		wtype = info_idq_free(dquot, 1);
20188c2ecf20Sopenharmony_ci		if (wtype != QUOTA_NL_NOWARN)
20198c2ecf20Sopenharmony_ci			prepare_warning(&warn[cnt], dquot, wtype);
20208c2ecf20Sopenharmony_ci		dquot_decr_inodes(dquot, 1);
20218c2ecf20Sopenharmony_ci		spin_unlock(&dquot->dq_dqb_lock);
20228c2ecf20Sopenharmony_ci	}
20238c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
20248c2ecf20Sopenharmony_ci	mark_all_dquot_dirty(dquots);
20258c2ecf20Sopenharmony_ci	srcu_read_unlock(&dquot_srcu, index);
20268c2ecf20Sopenharmony_ci	flush_warnings(warn);
20278c2ecf20Sopenharmony_ci}
20288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_free_inode);
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci/*
20318c2ecf20Sopenharmony_ci * Transfer the number of inode and blocks from one diskquota to an other.
20328c2ecf20Sopenharmony_ci * On success, dquot references in transfer_to are consumed and references
20338c2ecf20Sopenharmony_ci * to original dquots that need to be released are placed there. On failure,
20348c2ecf20Sopenharmony_ci * references are kept untouched.
20358c2ecf20Sopenharmony_ci *
20368c2ecf20Sopenharmony_ci * This operation can block, but only after everything is updated
20378c2ecf20Sopenharmony_ci * A transaction must be started when entering this function.
20388c2ecf20Sopenharmony_ci *
20398c2ecf20Sopenharmony_ci * We are holding reference on transfer_from & transfer_to, no need to
20408c2ecf20Sopenharmony_ci * protect them by srcu_read_lock().
20418c2ecf20Sopenharmony_ci */
20428c2ecf20Sopenharmony_ciint __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
20438c2ecf20Sopenharmony_ci{
20448c2ecf20Sopenharmony_ci	qsize_t cur_space;
20458c2ecf20Sopenharmony_ci	qsize_t rsv_space = 0;
20468c2ecf20Sopenharmony_ci	qsize_t inode_usage = 1;
20478c2ecf20Sopenharmony_ci	struct dquot *transfer_from[MAXQUOTAS] = {};
20488c2ecf20Sopenharmony_ci	int cnt, index, ret = 0;
20498c2ecf20Sopenharmony_ci	char is_valid[MAXQUOTAS] = {};
20508c2ecf20Sopenharmony_ci	struct dquot_warn warn_to[MAXQUOTAS];
20518c2ecf20Sopenharmony_ci	struct dquot_warn warn_from_inodes[MAXQUOTAS];
20528c2ecf20Sopenharmony_ci	struct dquot_warn warn_from_space[MAXQUOTAS];
20538c2ecf20Sopenharmony_ci
20548c2ecf20Sopenharmony_ci	if (IS_NOQUOTA(inode))
20558c2ecf20Sopenharmony_ci		return 0;
20568c2ecf20Sopenharmony_ci
20578c2ecf20Sopenharmony_ci	if (inode->i_sb->dq_op->get_inode_usage) {
20588c2ecf20Sopenharmony_ci		ret = inode->i_sb->dq_op->get_inode_usage(inode, &inode_usage);
20598c2ecf20Sopenharmony_ci		if (ret)
20608c2ecf20Sopenharmony_ci			return ret;
20618c2ecf20Sopenharmony_ci	}
20628c2ecf20Sopenharmony_ci
20638c2ecf20Sopenharmony_ci	/* Initialize the arrays */
20648c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
20658c2ecf20Sopenharmony_ci		warn_to[cnt].w_type = QUOTA_NL_NOWARN;
20668c2ecf20Sopenharmony_ci		warn_from_inodes[cnt].w_type = QUOTA_NL_NOWARN;
20678c2ecf20Sopenharmony_ci		warn_from_space[cnt].w_type = QUOTA_NL_NOWARN;
20688c2ecf20Sopenharmony_ci	}
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci	spin_lock(&dq_data_lock);
20718c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
20728c2ecf20Sopenharmony_ci	if (IS_NOQUOTA(inode)) {	/* File without quota accounting? */
20738c2ecf20Sopenharmony_ci		spin_unlock(&inode->i_lock);
20748c2ecf20Sopenharmony_ci		spin_unlock(&dq_data_lock);
20758c2ecf20Sopenharmony_ci		return 0;
20768c2ecf20Sopenharmony_ci	}
20778c2ecf20Sopenharmony_ci	cur_space = __inode_get_bytes(inode);
20788c2ecf20Sopenharmony_ci	rsv_space = __inode_get_rsv_space(inode);
20798c2ecf20Sopenharmony_ci	/*
20808c2ecf20Sopenharmony_ci	 * Build the transfer_from list, check limits, and update usage in
20818c2ecf20Sopenharmony_ci	 * the target structures.
20828c2ecf20Sopenharmony_ci	 */
20838c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
20848c2ecf20Sopenharmony_ci		/*
20858c2ecf20Sopenharmony_ci		 * Skip changes for same uid or gid or for turned off quota-type.
20868c2ecf20Sopenharmony_ci		 */
20878c2ecf20Sopenharmony_ci		if (!transfer_to[cnt])
20888c2ecf20Sopenharmony_ci			continue;
20898c2ecf20Sopenharmony_ci		/* Avoid races with quotaoff() */
20908c2ecf20Sopenharmony_ci		if (!sb_has_quota_active(inode->i_sb, cnt))
20918c2ecf20Sopenharmony_ci			continue;
20928c2ecf20Sopenharmony_ci		is_valid[cnt] = 1;
20938c2ecf20Sopenharmony_ci		transfer_from[cnt] = i_dquot(inode)[cnt];
20948c2ecf20Sopenharmony_ci		ret = dquot_add_inodes(transfer_to[cnt], inode_usage,
20958c2ecf20Sopenharmony_ci				       &warn_to[cnt]);
20968c2ecf20Sopenharmony_ci		if (ret)
20978c2ecf20Sopenharmony_ci			goto over_quota;
20988c2ecf20Sopenharmony_ci		ret = dquot_add_space(transfer_to[cnt], cur_space, rsv_space,
20998c2ecf20Sopenharmony_ci				      DQUOT_SPACE_WARN, &warn_to[cnt]);
21008c2ecf20Sopenharmony_ci		if (ret) {
21018c2ecf20Sopenharmony_ci			spin_lock(&transfer_to[cnt]->dq_dqb_lock);
21028c2ecf20Sopenharmony_ci			dquot_decr_inodes(transfer_to[cnt], inode_usage);
21038c2ecf20Sopenharmony_ci			spin_unlock(&transfer_to[cnt]->dq_dqb_lock);
21048c2ecf20Sopenharmony_ci			goto over_quota;
21058c2ecf20Sopenharmony_ci		}
21068c2ecf20Sopenharmony_ci	}
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	/* Decrease usage for source structures and update quota pointers */
21098c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
21108c2ecf20Sopenharmony_ci		if (!is_valid[cnt])
21118c2ecf20Sopenharmony_ci			continue;
21128c2ecf20Sopenharmony_ci		/* Due to IO error we might not have transfer_from[] structure */
21138c2ecf20Sopenharmony_ci		if (transfer_from[cnt]) {
21148c2ecf20Sopenharmony_ci			int wtype;
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci			spin_lock(&transfer_from[cnt]->dq_dqb_lock);
21178c2ecf20Sopenharmony_ci			wtype = info_idq_free(transfer_from[cnt], inode_usage);
21188c2ecf20Sopenharmony_ci			if (wtype != QUOTA_NL_NOWARN)
21198c2ecf20Sopenharmony_ci				prepare_warning(&warn_from_inodes[cnt],
21208c2ecf20Sopenharmony_ci						transfer_from[cnt], wtype);
21218c2ecf20Sopenharmony_ci			wtype = info_bdq_free(transfer_from[cnt],
21228c2ecf20Sopenharmony_ci					      cur_space + rsv_space);
21238c2ecf20Sopenharmony_ci			if (wtype != QUOTA_NL_NOWARN)
21248c2ecf20Sopenharmony_ci				prepare_warning(&warn_from_space[cnt],
21258c2ecf20Sopenharmony_ci						transfer_from[cnt], wtype);
21268c2ecf20Sopenharmony_ci			dquot_decr_inodes(transfer_from[cnt], inode_usage);
21278c2ecf20Sopenharmony_ci			dquot_decr_space(transfer_from[cnt], cur_space);
21288c2ecf20Sopenharmony_ci			dquot_free_reserved_space(transfer_from[cnt],
21298c2ecf20Sopenharmony_ci						  rsv_space);
21308c2ecf20Sopenharmony_ci			spin_unlock(&transfer_from[cnt]->dq_dqb_lock);
21318c2ecf20Sopenharmony_ci		}
21328c2ecf20Sopenharmony_ci		i_dquot(inode)[cnt] = transfer_to[cnt];
21338c2ecf20Sopenharmony_ci	}
21348c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
21358c2ecf20Sopenharmony_ci	spin_unlock(&dq_data_lock);
21368c2ecf20Sopenharmony_ci
21378c2ecf20Sopenharmony_ci	/*
21388c2ecf20Sopenharmony_ci	 * These arrays are local and we hold dquot references so we don't need
21398c2ecf20Sopenharmony_ci	 * the srcu protection but still take dquot_srcu to avoid warning in
21408c2ecf20Sopenharmony_ci	 * mark_all_dquot_dirty().
21418c2ecf20Sopenharmony_ci	 */
21428c2ecf20Sopenharmony_ci	index = srcu_read_lock(&dquot_srcu);
21438c2ecf20Sopenharmony_ci	mark_all_dquot_dirty(transfer_from);
21448c2ecf20Sopenharmony_ci	mark_all_dquot_dirty(transfer_to);
21458c2ecf20Sopenharmony_ci	srcu_read_unlock(&dquot_srcu, index);
21468c2ecf20Sopenharmony_ci
21478c2ecf20Sopenharmony_ci	flush_warnings(warn_to);
21488c2ecf20Sopenharmony_ci	flush_warnings(warn_from_inodes);
21498c2ecf20Sopenharmony_ci	flush_warnings(warn_from_space);
21508c2ecf20Sopenharmony_ci	/* Pass back references to put */
21518c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
21528c2ecf20Sopenharmony_ci		if (is_valid[cnt])
21538c2ecf20Sopenharmony_ci			transfer_to[cnt] = transfer_from[cnt];
21548c2ecf20Sopenharmony_ci	return 0;
21558c2ecf20Sopenharmony_ciover_quota:
21568c2ecf20Sopenharmony_ci	/* Back out changes we already did */
21578c2ecf20Sopenharmony_ci	for (cnt--; cnt >= 0; cnt--) {
21588c2ecf20Sopenharmony_ci		if (!is_valid[cnt])
21598c2ecf20Sopenharmony_ci			continue;
21608c2ecf20Sopenharmony_ci		spin_lock(&transfer_to[cnt]->dq_dqb_lock);
21618c2ecf20Sopenharmony_ci		dquot_decr_inodes(transfer_to[cnt], inode_usage);
21628c2ecf20Sopenharmony_ci		dquot_decr_space(transfer_to[cnt], cur_space);
21638c2ecf20Sopenharmony_ci		dquot_free_reserved_space(transfer_to[cnt], rsv_space);
21648c2ecf20Sopenharmony_ci		spin_unlock(&transfer_to[cnt]->dq_dqb_lock);
21658c2ecf20Sopenharmony_ci	}
21668c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
21678c2ecf20Sopenharmony_ci	spin_unlock(&dq_data_lock);
21688c2ecf20Sopenharmony_ci	flush_warnings(warn_to);
21698c2ecf20Sopenharmony_ci	return ret;
21708c2ecf20Sopenharmony_ci}
21718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__dquot_transfer);
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_ci/* Wrapper for transferring ownership of an inode for uid/gid only
21748c2ecf20Sopenharmony_ci * Called from FSXXX_setattr()
21758c2ecf20Sopenharmony_ci */
21768c2ecf20Sopenharmony_ciint dquot_transfer(struct inode *inode, struct iattr *iattr)
21778c2ecf20Sopenharmony_ci{
21788c2ecf20Sopenharmony_ci	struct dquot *transfer_to[MAXQUOTAS] = {};
21798c2ecf20Sopenharmony_ci	struct dquot *dquot;
21808c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
21818c2ecf20Sopenharmony_ci	int ret;
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci	if (!inode_quota_active(inode))
21848c2ecf20Sopenharmony_ci		return 0;
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_ci	if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)){
21878c2ecf20Sopenharmony_ci		dquot = dqget(sb, make_kqid_uid(iattr->ia_uid));
21888c2ecf20Sopenharmony_ci		if (IS_ERR(dquot)) {
21898c2ecf20Sopenharmony_ci			if (PTR_ERR(dquot) != -ESRCH) {
21908c2ecf20Sopenharmony_ci				ret = PTR_ERR(dquot);
21918c2ecf20Sopenharmony_ci				goto out_put;
21928c2ecf20Sopenharmony_ci			}
21938c2ecf20Sopenharmony_ci			dquot = NULL;
21948c2ecf20Sopenharmony_ci		}
21958c2ecf20Sopenharmony_ci		transfer_to[USRQUOTA] = dquot;
21968c2ecf20Sopenharmony_ci	}
21978c2ecf20Sopenharmony_ci	if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid)){
21988c2ecf20Sopenharmony_ci		dquot = dqget(sb, make_kqid_gid(iattr->ia_gid));
21998c2ecf20Sopenharmony_ci		if (IS_ERR(dquot)) {
22008c2ecf20Sopenharmony_ci			if (PTR_ERR(dquot) != -ESRCH) {
22018c2ecf20Sopenharmony_ci				ret = PTR_ERR(dquot);
22028c2ecf20Sopenharmony_ci				goto out_put;
22038c2ecf20Sopenharmony_ci			}
22048c2ecf20Sopenharmony_ci			dquot = NULL;
22058c2ecf20Sopenharmony_ci		}
22068c2ecf20Sopenharmony_ci		transfer_to[GRPQUOTA] = dquot;
22078c2ecf20Sopenharmony_ci	}
22088c2ecf20Sopenharmony_ci	ret = __dquot_transfer(inode, transfer_to);
22098c2ecf20Sopenharmony_ciout_put:
22108c2ecf20Sopenharmony_ci	dqput_all(transfer_to);
22118c2ecf20Sopenharmony_ci	return ret;
22128c2ecf20Sopenharmony_ci}
22138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_transfer);
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci/*
22168c2ecf20Sopenharmony_ci * Write info of quota file to disk
22178c2ecf20Sopenharmony_ci */
22188c2ecf20Sopenharmony_ciint dquot_commit_info(struct super_block *sb, int type)
22198c2ecf20Sopenharmony_ci{
22208c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
22218c2ecf20Sopenharmony_ci
22228c2ecf20Sopenharmony_ci	return dqopt->ops[type]->write_file_info(sb, type);
22238c2ecf20Sopenharmony_ci}
22248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_commit_info);
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ciint dquot_get_next_id(struct super_block *sb, struct kqid *qid)
22278c2ecf20Sopenharmony_ci{
22288c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
22298c2ecf20Sopenharmony_ci
22308c2ecf20Sopenharmony_ci	if (!sb_has_quota_active(sb, qid->type))
22318c2ecf20Sopenharmony_ci		return -ESRCH;
22328c2ecf20Sopenharmony_ci	if (!dqopt->ops[qid->type]->get_next_id)
22338c2ecf20Sopenharmony_ci		return -ENOSYS;
22348c2ecf20Sopenharmony_ci	return dqopt->ops[qid->type]->get_next_id(sb, qid);
22358c2ecf20Sopenharmony_ci}
22368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_get_next_id);
22378c2ecf20Sopenharmony_ci
22388c2ecf20Sopenharmony_ci/*
22398c2ecf20Sopenharmony_ci * Definitions of diskquota operations.
22408c2ecf20Sopenharmony_ci */
22418c2ecf20Sopenharmony_ciconst struct dquot_operations dquot_operations = {
22428c2ecf20Sopenharmony_ci	.write_dquot	= dquot_commit,
22438c2ecf20Sopenharmony_ci	.acquire_dquot	= dquot_acquire,
22448c2ecf20Sopenharmony_ci	.release_dquot	= dquot_release,
22458c2ecf20Sopenharmony_ci	.mark_dirty	= dquot_mark_dquot_dirty,
22468c2ecf20Sopenharmony_ci	.write_info	= dquot_commit_info,
22478c2ecf20Sopenharmony_ci	.alloc_dquot	= dquot_alloc,
22488c2ecf20Sopenharmony_ci	.destroy_dquot	= dquot_destroy,
22498c2ecf20Sopenharmony_ci	.get_next_id	= dquot_get_next_id,
22508c2ecf20Sopenharmony_ci};
22518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_operations);
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci/*
22548c2ecf20Sopenharmony_ci * Generic helper for ->open on filesystems supporting disk quotas.
22558c2ecf20Sopenharmony_ci */
22568c2ecf20Sopenharmony_ciint dquot_file_open(struct inode *inode, struct file *file)
22578c2ecf20Sopenharmony_ci{
22588c2ecf20Sopenharmony_ci	int error;
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci	error = generic_file_open(inode, file);
22618c2ecf20Sopenharmony_ci	if (!error && (file->f_mode & FMODE_WRITE))
22628c2ecf20Sopenharmony_ci		error = dquot_initialize(inode);
22638c2ecf20Sopenharmony_ci	return error;
22648c2ecf20Sopenharmony_ci}
22658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_file_open);
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_cistatic void vfs_cleanup_quota_inode(struct super_block *sb, int type)
22688c2ecf20Sopenharmony_ci{
22698c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
22708c2ecf20Sopenharmony_ci	struct inode *inode = dqopt->files[type];
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci	if (!inode)
22738c2ecf20Sopenharmony_ci		return;
22748c2ecf20Sopenharmony_ci	if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
22758c2ecf20Sopenharmony_ci		inode_lock(inode);
22768c2ecf20Sopenharmony_ci		inode->i_flags &= ~S_NOQUOTA;
22778c2ecf20Sopenharmony_ci		inode_unlock(inode);
22788c2ecf20Sopenharmony_ci	}
22798c2ecf20Sopenharmony_ci	dqopt->files[type] = NULL;
22808c2ecf20Sopenharmony_ci	iput(inode);
22818c2ecf20Sopenharmony_ci}
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci/*
22848c2ecf20Sopenharmony_ci * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
22858c2ecf20Sopenharmony_ci */
22868c2ecf20Sopenharmony_ciint dquot_disable(struct super_block *sb, int type, unsigned int flags)
22878c2ecf20Sopenharmony_ci{
22888c2ecf20Sopenharmony_ci	int cnt;
22898c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
22908c2ecf20Sopenharmony_ci
22918c2ecf20Sopenharmony_ci	/* s_umount should be held in exclusive mode */
22928c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount)))
22938c2ecf20Sopenharmony_ci		up_read(&sb->s_umount);
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci	/* Cannot turn off usage accounting without turning off limits, or
22968c2ecf20Sopenharmony_ci	 * suspend quotas and simultaneously turn quotas off. */
22978c2ecf20Sopenharmony_ci	if ((flags & DQUOT_USAGE_ENABLED && !(flags & DQUOT_LIMITS_ENABLED))
22988c2ecf20Sopenharmony_ci	    || (flags & DQUOT_SUSPENDED && flags & (DQUOT_LIMITS_ENABLED |
22998c2ecf20Sopenharmony_ci	    DQUOT_USAGE_ENABLED)))
23008c2ecf20Sopenharmony_ci		return -EINVAL;
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ci	/*
23038c2ecf20Sopenharmony_ci	 * Skip everything if there's nothing to do. We have to do this because
23048c2ecf20Sopenharmony_ci	 * sometimes we are called when fill_super() failed and calling
23058c2ecf20Sopenharmony_ci	 * sync_fs() in such cases does no good.
23068c2ecf20Sopenharmony_ci	 */
23078c2ecf20Sopenharmony_ci	if (!sb_any_quota_loaded(sb))
23088c2ecf20Sopenharmony_ci		return 0;
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
23118c2ecf20Sopenharmony_ci		if (type != -1 && cnt != type)
23128c2ecf20Sopenharmony_ci			continue;
23138c2ecf20Sopenharmony_ci		if (!sb_has_quota_loaded(sb, cnt))
23148c2ecf20Sopenharmony_ci			continue;
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci		if (flags & DQUOT_SUSPENDED) {
23178c2ecf20Sopenharmony_ci			spin_lock(&dq_state_lock);
23188c2ecf20Sopenharmony_ci			dqopt->flags |=
23198c2ecf20Sopenharmony_ci				dquot_state_flag(DQUOT_SUSPENDED, cnt);
23208c2ecf20Sopenharmony_ci			spin_unlock(&dq_state_lock);
23218c2ecf20Sopenharmony_ci		} else {
23228c2ecf20Sopenharmony_ci			spin_lock(&dq_state_lock);
23238c2ecf20Sopenharmony_ci			dqopt->flags &= ~dquot_state_flag(flags, cnt);
23248c2ecf20Sopenharmony_ci			/* Turning off suspended quotas? */
23258c2ecf20Sopenharmony_ci			if (!sb_has_quota_loaded(sb, cnt) &&
23268c2ecf20Sopenharmony_ci			    sb_has_quota_suspended(sb, cnt)) {
23278c2ecf20Sopenharmony_ci				dqopt->flags &=	~dquot_state_flag(
23288c2ecf20Sopenharmony_ci							DQUOT_SUSPENDED, cnt);
23298c2ecf20Sopenharmony_ci				spin_unlock(&dq_state_lock);
23308c2ecf20Sopenharmony_ci				vfs_cleanup_quota_inode(sb, cnt);
23318c2ecf20Sopenharmony_ci				continue;
23328c2ecf20Sopenharmony_ci			}
23338c2ecf20Sopenharmony_ci			spin_unlock(&dq_state_lock);
23348c2ecf20Sopenharmony_ci		}
23358c2ecf20Sopenharmony_ci
23368c2ecf20Sopenharmony_ci		/* We still have to keep quota loaded? */
23378c2ecf20Sopenharmony_ci		if (sb_has_quota_loaded(sb, cnt) && !(flags & DQUOT_SUSPENDED))
23388c2ecf20Sopenharmony_ci			continue;
23398c2ecf20Sopenharmony_ci
23408c2ecf20Sopenharmony_ci		/* Note: these are blocking operations */
23418c2ecf20Sopenharmony_ci		drop_dquot_ref(sb, cnt);
23428c2ecf20Sopenharmony_ci		invalidate_dquots(sb, cnt);
23438c2ecf20Sopenharmony_ci		/*
23448c2ecf20Sopenharmony_ci		 * Now all dquots should be invalidated, all writes done so we
23458c2ecf20Sopenharmony_ci		 * should be only users of the info. No locks needed.
23468c2ecf20Sopenharmony_ci		 */
23478c2ecf20Sopenharmony_ci		if (info_dirty(&dqopt->info[cnt]))
23488c2ecf20Sopenharmony_ci			sb->dq_op->write_info(sb, cnt);
23498c2ecf20Sopenharmony_ci		if (dqopt->ops[cnt]->free_file_info)
23508c2ecf20Sopenharmony_ci			dqopt->ops[cnt]->free_file_info(sb, cnt);
23518c2ecf20Sopenharmony_ci		put_quota_format(dqopt->info[cnt].dqi_format);
23528c2ecf20Sopenharmony_ci		dqopt->info[cnt].dqi_flags = 0;
23538c2ecf20Sopenharmony_ci		dqopt->info[cnt].dqi_igrace = 0;
23548c2ecf20Sopenharmony_ci		dqopt->info[cnt].dqi_bgrace = 0;
23558c2ecf20Sopenharmony_ci		dqopt->ops[cnt] = NULL;
23568c2ecf20Sopenharmony_ci	}
23578c2ecf20Sopenharmony_ci
23588c2ecf20Sopenharmony_ci	/* Skip syncing and setting flags if quota files are hidden */
23598c2ecf20Sopenharmony_ci	if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
23608c2ecf20Sopenharmony_ci		goto put_inodes;
23618c2ecf20Sopenharmony_ci
23628c2ecf20Sopenharmony_ci	/* Sync the superblock so that buffers with quota data are written to
23638c2ecf20Sopenharmony_ci	 * disk (and so userspace sees correct data afterwards). */
23648c2ecf20Sopenharmony_ci	if (sb->s_op->sync_fs)
23658c2ecf20Sopenharmony_ci		sb->s_op->sync_fs(sb, 1);
23668c2ecf20Sopenharmony_ci	sync_blockdev(sb->s_bdev);
23678c2ecf20Sopenharmony_ci	/* Now the quota files are just ordinary files and we can set the
23688c2ecf20Sopenharmony_ci	 * inode flags back. Moreover we discard the pagecache so that
23698c2ecf20Sopenharmony_ci	 * userspace sees the writes we did bypassing the pagecache. We
23708c2ecf20Sopenharmony_ci	 * must also discard the blockdev buffers so that we see the
23718c2ecf20Sopenharmony_ci	 * changes done by userspace on the next quotaon() */
23728c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
23738c2ecf20Sopenharmony_ci		if (!sb_has_quota_loaded(sb, cnt) && dqopt->files[cnt]) {
23748c2ecf20Sopenharmony_ci			inode_lock(dqopt->files[cnt]);
23758c2ecf20Sopenharmony_ci			truncate_inode_pages(&dqopt->files[cnt]->i_data, 0);
23768c2ecf20Sopenharmony_ci			inode_unlock(dqopt->files[cnt]);
23778c2ecf20Sopenharmony_ci		}
23788c2ecf20Sopenharmony_ci	if (sb->s_bdev)
23798c2ecf20Sopenharmony_ci		invalidate_bdev(sb->s_bdev);
23808c2ecf20Sopenharmony_ciput_inodes:
23818c2ecf20Sopenharmony_ci	/* We are done when suspending quotas */
23828c2ecf20Sopenharmony_ci	if (flags & DQUOT_SUSPENDED)
23838c2ecf20Sopenharmony_ci		return 0;
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
23868c2ecf20Sopenharmony_ci		if (!sb_has_quota_loaded(sb, cnt))
23878c2ecf20Sopenharmony_ci			vfs_cleanup_quota_inode(sb, cnt);
23888c2ecf20Sopenharmony_ci	return 0;
23898c2ecf20Sopenharmony_ci}
23908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_disable);
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ciint dquot_quota_off(struct super_block *sb, int type)
23938c2ecf20Sopenharmony_ci{
23948c2ecf20Sopenharmony_ci	return dquot_disable(sb, type,
23958c2ecf20Sopenharmony_ci			     DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
23968c2ecf20Sopenharmony_ci}
23978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_quota_off);
23988c2ecf20Sopenharmony_ci
23998c2ecf20Sopenharmony_ci/*
24008c2ecf20Sopenharmony_ci *	Turn quotas on on a device
24018c2ecf20Sopenharmony_ci */
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_cistatic int vfs_setup_quota_inode(struct inode *inode, int type)
24048c2ecf20Sopenharmony_ci{
24058c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
24068c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	if (is_bad_inode(inode))
24098c2ecf20Sopenharmony_ci		return -EUCLEAN;
24108c2ecf20Sopenharmony_ci	if (!S_ISREG(inode->i_mode))
24118c2ecf20Sopenharmony_ci		return -EACCES;
24128c2ecf20Sopenharmony_ci	if (IS_RDONLY(inode))
24138c2ecf20Sopenharmony_ci		return -EROFS;
24148c2ecf20Sopenharmony_ci	if (sb_has_quota_loaded(sb, type))
24158c2ecf20Sopenharmony_ci		return -EBUSY;
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	/*
24188c2ecf20Sopenharmony_ci	 * Quota files should never be encrypted.  They should be thought of as
24198c2ecf20Sopenharmony_ci	 * filesystem metadata, not user data.  New-style internal quota files
24208c2ecf20Sopenharmony_ci	 * cannot be encrypted by users anyway, but old-style external quota
24218c2ecf20Sopenharmony_ci	 * files could potentially be incorrectly created in an encrypted
24228c2ecf20Sopenharmony_ci	 * directory, hence this explicit check.  Some reasons why encrypted
24238c2ecf20Sopenharmony_ci	 * quota files don't work include: (1) some filesystems that support
24248c2ecf20Sopenharmony_ci	 * encryption don't handle it in their quota_read and quota_write, and
24258c2ecf20Sopenharmony_ci	 * (2) cleaning up encrypted quota files at unmount would need special
24268c2ecf20Sopenharmony_ci	 * consideration, as quota files are cleaned up later than user files.
24278c2ecf20Sopenharmony_ci	 */
24288c2ecf20Sopenharmony_ci	if (IS_ENCRYPTED(inode))
24298c2ecf20Sopenharmony_ci		return -EINVAL;
24308c2ecf20Sopenharmony_ci
24318c2ecf20Sopenharmony_ci	dqopt->files[type] = igrab(inode);
24328c2ecf20Sopenharmony_ci	if (!dqopt->files[type])
24338c2ecf20Sopenharmony_ci		return -EIO;
24348c2ecf20Sopenharmony_ci	if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
24358c2ecf20Sopenharmony_ci		/* We don't want quota and atime on quota files (deadlocks
24368c2ecf20Sopenharmony_ci		 * possible) Also nobody should write to the file - we use
24378c2ecf20Sopenharmony_ci		 * special IO operations which ignore the immutable bit. */
24388c2ecf20Sopenharmony_ci		inode_lock(inode);
24398c2ecf20Sopenharmony_ci		inode->i_flags |= S_NOQUOTA;
24408c2ecf20Sopenharmony_ci		inode_unlock(inode);
24418c2ecf20Sopenharmony_ci		/*
24428c2ecf20Sopenharmony_ci		 * When S_NOQUOTA is set, remove dquot references as no more
24438c2ecf20Sopenharmony_ci		 * references can be added
24448c2ecf20Sopenharmony_ci		 */
24458c2ecf20Sopenharmony_ci		__dquot_drop(inode);
24468c2ecf20Sopenharmony_ci	}
24478c2ecf20Sopenharmony_ci	return 0;
24488c2ecf20Sopenharmony_ci}
24498c2ecf20Sopenharmony_ci
24508c2ecf20Sopenharmony_ciint dquot_load_quota_sb(struct super_block *sb, int type, int format_id,
24518c2ecf20Sopenharmony_ci	unsigned int flags)
24528c2ecf20Sopenharmony_ci{
24538c2ecf20Sopenharmony_ci	struct quota_format_type *fmt = find_quota_format(format_id);
24548c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
24558c2ecf20Sopenharmony_ci	int error;
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci	/* Just unsuspend quotas? */
24588c2ecf20Sopenharmony_ci	BUG_ON(flags & DQUOT_SUSPENDED);
24598c2ecf20Sopenharmony_ci	/* s_umount should be held in exclusive mode */
24608c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount)))
24618c2ecf20Sopenharmony_ci		up_read(&sb->s_umount);
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci	if (!fmt)
24648c2ecf20Sopenharmony_ci		return -ESRCH;
24658c2ecf20Sopenharmony_ci	if (!sb->s_op->quota_write || !sb->s_op->quota_read ||
24668c2ecf20Sopenharmony_ci	    (type == PRJQUOTA && sb->dq_op->get_projid == NULL)) {
24678c2ecf20Sopenharmony_ci		error = -EINVAL;
24688c2ecf20Sopenharmony_ci		goto out_fmt;
24698c2ecf20Sopenharmony_ci	}
24708c2ecf20Sopenharmony_ci	/* Filesystems outside of init_user_ns not yet supported */
24718c2ecf20Sopenharmony_ci	if (sb->s_user_ns != &init_user_ns) {
24728c2ecf20Sopenharmony_ci		error = -EINVAL;
24738c2ecf20Sopenharmony_ci		goto out_fmt;
24748c2ecf20Sopenharmony_ci	}
24758c2ecf20Sopenharmony_ci	/* Usage always has to be set... */
24768c2ecf20Sopenharmony_ci	if (!(flags & DQUOT_USAGE_ENABLED)) {
24778c2ecf20Sopenharmony_ci		error = -EINVAL;
24788c2ecf20Sopenharmony_ci		goto out_fmt;
24798c2ecf20Sopenharmony_ci	}
24808c2ecf20Sopenharmony_ci	if (sb_has_quota_loaded(sb, type)) {
24818c2ecf20Sopenharmony_ci		error = -EBUSY;
24828c2ecf20Sopenharmony_ci		goto out_fmt;
24838c2ecf20Sopenharmony_ci	}
24848c2ecf20Sopenharmony_ci
24858c2ecf20Sopenharmony_ci	if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
24868c2ecf20Sopenharmony_ci		/* As we bypass the pagecache we must now flush all the
24878c2ecf20Sopenharmony_ci		 * dirty data and invalidate caches so that kernel sees
24888c2ecf20Sopenharmony_ci		 * changes from userspace. It is not enough to just flush
24898c2ecf20Sopenharmony_ci		 * the quota file since if blocksize < pagesize, invalidation
24908c2ecf20Sopenharmony_ci		 * of the cache could fail because of other unrelated dirty
24918c2ecf20Sopenharmony_ci		 * data */
24928c2ecf20Sopenharmony_ci		sync_filesystem(sb);
24938c2ecf20Sopenharmony_ci		invalidate_bdev(sb->s_bdev);
24948c2ecf20Sopenharmony_ci	}
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	error = -EINVAL;
24978c2ecf20Sopenharmony_ci	if (!fmt->qf_ops->check_quota_file(sb, type))
24988c2ecf20Sopenharmony_ci		goto out_fmt;
24998c2ecf20Sopenharmony_ci
25008c2ecf20Sopenharmony_ci	dqopt->ops[type] = fmt->qf_ops;
25018c2ecf20Sopenharmony_ci	dqopt->info[type].dqi_format = fmt;
25028c2ecf20Sopenharmony_ci	dqopt->info[type].dqi_fmt_id = format_id;
25038c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
25048c2ecf20Sopenharmony_ci	error = dqopt->ops[type]->read_file_info(sb, type);
25058c2ecf20Sopenharmony_ci	if (error < 0)
25068c2ecf20Sopenharmony_ci		goto out_fmt;
25078c2ecf20Sopenharmony_ci	if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) {
25088c2ecf20Sopenharmony_ci		spin_lock(&dq_data_lock);
25098c2ecf20Sopenharmony_ci		dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
25108c2ecf20Sopenharmony_ci		spin_unlock(&dq_data_lock);
25118c2ecf20Sopenharmony_ci	}
25128c2ecf20Sopenharmony_ci	spin_lock(&dq_state_lock);
25138c2ecf20Sopenharmony_ci	dqopt->flags |= dquot_state_flag(flags, type);
25148c2ecf20Sopenharmony_ci	spin_unlock(&dq_state_lock);
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci	error = add_dquot_ref(sb, type);
25178c2ecf20Sopenharmony_ci	if (error)
25188c2ecf20Sopenharmony_ci		dquot_disable(sb, type,
25198c2ecf20Sopenharmony_ci			      DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
25208c2ecf20Sopenharmony_ci
25218c2ecf20Sopenharmony_ci	return error;
25228c2ecf20Sopenharmony_ciout_fmt:
25238c2ecf20Sopenharmony_ci	put_quota_format(fmt);
25248c2ecf20Sopenharmony_ci
25258c2ecf20Sopenharmony_ci	return error;
25268c2ecf20Sopenharmony_ci}
25278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_load_quota_sb);
25288c2ecf20Sopenharmony_ci
25298c2ecf20Sopenharmony_ci/*
25308c2ecf20Sopenharmony_ci * More powerful function for turning on quotas on given quota inode allowing
25318c2ecf20Sopenharmony_ci * setting of individual quota flags
25328c2ecf20Sopenharmony_ci */
25338c2ecf20Sopenharmony_ciint dquot_load_quota_inode(struct inode *inode, int type, int format_id,
25348c2ecf20Sopenharmony_ci	unsigned int flags)
25358c2ecf20Sopenharmony_ci{
25368c2ecf20Sopenharmony_ci	int err;
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_ci	err = vfs_setup_quota_inode(inode, type);
25398c2ecf20Sopenharmony_ci	if (err < 0)
25408c2ecf20Sopenharmony_ci		return err;
25418c2ecf20Sopenharmony_ci	err = dquot_load_quota_sb(inode->i_sb, type, format_id, flags);
25428c2ecf20Sopenharmony_ci	if (err < 0)
25438c2ecf20Sopenharmony_ci		vfs_cleanup_quota_inode(inode->i_sb, type);
25448c2ecf20Sopenharmony_ci	return err;
25458c2ecf20Sopenharmony_ci}
25468c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_load_quota_inode);
25478c2ecf20Sopenharmony_ci
25488c2ecf20Sopenharmony_ci/* Reenable quotas on remount RW */
25498c2ecf20Sopenharmony_ciint dquot_resume(struct super_block *sb, int type)
25508c2ecf20Sopenharmony_ci{
25518c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
25528c2ecf20Sopenharmony_ci	int ret = 0, cnt;
25538c2ecf20Sopenharmony_ci	unsigned int flags;
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci	/* s_umount should be held in exclusive mode */
25568c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount)))
25578c2ecf20Sopenharmony_ci		up_read(&sb->s_umount);
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
25608c2ecf20Sopenharmony_ci		if (type != -1 && cnt != type)
25618c2ecf20Sopenharmony_ci			continue;
25628c2ecf20Sopenharmony_ci		if (!sb_has_quota_suspended(sb, cnt))
25638c2ecf20Sopenharmony_ci			continue;
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci		spin_lock(&dq_state_lock);
25668c2ecf20Sopenharmony_ci		flags = dqopt->flags & dquot_state_flag(DQUOT_USAGE_ENABLED |
25678c2ecf20Sopenharmony_ci							DQUOT_LIMITS_ENABLED,
25688c2ecf20Sopenharmony_ci							cnt);
25698c2ecf20Sopenharmony_ci		dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt);
25708c2ecf20Sopenharmony_ci		spin_unlock(&dq_state_lock);
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_ci		flags = dquot_generic_flag(flags, cnt);
25738c2ecf20Sopenharmony_ci		ret = dquot_load_quota_sb(sb, cnt, dqopt->info[cnt].dqi_fmt_id,
25748c2ecf20Sopenharmony_ci					  flags);
25758c2ecf20Sopenharmony_ci		if (ret < 0)
25768c2ecf20Sopenharmony_ci			vfs_cleanup_quota_inode(sb, cnt);
25778c2ecf20Sopenharmony_ci	}
25788c2ecf20Sopenharmony_ci
25798c2ecf20Sopenharmony_ci	return ret;
25808c2ecf20Sopenharmony_ci}
25818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_resume);
25828c2ecf20Sopenharmony_ci
25838c2ecf20Sopenharmony_ciint dquot_quota_on(struct super_block *sb, int type, int format_id,
25848c2ecf20Sopenharmony_ci		   const struct path *path)
25858c2ecf20Sopenharmony_ci{
25868c2ecf20Sopenharmony_ci	int error = security_quota_on(path->dentry);
25878c2ecf20Sopenharmony_ci	if (error)
25888c2ecf20Sopenharmony_ci		return error;
25898c2ecf20Sopenharmony_ci	/* Quota file not on the same filesystem? */
25908c2ecf20Sopenharmony_ci	if (path->dentry->d_sb != sb)
25918c2ecf20Sopenharmony_ci		error = -EXDEV;
25928c2ecf20Sopenharmony_ci	else
25938c2ecf20Sopenharmony_ci		error = dquot_load_quota_inode(d_inode(path->dentry), type,
25948c2ecf20Sopenharmony_ci					     format_id, DQUOT_USAGE_ENABLED |
25958c2ecf20Sopenharmony_ci					     DQUOT_LIMITS_ENABLED);
25968c2ecf20Sopenharmony_ci	return error;
25978c2ecf20Sopenharmony_ci}
25988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_quota_on);
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_ci/*
26018c2ecf20Sopenharmony_ci * This function is used when filesystem needs to initialize quotas
26028c2ecf20Sopenharmony_ci * during mount time.
26038c2ecf20Sopenharmony_ci */
26048c2ecf20Sopenharmony_ciint dquot_quota_on_mount(struct super_block *sb, char *qf_name,
26058c2ecf20Sopenharmony_ci		int format_id, int type)
26068c2ecf20Sopenharmony_ci{
26078c2ecf20Sopenharmony_ci	struct dentry *dentry;
26088c2ecf20Sopenharmony_ci	int error;
26098c2ecf20Sopenharmony_ci
26108c2ecf20Sopenharmony_ci	dentry = lookup_positive_unlocked(qf_name, sb->s_root, strlen(qf_name));
26118c2ecf20Sopenharmony_ci	if (IS_ERR(dentry))
26128c2ecf20Sopenharmony_ci		return PTR_ERR(dentry);
26138c2ecf20Sopenharmony_ci
26148c2ecf20Sopenharmony_ci	error = security_quota_on(dentry);
26158c2ecf20Sopenharmony_ci	if (!error)
26168c2ecf20Sopenharmony_ci		error = dquot_load_quota_inode(d_inode(dentry), type, format_id,
26178c2ecf20Sopenharmony_ci				DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_ci	dput(dentry);
26208c2ecf20Sopenharmony_ci	return error;
26218c2ecf20Sopenharmony_ci}
26228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_quota_on_mount);
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_cistatic int dquot_quota_enable(struct super_block *sb, unsigned int flags)
26258c2ecf20Sopenharmony_ci{
26268c2ecf20Sopenharmony_ci	int ret;
26278c2ecf20Sopenharmony_ci	int type;
26288c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
26298c2ecf20Sopenharmony_ci
26308c2ecf20Sopenharmony_ci	if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
26318c2ecf20Sopenharmony_ci		return -ENOSYS;
26328c2ecf20Sopenharmony_ci	/* Accounting cannot be turned on while fs is mounted */
26338c2ecf20Sopenharmony_ci	flags &= ~(FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT);
26348c2ecf20Sopenharmony_ci	if (!flags)
26358c2ecf20Sopenharmony_ci		return -EINVAL;
26368c2ecf20Sopenharmony_ci	for (type = 0; type < MAXQUOTAS; type++) {
26378c2ecf20Sopenharmony_ci		if (!(flags & qtype_enforce_flag(type)))
26388c2ecf20Sopenharmony_ci			continue;
26398c2ecf20Sopenharmony_ci		/* Can't enforce without accounting */
26408c2ecf20Sopenharmony_ci		if (!sb_has_quota_usage_enabled(sb, type)) {
26418c2ecf20Sopenharmony_ci			ret = -EINVAL;
26428c2ecf20Sopenharmony_ci			goto out_err;
26438c2ecf20Sopenharmony_ci		}
26448c2ecf20Sopenharmony_ci		if (sb_has_quota_limits_enabled(sb, type)) {
26458c2ecf20Sopenharmony_ci			ret = -EBUSY;
26468c2ecf20Sopenharmony_ci			goto out_err;
26478c2ecf20Sopenharmony_ci		}
26488c2ecf20Sopenharmony_ci		spin_lock(&dq_state_lock);
26498c2ecf20Sopenharmony_ci		dqopt->flags |= dquot_state_flag(DQUOT_LIMITS_ENABLED, type);
26508c2ecf20Sopenharmony_ci		spin_unlock(&dq_state_lock);
26518c2ecf20Sopenharmony_ci	}
26528c2ecf20Sopenharmony_ci	return 0;
26538c2ecf20Sopenharmony_ciout_err:
26548c2ecf20Sopenharmony_ci	/* Backout enforcement enablement we already did */
26558c2ecf20Sopenharmony_ci	for (type--; type >= 0; type--)  {
26568c2ecf20Sopenharmony_ci		if (flags & qtype_enforce_flag(type))
26578c2ecf20Sopenharmony_ci			dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
26588c2ecf20Sopenharmony_ci	}
26598c2ecf20Sopenharmony_ci	/* Error code translation for better compatibility with XFS */
26608c2ecf20Sopenharmony_ci	if (ret == -EBUSY)
26618c2ecf20Sopenharmony_ci		ret = -EEXIST;
26628c2ecf20Sopenharmony_ci	return ret;
26638c2ecf20Sopenharmony_ci}
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_cistatic int dquot_quota_disable(struct super_block *sb, unsigned int flags)
26668c2ecf20Sopenharmony_ci{
26678c2ecf20Sopenharmony_ci	int ret;
26688c2ecf20Sopenharmony_ci	int type;
26698c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ci	if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
26728c2ecf20Sopenharmony_ci		return -ENOSYS;
26738c2ecf20Sopenharmony_ci	/*
26748c2ecf20Sopenharmony_ci	 * We don't support turning off accounting via quotactl. In principle
26758c2ecf20Sopenharmony_ci	 * quota infrastructure can do this but filesystems don't expect
26768c2ecf20Sopenharmony_ci	 * userspace to be able to do it.
26778c2ecf20Sopenharmony_ci	 */
26788c2ecf20Sopenharmony_ci	if (flags &
26798c2ecf20Sopenharmony_ci		  (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT))
26808c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci	/* Filter out limits not enabled */
26838c2ecf20Sopenharmony_ci	for (type = 0; type < MAXQUOTAS; type++)
26848c2ecf20Sopenharmony_ci		if (!sb_has_quota_limits_enabled(sb, type))
26858c2ecf20Sopenharmony_ci			flags &= ~qtype_enforce_flag(type);
26868c2ecf20Sopenharmony_ci	/* Nothing left? */
26878c2ecf20Sopenharmony_ci	if (!flags)
26888c2ecf20Sopenharmony_ci		return -EEXIST;
26898c2ecf20Sopenharmony_ci	for (type = 0; type < MAXQUOTAS; type++) {
26908c2ecf20Sopenharmony_ci		if (flags & qtype_enforce_flag(type)) {
26918c2ecf20Sopenharmony_ci			ret = dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
26928c2ecf20Sopenharmony_ci			if (ret < 0)
26938c2ecf20Sopenharmony_ci				goto out_err;
26948c2ecf20Sopenharmony_ci		}
26958c2ecf20Sopenharmony_ci	}
26968c2ecf20Sopenharmony_ci	return 0;
26978c2ecf20Sopenharmony_ciout_err:
26988c2ecf20Sopenharmony_ci	/* Backout enforcement disabling we already did */
26998c2ecf20Sopenharmony_ci	for (type--; type >= 0; type--)  {
27008c2ecf20Sopenharmony_ci		if (flags & qtype_enforce_flag(type)) {
27018c2ecf20Sopenharmony_ci			spin_lock(&dq_state_lock);
27028c2ecf20Sopenharmony_ci			dqopt->flags |=
27038c2ecf20Sopenharmony_ci				dquot_state_flag(DQUOT_LIMITS_ENABLED, type);
27048c2ecf20Sopenharmony_ci			spin_unlock(&dq_state_lock);
27058c2ecf20Sopenharmony_ci		}
27068c2ecf20Sopenharmony_ci	}
27078c2ecf20Sopenharmony_ci	return ret;
27088c2ecf20Sopenharmony_ci}
27098c2ecf20Sopenharmony_ci
27108c2ecf20Sopenharmony_ci/* Generic routine for getting common part of quota structure */
27118c2ecf20Sopenharmony_cistatic void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di)
27128c2ecf20Sopenharmony_ci{
27138c2ecf20Sopenharmony_ci	struct mem_dqblk *dm = &dquot->dq_dqb;
27148c2ecf20Sopenharmony_ci
27158c2ecf20Sopenharmony_ci	memset(di, 0, sizeof(*di));
27168c2ecf20Sopenharmony_ci	spin_lock(&dquot->dq_dqb_lock);
27178c2ecf20Sopenharmony_ci	di->d_spc_hardlimit = dm->dqb_bhardlimit;
27188c2ecf20Sopenharmony_ci	di->d_spc_softlimit = dm->dqb_bsoftlimit;
27198c2ecf20Sopenharmony_ci	di->d_ino_hardlimit = dm->dqb_ihardlimit;
27208c2ecf20Sopenharmony_ci	di->d_ino_softlimit = dm->dqb_isoftlimit;
27218c2ecf20Sopenharmony_ci	di->d_space = dm->dqb_curspace + dm->dqb_rsvspace;
27228c2ecf20Sopenharmony_ci	di->d_ino_count = dm->dqb_curinodes;
27238c2ecf20Sopenharmony_ci	di->d_spc_timer = dm->dqb_btime;
27248c2ecf20Sopenharmony_ci	di->d_ino_timer = dm->dqb_itime;
27258c2ecf20Sopenharmony_ci	spin_unlock(&dquot->dq_dqb_lock);
27268c2ecf20Sopenharmony_ci}
27278c2ecf20Sopenharmony_ci
27288c2ecf20Sopenharmony_ciint dquot_get_dqblk(struct super_block *sb, struct kqid qid,
27298c2ecf20Sopenharmony_ci		    struct qc_dqblk *di)
27308c2ecf20Sopenharmony_ci{
27318c2ecf20Sopenharmony_ci	struct dquot *dquot;
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci	dquot = dqget(sb, qid);
27348c2ecf20Sopenharmony_ci	if (IS_ERR(dquot))
27358c2ecf20Sopenharmony_ci		return PTR_ERR(dquot);
27368c2ecf20Sopenharmony_ci	do_get_dqblk(dquot, di);
27378c2ecf20Sopenharmony_ci	dqput(dquot);
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci	return 0;
27408c2ecf20Sopenharmony_ci}
27418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_get_dqblk);
27428c2ecf20Sopenharmony_ci
27438c2ecf20Sopenharmony_ciint dquot_get_next_dqblk(struct super_block *sb, struct kqid *qid,
27448c2ecf20Sopenharmony_ci			 struct qc_dqblk *di)
27458c2ecf20Sopenharmony_ci{
27468c2ecf20Sopenharmony_ci	struct dquot *dquot;
27478c2ecf20Sopenharmony_ci	int err;
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ci	if (!sb->dq_op->get_next_id)
27508c2ecf20Sopenharmony_ci		return -ENOSYS;
27518c2ecf20Sopenharmony_ci	err = sb->dq_op->get_next_id(sb, qid);
27528c2ecf20Sopenharmony_ci	if (err < 0)
27538c2ecf20Sopenharmony_ci		return err;
27548c2ecf20Sopenharmony_ci	dquot = dqget(sb, *qid);
27558c2ecf20Sopenharmony_ci	if (IS_ERR(dquot))
27568c2ecf20Sopenharmony_ci		return PTR_ERR(dquot);
27578c2ecf20Sopenharmony_ci	do_get_dqblk(dquot, di);
27588c2ecf20Sopenharmony_ci	dqput(dquot);
27598c2ecf20Sopenharmony_ci
27608c2ecf20Sopenharmony_ci	return 0;
27618c2ecf20Sopenharmony_ci}
27628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_get_next_dqblk);
27638c2ecf20Sopenharmony_ci
27648c2ecf20Sopenharmony_ci#define VFS_QC_MASK \
27658c2ecf20Sopenharmony_ci	(QC_SPACE | QC_SPC_SOFT | QC_SPC_HARD | \
27668c2ecf20Sopenharmony_ci	 QC_INO_COUNT | QC_INO_SOFT | QC_INO_HARD | \
27678c2ecf20Sopenharmony_ci	 QC_SPC_TIMER | QC_INO_TIMER)
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci/* Generic routine for setting common part of quota structure */
27708c2ecf20Sopenharmony_cistatic int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
27718c2ecf20Sopenharmony_ci{
27728c2ecf20Sopenharmony_ci	struct mem_dqblk *dm = &dquot->dq_dqb;
27738c2ecf20Sopenharmony_ci	int check_blim = 0, check_ilim = 0;
27748c2ecf20Sopenharmony_ci	struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci	if (di->d_fieldmask & ~VFS_QC_MASK)
27778c2ecf20Sopenharmony_ci		return -EINVAL;
27788c2ecf20Sopenharmony_ci
27798c2ecf20Sopenharmony_ci	if (((di->d_fieldmask & QC_SPC_SOFT) &&
27808c2ecf20Sopenharmony_ci	     di->d_spc_softlimit > dqi->dqi_max_spc_limit) ||
27818c2ecf20Sopenharmony_ci	    ((di->d_fieldmask & QC_SPC_HARD) &&
27828c2ecf20Sopenharmony_ci	     di->d_spc_hardlimit > dqi->dqi_max_spc_limit) ||
27838c2ecf20Sopenharmony_ci	    ((di->d_fieldmask & QC_INO_SOFT) &&
27848c2ecf20Sopenharmony_ci	     (di->d_ino_softlimit > dqi->dqi_max_ino_limit)) ||
27858c2ecf20Sopenharmony_ci	    ((di->d_fieldmask & QC_INO_HARD) &&
27868c2ecf20Sopenharmony_ci	     (di->d_ino_hardlimit > dqi->dqi_max_ino_limit)))
27878c2ecf20Sopenharmony_ci		return -ERANGE;
27888c2ecf20Sopenharmony_ci
27898c2ecf20Sopenharmony_ci	spin_lock(&dquot->dq_dqb_lock);
27908c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_SPACE) {
27918c2ecf20Sopenharmony_ci		dm->dqb_curspace = di->d_space - dm->dqb_rsvspace;
27928c2ecf20Sopenharmony_ci		check_blim = 1;
27938c2ecf20Sopenharmony_ci		set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
27948c2ecf20Sopenharmony_ci	}
27958c2ecf20Sopenharmony_ci
27968c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_SPC_SOFT)
27978c2ecf20Sopenharmony_ci		dm->dqb_bsoftlimit = di->d_spc_softlimit;
27988c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_SPC_HARD)
27998c2ecf20Sopenharmony_ci		dm->dqb_bhardlimit = di->d_spc_hardlimit;
28008c2ecf20Sopenharmony_ci	if (di->d_fieldmask & (QC_SPC_SOFT | QC_SPC_HARD)) {
28018c2ecf20Sopenharmony_ci		check_blim = 1;
28028c2ecf20Sopenharmony_ci		set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
28038c2ecf20Sopenharmony_ci	}
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_INO_COUNT) {
28068c2ecf20Sopenharmony_ci		dm->dqb_curinodes = di->d_ino_count;
28078c2ecf20Sopenharmony_ci		check_ilim = 1;
28088c2ecf20Sopenharmony_ci		set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
28098c2ecf20Sopenharmony_ci	}
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_INO_SOFT)
28128c2ecf20Sopenharmony_ci		dm->dqb_isoftlimit = di->d_ino_softlimit;
28138c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_INO_HARD)
28148c2ecf20Sopenharmony_ci		dm->dqb_ihardlimit = di->d_ino_hardlimit;
28158c2ecf20Sopenharmony_ci	if (di->d_fieldmask & (QC_INO_SOFT | QC_INO_HARD)) {
28168c2ecf20Sopenharmony_ci		check_ilim = 1;
28178c2ecf20Sopenharmony_ci		set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
28188c2ecf20Sopenharmony_ci	}
28198c2ecf20Sopenharmony_ci
28208c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_SPC_TIMER) {
28218c2ecf20Sopenharmony_ci		dm->dqb_btime = di->d_spc_timer;
28228c2ecf20Sopenharmony_ci		check_blim = 1;
28238c2ecf20Sopenharmony_ci		set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
28248c2ecf20Sopenharmony_ci	}
28258c2ecf20Sopenharmony_ci
28268c2ecf20Sopenharmony_ci	if (di->d_fieldmask & QC_INO_TIMER) {
28278c2ecf20Sopenharmony_ci		dm->dqb_itime = di->d_ino_timer;
28288c2ecf20Sopenharmony_ci		check_ilim = 1;
28298c2ecf20Sopenharmony_ci		set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
28308c2ecf20Sopenharmony_ci	}
28318c2ecf20Sopenharmony_ci
28328c2ecf20Sopenharmony_ci	if (check_blim) {
28338c2ecf20Sopenharmony_ci		if (!dm->dqb_bsoftlimit ||
28348c2ecf20Sopenharmony_ci		    dm->dqb_curspace + dm->dqb_rsvspace <= dm->dqb_bsoftlimit) {
28358c2ecf20Sopenharmony_ci			dm->dqb_btime = 0;
28368c2ecf20Sopenharmony_ci			clear_bit(DQ_BLKS_B, &dquot->dq_flags);
28378c2ecf20Sopenharmony_ci		} else if (!(di->d_fieldmask & QC_SPC_TIMER))
28388c2ecf20Sopenharmony_ci			/* Set grace only if user hasn't provided his own... */
28398c2ecf20Sopenharmony_ci			dm->dqb_btime = ktime_get_real_seconds() + dqi->dqi_bgrace;
28408c2ecf20Sopenharmony_ci	}
28418c2ecf20Sopenharmony_ci	if (check_ilim) {
28428c2ecf20Sopenharmony_ci		if (!dm->dqb_isoftlimit ||
28438c2ecf20Sopenharmony_ci		    dm->dqb_curinodes <= dm->dqb_isoftlimit) {
28448c2ecf20Sopenharmony_ci			dm->dqb_itime = 0;
28458c2ecf20Sopenharmony_ci			clear_bit(DQ_INODES_B, &dquot->dq_flags);
28468c2ecf20Sopenharmony_ci		} else if (!(di->d_fieldmask & QC_INO_TIMER))
28478c2ecf20Sopenharmony_ci			/* Set grace only if user hasn't provided his own... */
28488c2ecf20Sopenharmony_ci			dm->dqb_itime = ktime_get_real_seconds() + dqi->dqi_igrace;
28498c2ecf20Sopenharmony_ci	}
28508c2ecf20Sopenharmony_ci	if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit ||
28518c2ecf20Sopenharmony_ci	    dm->dqb_isoftlimit)
28528c2ecf20Sopenharmony_ci		clear_bit(DQ_FAKE_B, &dquot->dq_flags);
28538c2ecf20Sopenharmony_ci	else
28548c2ecf20Sopenharmony_ci		set_bit(DQ_FAKE_B, &dquot->dq_flags);
28558c2ecf20Sopenharmony_ci	spin_unlock(&dquot->dq_dqb_lock);
28568c2ecf20Sopenharmony_ci	mark_dquot_dirty(dquot);
28578c2ecf20Sopenharmony_ci
28588c2ecf20Sopenharmony_ci	return 0;
28598c2ecf20Sopenharmony_ci}
28608c2ecf20Sopenharmony_ci
28618c2ecf20Sopenharmony_ciint dquot_set_dqblk(struct super_block *sb, struct kqid qid,
28628c2ecf20Sopenharmony_ci		  struct qc_dqblk *di)
28638c2ecf20Sopenharmony_ci{
28648c2ecf20Sopenharmony_ci	struct dquot *dquot;
28658c2ecf20Sopenharmony_ci	int rc;
28668c2ecf20Sopenharmony_ci
28678c2ecf20Sopenharmony_ci	dquot = dqget(sb, qid);
28688c2ecf20Sopenharmony_ci	if (IS_ERR(dquot)) {
28698c2ecf20Sopenharmony_ci		rc = PTR_ERR(dquot);
28708c2ecf20Sopenharmony_ci		goto out;
28718c2ecf20Sopenharmony_ci	}
28728c2ecf20Sopenharmony_ci	rc = do_set_dqblk(dquot, di);
28738c2ecf20Sopenharmony_ci	dqput(dquot);
28748c2ecf20Sopenharmony_ciout:
28758c2ecf20Sopenharmony_ci	return rc;
28768c2ecf20Sopenharmony_ci}
28778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_set_dqblk);
28788c2ecf20Sopenharmony_ci
28798c2ecf20Sopenharmony_ci/* Generic routine for getting common part of quota file information */
28808c2ecf20Sopenharmony_ciint dquot_get_state(struct super_block *sb, struct qc_state *state)
28818c2ecf20Sopenharmony_ci{
28828c2ecf20Sopenharmony_ci	struct mem_dqinfo *mi;
28838c2ecf20Sopenharmony_ci	struct qc_type_state *tstate;
28848c2ecf20Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
28858c2ecf20Sopenharmony_ci	int type;
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci	memset(state, 0, sizeof(*state));
28888c2ecf20Sopenharmony_ci	for (type = 0; type < MAXQUOTAS; type++) {
28898c2ecf20Sopenharmony_ci		if (!sb_has_quota_active(sb, type))
28908c2ecf20Sopenharmony_ci			continue;
28918c2ecf20Sopenharmony_ci		tstate = state->s_state + type;
28928c2ecf20Sopenharmony_ci		mi = sb_dqopt(sb)->info + type;
28938c2ecf20Sopenharmony_ci		tstate->flags = QCI_ACCT_ENABLED;
28948c2ecf20Sopenharmony_ci		spin_lock(&dq_data_lock);
28958c2ecf20Sopenharmony_ci		if (mi->dqi_flags & DQF_SYS_FILE)
28968c2ecf20Sopenharmony_ci			tstate->flags |= QCI_SYSFILE;
28978c2ecf20Sopenharmony_ci		if (mi->dqi_flags & DQF_ROOT_SQUASH)
28988c2ecf20Sopenharmony_ci			tstate->flags |= QCI_ROOT_SQUASH;
28998c2ecf20Sopenharmony_ci		if (sb_has_quota_limits_enabled(sb, type))
29008c2ecf20Sopenharmony_ci			tstate->flags |= QCI_LIMITS_ENFORCED;
29018c2ecf20Sopenharmony_ci		tstate->spc_timelimit = mi->dqi_bgrace;
29028c2ecf20Sopenharmony_ci		tstate->ino_timelimit = mi->dqi_igrace;
29038c2ecf20Sopenharmony_ci		if (dqopt->files[type]) {
29048c2ecf20Sopenharmony_ci			tstate->ino = dqopt->files[type]->i_ino;
29058c2ecf20Sopenharmony_ci			tstate->blocks = dqopt->files[type]->i_blocks;
29068c2ecf20Sopenharmony_ci		}
29078c2ecf20Sopenharmony_ci		tstate->nextents = 1;	/* We don't know... */
29088c2ecf20Sopenharmony_ci		spin_unlock(&dq_data_lock);
29098c2ecf20Sopenharmony_ci	}
29108c2ecf20Sopenharmony_ci	return 0;
29118c2ecf20Sopenharmony_ci}
29128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_get_state);
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci/* Generic routine for setting common part of quota file information */
29158c2ecf20Sopenharmony_ciint dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii)
29168c2ecf20Sopenharmony_ci{
29178c2ecf20Sopenharmony_ci	struct mem_dqinfo *mi;
29188c2ecf20Sopenharmony_ci	int err = 0;
29198c2ecf20Sopenharmony_ci
29208c2ecf20Sopenharmony_ci	if ((ii->i_fieldmask & QC_WARNS_MASK) ||
29218c2ecf20Sopenharmony_ci	    (ii->i_fieldmask & QC_RT_SPC_TIMER))
29228c2ecf20Sopenharmony_ci		return -EINVAL;
29238c2ecf20Sopenharmony_ci	if (!sb_has_quota_active(sb, type))
29248c2ecf20Sopenharmony_ci		return -ESRCH;
29258c2ecf20Sopenharmony_ci	mi = sb_dqopt(sb)->info + type;
29268c2ecf20Sopenharmony_ci	if (ii->i_fieldmask & QC_FLAGS) {
29278c2ecf20Sopenharmony_ci		if ((ii->i_flags & QCI_ROOT_SQUASH &&
29288c2ecf20Sopenharmony_ci		     mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD))
29298c2ecf20Sopenharmony_ci			return -EINVAL;
29308c2ecf20Sopenharmony_ci	}
29318c2ecf20Sopenharmony_ci	spin_lock(&dq_data_lock);
29328c2ecf20Sopenharmony_ci	if (ii->i_fieldmask & QC_SPC_TIMER)
29338c2ecf20Sopenharmony_ci		mi->dqi_bgrace = ii->i_spc_timelimit;
29348c2ecf20Sopenharmony_ci	if (ii->i_fieldmask & QC_INO_TIMER)
29358c2ecf20Sopenharmony_ci		mi->dqi_igrace = ii->i_ino_timelimit;
29368c2ecf20Sopenharmony_ci	if (ii->i_fieldmask & QC_FLAGS) {
29378c2ecf20Sopenharmony_ci		if (ii->i_flags & QCI_ROOT_SQUASH)
29388c2ecf20Sopenharmony_ci			mi->dqi_flags |= DQF_ROOT_SQUASH;
29398c2ecf20Sopenharmony_ci		else
29408c2ecf20Sopenharmony_ci			mi->dqi_flags &= ~DQF_ROOT_SQUASH;
29418c2ecf20Sopenharmony_ci	}
29428c2ecf20Sopenharmony_ci	spin_unlock(&dq_data_lock);
29438c2ecf20Sopenharmony_ci	mark_info_dirty(sb, type);
29448c2ecf20Sopenharmony_ci	/* Force write to disk */
29458c2ecf20Sopenharmony_ci	sb->dq_op->write_info(sb, type);
29468c2ecf20Sopenharmony_ci	return err;
29478c2ecf20Sopenharmony_ci}
29488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_set_dqinfo);
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ciconst struct quotactl_ops dquot_quotactl_sysfile_ops = {
29518c2ecf20Sopenharmony_ci	.quota_enable	= dquot_quota_enable,
29528c2ecf20Sopenharmony_ci	.quota_disable	= dquot_quota_disable,
29538c2ecf20Sopenharmony_ci	.quota_sync	= dquot_quota_sync,
29548c2ecf20Sopenharmony_ci	.get_state	= dquot_get_state,
29558c2ecf20Sopenharmony_ci	.set_info	= dquot_set_dqinfo,
29568c2ecf20Sopenharmony_ci	.get_dqblk	= dquot_get_dqblk,
29578c2ecf20Sopenharmony_ci	.get_nextdqblk	= dquot_get_next_dqblk,
29588c2ecf20Sopenharmony_ci	.set_dqblk	= dquot_set_dqblk
29598c2ecf20Sopenharmony_ci};
29608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dquot_quotactl_sysfile_ops);
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_cistatic int do_proc_dqstats(struct ctl_table *table, int write,
29638c2ecf20Sopenharmony_ci		     void *buffer, size_t *lenp, loff_t *ppos)
29648c2ecf20Sopenharmony_ci{
29658c2ecf20Sopenharmony_ci	unsigned int type = (unsigned long *)table->data - dqstats.stat;
29668c2ecf20Sopenharmony_ci	s64 value = percpu_counter_sum(&dqstats.counter[type]);
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_ci	/* Filter negative values for non-monotonic counters */
29698c2ecf20Sopenharmony_ci	if (value < 0 && (type == DQST_ALLOC_DQUOTS ||
29708c2ecf20Sopenharmony_ci			  type == DQST_FREE_DQUOTS))
29718c2ecf20Sopenharmony_ci		value = 0;
29728c2ecf20Sopenharmony_ci
29738c2ecf20Sopenharmony_ci	/* Update global table */
29748c2ecf20Sopenharmony_ci	dqstats.stat[type] = value;
29758c2ecf20Sopenharmony_ci	return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
29768c2ecf20Sopenharmony_ci}
29778c2ecf20Sopenharmony_ci
29788c2ecf20Sopenharmony_cistatic struct ctl_table fs_dqstats_table[] = {
29798c2ecf20Sopenharmony_ci	{
29808c2ecf20Sopenharmony_ci		.procname	= "lookups",
29818c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_LOOKUPS],
29828c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
29838c2ecf20Sopenharmony_ci		.mode		= 0444,
29848c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
29858c2ecf20Sopenharmony_ci	},
29868c2ecf20Sopenharmony_ci	{
29878c2ecf20Sopenharmony_ci		.procname	= "drops",
29888c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_DROPS],
29898c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
29908c2ecf20Sopenharmony_ci		.mode		= 0444,
29918c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
29928c2ecf20Sopenharmony_ci	},
29938c2ecf20Sopenharmony_ci	{
29948c2ecf20Sopenharmony_ci		.procname	= "reads",
29958c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_READS],
29968c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
29978c2ecf20Sopenharmony_ci		.mode		= 0444,
29988c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
29998c2ecf20Sopenharmony_ci	},
30008c2ecf20Sopenharmony_ci	{
30018c2ecf20Sopenharmony_ci		.procname	= "writes",
30028c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_WRITES],
30038c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
30048c2ecf20Sopenharmony_ci		.mode		= 0444,
30058c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
30068c2ecf20Sopenharmony_ci	},
30078c2ecf20Sopenharmony_ci	{
30088c2ecf20Sopenharmony_ci		.procname	= "cache_hits",
30098c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_CACHE_HITS],
30108c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
30118c2ecf20Sopenharmony_ci		.mode		= 0444,
30128c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
30138c2ecf20Sopenharmony_ci	},
30148c2ecf20Sopenharmony_ci	{
30158c2ecf20Sopenharmony_ci		.procname	= "allocated_dquots",
30168c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_ALLOC_DQUOTS],
30178c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
30188c2ecf20Sopenharmony_ci		.mode		= 0444,
30198c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
30208c2ecf20Sopenharmony_ci	},
30218c2ecf20Sopenharmony_ci	{
30228c2ecf20Sopenharmony_ci		.procname	= "free_dquots",
30238c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_FREE_DQUOTS],
30248c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
30258c2ecf20Sopenharmony_ci		.mode		= 0444,
30268c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
30278c2ecf20Sopenharmony_ci	},
30288c2ecf20Sopenharmony_ci	{
30298c2ecf20Sopenharmony_ci		.procname	= "syncs",
30308c2ecf20Sopenharmony_ci		.data		= &dqstats.stat[DQST_SYNCS],
30318c2ecf20Sopenharmony_ci		.maxlen		= sizeof(unsigned long),
30328c2ecf20Sopenharmony_ci		.mode		= 0444,
30338c2ecf20Sopenharmony_ci		.proc_handler	= do_proc_dqstats,
30348c2ecf20Sopenharmony_ci	},
30358c2ecf20Sopenharmony_ci#ifdef CONFIG_PRINT_QUOTA_WARNING
30368c2ecf20Sopenharmony_ci	{
30378c2ecf20Sopenharmony_ci		.procname	= "warnings",
30388c2ecf20Sopenharmony_ci		.data		= &flag_print_warnings,
30398c2ecf20Sopenharmony_ci		.maxlen		= sizeof(int),
30408c2ecf20Sopenharmony_ci		.mode		= 0644,
30418c2ecf20Sopenharmony_ci		.proc_handler	= proc_dointvec,
30428c2ecf20Sopenharmony_ci	},
30438c2ecf20Sopenharmony_ci#endif
30448c2ecf20Sopenharmony_ci	{ },
30458c2ecf20Sopenharmony_ci};
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_cistatic struct ctl_table fs_table[] = {
30488c2ecf20Sopenharmony_ci	{
30498c2ecf20Sopenharmony_ci		.procname	= "quota",
30508c2ecf20Sopenharmony_ci		.mode		= 0555,
30518c2ecf20Sopenharmony_ci		.child		= fs_dqstats_table,
30528c2ecf20Sopenharmony_ci	},
30538c2ecf20Sopenharmony_ci	{ },
30548c2ecf20Sopenharmony_ci};
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_cistatic struct ctl_table sys_table[] = {
30578c2ecf20Sopenharmony_ci	{
30588c2ecf20Sopenharmony_ci		.procname	= "fs",
30598c2ecf20Sopenharmony_ci		.mode		= 0555,
30608c2ecf20Sopenharmony_ci		.child		= fs_table,
30618c2ecf20Sopenharmony_ci	},
30628c2ecf20Sopenharmony_ci	{ },
30638c2ecf20Sopenharmony_ci};
30648c2ecf20Sopenharmony_ci
30658c2ecf20Sopenharmony_cistatic int __init dquot_init(void)
30668c2ecf20Sopenharmony_ci{
30678c2ecf20Sopenharmony_ci	int i, ret;
30688c2ecf20Sopenharmony_ci	unsigned long nr_hash, order;
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_ci	printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__);
30718c2ecf20Sopenharmony_ci
30728c2ecf20Sopenharmony_ci	register_sysctl_table(sys_table);
30738c2ecf20Sopenharmony_ci
30748c2ecf20Sopenharmony_ci	dquot_cachep = kmem_cache_create("dquot",
30758c2ecf20Sopenharmony_ci			sizeof(struct dquot), sizeof(unsigned long) * 4,
30768c2ecf20Sopenharmony_ci			(SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
30778c2ecf20Sopenharmony_ci				SLAB_MEM_SPREAD|SLAB_PANIC),
30788c2ecf20Sopenharmony_ci			NULL);
30798c2ecf20Sopenharmony_ci
30808c2ecf20Sopenharmony_ci	order = 0;
30818c2ecf20Sopenharmony_ci	dquot_hash = (struct hlist_head *)__get_free_pages(GFP_KERNEL, order);
30828c2ecf20Sopenharmony_ci	if (!dquot_hash)
30838c2ecf20Sopenharmony_ci		panic("Cannot create dquot hash table");
30848c2ecf20Sopenharmony_ci
30858c2ecf20Sopenharmony_ci	for (i = 0; i < _DQST_DQSTAT_LAST; i++) {
30868c2ecf20Sopenharmony_ci		ret = percpu_counter_init(&dqstats.counter[i], 0, GFP_KERNEL);
30878c2ecf20Sopenharmony_ci		if (ret)
30888c2ecf20Sopenharmony_ci			panic("Cannot create dquot stat counters");
30898c2ecf20Sopenharmony_ci	}
30908c2ecf20Sopenharmony_ci
30918c2ecf20Sopenharmony_ci	/* Find power-of-two hlist_heads which can fit into allocation */
30928c2ecf20Sopenharmony_ci	nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct hlist_head);
30938c2ecf20Sopenharmony_ci	dq_hash_bits = ilog2(nr_hash);
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci	nr_hash = 1UL << dq_hash_bits;
30968c2ecf20Sopenharmony_ci	dq_hash_mask = nr_hash - 1;
30978c2ecf20Sopenharmony_ci	for (i = 0; i < nr_hash; i++)
30988c2ecf20Sopenharmony_ci		INIT_HLIST_HEAD(dquot_hash + i);
30998c2ecf20Sopenharmony_ci
31008c2ecf20Sopenharmony_ci	pr_info("VFS: Dquot-cache hash table entries: %ld (order %ld,"
31018c2ecf20Sopenharmony_ci		" %ld bytes)\n", nr_hash, order, (PAGE_SIZE << order));
31028c2ecf20Sopenharmony_ci
31038c2ecf20Sopenharmony_ci	if (register_shrinker(&dqcache_shrinker))
31048c2ecf20Sopenharmony_ci		panic("Cannot register dquot shrinker");
31058c2ecf20Sopenharmony_ci
31068c2ecf20Sopenharmony_ci	return 0;
31078c2ecf20Sopenharmony_ci}
31088c2ecf20Sopenharmony_cifs_initcall(dquot_init);
3109