linux/fs/xfs/xfs_dquot_item.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2003 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#include "xfs.h"
  19#include "xfs_fs.h"
  20#include "xfs_log.h"
  21#include "xfs_trans.h"
  22#include "xfs_sb.h"
  23#include "xfs_ag.h"
  24#include "xfs_alloc.h"
  25#include "xfs_quota.h"
  26#include "xfs_mount.h"
  27#include "xfs_bmap_btree.h"
  28#include "xfs_inode.h"
  29#include "xfs_bmap.h"
  30#include "xfs_rtalloc.h"
  31#include "xfs_error.h"
  32#include "xfs_itable.h"
  33#include "xfs_attr.h"
  34#include "xfs_buf_item.h"
  35#include "xfs_trans_priv.h"
  36#include "xfs_qm.h"
  37
  38static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip)
  39{
  40        return container_of(lip, struct xfs_dq_logitem, qli_item);
  41}
  42
  43/*
  44 * returns the number of iovecs needed to log the given dquot item.
  45 */
  46STATIC uint
  47xfs_qm_dquot_logitem_size(
  48        struct xfs_log_item     *lip)
  49{
  50        /*
  51         * we need only two iovecs, one for the format, one for the real thing
  52         */
  53        return 2;
  54}
  55
  56/*
  57 * fills in the vector of log iovecs for the given dquot log item.
  58 */
  59STATIC void
  60xfs_qm_dquot_logitem_format(
  61        struct xfs_log_item     *lip,
  62        struct xfs_log_iovec    *logvec)
  63{
  64        struct xfs_dq_logitem   *qlip = DQUOT_ITEM(lip);
  65
  66        logvec->i_addr = &qlip->qli_format;
  67        logvec->i_len  = sizeof(xfs_dq_logformat_t);
  68        logvec->i_type = XLOG_REG_TYPE_QFORMAT;
  69        logvec++;
  70        logvec->i_addr = &qlip->qli_dquot->q_core;
  71        logvec->i_len  = sizeof(xfs_disk_dquot_t);
  72        logvec->i_type = XLOG_REG_TYPE_DQUOT;
  73
  74        qlip->qli_format.qlf_size = 2;
  75
  76}
  77
  78/*
  79 * Increment the pin count of the given dquot.
  80 */
  81STATIC void
  82xfs_qm_dquot_logitem_pin(
  83        struct xfs_log_item     *lip)
  84{
  85        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
  86
  87        ASSERT(XFS_DQ_IS_LOCKED(dqp));
  88        atomic_inc(&dqp->q_pincount);
  89}
  90
  91/*
  92 * Decrement the pin count of the given dquot, and wake up
  93 * anyone in xfs_dqwait_unpin() if the count goes to 0.  The
  94 * dquot must have been previously pinned with a call to
  95 * xfs_qm_dquot_logitem_pin().
  96 */
  97STATIC void
  98xfs_qm_dquot_logitem_unpin(
  99        struct xfs_log_item     *lip,
 100        int                     remove)
 101{
 102        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
 103
 104        ASSERT(atomic_read(&dqp->q_pincount) > 0);
 105        if (atomic_dec_and_test(&dqp->q_pincount))
 106                wake_up(&dqp->q_pinwait);
 107}
 108
 109STATIC xfs_lsn_t
 110xfs_qm_dquot_logitem_committed(
 111        struct xfs_log_item     *lip,
 112        xfs_lsn_t               lsn)
 113{
 114        /*
 115         * We always re-log the entire dquot when it becomes dirty,
 116         * so, the latest copy _is_ the only one that matters.
 117         */
 118        return lsn;
 119}
 120
 121/*
 122 * This is called to wait for the given dquot to be unpinned.
 123 * Most of these pin/unpin routines are plagiarized from inode code.
 124 */
 125void
 126xfs_qm_dqunpin_wait(
 127        struct xfs_dquot        *dqp)
 128{
 129        ASSERT(XFS_DQ_IS_LOCKED(dqp));
 130        if (atomic_read(&dqp->q_pincount) == 0)
 131                return;
 132
 133        /*
 134         * Give the log a push so we don't wait here too long.
 135         */
 136        xfs_log_force(dqp->q_mount, 0);
 137        wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
 138}
 139
 140STATIC uint
 141xfs_qm_dquot_logitem_push(
 142        struct xfs_log_item     *lip,
 143        struct list_head        *buffer_list)
 144{
 145        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
 146        struct xfs_buf          *bp = NULL;
 147        uint                    rval = XFS_ITEM_SUCCESS;
 148        int                     error;
 149
 150        if (atomic_read(&dqp->q_pincount) > 0)
 151                return XFS_ITEM_PINNED;
 152
 153        if (!xfs_dqlock_nowait(dqp))
 154                return XFS_ITEM_LOCKED;
 155
 156        /*
 157         * Re-check the pincount now that we stabilized the value by
 158         * taking the quota lock.
 159         */
 160        if (atomic_read(&dqp->q_pincount) > 0) {
 161                rval = XFS_ITEM_PINNED;
 162                goto out_unlock;
 163        }
 164
 165        /*
 166         * Someone else is already flushing the dquot.  Nothing we can do
 167         * here but wait for the flush to finish and remove the item from
 168         * the AIL.
 169         */
 170        if (!xfs_dqflock_nowait(dqp)) {
 171                rval = XFS_ITEM_FLUSHING;
 172                goto out_unlock;
 173        }
 174
 175        spin_unlock(&lip->li_ailp->xa_lock);
 176
 177        error = xfs_qm_dqflush(dqp, &bp);
 178        if (error) {
 179                xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p",
 180                        __func__, error, dqp);
 181        } else {
 182                if (!xfs_buf_delwri_queue(bp, buffer_list))
 183                        rval = XFS_ITEM_FLUSHING;
 184                xfs_buf_relse(bp);
 185        }
 186
 187        spin_lock(&lip->li_ailp->xa_lock);
 188out_unlock:
 189        xfs_dqunlock(dqp);
 190        return rval;
 191}
 192
 193/*
 194 * Unlock the dquot associated with the log item.
 195 * Clear the fields of the dquot and dquot log item that
 196 * are specific to the current transaction.  If the
 197 * hold flags is set, do not unlock the dquot.
 198 */
 199STATIC void
 200xfs_qm_dquot_logitem_unlock(
 201        struct xfs_log_item     *lip)
 202{
 203        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
 204
 205        ASSERT(XFS_DQ_IS_LOCKED(dqp));
 206
 207        /*
 208         * Clear the transaction pointer in the dquot
 209         */
 210        dqp->q_transp = NULL;
 211
 212        /*
 213         * dquots are never 'held' from getting unlocked at the end of
 214         * a transaction.  Their locking and unlocking is hidden inside the
 215         * transaction layer, within trans_commit. Hence, no LI_HOLD flag
 216         * for the logitem.
 217         */
 218        xfs_dqunlock(dqp);
 219}
 220
 221/*
 222 * this needs to stamp an lsn into the dquot, I think.
 223 * rpc's that look at user dquot's would then have to
 224 * push on the dependency recorded in the dquot
 225 */
 226STATIC void
 227xfs_qm_dquot_logitem_committing(
 228        struct xfs_log_item     *lip,
 229        xfs_lsn_t               lsn)
 230{
 231}
 232
 233/*
 234 * This is the ops vector for dquots
 235 */
 236static const struct xfs_item_ops xfs_dquot_item_ops = {
 237        .iop_size       = xfs_qm_dquot_logitem_size,
 238        .iop_format     = xfs_qm_dquot_logitem_format,
 239        .iop_pin        = xfs_qm_dquot_logitem_pin,
 240        .iop_unpin      = xfs_qm_dquot_logitem_unpin,
 241        .iop_unlock     = xfs_qm_dquot_logitem_unlock,
 242        .iop_committed  = xfs_qm_dquot_logitem_committed,
 243        .iop_push       = xfs_qm_dquot_logitem_push,
 244        .iop_committing = xfs_qm_dquot_logitem_committing
 245};
 246
 247/*
 248 * Initialize the dquot log item for a newly allocated dquot.
 249 * The dquot isn't locked at this point, but it isn't on any of the lists
 250 * either, so we don't care.
 251 */
 252void
 253xfs_qm_dquot_logitem_init(
 254        struct xfs_dquot        *dqp)
 255{
 256        struct xfs_dq_logitem   *lp = &dqp->q_logitem;
 257
 258        xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT,
 259                                        &xfs_dquot_item_ops);
 260        lp->qli_dquot = dqp;
 261        lp->qli_format.qlf_type = XFS_LI_DQUOT;
 262        lp->qli_format.qlf_id = be32_to_cpu(dqp->q_core.d_id);
 263        lp->qli_format.qlf_blkno = dqp->q_blkno;
 264        lp->qli_format.qlf_len = 1;
 265        /*
 266         * This is just the offset of this dquot within its buffer
 267         * (which is currently 1 FSB and probably won't change).
 268         * Hence 32 bits for this offset should be just fine.
 269         * Alternatively, we can store (bufoffset / sizeof(xfs_dqblk_t))
 270         * here, and recompute it at recovery time.
 271         */
 272        lp->qli_format.qlf_boffset = (__uint32_t)dqp->q_bufoffset;
 273}
 274
 275/*------------------  QUOTAOFF LOG ITEMS  -------------------*/
 276
 277static inline struct xfs_qoff_logitem *QOFF_ITEM(struct xfs_log_item *lip)
 278{
 279        return container_of(lip, struct xfs_qoff_logitem, qql_item);
 280}
 281
 282
 283/*
 284 * This returns the number of iovecs needed to log the given quotaoff item.
 285 * We only need 1 iovec for an quotaoff item.  It just logs the
 286 * quotaoff_log_format structure.
 287 */
 288STATIC uint
 289xfs_qm_qoff_logitem_size(
 290        struct xfs_log_item     *lip)
 291{
 292        return 1;
 293}
 294
 295/*
 296 * This is called to fill in the vector of log iovecs for the
 297 * given quotaoff log item. We use only 1 iovec, and we point that
 298 * at the quotaoff_log_format structure embedded in the quotaoff item.
 299 * It is at this point that we assert that all of the extent
 300 * slots in the quotaoff item have been filled.
 301 */
 302STATIC void
 303xfs_qm_qoff_logitem_format(
 304        struct xfs_log_item     *lip,
 305        struct xfs_log_iovec    *log_vector)
 306{
 307        struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip);
 308
 309        ASSERT(qflip->qql_format.qf_type == XFS_LI_QUOTAOFF);
 310
 311        log_vector->i_addr = &qflip->qql_format;
 312        log_vector->i_len = sizeof(xfs_qoff_logitem_t);
 313        log_vector->i_type = XLOG_REG_TYPE_QUOTAOFF;
 314        qflip->qql_format.qf_size = 1;
 315}
 316
 317/*
 318 * Pinning has no meaning for an quotaoff item, so just return.
 319 */
 320STATIC void
 321xfs_qm_qoff_logitem_pin(
 322        struct xfs_log_item     *lip)
 323{
 324}
 325
 326/*
 327 * Since pinning has no meaning for an quotaoff item, unpinning does
 328 * not either.
 329 */
 330STATIC void
 331xfs_qm_qoff_logitem_unpin(
 332        struct xfs_log_item     *lip,
 333        int                     remove)
 334{
 335}
 336
 337/*
 338 * There isn't much you can do to push a quotaoff item.  It is simply
 339 * stuck waiting for the log to be flushed to disk.
 340 */
 341STATIC uint
 342xfs_qm_qoff_logitem_push(
 343        struct xfs_log_item     *lip,
 344        struct list_head        *buffer_list)
 345{
 346        return XFS_ITEM_LOCKED;
 347}
 348
 349/*
 350 * Quotaoff items have no locking or pushing, so return failure
 351 * so that the caller doesn't bother with us.
 352 */
 353STATIC void
 354xfs_qm_qoff_logitem_unlock(
 355        struct xfs_log_item     *lip)
 356{
 357}
 358
 359/*
 360 * The quotaoff-start-item is logged only once and cannot be moved in the log,
 361 * so simply return the lsn at which it's been logged.
 362 */
 363STATIC xfs_lsn_t
 364xfs_qm_qoff_logitem_committed(
 365        struct xfs_log_item     *lip,
 366        xfs_lsn_t               lsn)
 367{
 368        return lsn;
 369}
 370
 371STATIC xfs_lsn_t
 372xfs_qm_qoffend_logitem_committed(
 373        struct xfs_log_item     *lip,
 374        xfs_lsn_t               lsn)
 375{
 376        struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip);
 377        struct xfs_qoff_logitem *qfs = qfe->qql_start_lip;
 378        struct xfs_ail          *ailp = qfs->qql_item.li_ailp;
 379
 380        /*
 381         * Delete the qoff-start logitem from the AIL.
 382         * xfs_trans_ail_delete() drops the AIL lock.
 383         */
 384        spin_lock(&ailp->xa_lock);
 385        xfs_trans_ail_delete(ailp, &qfs->qql_item, SHUTDOWN_LOG_IO_ERROR);
 386
 387        kmem_free(qfs);
 388        kmem_free(qfe);
 389        return (xfs_lsn_t)-1;
 390}
 391
 392/*
 393 * XXX rcc - don't know quite what to do with this.  I think we can
 394 * just ignore it.  The only time that isn't the case is if we allow
 395 * the client to somehow see that quotas have been turned off in which
 396 * we can't allow that to get back until the quotaoff hits the disk.
 397 * So how would that happen?  Also, do we need different routines for
 398 * quotaoff start and quotaoff end?  I suspect the answer is yes but
 399 * to be sure, I need to look at the recovery code and see how quota off
 400 * recovery is handled (do we roll forward or back or do something else).
 401 * If we roll forwards or backwards, then we need two separate routines,
 402 * one that does nothing and one that stamps in the lsn that matters
 403 * (truly makes the quotaoff irrevocable).  If we do something else,
 404 * then maybe we don't need two.
 405 */
 406STATIC void
 407xfs_qm_qoff_logitem_committing(
 408        struct xfs_log_item     *lip,
 409        xfs_lsn_t               commit_lsn)
 410{
 411}
 412
 413static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 414        .iop_size       = xfs_qm_qoff_logitem_size,
 415        .iop_format     = xfs_qm_qoff_logitem_format,
 416        .iop_pin        = xfs_qm_qoff_logitem_pin,
 417        .iop_unpin      = xfs_qm_qoff_logitem_unpin,
 418        .iop_unlock     = xfs_qm_qoff_logitem_unlock,
 419        .iop_committed  = xfs_qm_qoffend_logitem_committed,
 420        .iop_push       = xfs_qm_qoff_logitem_push,
 421        .iop_committing = xfs_qm_qoff_logitem_committing
 422};
 423
 424/*
 425 * This is the ops vector shared by all quotaoff-start log items.
 426 */
 427static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
 428        .iop_size       = xfs_qm_qoff_logitem_size,
 429        .iop_format     = xfs_qm_qoff_logitem_format,
 430        .iop_pin        = xfs_qm_qoff_logitem_pin,
 431        .iop_unpin      = xfs_qm_qoff_logitem_unpin,
 432        .iop_unlock     = xfs_qm_qoff_logitem_unlock,
 433        .iop_committed  = xfs_qm_qoff_logitem_committed,
 434        .iop_push       = xfs_qm_qoff_logitem_push,
 435        .iop_committing = xfs_qm_qoff_logitem_committing
 436};
 437
 438/*
 439 * Allocate and initialize an quotaoff item of the correct quota type(s).
 440 */
 441struct xfs_qoff_logitem *
 442xfs_qm_qoff_logitem_init(
 443        struct xfs_mount        *mp,
 444        struct xfs_qoff_logitem *start,
 445        uint                    flags)
 446{
 447        struct xfs_qoff_logitem *qf;
 448
 449        qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), KM_SLEEP);
 450
 451        xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ?
 452                        &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops);
 453        qf->qql_item.li_mountp = mp;
 454        qf->qql_format.qf_type = XFS_LI_QUOTAOFF;
 455        qf->qql_format.qf_flags = flags;
 456        qf->qql_start_lip = start;
 457        return qf;
 458}
 459
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.