0001
0002
0003
0004
0005
0006
0007 #include "xfs.h"
0008 #include "xfs_fs.h"
0009 #include "xfs_shared.h"
0010 #include "xfs_format.h"
0011 #include "xfs_log_format.h"
0012 #include "xfs_trans_resv.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_trans_priv.h"
0016 #include "xfs_trace.h"
0017 #include "xfs_errortag.h"
0018 #include "xfs_error.h"
0019 #include "xfs_log.h"
0020 #include "xfs_log_priv.h"
0021
0022 #ifdef DEBUG
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 STATIC void
0033 xfs_ail_check(
0034 struct xfs_ail *ailp,
0035 struct xfs_log_item *lip)
0036 __must_hold(&ailp->ail_lock)
0037 {
0038 struct xfs_log_item *prev_lip;
0039 struct xfs_log_item *next_lip;
0040 xfs_lsn_t prev_lsn = NULLCOMMITLSN;
0041 xfs_lsn_t next_lsn = NULLCOMMITLSN;
0042 xfs_lsn_t lsn;
0043 bool in_ail;
0044
0045
0046 if (list_empty(&ailp->ail_head))
0047 return;
0048
0049
0050
0051
0052 in_ail = test_bit(XFS_LI_IN_AIL, &lip->li_flags);
0053 prev_lip = list_entry(lip->li_ail.prev, struct xfs_log_item, li_ail);
0054 if (&prev_lip->li_ail != &ailp->ail_head)
0055 prev_lsn = prev_lip->li_lsn;
0056 next_lip = list_entry(lip->li_ail.next, struct xfs_log_item, li_ail);
0057 if (&next_lip->li_ail != &ailp->ail_head)
0058 next_lsn = next_lip->li_lsn;
0059 lsn = lip->li_lsn;
0060
0061 if (in_ail &&
0062 (prev_lsn == NULLCOMMITLSN || XFS_LSN_CMP(prev_lsn, lsn) <= 0) &&
0063 (next_lsn == NULLCOMMITLSN || XFS_LSN_CMP(next_lsn, lsn) >= 0))
0064 return;
0065
0066 spin_unlock(&ailp->ail_lock);
0067 ASSERT(in_ail);
0068 ASSERT(prev_lsn == NULLCOMMITLSN || XFS_LSN_CMP(prev_lsn, lsn) <= 0);
0069 ASSERT(next_lsn == NULLCOMMITLSN || XFS_LSN_CMP(next_lsn, lsn) >= 0);
0070 spin_lock(&ailp->ail_lock);
0071 }
0072 #else
0073 #define xfs_ail_check(a,l)
0074 #endif
0075
0076
0077
0078
0079
0080 static struct xfs_log_item *
0081 xfs_ail_max(
0082 struct xfs_ail *ailp)
0083 {
0084 if (list_empty(&ailp->ail_head))
0085 return NULL;
0086
0087 return list_entry(ailp->ail_head.prev, struct xfs_log_item, li_ail);
0088 }
0089
0090
0091
0092
0093
0094 static struct xfs_log_item *
0095 xfs_ail_next(
0096 struct xfs_ail *ailp,
0097 struct xfs_log_item *lip)
0098 {
0099 if (lip->li_ail.next == &ailp->ail_head)
0100 return NULL;
0101
0102 return list_first_entry(&lip->li_ail, struct xfs_log_item, li_ail);
0103 }
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 static xfs_lsn_t
0114 __xfs_ail_min_lsn(
0115 struct xfs_ail *ailp)
0116 {
0117 struct xfs_log_item *lip = xfs_ail_min(ailp);
0118
0119 if (lip)
0120 return lip->li_lsn;
0121 return 0;
0122 }
0123
0124 xfs_lsn_t
0125 xfs_ail_min_lsn(
0126 struct xfs_ail *ailp)
0127 {
0128 xfs_lsn_t lsn;
0129
0130 spin_lock(&ailp->ail_lock);
0131 lsn = __xfs_ail_min_lsn(ailp);
0132 spin_unlock(&ailp->ail_lock);
0133
0134 return lsn;
0135 }
0136
0137
0138
0139
0140 static xfs_lsn_t
0141 xfs_ail_max_lsn(
0142 struct xfs_ail *ailp)
0143 {
0144 xfs_lsn_t lsn = 0;
0145 struct xfs_log_item *lip;
0146
0147 spin_lock(&ailp->ail_lock);
0148 lip = xfs_ail_max(ailp);
0149 if (lip)
0150 lsn = lip->li_lsn;
0151 spin_unlock(&ailp->ail_lock);
0152
0153 return lsn;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163 STATIC void
0164 xfs_trans_ail_cursor_init(
0165 struct xfs_ail *ailp,
0166 struct xfs_ail_cursor *cur)
0167 {
0168 cur->item = NULL;
0169 list_add_tail(&cur->list, &ailp->ail_cursors);
0170 }
0171
0172
0173
0174
0175
0176 struct xfs_log_item *
0177 xfs_trans_ail_cursor_next(
0178 struct xfs_ail *ailp,
0179 struct xfs_ail_cursor *cur)
0180 {
0181 struct xfs_log_item *lip = cur->item;
0182
0183 if ((uintptr_t)lip & 1)
0184 lip = xfs_ail_min(ailp);
0185 if (lip)
0186 cur->item = xfs_ail_next(ailp, lip);
0187 return lip;
0188 }
0189
0190
0191
0192
0193
0194 void
0195 xfs_trans_ail_cursor_done(
0196 struct xfs_ail_cursor *cur)
0197 {
0198 cur->item = NULL;
0199 list_del_init(&cur->list);
0200 }
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 STATIC void
0211 xfs_trans_ail_cursor_clear(
0212 struct xfs_ail *ailp,
0213 struct xfs_log_item *lip)
0214 {
0215 struct xfs_ail_cursor *cur;
0216
0217 list_for_each_entry(cur, &ailp->ail_cursors, list) {
0218 if (cur->item == lip)
0219 cur->item = (struct xfs_log_item *)
0220 ((uintptr_t)cur->item | 1);
0221 }
0222 }
0223
0224
0225
0226
0227
0228
0229
0230 struct xfs_log_item *
0231 xfs_trans_ail_cursor_first(
0232 struct xfs_ail *ailp,
0233 struct xfs_ail_cursor *cur,
0234 xfs_lsn_t lsn)
0235 {
0236 struct xfs_log_item *lip;
0237
0238 xfs_trans_ail_cursor_init(ailp, cur);
0239
0240 if (lsn == 0) {
0241 lip = xfs_ail_min(ailp);
0242 goto out;
0243 }
0244
0245 list_for_each_entry(lip, &ailp->ail_head, li_ail) {
0246 if (XFS_LSN_CMP(lip->li_lsn, lsn) >= 0)
0247 goto out;
0248 }
0249 return NULL;
0250
0251 out:
0252 if (lip)
0253 cur->item = xfs_ail_next(ailp, lip);
0254 return lip;
0255 }
0256
0257 static struct xfs_log_item *
0258 __xfs_trans_ail_cursor_last(
0259 struct xfs_ail *ailp,
0260 xfs_lsn_t lsn)
0261 {
0262 struct xfs_log_item *lip;
0263
0264 list_for_each_entry_reverse(lip, &ailp->ail_head, li_ail) {
0265 if (XFS_LSN_CMP(lip->li_lsn, lsn) <= 0)
0266 return lip;
0267 }
0268 return NULL;
0269 }
0270
0271
0272
0273
0274
0275
0276
0277 struct xfs_log_item *
0278 xfs_trans_ail_cursor_last(
0279 struct xfs_ail *ailp,
0280 struct xfs_ail_cursor *cur,
0281 xfs_lsn_t lsn)
0282 {
0283 xfs_trans_ail_cursor_init(ailp, cur);
0284 cur->item = __xfs_trans_ail_cursor_last(ailp, lsn);
0285 return cur->item;
0286 }
0287
0288
0289
0290
0291
0292
0293
0294 static void
0295 xfs_ail_splice(
0296 struct xfs_ail *ailp,
0297 struct xfs_ail_cursor *cur,
0298 struct list_head *list,
0299 xfs_lsn_t lsn)
0300 {
0301 struct xfs_log_item *lip;
0302
0303 ASSERT(!list_empty(list));
0304
0305
0306
0307
0308
0309
0310 lip = cur ? cur->item : NULL;
0311 if (!lip || (uintptr_t)lip & 1)
0312 lip = __xfs_trans_ail_cursor_last(ailp, lsn);
0313
0314
0315
0316
0317
0318
0319
0320
0321 if (cur)
0322 cur->item = list_entry(list->prev, struct xfs_log_item, li_ail);
0323
0324
0325
0326
0327
0328
0329
0330 if (lip)
0331 list_splice(list, &lip->li_ail);
0332 else
0333 list_splice(list, &ailp->ail_head);
0334 }
0335
0336
0337
0338
0339 static void
0340 xfs_ail_delete(
0341 struct xfs_ail *ailp,
0342 struct xfs_log_item *lip)
0343 {
0344 xfs_ail_check(ailp, lip);
0345 list_del(&lip->li_ail);
0346 xfs_trans_ail_cursor_clear(ailp, lip);
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 static inline int
0366 xfsaild_resubmit_item(
0367 struct xfs_log_item *lip,
0368 struct list_head *buffer_list)
0369 {
0370 struct xfs_buf *bp = lip->li_buf;
0371
0372 if (!xfs_buf_trylock(bp))
0373 return XFS_ITEM_LOCKED;
0374
0375 if (!xfs_buf_delwri_queue(bp, buffer_list)) {
0376 xfs_buf_unlock(bp);
0377 return XFS_ITEM_FLUSHING;
0378 }
0379
0380
0381 list_for_each_entry(lip, &bp->b_li_list, li_bio_list) {
0382 if (bp->b_flags & _XBF_INODES)
0383 clear_bit(XFS_LI_FAILED, &lip->li_flags);
0384 else
0385 xfs_clear_li_failed(lip);
0386 }
0387
0388 xfs_buf_unlock(bp);
0389 return XFS_ITEM_SUCCESS;
0390 }
0391
0392 static inline uint
0393 xfsaild_push_item(
0394 struct xfs_ail *ailp,
0395 struct xfs_log_item *lip)
0396 {
0397
0398
0399
0400
0401 if (XFS_TEST_ERROR(false, ailp->ail_log->l_mp, XFS_ERRTAG_LOG_ITEM_PIN))
0402 return XFS_ITEM_PINNED;
0403
0404
0405
0406
0407
0408
0409
0410 if (!lip->li_ops->iop_push)
0411 return XFS_ITEM_PINNED;
0412 if (test_bit(XFS_LI_FAILED, &lip->li_flags))
0413 return xfsaild_resubmit_item(lip, &ailp->ail_buf_list);
0414 return lip->li_ops->iop_push(lip, &ailp->ail_buf_list);
0415 }
0416
0417 static long
0418 xfsaild_push(
0419 struct xfs_ail *ailp)
0420 {
0421 struct xfs_mount *mp = ailp->ail_log->l_mp;
0422 struct xfs_ail_cursor cur;
0423 struct xfs_log_item *lip;
0424 xfs_lsn_t lsn;
0425 xfs_lsn_t target;
0426 long tout;
0427 int stuck = 0;
0428 int flushing = 0;
0429 int count = 0;
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440 if (ailp->ail_log_flush && ailp->ail_last_pushed_lsn == 0 &&
0441 (!list_empty_careful(&ailp->ail_buf_list) ||
0442 xfs_ail_min_lsn(ailp))) {
0443 ailp->ail_log_flush = 0;
0444
0445 XFS_STATS_INC(mp, xs_push_ail_flush);
0446 xlog_cil_flush(ailp->ail_log);
0447 }
0448
0449 spin_lock(&ailp->ail_lock);
0450
0451
0452
0453
0454
0455
0456
0457 if (waitqueue_active(&ailp->ail_empty)) {
0458 lip = xfs_ail_max(ailp);
0459 if (lip)
0460 target = lip->li_lsn;
0461 } else {
0462
0463 smp_rmb();
0464 target = ailp->ail_target;
0465 ailp->ail_target_prev = target;
0466 }
0467
0468
0469 lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->ail_last_pushed_lsn);
0470 if (!lip)
0471 goto out_done;
0472
0473 XFS_STATS_INC(mp, xs_push_ail);
0474
0475 lsn = lip->li_lsn;
0476 while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) {
0477 int lock_result;
0478
0479
0480
0481
0482
0483
0484 lock_result = xfsaild_push_item(ailp, lip);
0485 switch (lock_result) {
0486 case XFS_ITEM_SUCCESS:
0487 XFS_STATS_INC(mp, xs_push_ail_success);
0488 trace_xfs_ail_push(lip);
0489
0490 ailp->ail_last_pushed_lsn = lsn;
0491 break;
0492
0493 case XFS_ITEM_FLUSHING:
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505 XFS_STATS_INC(mp, xs_push_ail_flushing);
0506 trace_xfs_ail_flushing(lip);
0507
0508 flushing++;
0509 ailp->ail_last_pushed_lsn = lsn;
0510 break;
0511
0512 case XFS_ITEM_PINNED:
0513 XFS_STATS_INC(mp, xs_push_ail_pinned);
0514 trace_xfs_ail_pinned(lip);
0515
0516 stuck++;
0517 ailp->ail_log_flush++;
0518 break;
0519 case XFS_ITEM_LOCKED:
0520 XFS_STATS_INC(mp, xs_push_ail_locked);
0521 trace_xfs_ail_locked(lip);
0522
0523 stuck++;
0524 break;
0525 default:
0526 ASSERT(0);
0527 break;
0528 }
0529
0530 count++;
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545 if (stuck > 100)
0546 break;
0547
0548 lip = xfs_trans_ail_cursor_next(ailp, &cur);
0549 if (lip == NULL)
0550 break;
0551 lsn = lip->li_lsn;
0552 }
0553
0554 out_done:
0555 xfs_trans_ail_cursor_done(&cur);
0556 spin_unlock(&ailp->ail_lock);
0557
0558 if (xfs_buf_delwri_submit_nowait(&ailp->ail_buf_list))
0559 ailp->ail_log_flush++;
0560
0561 if (!count || XFS_LSN_CMP(lsn, target) >= 0) {
0562
0563
0564
0565
0566
0567 tout = 50;
0568 ailp->ail_last_pushed_lsn = 0;
0569 } else if (((stuck + flushing) * 100) / count > 90) {
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580 tout = 20;
0581 ailp->ail_last_pushed_lsn = 0;
0582 } else {
0583
0584
0585
0586 tout = 10;
0587 }
0588
0589 return tout;
0590 }
0591
0592 static int
0593 xfsaild(
0594 void *data)
0595 {
0596 struct xfs_ail *ailp = data;
0597 long tout = 0;
0598 unsigned int noreclaim_flag;
0599
0600 noreclaim_flag = memalloc_noreclaim_save();
0601 set_freezable();
0602
0603 while (1) {
0604 if (tout && tout <= 20)
0605 set_current_state(TASK_KILLABLE);
0606 else
0607 set_current_state(TASK_INTERRUPTIBLE);
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617 if (kthread_should_stop()) {
0618 __set_current_state(TASK_RUNNING);
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634 ASSERT(list_empty(&ailp->ail_buf_list) ||
0635 xlog_is_shutdown(ailp->ail_log));
0636 xfs_buf_delwri_cancel(&ailp->ail_buf_list);
0637 break;
0638 }
0639
0640 spin_lock(&ailp->ail_lock);
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651 smp_rmb();
0652 if (!xfs_ail_min(ailp) &&
0653 ailp->ail_target == ailp->ail_target_prev &&
0654 list_empty(&ailp->ail_buf_list)) {
0655 spin_unlock(&ailp->ail_lock);
0656 freezable_schedule();
0657 tout = 0;
0658 continue;
0659 }
0660 spin_unlock(&ailp->ail_lock);
0661
0662 if (tout)
0663 freezable_schedule_timeout(msecs_to_jiffies(tout));
0664
0665 __set_current_state(TASK_RUNNING);
0666
0667 try_to_freeze();
0668
0669 tout = xfsaild_push(ailp);
0670 }
0671
0672 memalloc_noreclaim_restore(noreclaim_flag);
0673 return 0;
0674 }
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690 void
0691 xfs_ail_push(
0692 struct xfs_ail *ailp,
0693 xfs_lsn_t threshold_lsn)
0694 {
0695 struct xfs_log_item *lip;
0696
0697 lip = xfs_ail_min(ailp);
0698 if (!lip || xlog_is_shutdown(ailp->ail_log) ||
0699 XFS_LSN_CMP(threshold_lsn, ailp->ail_target) <= 0)
0700 return;
0701
0702
0703
0704
0705
0706 smp_wmb();
0707 xfs_trans_ail_copy_lsn(ailp, &ailp->ail_target, &threshold_lsn);
0708 smp_wmb();
0709
0710 wake_up_process(ailp->ail_task);
0711 }
0712
0713
0714
0715
0716 void
0717 xfs_ail_push_all(
0718 struct xfs_ail *ailp)
0719 {
0720 xfs_lsn_t threshold_lsn = xfs_ail_max_lsn(ailp);
0721
0722 if (threshold_lsn)
0723 xfs_ail_push(ailp, threshold_lsn);
0724 }
0725
0726
0727
0728
0729 void
0730 xfs_ail_push_all_sync(
0731 struct xfs_ail *ailp)
0732 {
0733 struct xfs_log_item *lip;
0734 DEFINE_WAIT(wait);
0735
0736 spin_lock(&ailp->ail_lock);
0737 while ((lip = xfs_ail_max(ailp)) != NULL) {
0738 prepare_to_wait(&ailp->ail_empty, &wait, TASK_UNINTERRUPTIBLE);
0739 wake_up_process(ailp->ail_task);
0740 spin_unlock(&ailp->ail_lock);
0741 schedule();
0742 spin_lock(&ailp->ail_lock);
0743 }
0744 spin_unlock(&ailp->ail_lock);
0745
0746 finish_wait(&ailp->ail_empty, &wait);
0747 }
0748
0749 void
0750 xfs_ail_update_finish(
0751 struct xfs_ail *ailp,
0752 xfs_lsn_t old_lsn) __releases(ailp->ail_lock)
0753 {
0754 struct xlog *log = ailp->ail_log;
0755
0756
0757 if (!old_lsn || old_lsn == __xfs_ail_min_lsn(ailp)) {
0758 spin_unlock(&ailp->ail_lock);
0759 return;
0760 }
0761
0762 if (!xlog_is_shutdown(log))
0763 xlog_assign_tail_lsn_locked(log->l_mp);
0764
0765 if (list_empty(&ailp->ail_head))
0766 wake_up_all(&ailp->ail_empty);
0767 spin_unlock(&ailp->ail_lock);
0768 xfs_log_space_wake(log->l_mp);
0769 }
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793 void
0794 xfs_trans_ail_update_bulk(
0795 struct xfs_ail *ailp,
0796 struct xfs_ail_cursor *cur,
0797 struct xfs_log_item **log_items,
0798 int nr_items,
0799 xfs_lsn_t lsn) __releases(ailp->ail_lock)
0800 {
0801 struct xfs_log_item *mlip;
0802 xfs_lsn_t tail_lsn = 0;
0803 int i;
0804 LIST_HEAD(tmp);
0805
0806 ASSERT(nr_items > 0);
0807 mlip = xfs_ail_min(ailp);
0808
0809 for (i = 0; i < nr_items; i++) {
0810 struct xfs_log_item *lip = log_items[i];
0811 if (test_and_set_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
0812
0813 if (XFS_LSN_CMP(lsn, lip->li_lsn) <= 0)
0814 continue;
0815
0816 trace_xfs_ail_move(lip, lip->li_lsn, lsn);
0817 if (mlip == lip && !tail_lsn)
0818 tail_lsn = lip->li_lsn;
0819
0820 xfs_ail_delete(ailp, lip);
0821 } else {
0822 trace_xfs_ail_insert(lip, 0, lsn);
0823 }
0824 lip->li_lsn = lsn;
0825 list_add(&lip->li_ail, &tmp);
0826 }
0827
0828 if (!list_empty(&tmp))
0829 xfs_ail_splice(ailp, cur, &tmp, lsn);
0830
0831 xfs_ail_update_finish(ailp, tail_lsn);
0832 }
0833
0834
0835 void
0836 xfs_trans_ail_insert(
0837 struct xfs_ail *ailp,
0838 struct xfs_log_item *lip,
0839 xfs_lsn_t lsn)
0840 {
0841 spin_lock(&ailp->ail_lock);
0842 xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
0843 }
0844
0845
0846
0847
0848
0849
0850
0851
0852 xfs_lsn_t
0853 xfs_ail_delete_one(
0854 struct xfs_ail *ailp,
0855 struct xfs_log_item *lip)
0856 {
0857 struct xfs_log_item *mlip = xfs_ail_min(ailp);
0858 xfs_lsn_t lsn = lip->li_lsn;
0859
0860 trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn);
0861 xfs_ail_delete(ailp, lip);
0862 clear_bit(XFS_LI_IN_AIL, &lip->li_flags);
0863 lip->li_lsn = 0;
0864
0865 if (mlip == lip)
0866 return lsn;
0867 return 0;
0868 }
0869
0870 void
0871 xfs_trans_ail_delete(
0872 struct xfs_log_item *lip,
0873 int shutdown_type)
0874 {
0875 struct xfs_ail *ailp = lip->li_ailp;
0876 struct xlog *log = ailp->ail_log;
0877 xfs_lsn_t tail_lsn;
0878
0879 spin_lock(&ailp->ail_lock);
0880 if (!test_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
0881 spin_unlock(&ailp->ail_lock);
0882 if (shutdown_type && !xlog_is_shutdown(log)) {
0883 xfs_alert_tag(log->l_mp, XFS_PTAG_AILDELETE,
0884 "%s: attempting to delete a log item that is not in the AIL",
0885 __func__);
0886 xlog_force_shutdown(log, shutdown_type);
0887 }
0888 return;
0889 }
0890
0891
0892 xfs_clear_li_failed(lip);
0893 tail_lsn = xfs_ail_delete_one(ailp, lip);
0894 xfs_ail_update_finish(ailp, tail_lsn);
0895 }
0896
0897 int
0898 xfs_trans_ail_init(
0899 xfs_mount_t *mp)
0900 {
0901 struct xfs_ail *ailp;
0902
0903 ailp = kmem_zalloc(sizeof(struct xfs_ail), KM_MAYFAIL);
0904 if (!ailp)
0905 return -ENOMEM;
0906
0907 ailp->ail_log = mp->m_log;
0908 INIT_LIST_HEAD(&ailp->ail_head);
0909 INIT_LIST_HEAD(&ailp->ail_cursors);
0910 spin_lock_init(&ailp->ail_lock);
0911 INIT_LIST_HEAD(&ailp->ail_buf_list);
0912 init_waitqueue_head(&ailp->ail_empty);
0913
0914 ailp->ail_task = kthread_run(xfsaild, ailp, "xfsaild/%s",
0915 mp->m_super->s_id);
0916 if (IS_ERR(ailp->ail_task))
0917 goto out_free_ailp;
0918
0919 mp->m_ail = ailp;
0920 return 0;
0921
0922 out_free_ailp:
0923 kmem_free(ailp);
0924 return -ENOMEM;
0925 }
0926
0927 void
0928 xfs_trans_ail_destroy(
0929 xfs_mount_t *mp)
0930 {
0931 struct xfs_ail *ailp = mp->m_ail;
0932
0933 kthread_stop(ailp->ail_task);
0934 kmem_free(ailp);
0935 }