diff options
author | Dave Chinner <dchinner@redhat.com> | 2010-03-07 19:28:28 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-05-19 10:58:08 -0400 |
commit | 0924378a689ccb05f6d60875742dc28f69bf0129 (patch) | |
tree | 8d6933bff18ac9f4670395673e38dad94fedd998 /fs/xfs/xfs_trans.c | |
parent | 713bf88bba55b8dd91a18e8a59b0f97bf9b0f5de (diff) |
xfs: split out iclog writing from xfs_trans_commit()
Split the the part of xfs_trans_commit() that deals with writing the
transaction into the iclog into a separate function. This isolates the
physical commit process from the logical commit operation and makes
it easier to insert different transaction commit paths without affecting
the existing algorithm adversely.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_trans.c')
-rw-r--r-- | fs/xfs/xfs_trans.c | 387 |
1 files changed, 199 insertions, 188 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 6962f2bd3da3..e07b3290b3bf 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -47,8 +47,6 @@ | |||
47 | 47 | ||
48 | 48 | ||
49 | STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *); | 49 | STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *); |
50 | STATIC uint xfs_trans_count_vecs(xfs_trans_t *); | ||
51 | STATIC void xfs_trans_fill_vecs(xfs_trans_t *, xfs_log_iovec_t *); | ||
52 | STATIC void xfs_trans_uncommit(xfs_trans_t *, uint); | 50 | STATIC void xfs_trans_uncommit(xfs_trans_t *, uint); |
53 | STATIC void xfs_trans_committed(xfs_trans_t *, int); | 51 | STATIC void xfs_trans_committed(xfs_trans_t *, int); |
54 | STATIC void xfs_trans_chunk_committed(xfs_log_item_chunk_t *, xfs_lsn_t, int); | 52 | STATIC void xfs_trans_chunk_committed(xfs_log_item_chunk_t *, xfs_lsn_t, int); |
@@ -764,94 +762,126 @@ xfs_trans_unreserve_and_mod_sb( | |||
764 | } | 762 | } |
765 | } | 763 | } |
766 | 764 | ||
767 | |||
768 | /* | 765 | /* |
769 | * xfs_trans_commit | 766 | * Total up the number of log iovecs needed to commit this |
770 | * | 767 | * transaction. The transaction itself needs one for the |
771 | * Commit the given transaction to the log a/synchronously. | 768 | * transaction header. Ask each dirty item in turn how many |
772 | * | 769 | * it needs to get the total. |
773 | * XFS disk error handling mechanism is not based on a typical | ||
774 | * transaction abort mechanism. Logically after the filesystem | ||
775 | * gets marked 'SHUTDOWN', we can't let any new transactions | ||
776 | * be durable - ie. committed to disk - because some metadata might | ||
777 | * be inconsistent. In such cases, this returns an error, and the | ||
778 | * caller may assume that all locked objects joined to the transaction | ||
779 | * have already been unlocked as if the commit had succeeded. | ||
780 | * Do not reference the transaction structure after this call. | ||
781 | */ | 770 | */ |
782 | /*ARGSUSED*/ | 771 | static uint |
783 | int | 772 | xfs_trans_count_vecs( |
784 | _xfs_trans_commit( | 773 | xfs_trans_t *tp) |
785 | xfs_trans_t *tp, | ||
786 | uint flags, | ||
787 | int *log_flushed) | ||
788 | { | 774 | { |
789 | xfs_log_iovec_t *log_vector; | 775 | int nvecs; |
790 | int nvec; | 776 | xfs_log_item_desc_t *lidp; |
791 | xfs_mount_t *mp; | ||
792 | xfs_lsn_t commit_lsn; | ||
793 | /* REFERENCED */ | ||
794 | int error; | ||
795 | int log_flags; | ||
796 | int sync; | ||
797 | #define XFS_TRANS_LOGVEC_COUNT 16 | ||
798 | xfs_log_iovec_t log_vector_fast[XFS_TRANS_LOGVEC_COUNT]; | ||
799 | struct xlog_in_core *commit_iclog; | ||
800 | int shutdown; | ||
801 | 777 | ||
802 | commit_lsn = -1; | 778 | nvecs = 1; |
779 | lidp = xfs_trans_first_item(tp); | ||
780 | ASSERT(lidp != NULL); | ||
803 | 781 | ||
804 | /* | 782 | /* In the non-debug case we need to start bailing out if we |
805 | * Determine whether this commit is releasing a permanent | 783 | * didn't find a log_item here, return zero and let trans_commit |
806 | * log reservation or not. | 784 | * deal with it. |
807 | */ | 785 | */ |
808 | if (flags & XFS_TRANS_RELEASE_LOG_RES) { | 786 | if (lidp == NULL) |
809 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 787 | return 0; |
810 | log_flags = XFS_LOG_REL_PERM_RESERV; | 788 | |
811 | } else { | 789 | while (lidp != NULL) { |
812 | log_flags = 0; | 790 | /* |
791 | * Skip items which aren't dirty in this transaction. | ||
792 | */ | ||
793 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | ||
794 | lidp = xfs_trans_next_item(tp, lidp); | ||
795 | continue; | ||
796 | } | ||
797 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | ||
798 | nvecs += lidp->lid_size; | ||
799 | lidp = xfs_trans_next_item(tp, lidp); | ||
813 | } | 800 | } |
814 | mp = tp->t_mountp; | 801 | |
802 | return nvecs; | ||
803 | } | ||
804 | |||
805 | /* | ||
806 | * Fill in the vector with pointers to data to be logged | ||
807 | * by this transaction. The transaction header takes | ||
808 | * the first vector, and then each dirty item takes the | ||
809 | * number of vectors it indicated it needed in xfs_trans_count_vecs(). | ||
810 | * | ||
811 | * As each item fills in the entries it needs, also pin the item | ||
812 | * so that it cannot be flushed out until the log write completes. | ||
813 | */ | ||
814 | static void | ||
815 | xfs_trans_fill_vecs( | ||
816 | struct xfs_trans *tp, | ||
817 | struct xfs_log_iovec *log_vector) | ||
818 | { | ||
819 | xfs_log_item_desc_t *lidp; | ||
820 | struct xfs_log_iovec *vecp; | ||
821 | uint nitems; | ||
815 | 822 | ||
816 | /* | 823 | /* |
817 | * If there is nothing to be logged by the transaction, | 824 | * Skip over the entry for the transaction header, we'll |
818 | * then unlock all of the items associated with the | 825 | * fill that in at the end. |
819 | * transaction and free the transaction structure. | ||
820 | * Also make sure to return any reserved blocks to | ||
821 | * the free pool. | ||
822 | */ | 826 | */ |
823 | shut_us_down: | 827 | vecp = log_vector + 1; |
824 | shutdown = XFS_FORCED_SHUTDOWN(mp) ? EIO : 0; | 828 | |
825 | if (!(tp->t_flags & XFS_TRANS_DIRTY) || shutdown) { | 829 | nitems = 0; |
826 | xfs_trans_unreserve_and_mod_sb(tp); | 830 | lidp = xfs_trans_first_item(tp); |
831 | ASSERT(lidp); | ||
832 | while (lidp) { | ||
833 | /* Skip items which aren't dirty in this transaction. */ | ||
834 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | ||
835 | lidp = xfs_trans_next_item(tp, lidp); | ||
836 | continue; | ||
837 | } | ||
838 | |||
827 | /* | 839 | /* |
828 | * It is indeed possible for the transaction to be | 840 | * The item may be marked dirty but not log anything. This can |
829 | * not dirty but the dqinfo portion to be. All that | 841 | * be used to get called when a transaction is committed. |
830 | * means is that we have some (non-persistent) quota | ||
831 | * reservations that need to be unreserved. | ||
832 | */ | 842 | */ |
833 | xfs_trans_unreserve_and_mod_dquots(tp); | 843 | if (lidp->lid_size) |
834 | if (tp->t_ticket) { | 844 | nitems++; |
835 | commit_lsn = xfs_log_done(mp, tp->t_ticket, | 845 | IOP_FORMAT(lidp->lid_item, vecp); |
836 | NULL, log_flags); | 846 | vecp += lidp->lid_size; |
837 | if (commit_lsn == -1 && !shutdown) | 847 | IOP_PIN(lidp->lid_item); |
838 | shutdown = XFS_ERROR(EIO); | 848 | lidp = xfs_trans_next_item(tp, lidp); |
839 | } | ||
840 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | ||
841 | xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0); | ||
842 | xfs_trans_free_busy(tp); | ||
843 | xfs_trans_free(tp); | ||
844 | XFS_STATS_INC(xs_trans_empty); | ||
845 | return (shutdown); | ||
846 | } | 849 | } |
847 | ASSERT(tp->t_ticket != NULL); | ||
848 | 850 | ||
849 | /* | 851 | /* |
850 | * If we need to update the superblock, then do it now. | 852 | * Now that we've counted the number of items in this transaction, fill |
853 | * in the transaction header. Note that the transaction header does not | ||
854 | * have a log item. | ||
851 | */ | 855 | */ |
852 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) | 856 | tp->t_header.th_magic = XFS_TRANS_HEADER_MAGIC; |
853 | xfs_trans_apply_sb_deltas(tp); | 857 | tp->t_header.th_type = tp->t_type; |
854 | xfs_trans_apply_dquot_deltas(tp); | 858 | tp->t_header.th_num_items = nitems; |
859 | log_vector->i_addr = (xfs_caddr_t)&tp->t_header; | ||
860 | log_vector->i_len = sizeof(xfs_trans_header_t); | ||
861 | log_vector->i_type = XLOG_REG_TYPE_TRANSHDR; | ||
862 | } | ||
863 | |||
864 | /* | ||
865 | * Format the transaction direct to the iclog. This isolates the physical | ||
866 | * transaction commit operation from the logical operation and hence allows | ||
867 | * other methods to be introduced without affecting the existing commit path. | ||
868 | */ | ||
869 | static int | ||
870 | xfs_trans_commit_iclog( | ||
871 | struct xfs_mount *mp, | ||
872 | struct xfs_trans *tp, | ||
873 | xfs_lsn_t *commit_lsn, | ||
874 | int flags) | ||
875 | { | ||
876 | int shutdown; | ||
877 | int error; | ||
878 | int log_flags = 0; | ||
879 | struct xlog_in_core *commit_iclog; | ||
880 | #define XFS_TRANS_LOGVEC_COUNT 16 | ||
881 | struct xfs_log_iovec log_vector_fast[XFS_TRANS_LOGVEC_COUNT]; | ||
882 | struct xfs_log_iovec *log_vector; | ||
883 | uint nvec; | ||
884 | |||
855 | 885 | ||
856 | /* | 886 | /* |
857 | * Ask each log item how many log_vector entries it will | 887 | * Ask each log item how many log_vector entries it will |
@@ -861,8 +891,7 @@ shut_us_down: | |||
861 | */ | 891 | */ |
862 | nvec = xfs_trans_count_vecs(tp); | 892 | nvec = xfs_trans_count_vecs(tp); |
863 | if (nvec == 0) { | 893 | if (nvec == 0) { |
864 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | 894 | return ENOMEM; /* triggers a shutdown! */ |
865 | goto shut_us_down; | ||
866 | } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) { | 895 | } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) { |
867 | log_vector = log_vector_fast; | 896 | log_vector = log_vector_fast; |
868 | } else { | 897 | } else { |
@@ -877,6 +906,9 @@ shut_us_down: | |||
877 | */ | 906 | */ |
878 | xfs_trans_fill_vecs(tp, log_vector); | 907 | xfs_trans_fill_vecs(tp, log_vector); |
879 | 908 | ||
909 | if (flags & XFS_TRANS_RELEASE_LOG_RES) | ||
910 | log_flags = XFS_LOG_REL_PERM_RESERV; | ||
911 | |||
880 | error = xfs_log_write(mp, log_vector, nvec, tp->t_ticket, &(tp->t_lsn)); | 912 | error = xfs_log_write(mp, log_vector, nvec, tp->t_ticket, &(tp->t_lsn)); |
881 | 913 | ||
882 | /* | 914 | /* |
@@ -884,18 +916,17 @@ shut_us_down: | |||
884 | * at any time after this call. However, all the items associated | 916 | * at any time after this call. However, all the items associated |
885 | * with the transaction are still locked and pinned in memory. | 917 | * with the transaction are still locked and pinned in memory. |
886 | */ | 918 | */ |
887 | commit_lsn = xfs_log_done(mp, tp->t_ticket, &commit_iclog, log_flags); | 919 | *commit_lsn = xfs_log_done(mp, tp->t_ticket, &commit_iclog, log_flags); |
888 | 920 | ||
889 | tp->t_commit_lsn = commit_lsn; | 921 | tp->t_commit_lsn = *commit_lsn; |
890 | if (nvec > XFS_TRANS_LOGVEC_COUNT) { | 922 | if (nvec > XFS_TRANS_LOGVEC_COUNT) |
891 | kmem_free(log_vector); | 923 | kmem_free(log_vector); |
892 | } | ||
893 | 924 | ||
894 | /* | 925 | /* |
895 | * If we got a log write error. Unpin the logitems that we | 926 | * If we got a log write error. Unpin the logitems that we |
896 | * had pinned, clean up, free trans structure, and return error. | 927 | * had pinned, clean up, free trans structure, and return error. |
897 | */ | 928 | */ |
898 | if (error || commit_lsn == -1) { | 929 | if (error || *commit_lsn == -1) { |
899 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 930 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
900 | xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT); | 931 | xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT); |
901 | return XFS_ERROR(EIO); | 932 | return XFS_ERROR(EIO); |
@@ -909,8 +940,6 @@ shut_us_down: | |||
909 | */ | 940 | */ |
910 | xfs_trans_unreserve_and_mod_sb(tp); | 941 | xfs_trans_unreserve_and_mod_sb(tp); |
911 | 942 | ||
912 | sync = tp->t_flags & XFS_TRANS_SYNC; | ||
913 | |||
914 | /* | 943 | /* |
915 | * Tell the LM to call the transaction completion routine | 944 | * Tell the LM to call the transaction completion routine |
916 | * when the log write with LSN commit_lsn completes (e.g. | 945 | * when the log write with LSN commit_lsn completes (e.g. |
@@ -953,7 +982,7 @@ shut_us_down: | |||
953 | * the commit lsn of this transaction for dependency tracking | 982 | * the commit lsn of this transaction for dependency tracking |
954 | * purposes. | 983 | * purposes. |
955 | */ | 984 | */ |
956 | xfs_trans_unlock_items(tp, commit_lsn); | 985 | xfs_trans_unlock_items(tp, *commit_lsn); |
957 | 986 | ||
958 | /* | 987 | /* |
959 | * If we detected a log error earlier, finish committing | 988 | * If we detected a log error earlier, finish committing |
@@ -973,7 +1002,92 @@ shut_us_down: | |||
973 | * and the items are released we can finally allow the iclog to | 1002 | * and the items are released we can finally allow the iclog to |
974 | * go to disk. | 1003 | * go to disk. |
975 | */ | 1004 | */ |
976 | error = xfs_log_release_iclog(mp, commit_iclog); | 1005 | return xfs_log_release_iclog(mp, commit_iclog); |
1006 | } | ||
1007 | |||
1008 | |||
1009 | /* | ||
1010 | * xfs_trans_commit | ||
1011 | * | ||
1012 | * Commit the given transaction to the log a/synchronously. | ||
1013 | * | ||
1014 | * XFS disk error handling mechanism is not based on a typical | ||
1015 | * transaction abort mechanism. Logically after the filesystem | ||
1016 | * gets marked 'SHUTDOWN', we can't let any new transactions | ||
1017 | * be durable - ie. committed to disk - because some metadata might | ||
1018 | * be inconsistent. In such cases, this returns an error, and the | ||
1019 | * caller may assume that all locked objects joined to the transaction | ||
1020 | * have already been unlocked as if the commit had succeeded. | ||
1021 | * Do not reference the transaction structure after this call. | ||
1022 | */ | ||
1023 | /*ARGSUSED*/ | ||
1024 | int | ||
1025 | _xfs_trans_commit( | ||
1026 | xfs_trans_t *tp, | ||
1027 | uint flags, | ||
1028 | int *log_flushed) | ||
1029 | { | ||
1030 | xfs_mount_t *mp = tp->t_mountp; | ||
1031 | xfs_lsn_t commit_lsn = -1; | ||
1032 | int error; | ||
1033 | int log_flags = 0; | ||
1034 | int sync = tp->t_flags & XFS_TRANS_SYNC; | ||
1035 | int shutdown; | ||
1036 | |||
1037 | /* | ||
1038 | * Determine whether this commit is releasing a permanent | ||
1039 | * log reservation or not. | ||
1040 | */ | ||
1041 | if (flags & XFS_TRANS_RELEASE_LOG_RES) { | ||
1042 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | ||
1043 | log_flags = XFS_LOG_REL_PERM_RESERV; | ||
1044 | } | ||
1045 | |||
1046 | /* | ||
1047 | * If there is nothing to be logged by the transaction, | ||
1048 | * then unlock all of the items associated with the | ||
1049 | * transaction and free the transaction structure. | ||
1050 | * Also make sure to return any reserved blocks to | ||
1051 | * the free pool. | ||
1052 | */ | ||
1053 | shut_us_down: | ||
1054 | shutdown = XFS_FORCED_SHUTDOWN(mp) ? EIO : 0; | ||
1055 | if (!(tp->t_flags & XFS_TRANS_DIRTY) || shutdown) { | ||
1056 | xfs_trans_unreserve_and_mod_sb(tp); | ||
1057 | /* | ||
1058 | * It is indeed possible for the transaction to be | ||
1059 | * not dirty but the dqinfo portion to be. All that | ||
1060 | * means is that we have some (non-persistent) quota | ||
1061 | * reservations that need to be unreserved. | ||
1062 | */ | ||
1063 | xfs_trans_unreserve_and_mod_dquots(tp); | ||
1064 | if (tp->t_ticket) { | ||
1065 | commit_lsn = xfs_log_done(mp, tp->t_ticket, | ||
1066 | NULL, log_flags); | ||
1067 | if (commit_lsn == -1 && !shutdown) | ||
1068 | shutdown = XFS_ERROR(EIO); | ||
1069 | } | ||
1070 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | ||
1071 | xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0); | ||
1072 | xfs_trans_free_busy(tp); | ||
1073 | xfs_trans_free(tp); | ||
1074 | XFS_STATS_INC(xs_trans_empty); | ||
1075 | return (shutdown); | ||
1076 | } | ||
1077 | ASSERT(tp->t_ticket != NULL); | ||
1078 | |||
1079 | /* | ||
1080 | * If we need to update the superblock, then do it now. | ||
1081 | */ | ||
1082 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) | ||
1083 | xfs_trans_apply_sb_deltas(tp); | ||
1084 | xfs_trans_apply_dquot_deltas(tp); | ||
1085 | |||
1086 | error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags); | ||
1087 | if (error == ENOMEM) { | ||
1088 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | ||
1089 | goto shut_us_down; | ||
1090 | } | ||
977 | 1091 | ||
978 | /* | 1092 | /* |
979 | * If the transaction needs to be synchronous, then force the | 1093 | * If the transaction needs to be synchronous, then force the |
@@ -992,47 +1106,6 @@ shut_us_down: | |||
992 | return (error); | 1106 | return (error); |
993 | } | 1107 | } |
994 | 1108 | ||
995 | |||
996 | /* | ||
997 | * Total up the number of log iovecs needed to commit this | ||
998 | * transaction. The transaction itself needs one for the | ||
999 | * transaction header. Ask each dirty item in turn how many | ||
1000 | * it needs to get the total. | ||
1001 | */ | ||
1002 | STATIC uint | ||
1003 | xfs_trans_count_vecs( | ||
1004 | xfs_trans_t *tp) | ||
1005 | { | ||
1006 | int nvecs; | ||
1007 | xfs_log_item_desc_t *lidp; | ||
1008 | |||
1009 | nvecs = 1; | ||
1010 | lidp = xfs_trans_first_item(tp); | ||
1011 | ASSERT(lidp != NULL); | ||
1012 | |||
1013 | /* In the non-debug case we need to start bailing out if we | ||
1014 | * didn't find a log_item here, return zero and let trans_commit | ||
1015 | * deal with it. | ||
1016 | */ | ||
1017 | if (lidp == NULL) | ||
1018 | return 0; | ||
1019 | |||
1020 | while (lidp != NULL) { | ||
1021 | /* | ||
1022 | * Skip items which aren't dirty in this transaction. | ||
1023 | */ | ||
1024 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | ||
1025 | lidp = xfs_trans_next_item(tp, lidp); | ||
1026 | continue; | ||
1027 | } | ||
1028 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | ||
1029 | nvecs += lidp->lid_size; | ||
1030 | lidp = xfs_trans_next_item(tp, lidp); | ||
1031 | } | ||
1032 | |||
1033 | return nvecs; | ||
1034 | } | ||
1035 | |||
1036 | /* | 1109 | /* |
1037 | * Called from the trans_commit code when we notice that | 1110 | * Called from the trans_commit code when we notice that |
1038 | * the filesystem is in the middle of a forced shutdown. | 1111 | * the filesystem is in the middle of a forced shutdown. |
@@ -1063,68 +1136,6 @@ xfs_trans_uncommit( | |||
1063 | } | 1136 | } |
1064 | 1137 | ||
1065 | /* | 1138 | /* |
1066 | * Fill in the vector with pointers to data to be logged | ||
1067 | * by this transaction. The transaction header takes | ||
1068 | * the first vector, and then each dirty item takes the | ||
1069 | * number of vectors it indicated it needed in xfs_trans_count_vecs(). | ||
1070 | * | ||
1071 | * As each item fills in the entries it needs, also pin the item | ||
1072 | * so that it cannot be flushed out until the log write completes. | ||
1073 | */ | ||
1074 | STATIC void | ||
1075 | xfs_trans_fill_vecs( | ||
1076 | xfs_trans_t *tp, | ||
1077 | xfs_log_iovec_t *log_vector) | ||
1078 | { | ||
1079 | xfs_log_item_desc_t *lidp; | ||
1080 | xfs_log_iovec_t *vecp; | ||
1081 | uint nitems; | ||
1082 | |||
1083 | /* | ||
1084 | * Skip over the entry for the transaction header, we'll | ||
1085 | * fill that in at the end. | ||
1086 | */ | ||
1087 | vecp = log_vector + 1; /* pointer arithmetic */ | ||
1088 | |||
1089 | nitems = 0; | ||
1090 | lidp = xfs_trans_first_item(tp); | ||
1091 | ASSERT(lidp != NULL); | ||
1092 | while (lidp != NULL) { | ||
1093 | /* | ||
1094 | * Skip items which aren't dirty in this transaction. | ||
1095 | */ | ||
1096 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | ||
1097 | lidp = xfs_trans_next_item(tp, lidp); | ||
1098 | continue; | ||
1099 | } | ||
1100 | /* | ||
1101 | * The item may be marked dirty but not log anything. | ||
1102 | * This can be used to get called when a transaction | ||
1103 | * is committed. | ||
1104 | */ | ||
1105 | if (lidp->lid_size) { | ||
1106 | nitems++; | ||
1107 | } | ||
1108 | IOP_FORMAT(lidp->lid_item, vecp); | ||
1109 | vecp += lidp->lid_size; /* pointer arithmetic */ | ||
1110 | IOP_PIN(lidp->lid_item); | ||
1111 | lidp = xfs_trans_next_item(tp, lidp); | ||
1112 | } | ||
1113 | |||
1114 | /* | ||
1115 | * Now that we've counted the number of items in this | ||
1116 | * transaction, fill in the transaction header. | ||
1117 | */ | ||
1118 | tp->t_header.th_magic = XFS_TRANS_HEADER_MAGIC; | ||
1119 | tp->t_header.th_type = tp->t_type; | ||
1120 | tp->t_header.th_num_items = nitems; | ||
1121 | log_vector->i_addr = (xfs_caddr_t)&tp->t_header; | ||
1122 | log_vector->i_len = sizeof(xfs_trans_header_t); | ||
1123 | log_vector->i_type = XLOG_REG_TYPE_TRANSHDR; | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | /* | ||
1128 | * Unlock all of the transaction's items and free the transaction. | 1139 | * Unlock all of the transaction's items and free the transaction. |
1129 | * The transaction must not have modified any of its items, because | 1140 | * The transaction must not have modified any of its items, because |
1130 | * there is no way to restore them to their previous state. | 1141 | * there is no way to restore them to their previous state. |