.. | .. |
---|
5 | 5 | */ |
---|
6 | 6 | #include "xfs.h" |
---|
7 | 7 | #include "xfs_fs.h" |
---|
| 8 | +#include "xfs_shared.h" |
---|
8 | 9 | #include "xfs_format.h" |
---|
9 | 10 | #include "xfs_log_format.h" |
---|
10 | 11 | #include "xfs_trans_resv.h" |
---|
11 | 12 | #include "xfs_mount.h" |
---|
12 | 13 | #include "xfs_inode.h" |
---|
13 | 14 | #include "xfs_quota.h" |
---|
14 | | -#include "xfs_error.h" |
---|
15 | 15 | #include "xfs_trans.h" |
---|
16 | 16 | #include "xfs_buf_item.h" |
---|
17 | 17 | #include "xfs_trans_priv.h" |
---|
.. | .. |
---|
45 | 45 | struct xfs_log_item *lip, |
---|
46 | 46 | struct xfs_log_vec *lv) |
---|
47 | 47 | { |
---|
| 48 | + struct xfs_disk_dquot ddq; |
---|
48 | 49 | struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); |
---|
49 | 50 | struct xfs_log_iovec *vecp = NULL; |
---|
50 | 51 | struct xfs_dq_logformat *qlf; |
---|
.. | .. |
---|
52 | 53 | qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QFORMAT); |
---|
53 | 54 | qlf->qlf_type = XFS_LI_DQUOT; |
---|
54 | 55 | qlf->qlf_size = 2; |
---|
55 | | - qlf->qlf_id = be32_to_cpu(qlip->qli_dquot->q_core.d_id); |
---|
| 56 | + qlf->qlf_id = qlip->qli_dquot->q_id; |
---|
56 | 57 | qlf->qlf_blkno = qlip->qli_dquot->q_blkno; |
---|
57 | 58 | qlf->qlf_len = 1; |
---|
58 | 59 | qlf->qlf_boffset = qlip->qli_dquot->q_bufoffset; |
---|
59 | 60 | xlog_finish_iovec(lv, vecp, sizeof(struct xfs_dq_logformat)); |
---|
60 | 61 | |
---|
61 | | - xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT, |
---|
62 | | - &qlip->qli_dquot->q_core, |
---|
| 62 | + xfs_dquot_to_disk(&ddq, qlip->qli_dquot); |
---|
| 63 | + |
---|
| 64 | + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT, &ddq, |
---|
63 | 65 | sizeof(struct xfs_disk_dquot)); |
---|
64 | 66 | } |
---|
65 | 67 | |
---|
.. | .. |
---|
94 | 96 | wake_up(&dqp->q_pinwait); |
---|
95 | 97 | } |
---|
96 | 98 | |
---|
97 | | -STATIC xfs_lsn_t |
---|
98 | | -xfs_qm_dquot_logitem_committed( |
---|
99 | | - struct xfs_log_item *lip, |
---|
100 | | - xfs_lsn_t lsn) |
---|
101 | | -{ |
---|
102 | | - /* |
---|
103 | | - * We always re-log the entire dquot when it becomes dirty, |
---|
104 | | - * so, the latest copy _is_ the only one that matters. |
---|
105 | | - */ |
---|
106 | | - return lsn; |
---|
107 | | -} |
---|
108 | | - |
---|
109 | 99 | /* |
---|
110 | 100 | * This is called to wait for the given dquot to be unpinned. |
---|
111 | 101 | * Most of these pin/unpin routines are plagiarized from inode code. |
---|
.. | .. |
---|
125 | 115 | wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0)); |
---|
126 | 116 | } |
---|
127 | 117 | |
---|
128 | | -/* |
---|
129 | | - * Callback used to mark a buffer with XFS_LI_FAILED when items in the buffer |
---|
130 | | - * have been failed during writeback |
---|
131 | | - * |
---|
132 | | - * this informs the AIL that the dquot is already flush locked on the next push, |
---|
133 | | - * and acquires a hold on the buffer to ensure that it isn't reclaimed before |
---|
134 | | - * dirty data makes it to disk. |
---|
135 | | - */ |
---|
136 | | -STATIC void |
---|
137 | | -xfs_dquot_item_error( |
---|
138 | | - struct xfs_log_item *lip, |
---|
139 | | - struct xfs_buf *bp) |
---|
140 | | -{ |
---|
141 | | - ASSERT(!completion_done(&DQUOT_ITEM(lip)->qli_dquot->q_flush)); |
---|
142 | | - xfs_set_li_failed(lip, bp); |
---|
143 | | -} |
---|
144 | | - |
---|
145 | 118 | STATIC uint |
---|
146 | 119 | xfs_qm_dquot_logitem_push( |
---|
147 | 120 | struct xfs_log_item *lip, |
---|
.. | .. |
---|
156 | 129 | |
---|
157 | 130 | if (atomic_read(&dqp->q_pincount) > 0) |
---|
158 | 131 | return XFS_ITEM_PINNED; |
---|
159 | | - |
---|
160 | | - /* |
---|
161 | | - * The buffer containing this item failed to be written back |
---|
162 | | - * previously. Resubmit the buffer for IO |
---|
163 | | - */ |
---|
164 | | - if (test_bit(XFS_LI_FAILED, &lip->li_flags)) { |
---|
165 | | - if (!xfs_buf_trylock(bp)) |
---|
166 | | - return XFS_ITEM_LOCKED; |
---|
167 | | - |
---|
168 | | - if (!xfs_buf_resubmit_failed_buffers(bp, buffer_list)) |
---|
169 | | - rval = XFS_ITEM_FLUSHING; |
---|
170 | | - |
---|
171 | | - xfs_buf_unlock(bp); |
---|
172 | | - return rval; |
---|
173 | | - } |
---|
174 | 132 | |
---|
175 | 133 | if (!xfs_dqlock_nowait(dqp)) |
---|
176 | 134 | return XFS_ITEM_LOCKED; |
---|
.. | .. |
---|
201 | 159 | if (!xfs_buf_delwri_queue(bp, buffer_list)) |
---|
202 | 160 | rval = XFS_ITEM_FLUSHING; |
---|
203 | 161 | xfs_buf_relse(bp); |
---|
204 | | - } |
---|
| 162 | + } else if (error == -EAGAIN) |
---|
| 163 | + rval = XFS_ITEM_LOCKED; |
---|
205 | 164 | |
---|
206 | 165 | spin_lock(&lip->li_ailp->ail_lock); |
---|
207 | 166 | out_unlock: |
---|
.. | .. |
---|
209 | 168 | return rval; |
---|
210 | 169 | } |
---|
211 | 170 | |
---|
212 | | -/* |
---|
213 | | - * Unlock the dquot associated with the log item. |
---|
214 | | - * Clear the fields of the dquot and dquot log item that |
---|
215 | | - * are specific to the current transaction. If the |
---|
216 | | - * hold flags is set, do not unlock the dquot. |
---|
217 | | - */ |
---|
218 | 171 | STATIC void |
---|
219 | | -xfs_qm_dquot_logitem_unlock( |
---|
| 172 | +xfs_qm_dquot_logitem_release( |
---|
220 | 173 | struct xfs_log_item *lip) |
---|
221 | 174 | { |
---|
222 | 175 | struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; |
---|
223 | 176 | |
---|
224 | 177 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
---|
225 | | - |
---|
226 | | - /* |
---|
227 | | - * Clear the transaction pointer in the dquot |
---|
228 | | - */ |
---|
229 | | - dqp->q_transp = NULL; |
---|
230 | 178 | |
---|
231 | 179 | /* |
---|
232 | 180 | * dquots are never 'held' from getting unlocked at the end of |
---|
.. | .. |
---|
237 | 185 | xfs_dqunlock(dqp); |
---|
238 | 186 | } |
---|
239 | 187 | |
---|
240 | | -/* |
---|
241 | | - * this needs to stamp an lsn into the dquot, I think. |
---|
242 | | - * rpc's that look at user dquot's would then have to |
---|
243 | | - * push on the dependency recorded in the dquot |
---|
244 | | - */ |
---|
245 | 188 | STATIC void |
---|
246 | 189 | xfs_qm_dquot_logitem_committing( |
---|
247 | 190 | struct xfs_log_item *lip, |
---|
248 | | - xfs_lsn_t lsn) |
---|
| 191 | + xfs_csn_t seq) |
---|
249 | 192 | { |
---|
| 193 | + return xfs_qm_dquot_logitem_release(lip); |
---|
250 | 194 | } |
---|
251 | 195 | |
---|
252 | | -/* |
---|
253 | | - * This is the ops vector for dquots |
---|
254 | | - */ |
---|
255 | 196 | static const struct xfs_item_ops xfs_dquot_item_ops = { |
---|
256 | 197 | .iop_size = xfs_qm_dquot_logitem_size, |
---|
257 | 198 | .iop_format = xfs_qm_dquot_logitem_format, |
---|
258 | 199 | .iop_pin = xfs_qm_dquot_logitem_pin, |
---|
259 | 200 | .iop_unpin = xfs_qm_dquot_logitem_unpin, |
---|
260 | | - .iop_unlock = xfs_qm_dquot_logitem_unlock, |
---|
261 | | - .iop_committed = xfs_qm_dquot_logitem_committed, |
---|
| 201 | + .iop_release = xfs_qm_dquot_logitem_release, |
---|
| 202 | + .iop_committing = xfs_qm_dquot_logitem_committing, |
---|
262 | 203 | .iop_push = xfs_qm_dquot_logitem_push, |
---|
263 | | - .iop_committing = xfs_qm_dquot_logitem_committing, |
---|
264 | | - .iop_error = xfs_dquot_item_error |
---|
265 | 204 | }; |
---|
266 | 205 | |
---|
267 | 206 | /* |
---|
.. | .. |
---|
320 | 259 | } |
---|
321 | 260 | |
---|
322 | 261 | /* |
---|
323 | | - * Pinning has no meaning for an quotaoff item, so just return. |
---|
324 | | - */ |
---|
325 | | -STATIC void |
---|
326 | | -xfs_qm_qoff_logitem_pin( |
---|
327 | | - struct xfs_log_item *lip) |
---|
328 | | -{ |
---|
329 | | -} |
---|
330 | | - |
---|
331 | | -/* |
---|
332 | | - * Since pinning has no meaning for an quotaoff item, unpinning does |
---|
333 | | - * not either. |
---|
334 | | - */ |
---|
335 | | -STATIC void |
---|
336 | | -xfs_qm_qoff_logitem_unpin( |
---|
337 | | - struct xfs_log_item *lip, |
---|
338 | | - int remove) |
---|
339 | | -{ |
---|
340 | | -} |
---|
341 | | - |
---|
342 | | -/* |
---|
343 | 262 | * There isn't much you can do to push a quotaoff item. It is simply |
---|
344 | 263 | * stuck waiting for the log to be flushed to disk. |
---|
345 | 264 | */ |
---|
.. | .. |
---|
351 | 270 | return XFS_ITEM_LOCKED; |
---|
352 | 271 | } |
---|
353 | 272 | |
---|
354 | | -/* |
---|
355 | | - * Quotaoff items have no locking or pushing, so return failure |
---|
356 | | - * so that the caller doesn't bother with us. |
---|
357 | | - */ |
---|
358 | | -STATIC void |
---|
359 | | -xfs_qm_qoff_logitem_unlock( |
---|
360 | | - struct xfs_log_item *lip) |
---|
361 | | -{ |
---|
362 | | -} |
---|
363 | | - |
---|
364 | | -/* |
---|
365 | | - * The quotaoff-start-item is logged only once and cannot be moved in the log, |
---|
366 | | - * so simply return the lsn at which it's been logged. |
---|
367 | | - */ |
---|
368 | | -STATIC xfs_lsn_t |
---|
369 | | -xfs_qm_qoff_logitem_committed( |
---|
370 | | - struct xfs_log_item *lip, |
---|
371 | | - xfs_lsn_t lsn) |
---|
372 | | -{ |
---|
373 | | - return lsn; |
---|
374 | | -} |
---|
375 | | - |
---|
376 | 273 | STATIC xfs_lsn_t |
---|
377 | 274 | xfs_qm_qoffend_logitem_committed( |
---|
378 | 275 | struct xfs_log_item *lip, |
---|
.. | .. |
---|
380 | 277 | { |
---|
381 | 278 | struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip); |
---|
382 | 279 | struct xfs_qoff_logitem *qfs = qfe->qql_start_lip; |
---|
383 | | - struct xfs_ail *ailp = qfs->qql_item.li_ailp; |
---|
384 | 280 | |
---|
385 | | - /* |
---|
386 | | - * Delete the qoff-start logitem from the AIL. |
---|
387 | | - * xfs_trans_ail_delete() drops the AIL lock. |
---|
388 | | - */ |
---|
389 | | - spin_lock(&ailp->ail_lock); |
---|
390 | | - xfs_trans_ail_delete(ailp, &qfs->qql_item, SHUTDOWN_LOG_IO_ERROR); |
---|
| 281 | + xfs_qm_qoff_logitem_relse(qfs); |
---|
391 | 282 | |
---|
392 | | - kmem_free(qfs->qql_item.li_lv_shadow); |
---|
393 | 283 | kmem_free(lip->li_lv_shadow); |
---|
394 | | - kmem_free(qfs); |
---|
395 | 284 | kmem_free(qfe); |
---|
396 | 285 | return (xfs_lsn_t)-1; |
---|
397 | 286 | } |
---|
398 | 287 | |
---|
399 | | -/* |
---|
400 | | - * XXX rcc - don't know quite what to do with this. I think we can |
---|
401 | | - * just ignore it. The only time that isn't the case is if we allow |
---|
402 | | - * the client to somehow see that quotas have been turned off in which |
---|
403 | | - * we can't allow that to get back until the quotaoff hits the disk. |
---|
404 | | - * So how would that happen? Also, do we need different routines for |
---|
405 | | - * quotaoff start and quotaoff end? I suspect the answer is yes but |
---|
406 | | - * to be sure, I need to look at the recovery code and see how quota off |
---|
407 | | - * recovery is handled (do we roll forward or back or do something else). |
---|
408 | | - * If we roll forwards or backwards, then we need two separate routines, |
---|
409 | | - * one that does nothing and one that stamps in the lsn that matters |
---|
410 | | - * (truly makes the quotaoff irrevocable). If we do something else, |
---|
411 | | - * then maybe we don't need two. |
---|
412 | | - */ |
---|
413 | 288 | STATIC void |
---|
414 | | -xfs_qm_qoff_logitem_committing( |
---|
415 | | - struct xfs_log_item *lip, |
---|
416 | | - xfs_lsn_t commit_lsn) |
---|
| 289 | +xfs_qm_qoff_logitem_release( |
---|
| 290 | + struct xfs_log_item *lip) |
---|
417 | 291 | { |
---|
| 292 | + struct xfs_qoff_logitem *qoff = QOFF_ITEM(lip); |
---|
| 293 | + |
---|
| 294 | + if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) { |
---|
| 295 | + if (qoff->qql_start_lip) |
---|
| 296 | + xfs_qm_qoff_logitem_relse(qoff->qql_start_lip); |
---|
| 297 | + xfs_qm_qoff_logitem_relse(qoff); |
---|
| 298 | + } |
---|
418 | 299 | } |
---|
419 | 300 | |
---|
420 | 301 | static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { |
---|
421 | 302 | .iop_size = xfs_qm_qoff_logitem_size, |
---|
422 | 303 | .iop_format = xfs_qm_qoff_logitem_format, |
---|
423 | | - .iop_pin = xfs_qm_qoff_logitem_pin, |
---|
424 | | - .iop_unpin = xfs_qm_qoff_logitem_unpin, |
---|
425 | | - .iop_unlock = xfs_qm_qoff_logitem_unlock, |
---|
426 | 304 | .iop_committed = xfs_qm_qoffend_logitem_committed, |
---|
427 | 305 | .iop_push = xfs_qm_qoff_logitem_push, |
---|
428 | | - .iop_committing = xfs_qm_qoff_logitem_committing |
---|
| 306 | + .iop_release = xfs_qm_qoff_logitem_release, |
---|
429 | 307 | }; |
---|
430 | 308 | |
---|
431 | | -/* |
---|
432 | | - * This is the ops vector shared by all quotaoff-start log items. |
---|
433 | | - */ |
---|
434 | 309 | static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = { |
---|
435 | 310 | .iop_size = xfs_qm_qoff_logitem_size, |
---|
436 | 311 | .iop_format = xfs_qm_qoff_logitem_format, |
---|
437 | | - .iop_pin = xfs_qm_qoff_logitem_pin, |
---|
438 | | - .iop_unpin = xfs_qm_qoff_logitem_unpin, |
---|
439 | | - .iop_unlock = xfs_qm_qoff_logitem_unlock, |
---|
440 | | - .iop_committed = xfs_qm_qoff_logitem_committed, |
---|
441 | 312 | .iop_push = xfs_qm_qoff_logitem_push, |
---|
442 | | - .iop_committing = xfs_qm_qoff_logitem_committing |
---|
| 313 | + .iop_release = xfs_qm_qoff_logitem_release, |
---|
443 | 314 | }; |
---|
| 315 | + |
---|
| 316 | +/* |
---|
| 317 | + * Delete the quotaoff intent from the AIL and free it. On success, |
---|
| 318 | + * this should only be called for the start item. It can be used for |
---|
| 319 | + * either on shutdown or abort. |
---|
| 320 | + */ |
---|
| 321 | +void |
---|
| 322 | +xfs_qm_qoff_logitem_relse( |
---|
| 323 | + struct xfs_qoff_logitem *qoff) |
---|
| 324 | +{ |
---|
| 325 | + struct xfs_log_item *lip = &qoff->qql_item; |
---|
| 326 | + |
---|
| 327 | + ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags) || |
---|
| 328 | + test_bit(XFS_LI_ABORTED, &lip->li_flags) || |
---|
| 329 | + XFS_FORCED_SHUTDOWN(lip->li_mountp)); |
---|
| 330 | + xfs_trans_ail_delete(lip, 0); |
---|
| 331 | + kmem_free(lip->li_lv_shadow); |
---|
| 332 | + kmem_free(qoff); |
---|
| 333 | +} |
---|
444 | 334 | |
---|
445 | 335 | /* |
---|
446 | 336 | * Allocate and initialize an quotaoff item of the correct quota type(s). |
---|
.. | .. |
---|
453 | 343 | { |
---|
454 | 344 | struct xfs_qoff_logitem *qf; |
---|
455 | 345 | |
---|
456 | | - qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), KM_SLEEP); |
---|
| 346 | + qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), 0); |
---|
457 | 347 | |
---|
458 | 348 | xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ? |
---|
459 | 349 | &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops); |
---|