aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_rtalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_rtalloc.c')
-rw-r--r--fs/xfs/xfs_rtalloc.c1552
1 files changed, 297 insertions, 1255 deletions
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 6f9e63c9fc26..a6a76b2b6a85 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -17,172 +17,260 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_shared.h"
20#include "xfs_format.h" 21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_dinode.h"
29#include "xfs_inode.h" 28#include "xfs_inode.h"
30#include "xfs_alloc.h"
31#include "xfs_bmap.h" 29#include "xfs_bmap.h"
32#include "xfs_bmap_util.h" 30#include "xfs_bmap_util.h"
33#include "xfs_rtalloc.h" 31#include "xfs_bmap_btree.h"
34#include "xfs_fsops.h" 32#include "xfs_alloc.h"
35#include "xfs_error.h" 33#include "xfs_error.h"
36#include "xfs_inode_item.h" 34#include "xfs_trans.h"
37#include "xfs_trans_space.h" 35#include "xfs_trans_space.h"
38#include "xfs_trace.h" 36#include "xfs_trace.h"
39#include "xfs_buf.h" 37#include "xfs_buf.h"
40#include "xfs_icache.h" 38#include "xfs_icache.h"
39#include "xfs_dinode.h"
40#include "xfs_rtalloc.h"
41 41
42 42
43/* 43/*
44 * Prototypes for internal functions. 44 * Read and return the summary information for a given extent size,
45 * bitmap block combination.
46 * Keeps track of a current summary block, so we don't keep reading
47 * it from the buffer cache.
45 */ 48 */
49STATIC int /* error */
50xfs_rtget_summary(
51 xfs_mount_t *mp, /* file system mount structure */
52 xfs_trans_t *tp, /* transaction pointer */
53 int log, /* log2 of extent size */
54 xfs_rtblock_t bbno, /* bitmap block number */
55 xfs_buf_t **rbpp, /* in/out: summary block buffer */
56 xfs_fsblock_t *rsb, /* in/out: summary block number */
57 xfs_suminfo_t *sum) /* out: summary info for this block */
58{
59 xfs_buf_t *bp; /* buffer for summary block */
60 int error; /* error value */
61 xfs_fsblock_t sb; /* summary fsblock */
62 int so; /* index into the summary file */
63 xfs_suminfo_t *sp; /* pointer to returned data */
46 64
65 /*
66 * Compute entry number in the summary file.
67 */
68 so = XFS_SUMOFFS(mp, log, bbno);
69 /*
70 * Compute the block number in the summary file.
71 */
72 sb = XFS_SUMOFFSTOBLOCK(mp, so);
73 /*
74 * If we have an old buffer, and the block number matches, use that.
75 */
76 if (rbpp && *rbpp && *rsb == sb)
77 bp = *rbpp;
78 /*
79 * Otherwise we have to get the buffer.
80 */
81 else {
82 /*
83 * If there was an old one, get rid of it first.
84 */
85 if (rbpp && *rbpp)
86 xfs_trans_brelse(tp, *rbpp);
87 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
88 if (error) {
89 return error;
90 }
91 /*
92 * Remember this buffer and block for the next call.
93 */
94 if (rbpp) {
95 *rbpp = bp;
96 *rsb = sb;
97 }
98 }
99 /*
100 * Point to the summary information & copy it out.
101 */
102 sp = XFS_SUMPTR(mp, bp, so);
103 *sum = *sp;
104 /*
105 * Drop the buffer if we're not asked to remember it.
106 */
107 if (!rbpp)
108 xfs_trans_brelse(tp, bp);
109 return 0;
110}
47 111
48STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
49 xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *);
50STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int,
51 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *);
52STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
53 xfs_extlen_t, int, xfs_rtblock_t *, int *);
54STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
55 xfs_rtblock_t, xfs_rtblock_t *);
56STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
57 xfs_rtblock_t, xfs_rtblock_t *);
58STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int,
59 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *);
60STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
61 xfs_extlen_t, int);
62STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
63 xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);
64
65/*
66 * Internal functions.
67 */
68 112
69/* 113/*
70 * Allocate space to the bitmap or summary file, and zero it, for growfs. 114 * Return whether there are any free extents in the size range given
115 * by low and high, for the bitmap block bbno.
71 */ 116 */
72STATIC int /* error */ 117STATIC int /* error */
73xfs_growfs_rt_alloc( 118xfs_rtany_summary(
74 xfs_mount_t *mp, /* file system mount point */ 119 xfs_mount_t *mp, /* file system mount structure */
75 xfs_extlen_t oblocks, /* old count of blocks */ 120 xfs_trans_t *tp, /* transaction pointer */
76 xfs_extlen_t nblocks, /* new count of blocks */ 121 int low, /* low log2 extent size */
77 xfs_inode_t *ip) /* inode (bitmap/summary) */ 122 int high, /* high log2 extent size */
123 xfs_rtblock_t bbno, /* bitmap block number */
124 xfs_buf_t **rbpp, /* in/out: summary block buffer */
125 xfs_fsblock_t *rsb, /* in/out: summary block number */
126 int *stat) /* out: any good extents here? */
78{ 127{
79 xfs_fileoff_t bno; /* block number in file */ 128 int error; /* error value */
80 xfs_buf_t *bp; /* temporary buffer for zeroing */ 129 int log; /* loop counter, log2 of ext. size */
81 int committed; /* transaction committed flag */ 130 xfs_suminfo_t sum; /* summary data */
82 xfs_daddr_t d; /* disk block address */
83 int error; /* error return value */
84 xfs_fsblock_t firstblock; /* first block allocated in xaction */
85 xfs_bmap_free_t flist; /* list of freed blocks */
86 xfs_fsblock_t fsbno; /* filesystem block for bno */
87 xfs_bmbt_irec_t map; /* block map output */
88 int nmap; /* number of block maps */
89 int resblks; /* space reservation */
90 131
91 /* 132 /*
92 * Allocate space to the file, as necessary. 133 * Loop over logs of extent sizes. Order is irrelevant.
93 */ 134 */
94 while (oblocks < nblocks) { 135 for (log = low; log <= high; log++) {
95 int cancelflags = 0;
96 xfs_trans_t *tp;
97
98 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
99 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
100 /* 136 /*
101 * Reserve space & log for one extent added to the file. 137 * Get one summary datum.
102 */ 138 */
103 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata, 139 error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
104 resblks, 0); 140 if (error) {
105 if (error) 141 return error;
106 goto error_cancel; 142 }
107 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
108 /* 143 /*
109 * Lock the inode. 144 * If there are any, return success.
110 */ 145 */
111 xfs_ilock(ip, XFS_ILOCK_EXCL); 146 if (sum) {
112 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 147 *stat = 1;
148 return 0;
149 }
150 }
151 /*
152 * Found nothing, return failure.
153 */
154 *stat = 0;
155 return 0;
156}
113 157
114 xfs_bmap_init(&flist, &firstblock); 158
115 /* 159/*
116 * Allocate blocks to the bitmap file. 160 * Copy and transform the summary file, given the old and new
117 */ 161 * parameters in the mount structures.
118 nmap = 1; 162 */
119 cancelflags |= XFS_TRANS_ABORT; 163STATIC int /* error */
120 error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, 164xfs_rtcopy_summary(
121 XFS_BMAPI_METADATA, &firstblock, 165 xfs_mount_t *omp, /* old file system mount point */
122 resblks, &map, &nmap, &flist); 166 xfs_mount_t *nmp, /* new file system mount point */
123 if (!error && nmap < 1) 167 xfs_trans_t *tp) /* transaction pointer */
124 error = XFS_ERROR(ENOSPC); 168{
125 if (error) 169 xfs_rtblock_t bbno; /* bitmap block number */
126 goto error_cancel; 170 xfs_buf_t *bp; /* summary buffer */
127 /* 171 int error; /* error return value */
128 * Free any blocks freed up in the transaction, then commit. 172 int log; /* summary level number (log length) */
129 */ 173 xfs_suminfo_t sum; /* summary data */
130 error = xfs_bmap_finish(&tp, &flist, &committed); 174 xfs_fsblock_t sumbno; /* summary block number */
131 if (error) 175
132 goto error_cancel; 176 bp = NULL;
133 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 177 for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
134 if (error) 178 for (bbno = omp->m_sb.sb_rbmblocks - 1;
135 goto error; 179 (xfs_srtblock_t)bbno >= 0;
136 /* 180 bbno--) {
137 * Now we need to clear the allocated blocks. 181 error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
138 * Do this one block per transaction, to keep it simple. 182 &sumbno, &sum);
139 */
140 cancelflags = 0;
141 for (bno = map.br_startoff, fsbno = map.br_startblock;
142 bno < map.br_startoff + map.br_blockcount;
143 bno++, fsbno++) {
144 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
145 /*
146 * Reserve log for one block zeroing.
147 */
148 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero,
149 0, 0);
150 if (error) 183 if (error)
151 goto error_cancel; 184 return error;
152 /* 185 if (sum == 0)
153 * Lock the bitmap inode. 186 continue;
154 */ 187 error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
155 xfs_ilock(ip, XFS_ILOCK_EXCL); 188 &bp, &sumbno);
156 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
157 /*
158 * Get a buffer for the block.
159 */
160 d = XFS_FSB_TO_DADDR(mp, fsbno);
161 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
162 mp->m_bsize, 0);
163 if (bp == NULL) {
164 error = XFS_ERROR(EIO);
165error_cancel:
166 xfs_trans_cancel(tp, cancelflags);
167 goto error;
168 }
169 memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
170 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
171 /*
172 * Commit the transaction.
173 */
174 error = xfs_trans_commit(tp, 0);
175 if (error) 189 if (error)
176 goto error; 190 return error;
191 error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
192 &bp, &sumbno);
193 if (error)
194 return error;
195 ASSERT(sum > 0);
177 } 196 }
178 /*
179 * Go on to the next extent, if any.
180 */
181 oblocks = map.br_startoff + map.br_blockcount;
182 } 197 }
183 return 0; 198 return 0;
199}
200/*
201 * Mark an extent specified by start and len allocated.
202 * Updates all the summary information as well as the bitmap.
203 */
204STATIC int /* error */
205xfs_rtallocate_range(
206 xfs_mount_t *mp, /* file system mount point */
207 xfs_trans_t *tp, /* transaction pointer */
208 xfs_rtblock_t start, /* start block to allocate */
209 xfs_extlen_t len, /* length to allocate */
210 xfs_buf_t **rbpp, /* in/out: summary block buffer */
211 xfs_fsblock_t *rsb) /* in/out: summary block number */
212{
213 xfs_rtblock_t end; /* end of the allocated extent */
214 int error; /* error value */
215 xfs_rtblock_t postblock = 0; /* first block allocated > end */
216 xfs_rtblock_t preblock = 0; /* first block allocated < start */
184 217
185error: 218 end = start + len - 1;
219 /*
220 * Assume we're allocating out of the middle of a free extent.
221 * We need to find the beginning and end of the extent so we can
222 * properly update the summary.
223 */
224 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
225 if (error) {
226 return error;
227 }
228 /*
229 * Find the next allocated block (end of free extent).
230 */
231 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
232 &postblock);
233 if (error) {
234 return error;
235 }
236 /*
237 * Decrement the summary information corresponding to the entire
238 * (old) free extent.
239 */
240 error = xfs_rtmodify_summary(mp, tp,
241 XFS_RTBLOCKLOG(postblock + 1 - preblock),
242 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
243 if (error) {
244 return error;
245 }
246 /*
247 * If there are blocks not being allocated at the front of the
248 * old extent, add summary data for them to be free.
249 */
250 if (preblock < start) {
251 error = xfs_rtmodify_summary(mp, tp,
252 XFS_RTBLOCKLOG(start - preblock),
253 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
254 if (error) {
255 return error;
256 }
257 }
258 /*
259 * If there are blocks not being allocated at the end of the
260 * old extent, add summary data for them to be free.
261 */
262 if (postblock > end) {
263 error = xfs_rtmodify_summary(mp, tp,
264 XFS_RTBLOCKLOG(postblock - end),
265 XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
266 if (error) {
267 return error;
268 }
269 }
270 /*
271 * Modify the bitmap to mark this extent allocated.
272 */
273 error = xfs_rtmodify_range(mp, tp, start, len, 0);
186 return error; 274 return error;
187} 275}
188 276
@@ -721,1112 +809,126 @@ xfs_rtallocate_extent_size(
721} 809}
722 810
723/* 811/*
724 * Mark an extent specified by start and len allocated. 812 * Allocate space to the bitmap or summary file, and zero it, for growfs.
725 * Updates all the summary information as well as the bitmap.
726 */ 813 */
727STATIC int /* error */ 814STATIC int /* error */
728xfs_rtallocate_range( 815xfs_growfs_rt_alloc(
729 xfs_mount_t *mp, /* file system mount point */ 816 xfs_mount_t *mp, /* file system mount point */
730 xfs_trans_t *tp, /* transaction pointer */ 817 xfs_extlen_t oblocks, /* old count of blocks */
731 xfs_rtblock_t start, /* start block to allocate */ 818 xfs_extlen_t nblocks, /* new count of blocks */
732 xfs_extlen_t len, /* length to allocate */ 819 xfs_inode_t *ip) /* inode (bitmap/summary) */
733 xfs_buf_t **rbpp, /* in/out: summary block buffer */
734 xfs_fsblock_t *rsb) /* in/out: summary block number */
735{ 820{
736 xfs_rtblock_t end; /* end of the allocated extent */ 821 xfs_fileoff_t bno; /* block number in file */
737 int error; /* error value */ 822 xfs_buf_t *bp; /* temporary buffer for zeroing */
738 xfs_rtblock_t postblock = 0; /* first block allocated > end */ 823 int committed; /* transaction committed flag */
739 xfs_rtblock_t preblock = 0; /* first block allocated < start */ 824 xfs_daddr_t d; /* disk block address */
825 int error; /* error return value */
826 xfs_fsblock_t firstblock; /* first block allocated in xaction */
827 xfs_bmap_free_t flist; /* list of freed blocks */
828 xfs_fsblock_t fsbno; /* filesystem block for bno */
829 xfs_bmbt_irec_t map; /* block map output */
830 int nmap; /* number of block maps */
831 int resblks; /* space reservation */
740 832
741 end = start + len - 1;
742 /*
743 * Assume we're allocating out of the middle of a free extent.
744 * We need to find the beginning and end of the extent so we can
745 * properly update the summary.
746 */
747 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
748 if (error) {
749 return error;
750 }
751 /*
752 * Find the next allocated block (end of free extent).
753 */
754 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
755 &postblock);
756 if (error) {
757 return error;
758 }
759 /*
760 * Decrement the summary information corresponding to the entire
761 * (old) free extent.
762 */
763 error = xfs_rtmodify_summary(mp, tp,
764 XFS_RTBLOCKLOG(postblock + 1 - preblock),
765 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
766 if (error) {
767 return error;
768 }
769 /*
770 * If there are blocks not being allocated at the front of the
771 * old extent, add summary data for them to be free.
772 */
773 if (preblock < start) {
774 error = xfs_rtmodify_summary(mp, tp,
775 XFS_RTBLOCKLOG(start - preblock),
776 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
777 if (error) {
778 return error;
779 }
780 }
781 /*
782 * If there are blocks not being allocated at the end of the
783 * old extent, add summary data for them to be free.
784 */
785 if (postblock > end) {
786 error = xfs_rtmodify_summary(mp, tp,
787 XFS_RTBLOCKLOG(postblock - end),
788 XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
789 if (error) {
790 return error;
791 }
792 }
793 /* 833 /*
794 * Modify the bitmap to mark this extent allocated. 834 * Allocate space to the file, as necessary.
795 */ 835 */
796 error = xfs_rtmodify_range(mp, tp, start, len, 0); 836 while (oblocks < nblocks) {
797 return error; 837 int cancelflags = 0;
798} 838 xfs_trans_t *tp;
799
800/*
801 * Return whether there are any free extents in the size range given
802 * by low and high, for the bitmap block bbno.
803 */
804STATIC int /* error */
805xfs_rtany_summary(
806 xfs_mount_t *mp, /* file system mount structure */
807 xfs_trans_t *tp, /* transaction pointer */
808 int low, /* low log2 extent size */
809 int high, /* high log2 extent size */
810 xfs_rtblock_t bbno, /* bitmap block number */
811 xfs_buf_t **rbpp, /* in/out: summary block buffer */
812 xfs_fsblock_t *rsb, /* in/out: summary block number */
813 int *stat) /* out: any good extents here? */
814{
815 int error; /* error value */
816 int log; /* loop counter, log2 of ext. size */
817 xfs_suminfo_t sum; /* summary data */
818 839
819 /* 840 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
820 * Loop over logs of extent sizes. Order is irrelevant. 841 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
821 */
822 for (log = low; log <= high; log++) {
823 /* 842 /*
824 * Get one summary datum. 843 * Reserve space & log for one extent added to the file.
825 */ 844 */
826 error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); 845 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata,
827 if (error) { 846 resblks, 0);
828 return error; 847 if (error)
829 } 848 goto error_cancel;
849 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
830 /* 850 /*
831 * If there are any, return success. 851 * Lock the inode.
832 */ 852 */
833 if (sum) { 853 xfs_ilock(ip, XFS_ILOCK_EXCL);
834 *stat = 1; 854 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
835 return 0;
836 }
837 }
838 /*
839 * Found nothing, return failure.
840 */
841 *stat = 0;
842 return 0;
843}
844
845/*
846 * Get a buffer for the bitmap or summary file block specified.
847 * The buffer is returned read and locked.
848 */
849STATIC int /* error */
850xfs_rtbuf_get(
851 xfs_mount_t *mp, /* file system mount structure */
852 xfs_trans_t *tp, /* transaction pointer */
853 xfs_rtblock_t block, /* block number in bitmap or summary */
854 int issum, /* is summary not bitmap */
855 xfs_buf_t **bpp) /* output: buffer for the block */
856{
857 xfs_buf_t *bp; /* block buffer, result */
858 xfs_inode_t *ip; /* bitmap or summary inode */
859 xfs_bmbt_irec_t map;
860 int nmap = 1;
861 int error; /* error value */
862
863 ip = issum ? mp->m_rsumip : mp->m_rbmip;
864
865 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
866 if (error)
867 return error;
868
869 ASSERT(map.br_startblock != NULLFSBLOCK);
870 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
871 XFS_FSB_TO_DADDR(mp, map.br_startblock),
872 mp->m_bsize, 0, &bp, NULL);
873 if (error)
874 return error;
875 ASSERT(!xfs_buf_geterror(bp));
876 *bpp = bp;
877 return 0;
878}
879
880#ifdef DEBUG
881/*
882 * Check that the given extent (block range) is allocated already.
883 */
884STATIC int /* error */
885xfs_rtcheck_alloc_range(
886 xfs_mount_t *mp, /* file system mount point */
887 xfs_trans_t *tp, /* transaction pointer */
888 xfs_rtblock_t bno, /* starting block number of extent */
889 xfs_extlen_t len, /* length of extent */
890 int *stat) /* out: 1 for allocated, 0 for not */
891{
892 xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
893
894 return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat);
895}
896#endif
897
898/*
899 * Check that the given range is either all allocated (val = 0) or
900 * all free (val = 1).
901 */
902STATIC int /* error */
903xfs_rtcheck_range(
904 xfs_mount_t *mp, /* file system mount point */
905 xfs_trans_t *tp, /* transaction pointer */
906 xfs_rtblock_t start, /* starting block number of extent */
907 xfs_extlen_t len, /* length of extent */
908 int val, /* 1 for free, 0 for allocated */
909 xfs_rtblock_t *new, /* out: first block not matching */
910 int *stat) /* out: 1 for matches, 0 for not */
911{
912 xfs_rtword_t *b; /* current word in buffer */
913 int bit; /* bit number in the word */
914 xfs_rtblock_t block; /* bitmap block number */
915 xfs_buf_t *bp; /* buf for the block */
916 xfs_rtword_t *bufp; /* starting word in buffer */
917 int error; /* error value */
918 xfs_rtblock_t i; /* current bit number rel. to start */
919 xfs_rtblock_t lastbit; /* last useful bit in word */
920 xfs_rtword_t mask; /* mask of relevant bits for value */
921 xfs_rtword_t wdiff; /* difference from wanted value */
922 int word; /* word number in the buffer */
923 855
924 /* 856 xfs_bmap_init(&flist, &firstblock);
925 * Compute starting bitmap block number
926 */
927 block = XFS_BITTOBLOCK(mp, start);
928 /*
929 * Read the bitmap block.
930 */
931 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
932 if (error) {
933 return error;
934 }
935 bufp = bp->b_addr;
936 /*
937 * Compute the starting word's address, and starting bit.
938 */
939 word = XFS_BITTOWORD(mp, start);
940 b = &bufp[word];
941 bit = (int)(start & (XFS_NBWORD - 1));
942 /*
943 * 0 (allocated) => all zero's; 1 (free) => all one's.
944 */
945 val = -val;
946 /*
947 * If not starting on a word boundary, deal with the first
948 * (partial) word.
949 */
950 if (bit) {
951 /*
952 * Compute first bit not examined.
953 */
954 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
955 /*
956 * Mask of relevant bits.
957 */
958 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
959 /*
960 * Compute difference between actual and desired value.
961 */
962 if ((wdiff = (*b ^ val) & mask)) {
963 /*
964 * Different, compute first wrong bit and return.
965 */
966 xfs_trans_brelse(tp, bp);
967 i = XFS_RTLOBIT(wdiff) - bit;
968 *new = start + i;
969 *stat = 0;
970 return 0;
971 }
972 i = lastbit - bit;
973 /*
974 * Go on to next block if that's where the next word is
975 * and we need the next word.
976 */
977 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
978 /*
979 * If done with this block, get the next one.
980 */
981 xfs_trans_brelse(tp, bp);
982 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
983 if (error) {
984 return error;
985 }
986 b = bufp = bp->b_addr;
987 word = 0;
988 } else {
989 /*
990 * Go on to the next word in the buffer.
991 */
992 b++;
993 }
994 } else {
995 /*
996 * Starting on a word boundary, no partial word.
997 */
998 i = 0;
999 }
1000 /*
1001 * Loop over whole words in buffers. When we use up one buffer
1002 * we move on to the next one.
1003 */
1004 while (len - i >= XFS_NBWORD) {
1005 /*
1006 * Compute difference between actual and desired value.
1007 */
1008 if ((wdiff = *b ^ val)) {
1009 /*
1010 * Different, compute first wrong bit and return.
1011 */
1012 xfs_trans_brelse(tp, bp);
1013 i += XFS_RTLOBIT(wdiff);
1014 *new = start + i;
1015 *stat = 0;
1016 return 0;
1017 }
1018 i += XFS_NBWORD;
1019 /* 857 /*
1020 * Go on to next block if that's where the next word is 858 * Allocate blocks to the bitmap file.
1021 * and we need the next word.
1022 */ 859 */
1023 if (++word == XFS_BLOCKWSIZE(mp) && i < len) { 860 nmap = 1;
1024 /* 861 cancelflags |= XFS_TRANS_ABORT;
1025 * If done with this block, get the next one. 862 error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
1026 */ 863 XFS_BMAPI_METADATA, &firstblock,
1027 xfs_trans_brelse(tp, bp); 864 resblks, &map, &nmap, &flist);
1028 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 865 if (!error && nmap < 1)
1029 if (error) { 866 error = XFS_ERROR(ENOSPC);
1030 return error; 867 if (error)
1031 } 868 goto error_cancel;
1032 b = bufp = bp->b_addr;
1033 word = 0;
1034 } else {
1035 /*
1036 * Go on to the next word in the buffer.
1037 */
1038 b++;
1039 }
1040 }
1041 /*
1042 * If not ending on a word boundary, deal with the last
1043 * (partial) word.
1044 */
1045 if ((lastbit = len - i)) {
1046 /* 869 /*
1047 * Mask of relevant bits. 870 * Free any blocks freed up in the transaction, then commit.
1048 */ 871 */
1049 mask = ((xfs_rtword_t)1 << lastbit) - 1; 872 error = xfs_bmap_finish(&tp, &flist, &committed);
873 if (error)
874 goto error_cancel;
875 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
876 if (error)
877 goto error;
1050 /* 878 /*
1051 * Compute difference between actual and desired value. 879 * Now we need to clear the allocated blocks.
880 * Do this one block per transaction, to keep it simple.
1052 */ 881 */
1053 if ((wdiff = (*b ^ val) & mask)) { 882 cancelflags = 0;
883 for (bno = map.br_startoff, fsbno = map.br_startblock;
884 bno < map.br_startoff + map.br_blockcount;
885 bno++, fsbno++) {
886 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
1054 /* 887 /*
1055 * Different, compute first wrong bit and return. 888 * Reserve log for one block zeroing.
1056 */ 889 */
1057 xfs_trans_brelse(tp, bp); 890 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero,
1058 i += XFS_RTLOBIT(wdiff); 891 0, 0);
1059 *new = start + i;
1060 *stat = 0;
1061 return 0;
1062 } else
1063 i = len;
1064 }
1065 /*
1066 * Successful, return.
1067 */
1068 xfs_trans_brelse(tp, bp);
1069 *new = start + i;
1070 *stat = 1;
1071 return 0;
1072}
1073
1074/*
1075 * Copy and transform the summary file, given the old and new
1076 * parameters in the mount structures.
1077 */
1078STATIC int /* error */
1079xfs_rtcopy_summary(
1080 xfs_mount_t *omp, /* old file system mount point */
1081 xfs_mount_t *nmp, /* new file system mount point */
1082 xfs_trans_t *tp) /* transaction pointer */
1083{
1084 xfs_rtblock_t bbno; /* bitmap block number */
1085 xfs_buf_t *bp; /* summary buffer */
1086 int error; /* error return value */
1087 int log; /* summary level number (log length) */
1088 xfs_suminfo_t sum; /* summary data */
1089 xfs_fsblock_t sumbno; /* summary block number */
1090
1091 bp = NULL;
1092 for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
1093 for (bbno = omp->m_sb.sb_rbmblocks - 1;
1094 (xfs_srtblock_t)bbno >= 0;
1095 bbno--) {
1096 error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
1097 &sumbno, &sum);
1098 if (error)
1099 return error;
1100 if (sum == 0)
1101 continue;
1102 error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
1103 &bp, &sumbno);
1104 if (error)
1105 return error;
1106 error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
1107 &bp, &sumbno);
1108 if (error) 892 if (error)
1109 return error; 893 goto error_cancel;
1110 ASSERT(sum > 0);
1111 }
1112 }
1113 return 0;
1114}
1115
1116/*
1117 * Searching backward from start to limit, find the first block whose
1118 * allocated/free state is different from start's.
1119 */
1120STATIC int /* error */
1121xfs_rtfind_back(
1122 xfs_mount_t *mp, /* file system mount point */
1123 xfs_trans_t *tp, /* transaction pointer */
1124 xfs_rtblock_t start, /* starting block to look at */
1125 xfs_rtblock_t limit, /* last block to look at */
1126 xfs_rtblock_t *rtblock) /* out: start block found */
1127{
1128 xfs_rtword_t *b; /* current word in buffer */
1129 int bit; /* bit number in the word */
1130 xfs_rtblock_t block; /* bitmap block number */
1131 xfs_buf_t *bp; /* buf for the block */
1132 xfs_rtword_t *bufp; /* starting word in buffer */
1133 int error; /* error value */
1134 xfs_rtblock_t firstbit; /* first useful bit in the word */
1135 xfs_rtblock_t i; /* current bit number rel. to start */
1136 xfs_rtblock_t len; /* length of inspected area */
1137 xfs_rtword_t mask; /* mask of relevant bits for value */
1138 xfs_rtword_t want; /* mask for "good" values */
1139 xfs_rtword_t wdiff; /* difference from wanted value */
1140 int word; /* word number in the buffer */
1141
1142 /*
1143 * Compute and read in starting bitmap block for starting block.
1144 */
1145 block = XFS_BITTOBLOCK(mp, start);
1146 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1147 if (error) {
1148 return error;
1149 }
1150 bufp = bp->b_addr;
1151 /*
1152 * Get the first word's index & point to it.
1153 */
1154 word = XFS_BITTOWORD(mp, start);
1155 b = &bufp[word];
1156 bit = (int)(start & (XFS_NBWORD - 1));
1157 len = start - limit + 1;
1158 /*
1159 * Compute match value, based on the bit at start: if 1 (free)
1160 * then all-ones, else all-zeroes.
1161 */
1162 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1163 /*
1164 * If the starting position is not word-aligned, deal with the
1165 * partial word.
1166 */
1167 if (bit < XFS_NBWORD - 1) {
1168 /*
1169 * Calculate first (leftmost) bit number to look at,
1170 * and mask for all the relevant bits in this word.
1171 */
1172 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
1173 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
1174 firstbit;
1175 /*
1176 * Calculate the difference between the value there
1177 * and what we're looking for.
1178 */
1179 if ((wdiff = (*b ^ want) & mask)) {
1180 /*
1181 * Different. Mark where we are and return.
1182 */
1183 xfs_trans_brelse(tp, bp);
1184 i = bit - XFS_RTHIBIT(wdiff);
1185 *rtblock = start - i + 1;
1186 return 0;
1187 }
1188 i = bit - firstbit + 1;
1189 /*
1190 * Go on to previous block if that's where the previous word is
1191 * and we need the previous word.
1192 */
1193 if (--word == -1 && i < len) {
1194 /*
1195 * If done with this block, get the previous one.
1196 */
1197 xfs_trans_brelse(tp, bp);
1198 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1199 if (error) {
1200 return error;
1201 }
1202 bufp = bp->b_addr;
1203 word = XFS_BLOCKWMASK(mp);
1204 b = &bufp[word];
1205 } else {
1206 /*
1207 * Go on to the previous word in the buffer.
1208 */
1209 b--;
1210 }
1211 } else {
1212 /*
1213 * Starting on a word boundary, no partial word.
1214 */
1215 i = 0;
1216 }
1217 /*
1218 * Loop over whole words in buffers. When we use up one buffer
1219 * we move on to the previous one.
1220 */
1221 while (len - i >= XFS_NBWORD) {
1222 /*
1223 * Compute difference between actual and desired value.
1224 */
1225 if ((wdiff = *b ^ want)) {
1226 /*
1227 * Different, mark where we are and return.
1228 */
1229 xfs_trans_brelse(tp, bp);
1230 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1231 *rtblock = start - i + 1;
1232 return 0;
1233 }
1234 i += XFS_NBWORD;
1235 /*
1236 * Go on to previous block if that's where the previous word is
1237 * and we need the previous word.
1238 */
1239 if (--word == -1 && i < len) {
1240 /*
1241 * If done with this block, get the previous one.
1242 */
1243 xfs_trans_brelse(tp, bp);
1244 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1245 if (error) {
1246 return error;
1247 }
1248 bufp = bp->b_addr;
1249 word = XFS_BLOCKWMASK(mp);
1250 b = &bufp[word];
1251 } else {
1252 /*
1253 * Go on to the previous word in the buffer.
1254 */
1255 b--;
1256 }
1257 }
1258 /*
1259 * If not ending on a word boundary, deal with the last
1260 * (partial) word.
1261 */
1262 if (len - i) {
1263 /*
1264 * Calculate first (leftmost) bit number to look at,
1265 * and mask for all the relevant bits in this word.
1266 */
1267 firstbit = XFS_NBWORD - (len - i);
1268 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
1269 /*
1270 * Compute difference between actual and desired value.
1271 */
1272 if ((wdiff = (*b ^ want) & mask)) {
1273 /*
1274 * Different, mark where we are and return.
1275 */
1276 xfs_trans_brelse(tp, bp);
1277 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1278 *rtblock = start - i + 1;
1279 return 0;
1280 } else
1281 i = len;
1282 }
1283 /*
1284 * No match, return that we scanned the whole area.
1285 */
1286 xfs_trans_brelse(tp, bp);
1287 *rtblock = start - i + 1;
1288 return 0;
1289}
1290
1291/*
1292 * Searching forward from start to limit, find the first block whose
1293 * allocated/free state is different from start's.
1294 */
1295STATIC int /* error */
1296xfs_rtfind_forw(
1297 xfs_mount_t *mp, /* file system mount point */
1298 xfs_trans_t *tp, /* transaction pointer */
1299 xfs_rtblock_t start, /* starting block to look at */
1300 xfs_rtblock_t limit, /* last block to look at */
1301 xfs_rtblock_t *rtblock) /* out: start block found */
1302{
1303 xfs_rtword_t *b; /* current word in buffer */
1304 int bit; /* bit number in the word */
1305 xfs_rtblock_t block; /* bitmap block number */
1306 xfs_buf_t *bp; /* buf for the block */
1307 xfs_rtword_t *bufp; /* starting word in buffer */
1308 int error; /* error value */
1309 xfs_rtblock_t i; /* current bit number rel. to start */
1310 xfs_rtblock_t lastbit; /* last useful bit in the word */
1311 xfs_rtblock_t len; /* length of inspected area */
1312 xfs_rtword_t mask; /* mask of relevant bits for value */
1313 xfs_rtword_t want; /* mask for "good" values */
1314 xfs_rtword_t wdiff; /* difference from wanted value */
1315 int word; /* word number in the buffer */
1316
1317 /*
1318 * Compute and read in starting bitmap block for starting block.
1319 */
1320 block = XFS_BITTOBLOCK(mp, start);
1321 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1322 if (error) {
1323 return error;
1324 }
1325 bufp = bp->b_addr;
1326 /*
1327 * Get the first word's index & point to it.
1328 */
1329 word = XFS_BITTOWORD(mp, start);
1330 b = &bufp[word];
1331 bit = (int)(start & (XFS_NBWORD - 1));
1332 len = limit - start + 1;
1333 /*
1334 * Compute match value, based on the bit at start: if 1 (free)
1335 * then all-ones, else all-zeroes.
1336 */
1337 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1338 /*
1339 * If the starting position is not word-aligned, deal with the
1340 * partial word.
1341 */
1342 if (bit) {
1343 /*
1344 * Calculate last (rightmost) bit number to look at,
1345 * and mask for all the relevant bits in this word.
1346 */
1347 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1348 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1349 /*
1350 * Calculate the difference between the value there
1351 * and what we're looking for.
1352 */
1353 if ((wdiff = (*b ^ want) & mask)) {
1354 /*
1355 * Different. Mark where we are and return.
1356 */
1357 xfs_trans_brelse(tp, bp);
1358 i = XFS_RTLOBIT(wdiff) - bit;
1359 *rtblock = start + i - 1;
1360 return 0;
1361 }
1362 i = lastbit - bit;
1363 /*
1364 * Go on to next block if that's where the next word is
1365 * and we need the next word.
1366 */
1367 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1368 /*
1369 * If done with this block, get the previous one.
1370 */
1371 xfs_trans_brelse(tp, bp);
1372 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1373 if (error) {
1374 return error;
1375 }
1376 b = bufp = bp->b_addr;
1377 word = 0;
1378 } else {
1379 /*
1380 * Go on to the previous word in the buffer.
1381 */
1382 b++;
1383 }
1384 } else {
1385 /*
1386 * Starting on a word boundary, no partial word.
1387 */
1388 i = 0;
1389 }
1390 /*
1391 * Loop over whole words in buffers. When we use up one buffer
1392 * we move on to the next one.
1393 */
1394 while (len - i >= XFS_NBWORD) {
1395 /*
1396 * Compute difference between actual and desired value.
1397 */
1398 if ((wdiff = *b ^ want)) {
1399 /* 894 /*
1400 * Different, mark where we are and return. 895 * Lock the bitmap inode.
1401 */ 896 */
1402 xfs_trans_brelse(tp, bp); 897 xfs_ilock(ip, XFS_ILOCK_EXCL);
1403 i += XFS_RTLOBIT(wdiff); 898 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1404 *rtblock = start + i - 1;
1405 return 0;
1406 }
1407 i += XFS_NBWORD;
1408 /*
1409 * Go on to next block if that's where the next word is
1410 * and we need the next word.
1411 */
1412 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1413 /* 899 /*
1414 * If done with this block, get the next one. 900 * Get a buffer for the block.
1415 */ 901 */
1416 xfs_trans_brelse(tp, bp); 902 d = XFS_FSB_TO_DADDR(mp, fsbno);
1417 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 903 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
1418 if (error) { 904 mp->m_bsize, 0);
1419 return error; 905 if (bp == NULL) {
906 error = XFS_ERROR(EIO);
907error_cancel:
908 xfs_trans_cancel(tp, cancelflags);
909 goto error;
1420 } 910 }
1421 b = bufp = bp->b_addr; 911 memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
1422 word = 0; 912 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
1423 } else {
1424 /* 913 /*
1425 * Go on to the next word in the buffer. 914 * Commit the transaction.
1426 */ 915 */
1427 b++; 916 error = xfs_trans_commit(tp, 0);
917 if (error)
918 goto error;
1428 } 919 }
1429 }
1430 /*
1431 * If not ending on a word boundary, deal with the last
1432 * (partial) word.
1433 */
1434 if ((lastbit = len - i)) {
1435 /*
1436 * Calculate mask for all the relevant bits in this word.
1437 */
1438 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1439 /* 920 /*
1440 * Compute difference between actual and desired value. 921 * Go on to the next extent, if any.
1441 */ 922 */
1442 if ((wdiff = (*b ^ want) & mask)) { 923 oblocks = map.br_startoff + map.br_blockcount;
1443 /*
1444 * Different, mark where we are and return.
1445 */
1446 xfs_trans_brelse(tp, bp);
1447 i += XFS_RTLOBIT(wdiff);
1448 *rtblock = start + i - 1;
1449 return 0;
1450 } else
1451 i = len;
1452 } 924 }
1453 /*
1454 * No match, return that we scanned the whole area.
1455 */
1456 xfs_trans_brelse(tp, bp);
1457 *rtblock = start + i - 1;
1458 return 0; 925 return 0;
1459}
1460 926
1461/* 927error:
1462 * Mark an extent specified by start and len freed.
1463 * Updates all the summary information as well as the bitmap.
1464 */
1465STATIC int /* error */
1466xfs_rtfree_range(
1467 xfs_mount_t *mp, /* file system mount point */
1468 xfs_trans_t *tp, /* transaction pointer */
1469 xfs_rtblock_t start, /* starting block to free */
1470 xfs_extlen_t len, /* length to free */
1471 xfs_buf_t **rbpp, /* in/out: summary block buffer */
1472 xfs_fsblock_t *rsb) /* in/out: summary block number */
1473{
1474 xfs_rtblock_t end; /* end of the freed extent */
1475 int error; /* error value */
1476 xfs_rtblock_t postblock; /* first block freed > end */
1477 xfs_rtblock_t preblock; /* first block freed < start */
1478
1479 end = start + len - 1;
1480 /*
1481 * Modify the bitmap to mark this extent freed.
1482 */
1483 error = xfs_rtmodify_range(mp, tp, start, len, 1);
1484 if (error) {
1485 return error;
1486 }
1487 /*
1488 * Assume we're freeing out of the middle of an allocated extent.
1489 * We need to find the beginning and end of the extent so we can
1490 * properly update the summary.
1491 */
1492 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
1493 if (error) {
1494 return error;
1495 }
1496 /*
1497 * Find the next allocated block (end of allocated extent).
1498 */
1499 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
1500 &postblock);
1501 if (error)
1502 return error;
1503 /*
1504 * If there are blocks not being freed at the front of the
1505 * old extent, add summary data for them to be allocated.
1506 */
1507 if (preblock < start) {
1508 error = xfs_rtmodify_summary(mp, tp,
1509 XFS_RTBLOCKLOG(start - preblock),
1510 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
1511 if (error) {
1512 return error;
1513 }
1514 }
1515 /*
1516 * If there are blocks not being freed at the end of the
1517 * old extent, add summary data for them to be allocated.
1518 */
1519 if (postblock > end) {
1520 error = xfs_rtmodify_summary(mp, tp,
1521 XFS_RTBLOCKLOG(postblock - end),
1522 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
1523 if (error) {
1524 return error;
1525 }
1526 }
1527 /*
1528 * Increment the summary information corresponding to the entire
1529 * (new) free extent.
1530 */
1531 error = xfs_rtmodify_summary(mp, tp,
1532 XFS_RTBLOCKLOG(postblock + 1 - preblock),
1533 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
1534 return error; 928 return error;
1535} 929}
1536 930
1537/* 931/*
1538 * Read and return the summary information for a given extent size,
1539 * bitmap block combination.
1540 * Keeps track of a current summary block, so we don't keep reading
1541 * it from the buffer cache.
1542 */
1543STATIC int /* error */
1544xfs_rtget_summary(
1545 xfs_mount_t *mp, /* file system mount structure */
1546 xfs_trans_t *tp, /* transaction pointer */
1547 int log, /* log2 of extent size */
1548 xfs_rtblock_t bbno, /* bitmap block number */
1549 xfs_buf_t **rbpp, /* in/out: summary block buffer */
1550 xfs_fsblock_t *rsb, /* in/out: summary block number */
1551 xfs_suminfo_t *sum) /* out: summary info for this block */
1552{
1553 xfs_buf_t *bp; /* buffer for summary block */
1554 int error; /* error value */
1555 xfs_fsblock_t sb; /* summary fsblock */
1556 int so; /* index into the summary file */
1557 xfs_suminfo_t *sp; /* pointer to returned data */
1558
1559 /*
1560 * Compute entry number in the summary file.
1561 */
1562 so = XFS_SUMOFFS(mp, log, bbno);
1563 /*
1564 * Compute the block number in the summary file.
1565 */
1566 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1567 /*
1568 * If we have an old buffer, and the block number matches, use that.
1569 */
1570 if (rbpp && *rbpp && *rsb == sb)
1571 bp = *rbpp;
1572 /*
1573 * Otherwise we have to get the buffer.
1574 */
1575 else {
1576 /*
1577 * If there was an old one, get rid of it first.
1578 */
1579 if (rbpp && *rbpp)
1580 xfs_trans_brelse(tp, *rbpp);
1581 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1582 if (error) {
1583 return error;
1584 }
1585 /*
1586 * Remember this buffer and block for the next call.
1587 */
1588 if (rbpp) {
1589 *rbpp = bp;
1590 *rsb = sb;
1591 }
1592 }
1593 /*
1594 * Point to the summary information & copy it out.
1595 */
1596 sp = XFS_SUMPTR(mp, bp, so);
1597 *sum = *sp;
1598 /*
1599 * Drop the buffer if we're not asked to remember it.
1600 */
1601 if (!rbpp)
1602 xfs_trans_brelse(tp, bp);
1603 return 0;
1604}
1605
1606/*
1607 * Set the given range of bitmap bits to the given value.
1608 * Do whatever I/O and logging is required.
1609 */
1610STATIC int /* error */
1611xfs_rtmodify_range(
1612 xfs_mount_t *mp, /* file system mount point */
1613 xfs_trans_t *tp, /* transaction pointer */
1614 xfs_rtblock_t start, /* starting block to modify */
1615 xfs_extlen_t len, /* length of extent to modify */
1616 int val) /* 1 for free, 0 for allocated */
1617{
1618 xfs_rtword_t *b; /* current word in buffer */
1619 int bit; /* bit number in the word */
1620 xfs_rtblock_t block; /* bitmap block number */
1621 xfs_buf_t *bp; /* buf for the block */
1622 xfs_rtword_t *bufp; /* starting word in buffer */
1623 int error; /* error value */
1624 xfs_rtword_t *first; /* first used word in the buffer */
1625 int i; /* current bit number rel. to start */
1626 int lastbit; /* last useful bit in word */
1627 xfs_rtword_t mask; /* mask o frelevant bits for value */
1628 int word; /* word number in the buffer */
1629
1630 /*
1631 * Compute starting bitmap block number.
1632 */
1633 block = XFS_BITTOBLOCK(mp, start);
1634 /*
1635 * Read the bitmap block, and point to its data.
1636 */
1637 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1638 if (error) {
1639 return error;
1640 }
1641 bufp = bp->b_addr;
1642 /*
1643 * Compute the starting word's address, and starting bit.
1644 */
1645 word = XFS_BITTOWORD(mp, start);
1646 first = b = &bufp[word];
1647 bit = (int)(start & (XFS_NBWORD - 1));
1648 /*
1649 * 0 (allocated) => all zeroes; 1 (free) => all ones.
1650 */
1651 val = -val;
1652 /*
1653 * If not starting on a word boundary, deal with the first
1654 * (partial) word.
1655 */
1656 if (bit) {
1657 /*
1658 * Compute first bit not changed and mask of relevant bits.
1659 */
1660 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1661 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1662 /*
1663 * Set/clear the active bits.
1664 */
1665 if (val)
1666 *b |= mask;
1667 else
1668 *b &= ~mask;
1669 i = lastbit - bit;
1670 /*
1671 * Go on to the next block if that's where the next word is
1672 * and we need the next word.
1673 */
1674 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1675 /*
1676 * Log the changed part of this block.
1677 * Get the next one.
1678 */
1679 xfs_trans_log_buf(tp, bp,
1680 (uint)((char *)first - (char *)bufp),
1681 (uint)((char *)b - (char *)bufp));
1682 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1683 if (error) {
1684 return error;
1685 }
1686 first = b = bufp = bp->b_addr;
1687 word = 0;
1688 } else {
1689 /*
1690 * Go on to the next word in the buffer
1691 */
1692 b++;
1693 }
1694 } else {
1695 /*
1696 * Starting on a word boundary, no partial word.
1697 */
1698 i = 0;
1699 }
1700 /*
1701 * Loop over whole words in buffers. When we use up one buffer
1702 * we move on to the next one.
1703 */
1704 while (len - i >= XFS_NBWORD) {
1705 /*
1706 * Set the word value correctly.
1707 */
1708 *b = val;
1709 i += XFS_NBWORD;
1710 /*
1711 * Go on to the next block if that's where the next word is
1712 * and we need the next word.
1713 */
1714 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1715 /*
1716 * Log the changed part of this block.
1717 * Get the next one.
1718 */
1719 xfs_trans_log_buf(tp, bp,
1720 (uint)((char *)first - (char *)bufp),
1721 (uint)((char *)b - (char *)bufp));
1722 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1723 if (error) {
1724 return error;
1725 }
1726 first = b = bufp = bp->b_addr;
1727 word = 0;
1728 } else {
1729 /*
1730 * Go on to the next word in the buffer
1731 */
1732 b++;
1733 }
1734 }
1735 /*
1736 * If not ending on a word boundary, deal with the last
1737 * (partial) word.
1738 */
1739 if ((lastbit = len - i)) {
1740 /*
1741 * Compute a mask of relevant bits.
1742 */
1743 bit = 0;
1744 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1745 /*
1746 * Set/clear the active bits.
1747 */
1748 if (val)
1749 *b |= mask;
1750 else
1751 *b &= ~mask;
1752 b++;
1753 }
1754 /*
1755 * Log any remaining changed bytes.
1756 */
1757 if (b > first)
1758 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
1759 (uint)((char *)b - (char *)bufp - 1));
1760 return 0;
1761}
1762
1763/*
1764 * Read and modify the summary information for a given extent size,
1765 * bitmap block combination.
1766 * Keeps track of a current summary block, so we don't keep reading
1767 * it from the buffer cache.
1768 */
1769STATIC int /* error */
1770xfs_rtmodify_summary(
1771 xfs_mount_t *mp, /* file system mount point */
1772 xfs_trans_t *tp, /* transaction pointer */
1773 int log, /* log2 of extent size */
1774 xfs_rtblock_t bbno, /* bitmap block number */
1775 int delta, /* change to make to summary info */
1776 xfs_buf_t **rbpp, /* in/out: summary block buffer */
1777 xfs_fsblock_t *rsb) /* in/out: summary block number */
1778{
1779 xfs_buf_t *bp; /* buffer for the summary block */
1780 int error; /* error value */
1781 xfs_fsblock_t sb; /* summary fsblock */
1782 int so; /* index into the summary file */
1783 xfs_suminfo_t *sp; /* pointer to returned data */
1784
1785 /*
1786 * Compute entry number in the summary file.
1787 */
1788 so = XFS_SUMOFFS(mp, log, bbno);
1789 /*
1790 * Compute the block number in the summary file.
1791 */
1792 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1793 /*
1794 * If we have an old buffer, and the block number matches, use that.
1795 */
1796 if (rbpp && *rbpp && *rsb == sb)
1797 bp = *rbpp;
1798 /*
1799 * Otherwise we have to get the buffer.
1800 */
1801 else {
1802 /*
1803 * If there was an old one, get rid of it first.
1804 */
1805 if (rbpp && *rbpp)
1806 xfs_trans_brelse(tp, *rbpp);
1807 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1808 if (error) {
1809 return error;
1810 }
1811 /*
1812 * Remember this buffer and block for the next call.
1813 */
1814 if (rbpp) {
1815 *rbpp = bp;
1816 *rsb = sb;
1817 }
1818 }
1819 /*
1820 * Point to the summary information, modify and log it.
1821 */
1822 sp = XFS_SUMPTR(mp, bp, so);
1823 *sp += delta;
1824 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
1825 (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
1826 return 0;
1827}
1828
1829/*
1830 * Visible (exported) functions. 932 * Visible (exported) functions.
1831 */ 933 */
1832 934
@@ -2129,66 +1231,6 @@ xfs_rtallocate_extent(
2129} 1231}
2130 1232
2131/* 1233/*
2132 * Free an extent in the realtime subvolume. Length is expressed in
2133 * realtime extents, as is the block number.
2134 */
2135int /* error */
2136xfs_rtfree_extent(
2137 xfs_trans_t *tp, /* transaction pointer */
2138 xfs_rtblock_t bno, /* starting block number to free */
2139 xfs_extlen_t len) /* length of extent freed */
2140{
2141 int error; /* error value */
2142 xfs_mount_t *mp; /* file system mount structure */
2143 xfs_fsblock_t sb; /* summary file block number */
2144 xfs_buf_t *sumbp; /* summary file block buffer */
2145
2146 mp = tp->t_mountp;
2147
2148 ASSERT(mp->m_rbmip->i_itemp != NULL);
2149 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
2150
2151#ifdef DEBUG
2152 /*
2153 * Check to see that this whole range is currently allocated.
2154 */
2155 {
2156 int stat; /* result from checking range */
2157
2158 error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
2159 if (error) {
2160 return error;
2161 }
2162 ASSERT(stat);
2163 }
2164#endif
2165 sumbp = NULL;
2166 /*
2167 * Free the range of realtime blocks.
2168 */
2169 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
2170 if (error) {
2171 return error;
2172 }
2173 /*
2174 * Mark more blocks free in the superblock.
2175 */
2176 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
2177 /*
2178 * If we've now freed all the blocks, reset the file sequence
2179 * number to 0.
2180 */
2181 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
2182 mp->m_sb.sb_rextents) {
2183 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
2184 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2185 *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
2186 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
2187 }
2188 return 0;
2189}
2190
2191/*
2192 * Initialize realtime fields in the mount structure. 1234 * Initialize realtime fields in the mount structure.
2193 */ 1235 */
2194int /* error */ 1236int /* error */