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_types.h"
22#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_inum.h"
25#include "xfs_trans.h"
26#include "xfs_sb.h"
27#include "xfs_ag.h"
28#include "xfs_mount.h"
29#include "xfs_error.h"
30#include "xfs_da_btree.h"
31#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h"
34#include "xfs_dinode.h"
35#include "xfs_inode.h"
36#include "xfs_btree.h"
37#include "xfs_ialloc.h"
38#include "xfs_alloc.h"
39#include "xfs_bmap.h"
40#include "xfs_quota.h"
41#include "xfs_trans_priv.h"
42#include "xfs_trans_space.h"
43#include "xfs_inode_item.h"
44#include "xfs_trace.h"
45
46kmem_zone_t *xfs_trans_zone;
47kmem_zone_t *xfs_log_item_desc_zone;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84STATIC uint
85xfs_calc_write_reservation(
86 struct xfs_mount *mp)
87{
88 return XFS_DQUOT_LOGRES(mp) +
89 MAX((mp->m_sb.sb_inodesize +
90 XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
91 2 * mp->m_sb.sb_sectsize +
92 mp->m_sb.sb_sectsize +
93 XFS_ALLOCFREE_LOG_RES(mp, 2) +
94 128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
95 XFS_ALLOCFREE_LOG_COUNT(mp, 2))),
96 (2 * mp->m_sb.sb_sectsize +
97 2 * mp->m_sb.sb_sectsize +
98 mp->m_sb.sb_sectsize +
99 XFS_ALLOCFREE_LOG_RES(mp, 2) +
100 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
101}
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116STATIC uint
117xfs_calc_itruncate_reservation(
118 struct xfs_mount *mp)
119{
120 return XFS_DQUOT_LOGRES(mp) +
121 MAX((mp->m_sb.sb_inodesize +
122 XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) +
123 128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
124 (4 * mp->m_sb.sb_sectsize +
125 4 * mp->m_sb.sb_sectsize +
126 mp->m_sb.sb_sectsize +
127 XFS_ALLOCFREE_LOG_RES(mp, 4) +
128 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)) +
129 128 * 5 +
130 XFS_ALLOCFREE_LOG_RES(mp, 1) +
131 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
132 XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
133}
134
135
136
137
138
139
140
141
142
143
144
145
146
147STATIC uint
148xfs_calc_rename_reservation(
149 struct xfs_mount *mp)
150{
151 return XFS_DQUOT_LOGRES(mp) +
152 MAX((4 * mp->m_sb.sb_inodesize +
153 2 * XFS_DIROP_LOG_RES(mp) +
154 128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp))),
155 (3 * mp->m_sb.sb_sectsize +
156 3 * mp->m_sb.sb_sectsize +
157 mp->m_sb.sb_sectsize +
158 XFS_ALLOCFREE_LOG_RES(mp, 3) +
159 128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))));
160}
161
162
163
164
165
166
167
168
169
170
171
172
173
174STATIC uint
175xfs_calc_link_reservation(
176 struct xfs_mount *mp)
177{
178 return XFS_DQUOT_LOGRES(mp) +
179 MAX((mp->m_sb.sb_inodesize +
180 mp->m_sb.sb_inodesize +
181 XFS_DIROP_LOG_RES(mp) +
182 128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
183 (mp->m_sb.sb_sectsize +
184 mp->m_sb.sb_sectsize +
185 mp->m_sb.sb_sectsize +
186 XFS_ALLOCFREE_LOG_RES(mp, 1) +
187 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
188}
189
190
191
192
193
194
195
196
197
198
199
200
201
202STATIC uint
203xfs_calc_remove_reservation(
204 struct xfs_mount *mp)
205{
206 return XFS_DQUOT_LOGRES(mp) +
207 MAX((mp->m_sb.sb_inodesize +
208 mp->m_sb.sb_inodesize +
209 XFS_DIROP_LOG_RES(mp) +
210 128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
211 (2 * mp->m_sb.sb_sectsize +
212 2 * mp->m_sb.sb_sectsize +
213 mp->m_sb.sb_sectsize +
214 XFS_ALLOCFREE_LOG_RES(mp, 2) +
215 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
216}
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232STATIC uint
233xfs_calc_symlink_reservation(
234 struct xfs_mount *mp)
235{
236 return XFS_DQUOT_LOGRES(mp) +
237 MAX((mp->m_sb.sb_inodesize +
238 mp->m_sb.sb_inodesize +
239 XFS_FSB_TO_B(mp, 1) +
240 XFS_DIROP_LOG_RES(mp) +
241 1024 +
242 128 * (4 + XFS_DIROP_LOG_COUNT(mp))),
243 (2 * mp->m_sb.sb_sectsize +
244 XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
245 XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
246 XFS_ALLOCFREE_LOG_RES(mp, 1) +
247 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
248 XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
249}
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266STATIC uint
267xfs_calc_create_reservation(
268 struct xfs_mount *mp)
269{
270 return XFS_DQUOT_LOGRES(mp) +
271 MAX((mp->m_sb.sb_inodesize +
272 mp->m_sb.sb_inodesize +
273 mp->m_sb.sb_sectsize +
274 XFS_FSB_TO_B(mp, 1) +
275 XFS_DIROP_LOG_RES(mp) +
276 128 * (3 + XFS_DIROP_LOG_COUNT(mp))),
277 (3 * mp->m_sb.sb_sectsize +
278 XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
279 XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
280 XFS_ALLOCFREE_LOG_RES(mp, 1) +
281 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
282 XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
283}
284
285
286
287
288STATIC uint
289xfs_calc_mkdir_reservation(
290 struct xfs_mount *mp)
291{
292 return xfs_calc_create_reservation(mp);
293}
294
295
296
297
298
299
300
301
302
303
304
305STATIC uint
306xfs_calc_ifree_reservation(
307 struct xfs_mount *mp)
308{
309 return XFS_DQUOT_LOGRES(mp) +
310 mp->m_sb.sb_inodesize +
311 mp->m_sb.sb_sectsize +
312 mp->m_sb.sb_sectsize +
313 XFS_FSB_TO_B(mp, 1) +
314 MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
315 XFS_INODE_CLUSTER_SIZE(mp)) +
316 128 * 5 +
317 XFS_ALLOCFREE_LOG_RES(mp, 1) +
318 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
319 XFS_ALLOCFREE_LOG_COUNT(mp, 1));
320}
321
322
323
324
325
326STATIC uint
327xfs_calc_ichange_reservation(
328 struct xfs_mount *mp)
329{
330 return XFS_DQUOT_LOGRES(mp) +
331 mp->m_sb.sb_inodesize +
332 mp->m_sb.sb_sectsize +
333 512;
334
335}
336
337
338
339
340
341
342
343STATIC uint
344xfs_calc_growdata_reservation(
345 struct xfs_mount *mp)
346{
347 return mp->m_sb.sb_sectsize * 3 +
348 XFS_ALLOCFREE_LOG_RES(mp, 1) +
349 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1));
350}
351
352
353
354
355
356
357
358
359
360
361
362STATIC uint
363xfs_calc_growrtalloc_reservation(
364 struct xfs_mount *mp)
365{
366 return 2 * mp->m_sb.sb_sectsize +
367 XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
368 mp->m_sb.sb_inodesize +
369 XFS_ALLOCFREE_LOG_RES(mp, 1) +
370 128 * (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
371 XFS_ALLOCFREE_LOG_COUNT(mp, 1));
372}
373
374
375
376
377
378
379STATIC uint
380xfs_calc_growrtzero_reservation(
381 struct xfs_mount *mp)
382{
383 return mp->m_sb.sb_blocksize + 128;
384}
385
386
387
388
389
390
391
392
393
394
395
396STATIC uint
397xfs_calc_growrtfree_reservation(
398 struct xfs_mount *mp)
399{
400 return mp->m_sb.sb_sectsize +
401 2 * mp->m_sb.sb_inodesize +
402 mp->m_sb.sb_blocksize +
403 mp->m_rsumsize +
404 128 * 5;
405}
406
407
408
409
410
411STATIC uint
412xfs_calc_swrite_reservation(
413 struct xfs_mount *mp)
414{
415 return mp->m_sb.sb_inodesize + 128;
416}
417
418
419
420
421
422STATIC uint
423xfs_calc_writeid_reservation(xfs_mount_t *mp)
424{
425 return mp->m_sb.sb_inodesize + 128;
426}
427
428
429
430
431
432
433
434
435
436STATIC uint
437xfs_calc_addafork_reservation(
438 struct xfs_mount *mp)
439{
440 return XFS_DQUOT_LOGRES(mp) +
441 mp->m_sb.sb_inodesize +
442 mp->m_sb.sb_sectsize * 2 +
443 mp->m_dirblksize +
444 XFS_FSB_TO_B(mp, XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) +
445 XFS_ALLOCFREE_LOG_RES(mp, 1) +
446 128 * (4 + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1 +
447 XFS_ALLOCFREE_LOG_COUNT(mp, 1));
448}
449
450
451
452
453
454
455
456
457
458
459
460
461STATIC uint
462xfs_calc_attrinval_reservation(
463 struct xfs_mount *mp)
464{
465 return MAX((mp->m_sb.sb_inodesize +
466 XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
467 128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))),
468 (4 * mp->m_sb.sb_sectsize +
469 4 * mp->m_sb.sb_sectsize +
470 mp->m_sb.sb_sectsize +
471 XFS_ALLOCFREE_LOG_RES(mp, 4) +
472 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))));
473}
474
475
476
477
478
479
480
481
482
483
484
485STATIC uint
486xfs_calc_attrset_reservation(
487 struct xfs_mount *mp)
488{
489 return XFS_DQUOT_LOGRES(mp) +
490 mp->m_sb.sb_inodesize +
491 mp->m_sb.sb_sectsize +
492 XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
493 128 * (2 + XFS_DA_NODE_MAXDEPTH);
494}
495
496
497
498
499
500
501
502
503
504
505
506
507STATIC uint
508xfs_calc_attrrm_reservation(
509 struct xfs_mount *mp)
510{
511 return XFS_DQUOT_LOGRES(mp) +
512 MAX((mp->m_sb.sb_inodesize +
513 XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
514 XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
515 128 * (1 + XFS_DA_NODE_MAXDEPTH +
516 XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
517 (2 * mp->m_sb.sb_sectsize +
518 2 * mp->m_sb.sb_sectsize +
519 mp->m_sb.sb_sectsize +
520 XFS_ALLOCFREE_LOG_RES(mp, 2) +
521 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
522}
523
524
525
526
527STATIC uint
528xfs_calc_clear_agi_bucket_reservation(
529 struct xfs_mount *mp)
530{
531 return mp->m_sb.sb_sectsize + 128;
532}
533
534
535
536
537
538void
539xfs_trans_init(
540 struct xfs_mount *mp)
541{
542 struct xfs_trans_reservations *resp = &mp->m_reservations;
543
544 resp->tr_write = xfs_calc_write_reservation(mp);
545 resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
546 resp->tr_rename = xfs_calc_rename_reservation(mp);
547 resp->tr_link = xfs_calc_link_reservation(mp);
548 resp->tr_remove = xfs_calc_remove_reservation(mp);
549 resp->tr_symlink = xfs_calc_symlink_reservation(mp);
550 resp->tr_create = xfs_calc_create_reservation(mp);
551 resp->tr_mkdir = xfs_calc_mkdir_reservation(mp);
552 resp->tr_ifree = xfs_calc_ifree_reservation(mp);
553 resp->tr_ichange = xfs_calc_ichange_reservation(mp);
554 resp->tr_growdata = xfs_calc_growdata_reservation(mp);
555 resp->tr_swrite = xfs_calc_swrite_reservation(mp);
556 resp->tr_writeid = xfs_calc_writeid_reservation(mp);
557 resp->tr_addafork = xfs_calc_addafork_reservation(mp);
558 resp->tr_attrinval = xfs_calc_attrinval_reservation(mp);
559 resp->tr_attrset = xfs_calc_attrset_reservation(mp);
560 resp->tr_attrrm = xfs_calc_attrrm_reservation(mp);
561 resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp);
562 resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp);
563 resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp);
564 resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp);
565}
566
567
568
569
570
571
572
573
574
575xfs_trans_t *
576xfs_trans_alloc(
577 xfs_mount_t *mp,
578 uint type)
579{
580 xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
581 return _xfs_trans_alloc(mp, type, KM_SLEEP);
582}
583
584xfs_trans_t *
585_xfs_trans_alloc(
586 xfs_mount_t *mp,
587 uint type,
588 uint memflags)
589{
590 xfs_trans_t *tp;
591
592 atomic_inc(&mp->m_active_trans);
593
594 tp = kmem_zone_zalloc(xfs_trans_zone, memflags);
595 tp->t_magic = XFS_TRANS_MAGIC;
596 tp->t_type = type;
597 tp->t_mountp = mp;
598 INIT_LIST_HEAD(&tp->t_items);
599 INIT_LIST_HEAD(&tp->t_busy);
600 return tp;
601}
602
603
604
605
606
607STATIC void
608xfs_trans_free(
609 struct xfs_trans *tp)
610{
611 struct xfs_busy_extent *busyp, *n;
612
613 list_for_each_entry_safe(busyp, n, &tp->t_busy, list)
614 xfs_alloc_busy_clear(tp->t_mountp, busyp);
615
616 atomic_dec(&tp->t_mountp->m_active_trans);
617 xfs_trans_free_dqinfo(tp);
618 kmem_zone_free(xfs_trans_zone, tp);
619}
620
621
622
623
624
625
626
627
628
629xfs_trans_t *
630xfs_trans_dup(
631 xfs_trans_t *tp)
632{
633 xfs_trans_t *ntp;
634
635 ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
636
637
638
639
640 ntp->t_magic = XFS_TRANS_MAGIC;
641 ntp->t_type = tp->t_type;
642 ntp->t_mountp = tp->t_mountp;
643 INIT_LIST_HEAD(&ntp->t_items);
644 INIT_LIST_HEAD(&ntp->t_busy);
645
646 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
647 ASSERT(tp->t_ticket != NULL);
648
649 ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE);
650 ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket);
651 ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;
652 tp->t_blk_res = tp->t_blk_res_used;
653 ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used;
654 tp->t_rtx_res = tp->t_rtx_res_used;
655 ntp->t_pflags = tp->t_pflags;
656
657 xfs_trans_dup_dqinfo(tp, ntp);
658
659 atomic_inc(&tp->t_mountp->m_active_trans);
660 return ntp;
661}
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677int
678xfs_trans_reserve(
679 xfs_trans_t *tp,
680 uint blocks,
681 uint logspace,
682 uint rtextents,
683 uint flags,
684 uint logcount)
685{
686 int log_flags;
687 int error = 0;
688 int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
689
690
691 current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
692
693
694
695
696
697
698 if (blocks > 0) {
699 error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
700 -((int64_t)blocks), rsvd);
701 if (error != 0) {
702 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
703 return (XFS_ERROR(ENOSPC));
704 }
705 tp->t_blk_res += blocks;
706 }
707
708
709
710
711 if (logspace > 0) {
712 ASSERT((tp->t_log_res == 0) || (tp->t_log_res == logspace));
713 ASSERT((tp->t_log_count == 0) ||
714 (tp->t_log_count == logcount));
715 if (flags & XFS_TRANS_PERM_LOG_RES) {
716 log_flags = XFS_LOG_PERM_RESERV;
717 tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
718 } else {
719 ASSERT(tp->t_ticket == NULL);
720 ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
721 log_flags = 0;
722 }
723
724 error = xfs_log_reserve(tp->t_mountp, logspace, logcount,
725 &tp->t_ticket,
726 XFS_TRANSACTION, log_flags, tp->t_type);
727 if (error) {
728 goto undo_blocks;
729 }
730 tp->t_log_res = logspace;
731 tp->t_log_count = logcount;
732 }
733
734
735
736
737
738
739 if (rtextents > 0) {
740 error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
741 -((int64_t)rtextents), rsvd);
742 if (error) {
743 error = XFS_ERROR(ENOSPC);
744 goto undo_log;
745 }
746 tp->t_rtx_res += rtextents;
747 }
748
749 return 0;
750
751
752
753
754
755undo_log:
756 if (logspace > 0) {
757 if (flags & XFS_TRANS_PERM_LOG_RES) {
758 log_flags = XFS_LOG_REL_PERM_RESERV;
759 } else {
760 log_flags = 0;
761 }
762 xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags);
763 tp->t_ticket = NULL;
764 tp->t_log_res = 0;
765 tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
766 }
767
768undo_blocks:
769 if (blocks > 0) {
770 xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
771 (int64_t)blocks, rsvd);
772 tp->t_blk_res = 0;
773 }
774
775 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
776
777 return error;
778}
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796void
797xfs_trans_mod_sb(
798 xfs_trans_t *tp,
799 uint field,
800 int64_t delta)
801{
802 uint32_t flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY);
803 xfs_mount_t *mp = tp->t_mountp;
804
805 switch (field) {
806 case XFS_TRANS_SB_ICOUNT:
807 tp->t_icount_delta += delta;
808 if (xfs_sb_version_haslazysbcount(&mp->m_sb))
809 flags &= ~XFS_TRANS_SB_DIRTY;
810 break;
811 case XFS_TRANS_SB_IFREE:
812 tp->t_ifree_delta += delta;
813 if (xfs_sb_version_haslazysbcount(&mp->m_sb))
814 flags &= ~XFS_TRANS_SB_DIRTY;
815 break;
816 case XFS_TRANS_SB_FDBLOCKS:
817
818
819
820
821
822 if (delta < 0) {
823 tp->t_blk_res_used += (uint)-delta;
824 ASSERT(tp->t_blk_res_used <= tp->t_blk_res);
825 }
826 tp->t_fdblocks_delta += delta;
827 if (xfs_sb_version_haslazysbcount(&mp->m_sb))
828 flags &= ~XFS_TRANS_SB_DIRTY;
829 break;
830 case XFS_TRANS_SB_RES_FDBLOCKS:
831
832
833
834
835
836 ASSERT(delta < 0);
837 tp->t_res_fdblocks_delta += delta;
838 if (xfs_sb_version_haslazysbcount(&mp->m_sb))
839 flags &= ~XFS_TRANS_SB_DIRTY;
840 break;
841 case XFS_TRANS_SB_FREXTENTS:
842
843
844
845
846
847 if (delta < 0) {
848 tp->t_rtx_res_used += (uint)-delta;
849 ASSERT(tp->t_rtx_res_used <= tp->t_rtx_res);
850 }
851 tp->t_frextents_delta += delta;
852 break;
853 case XFS_TRANS_SB_RES_FREXTENTS:
854
855
856
857
858
859 ASSERT(delta < 0);
860 tp->t_res_frextents_delta += delta;
861 break;
862 case XFS_TRANS_SB_DBLOCKS:
863 ASSERT(delta > 0);
864 tp->t_dblocks_delta += delta;
865 break;
866 case XFS_TRANS_SB_AGCOUNT:
867 ASSERT(delta > 0);
868 tp->t_agcount_delta += delta;
869 break;
870 case XFS_TRANS_SB_IMAXPCT:
871 tp->t_imaxpct_delta += delta;
872 break;
873 case XFS_TRANS_SB_REXTSIZE:
874 tp->t_rextsize_delta += delta;
875 break;
876 case XFS_TRANS_SB_RBMBLOCKS:
877 tp->t_rbmblocks_delta += delta;
878 break;
879 case XFS_TRANS_SB_RBLOCKS:
880 tp->t_rblocks_delta += delta;
881 break;
882 case XFS_TRANS_SB_REXTENTS:
883 tp->t_rextents_delta += delta;
884 break;
885 case XFS_TRANS_SB_REXTSLOG:
886 tp->t_rextslog_delta += delta;
887 break;
888 default:
889 ASSERT(0);
890 return;
891 }
892
893 tp->t_flags |= flags;
894}
895
896
897
898
899
900
901
902
903
904STATIC void
905xfs_trans_apply_sb_deltas(
906 xfs_trans_t *tp)
907{
908 xfs_dsb_t *sbp;
909 xfs_buf_t *bp;
910 int whole = 0;
911
912 bp = xfs_trans_getsb(tp, tp->t_mountp, 0);
913 sbp = XFS_BUF_TO_SBP(bp);
914
915
916
917
918 ASSERT((tp->t_fdblocks_delta + tp->t_res_fdblocks_delta) ==
919 (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
920 tp->t_ag_btree_delta));
921
922
923
924
925 if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
926 if (tp->t_icount_delta)
927 be64_add_cpu(&sbp->sb_icount, tp->t_icount_delta);
928 if (tp->t_ifree_delta)
929 be64_add_cpu(&sbp->sb_ifree, tp->t_ifree_delta);
930 if (tp->t_fdblocks_delta)
931 be64_add_cpu(&sbp->sb_fdblocks, tp->t_fdblocks_delta);
932 if (tp->t_res_fdblocks_delta)
933 be64_add_cpu(&sbp->sb_fdblocks, tp->t_res_fdblocks_delta);
934 }
935
936 if (tp->t_frextents_delta)
937 be64_add_cpu(&sbp->sb_frextents, tp->t_frextents_delta);
938 if (tp->t_res_frextents_delta)
939 be64_add_cpu(&sbp->sb_frextents, tp->t_res_frextents_delta);
940
941 if (tp->t_dblocks_delta) {
942 be64_add_cpu(&sbp->sb_dblocks, tp->t_dblocks_delta);
943 whole = 1;
944 }
945 if (tp->t_agcount_delta) {
946 be32_add_cpu(&sbp->sb_agcount, tp->t_agcount_delta);
947 whole = 1;
948 }
949 if (tp->t_imaxpct_delta) {
950 sbp->sb_imax_pct += tp->t_imaxpct_delta;
951 whole = 1;
952 }
953 if (tp->t_rextsize_delta) {
954 be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta);
955 whole = 1;
956 }
957 if (tp->t_rbmblocks_delta) {
958 be32_add_cpu(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta);
959 whole = 1;
960 }
961 if (tp->t_rblocks_delta) {
962 be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta);
963 whole = 1;
964 }
965 if (tp->t_rextents_delta) {
966 be64_add_cpu(&sbp->sb_rextents, tp->t_rextents_delta);
967 whole = 1;
968 }
969 if (tp->t_rextslog_delta) {
970 sbp->sb_rextslog += tp->t_rextslog_delta;
971 whole = 1;
972 }
973
974 if (whole)
975
976
977
978 xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_dsb_t) - 1);
979 else
980
981
982
983
984 xfs_trans_log_buf(tp, bp, offsetof(xfs_dsb_t, sb_icount),
985 offsetof(xfs_dsb_t, sb_frextents) +
986 sizeof(sbp->sb_frextents) - 1);
987}
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008void
1009xfs_trans_unreserve_and_mod_sb(
1010 xfs_trans_t *tp)
1011{
1012 xfs_mod_sb_t msb[9];
1013 xfs_mod_sb_t *msbp;
1014 xfs_mount_t *mp = tp->t_mountp;
1015
1016 int error;
1017 int rsvd;
1018 int64_t blkdelta = 0;
1019 int64_t rtxdelta = 0;
1020 int64_t idelta = 0;
1021 int64_t ifreedelta = 0;
1022
1023 msbp = msb;
1024 rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
1025
1026
1027 if (tp->t_blk_res > 0)
1028 blkdelta = tp->t_blk_res;
1029 if ((tp->t_fdblocks_delta != 0) &&
1030 (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
1031 (tp->t_flags & XFS_TRANS_SB_DIRTY)))
1032 blkdelta += tp->t_fdblocks_delta;
1033
1034 if (tp->t_rtx_res > 0)
1035 rtxdelta = tp->t_rtx_res;
1036 if ((tp->t_frextents_delta != 0) &&
1037 (tp->t_flags & XFS_TRANS_SB_DIRTY))
1038 rtxdelta += tp->t_frextents_delta;
1039
1040 if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
1041 (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
1042 idelta = tp->t_icount_delta;
1043 ifreedelta = tp->t_ifree_delta;
1044 }
1045
1046
1047 if (blkdelta) {
1048 error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
1049 blkdelta, rsvd);
1050 if (error)
1051 goto out;
1052 }
1053
1054 if (idelta) {
1055 error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT,
1056 idelta, rsvd);
1057 if (error)
1058 goto out_undo_fdblocks;
1059 }
1060
1061 if (ifreedelta) {
1062 error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
1063 ifreedelta, rsvd);
1064 if (error)
1065 goto out_undo_icount;
1066 }
1067
1068
1069 if (rtxdelta != 0) {
1070 msbp->msb_field = XFS_SBS_FREXTENTS;
1071 msbp->msb_delta = rtxdelta;
1072 msbp++;
1073 }
1074
1075 if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
1076 if (tp->t_dblocks_delta != 0) {
1077 msbp->msb_field = XFS_SBS_DBLOCKS;
1078 msbp->msb_delta = tp->t_dblocks_delta;
1079 msbp++;
1080 }
1081 if (tp->t_agcount_delta != 0) {
1082 msbp->msb_field = XFS_SBS_AGCOUNT;
1083 msbp->msb_delta = tp->t_agcount_delta;
1084 msbp++;
1085 }
1086 if (tp->t_imaxpct_delta != 0) {
1087 msbp->msb_field = XFS_SBS_IMAX_PCT;
1088 msbp->msb_delta = tp->t_imaxpct_delta;
1089 msbp++;
1090 }
1091 if (tp->t_rextsize_delta != 0) {
1092 msbp->msb_field = XFS_SBS_REXTSIZE;
1093 msbp->msb_delta = tp->t_rextsize_delta;
1094 msbp++;
1095 }
1096 if (tp->t_rbmblocks_delta != 0) {
1097 msbp->msb_field = XFS_SBS_RBMBLOCKS;
1098 msbp->msb_delta = tp->t_rbmblocks_delta;
1099 msbp++;
1100 }
1101 if (tp->t_rblocks_delta != 0) {
1102 msbp->msb_field = XFS_SBS_RBLOCKS;
1103 msbp->msb_delta = tp->t_rblocks_delta;
1104 msbp++;
1105 }
1106 if (tp->t_rextents_delta != 0) {
1107 msbp->msb_field = XFS_SBS_REXTENTS;
1108 msbp->msb_delta = tp->t_rextents_delta;
1109 msbp++;
1110 }
1111 if (tp->t_rextslog_delta != 0) {
1112 msbp->msb_field = XFS_SBS_REXTSLOG;
1113 msbp->msb_delta = tp->t_rextslog_delta;
1114 msbp++;
1115 }
1116 }
1117
1118
1119
1120
1121 if (msbp > msb) {
1122 error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
1123 (uint)(msbp - msb), rsvd);
1124 if (error)
1125 goto out_undo_ifreecount;
1126 }
1127
1128 return;
1129
1130out_undo_ifreecount:
1131 if (ifreedelta)
1132 xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
1133out_undo_icount:
1134 if (idelta)
1135 xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd);
1136out_undo_fdblocks:
1137 if (blkdelta)
1138 xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
1139out:
1140 ASSERT(error == 0);
1141 return;
1142}
1143
1144
1145
1146
1147
1148
1149void
1150xfs_trans_add_item(
1151 struct xfs_trans *tp,
1152 struct xfs_log_item *lip)
1153{
1154 struct xfs_log_item_desc *lidp;
1155
1156 ASSERT(lip->li_mountp = tp->t_mountp);
1157 ASSERT(lip->li_ailp = tp->t_mountp->m_ail);
1158
1159 lidp = kmem_zone_zalloc(xfs_log_item_desc_zone, KM_SLEEP | KM_NOFS);
1160
1161 lidp->lid_item = lip;
1162 lidp->lid_flags = 0;
1163 lidp->lid_size = 0;
1164 list_add_tail(&lidp->lid_trans, &tp->t_items);
1165
1166 lip->li_desc = lidp;
1167}
1168
1169STATIC void
1170xfs_trans_free_item_desc(
1171 struct xfs_log_item_desc *lidp)
1172{
1173 list_del_init(&lidp->lid_trans);
1174 kmem_zone_free(xfs_log_item_desc_zone, lidp);
1175}
1176
1177
1178
1179
1180void
1181xfs_trans_del_item(
1182 struct xfs_log_item *lip)
1183{
1184 xfs_trans_free_item_desc(lip->li_desc);
1185 lip->li_desc = NULL;
1186}
1187
1188
1189
1190
1191
1192void
1193xfs_trans_free_items(
1194 struct xfs_trans *tp,
1195 xfs_lsn_t commit_lsn,
1196 int flags)
1197{
1198 struct xfs_log_item_desc *lidp, *next;
1199
1200 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
1201 struct xfs_log_item *lip = lidp->lid_item;
1202
1203 lip->li_desc = NULL;
1204
1205 if (commit_lsn != NULLCOMMITLSN)
1206 IOP_COMMITTING(lip, commit_lsn);
1207 if (flags & XFS_TRANS_ABORT)
1208 lip->li_flags |= XFS_LI_ABORTED;
1209 IOP_UNLOCK(lip);
1210
1211 xfs_trans_free_item_desc(lidp);
1212 }
1213}
1214
1215
1216
1217
1218
1219
1220
1221STATIC void
1222xfs_trans_unlock_items(
1223 struct xfs_trans *tp,
1224 xfs_lsn_t commit_lsn)
1225{
1226 struct xfs_log_item_desc *lidp, *next;
1227
1228 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
1229 struct xfs_log_item *lip = lidp->lid_item;
1230
1231 lip->li_desc = NULL;
1232
1233 if (commit_lsn != NULLCOMMITLSN)
1234 IOP_COMMITTING(lip, commit_lsn);
1235 IOP_UNLOCK(lip);
1236
1237
1238
1239
1240
1241 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1242 xfs_trans_free_item_desc(lidp);
1243 }
1244}
1245
1246
1247
1248
1249
1250
1251
1252static uint
1253xfs_trans_count_vecs(
1254 struct xfs_trans *tp)
1255{
1256 int nvecs;
1257 struct xfs_log_item_desc *lidp;
1258
1259 nvecs = 1;
1260
1261
1262
1263
1264
1265 if (list_empty(&tp->t_items)) {
1266 ASSERT(0);
1267 return 0;
1268 }
1269
1270 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
1271
1272
1273
1274 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1275 continue;
1276 lidp->lid_size = IOP_SIZE(lidp->lid_item);
1277 nvecs += lidp->lid_size;
1278 }
1279
1280 return nvecs;
1281}
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292static void
1293xfs_trans_fill_vecs(
1294 struct xfs_trans *tp,
1295 struct xfs_log_iovec *log_vector)
1296{
1297 struct xfs_log_item_desc *lidp;
1298 struct xfs_log_iovec *vecp;
1299 uint nitems;
1300
1301
1302
1303
1304
1305 vecp = log_vector + 1;
1306
1307 nitems = 0;
1308 ASSERT(!list_empty(&tp->t_items));
1309 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
1310
1311 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1312 continue;
1313
1314
1315
1316
1317
1318 if (lidp->lid_size)
1319 nitems++;
1320 IOP_FORMAT(lidp->lid_item, vecp);
1321 vecp += lidp->lid_size;
1322 IOP_PIN(lidp->lid_item);
1323 }
1324
1325
1326
1327
1328
1329
1330 tp->t_header.th_magic = XFS_TRANS_HEADER_MAGIC;
1331 tp->t_header.th_type = tp->t_type;
1332 tp->t_header.th_num_items = nitems;
1333 log_vector->i_addr = (xfs_caddr_t)&tp->t_header;
1334 log_vector->i_len = sizeof(xfs_trans_header_t);
1335 log_vector->i_type = XLOG_REG_TYPE_TRANSHDR;
1336}
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353static void
1354xfs_trans_item_committed(
1355 struct xfs_log_item *lip,
1356 xfs_lsn_t commit_lsn,
1357 int aborted)
1358{
1359 xfs_lsn_t item_lsn;
1360 struct xfs_ail *ailp;
1361
1362 if (aborted)
1363 lip->li_flags |= XFS_LI_ABORTED;
1364 item_lsn = IOP_COMMITTED(lip, commit_lsn);
1365
1366
1367 if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0)
1368 return;
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380 ailp = lip->li_ailp;
1381 spin_lock(&ailp->xa_lock);
1382 if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) {
1383
1384
1385
1386
1387
1388
1389 xfs_trans_ail_update(ailp, lip, item_lsn);
1390 } else {
1391 spin_unlock(&ailp->xa_lock);
1392 }
1393
1394
1395
1396
1397
1398
1399
1400 IOP_UNPIN(lip, 0);
1401}
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412STATIC void
1413xfs_trans_committed(
1414 void *arg,
1415 int abortflag)
1416{
1417 struct xfs_trans *tp = arg;
1418 struct xfs_log_item_desc *lidp, *next;
1419
1420 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
1421 xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag);
1422 xfs_trans_free_item_desc(lidp);
1423 }
1424
1425 xfs_trans_free(tp);
1426}
1427
1428static inline void
1429xfs_log_item_batch_insert(
1430 struct xfs_ail *ailp,
1431 struct xfs_log_item **log_items,
1432 int nr_items,
1433 xfs_lsn_t commit_lsn)
1434{
1435 int i;
1436
1437 spin_lock(&ailp->xa_lock);
1438
1439 xfs_trans_ail_update_bulk(ailp, log_items, nr_items, commit_lsn);
1440
1441 for (i = 0; i < nr_items; i++)
1442 IOP_UNPIN(log_items[i], 0);
1443}
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458void
1459xfs_trans_committed_bulk(
1460 struct xfs_ail *ailp,
1461 struct xfs_log_vec *log_vector,
1462 xfs_lsn_t commit_lsn,
1463 int aborted)
1464{
1465#define LOG_ITEM_BATCH_SIZE 32
1466 struct xfs_log_item *log_items[LOG_ITEM_BATCH_SIZE];
1467 struct xfs_log_vec *lv;
1468 int i = 0;
1469
1470
1471 for (lv = log_vector; lv; lv = lv->lv_next ) {
1472 struct xfs_log_item *lip = lv->lv_item;
1473 xfs_lsn_t item_lsn;
1474
1475 if (aborted)
1476 lip->li_flags |= XFS_LI_ABORTED;
1477 item_lsn = IOP_COMMITTED(lip, commit_lsn);
1478
1479
1480 if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0)
1481 continue;
1482
1483
1484
1485
1486
1487 if (aborted) {
1488 ASSERT(XFS_FORCED_SHUTDOWN(ailp->xa_mount));
1489 IOP_UNPIN(lip, 1);
1490 continue;
1491 }
1492
1493 if (item_lsn != commit_lsn) {
1494
1495
1496
1497
1498
1499
1500 spin_lock(&ailp->xa_lock);
1501 if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0)
1502 xfs_trans_ail_update(ailp, lip, item_lsn);
1503 else
1504 spin_unlock(&ailp->xa_lock);
1505 IOP_UNPIN(lip, 0);
1506 continue;
1507 }
1508
1509
1510 log_items[i++] = lv->lv_item;
1511 if (i >= LOG_ITEM_BATCH_SIZE) {
1512 xfs_log_item_batch_insert(ailp, log_items,
1513 LOG_ITEM_BATCH_SIZE, commit_lsn);
1514 i = 0;
1515 }
1516 }
1517
1518
1519 if (i)
1520 xfs_log_item_batch_insert(ailp, log_items, i, commit_lsn);
1521}
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534STATIC void
1535xfs_trans_uncommit(
1536 struct xfs_trans *tp,
1537 uint flags)
1538{
1539 struct xfs_log_item_desc *lidp, *n;
1540
1541 list_for_each_entry_safe(lidp, n, &tp->t_items, lid_trans) {
1542 if (lidp->lid_flags & XFS_LID_DIRTY)
1543 IOP_UNPIN(lidp->lid_item, 1);
1544 }
1545
1546 xfs_trans_unreserve_and_mod_sb(tp);
1547 xfs_trans_unreserve_and_mod_dquots(tp);
1548
1549 xfs_trans_free_items(tp, NULLCOMMITLSN, flags);
1550 xfs_trans_free(tp);
1551}
1552
1553
1554
1555
1556
1557
1558static int
1559xfs_trans_commit_iclog(
1560 struct xfs_mount *mp,
1561 struct xfs_trans *tp,
1562 xfs_lsn_t *commit_lsn,
1563 int flags)
1564{
1565 int shutdown;
1566 int error;
1567 int log_flags = 0;
1568 struct xlog_in_core *commit_iclog;
1569#define XFS_TRANS_LOGVEC_COUNT 16
1570 struct xfs_log_iovec log_vector_fast[XFS_TRANS_LOGVEC_COUNT];
1571 struct xfs_log_iovec *log_vector;
1572 uint nvec;
1573
1574
1575
1576
1577
1578
1579
1580
1581 nvec = xfs_trans_count_vecs(tp);
1582 if (nvec == 0) {
1583 return ENOMEM;
1584 } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) {
1585 log_vector = log_vector_fast;
1586 } else {
1587 log_vector = (xfs_log_iovec_t *)kmem_alloc(nvec *
1588 sizeof(xfs_log_iovec_t),
1589 KM_SLEEP);
1590 }
1591
1592
1593
1594
1595
1596 xfs_trans_fill_vecs(tp, log_vector);
1597
1598 if (flags & XFS_TRANS_RELEASE_LOG_RES)
1599 log_flags = XFS_LOG_REL_PERM_RESERV;
1600
1601 error = xfs_log_write(mp, log_vector, nvec, tp->t_ticket, &(tp->t_lsn));
1602
1603
1604
1605
1606
1607
1608 *commit_lsn = xfs_log_done(mp, tp->t_ticket, &commit_iclog, log_flags);
1609
1610 tp->t_commit_lsn = *commit_lsn;
1611 trace_xfs_trans_commit_lsn(tp);
1612
1613 if (nvec > XFS_TRANS_LOGVEC_COUNT)
1614 kmem_free(log_vector);
1615
1616
1617
1618
1619
1620 if (error || *commit_lsn == -1) {
1621 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
1622 xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT);
1623 return XFS_ERROR(EIO);
1624 }
1625
1626
1627
1628
1629
1630
1631
1632 xfs_trans_unreserve_and_mod_sb(tp);
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646 tp->t_logcb.cb_func = xfs_trans_committed;
1647 tp->t_logcb.cb_arg = tp;
1648
1649
1650
1651
1652
1653
1654
1655
1656 shutdown = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
1657
1658
1659
1660
1661 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676 xfs_trans_unlock_items(tp, *commit_lsn);
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688 if (shutdown)
1689 xfs_trans_committed(tp, XFS_LI_ABORTED);
1690
1691
1692
1693
1694
1695
1696 return xfs_log_release_iclog(mp, commit_iclog);
1697}
1698
1699
1700
1701
1702
1703
1704
1705STATIC struct xfs_log_vec *
1706xfs_trans_alloc_log_vecs(
1707 xfs_trans_t *tp)
1708{
1709 struct xfs_log_item_desc *lidp;
1710 struct xfs_log_vec *lv = NULL;
1711 struct xfs_log_vec *ret_lv = NULL;
1712
1713
1714
1715 if (list_empty(&tp->t_items)) {
1716 ASSERT(0);
1717 return NULL;
1718 }
1719
1720 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
1721 struct xfs_log_vec *new_lv;
1722
1723
1724 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1725 continue;
1726
1727
1728 lidp->lid_size = IOP_SIZE(lidp->lid_item);
1729 if (!lidp->lid_size)
1730 continue;
1731
1732 new_lv = kmem_zalloc(sizeof(*new_lv) +
1733 lidp->lid_size * sizeof(struct xfs_log_iovec),
1734 KM_SLEEP);
1735
1736
1737 new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1];
1738 new_lv->lv_niovecs = lidp->lid_size;
1739 new_lv->lv_item = lidp->lid_item;
1740 if (!ret_lv)
1741 ret_lv = new_lv;
1742 else
1743 lv->lv_next = new_lv;
1744 lv = new_lv;
1745 }
1746
1747 return ret_lv;
1748}
1749
1750static int
1751xfs_trans_commit_cil(
1752 struct xfs_mount *mp,
1753 struct xfs_trans *tp,
1754 xfs_lsn_t *commit_lsn,
1755 int flags)
1756{
1757 struct xfs_log_vec *log_vector;
1758
1759
1760
1761
1762
1763
1764 log_vector = xfs_trans_alloc_log_vecs(tp);
1765 if (!log_vector)
1766 return ENOMEM;
1767
1768 xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags);
1769
1770 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
1771 xfs_trans_free(tp);
1772 return 0;
1773}
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789int
1790_xfs_trans_commit(
1791 struct xfs_trans *tp,
1792 uint flags,
1793 int *log_flushed)
1794{
1795 struct xfs_mount *mp = tp->t_mountp;
1796 xfs_lsn_t commit_lsn = -1;
1797 int error = 0;
1798 int log_flags = 0;
1799 int sync = tp->t_flags & XFS_TRANS_SYNC;
1800
1801
1802
1803
1804
1805 if (flags & XFS_TRANS_RELEASE_LOG_RES) {
1806 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
1807 log_flags = XFS_LOG_REL_PERM_RESERV;
1808 }
1809
1810
1811
1812
1813
1814
1815
1816
1817 if (!(tp->t_flags & XFS_TRANS_DIRTY))
1818 goto out_unreserve;
1819
1820 if (XFS_FORCED_SHUTDOWN(mp)) {
1821 error = XFS_ERROR(EIO);
1822 goto out_unreserve;
1823 }
1824
1825 ASSERT(tp->t_ticket != NULL);
1826
1827
1828
1829
1830 if (tp->t_flags & XFS_TRANS_SB_DIRTY)
1831 xfs_trans_apply_sb_deltas(tp);
1832 xfs_trans_apply_dquot_deltas(tp);
1833
1834 if (mp->m_flags & XFS_MOUNT_DELAYLOG)
1835 error = xfs_trans_commit_cil(mp, tp, &commit_lsn, flags);
1836 else
1837 error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags);
1838
1839 if (error == ENOMEM) {
1840 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
1841 error = XFS_ERROR(EIO);
1842 goto out_unreserve;
1843 }
1844
1845
1846
1847
1848
1849 if (sync) {
1850 if (!error) {
1851 error = _xfs_log_force_lsn(mp, commit_lsn,
1852 XFS_LOG_SYNC, log_flushed);
1853 }
1854 XFS_STATS_INC(xs_trans_sync);
1855 } else {
1856 XFS_STATS_INC(xs_trans_async);
1857 }
1858
1859 return error;
1860
1861out_unreserve:
1862 xfs_trans_unreserve_and_mod_sb(tp);
1863
1864
1865
1866
1867
1868
1869 xfs_trans_unreserve_and_mod_dquots(tp);
1870 if (tp->t_ticket) {
1871 commit_lsn = xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
1872 if (commit_lsn == -1 && !error)
1873 error = XFS_ERROR(EIO);
1874 }
1875 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
1876 xfs_trans_free_items(tp, NULLCOMMITLSN, error ? XFS_TRANS_ABORT : 0);
1877 xfs_trans_free(tp);
1878
1879 XFS_STATS_INC(xs_trans_empty);
1880 return error;
1881}
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891void
1892xfs_trans_cancel(
1893 xfs_trans_t *tp,
1894 int flags)
1895{
1896 int log_flags;
1897 xfs_mount_t *mp = tp->t_mountp;
1898
1899
1900
1901
1902
1903 if ((flags & XFS_TRANS_ABORT) && !(tp->t_flags & XFS_TRANS_DIRTY))
1904 flags &= ~XFS_TRANS_ABORT;
1905
1906
1907
1908
1909
1910 if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
1911 XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
1912 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1913 }
1914#ifdef DEBUG
1915 if (!(flags & XFS_TRANS_ABORT) && !XFS_FORCED_SHUTDOWN(mp)) {
1916 struct xfs_log_item_desc *lidp;
1917
1918 list_for_each_entry(lidp, &tp->t_items, lid_trans)
1919 ASSERT(!(lidp->lid_item->li_type == XFS_LI_EFD));
1920 }
1921#endif
1922 xfs_trans_unreserve_and_mod_sb(tp);
1923 xfs_trans_unreserve_and_mod_dquots(tp);
1924
1925 if (tp->t_ticket) {
1926 if (flags & XFS_TRANS_RELEASE_LOG_RES) {
1927 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
1928 log_flags = XFS_LOG_REL_PERM_RESERV;
1929 } else {
1930 log_flags = 0;
1931 }
1932 xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
1933 }
1934
1935
1936 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
1937
1938 xfs_trans_free_items(tp, NULLCOMMITLSN, flags);
1939 xfs_trans_free(tp);
1940}
1941
1942
1943
1944
1945
1946
1947
1948
1949int
1950xfs_trans_roll(
1951 struct xfs_trans **tpp,
1952 struct xfs_inode *dp)
1953{
1954 struct xfs_trans *trans;
1955 unsigned int logres, count;
1956 int error;
1957
1958
1959
1960
1961 trans = *tpp;
1962 xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
1963
1964
1965
1966
1967 logres = trans->t_log_res;
1968 count = trans->t_log_count;
1969 *tpp = xfs_trans_dup(trans);
1970
1971
1972
1973
1974
1975
1976
1977
1978 error = xfs_trans_commit(trans, 0);
1979 if (error)
1980 return (error);
1981
1982 trans = *tpp;
1983
1984
1985
1986
1987
1988 xfs_log_ticket_put(trans->t_ticket);
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999 error = xfs_trans_reserve(trans, 0, logres, 0,
2000 XFS_TRANS_PERM_LOG_RES, count);
2001
2002
2003
2004 if (error)
2005 return error;
2006
2007 xfs_trans_ijoin(trans, dp);
2008 return 0;
2009}
2010