.. | .. |
---|
11 | 11 | #include "xfs_trans_resv.h" |
---|
12 | 12 | #include "xfs_bit.h" |
---|
13 | 13 | #include "xfs_mount.h" |
---|
14 | | -#include "xfs_defer.h" |
---|
15 | 14 | #include "xfs_inode.h" |
---|
16 | 15 | #include "xfs_bmap.h" |
---|
17 | | -#include "xfs_bmap_util.h" |
---|
18 | 16 | #include "xfs_bmap_btree.h" |
---|
19 | | -#include "xfs_alloc.h" |
---|
20 | | -#include "xfs_error.h" |
---|
21 | 17 | #include "xfs_trans.h" |
---|
22 | 18 | #include "xfs_trans_space.h" |
---|
23 | | -#include "xfs_trace.h" |
---|
24 | | -#include "xfs_buf.h" |
---|
25 | 19 | #include "xfs_icache.h" |
---|
26 | 20 | #include "xfs_rtalloc.h" |
---|
27 | | - |
---|
| 21 | +#include "xfs_sb.h" |
---|
28 | 22 | |
---|
29 | 23 | /* |
---|
30 | 24 | * Read and return the summary information for a given extent size, |
---|
.. | .. |
---|
64 | 58 | int log; /* loop counter, log2 of ext. size */ |
---|
65 | 59 | xfs_suminfo_t sum; /* summary data */ |
---|
66 | 60 | |
---|
| 61 | + /* There are no extents at levels < m_rsum_cache[bbno]. */ |
---|
| 62 | + if (mp->m_rsum_cache && low < mp->m_rsum_cache[bbno]) |
---|
| 63 | + low = mp->m_rsum_cache[bbno]; |
---|
| 64 | + |
---|
67 | 65 | /* |
---|
68 | | - * Loop over logs of extent sizes. Order is irrelevant. |
---|
| 66 | + * Loop over logs of extent sizes. |
---|
69 | 67 | */ |
---|
70 | 68 | for (log = low; log <= high; log++) { |
---|
71 | 69 | /* |
---|
.. | .. |
---|
80 | 78 | */ |
---|
81 | 79 | if (sum) { |
---|
82 | 80 | *stat = 1; |
---|
83 | | - return 0; |
---|
| 81 | + goto out; |
---|
84 | 82 | } |
---|
85 | 83 | } |
---|
86 | 84 | /* |
---|
87 | 85 | * Found nothing, return failure. |
---|
88 | 86 | */ |
---|
89 | 87 | *stat = 0; |
---|
| 88 | +out: |
---|
| 89 | + /* There were no extents at levels < log. */ |
---|
| 90 | + if (mp->m_rsum_cache && log > mp->m_rsum_cache[bbno]) |
---|
| 91 | + mp->m_rsum_cache[bbno] = log; |
---|
90 | 92 | return 0; |
---|
91 | 93 | } |
---|
92 | 94 | |
---|
.. | .. |
---|
776 | 778 | struct xfs_bmbt_irec map; /* block map output */ |
---|
777 | 779 | int nmap; /* number of block maps */ |
---|
778 | 780 | int resblks; /* space reservation */ |
---|
| 781 | + enum xfs_blft buf_type; |
---|
779 | 782 | struct xfs_trans *tp; |
---|
| 783 | + |
---|
| 784 | + if (ip == mp->m_rsumip) |
---|
| 785 | + buf_type = XFS_BLFT_RTSUMMARY_BUF; |
---|
| 786 | + else |
---|
| 787 | + buf_type = XFS_BLFT_RTBITMAP_BUF; |
---|
780 | 788 | |
---|
781 | 789 | /* |
---|
782 | 790 | * Allocate space to the file, as necessary. |
---|
.. | .. |
---|
801 | 809 | */ |
---|
802 | 810 | nmap = 1; |
---|
803 | 811 | error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, |
---|
804 | | - XFS_BMAPI_METADATA, resblks, &map, |
---|
805 | | - &nmap); |
---|
| 812 | + XFS_BMAPI_METADATA, 0, &map, &nmap); |
---|
806 | 813 | if (!error && nmap < 1) |
---|
807 | 814 | error = -ENOSPC; |
---|
808 | 815 | if (error) |
---|
.. | .. |
---|
836 | 843 | * Get a buffer for the block. |
---|
837 | 844 | */ |
---|
838 | 845 | d = XFS_FSB_TO_DADDR(mp, fsbno); |
---|
839 | | - bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, |
---|
840 | | - mp->m_bsize, 0); |
---|
841 | | - if (bp == NULL) { |
---|
842 | | - error = -EIO; |
---|
| 846 | + error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, |
---|
| 847 | + mp->m_bsize, 0, &bp); |
---|
| 848 | + if (error) |
---|
843 | 849 | goto out_trans_cancel; |
---|
844 | | - } |
---|
| 850 | + |
---|
| 851 | + xfs_trans_buf_set_type(tp, bp, buf_type); |
---|
| 852 | + bp->b_ops = &xfs_rtbuf_ops; |
---|
845 | 853 | memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); |
---|
846 | 854 | xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); |
---|
847 | 855 | /* |
---|
.. | .. |
---|
862 | 870 | out_trans_cancel: |
---|
863 | 871 | xfs_trans_cancel(tp); |
---|
864 | 872 | return error; |
---|
| 873 | +} |
---|
| 874 | + |
---|
| 875 | +static void |
---|
| 876 | +xfs_alloc_rsum_cache( |
---|
| 877 | + xfs_mount_t *mp, /* file system mount structure */ |
---|
| 878 | + xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */ |
---|
| 879 | +{ |
---|
| 880 | + /* |
---|
| 881 | + * The rsum cache is initialized to all zeroes, which is trivially a |
---|
| 882 | + * lower bound on the minimum level with any free extents. We can |
---|
| 883 | + * continue without the cache if it couldn't be allocated. |
---|
| 884 | + */ |
---|
| 885 | + mp->m_rsum_cache = kvzalloc(rbmblocks, GFP_KERNEL); |
---|
| 886 | + if (!mp->m_rsum_cache) |
---|
| 887 | + xfs_warn(mp, "could not allocate realtime summary cache"); |
---|
865 | 888 | } |
---|
866 | 889 | |
---|
867 | 890 | /* |
---|
.. | .. |
---|
892 | 915 | xfs_extlen_t rsumblocks; /* current number of rt summary blks */ |
---|
893 | 916 | xfs_sb_t *sbp; /* old superblock */ |
---|
894 | 917 | xfs_fsblock_t sumbno; /* summary block number */ |
---|
| 918 | + uint8_t *rsum_cache; /* old summary cache */ |
---|
895 | 919 | |
---|
896 | 920 | sbp = &mp->m_sb; |
---|
897 | 921 | /* |
---|
.. | .. |
---|
948 | 972 | error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip); |
---|
949 | 973 | if (error) |
---|
950 | 974 | return error; |
---|
| 975 | + |
---|
| 976 | + rsum_cache = mp->m_rsum_cache; |
---|
| 977 | + if (nrbmblocks != sbp->sb_rbmblocks) |
---|
| 978 | + xfs_alloc_rsum_cache(mp, nrbmblocks); |
---|
| 979 | + |
---|
951 | 980 | /* |
---|
952 | 981 | * Allocate a new (fake) mount/sb. |
---|
953 | 982 | */ |
---|
954 | | - nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP); |
---|
| 983 | + nmp = kmem_alloc(sizeof(*nmp), 0); |
---|
955 | 984 | /* |
---|
956 | 985 | * Loop over the bitmap blocks. |
---|
957 | 986 | * We will do everything one bitmap block at a time. |
---|
.. | .. |
---|
995 | 1024 | /* |
---|
996 | 1025 | * Lock out other callers by grabbing the bitmap inode lock. |
---|
997 | 1026 | */ |
---|
998 | | - xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); |
---|
| 1027 | + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP); |
---|
999 | 1028 | xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); |
---|
1000 | 1029 | /* |
---|
1001 | 1030 | * Update the bitmap inode's size ondisk and incore. We need |
---|
.. | .. |
---|
1009 | 1038 | /* |
---|
1010 | 1039 | * Get the summary inode into the transaction. |
---|
1011 | 1040 | */ |
---|
1012 | | - xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); |
---|
| 1041 | + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM); |
---|
1013 | 1042 | xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); |
---|
1014 | 1043 | /* |
---|
1015 | 1044 | * Update the summary inode's size. We need to update the |
---|
.. | .. |
---|
1073 | 1102 | if (error) |
---|
1074 | 1103 | break; |
---|
1075 | 1104 | } |
---|
| 1105 | + if (error) |
---|
| 1106 | + goto out_free; |
---|
1076 | 1107 | |
---|
| 1108 | + /* Update secondary superblocks now the physical grow has completed */ |
---|
| 1109 | + error = xfs_update_secondary_sbs(mp); |
---|
| 1110 | + |
---|
| 1111 | +out_free: |
---|
1077 | 1112 | /* |
---|
1078 | 1113 | * Free the fake mp structure. |
---|
1079 | 1114 | */ |
---|
1080 | 1115 | kmem_free(nmp); |
---|
| 1116 | + |
---|
| 1117 | + /* |
---|
| 1118 | + * If we had to allocate a new rsum_cache, we either need to free the |
---|
| 1119 | + * old one (if we succeeded) or free the new one and restore the old one |
---|
| 1120 | + * (if there was an error). |
---|
| 1121 | + */ |
---|
| 1122 | + if (rsum_cache != mp->m_rsum_cache) { |
---|
| 1123 | + if (error) { |
---|
| 1124 | + kmem_free(mp->m_rsum_cache); |
---|
| 1125 | + mp->m_rsum_cache = rsum_cache; |
---|
| 1126 | + } else { |
---|
| 1127 | + kmem_free(rsum_cache); |
---|
| 1128 | + } |
---|
| 1129 | + } |
---|
1081 | 1130 | |
---|
1082 | 1131 | return error; |
---|
1083 | 1132 | } |
---|
.. | .. |
---|
1204 | 1253 | } |
---|
1205 | 1254 | |
---|
1206 | 1255 | /* |
---|
1207 | | - * Get the bitmap and summary inodes into the mount structure |
---|
1208 | | - * at mount time. |
---|
| 1256 | + * Get the bitmap and summary inodes and the summary cache into the mount |
---|
| 1257 | + * structure at mount time. |
---|
1209 | 1258 | */ |
---|
1210 | 1259 | int /* error */ |
---|
1211 | 1260 | xfs_rtmount_inodes( |
---|
.. | .. |
---|
1226 | 1275 | return error; |
---|
1227 | 1276 | } |
---|
1228 | 1277 | ASSERT(mp->m_rsumip != NULL); |
---|
| 1278 | + xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks); |
---|
1229 | 1279 | return 0; |
---|
1230 | 1280 | } |
---|
1231 | 1281 | |
---|
.. | .. |
---|
1233 | 1283 | xfs_rtunmount_inodes( |
---|
1234 | 1284 | struct xfs_mount *mp) |
---|
1235 | 1285 | { |
---|
| 1286 | + kmem_free(mp->m_rsum_cache); |
---|
1236 | 1287 | if (mp->m_rbmip) |
---|
1237 | 1288 | xfs_irele(mp->m_rbmip); |
---|
1238 | 1289 | if (mp->m_rsumip) |
---|