linux-old/fs/xfs/quota/xfs_dquot.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms of version 2 of the GNU General Public License as
   6 * published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it would be useful, but
   9 * WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11 *
  12 * Further, this software is distributed without any warranty that it is
  13 * free of the rightful claim of any third person regarding infringement
  14 * or the like.  Any license provided herein, whether implied or
  15 * otherwise, applies only to this software file.  Patent licenses, if
  16 * any, provided herein do not apply to combinations of this program with
  17 * other software, or any other product whatsoever.
  18 *
  19 * You should have received a copy of the GNU General Public License along
  20 * with this program; if not, write the Free Software Foundation, Inc., 59
  21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
  22 *
  23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
  24 * Mountain View, CA  94043, or:
  25 *
  26 * http://www.sgi.com
  27 *
  28 * For further information regarding this notice, see:
  29 *
  30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  31 */
  32
  33#include "xfs.h"
  34#include "xfs_fs.h"
  35#include "xfs_inum.h"
  36#include "xfs_log.h"
  37#include "xfs_trans.h"
  38#include "xfs_sb.h"
  39#include "xfs_ag.h"
  40#include "xfs_dir.h"
  41#include "xfs_dir2.h"
  42#include "xfs_alloc.h"
  43#include "xfs_dmapi.h"
  44#include "xfs_quota.h"
  45#include "xfs_mount.h"
  46#include "xfs_alloc_btree.h"
  47#include "xfs_bmap_btree.h"
  48#include "xfs_ialloc_btree.h"
  49#include "xfs_btree.h"
  50#include "xfs_ialloc.h"
  51#include "xfs_attr_sf.h"
  52#include "xfs_dir_sf.h"
  53#include "xfs_dir2_sf.h"
  54#include "xfs_dinode.h"
  55#include "xfs_inode.h"
  56#include "xfs_bmap.h"
  57#include "xfs_bit.h"
  58#include "xfs_rtalloc.h"
  59#include "xfs_error.h"
  60#include "xfs_itable.h"
  61#include "xfs_rw.h"
  62#include "xfs_acl.h"
  63#include "xfs_cap.h"
  64#include "xfs_mac.h"
  65#include "xfs_attr.h"
  66#include "xfs_buf_item.h"
  67#include "xfs_trans_space.h"
  68#include "xfs_trans_priv.h"
  69
  70#include "xfs_qm.h"
  71
  72
  73/*
  74   LOCK ORDER
  75
  76   inode lock               (ilock)
  77   dquot hash-chain lock    (hashlock)
  78   xqm dquot freelist lock  (freelistlock
  79   mount's dquot list lock  (mplistlock)
  80   user dquot lock - lock ordering among dquots is based on the uid or gid
  81   group dquot lock - similar to udquots. Between the two dquots, the udquot
  82                      has to be locked first.
  83   pin lock - the dquot lock must be held to take this lock.
  84   flush lock - ditto.
  85*/
  86
  87STATIC void             xfs_qm_dqflush_done(xfs_buf_t *, xfs_dq_logitem_t *);
  88
  89#ifdef DEBUG
  90xfs_buftarg_t *xfs_dqerror_target;
  91int xfs_do_dqerror;
  92int xfs_dqreq_num;
  93int xfs_dqerror_mod = 33;
  94#endif
  95
  96/*
  97 * Allocate and initialize a dquot. We don't always allocate fresh memory;
  98 * we try to reclaim a free dquot if the number of incore dquots are above
  99 * a threshold.
 100 * The only field inside the core that gets initialized at this point
 101 * is the d_id field. The idea is to fill in the entire q_core
 102 * when we read in the on disk dquot.
 103 */
 104xfs_dquot_t *
 105xfs_qm_dqinit(
 106        xfs_mount_t  *mp,
 107        xfs_dqid_t   id,
 108        uint         type)
 109{
 110        xfs_dquot_t     *dqp;
 111        boolean_t       brandnewdquot;
 112
 113        brandnewdquot = xfs_qm_dqalloc_incore(&dqp);
 114        dqp->dq_flags = type;
 115        INT_SET(dqp->q_core.d_id, ARCH_CONVERT, id);
 116        dqp->q_mount = mp;
 117
 118        /*
 119         * No need to re-initialize these if this is a reclaimed dquot.
 120         */
 121        if (brandnewdquot) {
 122                dqp->dq_flnext = dqp->dq_flprev = dqp;
 123                mutex_init(&dqp->q_qlock,  MUTEX_DEFAULT, "xdq");
 124                initnsema(&dqp->q_flock, 1, "fdq");
 125                sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq");
 126
 127#ifdef XFS_DQUOT_TRACE
 128                dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP);
 129                xfs_dqtrace_entry(dqp, "DQINIT");
 130#endif
 131        } else {
 132                /*
 133                 * Only the q_core portion was zeroed in dqreclaim_one().
 134                 * So, we need to reset others.
 135                 */
 136                 dqp->q_nrefs = 0;
 137                 dqp->q_blkno = 0;
 138                 dqp->MPL_NEXT = dqp->HL_NEXT = NULL;
 139                 dqp->HL_PREVP = dqp->MPL_PREVP = NULL;
 140                 dqp->q_bufoffset = 0;
 141                 dqp->q_fileoffset = 0;
 142                 dqp->q_transp = NULL;
 143                 dqp->q_gdquot = NULL;
 144                 dqp->q_res_bcount = 0;
 145                 dqp->q_res_icount = 0;
 146                 dqp->q_res_rtbcount = 0;
 147                 dqp->q_pincount = 0;
 148                 dqp->q_hash = NULL;
 149                 ASSERT(dqp->dq_flnext == dqp->dq_flprev);
 150
 151#ifdef XFS_DQUOT_TRACE
 152                 ASSERT(dqp->q_trace);
 153                 xfs_dqtrace_entry(dqp, "DQRECLAIMED_INIT");
 154#endif
 155         }
 156
 157        /*
 158         * log item gets initialized later
 159         */
 160        return (dqp);
 161}
 162
 163/*
 164 * This is called to free all the memory associated with a dquot
 165 */
 166void
 167xfs_qm_dqdestroy(
 168        xfs_dquot_t     *dqp)
 169{
 170        ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp));
 171
 172        mutex_destroy(&dqp->q_qlock);
 173        freesema(&dqp->q_flock);
 174        sv_destroy(&dqp->q_pinwait);
 175
 176#ifdef XFS_DQUOT_TRACE
 177        if (dqp->q_trace)
 178             ktrace_free(dqp->q_trace);
 179        dqp->q_trace = NULL;
 180#endif
 181        kmem_zone_free(xfs_Gqm->qm_dqzone, dqp);
 182        atomic_dec(&xfs_Gqm->qm_totaldquots);
 183}
 184
 185/*
 186 * This is what a 'fresh' dquot inside a dquot chunk looks like on disk.
 187 */
 188STATIC void
 189xfs_qm_dqinit_core(
 190        xfs_dqid_t      id,
 191        uint            type,
 192        xfs_dqblk_t     *d)
 193{
 194        /*
 195         * Caller has zero'd the entire dquot 'chunk' already.
 196         */
 197        INT_SET(d->dd_diskdq.d_magic, ARCH_CONVERT, XFS_DQUOT_MAGIC);
 198        INT_SET(d->dd_diskdq.d_version, ARCH_CONVERT, XFS_DQUOT_VERSION);
 199        INT_SET(d->dd_diskdq.d_id, ARCH_CONVERT, id);
 200        INT_SET(d->dd_diskdq.d_flags, ARCH_CONVERT, type);
 201}
 202
 203
 204#ifdef XFS_DQUOT_TRACE
 205/*
 206 * Dquot tracing for debugging.
 207 */
 208/* ARGSUSED */
 209void
 210__xfs_dqtrace_entry(
 211        xfs_dquot_t     *dqp,
 212        char            *func,
 213        void            *retaddr,
 214        xfs_inode_t     *ip)
 215{
 216        xfs_dquot_t     *udqp = NULL;
 217        xfs_ino_t       ino = 0;
 218
 219        ASSERT(dqp->q_trace);
 220        if (ip) {
 221                ino = ip->i_ino;
 222                udqp = ip->i_udquot;
 223        }
 224        ktrace_enter(dqp->q_trace,
 225                     (void *)(__psint_t)DQUOT_KTRACE_ENTRY,
 226                     (void *)func,
 227                     (void *)(__psint_t)dqp->q_nrefs,
 228                     (void *)(__psint_t)dqp->dq_flags,
 229                     (void *)(__psint_t)dqp->q_res_bcount,
 230                     (void *)(__psint_t)INT_GET(dqp->q_core.d_bcount,
 231                                                ARCH_CONVERT),
 232                     (void *)(__psint_t)INT_GET(dqp->q_core.d_icount,
 233                                                ARCH_CONVERT),
 234                     (void *)(__psint_t)INT_GET(dqp->q_core.d_blk_hardlimit,
 235                                                ARCH_CONVERT),
 236                     (void *)(__psint_t)INT_GET(dqp->q_core.d_blk_softlimit,
 237                                                ARCH_CONVERT),
 238                     (void *)(__psint_t)INT_GET(dqp->q_core.d_ino_hardlimit,
 239                                                ARCH_CONVERT),
 240                     (void *)(__psint_t)INT_GET(dqp->q_core.d_ino_softlimit,
 241                                                ARCH_CONVERT),
 242                     (void *)(__psint_t)INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
 243                     (void *)(__psint_t)current_pid(),
 244                     (void *)(__psint_t)ino,
 245                     (void *)(__psint_t)retaddr,
 246                     (void *)(__psint_t)udqp);
 247        return;
 248}
 249#endif
 250
 251
 252/*
 253 * If default limits are in force, push them into the dquot now.
 254 * We overwrite the dquot limits only if they are zero and this
 255 * is not the root dquot.
 256 */
 257void
 258xfs_qm_adjust_dqlimits(
 259        xfs_mount_t             *mp,
 260        xfs_disk_dquot_t        *d)
 261{
 262        xfs_quotainfo_t         *q = mp->m_quotainfo;
 263
 264        ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
 265
 266        if (q->qi_bsoftlimit && INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT))
 267                INT_SET(d->d_blk_softlimit, ARCH_CONVERT, q->qi_bsoftlimit);
 268        if (q->qi_bhardlimit && INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT))
 269                INT_SET(d->d_blk_hardlimit, ARCH_CONVERT, q->qi_bhardlimit);
 270        if (q->qi_isoftlimit && INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT))
 271                INT_SET(d->d_ino_softlimit, ARCH_CONVERT, q->qi_isoftlimit);
 272        if (q->qi_ihardlimit && INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT))
 273                INT_SET(d->d_ino_hardlimit, ARCH_CONVERT, q->qi_ihardlimit);
 274        if (q->qi_rtbsoftlimit &&
 275            INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT))
 276                INT_SET(d->d_rtb_softlimit, ARCH_CONVERT, q->qi_rtbsoftlimit);
 277        if (q->qi_rtbhardlimit &&
 278            INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT))
 279                INT_SET(d->d_rtb_hardlimit, ARCH_CONVERT, q->qi_rtbhardlimit);
 280}
 281
 282/*
 283 * Check the limits and timers of a dquot and start or reset timers
 284 * if necessary.
 285 * This gets called even when quota enforcement is OFF, which makes our
 286 * life a little less complicated. (We just don't reject any quota
 287 * reservations in that case, when enforcement is off).
 288 * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
 289 * enforcement's off.
 290 * In contrast, warnings are a little different in that they don't
 291 * 'automatically' get started when limits get exceeded.
 292 */
 293void
 294xfs_qm_adjust_dqtimers(
 295        xfs_mount_t             *mp,
 296        xfs_disk_dquot_t        *d)
 297{
 298        ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
 299
 300#ifdef QUOTADEBUG
 301        if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
 302                ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <=
 303                        INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
 304        if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT))
 305                ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <=
 306                        INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
 307        if (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT))
 308                ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <=
 309                        INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT));
 310#endif
 311        if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
 312                if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
 313                    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
 314                                INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
 315                    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
 316                    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
 317                                INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
 318                        INT_SET(d->d_btimer, ARCH_CONVERT,
 319                                get_seconds() + XFS_QI_BTIMELIMIT(mp));
 320                }
 321        } else {
 322                if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
 323                    (INT_GET(d->d_bcount, ARCH_CONVERT) <
 324                                INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
 325                    (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
 326                    (INT_GET(d->d_bcount, ARCH_CONVERT) <
 327                                INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
 328                        INT_ZERO(d->d_btimer, ARCH_CONVERT);
 329                }
 330        }
 331
 332        if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
 333                if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
 334                    (INT_GET(d->d_icount, ARCH_CONVERT) >=
 335                                INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
 336                    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
 337                    (INT_GET(d->d_icount, ARCH_CONVERT) >=
 338                                INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
 339                        INT_SET(d->d_itimer, ARCH_CONVERT,
 340                                get_seconds() + XFS_QI_ITIMELIMIT(mp));
 341                }
 342        } else {
 343                if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
 344                    (INT_GET(d->d_icount, ARCH_CONVERT) <
 345                                INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
 346                    (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
 347                    (INT_GET(d->d_icount, ARCH_CONVERT) <
 348                                INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
 349                        INT_ZERO(d->d_itimer, ARCH_CONVERT);
 350                }
 351        }
 352
 353        if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) {
 354                if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) &&
 355                    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
 356                                INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) ||
 357                    (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT) &&
 358                    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
 359                                INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
 360                        INT_SET(d->d_rtbtimer, ARCH_CONVERT,
 361                                get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
 362                }
 363        } else {
 364                if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) ||
 365                    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
 366                                INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) &&
 367                    (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) ||
 368                    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
 369                                INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
 370                        INT_ZERO(d->d_rtbtimer, ARCH_CONVERT);
 371                }
 372        }
 373}
 374
 375/*
 376 * Increment or reset warnings of a given dquot.
 377 */
 378int
 379xfs_qm_dqwarn(
 380        xfs_disk_dquot_t        *d,
 381        uint                    flags)
 382{
 383        int     warned;
 384
 385        /*
 386         * root's limits are not real limits.
 387         */
 388        if (INT_ISZERO(d->d_id, ARCH_CONVERT))
 389                return (0);
 390
 391        warned = 0;
 392        if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
 393            (INT_GET(d->d_bcount, ARCH_CONVERT) >=
 394             INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
 395                if (flags & XFS_QMOPT_DOWARN) {
 396                        INT_MOD(d->d_bwarns, ARCH_CONVERT, +1);
 397                        warned++;
 398                }
 399        } else {
 400                if (INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
 401                    (INT_GET(d->d_bcount, ARCH_CONVERT) <
 402                     INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
 403                        INT_ZERO(d->d_bwarns, ARCH_CONVERT);
 404                }
 405        }
 406
 407        if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 &&
 408            (INT_GET(d->d_icount, ARCH_CONVERT) >=
 409             INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
 410                if (flags & XFS_QMOPT_DOWARN) {
 411                        INT_MOD(d->d_iwarns, ARCH_CONVERT, +1);
 412                        warned++;
 413                }
 414        } else {
 415                if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT)) ||
 416                    (INT_GET(d->d_icount, ARCH_CONVERT) <
 417                     INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
 418                        INT_ZERO(d->d_iwarns, ARCH_CONVERT);
 419                }
 420        }
 421#ifdef QUOTADEBUG
 422        if (INT_GET(d->d_iwarns, ARCH_CONVERT))
 423                cmn_err(CE_DEBUG,
 424                        "--------@@Inode warnings running : %Lu >= %Lu",
 425                        INT_GET(d->d_icount, ARCH_CONVERT),
 426                        INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
 427        if (INT_GET(d->d_bwarns, ARCH_CONVERT))
 428                cmn_err(CE_DEBUG,
 429                        "--------@@Blks warnings running : %Lu >= %Lu",
 430                        INT_GET(d->d_bcount, ARCH_CONVERT),
 431                        INT_GET(d->d_blk_softlimit, ARCH_CONVERT));
 432#endif
 433        return (warned);
 434}
 435
 436
 437/*
 438 * initialize a buffer full of dquots and log the whole thing
 439 */
 440STATIC void
 441xfs_qm_init_dquot_blk(
 442        xfs_trans_t     *tp,
 443        xfs_mount_t     *mp,
 444        xfs_dqid_t      id,
 445        uint            type,
 446        xfs_buf_t       *bp)
 447{
 448        xfs_dqblk_t     *d;
 449        int             curid, i;
 450
 451        ASSERT(tp);
 452        ASSERT(XFS_BUF_ISBUSY(bp));
 453        ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 454
 455        d = (xfs_dqblk_t *)XFS_BUF_PTR(bp);
 456
 457        /*
 458         * ID of the first dquot in the block - id's are zero based.
 459         */
 460        curid = id - (id % XFS_QM_DQPERBLK(mp));
 461        ASSERT(curid >= 0);
 462        memset(d, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)));
 463        for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++)
 464                xfs_qm_dqinit_core(curid, type, d);
 465        xfs_trans_dquot_buf(tp, bp,
 466                            type & XFS_DQ_USER ?
 467                            XFS_BLI_UDQUOT_BUF :
 468                            XFS_BLI_GDQUOT_BUF);
 469        xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1);
 470}
 471
 472
 473
 474/*
 475 * Allocate a block and fill it with dquots.
 476 * This is called when the bmapi finds a hole.
 477 */
 478STATIC int
 479xfs_qm_dqalloc(
 480        xfs_trans_t     *tp,
 481        xfs_mount_t     *mp,
 482        xfs_dquot_t     *dqp,
 483        xfs_inode_t     *quotip,
 484        xfs_fileoff_t   offset_fsb,
 485        xfs_buf_t       **O_bpp)
 486{
 487        xfs_fsblock_t   firstblock;
 488        xfs_bmap_free_t flist;
 489        xfs_bmbt_irec_t map;
 490        int             nmaps, error, committed;
 491        xfs_buf_t       *bp;
 492
 493        ASSERT(tp != NULL);
 494        xfs_dqtrace_entry(dqp, "DQALLOC");
 495
 496        /*
 497         * Initialize the bmap freelist prior to calling bmapi code.
 498         */
 499        XFS_BMAP_INIT(&flist, &firstblock);
 500        xfs_ilock(quotip, XFS_ILOCK_EXCL);
 501        /*
 502         * Return if this type of quotas is turned off while we didn't
 503         * have an inode lock
 504         */
 505        if (XFS_IS_THIS_QUOTA_OFF(dqp)) {
 506                xfs_iunlock(quotip, XFS_ILOCK_EXCL);
 507                return (ESRCH);
 508        }
 509
 510        /*
 511         * xfs_trans_commit normally decrements the vnode ref count
 512         * when it unlocks the inode. Since we want to keep the quota
 513         * inode around, we bump the vnode ref count now.
 514         */
 515        VN_HOLD(XFS_ITOV(quotip));
 516
 517        xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL);
 518        nmaps = 1;
 519        if ((error = xfs_bmapi(tp, quotip,
 520                              offset_fsb, XFS_DQUOT_CLUSTER_SIZE_FSB,
 521                              XFS_BMAPI_METADATA | XFS_BMAPI_WRITE,
 522                              &firstblock,
 523                              XFS_QM_DQALLOC_SPACE_RES(mp),
 524                              &map, &nmaps, &flist))) {
 525                goto error0;
 526        }
 527        ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
 528        ASSERT(nmaps == 1);
 529        ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
 530               (map.br_startblock != HOLESTARTBLOCK));
 531
 532        /*
 533         * Keep track of the blkno to save a lookup later
 534         */
 535        dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
 536
 537        /* now we can just get the buffer (there's nothing to read yet) */
 538        bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
 539                               dqp->q_blkno,
 540                               XFS_QI_DQCHUNKLEN(mp),
 541                               0);
 542        if (!bp || (error = XFS_BUF_GETERROR(bp)))
 543                goto error1;
 544        /*
 545         * Make a chunk of dquots out of this buffer and log
 546         * the entire thing.
 547         */
 548        xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
 549                              dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
 550                              bp);
 551
 552        if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
 553                goto error1;
 554        }
 555
 556        *O_bpp = bp;
 557        return 0;
 558
 559      error1:
 560        xfs_bmap_cancel(&flist);
 561      error0:
 562        xfs_iunlock(quotip, XFS_ILOCK_EXCL);
 563
 564        return (error);
 565}
 566
 567/*
 568 * Maps a dquot to the buffer containing its on-disk version.
 569 * This returns a ptr to the buffer containing the on-disk dquot
 570 * in the bpp param, and a ptr to the on-disk dquot within that buffer
 571 */
 572STATIC int
 573xfs_qm_dqtobp(
 574        xfs_trans_t             *tp,
 575        xfs_dquot_t             *dqp,
 576        xfs_disk_dquot_t        **O_ddpp,
 577        xfs_buf_t               **O_bpp,
 578        uint                    flags)
 579{
 580        xfs_bmbt_irec_t map;
 581        int             nmaps, error;
 582        xfs_buf_t       *bp;
 583        xfs_inode_t     *quotip;
 584        xfs_mount_t     *mp;
 585        xfs_disk_dquot_t *ddq;
 586        xfs_dqid_t      id;
 587        boolean_t       newdquot;
 588
 589        mp = dqp->q_mount;
 590        id = INT_GET(dqp->q_core.d_id, ARCH_CONVERT);
 591        nmaps = 1;
 592        newdquot = B_FALSE;
 593
 594        /*
 595         * If we don't know where the dquot lives, find out.
 596         */
 597        if (dqp->q_blkno == (xfs_daddr_t) 0) {
 598                /* We use the id as an index */
 599                dqp->q_fileoffset = (xfs_fileoff_t) ((uint)id /
 600                                                     XFS_QM_DQPERBLK(mp));
 601                nmaps = 1;
 602                quotip = XFS_DQ_TO_QIP(dqp);
 603                xfs_ilock(quotip, XFS_ILOCK_SHARED);
 604                /*
 605                 * Return if this type of quotas is turned off while we didn't
 606                 * have an inode lock
 607                 */
 608                if (XFS_IS_THIS_QUOTA_OFF(dqp)) {
 609                        xfs_iunlock(quotip, XFS_ILOCK_SHARED);
 610                        return (ESRCH);
 611                }
 612                /*
 613                 * Find the block map; no allocations yet
 614                 */
 615                error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
 616                                  XFS_DQUOT_CLUSTER_SIZE_FSB,
 617                                  XFS_BMAPI_METADATA,
 618                                  NULL, 0, &map, &nmaps, NULL);
 619
 620                xfs_iunlock(quotip, XFS_ILOCK_SHARED);
 621                if (error)
 622                        return (error);
 623                ASSERT(nmaps == 1);
 624                ASSERT(map.br_blockcount == 1);
 625
 626                /*
 627                 * offset of dquot in the (fixed sized) dquot chunk.
 628                 */
 629                dqp->q_bufoffset = (id % XFS_QM_DQPERBLK(mp)) *
 630                        sizeof(xfs_dqblk_t);
 631                if (map.br_startblock == HOLESTARTBLOCK) {
 632                        /*
 633                         * We don't allocate unless we're asked to
 634                         */
 635                        if (!(flags & XFS_QMOPT_DQALLOC))
 636                                return (ENOENT);
 637
 638                        ASSERT(tp);
 639                        if ((error = xfs_qm_dqalloc(tp, mp, dqp, quotip,
 640                                                dqp->q_fileoffset, &bp)))
 641                                return (error);
 642                        newdquot = B_TRUE;
 643                } else {
 644                        /*
 645                         * store the blkno etc so that we don't have to do the
 646                         * mapping all the time
 647                         */
 648                        dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
 649                }
 650        }
 651        ASSERT(dqp->q_blkno != DELAYSTARTBLOCK);
 652        ASSERT(dqp->q_blkno != HOLESTARTBLOCK);
 653
 654        /*
 655         * Read in the buffer, unless we've just done the allocation
 656         * (in which case we already have the buf).
 657         */
 658        if (! newdquot) {
 659                xfs_dqtrace_entry(dqp, "DQTOBP READBUF");
 660                if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 661                                               dqp->q_blkno,
 662                                               XFS_QI_DQCHUNKLEN(mp),
 663                                               0, &bp))) {
 664                        return (error);
 665                }
 666                if (error || !bp)
 667                        return XFS_ERROR(error);
 668        }
 669        ASSERT(XFS_BUF_ISBUSY(bp));
 670        ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 671
 672        /*
 673         * calculate the location of the dquot inside the buffer.
 674         */
 675        ddq = (xfs_disk_dquot_t *)((char *)XFS_BUF_PTR(bp) + dqp->q_bufoffset);
 676
 677        /*
 678         * A simple sanity check in case we got a corrupted dquot...
 679         */
 680        if (xfs_qm_dqcheck(ddq, id,
 681                           dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
 682                           flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
 683                           "dqtobp")) {
 684                if (!(flags & XFS_QMOPT_DQREPAIR)) {
 685                        xfs_trans_brelse(tp, bp);
 686                        return XFS_ERROR(EIO);
 687                }
 688                XFS_BUF_BUSY(bp); /* We dirtied this */
 689        }
 690
 691        *O_bpp = bp;
 692        *O_ddpp = ddq;
 693
 694        return (0);
 695}
 696
 697
 698/*
 699 * Read in the ondisk dquot using dqtobp() then copy it to an incore version,
 700 * and release the buffer immediately.
 701 *
 702 */
 703/* ARGSUSED */
 704STATIC int
 705xfs_qm_dqread(
 706        xfs_trans_t     *tp,
 707        xfs_dqid_t      id,
 708        xfs_dquot_t     *dqp,   /* dquot to get filled in */
 709        uint            flags)
 710{
 711        xfs_disk_dquot_t *ddqp;
 712        xfs_buf_t        *bp;
 713        int              error;
 714
 715        /*
 716         * get a pointer to the on-disk dquot and the buffer containing it
 717         * dqp already knows its own type (GROUP/USER).
 718         */
 719        xfs_dqtrace_entry(dqp, "DQREAD");
 720        if ((error = xfs_qm_dqtobp(tp, dqp, &ddqp, &bp, flags))) {
 721                return (error);
 722        }
 723
 724        /* copy everything from disk dquot to the incore dquot */
 725        memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t));
 726        ASSERT(INT_GET(dqp->q_core.d_id, ARCH_CONVERT) == id);
 727        xfs_qm_dquot_logitem_init(dqp);
 728
 729        /*
 730         * Reservation counters are defined as reservation plus current usage
 731         * to avoid having to add everytime.
 732         */
 733        dqp->q_res_bcount = INT_GET(ddqp->d_bcount, ARCH_CONVERT);
 734        dqp->q_res_icount = INT_GET(ddqp->d_icount, ARCH_CONVERT);
 735        dqp->q_res_rtbcount = INT_GET(ddqp->d_rtbcount, ARCH_CONVERT);
 736
 737        /* Mark the buf so that this will stay incore a little longer */
 738        XFS_BUF_SET_VTYPE_REF(bp, B_FS_DQUOT, XFS_DQUOT_REF);
 739
 740        /*
 741         * We got the buffer with a xfs_trans_read_buf() (in dqtobp())
 742         * So we need to release with xfs_trans_brelse().
 743         * The strategy here is identical to that of inodes; we lock
 744         * the dquot in xfs_qm_dqget() before making it accessible to
 745         * others. This is because dquots, like inodes, need a good level of
 746         * concurrency, and we don't want to take locks on the entire buffers
 747         * for dquot accesses.
 748         * Note also that the dquot buffer may even be dirty at this point, if
 749         * this particular dquot was repaired. We still aren't afraid to
 750         * brelse it because we have the changes incore.
 751         */
 752        ASSERT(XFS_BUF_ISBUSY(bp));
 753        ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 754        xfs_trans_brelse(tp, bp);
 755
 756        return (error);
 757}
 758
 759
 760/*
 761 * allocate an incore dquot from the kernel heap,
 762 * and fill its core with quota information kept on disk.
 763 * If XFS_QMOPT_DQALLOC is set, it'll allocate a dquot on disk
 764 * if it wasn't already allocated.
 765 */
 766STATIC int
 767xfs_qm_idtodq(
 768        xfs_mount_t     *mp,
 769        xfs_dqid_t      id,      /* gid or uid, depending on type */
 770        uint            type,    /* UDQUOT or GDQUOT */
 771        uint            flags,   /* DQALLOC, DQREPAIR */
 772        xfs_dquot_t     **O_dqpp)/* OUT : incore dquot, not locked */
 773{
 774        xfs_dquot_t     *dqp;
 775        int             error;
 776        xfs_trans_t     *tp;
 777        int             cancelflags=0;
 778
 779        dqp = xfs_qm_dqinit(mp, id, type);
 780        tp = NULL;
 781        if (flags & XFS_QMOPT_DQALLOC) {
 782                tp = xfs_trans_alloc(mp, XFS_TRANS_QM_DQALLOC);
 783                if ((error = xfs_trans_reserve(tp,
 784                                       XFS_QM_DQALLOC_SPACE_RES(mp),
 785                                       XFS_WRITE_LOG_RES(mp) +
 786                                              BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1 +
 787                                              128,
 788                                       0,
 789                                       XFS_TRANS_PERM_LOG_RES,
 790                                       XFS_WRITE_LOG_COUNT))) {
 791                        cancelflags = 0;
 792                        goto error0;
 793                }
 794                cancelflags = XFS_TRANS_RELEASE_LOG_RES;
 795        }
 796
 797        /*
 798         * Read it from disk; xfs_dqread() takes care of
 799         * all the necessary initialization of dquot's fields (locks, etc)
 800         */
 801        if ((error = xfs_qm_dqread(tp, id, dqp, flags))) {
 802                /*
 803                 * This can happen if quotas got turned off (ESRCH),
 804                 * or if the dquot didn't exist on disk and we ask to
 805                 * allocate (ENOENT).
 806                 */
 807                xfs_dqtrace_entry(dqp, "DQREAD FAIL");
 808                cancelflags |= XFS_TRANS_ABORT;
 809                goto error0;
 810        }
 811        if (tp) {
 812                if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES,
 813                                             NULL)))
 814                        goto error1;
 815        }
 816
 817        *O_dqpp = dqp;
 818        return (0);
 819
 820 error0:
 821        ASSERT(error);
 822        if (tp)
 823                xfs_trans_cancel(tp, cancelflags);
 824 error1:
 825        xfs_qm_dqdestroy(dqp);
 826        *O_dqpp = NULL;
 827        return (error);
 828}
 829
 830/*
 831 * Lookup a dquot in the incore dquot hashtable. We keep two separate
 832 * hashtables for user and group dquots; and, these are global tables
 833 * inside the XQM, not per-filesystem tables.
 834 * The hash chain must be locked by caller, and it is left locked
 835 * on return. Returning dquot is locked.
 836 */
 837STATIC int
 838xfs_qm_dqlookup(
 839        xfs_mount_t             *mp,
 840        xfs_dqid_t              id,
 841        xfs_dqhash_t            *qh,
 842        xfs_dquot_t             **O_dqpp)
 843{
 844        xfs_dquot_t             *dqp;
 845        uint                    flist_locked;
 846        xfs_dquot_t             *d;
 847
 848        ASSERT(XFS_DQ_IS_HASH_LOCKED(qh));
 849
 850        flist_locked = B_FALSE;
 851
 852        /*
 853         * Traverse the hashchain looking for a match
 854         */
 855        for (dqp = qh->qh_next; dqp != NULL; dqp = dqp->HL_NEXT) {
 856                /*
 857                 * We already have the hashlock. We don't need the
 858                 * dqlock to look at the id field of the dquot, since the
 859                 * id can't be modified without the hashlock anyway.
 860                 */
 861                if (INT_GET(dqp->q_core.d_id, ARCH_CONVERT) == id && dqp->q_mount == mp) {
 862                        xfs_dqtrace_entry(dqp, "DQFOUND BY LOOKUP");
 863                        /*
 864                         * All in core dquots must be on the dqlist of mp
 865                         */
 866                        ASSERT(dqp->MPL_PREVP != NULL);
 867
 868                        xfs_dqlock(dqp);
 869                        if (dqp->q_nrefs == 0) {
 870                                ASSERT (XFS_DQ_IS_ON_FREELIST(dqp));
 871                                if (! xfs_qm_freelist_lock_nowait(xfs_Gqm)) {
 872                                        xfs_dqtrace_entry(dqp, "DQLOOKUP: WANT");
 873
 874                                        /*
 875                                         * We may have raced with dqreclaim_one()
 876                                         * (and lost). So, flag that we don't
 877                                         * want the dquot to be reclaimed.
 878                                         */
 879                                        dqp->dq_flags |= XFS_DQ_WANT;
 880                                        xfs_dqunlock(dqp);
 881                                        xfs_qm_freelist_lock(xfs_Gqm);
 882                                        xfs_dqlock(dqp);
 883                                        dqp->dq_flags &= ~(XFS_DQ_WANT);
 884                                }
 885                                flist_locked = B_TRUE;
 886                        }
 887
 888                        /*
 889                         * id couldn't have changed; we had the hashlock all
 890                         * along
 891                         */
 892                        ASSERT(INT_GET(dqp->q_core.d_id, ARCH_CONVERT) == id);
 893
 894                        if (flist_locked) {
 895                                if (dqp->q_nrefs != 0) {
 896                                        xfs_qm_freelist_unlock(xfs_Gqm);
 897                                        flist_locked = B_FALSE;
 898                                } else {
 899                                        /*
 900                                         * take it off the freelist
 901                                         */
 902                                        xfs_dqtrace_entry(dqp,
 903                                                        "DQLOOKUP: TAKEOFF FL");
 904                                        XQM_FREELIST_REMOVE(dqp);
 905                                        /* xfs_qm_freelist_print(&(xfs_Gqm->
 906                                                        qm_dqfreelist),
 907                                                        "after removal"); */
 908                                }
 909                        }
 910
 911                        /*
 912                         * grab a reference
 913                         */
 914                        XFS_DQHOLD(dqp);
 915
 916                        if (flist_locked)
 917                                xfs_qm_freelist_unlock(xfs_Gqm);
 918                        /*
 919                         * move the dquot to the front of the hashchain
 920                         */
 921                        ASSERT(XFS_DQ_IS_HASH_LOCKED(qh));
 922                        if (dqp->HL_PREVP != &qh->qh_next) {
 923                                xfs_dqtrace_entry(dqp,
 924                                                  "DQLOOKUP: HASH MOVETOFRONT");
 925                                if ((d = dqp->HL_NEXT))
 926                                        d->HL_PREVP = dqp->HL_PREVP;
 927                                *(dqp->HL_PREVP) = d;
 928                                d = qh->qh_next;
 929                                d->HL_PREVP = &dqp->HL_NEXT;
 930                                dqp->HL_NEXT = d;
 931                                dqp->HL_PREVP = &qh->qh_next;
 932                                qh->qh_next = dqp;
 933                        }
 934                        xfs_dqtrace_entry(dqp, "LOOKUP END");
 935                        *O_dqpp = dqp;
 936                        ASSERT(XFS_DQ_IS_HASH_LOCKED(qh));
 937                        return (0);
 938                }
 939        }
 940
 941        *O_dqpp = NULL;
 942        ASSERT(XFS_DQ_IS_HASH_LOCKED(qh));
 943        return (1);
 944}
 945
 946/*
 947 * Given the file system, inode OR id, and type (UDQUOT/GDQUOT), return a
 948 * a locked dquot, doing an allocation (if requested) as needed.
 949 * When both an inode and an id are given, the inode's id takes precedence.
 950 * That is, if the id changes while we don't hold the ilock inside this
 951 * function, the new dquot is returned, not necessarily the one requested
 952 * in the id argument.
 953 */
 954int
 955xfs_qm_dqget(
 956        xfs_mount_t     *mp,
 957        xfs_inode_t     *ip,      /* locked inode (optional) */
 958        xfs_dqid_t      id,       /* gid or uid, depending on type */
 959        uint            type,     /* UDQUOT or GDQUOT */
 960        uint            flags,    /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
 961        xfs_dquot_t     **O_dqpp) /* OUT : locked incore dquot */
 962{
 963        xfs_dquot_t     *dqp;
 964        xfs_dqhash_t    *h;
 965        uint            version;
 966        int             error;
 967
 968        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 969        if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
 970            (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
 971                return (ESRCH);
 972        }
 973        h = XFS_DQ_HASH(mp, id, type);
 974
 975#ifdef DEBUG
 976        if (xfs_do_dqerror) {
 977                if ((xfs_dqerror_target == mp->m_ddev_targp) &&
 978                    (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) {
 979                        cmn_err(CE_DEBUG, "Returning error in dqget");
 980                        return (EIO);
 981                }
 982        }
 983#endif
 984
 985 again:
 986
 987#ifdef DEBUG
 988        ASSERT(type == XFS_DQ_USER || type == XFS_DQ_GROUP);
 989        if (ip) {
 990                ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
 991                if (type == XFS_DQ_USER)
 992                        ASSERT(ip->i_udquot == NULL);
 993                else
 994                        ASSERT(ip->i_gdquot == NULL);
 995        }
 996#endif
 997        XFS_DQ_HASH_LOCK(h);
 998
 999        /*
1000         * Look in the cache (hashtable).
1001         * The chain is kept locked during lookup.
1002         */
1003        if (xfs_qm_dqlookup(mp, id, h, O_dqpp) == 0) {
1004                XQM_STATS_INC(xqmstats.xs_qm_dqcachehits);
1005                /*
1006                 * The dquot was found, moved to the front of the chain,
1007                 * taken off the freelist if it was on it, and locked
1008                 * at this point. Just unlock the hashchain and return.
1009                 */
1010                ASSERT(*O_dqpp);
1011                ASSERT(XFS_DQ_IS_LOCKED(*O_dqpp));
1012                XFS_DQ_HASH_UNLOCK(h);
1013                xfs_dqtrace_entry(*O_dqpp, "DQGET DONE (FROM CACHE)");
1014                return (0);     /* success */
1015        }
1016        XQM_STATS_INC(xqmstats.xs_qm_dqcachemisses);
1017
1018        /*
1019         * Dquot cache miss. We don't want to keep the inode lock across
1020         * a (potential) disk read. Also we don't want to deal with the lock
1021         * ordering between quotainode and this inode. OTOH, dropping the inode
1022         * lock here means dealing with a chown that can happen before
1023         * we re-acquire the lock.
1024         */
1025        if (ip)
1026                xfs_iunlock(ip, XFS_ILOCK_EXCL);
1027        /*
1028         * Save the hashchain version stamp, and unlock the chain, so that
1029         * we don't keep the lock across a disk read
1030         */
1031        version = h->qh_version;
1032        XFS_DQ_HASH_UNLOCK(h);
1033
1034        /*
1035         * Allocate the dquot on the kernel heap, and read the ondisk
1036         * portion off the disk. Also, do all the necessary initialization
1037         * This can return ENOENT if dquot didn't exist on disk and we didn't
1038         * ask it to allocate; ESRCH if quotas got turned off suddenly.
1039         */
1040        if ((error = xfs_qm_idtodq(mp, id, type,
1041                                  flags & (XFS_QMOPT_DQALLOC|XFS_QMOPT_DQREPAIR|
1042                                           XFS_QMOPT_DOWARN),
1043                                  &dqp))) {
1044                if (ip)
1045                        xfs_ilock(ip, XFS_ILOCK_EXCL);
1046                return (error);
1047        }
1048
1049        /*
1050         * See if this is mount code calling to look at the overall quota limits
1051         * which are stored in the id == 0 user or group's dquot.
1052         * Since we may not have done a quotacheck by this point, just return
1053         * the dquot without attaching it to any hashtables, lists, etc, or even
1054         * taking a reference.
1055         * The caller must dqdestroy this once done.
1056         */
1057        if (flags & XFS_QMOPT_DQSUSER) {
1058                ASSERT(id == 0);
1059                ASSERT(! ip);
1060                goto dqret;
1061        }
1062
1063        /*
1064         * Dquot lock comes after hashlock in the lock ordering
1065         */
1066        if (ip) {
1067                xfs_ilock(ip, XFS_ILOCK_EXCL);
1068                if (! XFS_IS_DQTYPE_ON(mp, type)) {
1069                        /* inode stays locked on return */
1070                        xfs_qm_dqdestroy(dqp);
1071                        return XFS_ERROR(ESRCH);
1072                }
1073                /*
1074                 * A dquot could be attached to this inode by now, since
1075                 * we had dropped the ilock.
1076                 */
1077                if (type == XFS_DQ_USER) {
1078                        if (ip->i_udquot) {
1079                                xfs_qm_dqdestroy(dqp);
1080                                dqp = ip->i_udquot;
1081                                xfs_dqlock(dqp);
1082                                goto dqret;
1083                        }
1084                } else {
1085                        if (ip->i_gdquot) {
1086                                xfs_qm_dqdestroy(dqp);
1087                                dqp = ip->i_gdquot;
1088                                xfs_dqlock(dqp);
1089                                goto dqret;
1090                        }
1091                }
1092        }
1093
1094        /*
1095         * Hashlock comes after ilock in lock order
1096         */
1097        XFS_DQ_HASH_LOCK(h);
1098        if (version != h->qh_version) {
1099                xfs_dquot_t *tmpdqp;
1100                /*
1101                 * Now, see if somebody else put the dquot in the
1102                 * hashtable before us. This can happen because we didn't
1103                 * keep the hashchain lock. We don't have to worry about
1104                 * lock order between the two dquots here since dqp isn't
1105                 * on any findable lists yet.
1106                 */
1107                if (xfs_qm_dqlookup(mp, id, h, &tmpdqp) == 0) {
1108                        /*
1109                         * Duplicate found. Just throw away the new dquot
1110                         * and start over.
1111                         */
1112                        xfs_qm_dqput(tmpdqp);
1113                        XFS_DQ_HASH_UNLOCK(h);
1114                        xfs_qm_dqdestroy(dqp);
1115                        XQM_STATS_INC(xqmstats.xs_qm_dquot_dups);
1116                        goto again;
1117                }
1118        }
1119
1120        /*
1121         * Put the dquot at the beginning of the hash-chain and mp's list
1122         * LOCK ORDER: hashlock, freelistlock, mplistlock, udqlock, gdqlock ..
1123         */
1124        ASSERT(XFS_DQ_IS_HASH_LOCKED(h));
1125        dqp->q_hash = h;
1126        XQM_HASHLIST_INSERT(h, dqp);
1127
1128        /*
1129         * Attach this dquot to this filesystem's list of all dquots,
1130         * kept inside the mount structure in m_quotainfo field
1131         */
1132        xfs_qm_mplist_lock(mp);
1133
1134        /*
1135         * We return a locked dquot to the caller, with a reference taken
1136         */
1137        xfs_dqlock(dqp);
1138        dqp->q_nrefs = 1;
1139
1140        XQM_MPLIST_INSERT(&(XFS_QI_MPL_LIST(mp)), dqp);
1141
1142        xfs_qm_mplist_unlock(mp);
1143        XFS_DQ_HASH_UNLOCK(h);
1144 dqret:
1145        ASSERT((ip == NULL) || XFS_ISLOCKED_INODE_EXCL(ip));
1146        xfs_dqtrace_entry(dqp, "DQGET DONE");
1147        *O_dqpp = dqp;
1148        return (0);
1149}
1150
1151
1152/*
1153 * Release a reference to the dquot (decrement ref-count)
1154 * and unlock it. If there is a group quota attached to this
1155 * dquot, carefully release that too without tripping over
1156 * deadlocks'n'stuff.
1157 */
1158void
1159xfs_qm_dqput(
1160        xfs_dquot_t     *dqp)
1161{
1162        xfs_dquot_t     *gdqp;
1163
1164        ASSERT(dqp->q_nrefs > 0);
1165        ASSERT(XFS_DQ_IS_LOCKED(dqp));
1166        xfs_dqtrace_entry(dqp, "DQPUT");
1167
1168        if (dqp->q_nrefs != 1) {
1169                dqp->q_nrefs--;
1170                xfs_dqunlock(dqp);
1171                return;
1172        }
1173
1174        /*
1175         * drop the dqlock and acquire the freelist and dqlock
1176         * in the right order; but try to get it out-of-order first
1177         */
1178        if (! xfs_qm_freelist_lock_nowait(xfs_Gqm)) {
1179                xfs_dqtrace_entry(dqp, "DQPUT: FLLOCK-WAIT");
1180                xfs_dqunlock(dqp);
1181                xfs_qm_freelist_lock(xfs_Gqm);
1182                xfs_dqlock(dqp);
1183        }
1184
1185        while (1) {
1186                gdqp = NULL;
1187
1188                /* We can't depend on nrefs being == 1 here */
1189                if (--dqp->q_nrefs == 0) {
1190                        xfs_dqtrace_entry(dqp, "DQPUT: ON FREELIST");
1191                        /*
1192                         * insert at end of the freelist.
1193                         */
1194                        XQM_FREELIST_INSERT(&(xfs_Gqm->qm_dqfreelist), dqp);
1195
1196                        /*
1197                         * If we just added a udquot to the freelist, then
1198                         * we want to release the gdquot reference that
1199                         * it (probably) has. Otherwise it'll keep the
1200                         * gdquot from getting reclaimed.
1201                         */
1202                        if ((gdqp = dqp->q_gdquot)) {
1203                                /*
1204                                 * Avoid a recursive dqput call
1205                                 */
1206                                xfs_dqlock(gdqp);
1207                                dqp->q_gdquot = NULL;
1208                        }
1209
1210                        /* xfs_qm_freelist_print(&(xfs_Gqm->qm_dqfreelist),
1211                           "@@@@@++ Free list (after append) @@@@@+");
1212                           */
1213                }
1214                xfs_dqunlock(dqp);
1215
1216                /*
1217                 * If we had a group quota inside the user quota as a hint,
1218                 * release it now.
1219                 */
1220                if (! gdqp)
1221                        break;
1222                dqp = gdqp;
1223        }
1224        xfs_qm_freelist_unlock(xfs_Gqm);
1225}
1226
1227/*
1228 * Release a dquot. Flush it if dirty, then dqput() it.
1229 * dquot must not be locked.
1230 */
1231void
1232xfs_qm_dqrele(
1233        xfs_dquot_t     *dqp)
1234{
1235        ASSERT(dqp);
1236        xfs_dqtrace_entry(dqp, "DQRELE");
1237
1238        xfs_dqlock(dqp);
1239        /*
1240         * We don't care to flush it if the dquot is dirty here.
1241         * That will create stutters that we want to avoid.
1242         * Instead we do a delayed write when we try to reclaim
1243         * a dirty dquot. Also xfs_sync will take part of the burden...
1244         */
1245        xfs_qm_dqput(dqp);
1246}
1247
1248
1249/*
1250 * Write a modified dquot to disk.
1251 * The dquot must be locked and the flush lock too taken by caller.
1252 * The flush lock will not be unlocked until the dquot reaches the disk,
1253 * but the dquot is free to be unlocked and modified by the caller
1254 * in the interim. Dquot is still locked on return. This behavior is
1255 * identical to that of inodes.
1256 */
1257int
1258xfs_qm_dqflush(
1259        xfs_dquot_t             *dqp,
1260        uint                    flags)
1261{
1262        xfs_mount_t             *mp;
1263        xfs_buf_t               *bp;
1264        xfs_disk_dquot_t        *ddqp;
1265        int                     error;
1266        SPLDECL(s);
1267
1268        ASSERT(XFS_DQ_IS_LOCKED(dqp));
1269        ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp));
1270        xfs_dqtrace_entry(dqp, "DQFLUSH");
1271
1272        /*
1273         * If not dirty, nada.
1274         */
1275        if (!XFS_DQ_IS_DIRTY(dqp)) {
1276                xfs_dqfunlock(dqp);
1277                return (0);
1278        }
1279
1280        /*
1281         * Cant flush a pinned dquot. Wait for it.
1282         */
1283        xfs_qm_dqunpin_wait(dqp);
1284
1285        /*
1286         * This may have been unpinned because the filesystem is shutting
1287         * down forcibly. If that's the case we must not write this dquot
1288         * to disk, because the log record didn't make it to disk!
1289         */
1290        if (XFS_FORCED_SHUTDOWN(dqp->q_mount)) {
1291                dqp->dq_flags &= ~(XFS_DQ_DIRTY);
1292                xfs_dqfunlock(dqp);
1293                return XFS_ERROR(EIO);
1294        }
1295
1296        /*
1297         * Get the buffer containing the on-disk dquot
1298         * We don't need a transaction envelope because we know that the
1299         * the ondisk-dquot has already been allocated for.
1300         */
1301        if ((error = xfs_qm_dqtobp(NULL, dqp, &ddqp, &bp, XFS_QMOPT_DOWARN))) {
1302                xfs_dqtrace_entry(dqp, "DQTOBP FAIL");
1303                ASSERT(error != ENOENT);
1304                /*
1305                 * Quotas could have gotten turned off (ESRCH)
1306                 */
1307                xfs_dqfunlock(dqp);
1308                return (error);
1309        }
1310
1311        if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT), 0, XFS_QMOPT_DOWARN,
1312                           "dqflush (incore copy)")) {
1313                xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
1314                return XFS_ERROR(EIO);
1315        }
1316
1317        /* This is the only portion of data that needs to persist */
1318        memcpy(ddqp, &(dqp->q_core), sizeof(xfs_disk_dquot_t));
1319
1320        /*
1321         * Clear the dirty field and remember the flush lsn for later use.
1322         */
1323        dqp->dq_flags &= ~(XFS_DQ_DIRTY);
1324        mp = dqp->q_mount;
1325
1326        /* lsn is 64 bits */
1327        AIL_LOCK(mp, s);
1328        dqp->q_logitem.qli_flush_lsn = dqp->q_logitem.qli_item.li_lsn;
1329        AIL_UNLOCK(mp, s);
1330
1331        /*
1332         * Attach an iodone routine so that we can remove this dquot from the
1333         * AIL and release the flush lock once the dquot is synced to disk.
1334         */
1335        xfs_buf_attach_iodone(bp, (void(*)(xfs_buf_t *, xfs_log_item_t *))
1336                              xfs_qm_dqflush_done, &(dqp->q_logitem.qli_item));
1337        /*
1338         * If the buffer is pinned then push on the log so we won't
1339         * get stuck waiting in the write for too long.
1340         */
1341        if (XFS_BUF_ISPINNED(bp)) {
1342                xfs_dqtrace_entry(dqp, "DQFLUSH LOG FORCE");
1343                xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
1344        }
1345
1346        if (flags & XFS_QMOPT_DELWRI) {
1347                xfs_bdwrite(mp, bp);
1348        } else if (flags & XFS_QMOPT_ASYNC) {
1349                xfs_bawrite(mp, bp);
1350        } else {
1351                error = xfs_bwrite(mp, bp);
1352        }
1353        xfs_dqtrace_entry(dqp, "DQFLUSH END");
1354        /*
1355         * dqp is still locked, but caller is free to unlock it now.
1356         */
1357        return (error);
1358
1359}
1360
1361/*
1362 * This is the dquot flushing I/O completion routine.  It is called
1363 * from interrupt level when the buffer containing the dquot is
1364 * flushed to disk.  It is responsible for removing the dquot logitem
1365 * from the AIL if it has not been re-logged, and unlocking the dquot's
1366 * flush lock. This behavior is very similar to that of inodes..
1367 */
1368/*ARGSUSED*/
1369STATIC void
1370xfs_qm_dqflush_done(
1371        xfs_buf_t               *bp,
1372        xfs_dq_logitem_t        *qip)
1373{
1374        xfs_dquot_t             *dqp;
1375        SPLDECL(s);
1376
1377        dqp = qip->qli_dquot;
1378
1379        /*
1380         * We only want to pull the item from the AIL if its
1381         * location in the log has not changed since we started the flush.
1382         * Thus, we only bother if the dquot's lsn has
1383         * not changed. First we check the lsn outside the lock
1384         * since it's cheaper, and then we recheck while
1385         * holding the lock before removing the dquot from the AIL.
1386         */
1387        if ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
1388            qip->qli_item.li_lsn == qip->qli_flush_lsn) {
1389
1390                AIL_LOCK(dqp->q_mount, s);
1391                /*
1392                 * xfs_trans_delete_ail() drops the AIL lock.
1393                 */
1394                if (qip->qli_item.li_lsn == qip->qli_flush_lsn)
1395                        xfs_trans_delete_ail(dqp->q_mount,
1396                                             (xfs_log_item_t*)qip, s);
1397                else
1398                        AIL_UNLOCK(dqp->q_mount, s);
1399        }
1400
1401        /*
1402         * Release the dq's flush lock since we're done with it.
1403         */
1404        xfs_dqfunlock(dqp);
1405}
1406
1407
1408int
1409xfs_qm_dqflock_nowait(
1410        xfs_dquot_t *dqp)
1411{
1412        int locked;
1413
1414        locked = cpsema(&((dqp)->q_flock));
1415
1416        /* XXX ifdef these out */
1417        if (locked)
1418                (dqp)->dq_flags |= XFS_DQ_FLOCKED;
1419        return (locked);
1420}
1421
1422
1423int
1424xfs_qm_dqlock_nowait(
1425        xfs_dquot_t *dqp)
1426{
1427        return (mutex_trylock(&((dqp)->q_qlock)));
1428}
1429
1430void
1431xfs_dqlock(
1432        xfs_dquot_t *dqp)
1433{
1434        mutex_lock(&(dqp->q_qlock), PINOD);
1435}
1436
1437void
1438xfs_dqunlock(
1439        xfs_dquot_t *dqp)
1440{
1441        mutex_unlock(&(dqp->q_qlock));
1442        if (dqp->q_logitem.qli_dquot == dqp) {
1443                /* Once was dqp->q_mount, but might just have been cleared */
1444                xfs_trans_unlocked_item(dqp->q_logitem.qli_item.li_mountp,
1445                                        (xfs_log_item_t*)&(dqp->q_logitem));
1446        }
1447}
1448
1449
1450void
1451xfs_dqunlock_nonotify(
1452        xfs_dquot_t *dqp)
1453{
1454        mutex_unlock(&(dqp->q_qlock));
1455}
1456
1457void
1458xfs_dqlock2(
1459        xfs_dquot_t     *d1,
1460        xfs_dquot_t     *d2)
1461{
1462        if (d1 && d2) {
1463                ASSERT(d1 != d2);
1464                if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) > INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
1465                        xfs_dqlock(d2);
1466                        xfs_dqlock(d1);
1467                } else {
1468                        xfs_dqlock(d1);
1469                        xfs_dqlock(d2);
1470                }
1471        } else {
1472                if (d1) {
1473                        xfs_dqlock(d1);
1474                } else if (d2) {
1475                        xfs_dqlock(d2);
1476                }
1477        }
1478}
1479
1480
1481/*
1482 * Take a dquot out of the mount's dqlist as well as the hashlist.
1483 * This is called via unmount as well as quotaoff, and the purge
1484 * will always succeed unless there are soft (temp) references
1485 * outstanding.
1486 *
1487 * This returns 0 if it was purged, 1 if it wasn't. It's not an error code
1488 * that we're returning! XXXsup - not cool.
1489 */
1490/* ARGSUSED */
1491int
1492xfs_qm_dqpurge(
1493        xfs_dquot_t     *dqp,
1494        uint            flags)
1495{
1496        xfs_dqhash_t    *thishash;
1497        xfs_mount_t     *mp;
1498
1499        mp = dqp->q_mount;
1500
1501        ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp));
1502        ASSERT(XFS_DQ_IS_HASH_LOCKED(dqp->q_hash));
1503
1504        xfs_dqlock(dqp);
1505        /*
1506         * We really can't afford to purge a dquot that is
1507         * referenced, because these are hard refs.
1508         * It shouldn't happen in general because we went thru _all_ inodes in
1509         * dqrele_all_inodes before calling this and didn't let the mountlock go.
1510         * However it is possible that we have dquots with temporary
1511         * references that are not attached to an inode. e.g. see xfs_setattr().
1512         */
1513        if (dqp->q_nrefs != 0) {
1514                xfs_dqunlock(dqp);
1515                XFS_DQ_HASH_UNLOCK(dqp->q_hash);
1516                return (1);
1517        }
1518
1519        ASSERT(XFS_DQ_IS_ON_FREELIST(dqp));
1520
1521        /*
1522         * If we're turning off quotas, we have to make sure that, for
1523         * example, we don't delete quota disk blocks while dquots are
1524         * in the process of getting written to those disk blocks.
1525         * This dquot might well be on AIL, and we can't leave it there
1526         * if we're turning off quotas. Basically, we need this flush
1527         * lock, and are willing to block on it.
1528         */
1529        if (! xfs_qm_dqflock_nowait(dqp)) {
1530                /*
1531                 * Block on the flush lock after nudging dquot buffer,
1532                 * if it is incore.
1533                 */
1534                xfs_qm_dqflock_pushbuf_wait(dqp);
1535        }
1536
1537        /*
1538         * XXXIf we're turning this type of quotas off, we don't care
1539         * about the dirty metadata sitting in this dquot. OTOH, if
1540         * we're unmounting, we do care, so we flush it and wait.
1541         */
1542        if (XFS_DQ_IS_DIRTY(dqp)) {
1543                xfs_dqtrace_entry(dqp, "DQPURGE ->DQFLUSH: DQDIRTY");
1544                /* dqflush unlocks dqflock */
1545                /*
1546                 * Given that dqpurge is a very rare occurrence, it is OK
1547                 * that we're holding the hashlist and mplist locks
1548                 * across the disk write. But, ... XXXsup
1549                 *
1550                 * We don't care about getting disk errors here. We need
1551                 * to purge this dquot anyway, so we go ahead regardless.
1552                 */
1553                (void) xfs_qm_dqflush(dqp, XFS_QMOPT_SYNC);
1554                xfs_dqflock(dqp);
1555        }
1556        ASSERT(dqp->q_pincount == 0);
1557        ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
1558               !(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
1559
1560        thishash = dqp->q_hash;
1561        XQM_HASHLIST_REMOVE(thishash, dqp);
1562        XQM_MPLIST_REMOVE(&(XFS_QI_MPL_LIST(mp)), dqp);
1563        /*
1564         * XXX Move this to the front of the freelist, if we can get the
1565         * freelist lock.
1566         */
1567        ASSERT(XFS_DQ_IS_ON_FREELIST(dqp));
1568
1569        dqp->q_mount = NULL;
1570        dqp->q_hash = NULL;
1571        dqp->dq_flags = XFS_DQ_INACTIVE;
1572        memset(&dqp->q_core, 0, sizeof(dqp->q_core));
1573        xfs_dqfunlock(dqp);
1574        xfs_dqunlock(dqp);
1575        XFS_DQ_HASH_UNLOCK(thishash);
1576        return (0);
1577}
1578
1579
1580#ifdef QUOTADEBUG
1581void
1582xfs_qm_dqprint(xfs_dquot_t *dqp)
1583{
1584        cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
1585        cmn_err(CE_DEBUG, "---- dquotID =  %d",
1586                (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT));
1587        cmn_err(CE_DEBUG, "---- type    =  %s",
1588                XFS_QM_ISUDQ(dqp) ? "USR" : "GRP");
1589        cmn_err(CE_DEBUG, "---- fs      =  0x%p", dqp->q_mount);
1590        cmn_err(CE_DEBUG, "---- blkno   =  0x%x", (int) dqp->q_blkno);
1591        cmn_err(CE_DEBUG, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
1592        cmn_err(CE_DEBUG, "---- blkhlimit =  %Lu (0x%x)",
1593                INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT),
1594                (int) INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT));
1595        cmn_err(CE_DEBUG, "---- blkslimit =  %Lu (0x%x)",
1596                INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT),
1597                (int)INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT));
1598        cmn_err(CE_DEBUG, "---- inohlimit =  %Lu (0x%x)",
1599                INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT),
1600                (int)INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT));
1601        cmn_err(CE_DEBUG, "---- inoslimit =  %Lu (0x%x)",
1602                INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT),
1603                (int)INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT));
1604        cmn_err(CE_DEBUG, "---- bcount  =  %Lu (0x%x)",
1605                INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT),
1606                (int)INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
1607        cmn_err(CE_DEBUG, "---- icount  =  %Lu (0x%x)",
1608                INT_GET(dqp->q_core.d_icount, ARCH_CONVERT),
1609                (int)INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
1610        cmn_err(CE_DEBUG, "---- btimer  =  %d",
1611                (int)INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT));
1612        cmn_err(CE_DEBUG, "---- itimer  =  %d",
1613                (int)INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT));
1614        cmn_err(CE_DEBUG, "---------------------------");
1615}
1616#endif
1617
1618/*
1619 * Give the buffer a little push if it is incore and
1620 * wait on the flush lock.
1621 */
1622void
1623xfs_qm_dqflock_pushbuf_wait(
1624        xfs_dquot_t     *dqp)
1625{
1626        xfs_buf_t       *bp;
1627
1628        /*
1629         * Check to see if the dquot has been flushed delayed
1630         * write.  If so, grab its buffer and send it
1631         * out immediately.  We'll be able to acquire
1632         * the flush lock when the I/O completes.
1633         */
1634        bp = xfs_incore(dqp->q_mount->m_ddev_targp, dqp->q_blkno,
1635                    XFS_QI_DQCHUNKLEN(dqp->q_mount),
1636                    XFS_INCORE_TRYLOCK);
1637        if (bp != NULL) {
1638                if (XFS_BUF_ISDELAYWRITE(bp)) {
1639                        if (XFS_BUF_ISPINNED(bp)) {
1640                                xfs_log_force(dqp->q_mount,
1641                                              (xfs_lsn_t)0,
1642                                              XFS_LOG_FORCE);
1643                        }
1644                        xfs_bawrite(dqp->q_mount, bp);
1645                } else {
1646                        xfs_buf_relse(bp);
1647                }
1648        }
1649        xfs_dqflock(dqp);
1650}
1651
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.