linux/fs/xfs/xfs_qm_syscalls.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   3 * All Rights Reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it would be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write the Free Software Foundation,
  16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17 */
  18
  19#include <linux/capability.h>
  20
  21#include "xfs.h"
  22#include "xfs_fs.h"
  23#include "xfs_bit.h"
  24#include "xfs_log.h"
  25#include "xfs_trans.h"
  26#include "xfs_sb.h"
  27#include "xfs_ag.h"
  28#include "xfs_alloc.h"
  29#include "xfs_quota.h"
  30#include "xfs_mount.h"
  31#include "xfs_bmap_btree.h"
  32#include "xfs_inode.h"
  33#include "xfs_inode_item.h"
  34#include "xfs_itable.h"
  35#include "xfs_bmap.h"
  36#include "xfs_rtalloc.h"
  37#include "xfs_error.h"
  38#include "xfs_attr.h"
  39#include "xfs_buf_item.h"
  40#include "xfs_utils.h"
  41#include "xfs_qm.h"
  42#include "xfs_trace.h"
  43#include "xfs_icache.h"
  44
  45STATIC int      xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
  46STATIC int      xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
  47                                        uint);
  48STATIC uint     xfs_qm_export_flags(uint);
  49STATIC uint     xfs_qm_export_qtype_flags(uint);
  50
  51/*
  52 * Turn off quota accounting and/or enforcement for all udquots and/or
  53 * gdquots. Called only at unmount time.
  54 *
  55 * This assumes that there are no dquots of this file system cached
  56 * incore, and modifies the ondisk dquot directly. Therefore, for example,
  57 * it is an error to call this twice, without purging the cache.
  58 */
  59int
  60xfs_qm_scall_quotaoff(
  61        xfs_mount_t             *mp,
  62        uint                    flags)
  63{
  64        struct xfs_quotainfo    *q = mp->m_quotainfo;
  65        uint                    dqtype;
  66        int                     error;
  67        uint                    inactivate_flags;
  68        xfs_qoff_logitem_t      *qoffstart;
  69
  70        /*
  71         * No file system can have quotas enabled on disk but not in core.
  72         * Note that quota utilities (like quotaoff) _expect_
  73         * errno == EEXIST here.
  74         */
  75        if ((mp->m_qflags & flags) == 0)
  76                return XFS_ERROR(EEXIST);
  77        error = 0;
  78
  79        flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
  80
  81        /*
  82         * We don't want to deal with two quotaoffs messing up each other,
  83         * so we're going to serialize it. quotaoff isn't exactly a performance
  84         * critical thing.
  85         * If quotaoff, then we must be dealing with the root filesystem.
  86         */
  87        ASSERT(q);
  88        mutex_lock(&q->qi_quotaofflock);
  89
  90        /*
  91         * If we're just turning off quota enforcement, change mp and go.
  92         */
  93        if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
  94                mp->m_qflags &= ~(flags);
  95
  96                spin_lock(&mp->m_sb_lock);
  97                mp->m_sb.sb_qflags = mp->m_qflags;
  98                spin_unlock(&mp->m_sb_lock);
  99                mutex_unlock(&q->qi_quotaofflock);
 100
 101                /* XXX what to do if error ? Revert back to old vals incore ? */
 102                error = xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS);
 103                return (error);
 104        }
 105
 106        dqtype = 0;
 107        inactivate_flags = 0;
 108        /*
 109         * If accounting is off, we must turn enforcement off, clear the
 110         * quota 'CHKD' certificate to make it known that we have to
 111         * do a quotacheck the next time this quota is turned on.
 112         */
 113        if (flags & XFS_UQUOTA_ACCT) {
 114                dqtype |= XFS_QMOPT_UQUOTA;
 115                flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
 116                inactivate_flags |= XFS_UQUOTA_ACTIVE;
 117        }
 118        if (flags & XFS_GQUOTA_ACCT) {
 119                dqtype |= XFS_QMOPT_GQUOTA;
 120                flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
 121                inactivate_flags |= XFS_GQUOTA_ACTIVE;
 122        }
 123        if (flags & XFS_PQUOTA_ACCT) {
 124                dqtype |= XFS_QMOPT_PQUOTA;
 125                flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
 126                inactivate_flags |= XFS_PQUOTA_ACTIVE;
 127        }
 128
 129        /*
 130         * Nothing to do?  Don't complain. This happens when we're just
 131         * turning off quota enforcement.
 132         */
 133        if ((mp->m_qflags & flags) == 0)
 134                goto out_unlock;
 135
 136        /*
 137         * Write the LI_QUOTAOFF log record, and do SB changes atomically,
 138         * and synchronously. If we fail to write, we should abort the
 139         * operation as it cannot be recovered safely if we crash.
 140         */
 141        error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
 142        if (error)
 143                goto out_unlock;
 144
 145        /*
 146         * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
 147         * to take care of the race between dqget and quotaoff. We don't take
 148         * any special locks to reset these bits. All processes need to check
 149         * these bits *after* taking inode lock(s) to see if the particular
 150         * quota type is in the process of being turned off. If *ACTIVE, it is
 151         * guaranteed that all dquot structures and all quotainode ptrs will all
 152         * stay valid as long as that inode is kept locked.
 153         *
 154         * There is no turning back after this.
 155         */
 156        mp->m_qflags &= ~inactivate_flags;
 157
 158        /*
 159         * Give back all the dquot reference(s) held by inodes.
 160         * Here we go thru every single incore inode in this file system, and
 161         * do a dqrele on the i_udquot/i_gdquot that it may have.
 162         * Essentially, as long as somebody has an inode locked, this guarantees
 163         * that quotas will not be turned off. This is handy because in a
 164         * transaction once we lock the inode(s) and check for quotaon, we can
 165         * depend on the quota inodes (and other things) being valid as long as
 166         * we keep the lock(s).
 167         */
 168        xfs_qm_dqrele_all_inodes(mp, flags);
 169
 170        /*
 171         * Next we make the changes in the quota flag in the mount struct.
 172         * This isn't protected by a particular lock directly, because we
 173         * don't want to take a mrlock every time we depend on quotas being on.
 174         */
 175        mp->m_qflags &= ~flags;
 176
 177        /*
 178         * Go through all the dquots of this file system and purge them,
 179         * according to what was turned off.
 180         */
 181        xfs_qm_dqpurge_all(mp, dqtype);
 182
 183        /*
 184         * Transactions that had started before ACTIVE state bit was cleared
 185         * could have logged many dquots, so they'd have higher LSNs than
 186         * the first QUOTAOFF log record does. If we happen to crash when
 187         * the tail of the log has gone past the QUOTAOFF record, but
 188         * before the last dquot modification, those dquots __will__
 189         * recover, and that's not good.
 190         *
 191         * So, we have QUOTAOFF start and end logitems; the start
 192         * logitem won't get overwritten until the end logitem appears...
 193         */
 194        error = xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
 195        if (error) {
 196                /* We're screwed now. Shutdown is the only option. */
 197                xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 198                goto out_unlock;
 199        }
 200
 201        /*
 202         * If all quotas are completely turned off, close shop.
 203         */
 204        if (mp->m_qflags == 0) {
 205                mutex_unlock(&q->qi_quotaofflock);
 206                xfs_qm_destroy_quotainfo(mp);
 207                return (0);
 208        }
 209
 210        /*
 211         * Release our quotainode references if we don't need them anymore.
 212         */
 213        if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
 214                IRELE(q->qi_uquotaip);
 215                q->qi_uquotaip = NULL;
 216        }
 217        if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
 218                IRELE(q->qi_gquotaip);
 219                q->qi_gquotaip = NULL;
 220        }
 221        if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
 222                IRELE(q->qi_pquotaip);
 223                q->qi_pquotaip = NULL;
 224        }
 225
 226out_unlock:
 227        mutex_unlock(&q->qi_quotaofflock);
 228        return error;
 229}
 230
 231STATIC int
 232xfs_qm_scall_trunc_qfile(
 233        struct xfs_mount        *mp,
 234        xfs_ino_t               ino)
 235{
 236        struct xfs_inode        *ip;
 237        struct xfs_trans        *tp;
 238        int                     error;
 239
 240        if (ino == NULLFSINO)
 241                return 0;
 242
 243        error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
 244        if (error)
 245                return error;
 246
 247        xfs_ilock(ip, XFS_IOLOCK_EXCL);
 248
 249        tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE);
 250        error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
 251                                  XFS_TRANS_PERM_LOG_RES,
 252                                  XFS_ITRUNCATE_LOG_COUNT);
 253        if (error) {
 254                xfs_trans_cancel(tp, 0);
 255                xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 256                goto out_put;
 257        }
 258
 259        xfs_ilock(ip, XFS_ILOCK_EXCL);
 260        xfs_trans_ijoin(tp, ip, 0);
 261
 262        ip->i_d.di_size = 0;
 263        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 264
 265        error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
 266        if (error) {
 267                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
 268                                     XFS_TRANS_ABORT);
 269                goto out_unlock;
 270        }
 271
 272        ASSERT(ip->i_d.di_nextents == 0);
 273
 274        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 275        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 276
 277out_unlock:
 278        xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 279out_put:
 280        IRELE(ip);
 281        return error;
 282}
 283
 284int
 285xfs_qm_scall_trunc_qfiles(
 286        xfs_mount_t     *mp,
 287        uint            flags)
 288{
 289        int             error = 0, error2 = 0;
 290
 291        if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
 292                xfs_debug(mp, "%s: flags=%x m_qflags=%x\n",
 293                        __func__, flags, mp->m_qflags);
 294                return XFS_ERROR(EINVAL);
 295        }
 296
 297        if (flags & XFS_DQ_USER)
 298                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
 299        if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ))
 300                error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
 301
 302        return error ? error : error2;
 303}
 304
 305/*
 306 * Switch on (a given) quota enforcement for a filesystem.  This takes
 307 * effect immediately.
 308 * (Switching on quota accounting must be done at mount time.)
 309 */
 310int
 311xfs_qm_scall_quotaon(
 312        xfs_mount_t     *mp,
 313        uint            flags)
 314{
 315        int             error;
 316        uint            qf;
 317        __int64_t       sbflags;
 318
 319        flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
 320        /*
 321         * Switching on quota accounting must be done at mount time.
 322         */
 323        flags &= ~(XFS_ALL_QUOTA_ACCT);
 324
 325        sbflags = 0;
 326
 327        if (flags == 0) {
 328                xfs_debug(mp, "%s: zero flags, m_qflags=%x\n",
 329                        __func__, mp->m_qflags);
 330                return XFS_ERROR(EINVAL);
 331        }
 332
 333        /* No fs can turn on quotas with a delayed effect */
 334        ASSERT((flags & XFS_ALL_QUOTA_ACCT) == 0);
 335
 336        /*
 337         * Can't enforce without accounting. We check the superblock
 338         * qflags here instead of m_qflags because rootfs can have
 339         * quota acct on ondisk without m_qflags' knowing.
 340         */
 341        if (((flags & XFS_UQUOTA_ACCT) == 0 &&
 342             (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
 343             (flags & XFS_UQUOTA_ENFD)) ||
 344            ((flags & XFS_GQUOTA_ACCT) == 0 &&
 345             (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
 346             (flags & XFS_GQUOTA_ENFD)) ||
 347            ((flags & XFS_PQUOTA_ACCT) == 0 &&
 348             (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
 349             (flags & XFS_PQUOTA_ENFD))) {
 350                xfs_debug(mp,
 351                        "%s: Can't enforce without acct, flags=%x sbflags=%x\n",
 352                        __func__, flags, mp->m_sb.sb_qflags);
 353                return XFS_ERROR(EINVAL);
 354        }
 355        /*
 356         * If everything's up to-date incore, then don't waste time.
 357         */
 358        if ((mp->m_qflags & flags) == flags)
 359                return XFS_ERROR(EEXIST);
 360
 361        /*
 362         * Change sb_qflags on disk but not incore mp->qflags
 363         * if this is the root filesystem.
 364         */
 365        spin_lock(&mp->m_sb_lock);
 366        qf = mp->m_sb.sb_qflags;
 367        mp->m_sb.sb_qflags = qf | flags;
 368        spin_unlock(&mp->m_sb_lock);
 369
 370        /*
 371         * There's nothing to change if it's the same.
 372         */
 373        if ((qf & flags) == flags && sbflags == 0)
 374                return XFS_ERROR(EEXIST);
 375        sbflags |= XFS_SB_QFLAGS;
 376
 377        if ((error = xfs_qm_write_sb_changes(mp, sbflags)))
 378                return (error);
 379        /*
 380         * If we aren't trying to switch on quota enforcement, we are done.
 381         */
 382        if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
 383             (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
 384             ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
 385             (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
 386             ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
 387             (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
 388            (flags & XFS_ALL_QUOTA_ENFD) == 0)
 389                return (0);
 390
 391        if (! XFS_IS_QUOTA_RUNNING(mp))
 392                return XFS_ERROR(ESRCH);
 393
 394        /*
 395         * Switch on quota enforcement in core.
 396         */
 397        mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
 398        mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
 399        mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
 400
 401        return (0);
 402}
 403
 404
 405/*
 406 * Return quota status information, such as uquota-off, enforcements, etc.
 407 */
 408int
 409xfs_qm_scall_getqstat(
 410        struct xfs_mount        *mp,
 411        struct fs_quota_stat    *out)
 412{
 413        struct xfs_quotainfo    *q = mp->m_quotainfo;
 414        struct xfs_inode        *uip = NULL;
 415        struct xfs_inode        *gip = NULL;
 416        bool                    tempuqip = false;
 417        bool                    tempgqip = false;
 418
 419        memset(out, 0, sizeof(fs_quota_stat_t));
 420
 421        out->qs_version = FS_QSTAT_VERSION;
 422        if (!xfs_sb_version_hasquota(&mp->m_sb)) {
 423                out->qs_uquota.qfs_ino = NULLFSINO;
 424                out->qs_gquota.qfs_ino = NULLFSINO;
 425                return (0);
 426        }
 427        out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
 428                                                        (XFS_ALL_QUOTA_ACCT|
 429                                                         XFS_ALL_QUOTA_ENFD));
 430        out->qs_pad = 0;
 431        out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
 432        out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
 433
 434        if (q) {
 435                uip = q->qi_uquotaip;
 436                gip = q->qi_gquotaip;
 437        }
 438        if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
 439                if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
 440                                        0, 0, &uip) == 0)
 441                        tempuqip = true;
 442        }
 443        if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
 444                if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
 445                                        0, 0, &gip) == 0)
 446                        tempgqip = true;
 447        }
 448        if (uip) {
 449                out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
 450                out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
 451                if (tempuqip)
 452                        IRELE(uip);
 453        }
 454        if (gip) {
 455                out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
 456                out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
 457                if (tempgqip)
 458                        IRELE(gip);
 459        }
 460        if (q) {
 461                out->qs_incoredqs = q->qi_dquots;
 462                out->qs_btimelimit = q->qi_btimelimit;
 463                out->qs_itimelimit = q->qi_itimelimit;
 464                out->qs_rtbtimelimit = q->qi_rtbtimelimit;
 465                out->qs_bwarnlimit = q->qi_bwarnlimit;
 466                out->qs_iwarnlimit = q->qi_iwarnlimit;
 467        }
 468        return 0;
 469}
 470
 471#define XFS_DQ_MASK \
 472        (FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK)
 473
 474/*
 475 * Adjust quota limits, and start/stop timers accordingly.
 476 */
 477int
 478xfs_qm_scall_setqlim(
 479        struct xfs_mount        *mp,
 480        xfs_dqid_t              id,
 481        uint                    type,
 482        fs_disk_quota_t         *newlim)
 483{
 484        struct xfs_quotainfo    *q = mp->m_quotainfo;
 485        struct xfs_disk_dquot   *ddq;
 486        struct xfs_dquot        *dqp;
 487        struct xfs_trans        *tp;
 488        int                     error;
 489        xfs_qcnt_t              hard, soft;
 490
 491        if (newlim->d_fieldmask & ~XFS_DQ_MASK)
 492                return EINVAL;
 493        if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
 494                return 0;
 495
 496        /*
 497         * We don't want to race with a quotaoff so take the quotaoff lock.
 498         * We don't hold an inode lock, so there's nothing else to stop
 499         * a quotaoff from happening.
 500         */
 501        mutex_lock(&q->qi_quotaofflock);
 502
 503        /*
 504         * Get the dquot (locked) before we start, as we need to do a
 505         * transaction to allocate it if it doesn't exist. Once we have the
 506         * dquot, unlock it so we can start the next transaction safely. We hold
 507         * a reference to the dquot, so it's safe to do this unlock/lock without
 508         * it being reclaimed in the mean time.
 509         */
 510        error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp);
 511        if (error) {
 512                ASSERT(error != ENOENT);
 513                goto out_unlock;
 514        }
 515        xfs_dqunlock(dqp);
 516
 517        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
 518        error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp),
 519                                  0, 0, XFS_DEFAULT_LOG_COUNT);
 520        if (error) {
 521                xfs_trans_cancel(tp, 0);
 522                goto out_rele;
 523        }
 524
 525        xfs_dqlock(dqp);
 526        xfs_trans_dqjoin(tp, dqp);
 527        ddq = &dqp->q_core;
 528
 529        /*
 530         * Make sure that hardlimits are >= soft limits before changing.
 531         */
 532        hard = (newlim->d_fieldmask & FS_DQ_BHARD) ?
 533                (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_hardlimit) :
 534                        be64_to_cpu(ddq->d_blk_hardlimit);
 535        soft = (newlim->d_fieldmask & FS_DQ_BSOFT) ?
 536                (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_softlimit) :
 537                        be64_to_cpu(ddq->d_blk_softlimit);
 538        if (hard == 0 || hard >= soft) {
 539                ddq->d_blk_hardlimit = cpu_to_be64(hard);
 540                ddq->d_blk_softlimit = cpu_to_be64(soft);
 541                xfs_dquot_set_prealloc_limits(dqp);
 542                if (id == 0) {
 543                        q->qi_bhardlimit = hard;
 544                        q->qi_bsoftlimit = soft;
 545                }
 546        } else {
 547                xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft);
 548        }
 549        hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
 550                (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
 551                        be64_to_cpu(ddq->d_rtb_hardlimit);
 552        soft = (newlim->d_fieldmask & FS_DQ_RTBSOFT) ?
 553                (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_softlimit) :
 554                        be64_to_cpu(ddq->d_rtb_softlimit);
 555        if (hard == 0 || hard >= soft) {
 556                ddq->d_rtb_hardlimit = cpu_to_be64(hard);
 557                ddq->d_rtb_softlimit = cpu_to_be64(soft);
 558                if (id == 0) {
 559                        q->qi_rtbhardlimit = hard;
 560                        q->qi_rtbsoftlimit = soft;
 561                }
 562        } else {
 563                xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
 564        }
 565
 566        hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
 567                (xfs_qcnt_t) newlim->d_ino_hardlimit :
 568                        be64_to_cpu(ddq->d_ino_hardlimit);
 569        soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
 570                (xfs_qcnt_t) newlim->d_ino_softlimit :
 571                        be64_to_cpu(ddq->d_ino_softlimit);
 572        if (hard == 0 || hard >= soft) {
 573                ddq->d_ino_hardlimit = cpu_to_be64(hard);
 574                ddq->d_ino_softlimit = cpu_to_be64(soft);
 575                if (id == 0) {
 576                        q->qi_ihardlimit = hard;
 577                        q->qi_isoftlimit = soft;
 578                }
 579        } else {
 580                xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft);
 581        }
 582
 583        /*
 584         * Update warnings counter(s) if requested
 585         */
 586        if (newlim->d_fieldmask & FS_DQ_BWARNS)
 587                ddq->d_bwarns = cpu_to_be16(newlim->d_bwarns);
 588        if (newlim->d_fieldmask & FS_DQ_IWARNS)
 589                ddq->d_iwarns = cpu_to_be16(newlim->d_iwarns);
 590        if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
 591                ddq->d_rtbwarns = cpu_to_be16(newlim->d_rtbwarns);
 592
 593        if (id == 0) {
 594                /*
 595                 * Timelimits for the super user set the relative time
 596                 * the other users can be over quota for this file system.
 597                 * If it is zero a default is used.  Ditto for the default
 598                 * soft and hard limit values (already done, above), and
 599                 * for warnings.
 600                 */
 601                if (newlim->d_fieldmask & FS_DQ_BTIMER) {
 602                        q->qi_btimelimit = newlim->d_btimer;
 603                        ddq->d_btimer = cpu_to_be32(newlim->d_btimer);
 604                }
 605                if (newlim->d_fieldmask & FS_DQ_ITIMER) {
 606                        q->qi_itimelimit = newlim->d_itimer;
 607                        ddq->d_itimer = cpu_to_be32(newlim->d_itimer);
 608                }
 609                if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
 610                        q->qi_rtbtimelimit = newlim->d_rtbtimer;
 611                        ddq->d_rtbtimer = cpu_to_be32(newlim->d_rtbtimer);
 612                }
 613                if (newlim->d_fieldmask & FS_DQ_BWARNS)
 614                        q->qi_bwarnlimit = newlim->d_bwarns;
 615                if (newlim->d_fieldmask & FS_DQ_IWARNS)
 616                        q->qi_iwarnlimit = newlim->d_iwarns;
 617                if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
 618                        q->qi_rtbwarnlimit = newlim->d_rtbwarns;
 619        } else {
 620                /*
 621                 * If the user is now over quota, start the timelimit.
 622                 * The user will not be 'warned'.
 623                 * Note that we keep the timers ticking, whether enforcement
 624                 * is on or off. We don't really want to bother with iterating
 625                 * over all ondisk dquots and turning the timers on/off.
 626                 */
 627                xfs_qm_adjust_dqtimers(mp, ddq);
 628        }
 629        dqp->dq_flags |= XFS_DQ_DIRTY;
 630        xfs_trans_log_dquot(tp, dqp);
 631
 632        error = xfs_trans_commit(tp, 0);
 633
 634out_rele:
 635        xfs_qm_dqrele(dqp);
 636out_unlock:
 637        mutex_unlock(&q->qi_quotaofflock);
 638        return error;
 639}
 640
 641STATIC int
 642xfs_qm_log_quotaoff_end(
 643        xfs_mount_t             *mp,
 644        xfs_qoff_logitem_t      *startqoff,
 645        uint                    flags)
 646{
 647        xfs_trans_t             *tp;
 648        int                     error;
 649        xfs_qoff_logitem_t      *qoffi;
 650
 651        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
 652
 653        error = xfs_trans_reserve(tp, 0, XFS_QM_QUOTAOFF_END_LOG_RES(mp),
 654                                  0, 0, XFS_DEFAULT_LOG_COUNT);
 655        if (error) {
 656                xfs_trans_cancel(tp, 0);
 657                return (error);
 658        }
 659
 660        qoffi = xfs_trans_get_qoff_item(tp, startqoff,
 661                                        flags & XFS_ALL_QUOTA_ACCT);
 662        xfs_trans_log_quotaoff_item(tp, qoffi);
 663
 664        /*
 665         * We have to make sure that the transaction is secure on disk before we
 666         * return and actually stop quota accounting. So, make it synchronous.
 667         * We don't care about quotoff's performance.
 668         */
 669        xfs_trans_set_sync(tp);
 670        error = xfs_trans_commit(tp, 0);
 671        return (error);
 672}
 673
 674
 675STATIC int
 676xfs_qm_log_quotaoff(
 677        xfs_mount_t            *mp,
 678        xfs_qoff_logitem_t     **qoffstartp,
 679        uint                   flags)
 680{
 681        xfs_trans_t            *tp;
 682        int                     error;
 683        xfs_qoff_logitem_t     *qoffi=NULL;
 684        uint                    oldsbqflag=0;
 685
 686        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
 687        error = xfs_trans_reserve(tp, 0, XFS_QM_QUOTAOFF_LOG_RES(mp),
 688                                  0, 0, XFS_DEFAULT_LOG_COUNT);
 689        if (error)
 690                goto error0;
 691
 692        qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
 693        xfs_trans_log_quotaoff_item(tp, qoffi);
 694
 695        spin_lock(&mp->m_sb_lock);
 696        oldsbqflag = mp->m_sb.sb_qflags;
 697        mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
 698        spin_unlock(&mp->m_sb_lock);
 699
 700        xfs_mod_sb(tp, XFS_SB_QFLAGS);
 701
 702        /*
 703         * We have to make sure that the transaction is secure on disk before we
 704         * return and actually stop quota accounting. So, make it synchronous.
 705         * We don't care about quotoff's performance.
 706         */
 707        xfs_trans_set_sync(tp);
 708        error = xfs_trans_commit(tp, 0);
 709
 710error0:
 711        if (error) {
 712                xfs_trans_cancel(tp, 0);
 713                /*
 714                 * No one else is modifying sb_qflags, so this is OK.
 715                 * We still hold the quotaofflock.
 716                 */
 717                spin_lock(&mp->m_sb_lock);
 718                mp->m_sb.sb_qflags = oldsbqflag;
 719                spin_unlock(&mp->m_sb_lock);
 720        }
 721        *qoffstartp = qoffi;
 722        return (error);
 723}
 724
 725
 726int
 727xfs_qm_scall_getquota(
 728        struct xfs_mount        *mp,
 729        xfs_dqid_t              id,
 730        uint                    type,
 731        struct fs_disk_quota    *dst)
 732{
 733        struct xfs_dquot        *dqp;
 734        int                     error;
 735
 736        /*
 737         * Try to get the dquot. We don't want it allocated on disk, so
 738         * we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
 739         * exist, we'll get ENOENT back.
 740         */
 741        error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp);
 742        if (error)
 743                return error;
 744
 745        /*
 746         * If everything's NULL, this dquot doesn't quite exist as far as
 747         * our utility programs are concerned.
 748         */
 749        if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
 750                error = XFS_ERROR(ENOENT);
 751                goto out_put;
 752        }
 753
 754        memset(dst, 0, sizeof(*dst));
 755        dst->d_version = FS_DQUOT_VERSION;
 756        dst->d_flags = xfs_qm_export_qtype_flags(dqp->q_core.d_flags);
 757        dst->d_id = be32_to_cpu(dqp->q_core.d_id);
 758        dst->d_blk_hardlimit =
 759                XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_hardlimit));
 760        dst->d_blk_softlimit =
 761                XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_softlimit));
 762        dst->d_ino_hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);
 763        dst->d_ino_softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
 764        dst->d_bcount = XFS_FSB_TO_BB(mp, dqp->q_res_bcount);
 765        dst->d_icount = dqp->q_res_icount;
 766        dst->d_btimer = be32_to_cpu(dqp->q_core.d_btimer);
 767        dst->d_itimer = be32_to_cpu(dqp->q_core.d_itimer);
 768        dst->d_iwarns = be16_to_cpu(dqp->q_core.d_iwarns);
 769        dst->d_bwarns = be16_to_cpu(dqp->q_core.d_bwarns);
 770        dst->d_rtb_hardlimit =
 771                XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_hardlimit));
 772        dst->d_rtb_softlimit =
 773                XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit));
 774        dst->d_rtbcount = XFS_FSB_TO_BB(mp, dqp->q_res_rtbcount);
 775        dst->d_rtbtimer = be32_to_cpu(dqp->q_core.d_rtbtimer);
 776        dst->d_rtbwarns = be16_to_cpu(dqp->q_core.d_rtbwarns);
 777
 778        /*
 779         * Internally, we don't reset all the timers when quota enforcement
 780         * gets turned off. No need to confuse the user level code,
 781         * so return zeroes in that case.
 782         */
 783        if ((!XFS_IS_UQUOTA_ENFORCED(mp) &&
 784             dqp->q_core.d_flags == XFS_DQ_USER) ||
 785            (!XFS_IS_GQUOTA_ENFORCED(mp) &&
 786             dqp->q_core.d_flags == XFS_DQ_GROUP) ||
 787            (!XFS_IS_PQUOTA_ENFORCED(mp) &&
 788             dqp->q_core.d_flags == XFS_DQ_PROJ)) {
 789                dst->d_btimer = 0;
 790                dst->d_itimer = 0;
 791                dst->d_rtbtimer = 0;
 792        }
 793
 794#ifdef DEBUG
 795        if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) ||
 796             (XFS_IS_GQUOTA_ENFORCED(mp) && dst->d_flags == FS_GROUP_QUOTA) ||
 797             (XFS_IS_PQUOTA_ENFORCED(mp) && dst->d_flags == FS_PROJ_QUOTA)) &&
 798            dst->d_id != 0) {
 799                if ((dst->d_bcount > dst->d_blk_softlimit) &&
 800                    (dst->d_blk_softlimit > 0)) {
 801                        ASSERT(dst->d_btimer != 0);
 802                }
 803                if ((dst->d_icount > dst->d_ino_softlimit) &&
 804                    (dst->d_ino_softlimit > 0)) {
 805                        ASSERT(dst->d_itimer != 0);
 806                }
 807        }
 808#endif
 809out_put:
 810        xfs_qm_dqput(dqp);
 811        return error;
 812}
 813
 814STATIC uint
 815xfs_qm_export_qtype_flags(
 816        uint flags)
 817{
 818        /*
 819         * Can't be more than one, or none.
 820         */
 821        ASSERT((flags & (FS_PROJ_QUOTA | FS_USER_QUOTA)) !=
 822                (FS_PROJ_QUOTA | FS_USER_QUOTA));
 823        ASSERT((flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)) !=
 824                (FS_PROJ_QUOTA | FS_GROUP_QUOTA));
 825        ASSERT((flags & (FS_USER_QUOTA | FS_GROUP_QUOTA)) !=
 826                (FS_USER_QUOTA | FS_GROUP_QUOTA));
 827        ASSERT((flags & (FS_PROJ_QUOTA|FS_USER_QUOTA|FS_GROUP_QUOTA)) != 0);
 828
 829        return (flags & XFS_DQ_USER) ?
 830                FS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
 831                        FS_PROJ_QUOTA : FS_GROUP_QUOTA;
 832}
 833
 834STATIC uint
 835xfs_qm_export_flags(
 836        uint flags)
 837{
 838        uint uflags;
 839
 840        uflags = 0;
 841        if (flags & XFS_UQUOTA_ACCT)
 842                uflags |= FS_QUOTA_UDQ_ACCT;
 843        if (flags & XFS_GQUOTA_ACCT)
 844                uflags |= FS_QUOTA_GDQ_ACCT;
 845        if (flags & XFS_PQUOTA_ACCT)
 846                uflags |= FS_QUOTA_PDQ_ACCT;
 847        if (flags & XFS_UQUOTA_ENFD)
 848                uflags |= FS_QUOTA_UDQ_ENFD;
 849        if (flags & XFS_GQUOTA_ENFD)
 850                uflags |= FS_QUOTA_GDQ_ENFD;
 851        if (flags & XFS_PQUOTA_ENFD)
 852                uflags |= FS_QUOTA_PDQ_ENFD;
 853        return (uflags);
 854}
 855
 856
 857STATIC int
 858xfs_dqrele_inode(
 859        struct xfs_inode        *ip,
 860        struct xfs_perag        *pag,
 861        int                     flags,
 862        void                    *args)
 863{
 864        /* skip quota inodes */
 865        if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
 866            ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
 867            ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
 868                ASSERT(ip->i_udquot == NULL);
 869                ASSERT(ip->i_gdquot == NULL);
 870                ASSERT(ip->i_pdquot == NULL);
 871                return 0;
 872        }
 873
 874        xfs_ilock(ip, XFS_ILOCK_EXCL);
 875        if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
 876                xfs_qm_dqrele(ip->i_udquot);
 877                ip->i_udquot = NULL;
 878        }
 879        if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
 880                xfs_qm_dqrele(ip->i_gdquot);
 881                ip->i_gdquot = NULL;
 882        }
 883        if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
 884                xfs_qm_dqrele(ip->i_pdquot);
 885                ip->i_pdquot = NULL;
 886        }
 887        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 888        return 0;
 889}
 890
 891
 892/*
 893 * Go thru all the inodes in the file system, releasing their dquots.
 894 *
 895 * Note that the mount structure gets modified to indicate that quotas are off
 896 * AFTER this, in the case of quotaoff.
 897 */
 898void
 899xfs_qm_dqrele_all_inodes(
 900        struct xfs_mount *mp,
 901        uint             flags)
 902{
 903        ASSERT(mp->m_quotainfo);
 904        xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, NULL);
 905}
 906
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.