linux/fs/xfs/xfs_qm_syscalls.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   4 * All Rights Reserved.
   5 */
   6
   7
   8#include "xfs.h"
   9#include "xfs_fs.h"
  10#include "xfs_shared.h"
  11#include "xfs_format.h"
  12#include "xfs_log_format.h"
  13#include "xfs_trans_resv.h"
  14#include "xfs_sb.h"
  15#include "xfs_mount.h"
  16#include "xfs_inode.h"
  17#include "xfs_trans.h"
  18#include "xfs_quota.h"
  19#include "xfs_qm.h"
  20#include "xfs_icache.h"
  21
  22int
  23xfs_qm_scall_quotaoff(
  24        xfs_mount_t             *mp,
  25        uint                    flags)
  26{
  27        /*
  28         * No file system can have quotas enabled on disk but not in core.
  29         * Note that quota utilities (like quotaoff) _expect_
  30         * errno == -EEXIST here.
  31         */
  32        if ((mp->m_qflags & flags) == 0)
  33                return -EEXIST;
  34
  35        /*
  36         * We do not support actually turning off quota accounting any more.
  37         * Just log a warning and ignore the accounting related flags.
  38         */
  39        if (flags & XFS_ALL_QUOTA_ACCT)
  40                xfs_info(mp, "disabling of quota accounting not supported.");
  41
  42        mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
  43        mp->m_qflags &= ~(flags & XFS_ALL_QUOTA_ENFD);
  44        spin_lock(&mp->m_sb_lock);
  45        mp->m_sb.sb_qflags = mp->m_qflags;
  46        spin_unlock(&mp->m_sb_lock);
  47        mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
  48
  49        /* XXX what to do if error ? Revert back to old vals incore ? */
  50        return xfs_sync_sb(mp, false);
  51}
  52
  53STATIC int
  54xfs_qm_scall_trunc_qfile(
  55        struct xfs_mount        *mp,
  56        xfs_ino_t               ino)
  57{
  58        struct xfs_inode        *ip;
  59        struct xfs_trans        *tp;
  60        int                     error;
  61
  62        if (ino == NULLFSINO)
  63                return 0;
  64
  65        error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
  66        if (error)
  67                return error;
  68
  69        xfs_ilock(ip, XFS_IOLOCK_EXCL);
  70
  71        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
  72        if (error) {
  73                xfs_iunlock(ip, XFS_IOLOCK_EXCL);
  74                goto out_put;
  75        }
  76
  77        xfs_ilock(ip, XFS_ILOCK_EXCL);
  78        xfs_trans_ijoin(tp, ip, 0);
  79
  80        ip->i_disk_size = 0;
  81        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
  82
  83        error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
  84        if (error) {
  85                xfs_trans_cancel(tp);
  86                goto out_unlock;
  87        }
  88
  89        ASSERT(ip->i_df.if_nextents == 0);
  90
  91        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
  92        error = xfs_trans_commit(tp);
  93
  94out_unlock:
  95        xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
  96out_put:
  97        xfs_irele(ip);
  98        return error;
  99}
 100
 101int
 102xfs_qm_scall_trunc_qfiles(
 103        xfs_mount_t     *mp,
 104        uint            flags)
 105{
 106        int             error = -EINVAL;
 107
 108        if (!xfs_has_quota(mp) || flags == 0 ||
 109            (flags & ~XFS_QMOPT_QUOTALL)) {
 110                xfs_debug(mp, "%s: flags=%x m_qflags=%x",
 111                        __func__, flags, mp->m_qflags);
 112                return -EINVAL;
 113        }
 114
 115        if (flags & XFS_QMOPT_UQUOTA) {
 116                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
 117                if (error)
 118                        return error;
 119        }
 120        if (flags & XFS_QMOPT_GQUOTA) {
 121                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
 122                if (error)
 123                        return error;
 124        }
 125        if (flags & XFS_QMOPT_PQUOTA)
 126                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
 127
 128        return error;
 129}
 130
 131/*
 132 * Switch on (a given) quota enforcement for a filesystem.  This takes
 133 * effect immediately.
 134 * (Switching on quota accounting must be done at mount time.)
 135 */
 136int
 137xfs_qm_scall_quotaon(
 138        xfs_mount_t     *mp,
 139        uint            flags)
 140{
 141        int             error;
 142        uint            qf;
 143
 144        /*
 145         * Switching on quota accounting must be done at mount time,
 146         * only consider quota enforcement stuff here.
 147         */
 148        flags &= XFS_ALL_QUOTA_ENFD;
 149
 150        if (flags == 0) {
 151                xfs_debug(mp, "%s: zero flags, m_qflags=%x",
 152                        __func__, mp->m_qflags);
 153                return -EINVAL;
 154        }
 155
 156        /*
 157         * Can't enforce without accounting. We check the superblock
 158         * qflags here instead of m_qflags because rootfs can have
 159         * quota acct on ondisk without m_qflags' knowing.
 160         */
 161        if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
 162             (flags & XFS_UQUOTA_ENFD)) ||
 163            ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
 164             (flags & XFS_GQUOTA_ENFD)) ||
 165            ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
 166             (flags & XFS_PQUOTA_ENFD))) {
 167                xfs_debug(mp,
 168                        "%s: Can't enforce without acct, flags=%x sbflags=%x",
 169                        __func__, flags, mp->m_sb.sb_qflags);
 170                return -EINVAL;
 171        }
 172        /*
 173         * If everything's up to-date incore, then don't waste time.
 174         */
 175        if ((mp->m_qflags & flags) == flags)
 176                return -EEXIST;
 177
 178        /*
 179         * Change sb_qflags on disk but not incore mp->qflags
 180         * if this is the root filesystem.
 181         */
 182        spin_lock(&mp->m_sb_lock);
 183        qf = mp->m_sb.sb_qflags;
 184        mp->m_sb.sb_qflags = qf | flags;
 185        spin_unlock(&mp->m_sb_lock);
 186
 187        /*
 188         * There's nothing to change if it's the same.
 189         */
 190        if ((qf & flags) == flags)
 191                return -EEXIST;
 192
 193        error = xfs_sync_sb(mp, false);
 194        if (error)
 195                return error;
 196        /*
 197         * If we aren't trying to switch on quota enforcement, we are done.
 198         */
 199        if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
 200             (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
 201             ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
 202             (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
 203             ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
 204             (mp->m_qflags & XFS_GQUOTA_ACCT)))
 205                return 0;
 206
 207        if (!XFS_IS_QUOTA_ON(mp))
 208                return -ESRCH;
 209
 210        /*
 211         * Switch on quota enforcement in core.
 212         */
 213        mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
 214        mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
 215        mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
 216
 217        return 0;
 218}
 219
 220#define XFS_QC_MASK \
 221        (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
 222
 223/*
 224 * Adjust limits of this quota, and the defaults if passed in.  Returns true
 225 * if the new limits made sense and were applied, false otherwise.
 226 */
 227static inline bool
 228xfs_setqlim_limits(
 229        struct xfs_mount        *mp,
 230        struct xfs_dquot_res    *res,
 231        struct xfs_quota_limits *qlim,
 232        xfs_qcnt_t              hard,
 233        xfs_qcnt_t              soft,
 234        const char              *tag)
 235{
 236        /* The hard limit can't be less than the soft limit. */
 237        if (hard != 0 && hard < soft) {
 238                xfs_debug(mp, "%shard %lld < %ssoft %lld", tag, hard, tag,
 239                                soft);
 240                return false;
 241        }
 242
 243        res->hardlimit = hard;
 244        res->softlimit = soft;
 245        if (qlim) {
 246                qlim->hard = hard;
 247                qlim->soft = soft;
 248        }
 249
 250        return true;
 251}
 252
 253static inline void
 254xfs_setqlim_warns(
 255        struct xfs_dquot_res    *res,
 256        struct xfs_quota_limits *qlim,
 257        int                     warns)
 258{
 259        res->warnings = warns;
 260        if (qlim)
 261                qlim->warn = warns;
 262}
 263
 264static inline void
 265xfs_setqlim_timer(
 266        struct xfs_mount        *mp,
 267        struct xfs_dquot_res    *res,
 268        struct xfs_quota_limits *qlim,
 269        s64                     timer)
 270{
 271        if (qlim) {
 272                /* Set the length of the default grace period. */
 273                res->timer = xfs_dquot_set_grace_period(timer);
 274                qlim->time = res->timer;
 275        } else {
 276                /* Set the grace period expiration on a quota. */
 277                res->timer = xfs_dquot_set_timeout(mp, timer);
 278        }
 279}
 280
 281/*
 282 * Adjust quota limits, and start/stop timers accordingly.
 283 */
 284int
 285xfs_qm_scall_setqlim(
 286        struct xfs_mount        *mp,
 287        xfs_dqid_t              id,
 288        xfs_dqtype_t            type,
 289        struct qc_dqblk         *newlim)
 290{
 291        struct xfs_quotainfo    *q = mp->m_quotainfo;
 292        struct xfs_dquot        *dqp;
 293        struct xfs_trans        *tp;
 294        struct xfs_def_quota    *defq;
 295        struct xfs_dquot_res    *res;
 296        struct xfs_quota_limits *qlim;
 297        int                     error;
 298        xfs_qcnt_t              hard, soft;
 299
 300        if (newlim->d_fieldmask & ~XFS_QC_MASK)
 301                return -EINVAL;
 302        if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
 303                return 0;
 304
 305        /*
 306         * We don't want to race with a quotaoff so take the quotaoff lock.
 307         * We don't hold an inode lock, so there's nothing else to stop
 308         * a quotaoff from happening.
 309         */
 310        mutex_lock(&q->qi_quotaofflock);
 311
 312        /*
 313         * Get the dquot (locked) before we start, as we need to do a
 314         * transaction to allocate it if it doesn't exist. Once we have the
 315         * dquot, unlock it so we can start the next transaction safely. We hold
 316         * a reference to the dquot, so it's safe to do this unlock/lock without
 317         * it being reclaimed in the mean time.
 318         */
 319        error = xfs_qm_dqget(mp, id, type, true, &dqp);
 320        if (error) {
 321                ASSERT(error != -ENOENT);
 322                goto out_unlock;
 323        }
 324
 325        defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
 326        xfs_dqunlock(dqp);
 327
 328        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
 329        if (error)
 330                goto out_rele;
 331
 332        xfs_dqlock(dqp);
 333        xfs_trans_dqjoin(tp, dqp);
 334
 335        /*
 336         * Update quota limits, warnings, and timers, and the defaults
 337         * if we're touching id == 0.
 338         *
 339         * Make sure that hardlimits are >= soft limits before changing.
 340         *
 341         * Update warnings counter(s) if requested.
 342         *
 343         * Timelimits for the super user set the relative time the other users
 344         * can be over quota for this file system. If it is zero a default is
 345         * used.  Ditto for the default soft and hard limit values (already
 346         * done, above), and for warnings.
 347         *
 348         * For other IDs, userspace can bump out the grace period if over
 349         * the soft limit.
 350         */
 351
 352        /* Blocks on the data device. */
 353        hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
 354                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
 355                        dqp->q_blk.hardlimit;
 356        soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
 357                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
 358                        dqp->q_blk.softlimit;
 359        res = &dqp->q_blk;
 360        qlim = id == 0 ? &defq->blk : NULL;
 361
 362        if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
 363                xfs_dquot_set_prealloc_limits(dqp);
 364        if (newlim->d_fieldmask & QC_SPC_WARNS)
 365                xfs_setqlim_warns(res, qlim, newlim->d_spc_warns);
 366        if (newlim->d_fieldmask & QC_SPC_TIMER)
 367                xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
 368
 369        /* Blocks on the realtime device. */
 370        hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
 371                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
 372                        dqp->q_rtb.hardlimit;
 373        soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
 374                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
 375                        dqp->q_rtb.softlimit;
 376        res = &dqp->q_rtb;
 377        qlim = id == 0 ? &defq->rtb : NULL;
 378
 379        xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
 380        if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
 381                xfs_setqlim_warns(res, qlim, newlim->d_rt_spc_warns);
 382        if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
 383                xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
 384
 385        /* Inodes */
 386        hard = (newlim->d_fieldmask & QC_INO_HARD) ?
 387                (xfs_qcnt_t) newlim->d_ino_hardlimit :
 388                        dqp->q_ino.hardlimit;
 389        soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
 390                (xfs_qcnt_t) newlim->d_ino_softlimit :
 391                        dqp->q_ino.softlimit;
 392        res = &dqp->q_ino;
 393        qlim = id == 0 ? &defq->ino : NULL;
 394
 395        xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
 396        if (newlim->d_fieldmask & QC_INO_WARNS)
 397                xfs_setqlim_warns(res, qlim, newlim->d_ino_warns);
 398        if (newlim->d_fieldmask & QC_INO_TIMER)
 399                xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
 400
 401        if (id != 0) {
 402                /*
 403                 * If the user is now over quota, start the timelimit.
 404                 * The user will not be 'warned'.
 405                 * Note that we keep the timers ticking, whether enforcement
 406                 * is on or off. We don't really want to bother with iterating
 407                 * over all ondisk dquots and turning the timers on/off.
 408                 */
 409                xfs_qm_adjust_dqtimers(dqp);
 410        }
 411        dqp->q_flags |= XFS_DQFLAG_DIRTY;
 412        xfs_trans_log_dquot(tp, dqp);
 413
 414        error = xfs_trans_commit(tp);
 415
 416out_rele:
 417        xfs_qm_dqrele(dqp);
 418out_unlock:
 419        mutex_unlock(&q->qi_quotaofflock);
 420        return error;
 421}
 422
 423/* Fill out the quota context. */
 424static void
 425xfs_qm_scall_getquota_fill_qc(
 426        struct xfs_mount        *mp,
 427        xfs_dqtype_t            type,
 428        const struct xfs_dquot  *dqp,
 429        struct qc_dqblk         *dst)
 430{
 431        memset(dst, 0, sizeof(*dst));
 432        dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
 433        dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
 434        dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
 435        dst->d_ino_softlimit = dqp->q_ino.softlimit;
 436        dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
 437        dst->d_ino_count = dqp->q_ino.reserved;
 438        dst->d_spc_timer = dqp->q_blk.timer;
 439        dst->d_ino_timer = dqp->q_ino.timer;
 440        dst->d_ino_warns = dqp->q_ino.warnings;
 441        dst->d_spc_warns = dqp->q_blk.warnings;
 442        dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
 443        dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
 444        dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
 445        dst->d_rt_spc_timer = dqp->q_rtb.timer;
 446        dst->d_rt_spc_warns = dqp->q_rtb.warnings;
 447
 448        /*
 449         * Internally, we don't reset all the timers when quota enforcement
 450         * gets turned off. No need to confuse the user level code,
 451         * so return zeroes in that case.
 452         */
 453        if (!xfs_dquot_is_enforced(dqp)) {
 454                dst->d_spc_timer = 0;
 455                dst->d_ino_timer = 0;
 456                dst->d_rt_spc_timer = 0;
 457        }
 458
 459#ifdef DEBUG
 460        if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
 461                if ((dst->d_space > dst->d_spc_softlimit) &&
 462                    (dst->d_spc_softlimit > 0)) {
 463                        ASSERT(dst->d_spc_timer != 0);
 464                }
 465                if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
 466                    (dqp->q_ino.softlimit > 0)) {
 467                        ASSERT(dst->d_ino_timer != 0);
 468                }
 469        }
 470#endif
 471}
 472
 473/* Return the quota information for the dquot matching id. */
 474int
 475xfs_qm_scall_getquota(
 476        struct xfs_mount        *mp,
 477        xfs_dqid_t              id,
 478        xfs_dqtype_t            type,
 479        struct qc_dqblk         *dst)
 480{
 481        struct xfs_dquot        *dqp;
 482        int                     error;
 483
 484        /* Flush inodegc work at the start of a quota reporting scan. */
 485        if (id == 0)
 486                xfs_inodegc_flush(mp);
 487
 488        /*
 489         * Try to get the dquot. We don't want it allocated on disk, so don't
 490         * set doalloc. If it doesn't exist, we'll get ENOENT back.
 491         */
 492        error = xfs_qm_dqget(mp, id, type, false, &dqp);
 493        if (error)
 494                return error;
 495
 496        /*
 497         * If everything's NULL, this dquot doesn't quite exist as far as
 498         * our utility programs are concerned.
 499         */
 500        if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
 501                error = -ENOENT;
 502                goto out_put;
 503        }
 504
 505        xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
 506
 507out_put:
 508        xfs_qm_dqput(dqp);
 509        return error;
 510}
 511
 512/*
 513 * Return the quota information for the first initialized dquot whose id
 514 * is at least as high as id.
 515 */
 516int
 517xfs_qm_scall_getquota_next(
 518        struct xfs_mount        *mp,
 519        xfs_dqid_t              *id,
 520        xfs_dqtype_t            type,
 521        struct qc_dqblk         *dst)
 522{
 523        struct xfs_dquot        *dqp;
 524        int                     error;
 525
 526        /* Flush inodegc work at the start of a quota reporting scan. */
 527        if (*id == 0)
 528                xfs_inodegc_flush(mp);
 529
 530        error = xfs_qm_dqget_next(mp, *id, type, &dqp);
 531        if (error)
 532                return error;
 533
 534        /* Fill in the ID we actually read from disk */
 535        *id = dqp->q_id;
 536
 537        xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
 538
 539        xfs_qm_dqput(dqp);
 540        return error;
 541}
 542