1
2
3
4
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
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
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
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
81
82
83
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
99
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
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
118
119
120
121
122
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
150
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
168
169
170 if (atomic_read(&dqp->q_pincount) > 0) {
171 rval = XFS_ITEM_PINNED;
172 goto out_unlock;
173 }
174
175
176
177
178
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
210
211
212
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
238
239
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
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
262
263
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
293
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
348
349
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
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