linux/fs/xfs/xfs_quotaops.c
<<
>>
Prefs
   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_d.di_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 = defq->blk.warn;
  44        tstate->ino_warnlimit = defq->ino.warn;
  45        tstate->rt_spc_warnlimit = defq->rtb.warn;
  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_RUNNING(mp))
  64                return 0;
  65        state->s_incoredqs = q->qi_dquots;
  66        if (XFS_IS_UQUOTA_RUNNING(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_RUNNING(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_RUNNING(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 | QC_WARNS_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_RUNNING(mp))
 118                return -ENOSYS;
 119        if (!XFS_IS_QUOTA_ON(mp))
 120                return -ESRCH;
 121        if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
 122                return -EINVAL;
 123        if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
 124                return 0;
 125
 126        newlim.d_fieldmask = info->i_fieldmask;
 127        newlim.d_spc_timer = info->i_spc_timelimit;
 128        newlim.d_ino_timer = info->i_ino_timelimit;
 129        newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
 130        newlim.d_ino_warns = info->i_ino_warnlimit;
 131        newlim.d_spc_warns = info->i_spc_warnlimit;
 132        newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
 133
 134        return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
 135}
 136
 137static unsigned int
 138xfs_quota_flags(unsigned int uflags)
 139{
 140        unsigned int flags = 0;
 141
 142        if (uflags & FS_QUOTA_UDQ_ACCT)
 143                flags |= XFS_UQUOTA_ACCT;
 144        if (uflags & FS_QUOTA_PDQ_ACCT)
 145                flags |= XFS_PQUOTA_ACCT;
 146        if (uflags & FS_QUOTA_GDQ_ACCT)
 147                flags |= XFS_GQUOTA_ACCT;
 148        if (uflags & FS_QUOTA_UDQ_ENFD)
 149                flags |= XFS_UQUOTA_ENFD;
 150        if (uflags & FS_QUOTA_GDQ_ENFD)
 151                flags |= XFS_GQUOTA_ENFD;
 152        if (uflags & FS_QUOTA_PDQ_ENFD)
 153                flags |= XFS_PQUOTA_ENFD;
 154
 155        return flags;
 156}
 157
 158STATIC int
 159xfs_quota_enable(
 160        struct super_block      *sb,
 161        unsigned int            uflags)
 162{
 163        struct xfs_mount        *mp = XFS_M(sb);
 164
 165        if (sb_rdonly(sb))
 166                return -EROFS;
 167        if (!XFS_IS_QUOTA_RUNNING(mp))
 168                return -ENOSYS;
 169
 170        return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
 171}
 172
 173STATIC int
 174xfs_quota_disable(
 175        struct super_block      *sb,
 176        unsigned int            uflags)
 177{
 178        struct xfs_mount        *mp = XFS_M(sb);
 179
 180        if (sb_rdonly(sb))
 181                return -EROFS;
 182        if (!XFS_IS_QUOTA_RUNNING(mp))
 183                return -ENOSYS;
 184        if (!XFS_IS_QUOTA_ON(mp))
 185                return -EINVAL;
 186
 187        return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
 188}
 189
 190STATIC int
 191xfs_fs_rm_xquota(
 192        struct super_block      *sb,
 193        unsigned int            uflags)
 194{
 195        struct xfs_mount        *mp = XFS_M(sb);
 196        unsigned int            flags = 0;
 197
 198        if (sb_rdonly(sb))
 199                return -EROFS;
 200
 201        if (XFS_IS_QUOTA_ON(mp))
 202                return -EINVAL;
 203
 204        if (uflags & ~(FS_USER_QUOTA | FS_GROUP_QUOTA | FS_PROJ_QUOTA))
 205                return -EINVAL;
 206
 207        if (uflags & FS_USER_QUOTA)
 208                flags |= XFS_QMOPT_UQUOTA;
 209        if (uflags & FS_GROUP_QUOTA)
 210                flags |= XFS_QMOPT_GQUOTA;
 211        if (uflags & FS_PROJ_QUOTA)
 212                flags |= XFS_QMOPT_PQUOTA;
 213
 214        return xfs_qm_scall_trunc_qfiles(mp, flags);
 215}
 216
 217STATIC int
 218xfs_fs_get_dqblk(
 219        struct super_block      *sb,
 220        struct kqid             qid,
 221        struct qc_dqblk         *qdq)
 222{
 223        struct xfs_mount        *mp = XFS_M(sb);
 224        xfs_dqid_t              id;
 225
 226        if (!XFS_IS_QUOTA_RUNNING(mp))
 227                return -ENOSYS;
 228        if (!XFS_IS_QUOTA_ON(mp))
 229                return -ESRCH;
 230
 231        id = from_kqid(&init_user_ns, qid);
 232        return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq);
 233}
 234
 235/* Return quota info for active quota >= this qid */
 236STATIC int
 237xfs_fs_get_nextdqblk(
 238        struct super_block      *sb,
 239        struct kqid             *qid,
 240        struct qc_dqblk         *qdq)
 241{
 242        int                     ret;
 243        struct xfs_mount        *mp = XFS_M(sb);
 244        xfs_dqid_t              id;
 245
 246        if (!XFS_IS_QUOTA_RUNNING(mp))
 247                return -ENOSYS;
 248        if (!XFS_IS_QUOTA_ON(mp))
 249                return -ESRCH;
 250
 251        id = from_kqid(&init_user_ns, *qid);
 252        ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type),
 253                        qdq);
 254        if (ret)
 255                return ret;
 256
 257        /* ID may be different, so convert back what we got */
 258        *qid = make_kqid(current_user_ns(), qid->type, id);
 259        return 0;
 260}
 261
 262STATIC int
 263xfs_fs_set_dqblk(
 264        struct super_block      *sb,
 265        struct kqid             qid,
 266        struct qc_dqblk         *qdq)
 267{
 268        struct xfs_mount        *mp = XFS_M(sb);
 269
 270        if (sb_rdonly(sb))
 271                return -EROFS;
 272        if (!XFS_IS_QUOTA_RUNNING(mp))
 273                return -ENOSYS;
 274        if (!XFS_IS_QUOTA_ON(mp))
 275                return -ESRCH;
 276
 277        return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
 278                                     xfs_quota_type(qid.type), qdq);
 279}
 280
 281const struct quotactl_ops xfs_quotactl_operations = {
 282        .get_state              = xfs_fs_get_quota_state,
 283        .set_info               = xfs_fs_set_info,
 284        .quota_enable           = xfs_quota_enable,
 285        .quota_disable          = xfs_quota_disable,
 286        .rm_xquota              = xfs_fs_rm_xquota,
 287        .get_dqblk              = xfs_fs_get_dqblk,
 288        .get_nextdqblk          = xfs_fs_get_nextdqblk,
 289        .set_dqblk              = xfs_fs_set_dqblk,
 290};
 291