linux/fs/xfs/xfs_dquot_item.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2000-2003 Silicon Graphics, Inc.
   4 * All Rights Reserved.
   5 */
   6#include "xfs.h"
   7#include "xfs_fs.h"
   8#include "xfs_shared.h"
   9#include "xfs_format.h"
  10#include "xfs_log_format.h"
  11#include "xfs_trans_resv.h"
  12#include "xfs_mount.h"
  13#include "xfs_inode.h"
  14#include "xfs_quota.h"
  15#include "xfs_trans.h"
  16#include "xfs_buf_item.h"
  17#include "xfs_trans_priv.h"
  18#include "xfs_qm.h"
  19#include "xfs_log.h"
  20
  21static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip)
  22{
  23        return container_of(lip, struct xfs_dq_logitem, qli_item);
  24}
  25
  26/*
  27 * returns the number of iovecs needed to log the given dquot item.
  28 */
  29STATIC void
  30xfs_qm_dquot_logitem_size(
  31        struct xfs_log_item     *lip,
  32        int                     *nvecs,
  33        int                     *nbytes)
  34{
  35        *nvecs += 2;
  36        *nbytes += sizeof(struct xfs_dq_logformat) +
  37                   sizeof(struct xfs_disk_dquot);
  38}
  39
  40/*
  41 * fills in the vector of log iovecs for the given dquot log item.
  42 */
  43STATIC void
  44xfs_qm_dquot_logitem_format(
  45        struct xfs_log_item     *lip,
  46        struct xfs_log_vec      *lv)
  47{
  48        struct xfs_dq_logitem   *qlip = DQUOT_ITEM(lip);
  49        struct xfs_log_iovec    *vecp = NULL;
  50        struct xfs_dq_logformat *qlf;
  51
  52        qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QFORMAT);
  53        qlf->qlf_type = XFS_LI_DQUOT;
  54        qlf->qlf_size = 2;
  55        qlf->qlf_id = be32_to_cpu(qlip->qli_dquot->q_core.d_id);
  56        qlf->qlf_blkno = qlip->qli_dquot->q_blkno;
  57        qlf->qlf_len = 1;
  58        qlf->qlf_boffset = qlip->qli_dquot->q_bufoffset;
  59        xlog_finish_iovec(lv, vecp, sizeof(struct xfs_dq_logformat));
  60
  61        xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT,
  62                        &qlip->qli_dquot->q_core,
  63                        sizeof(struct xfs_disk_dquot));
  64}
  65
  66/*
  67 * Increment the pin count of the given dquot.
  68 */
  69STATIC void
  70xfs_qm_dquot_logitem_pin(
  71        struct xfs_log_item     *lip)
  72{
  73        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
  74
  75        ASSERT(XFS_DQ_IS_LOCKED(dqp));
  76        atomic_inc(&dqp->q_pincount);
  77}
  78
  79/*
  80 * Decrement the pin count of the given dquot, and wake up
  81 * anyone in xfs_dqwait_unpin() if the count goes to 0.  The
  82 * dquot must have been previously pinned with a call to
  83 * xfs_qm_dquot_logitem_pin().
  84 */
  85STATIC void
  86xfs_qm_dquot_logitem_unpin(
  87        struct xfs_log_item     *lip,
  88        int                     remove)
  89{
  90        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
  91
  92        ASSERT(atomic_read(&dqp->q_pincount) > 0);
  93        if (atomic_dec_and_test(&dqp->q_pincount))
  94                wake_up(&dqp->q_pinwait);
  95}
  96
  97/*
  98 * This is called to wait for the given dquot to be unpinned.
  99 * Most of these pin/unpin routines are plagiarized from inode code.
 100 */
 101void
 102xfs_qm_dqunpin_wait(
 103        struct xfs_dquot        *dqp)
 104{
 105        ASSERT(XFS_DQ_IS_LOCKED(dqp));
 106        if (atomic_read(&dqp->q_pincount) == 0)
 107                return;
 108
 109        /*
 110         * Give the log a push so we don't wait here too long.
 111         */
 112        xfs_log_force(dqp->q_mount, 0);
 113        wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
 114}
 115
 116/*
 117 * Callback used to mark a buffer with XFS_LI_FAILED when items in the buffer
 118 * have been failed during writeback
 119 *
 120 * this informs the AIL that the dquot is already flush locked on the next push,
 121 * and acquires a hold on the buffer to ensure that it isn't reclaimed before
 122 * dirty data makes it to disk.
 123 */
 124STATIC void
 125xfs_dquot_item_error(
 126        struct xfs_log_item     *lip,
 127        struct xfs_buf          *bp)
 128{
 129        ASSERT(!completion_done(&DQUOT_ITEM(lip)->qli_dquot->q_flush));
 130        xfs_set_li_failed(lip, bp);
 131}
 132
 133STATIC uint
 134xfs_qm_dquot_logitem_push(
 135        struct xfs_log_item     *lip,
 136        struct list_head        *buffer_list)
 137                __releases(&lip->li_ailp->ail_lock)
 138                __acquires(&lip->li_ailp->ail_lock)
 139{
 140        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
 141        struct xfs_buf          *bp = lip->li_buf;
 142        uint                    rval = XFS_ITEM_SUCCESS;
 143        int                     error;
 144
 145        if (atomic_read(&dqp->q_pincount) > 0)
 146                return XFS_ITEM_PINNED;
 147
 148        /*
 149         * The buffer containing this item failed to be written back
 150         * previously. Resubmit the buffer for IO
 151         */
 152        if (test_bit(XFS_LI_FAILED, &lip->li_flags)) {
 153                if (!xfs_buf_trylock(bp))
 154                        return XFS_ITEM_LOCKED;
 155
 156                if (!xfs_buf_resubmit_failed_buffers(bp, buffer_list))
 157                        rval = XFS_ITEM_FLUSHING;
 158
 159                xfs_buf_unlock(bp);
 160                return rval;
 161        }
 162
 163        if (!xfs_dqlock_nowait(dqp))
 164                return XFS_ITEM_LOCKED;
 165
 166        /*
 167         * Re-check the pincount now that we stabilized the value by
 168         * taking the quota lock.
 169         */
 170        if (atomic_read(&dqp->q_pincount) > 0) {
 171                rval = XFS_ITEM_PINNED;
 172                goto out_unlock;
 173        }
 174
 175        /*
 176         * Someone else is already flushing the dquot.  Nothing we can do
 177         * here but wait for the flush to finish and remove the item from
 178         * the AIL.
 179         */
 180        if (!xfs_dqflock_nowait(dqp)) {
 181                rval = XFS_ITEM_FLUSHING;
 182                goto out_unlock;
 183        }
 184
 185        spin_unlock(&lip->li_ailp->ail_lock);
 186
 187        error = xfs_qm_dqflush(dqp, &bp);
 188        if (!error) {
 189                if (!xfs_buf_delwri_queue(bp, buffer_list))
 190                        rval = XFS_ITEM_FLUSHING;
 191                xfs_buf_relse(bp);
 192        }
 193
 194        spin_lock(&lip->li_ailp->ail_lock);
 195out_unlock:
 196        xfs_dqunlock(dqp);
 197        return rval;
 198}
 199
 200STATIC void
 201xfs_qm_dquot_logitem_release(
 202        struct xfs_log_item     *lip)
 203{
 204        struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
 205
 206        ASSERT(XFS_DQ_IS_LOCKED(dqp));
 207
 208        /*
 209         * dquots are never 'held' from getting unlocked at the end of
 210         * a transaction.  Their locking and unlocking is hidden inside the
 211         * transaction layer, within trans_commit. Hence, no LI_HOLD flag
 212         * for the logitem.
 213         */
 214        xfs_dqunlock(dqp);
 215}
 216
 217STATIC void
 218xfs_qm_dquot_logitem_committing(
 219        struct xfs_log_item     *lip,
 220        xfs_lsn_t               commit_lsn)
 221{
 222        return xfs_qm_dquot_logitem_release(lip);
 223}
 224
 225static const struct xfs_item_ops xfs_dquot_item_ops = {
 226        .iop_size       = xfs_qm_dquot_logitem_size,
 227        .iop_format     = xfs_qm_dquot_logitem_format,
 228        .iop_pin        = xfs_qm_dquot_logitem_pin,
 229        .iop_unpin      = xfs_qm_dquot_logitem_unpin,
 230        .iop_release    = xfs_qm_dquot_logitem_release,
 231        .iop_committing = xfs_qm_dquot_logitem_committing,
 232        .iop_push       = xfs_qm_dquot_logitem_push,
 233        .iop_error      = xfs_dquot_item_error
 234};
 235
 236/*
 237 * Initialize the dquot log item for a newly allocated dquot.
 238 * The dquot isn't locked at this point, but it isn't on any of the lists
 239 * either, so we don't care.
 240 */
 241void
 242xfs_qm_dquot_logitem_init(
 243        struct xfs_dquot        *dqp)
 244{
 245        struct xfs_dq_logitem   *lp = &dqp->q_logitem;
 246
 247        xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT,
 248                                        &xfs_dquot_item_ops);
 249        lp->qli_dquot = dqp;
 250}
 251
 252/*------------------  QUOTAOFF LOG ITEMS  -------------------*/
 253
 254static inline struct xfs_qoff_logitem *QOFF_ITEM(struct xfs_log_item *lip)
 255{
 256        return container_of(lip, struct xfs_qoff_logitem, qql_item);
 257}
 258
 259
 260/*
 261 * This returns the number of iovecs needed to log the given quotaoff item.
 262 * We only need 1 iovec for an quotaoff item.  It just logs the
 263 * quotaoff_log_format structure.
 264 */
 265STATIC void
 266xfs_qm_qoff_logitem_size(
 267        struct xfs_log_item     *lip,
 268        int                     *nvecs,
 269        int                     *nbytes)
 270{
 271        *nvecs += 1;
 272        *nbytes += sizeof(struct xfs_qoff_logitem);
 273}
 274
 275STATIC void
 276xfs_qm_qoff_logitem_format(
 277        struct xfs_log_item     *lip,
 278        struct xfs_log_vec      *lv)
 279{
 280        struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip);
 281        struct xfs_log_iovec    *vecp = NULL;
 282        struct xfs_qoff_logformat *qlf;
 283
 284        qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QUOTAOFF);
 285        qlf->qf_type = XFS_LI_QUOTAOFF;
 286        qlf->qf_size = 1;
 287        qlf->qf_flags = qflip->qql_flags;
 288        xlog_finish_iovec(lv, vecp, sizeof(struct xfs_qoff_logitem));
 289}
 290
 291/*
 292 * There isn't much you can do to push a quotaoff item.  It is simply
 293 * stuck waiting for the log to be flushed to disk.
 294 */
 295STATIC uint
 296xfs_qm_qoff_logitem_push(
 297        struct xfs_log_item     *lip,
 298        struct list_head        *buffer_list)
 299{
 300        return XFS_ITEM_LOCKED;
 301}
 302
 303STATIC xfs_lsn_t
 304xfs_qm_qoffend_logitem_committed(
 305        struct xfs_log_item     *lip,
 306        xfs_lsn_t               lsn)
 307{
 308        struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip);
 309        struct xfs_qoff_logitem *qfs = qfe->qql_start_lip;
 310
 311        xfs_qm_qoff_logitem_relse(qfs);
 312
 313        kmem_free(lip->li_lv_shadow);
 314        kmem_free(qfe);
 315        return (xfs_lsn_t)-1;
 316}
 317
 318STATIC void
 319xfs_qm_qoff_logitem_release(
 320        struct xfs_log_item     *lip)
 321{
 322        struct xfs_qoff_logitem *qoff = QOFF_ITEM(lip);
 323
 324        if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) {
 325                if (qoff->qql_start_lip)
 326                        xfs_qm_qoff_logitem_relse(qoff->qql_start_lip);
 327                xfs_qm_qoff_logitem_relse(qoff);
 328        }
 329}
 330
 331static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 332        .iop_size       = xfs_qm_qoff_logitem_size,
 333        .iop_format     = xfs_qm_qoff_logitem_format,
 334        .iop_committed  = xfs_qm_qoffend_logitem_committed,
 335        .iop_push       = xfs_qm_qoff_logitem_push,
 336        .iop_release    = xfs_qm_qoff_logitem_release,
 337};
 338
 339static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
 340        .iop_size       = xfs_qm_qoff_logitem_size,
 341        .iop_format     = xfs_qm_qoff_logitem_format,
 342        .iop_push       = xfs_qm_qoff_logitem_push,
 343        .iop_release    = xfs_qm_qoff_logitem_release,
 344};
 345
 346/*
 347 * Delete the quotaoff intent from the AIL and free it. On success,
 348 * this should only be called for the start item. It can be used for
 349 * either on shutdown or abort.
 350 */
 351void
 352xfs_qm_qoff_logitem_relse(
 353        struct xfs_qoff_logitem *qoff)
 354{
 355        struct xfs_log_item     *lip = &qoff->qql_item;
 356
 357        ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags) ||
 358               test_bit(XFS_LI_ABORTED, &lip->li_flags) ||
 359               XFS_FORCED_SHUTDOWN(lip->li_mountp));
 360        xfs_trans_ail_remove(lip, SHUTDOWN_LOG_IO_ERROR);
 361        kmem_free(lip->li_lv_shadow);
 362        kmem_free(qoff);
 363}
 364
 365/*
 366 * Allocate and initialize an quotaoff item of the correct quota type(s).
 367 */
 368struct xfs_qoff_logitem *
 369xfs_qm_qoff_logitem_init(
 370        struct xfs_mount        *mp,
 371        struct xfs_qoff_logitem *start,
 372        uint                    flags)
 373{
 374        struct xfs_qoff_logitem *qf;
 375
 376        qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), 0);
 377
 378        xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ?
 379                        &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops);
 380        qf->qql_item.li_mountp = mp;
 381        qf->qql_start_lip = start;
 382        qf->qql_flags = flags;
 383        return qf;
 384}
 385