aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-09-29 22:25:56 -0400
committerAlex Elder <aelder@sgi.com>2010-10-18 16:08:00 -0400
commit1b0407125f9a5be63e861eb27c8af9e32f20619c (patch)
tree206f43a7131ad11b8c603247254a8eb9aa2fc17e /fs/xfs
parent96540c78583a417113df4d027e6b68a595ab9a09 (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.c114
-rw-r--r--fs/xfs/xfs_trans.c78
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 */
1869int 1870int
1870xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) 1871xfs_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 /* 1899unwind:
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
2481STATIC int 2437int
2482xfs_icsb_modify_counters( 2438xfs_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
1009xfs_trans_unreserve_and_mod_sb( 1009xfs_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
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;
1120} 1142}
1121 1143
1122/* 1144/*