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 : }