0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_quota.h"
0015 #include "xfs_trans.h"
0016 #include "xfs_buf_item.h"
0017 #include "xfs_trans_priv.h"
0018 #include "xfs_qm.h"
0019 #include "xfs_log.h"
0020
0021 static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip)
0022 {
0023 return container_of(lip, struct xfs_dq_logitem, qli_item);
0024 }
0025
0026
0027
0028
0029 STATIC void
0030 xfs_qm_dquot_logitem_size(
0031 struct xfs_log_item *lip,
0032 int *nvecs,
0033 int *nbytes)
0034 {
0035 *nvecs += 2;
0036 *nbytes += sizeof(struct xfs_dq_logformat) +
0037 sizeof(struct xfs_disk_dquot);
0038 }
0039
0040
0041
0042
0043 STATIC void
0044 xfs_qm_dquot_logitem_format(
0045 struct xfs_log_item *lip,
0046 struct xfs_log_vec *lv)
0047 {
0048 struct xfs_disk_dquot ddq;
0049 struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
0050 struct xfs_log_iovec *vecp = NULL;
0051 struct xfs_dq_logformat *qlf;
0052
0053 qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QFORMAT);
0054 qlf->qlf_type = XFS_LI_DQUOT;
0055 qlf->qlf_size = 2;
0056 qlf->qlf_id = qlip->qli_dquot->q_id;
0057 qlf->qlf_blkno = qlip->qli_dquot->q_blkno;
0058 qlf->qlf_len = 1;
0059 qlf->qlf_boffset = qlip->qli_dquot->q_bufoffset;
0060 xlog_finish_iovec(lv, vecp, sizeof(struct xfs_dq_logformat));
0061
0062 xfs_dquot_to_disk(&ddq, qlip->qli_dquot);
0063
0064 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT, &ddq,
0065 sizeof(struct xfs_disk_dquot));
0066 }
0067
0068
0069
0070
0071 STATIC void
0072 xfs_qm_dquot_logitem_pin(
0073 struct xfs_log_item *lip)
0074 {
0075 struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
0076
0077 ASSERT(XFS_DQ_IS_LOCKED(dqp));
0078 atomic_inc(&dqp->q_pincount);
0079 }
0080
0081
0082
0083
0084
0085
0086
0087 STATIC void
0088 xfs_qm_dquot_logitem_unpin(
0089 struct xfs_log_item *lip,
0090 int remove)
0091 {
0092 struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
0093
0094 ASSERT(atomic_read(&dqp->q_pincount) > 0);
0095 if (atomic_dec_and_test(&dqp->q_pincount))
0096 wake_up(&dqp->q_pinwait);
0097 }
0098
0099
0100
0101
0102
0103 void
0104 xfs_qm_dqunpin_wait(
0105 struct xfs_dquot *dqp)
0106 {
0107 ASSERT(XFS_DQ_IS_LOCKED(dqp));
0108 if (atomic_read(&dqp->q_pincount) == 0)
0109 return;
0110
0111
0112
0113
0114 xfs_log_force(dqp->q_mount, 0);
0115 wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
0116 }
0117
0118 STATIC uint
0119 xfs_qm_dquot_logitem_push(
0120 struct xfs_log_item *lip,
0121 struct list_head *buffer_list)
0122 __releases(&lip->li_ailp->ail_lock)
0123 __acquires(&lip->li_ailp->ail_lock)
0124 {
0125 struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
0126 struct xfs_buf *bp = lip->li_buf;
0127 uint rval = XFS_ITEM_SUCCESS;
0128 int error;
0129
0130 if (atomic_read(&dqp->q_pincount) > 0)
0131 return XFS_ITEM_PINNED;
0132
0133 if (!xfs_dqlock_nowait(dqp))
0134 return XFS_ITEM_LOCKED;
0135
0136
0137
0138
0139
0140 if (atomic_read(&dqp->q_pincount) > 0) {
0141 rval = XFS_ITEM_PINNED;
0142 goto out_unlock;
0143 }
0144
0145
0146
0147
0148
0149
0150 if (!xfs_dqflock_nowait(dqp)) {
0151 rval = XFS_ITEM_FLUSHING;
0152 goto out_unlock;
0153 }
0154
0155 spin_unlock(&lip->li_ailp->ail_lock);
0156
0157 error = xfs_qm_dqflush(dqp, &bp);
0158 if (!error) {
0159 if (!xfs_buf_delwri_queue(bp, buffer_list))
0160 rval = XFS_ITEM_FLUSHING;
0161 xfs_buf_relse(bp);
0162 } else if (error == -EAGAIN)
0163 rval = XFS_ITEM_LOCKED;
0164
0165 spin_lock(&lip->li_ailp->ail_lock);
0166 out_unlock:
0167 xfs_dqunlock(dqp);
0168 return rval;
0169 }
0170
0171 STATIC void
0172 xfs_qm_dquot_logitem_release(
0173 struct xfs_log_item *lip)
0174 {
0175 struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
0176
0177 ASSERT(XFS_DQ_IS_LOCKED(dqp));
0178
0179
0180
0181
0182
0183
0184
0185 xfs_dqunlock(dqp);
0186 }
0187
0188 STATIC void
0189 xfs_qm_dquot_logitem_committing(
0190 struct xfs_log_item *lip,
0191 xfs_csn_t seq)
0192 {
0193 return xfs_qm_dquot_logitem_release(lip);
0194 }
0195
0196 static const struct xfs_item_ops xfs_dquot_item_ops = {
0197 .iop_size = xfs_qm_dquot_logitem_size,
0198 .iop_format = xfs_qm_dquot_logitem_format,
0199 .iop_pin = xfs_qm_dquot_logitem_pin,
0200 .iop_unpin = xfs_qm_dquot_logitem_unpin,
0201 .iop_release = xfs_qm_dquot_logitem_release,
0202 .iop_committing = xfs_qm_dquot_logitem_committing,
0203 .iop_push = xfs_qm_dquot_logitem_push,
0204 };
0205
0206
0207
0208
0209
0210
0211 void
0212 xfs_qm_dquot_logitem_init(
0213 struct xfs_dquot *dqp)
0214 {
0215 struct xfs_dq_logitem *lp = &dqp->q_logitem;
0216
0217 xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT,
0218 &xfs_dquot_item_ops);
0219 lp->qli_dquot = dqp;
0220 }