diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-09-29 22:25:56 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-10-18 16:08:00 -0400 |
commit | 1b0407125f9a5be63e861eb27c8af9e32f20619c (patch) | |
tree | 206f43a7131ad11b8c603247254a8eb9aa2fc17e /fs/xfs | |
parent | 96540c78583a417113df4d027e6b68a595ab9a09 (diff) |
xfs: do not use xfs_mod_incore_sb_batch for per-cpu counters
Update the per-cpu counters manually in xfs_trans_unreserve_and_mod_sb
and remove support for per-cpu counters from xfs_mod_incore_sb_batch
to simplify it. And added benefit is that we don't have to take
m_sb_lock for transactions that only modify per-cpu counters.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_mount.c | 114 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.c | 78 |
2 files changed, 85 insertions, 107 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 20c67ff57536..00538b7e694a 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1856,98 +1856,54 @@ xfs_mod_incore_sb( | |||
1856 | } | 1856 | } |
1857 | 1857 | ||
1858 | /* | 1858 | /* |
1859 | * xfs_mod_incore_sb_batch() is used to change more than one field | 1859 | * Change more than one field in the in-core superblock structure at a time. |
1860 | * in the in-core superblock structure at a time. This modification | ||
1861 | * is protected by a lock internal to this module. The fields and | ||
1862 | * changes to those fields are specified in the array of xfs_mod_sb | ||
1863 | * structures passed in. | ||
1864 | * | 1860 | * |
1865 | * Either all of the specified deltas will be applied or none of | 1861 | * The fields and changes to those fields are specified in the array of |
1866 | * them will. If any modified field dips below 0, then all modifications | 1862 | * xfs_mod_sb structures passed in. Either all of the specified deltas |
1867 | * will be backed out and EINVAL will be returned. | 1863 | * will be applied or none of them will. If any modified field dips below 0, |
1864 | * then all modifications will be backed out and EINVAL will be returned. | ||
1865 | * | ||
1866 | * Note that this function may not be used for the superblock values that | ||
1867 | * are tracked with the in-memory per-cpu counters - a direct call to | ||
1868 | * xfs_icsb_modify_counters is required for these. | ||
1868 | */ | 1869 | */ |
1869 | int | 1870 | int |
1870 | xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) | 1871 | xfs_mod_incore_sb_batch( |
1872 | struct xfs_mount *mp, | ||
1873 | xfs_mod_sb_t *msb, | ||
1874 | uint nmsb, | ||
1875 | int rsvd) | ||
1871 | { | 1876 | { |
1872 | int status=0; | 1877 | xfs_mod_sb_t *msbp = &msb[0]; |
1873 | xfs_mod_sb_t *msbp; | 1878 | int error = 0; |
1874 | 1879 | ||
1875 | /* | 1880 | /* |
1876 | * Loop through the array of mod structures and apply each | 1881 | * Loop through the array of mod structures and apply each individually. |
1877 | * individually. If any fail, then back out all those | 1882 | * If any fail, then back out all those which have already been applied. |
1878 | * which have already been applied. Do all of this within | 1883 | * Do all of this within the scope of the m_sb_lock so that all of the |
1879 | * the scope of the m_sb_lock so that all of the changes will | 1884 | * changes will be atomic. |
1880 | * be atomic. | ||
1881 | */ | 1885 | */ |
1882 | spin_lock(&mp->m_sb_lock); | 1886 | spin_lock(&mp->m_sb_lock); |
1883 | msbp = &msb[0]; | ||
1884 | for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) { | 1887 | for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) { |
1885 | /* | 1888 | ASSERT(msbp->msb_field < XFS_SBS_ICOUNT || |
1886 | * Apply the delta at index n. If it fails, break | 1889 | msbp->msb_field > XFS_SBS_FDBLOCKS); |
1887 | * from the loop so we'll fall into the undo loop | ||
1888 | * below. | ||
1889 | */ | ||
1890 | switch (msbp->msb_field) { | ||
1891 | #ifdef HAVE_PERCPU_SB | ||
1892 | case XFS_SBS_ICOUNT: | ||
1893 | case XFS_SBS_IFREE: | ||
1894 | case XFS_SBS_FDBLOCKS: | ||
1895 | spin_unlock(&mp->m_sb_lock); | ||
1896 | status = xfs_icsb_modify_counters(mp, | ||
1897 | msbp->msb_field, | ||
1898 | msbp->msb_delta, rsvd); | ||
1899 | spin_lock(&mp->m_sb_lock); | ||
1900 | break; | ||
1901 | #endif | ||
1902 | default: | ||
1903 | status = xfs_mod_incore_sb_unlocked(mp, | ||
1904 | msbp->msb_field, | ||
1905 | msbp->msb_delta, rsvd); | ||
1906 | break; | ||
1907 | } | ||
1908 | 1890 | ||
1909 | if (status != 0) { | 1891 | error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, |
1910 | break; | 1892 | msbp->msb_delta, rsvd); |
1911 | } | 1893 | if (error) |
1894 | goto unwind; | ||
1912 | } | 1895 | } |
1896 | spin_unlock(&mp->m_sb_lock); | ||
1897 | return 0; | ||
1913 | 1898 | ||
1914 | /* | 1899 | unwind: |
1915 | * If we didn't complete the loop above, then back out | 1900 | while (--msbp >= msb) { |
1916 | * any changes made to the superblock. If you add code | 1901 | error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, |
1917 | * between the loop above and here, make sure that you | 1902 | -msbp->msb_delta, rsvd); |
1918 | * preserve the value of status. Loop back until | 1903 | ASSERT(error == 0); |
1919 | * we step below the beginning of the array. Make sure | ||
1920 | * we don't touch anything back there. | ||
1921 | */ | ||
1922 | if (status != 0) { | ||
1923 | msbp--; | ||
1924 | while (msbp >= msb) { | ||
1925 | switch (msbp->msb_field) { | ||
1926 | #ifdef HAVE_PERCPU_SB | ||
1927 | case XFS_SBS_ICOUNT: | ||
1928 | case XFS_SBS_IFREE: | ||
1929 | case XFS_SBS_FDBLOCKS: | ||
1930 | spin_unlock(&mp->m_sb_lock); | ||
1931 | status = xfs_icsb_modify_counters(mp, | ||
1932 | msbp->msb_field, | ||
1933 | -(msbp->msb_delta), | ||
1934 | rsvd); | ||
1935 | spin_lock(&mp->m_sb_lock); | ||
1936 | break; | ||
1937 | #endif | ||
1938 | default: | ||
1939 | status = xfs_mod_incore_sb_unlocked(mp, | ||
1940 | msbp->msb_field, | ||
1941 | -(msbp->msb_delta), | ||
1942 | rsvd); | ||
1943 | break; | ||
1944 | } | ||
1945 | ASSERT(status == 0); | ||
1946 | msbp--; | ||
1947 | } | ||
1948 | } | 1904 | } |
1949 | spin_unlock(&mp->m_sb_lock); | 1905 | spin_unlock(&mp->m_sb_lock); |
1950 | return status; | 1906 | return error; |
1951 | } | 1907 | } |
1952 | 1908 | ||
1953 | /* | 1909 | /* |
@@ -2478,7 +2434,7 @@ xfs_icsb_balance_counter( | |||
2478 | spin_unlock(&mp->m_sb_lock); | 2434 | spin_unlock(&mp->m_sb_lock); |
2479 | } | 2435 | } |
2480 | 2436 | ||
2481 | STATIC int | 2437 | int |
2482 | xfs_icsb_modify_counters( | 2438 | xfs_icsb_modify_counters( |
2483 | xfs_mount_t *mp, | 2439 | xfs_mount_t *mp, |
2484 | xfs_sb_field_t field, | 2440 | xfs_sb_field_t field, |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 73cf8f45725e..5fab0e6bf86e 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -1009,7 +1009,7 @@ void | |||
1009 | xfs_trans_unreserve_and_mod_sb( | 1009 | xfs_trans_unreserve_and_mod_sb( |
1010 | xfs_trans_t *tp) | 1010 | xfs_trans_t *tp) |
1011 | { | 1011 | { |
1012 | xfs_mod_sb_t msb[14]; /* If you add cases, add entries */ | 1012 | xfs_mod_sb_t msb[9]; /* If you add cases, add entries */ |
1013 | xfs_mod_sb_t *msbp; | 1013 | xfs_mod_sb_t *msbp; |
1014 | xfs_mount_t *mp = tp->t_mountp; | 1014 | xfs_mount_t *mp = tp->t_mountp; |
1015 | /* REFERENCED */ | 1015 | /* REFERENCED */ |
@@ -1017,55 +1017,61 @@ xfs_trans_unreserve_and_mod_sb( | |||
1017 | int rsvd; | 1017 | int rsvd; |
1018 | int64_t blkdelta = 0; | 1018 | int64_t blkdelta = 0; |
1019 | int64_t rtxdelta = 0; | 1019 | int64_t rtxdelta = 0; |
1020 | int64_t idelta = 0; | ||
1021 | int64_t ifreedelta = 0; | ||
1020 | 1022 | ||
1021 | msbp = msb; | 1023 | msbp = msb; |
1022 | rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; | 1024 | rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; |
1023 | 1025 | ||
1024 | /* calculate free blocks delta */ | 1026 | /* calculate deltas */ |
1025 | if (tp->t_blk_res > 0) | 1027 | if (tp->t_blk_res > 0) |
1026 | blkdelta = tp->t_blk_res; | 1028 | blkdelta = tp->t_blk_res; |
1027 | |||
1028 | if ((tp->t_fdblocks_delta != 0) && | 1029 | if ((tp->t_fdblocks_delta != 0) && |
1029 | (xfs_sb_version_haslazysbcount(&mp->m_sb) || | 1030 | (xfs_sb_version_haslazysbcount(&mp->m_sb) || |
1030 | (tp->t_flags & XFS_TRANS_SB_DIRTY))) | 1031 | (tp->t_flags & XFS_TRANS_SB_DIRTY))) |
1031 | blkdelta += tp->t_fdblocks_delta; | 1032 | blkdelta += tp->t_fdblocks_delta; |
1032 | 1033 | ||
1033 | if (blkdelta != 0) { | ||
1034 | msbp->msb_field = XFS_SBS_FDBLOCKS; | ||
1035 | msbp->msb_delta = blkdelta; | ||
1036 | msbp++; | ||
1037 | } | ||
1038 | |||
1039 | /* calculate free realtime extents delta */ | ||
1040 | if (tp->t_rtx_res > 0) | 1034 | if (tp->t_rtx_res > 0) |
1041 | rtxdelta = tp->t_rtx_res; | 1035 | rtxdelta = tp->t_rtx_res; |
1042 | |||
1043 | if ((tp->t_frextents_delta != 0) && | 1036 | if ((tp->t_frextents_delta != 0) && |
1044 | (tp->t_flags & XFS_TRANS_SB_DIRTY)) | 1037 | (tp->t_flags & XFS_TRANS_SB_DIRTY)) |
1045 | rtxdelta += tp->t_frextents_delta; | 1038 | rtxdelta += tp->t_frextents_delta; |
1046 | 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 | /* apply the per-cpu counters */ | ||
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 | /* apply remaining deltas */ | ||
1047 | if (rtxdelta != 0) { | 1069 | if (rtxdelta != 0) { |
1048 | msbp->msb_field = XFS_SBS_FREXTENTS; | 1070 | msbp->msb_field = XFS_SBS_FREXTENTS; |
1049 | msbp->msb_delta = rtxdelta; | 1071 | msbp->msb_delta = rtxdelta; |
1050 | msbp++; | 1072 | msbp++; |
1051 | } | 1073 | } |
1052 | 1074 | ||
1053 | /* apply remaining deltas */ | ||
1054 | |||
1055 | if (xfs_sb_version_haslazysbcount(&mp->m_sb) || | ||
1056 | (tp->t_flags & XFS_TRANS_SB_DIRTY)) { | ||
1057 | if (tp->t_icount_delta != 0) { | ||
1058 | msbp->msb_field = XFS_SBS_ICOUNT; | ||
1059 | msbp->msb_delta = tp->t_icount_delta; | ||
1060 | msbp++; | ||
1061 | } | ||
1062 | if (tp->t_ifree_delta != 0) { | ||
1063 | msbp->msb_field = XFS_SBS_IFREE; | ||
1064 | msbp->msb_delta = tp->t_ifree_delta; | ||
1065 | msbp++; | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { | 1075 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { |
1070 | if (tp->t_dblocks_delta != 0) { | 1076 | if (tp->t_dblocks_delta != 0) { |
1071 | msbp->msb_field = XFS_SBS_DBLOCKS; | 1077 | msbp->msb_field = XFS_SBS_DBLOCKS; |
@@ -1115,8 +1121,24 @@ xfs_trans_unreserve_and_mod_sb( | |||
1115 | if (msbp > msb) { | 1121 | if (msbp > msb) { |
1116 | error = xfs_mod_incore_sb_batch(tp->t_mountp, msb, | 1122 | error = xfs_mod_incore_sb_batch(tp->t_mountp, msb, |
1117 | (uint)(msbp - msb), rsvd); | 1123 | (uint)(msbp - msb), rsvd); |
1118 | ASSERT(error == 0); | 1124 | if (error) |
1125 | goto out_undo_ifreecount; | ||
1119 | } | 1126 | } |
1127 | |||
1128 | return; | ||
1129 | |||
1130 | out_undo_ifreecount: | ||
1131 | if (ifreedelta) | ||
1132 | xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd); | ||
1133 | out_undo_icount: | ||
1134 | if (idelta) | ||
1135 | xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd); | ||
1136 | out_undo_fdblocks: | ||
1137 | if (blkdelta) | ||
1138 | xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd); | ||
1139 | out: | ||
1140 | ASSERT(error = 0); | ||
1141 | return; | ||
1120 | } | 1142 | } |
1121 | 1143 | ||
1122 | /* | 1144 | /* |