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
  22STATIC int
  23xfs_qm_log_quotaoff(
  24        struct xfs_mount        *mp,
  25        struct xfs_qoff_logitem **qoffstartp,
  26        uint                    flags)
  27{
  28        struct xfs_trans        *tp;
  29        int                     error;
  30        struct xfs_qoff_logitem *qoffi;
  31
  32        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_quotaoff, 0, 0, 0, &tp);
  33        if (error)
  34                goto out;
  35
  36        qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
  37        xfs_trans_log_quotaoff_item(tp, qoffi);
  38
  39        spin_lock(&mp->m_sb_lock);
  40        mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
  41        spin_unlock(&mp->m_sb_lock);
  42
  43        xfs_log_sb(tp);
  44
  45        /*
  46         * We have to make sure that the transaction is secure on disk before we
  47         * return and actually stop quota accounting. So, make it synchronous.
  48         * We don't care about quotoff's performance.
  49         */
  50        xfs_trans_set_sync(tp);
  51        error = xfs_trans_commit(tp);
  52        if (error)
  53                goto out;
  54
  55        *qoffstartp = qoffi;
  56out:
  57        return error;
  58}
  59
  60STATIC int
  61xfs_qm_log_quotaoff_end(
  62        struct xfs_mount        *mp,
  63        struct xfs_qoff_logitem **startqoff,
  64        uint                    flags)
  65{
  66        struct xfs_trans        *tp;
  67        int                     error;
  68        struct xfs_qoff_logitem *qoffi;
  69
  70        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_equotaoff, 0, 0, 0, &tp);
  71        if (error)
  72                return error;
  73
  74        qoffi = xfs_trans_get_qoff_item(tp, *startqoff,
  75                                        flags & XFS_ALL_QUOTA_ACCT);
  76        xfs_trans_log_quotaoff_item(tp, qoffi);
  77        *startqoff = NULL;
  78
  79        /*
  80         * We have to make sure that the transaction is secure on disk before we
  81         * return and actually stop quota accounting. So, make it synchronous.
  82         * We don't care about quotoff's performance.
  83         */
  84        xfs_trans_set_sync(tp);
  85        return xfs_trans_commit(tp);
  86}
  87
  88/*
  89 * Turn off quota accounting and/or enforcement for all udquots and/or
  90 * gdquots. Called only at unmount time.
  91 *
  92 * This assumes that there are no dquots of this file system cached
  93 * incore, and modifies the ondisk dquot directly. Therefore, for example,
  94 * it is an error to call this twice, without purging the cache.
  95 */
  96int
  97xfs_qm_scall_quotaoff(
  98        xfs_mount_t             *mp,
  99        uint                    flags)
 100{
 101        struct xfs_quotainfo    *q = mp->m_quotainfo;
 102        uint                    dqtype;
 103        int                     error;
 104        uint                    inactivate_flags;
 105        struct xfs_qoff_logitem *qoffstart = NULL;
 106
 107        /*
 108         * No file system can have quotas enabled on disk but not in core.
 109         * Note that quota utilities (like quotaoff) _expect_
 110         * errno == -EEXIST here.
 111         */
 112        if ((mp->m_qflags & flags) == 0)
 113                return -EEXIST;
 114        error = 0;
 115
 116        flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
 117
 118        /*
 119         * We don't want to deal with two quotaoffs messing up each other,
 120         * so we're going to serialize it. quotaoff isn't exactly a performance
 121         * critical thing.
 122         * If quotaoff, then we must be dealing with the root filesystem.
 123         */
 124        ASSERT(q);
 125        mutex_lock(&q->qi_quotaofflock);
 126
 127        /*
 128         * If we're just turning off quota enforcement, change mp and go.
 129         */
 130        if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
 131                mp->m_qflags &= ~(flags);
 132
 133                spin_lock(&mp->m_sb_lock);
 134                mp->m_sb.sb_qflags = mp->m_qflags;
 135                spin_unlock(&mp->m_sb_lock);
 136                mutex_unlock(&q->qi_quotaofflock);
 137
 138                /* XXX what to do if error ? Revert back to old vals incore ? */
 139                return xfs_sync_sb(mp, false);
 140        }
 141
 142        dqtype = 0;
 143        inactivate_flags = 0;
 144        /*
 145         * If accounting is off, we must turn enforcement off, clear the
 146         * quota 'CHKD' certificate to make it known that we have to
 147         * do a quotacheck the next time this quota is turned on.
 148         */
 149        if (flags & XFS_UQUOTA_ACCT) {
 150                dqtype |= XFS_QMOPT_UQUOTA;
 151                flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
 152                inactivate_flags |= XFS_UQUOTA_ACTIVE;
 153        }
 154        if (flags & XFS_GQUOTA_ACCT) {
 155                dqtype |= XFS_QMOPT_GQUOTA;
 156                flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
 157                inactivate_flags |= XFS_GQUOTA_ACTIVE;
 158        }
 159        if (flags & XFS_PQUOTA_ACCT) {
 160                dqtype |= XFS_QMOPT_PQUOTA;
 161                flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
 162                inactivate_flags |= XFS_PQUOTA_ACTIVE;
 163        }
 164
 165        /*
 166         * Nothing to do?  Don't complain. This happens when we're just
 167         * turning off quota enforcement.
 168         */
 169        if ((mp->m_qflags & flags) == 0)
 170                goto out_unlock;
 171
 172        /*
 173         * Write the LI_QUOTAOFF log record, and do SB changes atomically,
 174         * and synchronously. If we fail to write, we should abort the
 175         * operation as it cannot be recovered safely if we crash.
 176         */
 177        error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
 178        if (error)
 179                goto out_unlock;
 180
 181        /*
 182         * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
 183         * to take care of the race between dqget and quotaoff. We don't take
 184         * any special locks to reset these bits. All processes need to check
 185         * these bits *after* taking inode lock(s) to see if the particular
 186         * quota type is in the process of being turned off. If *ACTIVE, it is
 187         * guaranteed that all dquot structures and all quotainode ptrs will all
 188         * stay valid as long as that inode is kept locked.
 189         *
 190         * There is no turning back after this.
 191         */
 192        mp->m_qflags &= ~inactivate_flags;
 193
 194        /*
 195         * Give back all the dquot reference(s) held by inodes.
 196         * Here we go thru every single incore inode in this file system, and
 197         * do a dqrele on the i_udquot/i_gdquot that it may have.
 198         * Essentially, as long as somebody has an inode locked, this guarantees
 199         * that quotas will not be turned off. This is handy because in a
 200         * transaction once we lock the inode(s) and check for quotaon, we can
 201         * depend on the quota inodes (and other things) being valid as long as
 202         * we keep the lock(s).
 203         */
 204        xfs_qm_dqrele_all_inodes(mp, flags);
 205
 206        /*
 207         * Next we make the changes in the quota flag in the mount struct.
 208         * This isn't protected by a particular lock directly, because we
 209         * don't want to take a mrlock every time we depend on quotas being on.
 210         */
 211        mp->m_qflags &= ~flags;
 212
 213        /*
 214         * Go through all the dquots of this file system and purge them,
 215         * according to what was turned off.
 216         */
 217        xfs_qm_dqpurge_all(mp, dqtype);
 218
 219        /*
 220         * Transactions that had started before ACTIVE state bit was cleared
 221         * could have logged many dquots, so they'd have higher LSNs than
 222         * the first QUOTAOFF log record does. If we happen to crash when
 223         * the tail of the log has gone past the QUOTAOFF record, but
 224         * before the last dquot modification, those dquots __will__
 225         * recover, and that's not good.
 226         *
 227         * So, we have QUOTAOFF start and end logitems; the start
 228         * logitem won't get overwritten until the end logitem appears...
 229         */
 230        error = xfs_qm_log_quotaoff_end(mp, &qoffstart, flags);
 231        if (error) {
 232                /* We're screwed now. Shutdown is the only option. */
 233                xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 234                goto out_unlock;
 235        }
 236
 237        /*
 238         * If all quotas are completely turned off, close shop.
 239         */
 240        if (mp->m_qflags == 0) {
 241                mutex_unlock(&q->qi_quotaofflock);
 242                xfs_qm_destroy_quotainfo(mp);
 243                return 0;
 244        }
 245
 246        /*
 247         * Release our quotainode references if we don't need them anymore.
 248         */
 249        if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
 250                xfs_irele(q->qi_uquotaip);
 251                q->qi_uquotaip = NULL;
 252        }
 253        if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
 254                xfs_irele(q->qi_gquotaip);
 255                q->qi_gquotaip = NULL;
 256        }
 257        if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
 258                xfs_irele(q->qi_pquotaip);
 259                q->qi_pquotaip = NULL;
 260        }
 261
 262out_unlock:
 263        if (error && qoffstart)
 264                xfs_qm_qoff_logitem_relse(qoffstart);
 265        mutex_unlock(&q->qi_quotaofflock);
 266        return error;
 267}
 268
 269STATIC int
 270xfs_qm_scall_trunc_qfile(
 271        struct xfs_mount        *mp,
 272        xfs_ino_t               ino)
 273{
 274        struct xfs_inode        *ip;
 275        struct xfs_trans        *tp;
 276        int                     error;
 277
 278        if (ino == NULLFSINO)
 279                return 0;
 280
 281        error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
 282        if (error)
 283                return error;
 284
 285        xfs_ilock(ip, XFS_IOLOCK_EXCL);
 286
 287        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
 288        if (error) {
 289                xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 290                goto out_put;
 291        }
 292
 293        xfs_ilock(ip, XFS_ILOCK_EXCL);
 294        xfs_trans_ijoin(tp, ip, 0);
 295
 296        ip->i_d.di_size = 0;
 297        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 298
 299        error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
 300        if (error) {
 301                xfs_trans_cancel(tp);
 302                goto out_unlock;
 303        }
 304
 305        ASSERT(ip->i_df.if_nextents == 0);
 306
 307        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 308        error = xfs_trans_commit(tp);
 309
 310out_unlock:
 311        xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 312out_put:
 313        xfs_irele(ip);
 314        return error;
 315}
 316
 317int
 318xfs_qm_scall_trunc_qfiles(
 319        xfs_mount_t     *mp,
 320        uint            flags)
 321{
 322        int             error = -EINVAL;
 323
 324        if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0 ||
 325            (flags & ~XFS_QMOPT_QUOTALL)) {
 326                xfs_debug(mp, "%s: flags=%x m_qflags=%x",
 327                        __func__, flags, mp->m_qflags);
 328                return -EINVAL;
 329        }
 330
 331        if (flags & XFS_QMOPT_UQUOTA) {
 332                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
 333                if (error)
 334                        return error;
 335        }
 336        if (flags & XFS_QMOPT_GQUOTA) {
 337                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
 338                if (error)
 339                        return error;
 340        }
 341        if (flags & XFS_QMOPT_PQUOTA)
 342                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
 343
 344        return error;
 345}
 346
 347/*
 348 * Switch on (a given) quota enforcement for a filesystem.  This takes
 349 * effect immediately.
 350 * (Switching on quota accounting must be done at mount time.)
 351 */
 352int
 353xfs_qm_scall_quotaon(
 354        xfs_mount_t     *mp,
 355        uint            flags)
 356{
 357        int             error;
 358        uint            qf;
 359
 360        /*
 361         * Switching on quota accounting must be done at mount time,
 362         * only consider quota enforcement stuff here.
 363         */
 364        flags &= XFS_ALL_QUOTA_ENFD;
 365
 366        if (flags == 0) {
 367                xfs_debug(mp, "%s: zero flags, m_qflags=%x",
 368                        __func__, mp->m_qflags);
 369                return -EINVAL;
 370        }
 371
 372        /*
 373         * Can't enforce without accounting. We check the superblock
 374         * qflags here instead of m_qflags because rootfs can have
 375         * quota acct on ondisk without m_qflags' knowing.
 376         */
 377        if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
 378             (flags & XFS_UQUOTA_ENFD)) ||
 379            ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
 380             (flags & XFS_GQUOTA_ENFD)) ||
 381            ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
 382             (flags & XFS_PQUOTA_ENFD))) {
 383                xfs_debug(mp,
 384                        "%s: Can't enforce without acct, flags=%x sbflags=%x",
 385                        __func__, flags, mp->m_sb.sb_qflags);
 386                return -EINVAL;
 387        }
 388        /*
 389         * If everything's up to-date incore, then don't waste time.
 390         */
 391        if ((mp->m_qflags & flags) == flags)
 392                return -EEXIST;
 393
 394        /*
 395         * Change sb_qflags on disk but not incore mp->qflags
 396         * if this is the root filesystem.
 397         */
 398        spin_lock(&mp->m_sb_lock);
 399        qf = mp->m_sb.sb_qflags;
 400        mp->m_sb.sb_qflags = qf | flags;
 401        spin_unlock(&mp->m_sb_lock);
 402
 403        /*
 404         * There's nothing to change if it's the same.
 405         */
 406        if ((qf & flags) == flags)
 407                return -EEXIST;
 408
 409        error = xfs_sync_sb(mp, false);
 410        if (error)
 411                return error;
 412        /*
 413         * If we aren't trying to switch on quota enforcement, we are done.
 414         */
 415        if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
 416             (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
 417             ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
 418             (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
 419             ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
 420             (mp->m_qflags & XFS_GQUOTA_ACCT)))
 421                return 0;
 422
 423        if (! XFS_IS_QUOTA_RUNNING(mp))
 424                return -ESRCH;
 425
 426        /*
 427         * Switch on quota enforcement in core.
 428         */
 429        mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
 430        mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
 431        mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
 432
 433        return 0;
 434}
 435
 436#define XFS_QC_MASK \
 437        (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
 438
 439/*
 440 * Adjust limits of this quota, and the defaults if passed in.  Returns true
 441 * if the new limits made sense and were applied, false otherwise.
 442 */
 443static inline bool
 444xfs_setqlim_limits(
 445        struct xfs_mount        *mp,
 446        struct xfs_dquot_res    *res,
 447        struct xfs_quota_limits *qlim,
 448        xfs_qcnt_t              hard,
 449        xfs_qcnt_t              soft,
 450        const char              *tag)
 451{
 452        /* The hard limit can't be less than the soft limit. */
 453        if (hard != 0 && hard < soft) {
 454                xfs_debug(mp, "%shard %lld < %ssoft %lld", tag, hard, tag,
 455                                soft);
 456                return false;
 457        }
 458
 459        res->hardlimit = hard;
 460        res->softlimit = soft;
 461        if (qlim) {
 462                qlim->hard = hard;
 463                qlim->soft = soft;
 464        }
 465
 466        return true;
 467}
 468
 469static inline void
 470xfs_setqlim_warns(
 471        struct xfs_dquot_res    *res,
 472        struct xfs_quota_limits *qlim,
 473        int                     warns)
 474{
 475        res->warnings = warns;
 476        if (qlim)
 477                qlim->warn = warns;
 478}
 479
 480static inline void
 481xfs_setqlim_timer(
 482        struct xfs_mount        *mp,
 483        struct xfs_dquot_res    *res,
 484        struct xfs_quota_limits *qlim,
 485        s64                     timer)
 486{
 487        if (qlim) {
 488                /* Set the length of the default grace period. */
 489                res->timer = xfs_dquot_set_grace_period(timer);
 490                qlim->time = res->timer;
 491        } else {
 492                /* Set the grace period expiration on a quota. */
 493                res->timer = xfs_dquot_set_timeout(mp, timer);
 494        }
 495}
 496
 497/*
 498 * Adjust quota limits, and start/stop timers accordingly.
 499 */
 500int
 501xfs_qm_scall_setqlim(
 502        struct xfs_mount        *mp,
 503        xfs_dqid_t              id,
 504        xfs_dqtype_t            type,
 505        struct qc_dqblk         *newlim)
 506{
 507        struct xfs_quotainfo    *q = mp->m_quotainfo;
 508        struct xfs_dquot        *dqp;
 509        struct xfs_trans        *tp;
 510        struct xfs_def_quota    *defq;
 511        struct xfs_dquot_res    *res;
 512        struct xfs_quota_limits *qlim;
 513        int                     error;
 514        xfs_qcnt_t              hard, soft;
 515
 516        if (newlim->d_fieldmask & ~XFS_QC_MASK)
 517                return -EINVAL;
 518        if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
 519                return 0;
 520
 521        /*
 522         * We don't want to race with a quotaoff so take the quotaoff lock.
 523         * We don't hold an inode lock, so there's nothing else to stop
 524         * a quotaoff from happening.
 525         */
 526        mutex_lock(&q->qi_quotaofflock);
 527
 528        /*
 529         * Get the dquot (locked) before we start, as we need to do a
 530         * transaction to allocate it if it doesn't exist. Once we have the
 531         * dquot, unlock it so we can start the next transaction safely. We hold
 532         * a reference to the dquot, so it's safe to do this unlock/lock without
 533         * it being reclaimed in the mean time.
 534         */
 535        error = xfs_qm_dqget(mp, id, type, true, &dqp);
 536        if (error) {
 537                ASSERT(error != -ENOENT);
 538                goto out_unlock;
 539        }
 540
 541        defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
 542        xfs_dqunlock(dqp);
 543
 544        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
 545        if (error)
 546                goto out_rele;
 547
 548        xfs_dqlock(dqp);
 549        xfs_trans_dqjoin(tp, dqp);
 550
 551        /*
 552         * Update quota limits, warnings, and timers, and the defaults
 553         * if we're touching id == 0.
 554         *
 555         * Make sure that hardlimits are >= soft limits before changing.
 556         *
 557         * Update warnings counter(s) if requested.
 558         *
 559         * Timelimits for the super user set the relative time the other users
 560         * can be over quota for this file system. If it is zero a default is
 561         * used.  Ditto for the default soft and hard limit values (already
 562         * done, above), and for warnings.
 563         *
 564         * For other IDs, userspace can bump out the grace period if over
 565         * the soft limit.
 566         */
 567
 568        /* Blocks on the data device. */
 569        hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
 570                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
 571                        dqp->q_blk.hardlimit;
 572        soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
 573                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
 574                        dqp->q_blk.softlimit;
 575        res = &dqp->q_blk;
 576        qlim = id == 0 ? &defq->blk : NULL;
 577
 578        if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
 579                xfs_dquot_set_prealloc_limits(dqp);
 580        if (newlim->d_fieldmask & QC_SPC_WARNS)
 581                xfs_setqlim_warns(res, qlim, newlim->d_spc_warns);
 582        if (newlim->d_fieldmask & QC_SPC_TIMER)
 583                xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
 584
 585        /* Blocks on the realtime device. */
 586        hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
 587                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
 588                        dqp->q_rtb.hardlimit;
 589        soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
 590                (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
 591                        dqp->q_rtb.softlimit;
 592        res = &dqp->q_rtb;
 593        qlim = id == 0 ? &defq->rtb : NULL;
 594
 595        xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
 596        if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
 597                xfs_setqlim_warns(res, qlim, newlim->d_rt_spc_warns);
 598        if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
 599                xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
 600
 601        /* Inodes */
 602        hard = (newlim->d_fieldmask & QC_INO_HARD) ?
 603                (xfs_qcnt_t) newlim->d_ino_hardlimit :
 604                        dqp->q_ino.hardlimit;
 605        soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
 606                (xfs_qcnt_t) newlim->d_ino_softlimit :
 607                        dqp->q_ino.softlimit;
 608        res = &dqp->q_ino;
 609        qlim = id == 0 ? &defq->ino : NULL;
 610
 611        xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
 612        if (newlim->d_fieldmask & QC_INO_WARNS)
 613                xfs_setqlim_warns(res, qlim, newlim->d_ino_warns);
 614        if (newlim->d_fieldmask & QC_INO_TIMER)
 615                xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
 616
 617        if (id != 0) {
 618                /*
 619                 * If the user is now over quota, start the timelimit.
 620                 * The user will not be 'warned'.
 621                 * Note that we keep the timers ticking, whether enforcement
 622                 * is on or off. We don't really want to bother with iterating
 623                 * over all ondisk dquots and turning the timers on/off.
 624                 */
 625                xfs_qm_adjust_dqtimers(dqp);
 626        }
 627        dqp->q_flags |= XFS_DQFLAG_DIRTY;
 628        xfs_trans_log_dquot(tp, dqp);
 629
 630        error = xfs_trans_commit(tp);
 631
 632out_rele:
 633        xfs_qm_dqrele(dqp);
 634out_unlock:
 635        mutex_unlock(&q->qi_quotaofflock);
 636        return error;
 637}
 638
 639/* Fill out the quota context. */
 640static void
 641xfs_qm_scall_getquota_fill_qc(
 642        struct xfs_mount        *mp,
 643        xfs_dqtype_t            type,
 644        const struct xfs_dquot  *dqp,
 645        struct qc_dqblk         *dst)
 646{
 647        memset(dst, 0, sizeof(*dst));
 648        dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
 649        dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
 650        dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
 651        dst->d_ino_softlimit = dqp->q_ino.softlimit;
 652        dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
 653        dst->d_ino_count = dqp->q_ino.reserved;
 654        dst->d_spc_timer = dqp->q_blk.timer;
 655        dst->d_ino_timer = dqp->q_ino.timer;
 656        dst->d_ino_warns = dqp->q_ino.warnings;
 657        dst->d_spc_warns = dqp->q_blk.warnings;
 658        dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
 659        dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
 660        dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
 661        dst->d_rt_spc_timer = dqp->q_rtb.timer;
 662        dst->d_rt_spc_warns = dqp->q_rtb.warnings;
 663
 664        /*
 665         * Internally, we don't reset all the timers when quota enforcement
 666         * gets turned off. No need to confuse the user level code,
 667         * so return zeroes in that case.
 668         */
 669        if (!xfs_dquot_is_enforced(dqp)) {
 670                dst->d_spc_timer = 0;
 671                dst->d_ino_timer = 0;
 672                dst->d_rt_spc_timer = 0;
 673        }
 674
 675#ifdef DEBUG
 676        if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
 677                if ((dst->d_space > dst->d_spc_softlimit) &&
 678                    (dst->d_spc_softlimit > 0)) {
 679                        ASSERT(dst->d_spc_timer != 0);
 680                }
 681                if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
 682                    (dqp->q_ino.softlimit > 0)) {
 683                        ASSERT(dst->d_ino_timer != 0);
 684                }
 685        }
 686#endif
 687}
 688
 689/* Return the quota information for the dquot matching id. */
 690int
 691xfs_qm_scall_getquota(
 692        struct xfs_mount        *mp,
 693        xfs_dqid_t              id,
 694        xfs_dqtype_t            type,
 695        struct qc_dqblk         *dst)
 696{
 697        struct xfs_dquot        *dqp;
 698        int                     error;
 699
 700        /*
 701         * Try to get the dquot. We don't want it allocated on disk, so don't
 702         * set doalloc. If it doesn't exist, we'll get ENOENT back.
 703         */
 704        error = xfs_qm_dqget(mp, id, type, false, &dqp);
 705        if (error)
 706                return error;
 707
 708        /*
 709         * If everything's NULL, this dquot doesn't quite exist as far as
 710         * our utility programs are concerned.
 711         */
 712        if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
 713                error = -ENOENT;
 714                goto out_put;
 715        }
 716
 717        xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
 718
 719out_put:
 720        xfs_qm_dqput(dqp);
 721        return error;
 722}
 723
 724/*
 725 * Return the quota information for the first initialized dquot whose id
 726 * is at least as high as id.
 727 */
 728int
 729xfs_qm_scall_getquota_next(
 730        struct xfs_mount        *mp,
 731        xfs_dqid_t              *id,
 732        xfs_dqtype_t            type,
 733        struct qc_dqblk         *dst)
 734{
 735        struct xfs_dquot        *dqp;
 736        int                     error;
 737
 738        error = xfs_qm_dqget_next(mp, *id, type, &dqp);
 739        if (error)
 740                return error;
 741
 742        /* Fill in the ID we actually read from disk */
 743        *id = dqp->q_id;
 744
 745        xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
 746
 747        xfs_qm_dqput(dqp);
 748        return error;
 749}
 750
 751STATIC int
 752xfs_dqrele_inode(
 753        struct xfs_inode        *ip,
 754        void                    *args)
 755{
 756        uint                    *flags = args;
 757
 758        /* skip quota inodes */
 759        if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
 760            ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
 761            ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
 762                ASSERT(ip->i_udquot == NULL);
 763                ASSERT(ip->i_gdquot == NULL);
 764                ASSERT(ip->i_pdquot == NULL);
 765                return 0;
 766        }
 767
 768        xfs_ilock(ip, XFS_ILOCK_EXCL);
 769        if ((*flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
 770                xfs_qm_dqrele(ip->i_udquot);
 771                ip->i_udquot = NULL;
 772        }
 773        if ((*flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
 774                xfs_qm_dqrele(ip->i_gdquot);
 775                ip->i_gdquot = NULL;
 776        }
 777        if ((*flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
 778                xfs_qm_dqrele(ip->i_pdquot);
 779                ip->i_pdquot = NULL;
 780        }
 781        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 782        return 0;
 783}
 784
 785
 786/*
 787 * Go thru all the inodes in the file system, releasing their dquots.
 788 *
 789 * Note that the mount structure gets modified to indicate that quotas are off
 790 * AFTER this, in the case of quotaoff.
 791 */
 792void
 793xfs_qm_dqrele_all_inodes(
 794        struct xfs_mount        *mp,
 795        uint                    flags)
 796{
 797        ASSERT(mp->m_quotainfo);
 798        xfs_inode_walk(mp, XFS_INODE_WALK_INEW_WAIT, xfs_dqrele_inode,
 799                        &flags, XFS_ICI_NO_TAG);
 800}
 801