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_format.h"
  21#include "xfs_log_format.h"
  22#include "xfs_trans_resv.h"
  23#include "xfs_mount.h"
  24#include "xfs_inode.h"
  25#include "xfs_quota.h"
  26#include "xfs_error.h"
  27#include "xfs_trans.h"
  28#include "xfs_buf_item.h"
  29#include "xfs_trans_priv.h"
  30#include "xfs_qm.h"
  31#include "xfs_log.h"
  32
  33static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip)
  34{
  35        return container_of(lip, struct xfs_dq_logitem, qli_item);
  36}
  37
  38/*
  39 * returns the number of iovecs needed to log the given dquot item.
  40 */
  41STATIC void
  42xfs_qm_dquot_logitem_size(
  43        struct xfs_log_item     *lip,
  44        int                     *nvecs,
  45        int                     *nbytes)
  46{
  47        *nvecs += 2;
  48        *nbytes += sizeof(struct xfs_dq_logformat) +
  49                   sizeof(struct xfs_disk_dquot);
  50}
  51
  52/*
  53 * fills in the vector of log iovecs for the given dquot log item.
  54 */
  55STATIC void
  56xfs_qm_dquot_logitem_format(
  57        struct xfs_log_item     *lip,
  58        struct xfs_log_vec      *lv)
  59{
  60        struct xfs_dq_logitem   *qlip = DQUOT_ITEM(lip);
  61        struct xfs_log_iovec    *vecp = NULL;
  62        struct xfs_dq_logformat *qlf;
  63
  64        qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QFORMAT);
  65        qlf->qlf_type = XFS_LI_DQUOT;
  66        qlf->qlf_size = 2;
  67        qlf->qlf_id = be32_to_cpu(qlip->qli_dquot->q_core.d_id);
  68        qlf->qlf_blkno = qlip->qli_dquot->q_blkno;
  69        qlf->qlf_len = 1;
  70        qlf->qlf_boffset = qlip->qli_dquot->q_bufoffset;
  71        xlog_finish_iovec(lv, vecp, sizeof(struct xfs_dq_logformat));
  72
  73        xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT,
  74                        &qlip->qli_dquot->q_core,
  75                        sizeof(struct xfs_disk_dquot));
  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
 140/*
 141 * Callback used to mark a buffer with XFS_LI_FAILED when items in the buffer
 142 * have been failed during writeback
 143 *
 144 * this informs the AIL that the dquot is already flush locked on the next push,
 145 * and acquires a hold on the buffer to ensure that it isn't reclaimed before
 146 * dirty data makes it to disk.
 147 */
 148STATIC void
 149xfs_dquot_item_error(
 150        struct xfs_log_item     *lip,
 151        struct xfs_buf          *bp)
 152{
 153        ASSERT(!completion_done(&DQUOT_ITEM(lip)->qli_dquot->q_flush));
 154        xfs_set_li_failed(lip, bp);
 155}
 156
 157STATIC uint
 158xfs_qm_dquot_logitem_push(
 159        struct xfs_log_item     *lip,
 160        struct list_head        *buffer_list) __releases(&lip->li_ailp->xa_lock)
 161                                              __acquires(&lip->li_ailp->xa_lock)
 162{
 163        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
 164        struct xfs_buf          *bp = lip->li_buf;
 165        uint                    rval = XFS_ITEM_SUCCESS;
 166        int                     error;
 167
 168        if (atomic_read(&dqp->q_pincount) > 0)
 169                return XFS_ITEM_PINNED;
 170
 171        /*
 172         * The buffer containing this item failed to be written back
 173         * previously. Resubmit the buffer for IO
 174         */
 175        if (test_bit(XFS_LI_FAILED, &lip->li_flags)) {
 176                if (!xfs_buf_trylock(bp))
 177                        return XFS_ITEM_LOCKED;
 178
 179                if (!xfs_buf_resubmit_failed_buffers(bp, lip, buffer_list))
 180                        rval = XFS_ITEM_FLUSHING;
 181
 182                xfs_buf_unlock(bp);
 183                return rval;
 184        }
 185
 186        if (!xfs_dqlock_nowait(dqp))
 187                return XFS_ITEM_LOCKED;
 188
 189        /*
 190         * Re-check the pincount now that we stabilized the value by
 191         * taking the quota lock.
 192         */
 193        if (atomic_read(&dqp->q_pincount) > 0) {
 194                rval = XFS_ITEM_PINNED;
 195                goto out_unlock;
 196        }
 197
 198        /*
 199         * Someone else is already flushing the dquot.  Nothing we can do
 200         * here but wait for the flush to finish and remove the item from
 201         * the AIL.
 202         */
 203        if (!xfs_dqflock_nowait(dqp)) {
 204                rval = XFS_ITEM_FLUSHING;
 205                goto out_unlock;
 206        }
 207
 208        spin_unlock(&lip->li_ailp->xa_lock);
 209
 210        error = xfs_qm_dqflush(dqp, &bp);
 211        if (error) {
 212                xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p",
 213                        __func__, error, dqp);
 214        } else {
 215                if (!xfs_buf_delwri_queue(bp, buffer_list))
 216                        rval = XFS_ITEM_FLUSHING;
 217                xfs_buf_relse(bp);
 218        }
 219
 220        spin_lock(&lip->li_ailp->xa_lock);
 221out_unlock:
 222        xfs_dqunlock(dqp);
 223        return rval;
 224}
 225
 226/*
 227 * Unlock the dquot associated with the log item.
 228 * Clear the fields of the dquot and dquot log item that
 229 * are specific to the current transaction.  If the
 230 * hold flags is set, do not unlock the dquot.
 231 */
 232STATIC void
 233xfs_qm_dquot_logitem_unlock(
 234        struct xfs_log_item     *lip)
 235{
 236        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
 237
 238        ASSERT(XFS_DQ_IS_LOCKED(dqp));
 239
 240        /*
 241         * Clear the transaction pointer in the dquot
 242         */
 243        dqp->q_transp = NULL;
 244
 245        /*
 246         * dquots are never 'held' from getting unlocked at the end of
 247         * a transaction.  Their locking and unlocking is hidden inside the
 248         * transaction layer, within trans_commit. Hence, no LI_HOLD flag
 249         * for the logitem.
 250         */
 251        xfs_dqunlock(dqp);
 252}
 253
 254/*
 255 * this needs to stamp an lsn into the dquot, I think.
 256 * rpc's that look at user dquot's would then have to
 257 * push on the dependency recorded in the dquot
 258 */
 259STATIC void
 260xfs_qm_dquot_logitem_committing(
 261        struct xfs_log_item     *lip,
 262        xfs_lsn_t               lsn)
 263{
 264}
 265
 266/*
 267 * This is the ops vector for dquots
 268 */
 269static const struct xfs_item_ops xfs_dquot_item_ops = {
 270        .iop_size       = xfs_qm_dquot_logitem_size,
 271        .iop_format     = xfs_qm_dquot_logitem_format,
 272        .iop_pin        = xfs_qm_dquot_logitem_pin,
 273        .iop_unpin      = xfs_qm_dquot_logitem_unpin,
 274        .iop_unlock     = xfs_qm_dquot_logitem_unlock,
 275        .iop_committed  = xfs_qm_dquot_logitem_committed,
 276        .iop_push       = xfs_qm_dquot_logitem_push,
 277        .iop_committing = xfs_qm_dquot_logitem_committing,
 278        .iop_error      = xfs_dquot_item_error
 279};
 280
 281/*
 282 * Initialize the dquot log item for a newly allocated dquot.
 283 * The dquot isn't locked at this point, but it isn't on any of the lists
 284 * either, so we don't care.
 285 */
 286void
 287xfs_qm_dquot_logitem_init(
 288        struct xfs_dquot        *dqp)
 289{
 290        struct xfs_dq_logitem   *lp = &dqp->q_logitem;
 291
 292        xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT,
 293                                        &xfs_dquot_item_ops);
 294        lp->qli_dquot = dqp;
 295}
 296
 297/*------------------  QUOTAOFF LOG ITEMS  -------------------*/
 298
 299static inline struct xfs_qoff_logitem *QOFF_ITEM(struct xfs_log_item *lip)
 300{
 301        return container_of(lip, struct xfs_qoff_logitem, qql_item);
 302}
 303
 304
 305/*
 306 * This returns the number of iovecs needed to log the given quotaoff item.
 307 * We only need 1 iovec for an quotaoff item.  It just logs the
 308 * quotaoff_log_format structure.
 309 */
 310STATIC void
 311xfs_qm_qoff_logitem_size(
 312        struct xfs_log_item     *lip,
 313        int                     *nvecs,
 314        int                     *nbytes)
 315{
 316        *nvecs += 1;
 317        *nbytes += sizeof(struct xfs_qoff_logitem);
 318}
 319
 320STATIC void
 321xfs_qm_qoff_logitem_format(
 322        struct xfs_log_item     *lip,
 323        struct xfs_log_vec      *lv)
 324{
 325        struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip);
 326        struct xfs_log_iovec    *vecp = NULL;
 327        struct xfs_qoff_logformat *qlf;
 328
 329        qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QUOTAOFF);
 330        qlf->qf_type = XFS_LI_QUOTAOFF;
 331        qlf->qf_size = 1;
 332        qlf->qf_flags = qflip->qql_flags;
 333        xlog_finish_iovec(lv, vecp, sizeof(struct xfs_qoff_logitem));
 334}
 335
 336/*
 337 * Pinning has no meaning for an quotaoff item, so just return.
 338 */
 339STATIC void
 340xfs_qm_qoff_logitem_pin(
 341        struct xfs_log_item     *lip)
 342{
 343}
 344
 345/*
 346 * Since pinning has no meaning for an quotaoff item, unpinning does
 347 * not either.
 348 */
 349STATIC void
 350xfs_qm_qoff_logitem_unpin(
 351        struct xfs_log_item     *lip,
 352        int                     remove)
 353{
 354}
 355
 356/*
 357 * There isn't much you can do to push a quotaoff item.  It is simply
 358 * stuck waiting for the log to be flushed to disk.
 359 */
 360STATIC uint
 361xfs_qm_qoff_logitem_push(
 362        struct xfs_log_item     *lip,
 363        struct list_head        *buffer_list)
 364{
 365        return XFS_ITEM_LOCKED;
 366}
 367
 368/*
 369 * Quotaoff items have no locking or pushing, so return failure
 370 * so that the caller doesn't bother with us.
 371 */
 372STATIC void
 373xfs_qm_qoff_logitem_unlock(
 374        struct xfs_log_item     *lip)
 375{
 376}
 377
 378/*
 379 * The quotaoff-start-item is logged only once and cannot be moved in the log,
 380 * so simply return the lsn at which it's been logged.
 381 */
 382STATIC xfs_lsn_t
 383xfs_qm_qoff_logitem_committed(
 384        struct xfs_log_item     *lip,
 385        xfs_lsn_t               lsn)
 386{
 387        return lsn;
 388}
 389
 390STATIC xfs_lsn_t
 391xfs_qm_qoffend_logitem_committed(
 392        struct xfs_log_item     *lip,
 393        xfs_lsn_t               lsn)
 394{
 395        struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip);
 396        struct xfs_qoff_logitem *qfs = qfe->qql_start_lip;
 397        struct xfs_ail          *ailp = qfs->qql_item.li_ailp;
 398
 399        /*
 400         * Delete the qoff-start logitem from the AIL.
 401         * xfs_trans_ail_delete() drops the AIL lock.
 402         */
 403        spin_lock(&ailp->xa_lock);
 404        xfs_trans_ail_delete(ailp, &qfs->qql_item, SHUTDOWN_LOG_IO_ERROR);
 405
 406        kmem_free(qfs->qql_item.li_lv_shadow);
 407        kmem_free(lip->li_lv_shadow);
 408        kmem_free(qfs);
 409        kmem_free(qfe);
 410        return (xfs_lsn_t)-1;
 411}
 412
 413/*
 414 * XXX rcc - don't know quite what to do with this.  I think we can
 415 * just ignore it.  The only time that isn't the case is if we allow
 416 * the client to somehow see that quotas have been turned off in which
 417 * we can't allow that to get back until the quotaoff hits the disk.
 418 * So how would that happen?  Also, do we need different routines for
 419 * quotaoff start and quotaoff end?  I suspect the answer is yes but
 420 * to be sure, I need to look at the recovery code and see how quota off
 421 * recovery is handled (do we roll forward or back or do something else).
 422 * If we roll forwards or backwards, then we need two separate routines,
 423 * one that does nothing and one that stamps in the lsn that matters
 424 * (truly makes the quotaoff irrevocable).  If we do something else,
 425 * then maybe we don't need two.
 426 */
 427STATIC void
 428xfs_qm_qoff_logitem_committing(
 429        struct xfs_log_item     *lip,
 430        xfs_lsn_t               commit_lsn)
 431{
 432}
 433
 434static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 435        .iop_size       = xfs_qm_qoff_logitem_size,
 436        .iop_format     = xfs_qm_qoff_logitem_format,
 437        .iop_pin        = xfs_qm_qoff_logitem_pin,
 438        .iop_unpin      = xfs_qm_qoff_logitem_unpin,
 439        .iop_unlock     = xfs_qm_qoff_logitem_unlock,
 440        .iop_committed  = xfs_qm_qoffend_logitem_committed,
 441        .iop_push       = xfs_qm_qoff_logitem_push,
 442        .iop_committing = xfs_qm_qoff_logitem_committing
 443};
 444
 445/*
 446 * This is the ops vector shared by all quotaoff-start log items.
 447 */
 448static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
 449        .iop_size       = xfs_qm_qoff_logitem_size,
 450        .iop_format     = xfs_qm_qoff_logitem_format,
 451        .iop_pin        = xfs_qm_qoff_logitem_pin,
 452        .iop_unpin      = xfs_qm_qoff_logitem_unpin,
 453        .iop_unlock     = xfs_qm_qoff_logitem_unlock,
 454        .iop_committed  = xfs_qm_qoff_logitem_committed,
 455        .iop_push       = xfs_qm_qoff_logitem_push,
 456        .iop_committing = xfs_qm_qoff_logitem_committing
 457};
 458
 459/*
 460 * Allocate and initialize an quotaoff item of the correct quota type(s).
 461 */
 462struct xfs_qoff_logitem *
 463xfs_qm_qoff_logitem_init(
 464        struct xfs_mount        *mp,
 465        struct xfs_qoff_logitem *start,
 466        uint                    flags)
 467{
 468        struct xfs_qoff_logitem *qf;
 469
 470        qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), KM_SLEEP);
 471
 472        xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ?
 473                        &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops);
 474        qf->qql_item.li_mountp = mp;
 475        qf->qql_start_lip = start;
 476        qf->qql_flags = flags;
 477        return qf;
 478}
 479