LCOV - code coverage report
Current view: top level - fs/xfs - xfs_dquot_item.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 71 73 97.3 %
Date: 2023-07-31 20:08:22 Functions: 9 9 100.0 %

          Line data    Source code
       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             : 
      21             : static 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             :  */
      29             : STATIC void
      30  2847349968 : xfs_qm_dquot_logitem_size(
      31             :         struct xfs_log_item     *lip,
      32             :         int                     *nvecs,
      33             :         int                     *nbytes)
      34             : {
      35  2847349968 :         *nvecs += 2;
      36  2847349968 :         *nbytes += sizeof(struct xfs_dq_logformat) +
      37             :                    sizeof(struct xfs_disk_dquot);
      38  2847349968 : }
      39             : 
      40             : /*
      41             :  * fills in the vector of log iovecs for the given dquot log item.
      42             :  */
      43             : STATIC void
      44  2847359655 : xfs_qm_dquot_logitem_format(
      45             :         struct xfs_log_item     *lip,
      46             :         struct xfs_log_vec      *lv)
      47             : {
      48  2847359655 :         struct xfs_disk_dquot   ddq;
      49  2847359655 :         struct xfs_dq_logitem   *qlip = DQUOT_ITEM(lip);
      50  2847359655 :         struct xfs_log_iovec    *vecp = NULL;
      51  2847359655 :         struct xfs_dq_logformat *qlf;
      52             : 
      53  2847359655 :         qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QFORMAT);
      54  2847360447 :         qlf->qlf_type = XFS_LI_DQUOT;
      55  2847360447 :         qlf->qlf_size = 2;
      56  2847360447 :         qlf->qlf_id = qlip->qli_dquot->q_id;
      57  2847360447 :         qlf->qlf_blkno = qlip->qli_dquot->q_blkno;
      58  2847360447 :         qlf->qlf_len = 1;
      59  2847360447 :         qlf->qlf_boffset = qlip->qli_dquot->q_bufoffset;
      60  2847360447 :         xlog_finish_iovec(lv, vecp, sizeof(struct xfs_dq_logformat));
      61             : 
      62  2847349799 :         xfs_dquot_to_disk(&ddq, qlip->qli_dquot);
      63             : 
      64  2847356911 :         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT, &ddq,
      65             :                         sizeof(struct xfs_disk_dquot));
      66  2847365487 : }
      67             : 
      68             : /*
      69             :  * Increment the pin count of the given dquot.
      70             :  */
      71             : STATIC void
      72    36014519 : xfs_qm_dquot_logitem_pin(
      73             :         struct xfs_log_item     *lip)
      74             : {
      75    36014519 :         struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
      76             : 
      77    36014519 :         ASSERT(XFS_DQ_IS_LOCKED(dqp));
      78    36014536 :         atomic_inc(&dqp->q_pincount);
      79    36015029 : }
      80             : 
      81             : /*
      82             :  * Decrement the pin count of the given dquot, and wake up
      83             :  * anyone in xfs_dqwait_unpin() if the count goes to 0.  The
      84             :  * dquot must have been previously pinned with a call to
      85             :  * xfs_qm_dquot_logitem_pin().
      86             :  */
      87             : STATIC void
      88    36015408 : xfs_qm_dquot_logitem_unpin(
      89             :         struct xfs_log_item     *lip,
      90             :         int                     remove)
      91             : {
      92    36015408 :         struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
      93             : 
      94    36015408 :         ASSERT(atomic_read(&dqp->q_pincount) > 0);
      95    36015408 :         if (atomic_dec_and_test(&dqp->q_pincount))
      96    31982290 :                 wake_up(&dqp->q_pinwait);
      97    36015408 : }
      98             : 
      99             : /*
     100             :  * This is called to wait for the given dquot to be unpinned.
     101             :  * Most of these pin/unpin routines are plagiarized from inode code.
     102             :  */
     103             : void
     104    13112524 : xfs_qm_dqunpin_wait(
     105             :         struct xfs_dquot        *dqp)
     106             : {
     107    13112524 :         ASSERT(XFS_DQ_IS_LOCKED(dqp));
     108    13112524 :         if (atomic_read(&dqp->q_pincount) == 0)
     109             :                 return;
     110             : 
     111             :         /*
     112             :          * Give the log a push so we don't wait here too long.
     113             :          */
     114          55 :         xfs_log_force(dqp->q_mount, 0);
     115         109 :         wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
     116             : }
     117             : 
     118             : STATIC uint
     119    13233623 : xfs_qm_dquot_logitem_push(
     120             :         struct xfs_log_item     *lip,
     121             :         struct list_head        *buffer_list)
     122             :                 __releases(&lip->li_ailp->ail_lock)
     123             :                 __acquires(&lip->li_ailp->ail_lock)
     124             : {
     125    13233623 :         struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
     126    13233623 :         struct xfs_buf          *bp = lip->li_buf;
     127    13233623 :         uint                    rval = XFS_ITEM_SUCCESS;
     128    13233623 :         int                     error;
     129             : 
     130    13233623 :         if (atomic_read(&dqp->q_pincount) > 0)
     131             :                 return XFS_ITEM_PINNED;
     132             : 
     133    13069533 :         if (!xfs_dqlock_nowait(dqp))
     134             :                 return XFS_ITEM_LOCKED;
     135             : 
     136             :         /*
     137             :          * Re-check the pincount now that we stabilized the value by
     138             :          * taking the quota lock.
     139             :          */
     140    13069318 :         if (atomic_read(&dqp->q_pincount) > 0) {
     141           0 :                 rval = XFS_ITEM_PINNED;
     142           0 :                 goto out_unlock;
     143             :         }
     144             : 
     145             :         /*
     146             :          * Someone else is already flushing the dquot.  Nothing we can do
     147             :          * here but wait for the flush to finish and remove the item from
     148             :          * the AIL.
     149             :          */
     150    13069318 :         if (!xfs_dqflock_nowait(dqp)) {
     151       32257 :                 rval = XFS_ITEM_FLUSHING;
     152       32257 :                 goto out_unlock;
     153             :         }
     154             : 
     155    13037061 :         spin_unlock(&lip->li_ailp->ail_lock);
     156             : 
     157    13037061 :         error = xfs_qm_dqflush(dqp, &bp);
     158    13037061 :         if (!error) {
     159    11505294 :                 if (!xfs_buf_delwri_queue(bp, buffer_list))
     160     3539896 :                         rval = XFS_ITEM_FLUSHING;
     161    11505294 :                 xfs_buf_relse(bp);
     162     1531767 :         } else if (error == -EAGAIN)
     163        2404 :                 rval = XFS_ITEM_LOCKED;
     164             : 
     165    13037061 :         spin_lock(&lip->li_ailp->ail_lock);
     166    13069318 : out_unlock:
     167    13069318 :         xfs_dqunlock(dqp);
     168    13069318 :         return rval;
     169             : }
     170             : 
     171             : STATIC void
     172  2847360049 : xfs_qm_dquot_logitem_release(
     173             :         struct xfs_log_item     *lip)
     174             : {
     175  2847360049 :         struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
     176             : 
     177  2847360049 :         ASSERT(XFS_DQ_IS_LOCKED(dqp));
     178             : 
     179             :         /*
     180             :          * dquots are never 'held' from getting unlocked at the end of
     181             :          * a transaction.  Their locking and unlocking is hidden inside the
     182             :          * transaction layer, within trans_commit. Hence, no LI_HOLD flag
     183             :          * for the logitem.
     184             :          */
     185  2847359971 :         xfs_dqunlock(dqp);
     186  2847365455 : }
     187             : 
     188             : STATIC void
     189  2847360349 : xfs_qm_dquot_logitem_committing(
     190             :         struct xfs_log_item     *lip,
     191             :         xfs_csn_t               seq)
     192             : {
     193  2847360349 :         return xfs_qm_dquot_logitem_release(lip);
     194             : }
     195             : 
     196             : static const struct xfs_item_ops xfs_dquot_item_ops = {
     197             :         .iop_size       = xfs_qm_dquot_logitem_size,
     198             :         .iop_format     = xfs_qm_dquot_logitem_format,
     199             :         .iop_pin        = xfs_qm_dquot_logitem_pin,
     200             :         .iop_unpin      = xfs_qm_dquot_logitem_unpin,
     201             :         .iop_release    = xfs_qm_dquot_logitem_release,
     202             :         .iop_committing = xfs_qm_dquot_logitem_committing,
     203             :         .iop_push       = xfs_qm_dquot_logitem_push,
     204             : };
     205             : 
     206             : /*
     207             :  * Initialize the dquot log item for a newly allocated dquot.
     208             :  * The dquot isn't locked at this point, but it isn't on any of the lists
     209             :  * either, so we don't care.
     210             :  */
     211             : void
     212    14575428 : xfs_qm_dquot_logitem_init(
     213             :         struct xfs_dquot        *dqp)
     214             : {
     215    14575428 :         struct xfs_dq_logitem   *lp = &dqp->q_logitem;
     216             : 
     217    14575428 :         xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT,
     218             :                                         &xfs_dquot_item_ops);
     219    14575298 :         lp->qli_dquot = dqp;
     220    14575298 : }

Generated by: LCOV version 1.14