1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "xfs.h"
20#include "xfs_fs.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
24#include "xfs_mount.h"
25#include "xfs_trans.h"
26#include "xfs_trans_priv.h"
27#include "xfs_trace.h"
28#include "xfs_errortag.h"
29#include "xfs_error.h"
30#include "xfs_log.h"
31
32#ifdef DEBUG
33
34
35
36STATIC void
37xfs_ail_check(
38 struct xfs_ail *ailp,
39 xfs_log_item_t *lip)
40{
41 xfs_log_item_t *prev_lip;
42
43 if (list_empty(&ailp->ail_head))
44 return;
45
46
47
48
49 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
50 prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
51 if (&prev_lip->li_ail != &ailp->ail_head)
52 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
53
54 prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
55 if (&prev_lip->li_ail != &ailp->ail_head)
56 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
57
58
59}
60#else
61#define xfs_ail_check(a,l)
62#endif
63
64
65
66
67
68static xfs_log_item_t *
69xfs_ail_max(
70 struct xfs_ail *ailp)
71{
72 if (list_empty(&ailp->ail_head))
73 return NULL;
74
75 return list_entry(ailp->ail_head.prev, xfs_log_item_t, li_ail);
76}
77
78
79
80
81
82static xfs_log_item_t *
83xfs_ail_next(
84 struct xfs_ail *ailp,
85 xfs_log_item_t *lip)
86{
87 if (lip->li_ail.next == &ailp->ail_head)
88 return NULL;
89
90 return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail);
91}
92
93
94
95
96
97
98
99
100
101xfs_lsn_t
102xfs_ail_min_lsn(
103 struct xfs_ail *ailp)
104{
105 xfs_lsn_t lsn = 0;
106 xfs_log_item_t *lip;
107
108 spin_lock(&ailp->ail_lock);
109 lip = xfs_ail_min(ailp);
110 if (lip)
111 lsn = lip->li_lsn;
112 spin_unlock(&ailp->ail_lock);
113
114 return lsn;
115}
116
117
118
119
120static xfs_lsn_t
121xfs_ail_max_lsn(
122 struct xfs_ail *ailp)
123{
124 xfs_lsn_t lsn = 0;
125 xfs_log_item_t *lip;
126
127 spin_lock(&ailp->ail_lock);
128 lip = xfs_ail_max(ailp);
129 if (lip)
130 lsn = lip->li_lsn;
131 spin_unlock(&ailp->ail_lock);
132
133 return lsn;
134}
135
136
137
138
139
140
141
142
143STATIC void
144xfs_trans_ail_cursor_init(
145 struct xfs_ail *ailp,
146 struct xfs_ail_cursor *cur)
147{
148 cur->item = NULL;
149 list_add_tail(&cur->list, &ailp->ail_cursors);
150}
151
152
153
154
155
156struct xfs_log_item *
157xfs_trans_ail_cursor_next(
158 struct xfs_ail *ailp,
159 struct xfs_ail_cursor *cur)
160{
161 struct xfs_log_item *lip = cur->item;
162
163 if ((uintptr_t)lip & 1)
164 lip = xfs_ail_min(ailp);
165 if (lip)
166 cur->item = xfs_ail_next(ailp, lip);
167 return lip;
168}
169
170
171
172
173
174void
175xfs_trans_ail_cursor_done(
176 struct xfs_ail_cursor *cur)
177{
178 cur->item = NULL;
179 list_del_init(&cur->list);
180}
181
182
183
184
185
186
187
188
189
190STATIC void
191xfs_trans_ail_cursor_clear(
192 struct xfs_ail *ailp,
193 struct xfs_log_item *lip)
194{
195 struct xfs_ail_cursor *cur;
196
197 list_for_each_entry(cur, &ailp->ail_cursors, list) {
198 if (cur->item == lip)
199 cur->item = (struct xfs_log_item *)
200 ((uintptr_t)cur->item | 1);
201 }
202}
203
204
205
206
207
208
209
210xfs_log_item_t *
211xfs_trans_ail_cursor_first(
212 struct xfs_ail *ailp,
213 struct xfs_ail_cursor *cur,
214 xfs_lsn_t lsn)
215{
216 xfs_log_item_t *lip;
217
218 xfs_trans_ail_cursor_init(ailp, cur);
219
220 if (lsn == 0) {
221 lip = xfs_ail_min(ailp);
222 goto out;
223 }
224
225 list_for_each_entry(lip, &ailp->ail_head, li_ail) {
226 if (XFS_LSN_CMP(lip->li_lsn, lsn) >= 0)
227 goto out;
228 }
229 return NULL;
230
231out:
232 if (lip)
233 cur->item = xfs_ail_next(ailp, lip);
234 return lip;
235}
236
237static struct xfs_log_item *
238__xfs_trans_ail_cursor_last(
239 struct xfs_ail *ailp,
240 xfs_lsn_t lsn)
241{
242 xfs_log_item_t *lip;
243
244 list_for_each_entry_reverse(lip, &ailp->ail_head, li_ail) {
245 if (XFS_LSN_CMP(lip->li_lsn, lsn) <= 0)
246 return lip;
247 }
248 return NULL;
249}
250
251
252
253
254
255
256
257struct xfs_log_item *
258xfs_trans_ail_cursor_last(
259 struct xfs_ail *ailp,
260 struct xfs_ail_cursor *cur,
261 xfs_lsn_t lsn)
262{
263 xfs_trans_ail_cursor_init(ailp, cur);
264 cur->item = __xfs_trans_ail_cursor_last(ailp, lsn);
265 return cur->item;
266}
267
268
269
270
271
272
273
274static void
275xfs_ail_splice(
276 struct xfs_ail *ailp,
277 struct xfs_ail_cursor *cur,
278 struct list_head *list,
279 xfs_lsn_t lsn)
280{
281 struct xfs_log_item *lip;
282
283 ASSERT(!list_empty(list));
284
285
286
287
288
289
290 lip = cur ? cur->item : NULL;
291 if (!lip || (uintptr_t)lip & 1)
292 lip = __xfs_trans_ail_cursor_last(ailp, lsn);
293
294
295
296
297
298
299
300
301 if (cur)
302 cur->item = list_entry(list->prev, struct xfs_log_item, li_ail);
303
304
305
306
307
308
309
310 if (lip)
311 list_splice(list, &lip->li_ail);
312 else
313 list_splice(list, &ailp->ail_head);
314}
315
316
317
318
319static void
320xfs_ail_delete(
321 struct xfs_ail *ailp,
322 xfs_log_item_t *lip)
323{
324 xfs_ail_check(ailp, lip);
325 list_del(&lip->li_ail);
326 xfs_trans_ail_cursor_clear(ailp, lip);
327}
328
329static inline uint
330xfsaild_push_item(
331 struct xfs_ail *ailp,
332 struct xfs_log_item *lip)
333{
334
335
336
337
338 if (XFS_TEST_ERROR(false, ailp->ail_mount, XFS_ERRTAG_LOG_ITEM_PIN))
339 return XFS_ITEM_PINNED;
340
341 return lip->li_ops->iop_push(lip, &ailp->ail_buf_list);
342}
343
344static long
345xfsaild_push(
346 struct xfs_ail *ailp)
347{
348 xfs_mount_t *mp = ailp->ail_mount;
349 struct xfs_ail_cursor cur;
350 xfs_log_item_t *lip;
351 xfs_lsn_t lsn;
352 xfs_lsn_t target;
353 long tout;
354 int stuck = 0;
355 int flushing = 0;
356 int count = 0;
357
358
359
360
361
362
363 if (ailp->ail_log_flush && ailp->ail_last_pushed_lsn == 0 &&
364 (!list_empty_careful(&ailp->ail_buf_list) ||
365 xfs_ail_min_lsn(ailp))) {
366 ailp->ail_log_flush = 0;
367
368 XFS_STATS_INC(mp, xs_push_ail_flush);
369 xfs_log_force(mp, XFS_LOG_SYNC);
370 }
371
372 spin_lock(&ailp->ail_lock);
373
374
375 smp_rmb();
376 target = ailp->ail_target;
377 ailp->ail_target_prev = target;
378
379 lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->ail_last_pushed_lsn);
380 if (!lip) {
381
382
383
384
385 xfs_trans_ail_cursor_done(&cur);
386 spin_unlock(&ailp->ail_lock);
387 goto out_done;
388 }
389
390 XFS_STATS_INC(mp, xs_push_ail);
391
392 lsn = lip->li_lsn;
393 while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) {
394 int lock_result;
395
396
397
398
399
400
401 lock_result = xfsaild_push_item(ailp, lip);
402 switch (lock_result) {
403 case XFS_ITEM_SUCCESS:
404 XFS_STATS_INC(mp, xs_push_ail_success);
405 trace_xfs_ail_push(lip);
406
407 ailp->ail_last_pushed_lsn = lsn;
408 break;
409
410 case XFS_ITEM_FLUSHING:
411
412
413
414
415
416
417
418
419
420
421
422 XFS_STATS_INC(mp, xs_push_ail_flushing);
423 trace_xfs_ail_flushing(lip);
424
425 flushing++;
426 ailp->ail_last_pushed_lsn = lsn;
427 break;
428
429 case XFS_ITEM_PINNED:
430 XFS_STATS_INC(mp, xs_push_ail_pinned);
431 trace_xfs_ail_pinned(lip);
432
433 stuck++;
434 ailp->ail_log_flush++;
435 break;
436 case XFS_ITEM_LOCKED:
437 XFS_STATS_INC(mp, xs_push_ail_locked);
438 trace_xfs_ail_locked(lip);
439
440 stuck++;
441 break;
442 default:
443 ASSERT(0);
444 break;
445 }
446
447 count++;
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462 if (stuck > 100)
463 break;
464
465 lip = xfs_trans_ail_cursor_next(ailp, &cur);
466 if (lip == NULL)
467 break;
468 lsn = lip->li_lsn;
469 }
470 xfs_trans_ail_cursor_done(&cur);
471 spin_unlock(&ailp->ail_lock);
472
473 if (xfs_buf_delwri_submit_nowait(&ailp->ail_buf_list))
474 ailp->ail_log_flush++;
475
476 if (!count || XFS_LSN_CMP(lsn, target) >= 0) {
477out_done:
478
479
480
481
482
483 tout = 50;
484 ailp->ail_last_pushed_lsn = 0;
485 } else if (((stuck + flushing) * 100) / count > 90) {
486
487
488
489
490
491
492
493
494
495
496 tout = 20;
497 ailp->ail_last_pushed_lsn = 0;
498 } else {
499
500
501
502 tout = 10;
503 }
504
505 return tout;
506}
507
508static int
509xfsaild(
510 void *data)
511{
512 struct xfs_ail *ailp = data;
513 long tout = 0;
514
515 current->flags |= PF_MEMALLOC;
516 set_freezable();
517
518 while (1) {
519 if (tout && tout <= 20)
520 set_current_state(TASK_KILLABLE);
521 else
522 set_current_state(TASK_INTERRUPTIBLE);
523
524
525
526
527
528
529
530
531
532
533
534 if (kthread_should_stop()) {
535 __set_current_state(TASK_RUNNING);
536 break;
537 }
538
539 spin_lock(&ailp->ail_lock);
540
541
542
543
544
545
546
547
548
549
550 smp_rmb();
551 if (!xfs_ail_min(ailp) &&
552 ailp->ail_target == ailp->ail_target_prev) {
553 spin_unlock(&ailp->ail_lock);
554 freezable_schedule();
555 tout = 0;
556 continue;
557 }
558 spin_unlock(&ailp->ail_lock);
559
560 if (tout)
561 freezable_schedule_timeout(msecs_to_jiffies(tout));
562
563 __set_current_state(TASK_RUNNING);
564
565 try_to_freeze();
566
567 tout = xfsaild_push(ailp);
568 }
569
570 return 0;
571}
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587void
588xfs_ail_push(
589 struct xfs_ail *ailp,
590 xfs_lsn_t threshold_lsn)
591{
592 xfs_log_item_t *lip;
593
594 lip = xfs_ail_min(ailp);
595 if (!lip || XFS_FORCED_SHUTDOWN(ailp->ail_mount) ||
596 XFS_LSN_CMP(threshold_lsn, ailp->ail_target) <= 0)
597 return;
598
599
600
601
602
603 smp_wmb();
604 xfs_trans_ail_copy_lsn(ailp, &ailp->ail_target, &threshold_lsn);
605 smp_wmb();
606
607 wake_up_process(ailp->ail_task);
608}
609
610
611
612
613void
614xfs_ail_push_all(
615 struct xfs_ail *ailp)
616{
617 xfs_lsn_t threshold_lsn = xfs_ail_max_lsn(ailp);
618
619 if (threshold_lsn)
620 xfs_ail_push(ailp, threshold_lsn);
621}
622
623
624
625
626void
627xfs_ail_push_all_sync(
628 struct xfs_ail *ailp)
629{
630 struct xfs_log_item *lip;
631 DEFINE_WAIT(wait);
632
633 spin_lock(&ailp->ail_lock);
634 while ((lip = xfs_ail_max(ailp)) != NULL) {
635 prepare_to_wait(&ailp->ail_empty, &wait, TASK_UNINTERRUPTIBLE);
636 ailp->ail_target = lip->li_lsn;
637 wake_up_process(ailp->ail_task);
638 spin_unlock(&ailp->ail_lock);
639 schedule();
640 spin_lock(&ailp->ail_lock);
641 }
642 spin_unlock(&ailp->ail_lock);
643
644 finish_wait(&ailp->ail_empty, &wait);
645}
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669void
670xfs_trans_ail_update_bulk(
671 struct xfs_ail *ailp,
672 struct xfs_ail_cursor *cur,
673 struct xfs_log_item **log_items,
674 int nr_items,
675 xfs_lsn_t lsn) __releases(ailp->ail_lock)
676{
677 xfs_log_item_t *mlip;
678 int mlip_changed = 0;
679 int i;
680 LIST_HEAD(tmp);
681
682 ASSERT(nr_items > 0);
683 mlip = xfs_ail_min(ailp);
684
685 for (i = 0; i < nr_items; i++) {
686 struct xfs_log_item *lip = log_items[i];
687 if (lip->li_flags & XFS_LI_IN_AIL) {
688
689 if (XFS_LSN_CMP(lsn, lip->li_lsn) <= 0)
690 continue;
691
692 trace_xfs_ail_move(lip, lip->li_lsn, lsn);
693 xfs_ail_delete(ailp, lip);
694 if (mlip == lip)
695 mlip_changed = 1;
696 } else {
697 lip->li_flags |= XFS_LI_IN_AIL;
698 trace_xfs_ail_insert(lip, 0, lsn);
699 }
700 lip->li_lsn = lsn;
701 list_add(&lip->li_ail, &tmp);
702 }
703
704 if (!list_empty(&tmp))
705 xfs_ail_splice(ailp, cur, &tmp, lsn);
706
707 if (mlip_changed) {
708 if (!XFS_FORCED_SHUTDOWN(ailp->ail_mount))
709 xlog_assign_tail_lsn_locked(ailp->ail_mount);
710 spin_unlock(&ailp->ail_lock);
711
712 xfs_log_space_wake(ailp->ail_mount);
713 } else {
714 spin_unlock(&ailp->ail_lock);
715 }
716}
717
718bool
719xfs_ail_delete_one(
720 struct xfs_ail *ailp,
721 struct xfs_log_item *lip)
722{
723 struct xfs_log_item *mlip = xfs_ail_min(ailp);
724
725 trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn);
726 xfs_ail_delete(ailp, lip);
727 xfs_clear_li_failed(lip);
728 lip->li_flags &= ~XFS_LI_IN_AIL;
729 lip->li_lsn = 0;
730
731 return mlip == lip;
732}
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755void
756xfs_trans_ail_delete(
757 struct xfs_ail *ailp,
758 struct xfs_log_item *lip,
759 int shutdown_type) __releases(ailp->ail_lock)
760{
761 struct xfs_mount *mp = ailp->ail_mount;
762 bool mlip_changed;
763
764 if (!(lip->li_flags & XFS_LI_IN_AIL)) {
765 spin_unlock(&ailp->ail_lock);
766 if (!XFS_FORCED_SHUTDOWN(mp)) {
767 xfs_alert_tag(mp, XFS_PTAG_AILDELETE,
768 "%s: attempting to delete a log item that is not in the AIL",
769 __func__);
770 xfs_force_shutdown(mp, shutdown_type);
771 }
772 return;
773 }
774
775 mlip_changed = xfs_ail_delete_one(ailp, lip);
776 if (mlip_changed) {
777 if (!XFS_FORCED_SHUTDOWN(mp))
778 xlog_assign_tail_lsn_locked(mp);
779 if (list_empty(&ailp->ail_head))
780 wake_up_all(&ailp->ail_empty);
781 }
782
783 spin_unlock(&ailp->ail_lock);
784 if (mlip_changed)
785 xfs_log_space_wake(ailp->ail_mount);
786}
787
788int
789xfs_trans_ail_init(
790 xfs_mount_t *mp)
791{
792 struct xfs_ail *ailp;
793
794 ailp = kmem_zalloc(sizeof(struct xfs_ail), KM_MAYFAIL);
795 if (!ailp)
796 return -ENOMEM;
797
798 ailp->ail_mount = mp;
799 INIT_LIST_HEAD(&ailp->ail_head);
800 INIT_LIST_HEAD(&ailp->ail_cursors);
801 spin_lock_init(&ailp->ail_lock);
802 INIT_LIST_HEAD(&ailp->ail_buf_list);
803 init_waitqueue_head(&ailp->ail_empty);
804
805 ailp->ail_task = kthread_run(xfsaild, ailp, "xfsaild/%s",
806 ailp->ail_mount->m_fsname);
807 if (IS_ERR(ailp->ail_task))
808 goto out_free_ailp;
809
810 mp->m_ail = ailp;
811 return 0;
812
813out_free_ailp:
814 kmem_free(ailp);
815 return -ENOMEM;
816}
817
818void
819xfs_trans_ail_destroy(
820 xfs_mount_t *mp)
821{
822 struct xfs_ail *ailp = mp->m_ail;
823
824 kthread_stop(ailp->ail_task);
825 kmem_free(ailp);
826}
827