cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xfs_quotaops.c (6381B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2008, Christoph Hellwig
      4 * All Rights Reserved.
      5 */
      6#include "xfs.h"
      7#include "xfs_shared.h"
      8#include "xfs_format.h"
      9#include "xfs_log_format.h"
     10#include "xfs_trans_resv.h"
     11#include "xfs_mount.h"
     12#include "xfs_inode.h"
     13#include "xfs_quota.h"
     14#include "xfs_trans.h"
     15#include "xfs_icache.h"
     16#include "xfs_qm.h"
     17
     18
     19static void
     20xfs_qm_fill_state(
     21	struct qc_type_state	*tstate,
     22	struct xfs_mount	*mp,
     23	struct xfs_inode	*ip,
     24	xfs_ino_t		ino,
     25	struct xfs_def_quota	*defq)
     26{
     27	bool			tempqip = false;
     28
     29	tstate->ino = ino;
     30	if (!ip && ino == NULLFSINO)
     31		return;
     32	if (!ip) {
     33		if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
     34			return;
     35		tempqip = true;
     36	}
     37	tstate->flags |= QCI_SYSFILE;
     38	tstate->blocks = ip->i_nblocks;
     39	tstate->nextents = ip->i_df.if_nextents;
     40	tstate->spc_timelimit = (u32)defq->blk.time;
     41	tstate->ino_timelimit = (u32)defq->ino.time;
     42	tstate->rt_spc_timelimit = (u32)defq->rtb.time;
     43	tstate->spc_warnlimit = 0;
     44	tstate->ino_warnlimit = 0;
     45	tstate->rt_spc_warnlimit = 0;
     46	if (tempqip)
     47		xfs_irele(ip);
     48}
     49
     50/*
     51 * Return quota status information, such as enforcements, quota file inode
     52 * numbers etc.
     53 */
     54static int
     55xfs_fs_get_quota_state(
     56	struct super_block	*sb,
     57	struct qc_state		*state)
     58{
     59	struct xfs_mount *mp = XFS_M(sb);
     60	struct xfs_quotainfo *q = mp->m_quotainfo;
     61
     62	memset(state, 0, sizeof(*state));
     63	if (!XFS_IS_QUOTA_ON(mp))
     64		return 0;
     65	state->s_incoredqs = q->qi_dquots;
     66	if (XFS_IS_UQUOTA_ON(mp))
     67		state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
     68	if (XFS_IS_UQUOTA_ENFORCED(mp))
     69		state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
     70	if (XFS_IS_GQUOTA_ON(mp))
     71		state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
     72	if (XFS_IS_GQUOTA_ENFORCED(mp))
     73		state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
     74	if (XFS_IS_PQUOTA_ON(mp))
     75		state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
     76	if (XFS_IS_PQUOTA_ENFORCED(mp))
     77		state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
     78
     79	xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
     80			  mp->m_sb.sb_uquotino, &q->qi_usr_default);
     81	xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
     82			  mp->m_sb.sb_gquotino, &q->qi_grp_default);
     83	xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
     84			  mp->m_sb.sb_pquotino, &q->qi_prj_default);
     85	return 0;
     86}
     87
     88STATIC xfs_dqtype_t
     89xfs_quota_type(int type)
     90{
     91	switch (type) {
     92	case USRQUOTA:
     93		return XFS_DQTYPE_USER;
     94	case GRPQUOTA:
     95		return XFS_DQTYPE_GROUP;
     96	default:
     97		return XFS_DQTYPE_PROJ;
     98	}
     99}
    100
    101#define XFS_QC_SETINFO_MASK (QC_TIMER_MASK)
    102
    103/*
    104 * Adjust quota timers & warnings
    105 */
    106static int
    107xfs_fs_set_info(
    108	struct super_block	*sb,
    109	int			type,
    110	struct qc_info		*info)
    111{
    112	struct xfs_mount	*mp = XFS_M(sb);
    113	struct qc_dqblk		newlim;
    114
    115	if (sb_rdonly(sb))
    116		return -EROFS;
    117	if (!XFS_IS_QUOTA_ON(mp))
    118		return -ENOSYS;
    119	if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
    120		return -EINVAL;
    121	if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
    122		return 0;
    123
    124	newlim.d_fieldmask = info->i_fieldmask;
    125	newlim.d_spc_timer = info->i_spc_timelimit;
    126	newlim.d_ino_timer = info->i_ino_timelimit;
    127	newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
    128	newlim.d_ino_warns = info->i_ino_warnlimit;
    129	newlim.d_spc_warns = info->i_spc_warnlimit;
    130	newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
    131
    132	return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
    133}
    134
    135static unsigned int
    136xfs_quota_flags(unsigned int uflags)
    137{
    138	unsigned int flags = 0;
    139
    140	if (uflags & FS_QUOTA_UDQ_ACCT)
    141		flags |= XFS_UQUOTA_ACCT;
    142	if (uflags & FS_QUOTA_PDQ_ACCT)
    143		flags |= XFS_PQUOTA_ACCT;
    144	if (uflags & FS_QUOTA_GDQ_ACCT)
    145		flags |= XFS_GQUOTA_ACCT;
    146	if (uflags & FS_QUOTA_UDQ_ENFD)
    147		flags |= XFS_UQUOTA_ENFD;
    148	if (uflags & FS_QUOTA_GDQ_ENFD)
    149		flags |= XFS_GQUOTA_ENFD;
    150	if (uflags & FS_QUOTA_PDQ_ENFD)
    151		flags |= XFS_PQUOTA_ENFD;
    152
    153	return flags;
    154}
    155
    156STATIC int
    157xfs_quota_enable(
    158	struct super_block	*sb,
    159	unsigned int		uflags)
    160{
    161	struct xfs_mount	*mp = XFS_M(sb);
    162
    163	if (sb_rdonly(sb))
    164		return -EROFS;
    165	if (!XFS_IS_QUOTA_ON(mp))
    166		return -ENOSYS;
    167
    168	return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
    169}
    170
    171STATIC int
    172xfs_quota_disable(
    173	struct super_block	*sb,
    174	unsigned int		uflags)
    175{
    176	struct xfs_mount	*mp = XFS_M(sb);
    177
    178	if (sb_rdonly(sb))
    179		return -EROFS;
    180	if (!XFS_IS_QUOTA_ON(mp))
    181		return -ENOSYS;
    182
    183	return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
    184}
    185
    186STATIC int
    187xfs_fs_rm_xquota(
    188	struct super_block	*sb,
    189	unsigned int		uflags)
    190{
    191	struct xfs_mount	*mp = XFS_M(sb);
    192	unsigned int		flags = 0;
    193
    194	if (sb_rdonly(sb))
    195		return -EROFS;
    196
    197	if (XFS_IS_QUOTA_ON(mp))
    198		return -EINVAL;
    199
    200	if (uflags & ~(FS_USER_QUOTA | FS_GROUP_QUOTA | FS_PROJ_QUOTA))
    201		return -EINVAL;
    202
    203	if (uflags & FS_USER_QUOTA)
    204		flags |= XFS_QMOPT_UQUOTA;
    205	if (uflags & FS_GROUP_QUOTA)
    206		flags |= XFS_QMOPT_GQUOTA;
    207	if (uflags & FS_PROJ_QUOTA)
    208		flags |= XFS_QMOPT_PQUOTA;
    209
    210	return xfs_qm_scall_trunc_qfiles(mp, flags);
    211}
    212
    213STATIC int
    214xfs_fs_get_dqblk(
    215	struct super_block	*sb,
    216	struct kqid		qid,
    217	struct qc_dqblk		*qdq)
    218{
    219	struct xfs_mount	*mp = XFS_M(sb);
    220	xfs_dqid_t		id;
    221
    222	if (!XFS_IS_QUOTA_ON(mp))
    223		return -ENOSYS;
    224
    225	id = from_kqid(&init_user_ns, qid);
    226	return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq);
    227}
    228
    229/* Return quota info for active quota >= this qid */
    230STATIC int
    231xfs_fs_get_nextdqblk(
    232	struct super_block	*sb,
    233	struct kqid		*qid,
    234	struct qc_dqblk		*qdq)
    235{
    236	int			ret;
    237	struct xfs_mount	*mp = XFS_M(sb);
    238	xfs_dqid_t		id;
    239
    240	if (!XFS_IS_QUOTA_ON(mp))
    241		return -ENOSYS;
    242
    243	id = from_kqid(&init_user_ns, *qid);
    244	ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type),
    245			qdq);
    246	if (ret)
    247		return ret;
    248
    249	/* ID may be different, so convert back what we got */
    250	*qid = make_kqid(current_user_ns(), qid->type, id);
    251	return 0;
    252}
    253
    254STATIC int
    255xfs_fs_set_dqblk(
    256	struct super_block	*sb,
    257	struct kqid		qid,
    258	struct qc_dqblk		*qdq)
    259{
    260	struct xfs_mount	*mp = XFS_M(sb);
    261
    262	if (sb_rdonly(sb))
    263		return -EROFS;
    264	if (!XFS_IS_QUOTA_ON(mp))
    265		return -ENOSYS;
    266
    267	return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
    268				     xfs_quota_type(qid.type), qdq);
    269}
    270
    271const struct quotactl_ops xfs_quotactl_operations = {
    272	.get_state		= xfs_fs_get_quota_state,
    273	.set_info		= xfs_fs_set_info,
    274	.quota_enable		= xfs_quota_enable,
    275	.quota_disable		= xfs_quota_disable,
    276	.rm_xquota		= xfs_fs_rm_xquota,
    277	.get_dqblk		= xfs_fs_get_dqblk,
    278	.get_nextdqblk		= xfs_fs_get_nextdqblk,
    279	.set_dqblk		= xfs_fs_set_dqblk,
    280};