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