1153323Srodrigc/*
2159451Srodrigc * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3159451Srodrigc * All Rights Reserved.
4153323Srodrigc *
5159451Srodrigc * This program is free software; you can redistribute it and/or
6159451Srodrigc * modify it under the terms of the GNU General Public License as
7153323Srodrigc * published by the Free Software Foundation.
8153323Srodrigc *
9159451Srodrigc * This program is distributed in the hope that it would be useful,
10159451Srodrigc * but WITHOUT ANY WARRANTY; without even the implied warranty of
11159451Srodrigc * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12159451Srodrigc * GNU General Public License for more details.
13153323Srodrigc *
14159451Srodrigc * You should have received a copy of the GNU General Public License
15159451Srodrigc * along with this program; if not, write the Free Software Foundation,
16159451Srodrigc * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17153323Srodrigc */
18153323Srodrigc#include "xfs.h"
19159451Srodrigc#include "xfs_fs.h"
20153323Srodrigc#include "xfs_types.h"
21159451Srodrigc#include "xfs_bit.h"
22159451Srodrigc#include "xfs_log.h"
23153323Srodrigc#include "xfs_inum.h"
24153323Srodrigc#include "xfs_trans.h"
25153323Srodrigc#include "xfs_sb.h"
26153323Srodrigc#include "xfs_ag.h"
27153323Srodrigc#include "xfs_dir.h"
28153323Srodrigc#include "xfs_dir2.h"
29153323Srodrigc#include "xfs_dmapi.h"
30153323Srodrigc#include "xfs_mount.h"
31159451Srodrigc#include "xfs_bmap_btree.h"
32153323Srodrigc#include "xfs_alloc_btree.h"
33153323Srodrigc#include "xfs_ialloc_btree.h"
34153323Srodrigc#include "xfs_dir_sf.h"
35153323Srodrigc#include "xfs_dir2_sf.h"
36159451Srodrigc#include "xfs_attr_sf.h"
37153323Srodrigc#include "xfs_dinode.h"
38153323Srodrigc#include "xfs_inode.h"
39159451Srodrigc#include "xfs_btree.h"
40159451Srodrigc#include "xfs_ialloc.h"
41153323Srodrigc#include "xfs_alloc.h"
42153323Srodrigc#include "xfs_bmap.h"
43153323Srodrigc#include "xfs_rtalloc.h"
44153323Srodrigc#include "xfs_fsops.h"
45153323Srodrigc#include "xfs_error.h"
46153323Srodrigc#include "xfs_rw.h"
47153323Srodrigc#include "xfs_inode_item.h"
48153323Srodrigc#include "xfs_trans_space.h"
49153323Srodrigc
50153323Srodrigc
51153323Srodrigc/*
52153323Srodrigc * Prototypes for internal functions.
53153323Srodrigc */
54153323Srodrigc
55153323Srodrigc
56153323SrodrigcSTATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
57153323Srodrigc		xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *);
58153323SrodrigcSTATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int,
59153323Srodrigc		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *);
60153323SrodrigcSTATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
61153323Srodrigc		xfs_extlen_t, int, xfs_rtblock_t *, int *);
62153323SrodrigcSTATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
63153323Srodrigc		xfs_rtblock_t, xfs_rtblock_t *);
64153323SrodrigcSTATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
65153323Srodrigc		xfs_rtblock_t, xfs_rtblock_t *);
66153323SrodrigcSTATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int,
67153323Srodrigc		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *);
68153323SrodrigcSTATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
69153323Srodrigc		xfs_extlen_t, int);
70153323SrodrigcSTATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
71153323Srodrigc		xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);
72153323Srodrigc
73153323Srodrigc/*
74153323Srodrigc * Internal functions.
75153323Srodrigc */
76153323Srodrigc
77153323Srodrigc/*
78153323Srodrigc * xfs_lowbit32: get low bit set out of 32-bit argument, -1 if none set.
79153323Srodrigc */
80153323SrodrigcSTATIC int
81153323Srodrigcxfs_lowbit32(
82153323Srodrigc	__uint32_t	v)
83153323Srodrigc{
84159451Srodrigc	if (v)
85159451Srodrigc		return ffs(v) - 1;
86159451Srodrigc	return -1;
87153323Srodrigc}
88153323Srodrigc
89153323Srodrigc/*
90153323Srodrigc * Allocate space to the bitmap or summary file, and zero it, for growfs.
91153323Srodrigc */
92153323SrodrigcSTATIC int				/* error */
93153323Srodrigcxfs_growfs_rt_alloc(
94153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
95153323Srodrigc	xfs_extlen_t	oblocks,	/* old count of blocks */
96153323Srodrigc	xfs_extlen_t	nblocks,	/* new count of blocks */
97153323Srodrigc	xfs_ino_t	ino)		/* inode number (bitmap/summary) */
98153323Srodrigc{
99153323Srodrigc	xfs_fileoff_t	bno;		/* block number in file */
100153323Srodrigc	xfs_buf_t	*bp;		/* temporary buffer for zeroing */
101153323Srodrigc	int		cancelflags;	/* flags for xfs_trans_cancel */
102153323Srodrigc	int		committed;	/* transaction committed flag */
103153323Srodrigc	xfs_daddr_t	d;		/* disk block address */
104153323Srodrigc	int		error;		/* error return value */
105153323Srodrigc	xfs_fsblock_t	firstblock;	/* first block allocated in xaction */
106153323Srodrigc	xfs_bmap_free_t	flist;		/* list of freed blocks */
107153323Srodrigc	xfs_fsblock_t	fsbno;		/* filesystem block for bno */
108153323Srodrigc	xfs_inode_t	*ip;		/* pointer to incore inode */
109153323Srodrigc	xfs_bmbt_irec_t	map;		/* block map output */
110153323Srodrigc	int		nmap;		/* number of block maps */
111153323Srodrigc	int		resblks;	/* space reservation */
112153323Srodrigc	xfs_trans_t	*tp;		/* transaction pointer */
113153323Srodrigc
114153323Srodrigc	/*
115153323Srodrigc	 * Allocate space to the file, as necessary.
116153323Srodrigc	 */
117153323Srodrigc	while (oblocks < nblocks) {
118153323Srodrigc		tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
119153323Srodrigc		resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
120153323Srodrigc		cancelflags = 0;
121153323Srodrigc		/*
122153323Srodrigc		 * Reserve space & log for one extent added to the file.
123153323Srodrigc		 */
124153323Srodrigc		if ((error = xfs_trans_reserve(tp, resblks,
125153323Srodrigc				XFS_GROWRTALLOC_LOG_RES(mp), 0,
126153323Srodrigc				XFS_TRANS_PERM_LOG_RES,
127153323Srodrigc				XFS_DEFAULT_PERM_LOG_COUNT)))
128153323Srodrigc			goto error_exit;
129153323Srodrigc		cancelflags = XFS_TRANS_RELEASE_LOG_RES;
130153323Srodrigc		/*
131153323Srodrigc		 * Lock the inode.
132153323Srodrigc		 */
133159451Srodrigc		if ((error = xfs_trans_iget(mp, tp, ino, 0,
134159451Srodrigc						XFS_ILOCK_EXCL, &ip)))
135153323Srodrigc			goto error_exit;
136153323Srodrigc		XFS_BMAP_INIT(&flist, &firstblock);
137153323Srodrigc		/*
138153323Srodrigc		 * Allocate blocks to the bitmap file.
139153323Srodrigc		 */
140153323Srodrigc		nmap = 1;
141153323Srodrigc		cancelflags |= XFS_TRANS_ABORT;
142153323Srodrigc		error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks,
143153323Srodrigc			XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock,
144159451Srodrigc			resblks, &map, &nmap, &flist, NULL);
145153323Srodrigc		if (!error && nmap < 1)
146153323Srodrigc			error = XFS_ERROR(ENOSPC);
147153323Srodrigc		if (error)
148153323Srodrigc			goto error_exit;
149153323Srodrigc		/*
150153323Srodrigc		 * Free any blocks freed up in the transaction, then commit.
151153323Srodrigc		 */
152153323Srodrigc		error = xfs_bmap_finish(&tp, &flist, firstblock, &committed);
153153323Srodrigc		if (error)
154153323Srodrigc			goto error_exit;
155153323Srodrigc		xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
156153323Srodrigc		/*
157153323Srodrigc		 * Now we need to clear the allocated blocks.
158153323Srodrigc		 * Do this one block per transaction, to keep it simple.
159153323Srodrigc		 */
160153323Srodrigc		cancelflags = 0;
161153323Srodrigc		for (bno = map.br_startoff, fsbno = map.br_startblock;
162153323Srodrigc		     bno < map.br_startoff + map.br_blockcount;
163153323Srodrigc		     bno++, fsbno++) {
164153323Srodrigc			tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
165153323Srodrigc			/*
166153323Srodrigc			 * Reserve log for one block zeroing.
167153323Srodrigc			 */
168153323Srodrigc			if ((error = xfs_trans_reserve(tp, 0,
169153323Srodrigc					XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))
170153323Srodrigc				goto error_exit;
171153323Srodrigc			/*
172153323Srodrigc			 * Lock the bitmap inode.
173153323Srodrigc			 */
174159451Srodrigc			if ((error = xfs_trans_iget(mp, tp, ino, 0,
175159451Srodrigc							XFS_ILOCK_EXCL, &ip)))
176153323Srodrigc				goto error_exit;
177153323Srodrigc			/*
178153323Srodrigc			 * Get a buffer for the block.
179153323Srodrigc			 */
180153323Srodrigc			d = XFS_FSB_TO_DADDR(mp, fsbno);
181153323Srodrigc			bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
182153323Srodrigc				mp->m_bsize, 0);
183153323Srodrigc			if (bp == NULL) {
184153323Srodrigc				error = XFS_ERROR(EIO);
185153323Srodrigc				goto error_exit;
186153323Srodrigc			}
187153323Srodrigc			memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);
188153323Srodrigc			xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
189153323Srodrigc			/*
190153323Srodrigc			 * Commit the transaction.
191153323Srodrigc			 */
192153323Srodrigc			xfs_trans_commit(tp, 0, NULL);
193153323Srodrigc		}
194153323Srodrigc		/*
195153323Srodrigc		 * Go on to the next extent, if any.
196153323Srodrigc		 */
197153323Srodrigc		oblocks = map.br_startoff + map.br_blockcount;
198153323Srodrigc	}
199153323Srodrigc	return 0;
200153323Srodrigcerror_exit:
201153323Srodrigc	xfs_trans_cancel(tp, cancelflags);
202153323Srodrigc	return error;
203153323Srodrigc}
204153323Srodrigc
205153323Srodrigc/*
206153323Srodrigc * Attempt to allocate an extent minlen<=len<=maxlen starting from
207153323Srodrigc * bitmap block bbno.  If we don't get maxlen then use prod to trim
208153323Srodrigc * the length, if given.  Returns error; returns starting block in *rtblock.
209153323Srodrigc * The lengths are all in rtextents.
210153323Srodrigc */
211153323SrodrigcSTATIC int				/* error */
212153323Srodrigcxfs_rtallocate_extent_block(
213153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
214153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
215153323Srodrigc	xfs_rtblock_t	bbno,		/* bitmap block number */
216153323Srodrigc	xfs_extlen_t	minlen,		/* minimum length to allocate */
217153323Srodrigc	xfs_extlen_t	maxlen,		/* maximum length to allocate */
218153323Srodrigc	xfs_extlen_t	*len,		/* out: actual length allocated */
219153323Srodrigc	xfs_rtblock_t	*nextp,		/* out: next block to try */
220153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
221153323Srodrigc	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
222153323Srodrigc	xfs_extlen_t	prod,		/* extent product factor */
223153323Srodrigc	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
224153323Srodrigc{
225153323Srodrigc	xfs_rtblock_t	besti;		/* best rtblock found so far */
226153323Srodrigc	xfs_rtblock_t	bestlen;	/* best length found so far */
227153323Srodrigc	xfs_rtblock_t	end;		/* last rtblock in chunk */
228153323Srodrigc	int		error;		/* error value */
229153323Srodrigc	xfs_rtblock_t	i;		/* current rtblock trying */
230153323Srodrigc	xfs_rtblock_t	next;		/* next rtblock to try */
231153323Srodrigc	int		stat;		/* status from internal calls */
232153323Srodrigc
233153323Srodrigc	/*
234153323Srodrigc	 * Loop over all the extents starting in this bitmap block,
235153323Srodrigc	 * looking for one that's long enough.
236153323Srodrigc	 */
237153323Srodrigc	for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0,
238153323Srodrigc		end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1;
239153323Srodrigc	     i <= end;
240153323Srodrigc	     i++) {
241153323Srodrigc		/*
242153323Srodrigc		 * See if there's a free extent of maxlen starting at i.
243153323Srodrigc		 * If it's not so then next will contain the first non-free.
244153323Srodrigc		 */
245153323Srodrigc		error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat);
246153323Srodrigc		if (error) {
247153323Srodrigc			return error;
248153323Srodrigc		}
249153323Srodrigc		if (stat) {
250153323Srodrigc			/*
251153323Srodrigc			 * i for maxlen is all free, allocate and return that.
252153323Srodrigc			 */
253153323Srodrigc			error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp,
254153323Srodrigc				rsb);
255153323Srodrigc			if (error) {
256153323Srodrigc				return error;
257153323Srodrigc			}
258153323Srodrigc			*len = maxlen;
259153323Srodrigc			*rtblock = i;
260153323Srodrigc			return 0;
261153323Srodrigc		}
262153323Srodrigc		/*
263153323Srodrigc		 * In the case where we have a variable-sized allocation
264153323Srodrigc		 * request, figure out how big this free piece is,
265153323Srodrigc		 * and if it's big enough for the minimum, and the best
266153323Srodrigc		 * so far, remember it.
267153323Srodrigc		 */
268153323Srodrigc		if (minlen < maxlen) {
269153323Srodrigc			xfs_rtblock_t	thislen;	/* this extent size */
270153323Srodrigc
271153323Srodrigc			thislen = next - i;
272153323Srodrigc			if (thislen >= minlen && thislen > bestlen) {
273153323Srodrigc				besti = i;
274153323Srodrigc				bestlen = thislen;
275153323Srodrigc			}
276153323Srodrigc		}
277153323Srodrigc		/*
278153323Srodrigc		 * If not done yet, find the start of the next free space.
279153323Srodrigc		 */
280153323Srodrigc		if (next < end) {
281153323Srodrigc			error = xfs_rtfind_forw(mp, tp, next, end, &i);
282153323Srodrigc			if (error) {
283153323Srodrigc				return error;
284153323Srodrigc			}
285153323Srodrigc		} else
286153323Srodrigc			break;
287153323Srodrigc	}
288153323Srodrigc	/*
289153323Srodrigc	 * Searched the whole thing & didn't find a maxlen free extent.
290153323Srodrigc	 */
291153323Srodrigc	if (minlen < maxlen && besti != -1) {
292153323Srodrigc		xfs_extlen_t	p;	/* amount to trim length by */
293153323Srodrigc
294153323Srodrigc		/*
295153323Srodrigc		 * If size should be a multiple of prod, make that so.
296153323Srodrigc		 */
297153323Srodrigc		if (prod > 1 && (p = do_mod(bestlen, prod)))
298153323Srodrigc			bestlen -= p;
299153323Srodrigc		/*
300153323Srodrigc		 * Allocate besti for bestlen & return that.
301153323Srodrigc		 */
302153323Srodrigc		error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb);
303153323Srodrigc		if (error) {
304153323Srodrigc			return error;
305153323Srodrigc		}
306153323Srodrigc		*len = bestlen;
307153323Srodrigc		*rtblock = besti;
308153323Srodrigc		return 0;
309153323Srodrigc	}
310153323Srodrigc	/*
311153323Srodrigc	 * Allocation failed.  Set *nextp to the next block to try.
312153323Srodrigc	 */
313153323Srodrigc	*nextp = next;
314153323Srodrigc	*rtblock = NULLRTBLOCK;
315153323Srodrigc	return 0;
316153323Srodrigc}
317153323Srodrigc
318153323Srodrigc/*
319153323Srodrigc * Allocate an extent of length minlen<=len<=maxlen, starting at block
320153323Srodrigc * bno.  If we don't get maxlen then use prod to trim the length, if given.
321153323Srodrigc * Returns error; returns starting block in *rtblock.
322153323Srodrigc * The lengths are all in rtextents.
323153323Srodrigc */
324153323SrodrigcSTATIC int				/* error */
325153323Srodrigcxfs_rtallocate_extent_exact(
326153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
327153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
328153323Srodrigc	xfs_rtblock_t	bno,		/* starting block number to allocate */
329153323Srodrigc	xfs_extlen_t	minlen,		/* minimum length to allocate */
330153323Srodrigc	xfs_extlen_t	maxlen,		/* maximum length to allocate */
331153323Srodrigc	xfs_extlen_t	*len,		/* out: actual length allocated */
332153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
333153323Srodrigc	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
334153323Srodrigc	xfs_extlen_t	prod,		/* extent product factor */
335153323Srodrigc	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
336153323Srodrigc{
337153323Srodrigc	int		error;		/* error value */
338153323Srodrigc	xfs_extlen_t	i;		/* extent length trimmed due to prod */
339153323Srodrigc	int		isfree;		/* extent is free */
340153323Srodrigc	xfs_rtblock_t	next;		/* next block to try (dummy) */
341153323Srodrigc
342153323Srodrigc	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
343153323Srodrigc	/*
344153323Srodrigc	 * Check if the range in question (for maxlen) is free.
345153323Srodrigc	 */
346153323Srodrigc	error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree);
347153323Srodrigc	if (error) {
348153323Srodrigc		return error;
349153323Srodrigc	}
350153323Srodrigc	if (isfree) {
351153323Srodrigc		/*
352153323Srodrigc		 * If it is, allocate it and return success.
353153323Srodrigc		 */
354153323Srodrigc		error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
355153323Srodrigc		if (error) {
356153323Srodrigc			return error;
357153323Srodrigc		}
358153323Srodrigc		*len = maxlen;
359153323Srodrigc		*rtblock = bno;
360153323Srodrigc		return 0;
361153323Srodrigc	}
362153323Srodrigc	/*
363153323Srodrigc	 * If not, allocate what there is, if it's at least minlen.
364153323Srodrigc	 */
365153323Srodrigc	maxlen = next - bno;
366153323Srodrigc	if (maxlen < minlen) {
367153323Srodrigc		/*
368153323Srodrigc		 * Failed, return failure status.
369153323Srodrigc		 */
370153323Srodrigc		*rtblock = NULLRTBLOCK;
371153323Srodrigc		return 0;
372153323Srodrigc	}
373153323Srodrigc	/*
374153323Srodrigc	 * Trim off tail of extent, if prod is specified.
375153323Srodrigc	 */
376153323Srodrigc	if (prod > 1 && (i = maxlen % prod)) {
377153323Srodrigc		maxlen -= i;
378153323Srodrigc		if (maxlen < minlen) {
379153323Srodrigc			/*
380153323Srodrigc			 * Now we can't do it, return failure status.
381153323Srodrigc			 */
382153323Srodrigc			*rtblock = NULLRTBLOCK;
383153323Srodrigc			return 0;
384153323Srodrigc		}
385153323Srodrigc	}
386153323Srodrigc	/*
387153323Srodrigc	 * Allocate what we can and return it.
388153323Srodrigc	 */
389153323Srodrigc	error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
390153323Srodrigc	if (error) {
391153323Srodrigc		return error;
392153323Srodrigc	}
393153323Srodrigc	*len = maxlen;
394153323Srodrigc	*rtblock = bno;
395153323Srodrigc	return 0;
396153323Srodrigc}
397153323Srodrigc
398153323Srodrigc/*
399153323Srodrigc * Allocate an extent of length minlen<=len<=maxlen, starting as near
400153323Srodrigc * to bno as possible.  If we don't get maxlen then use prod to trim
401153323Srodrigc * the length, if given.  The lengths are all in rtextents.
402153323Srodrigc */
403153323SrodrigcSTATIC int				/* error */
404153323Srodrigcxfs_rtallocate_extent_near(
405153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
406153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
407153323Srodrigc	xfs_rtblock_t	bno,		/* starting block number to allocate */
408153323Srodrigc	xfs_extlen_t	minlen,		/* minimum length to allocate */
409153323Srodrigc	xfs_extlen_t	maxlen,		/* maximum length to allocate */
410153323Srodrigc	xfs_extlen_t	*len,		/* out: actual length allocated */
411153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
412153323Srodrigc	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
413153323Srodrigc	xfs_extlen_t	prod,		/* extent product factor */
414153323Srodrigc	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
415153323Srodrigc{
416153323Srodrigc	int		any;		/* any useful extents from summary */
417153323Srodrigc	xfs_rtblock_t	bbno;		/* bitmap block number */
418153323Srodrigc	int		error;		/* error value */
419153323Srodrigc	int		i;		/* bitmap block offset (loop control) */
420153323Srodrigc	int		j;		/* secondary loop control */
421153323Srodrigc	int		log2len;	/* log2 of minlen */
422153323Srodrigc	xfs_rtblock_t	n;		/* next block to try */
423153323Srodrigc	xfs_rtblock_t	r;		/* result block */
424153323Srodrigc
425153323Srodrigc	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
426153323Srodrigc	/*
427153323Srodrigc	 * If the block number given is off the end, silently set it to
428153323Srodrigc	 * the last block.
429153323Srodrigc	 */
430153323Srodrigc	if (bno >= mp->m_sb.sb_rextents)
431153323Srodrigc		bno = mp->m_sb.sb_rextents - 1;
432153323Srodrigc	/*
433153323Srodrigc	 * Try the exact allocation first.
434153323Srodrigc	 */
435153323Srodrigc	error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len,
436153323Srodrigc		rbpp, rsb, prod, &r);
437153323Srodrigc	if (error) {
438153323Srodrigc		return error;
439153323Srodrigc	}
440153323Srodrigc	/*
441153323Srodrigc	 * If the exact allocation worked, return that.
442153323Srodrigc	 */
443153323Srodrigc	if (r != NULLRTBLOCK) {
444153323Srodrigc		*rtblock = r;
445153323Srodrigc		return 0;
446153323Srodrigc	}
447153323Srodrigc	bbno = XFS_BITTOBLOCK(mp, bno);
448153323Srodrigc	i = 0;
449153323Srodrigc	log2len = xfs_highbit32(minlen);
450153323Srodrigc	/*
451153323Srodrigc	 * Loop over all bitmap blocks (bbno + i is current block).
452153323Srodrigc	 */
453153323Srodrigc	for (;;) {
454153323Srodrigc		/*
455153323Srodrigc		 * Get summary information of extents of all useful levels
456153323Srodrigc		 * starting in this bitmap block.
457153323Srodrigc		 */
458153323Srodrigc		error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1,
459153323Srodrigc			bbno + i, rbpp, rsb, &any);
460153323Srodrigc		if (error) {
461153323Srodrigc			return error;
462153323Srodrigc		}
463153323Srodrigc		/*
464153323Srodrigc		 * If there are any useful extents starting here, try
465153323Srodrigc		 * allocating one.
466153323Srodrigc		 */
467153323Srodrigc		if (any) {
468153323Srodrigc			/*
469153323Srodrigc			 * On the positive side of the starting location.
470153323Srodrigc			 */
471153323Srodrigc			if (i >= 0) {
472153323Srodrigc				/*
473153323Srodrigc				 * Try to allocate an extent starting in
474153323Srodrigc				 * this block.
475153323Srodrigc				 */
476153323Srodrigc				error = xfs_rtallocate_extent_block(mp, tp,
477153323Srodrigc					bbno + i, minlen, maxlen, len, &n, rbpp,
478153323Srodrigc					rsb, prod, &r);
479153323Srodrigc				if (error) {
480153323Srodrigc					return error;
481153323Srodrigc				}
482153323Srodrigc				/*
483153323Srodrigc				 * If it worked, return it.
484153323Srodrigc				 */
485153323Srodrigc				if (r != NULLRTBLOCK) {
486153323Srodrigc					*rtblock = r;
487153323Srodrigc					return 0;
488153323Srodrigc				}
489153323Srodrigc			}
490153323Srodrigc			/*
491153323Srodrigc			 * On the negative side of the starting location.
492153323Srodrigc			 */
493153323Srodrigc			else {		/* i < 0 */
494153323Srodrigc				/*
495153323Srodrigc				 * Loop backwards through the bitmap blocks from
496153323Srodrigc				 * the starting point-1 up to where we are now.
497153323Srodrigc				 * There should be an extent which ends in this
498153323Srodrigc				 * bitmap block and is long enough.
499153323Srodrigc				 */
500153323Srodrigc				for (j = -1; j > i; j--) {
501153323Srodrigc					/*
502153323Srodrigc					 * Grab the summary information for
503153323Srodrigc					 * this bitmap block.
504153323Srodrigc					 */
505153323Srodrigc					error = xfs_rtany_summary(mp, tp,
506153323Srodrigc						log2len, mp->m_rsumlevels - 1,
507153323Srodrigc						bbno + j, rbpp, rsb, &any);
508153323Srodrigc					if (error) {
509153323Srodrigc						return error;
510153323Srodrigc					}
511153323Srodrigc					/*
512153323Srodrigc					 * If there's no extent given in the
513153323Srodrigc					 * summary that means the extent we
514153323Srodrigc					 * found must carry over from an
515153323Srodrigc					 * earlier block.  If there is an
516153323Srodrigc					 * extent given, we've already tried
517153323Srodrigc					 * that allocation, don't do it again.
518153323Srodrigc					 */
519153323Srodrigc					if (any)
520153323Srodrigc						continue;
521153323Srodrigc					error = xfs_rtallocate_extent_block(mp,
522153323Srodrigc						tp, bbno + j, minlen, maxlen,
523153323Srodrigc						len, &n, rbpp, rsb, prod, &r);
524153323Srodrigc					if (error) {
525153323Srodrigc						return error;
526153323Srodrigc					}
527153323Srodrigc					/*
528153323Srodrigc					 * If it works, return the extent.
529153323Srodrigc					 */
530153323Srodrigc					if (r != NULLRTBLOCK) {
531153323Srodrigc						*rtblock = r;
532153323Srodrigc						return 0;
533153323Srodrigc					}
534153323Srodrigc				}
535153323Srodrigc				/*
536153323Srodrigc				 * There weren't intervening bitmap blocks
537153323Srodrigc				 * with a long enough extent, or the
538153323Srodrigc				 * allocation didn't work for some reason
539153323Srodrigc				 * (i.e. it's a little * too short).
540153323Srodrigc				 * Try to allocate from the summary block
541153323Srodrigc				 * that we found.
542153323Srodrigc				 */
543153323Srodrigc				error = xfs_rtallocate_extent_block(mp, tp,
544153323Srodrigc					bbno + i, minlen, maxlen, len, &n, rbpp,
545153323Srodrigc					rsb, prod, &r);
546153323Srodrigc				if (error) {
547153323Srodrigc					return error;
548153323Srodrigc				}
549153323Srodrigc				/*
550153323Srodrigc				 * If it works, return the extent.
551153323Srodrigc				 */
552153323Srodrigc				if (r != NULLRTBLOCK) {
553153323Srodrigc					*rtblock = r;
554153323Srodrigc					return 0;
555153323Srodrigc				}
556153323Srodrigc			}
557153323Srodrigc		}
558153323Srodrigc		/*
559153323Srodrigc		 * Loop control.  If we were on the positive side, and there's
560153323Srodrigc		 * still more blocks on the negative side, go there.
561153323Srodrigc		 */
562153323Srodrigc		if (i > 0 && (int)bbno - i >= 0)
563153323Srodrigc			i = -i;
564153323Srodrigc		/*
565153323Srodrigc		 * If positive, and no more negative, but there are more
566153323Srodrigc		 * positive, go there.
567153323Srodrigc		 */
568153323Srodrigc		else if (i > 0 && (int)bbno + i < mp->m_sb.sb_rbmblocks - 1)
569153323Srodrigc			i++;
570153323Srodrigc		/*
571153323Srodrigc		 * If negative or 0 (just started), and there are positive
572153323Srodrigc		 * blocks to go, go there.  The 0 case moves to block 1.
573153323Srodrigc		 */
574153323Srodrigc		else if (i <= 0 && (int)bbno - i < mp->m_sb.sb_rbmblocks - 1)
575153323Srodrigc			i = 1 - i;
576153323Srodrigc		/*
577153323Srodrigc		 * If negative or 0 and there are more negative blocks,
578153323Srodrigc		 * go there.
579153323Srodrigc		 */
580153323Srodrigc		else if (i <= 0 && (int)bbno + i > 0)
581153323Srodrigc			i--;
582153323Srodrigc		/*
583153323Srodrigc		 * Must be done.  Return failure.
584153323Srodrigc		 */
585153323Srodrigc		else
586153323Srodrigc			break;
587153323Srodrigc	}
588153323Srodrigc	*rtblock = NULLRTBLOCK;
589153323Srodrigc	return 0;
590153323Srodrigc}
591153323Srodrigc
592153323Srodrigc/*
593153323Srodrigc * Allocate an extent of length minlen<=len<=maxlen, with no position
594153323Srodrigc * specified.  If we don't get maxlen then use prod to trim
595153323Srodrigc * the length, if given.  The lengths are all in rtextents.
596153323Srodrigc */
597153323SrodrigcSTATIC int				/* error */
598153323Srodrigcxfs_rtallocate_extent_size(
599153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
600153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
601153323Srodrigc	xfs_extlen_t	minlen,		/* minimum length to allocate */
602153323Srodrigc	xfs_extlen_t	maxlen,		/* maximum length to allocate */
603153323Srodrigc	xfs_extlen_t	*len,		/* out: actual length allocated */
604153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
605153323Srodrigc	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
606153323Srodrigc	xfs_extlen_t	prod,		/* extent product factor */
607153323Srodrigc	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
608153323Srodrigc{
609153323Srodrigc	int		error;		/* error value */
610153323Srodrigc	int		i;		/* bitmap block number */
611153323Srodrigc	int		l;		/* level number (loop control) */
612153323Srodrigc	xfs_rtblock_t	n;		/* next block to be tried */
613153323Srodrigc	xfs_rtblock_t	r;		/* result block number */
614153323Srodrigc	xfs_suminfo_t	sum;		/* summary information for extents */
615153323Srodrigc
616153323Srodrigc	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
617153323Srodrigc	/*
618153323Srodrigc	 * Loop over all the levels starting with maxlen.
619153323Srodrigc	 * At each level, look at all the bitmap blocks, to see if there
620153323Srodrigc	 * are extents starting there that are long enough (>= maxlen).
621153323Srodrigc	 * Note, only on the initial level can the allocation fail if
622153323Srodrigc	 * the summary says there's an extent.
623153323Srodrigc	 */
624153323Srodrigc	for (l = xfs_highbit32(maxlen); l < mp->m_rsumlevels; l++) {
625153323Srodrigc		/*
626153323Srodrigc		 * Loop over all the bitmap blocks.
627153323Srodrigc		 */
628153323Srodrigc		for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
629153323Srodrigc			/*
630153323Srodrigc			 * Get the summary for this level/block.
631153323Srodrigc			 */
632153323Srodrigc			error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
633153323Srodrigc				&sum);
634153323Srodrigc			if (error) {
635153323Srodrigc				return error;
636153323Srodrigc			}
637153323Srodrigc			/*
638153323Srodrigc			 * Nothing there, on to the next block.
639153323Srodrigc			 */
640153323Srodrigc			if (!sum)
641153323Srodrigc				continue;
642153323Srodrigc			/*
643153323Srodrigc			 * Try allocating the extent.
644153323Srodrigc			 */
645153323Srodrigc			error = xfs_rtallocate_extent_block(mp, tp, i, maxlen,
646153323Srodrigc				maxlen, len, &n, rbpp, rsb, prod, &r);
647153323Srodrigc			if (error) {
648153323Srodrigc				return error;
649153323Srodrigc			}
650153323Srodrigc			/*
651153323Srodrigc			 * If it worked, return that.
652153323Srodrigc			 */
653153323Srodrigc			if (r != NULLRTBLOCK) {
654153323Srodrigc				*rtblock = r;
655153323Srodrigc				return 0;
656153323Srodrigc			}
657153323Srodrigc			/*
658153323Srodrigc			 * If the "next block to try" returned from the
659153323Srodrigc			 * allocator is beyond the next bitmap block,
660153323Srodrigc			 * skip to that bitmap block.
661153323Srodrigc			 */
662153323Srodrigc			if (XFS_BITTOBLOCK(mp, n) > i + 1)
663153323Srodrigc				i = XFS_BITTOBLOCK(mp, n) - 1;
664153323Srodrigc		}
665153323Srodrigc	}
666153323Srodrigc	/*
667153323Srodrigc	 * Didn't find any maxlen blocks.  Try smaller ones, unless
668153323Srodrigc	 * we're asking for a fixed size extent.
669153323Srodrigc	 */
670153323Srodrigc	if (minlen > --maxlen) {
671153323Srodrigc		*rtblock = NULLRTBLOCK;
672153323Srodrigc		return 0;
673153323Srodrigc	}
674153323Srodrigc	/*
675153323Srodrigc	 * Loop over sizes, from maxlen down to minlen.
676153323Srodrigc	 * This time, when we do the allocations, allow smaller ones
677153323Srodrigc	 * to succeed.
678153323Srodrigc	 */
679153323Srodrigc	for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) {
680153323Srodrigc		/*
681153323Srodrigc		 * Loop over all the bitmap blocks, try an allocation
682153323Srodrigc		 * starting in that block.
683153323Srodrigc		 */
684153323Srodrigc		for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
685153323Srodrigc			/*
686153323Srodrigc			 * Get the summary information for this level/block.
687153323Srodrigc			 */
688153323Srodrigc			error =	xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
689153323Srodrigc						  &sum);
690153323Srodrigc			if (error) {
691153323Srodrigc				return error;
692153323Srodrigc			}
693153323Srodrigc			/*
694153323Srodrigc			 * If nothing there, go on to next.
695153323Srodrigc			 */
696153323Srodrigc			if (!sum)
697153323Srodrigc				continue;
698153323Srodrigc			/*
699153323Srodrigc			 * Try the allocation.  Make sure the specified
700153323Srodrigc			 * minlen/maxlen are in the possible range for
701153323Srodrigc			 * this summary level.
702153323Srodrigc			 */
703153323Srodrigc			error = xfs_rtallocate_extent_block(mp, tp, i,
704153323Srodrigc					XFS_RTMAX(minlen, 1 << l),
705153323Srodrigc					XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
706153323Srodrigc					len, &n, rbpp, rsb, prod, &r);
707153323Srodrigc			if (error) {
708153323Srodrigc				return error;
709153323Srodrigc			}
710153323Srodrigc			/*
711153323Srodrigc			 * If it worked, return that extent.
712153323Srodrigc			 */
713153323Srodrigc			if (r != NULLRTBLOCK) {
714153323Srodrigc				*rtblock = r;
715153323Srodrigc				return 0;
716153323Srodrigc			}
717153323Srodrigc			/*
718153323Srodrigc			 * If the "next block to try" returned from the
719153323Srodrigc			 * allocator is beyond the next bitmap block,
720153323Srodrigc			 * skip to that bitmap block.
721153323Srodrigc			 */
722153323Srodrigc			if (XFS_BITTOBLOCK(mp, n) > i + 1)
723153323Srodrigc				i = XFS_BITTOBLOCK(mp, n) - 1;
724153323Srodrigc		}
725153323Srodrigc	}
726153323Srodrigc	/*
727153323Srodrigc	 * Got nothing, return failure.
728153323Srodrigc	 */
729153323Srodrigc	*rtblock = NULLRTBLOCK;
730153323Srodrigc	return 0;
731153323Srodrigc}
732153323Srodrigc
733153323Srodrigc/*
734153323Srodrigc * Mark an extent specified by start and len allocated.
735153323Srodrigc * Updates all the summary information as well as the bitmap.
736153323Srodrigc */
737153323SrodrigcSTATIC int				/* error */
738153323Srodrigcxfs_rtallocate_range(
739153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
740153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
741153323Srodrigc	xfs_rtblock_t	start,		/* start block to allocate */
742153323Srodrigc	xfs_extlen_t	len,		/* length to allocate */
743153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
744153323Srodrigc	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
745153323Srodrigc{
746153323Srodrigc	xfs_rtblock_t	end;		/* end of the allocated extent */
747153323Srodrigc	int		error;		/* error value */
748153323Srodrigc	xfs_rtblock_t	postblock;	/* first block allocated > end */
749153323Srodrigc	xfs_rtblock_t	preblock;	/* first block allocated < start */
750153323Srodrigc
751153323Srodrigc	end = start + len - 1;
752153323Srodrigc	/*
753153323Srodrigc	 * Assume we're allocating out of the middle of a free extent.
754153323Srodrigc	 * We need to find the beginning and end of the extent so we can
755153323Srodrigc	 * properly update the summary.
756153323Srodrigc	 */
757153323Srodrigc	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
758153323Srodrigc	if (error) {
759153323Srodrigc		return error;
760153323Srodrigc	}
761153323Srodrigc	/*
762153323Srodrigc	 * Find the next allocated block (end of free extent).
763153323Srodrigc	 */
764153323Srodrigc	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
765153323Srodrigc		&postblock);
766153323Srodrigc	if (error) {
767153323Srodrigc		return error;
768153323Srodrigc	}
769153323Srodrigc	/*
770153323Srodrigc	 * Decrement the summary information corresponding to the entire
771153323Srodrigc	 * (old) free extent.
772153323Srodrigc	 */
773153323Srodrigc	error = xfs_rtmodify_summary(mp, tp,
774153323Srodrigc		XFS_RTBLOCKLOG(postblock + 1 - preblock),
775153323Srodrigc		XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
776153323Srodrigc	if (error) {
777153323Srodrigc		return error;
778153323Srodrigc	}
779153323Srodrigc	/*
780153323Srodrigc	 * If there are blocks not being allocated at the front of the
781153323Srodrigc	 * old extent, add summary data for them to be free.
782153323Srodrigc	 */
783153323Srodrigc	if (preblock < start) {
784153323Srodrigc		error = xfs_rtmodify_summary(mp, tp,
785153323Srodrigc			XFS_RTBLOCKLOG(start - preblock),
786153323Srodrigc			XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
787153323Srodrigc		if (error) {
788153323Srodrigc			return error;
789153323Srodrigc		}
790153323Srodrigc	}
791153323Srodrigc	/*
792153323Srodrigc	 * If there are blocks not being allocated at the end of the
793153323Srodrigc	 * old extent, add summary data for them to be free.
794153323Srodrigc	 */
795153323Srodrigc	if (postblock > end) {
796153323Srodrigc		error = xfs_rtmodify_summary(mp, tp,
797153323Srodrigc			XFS_RTBLOCKLOG(postblock - end),
798153323Srodrigc			XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
799153323Srodrigc		if (error) {
800153323Srodrigc			return error;
801153323Srodrigc		}
802153323Srodrigc	}
803153323Srodrigc	/*
804153323Srodrigc	 * Modify the bitmap to mark this extent allocated.
805153323Srodrigc	 */
806153323Srodrigc	error = xfs_rtmodify_range(mp, tp, start, len, 0);
807153323Srodrigc	return error;
808153323Srodrigc}
809153323Srodrigc
810153323Srodrigc/*
811153323Srodrigc * Return whether there are any free extents in the size range given
812153323Srodrigc * by low and high, for the bitmap block bbno.
813153323Srodrigc */
814153323SrodrigcSTATIC int				/* error */
815153323Srodrigcxfs_rtany_summary(
816153323Srodrigc	xfs_mount_t	*mp,		/* file system mount structure */
817153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
818153323Srodrigc	int		low,		/* low log2 extent size */
819153323Srodrigc	int		high,		/* high log2 extent size */
820153323Srodrigc	xfs_rtblock_t	bbno,		/* bitmap block number */
821153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
822153323Srodrigc	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
823153323Srodrigc	int		*stat)		/* out: any good extents here? */
824153323Srodrigc{
825153323Srodrigc	int		error;		/* error value */
826153323Srodrigc	int		log;		/* loop counter, log2 of ext. size */
827153323Srodrigc	xfs_suminfo_t	sum;		/* summary data */
828153323Srodrigc
829153323Srodrigc	/*
830153323Srodrigc	 * Loop over logs of extent sizes.  Order is irrelevant.
831153323Srodrigc	 */
832153323Srodrigc	for (log = low; log <= high; log++) {
833153323Srodrigc		/*
834153323Srodrigc		 * Get one summary datum.
835153323Srodrigc		 */
836153323Srodrigc		error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
837153323Srodrigc		if (error) {
838153323Srodrigc			return error;
839153323Srodrigc		}
840153323Srodrigc		/*
841153323Srodrigc		 * If there are any, return success.
842153323Srodrigc		 */
843153323Srodrigc		if (sum) {
844153323Srodrigc			*stat = 1;
845153323Srodrigc			return 0;
846153323Srodrigc		}
847153323Srodrigc	}
848153323Srodrigc	/*
849153323Srodrigc	 * Found nothing, return failure.
850153323Srodrigc	 */
851153323Srodrigc	*stat = 0;
852153323Srodrigc	return 0;
853153323Srodrigc}
854153323Srodrigc
855153323Srodrigc/*
856153323Srodrigc * Get a buffer for the bitmap or summary file block specified.
857153323Srodrigc * The buffer is returned read and locked.
858153323Srodrigc */
859153323SrodrigcSTATIC int				/* error */
860153323Srodrigcxfs_rtbuf_get(
861153323Srodrigc	xfs_mount_t	*mp,		/* file system mount structure */
862153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
863153323Srodrigc	xfs_rtblock_t	block,		/* block number in bitmap or summary */
864153323Srodrigc	int		issum,		/* is summary not bitmap */
865153323Srodrigc	xfs_buf_t	**bpp)		/* output: buffer for the block */
866153323Srodrigc{
867153323Srodrigc	xfs_buf_t	*bp;		/* block buffer, result */
868153323Srodrigc	xfs_daddr_t	d;		/* disk addr of block */
869153323Srodrigc	int		error;		/* error value */
870153323Srodrigc	xfs_fsblock_t	fsb;		/* fs block number for block */
871153323Srodrigc	xfs_inode_t	*ip;		/* bitmap or summary inode */
872153323Srodrigc
873153323Srodrigc	ip = issum ? mp->m_rsumip : mp->m_rbmip;
874153323Srodrigc	/*
875153323Srodrigc	 * Map from the file offset (block) and inode number to the
876153323Srodrigc	 * file system block.
877153323Srodrigc	 */
878153323Srodrigc	error = xfs_bmapi_single(tp, ip, XFS_DATA_FORK, &fsb, block);
879153323Srodrigc	if (error) {
880153323Srodrigc		return error;
881153323Srodrigc	}
882153323Srodrigc	ASSERT(fsb != NULLFSBLOCK);
883153323Srodrigc	/*
884153323Srodrigc	 * Convert to disk address for buffer cache.
885153323Srodrigc	 */
886153323Srodrigc	d = XFS_FSB_TO_DADDR(mp, fsb);
887153323Srodrigc	/*
888153323Srodrigc	 * Read the buffer.
889153323Srodrigc	 */
890153323Srodrigc	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
891153323Srodrigc				   mp->m_bsize, 0, &bp);
892153323Srodrigc	if (error) {
893153323Srodrigc		return error;
894153323Srodrigc	}
895153323Srodrigc	ASSERT(bp && !XFS_BUF_GETERROR(bp));
896153323Srodrigc	*bpp = bp;
897153323Srodrigc	return 0;
898153323Srodrigc}
899153323Srodrigc
900153323Srodrigc#ifdef DEBUG
901153323Srodrigc/*
902153323Srodrigc * Check that the given extent (block range) is allocated already.
903153323Srodrigc */
904153323SrodrigcSTATIC int				/* error */
905153323Srodrigcxfs_rtcheck_alloc_range(
906153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
907153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
908153323Srodrigc	xfs_rtblock_t	bno,		/* starting block number of extent */
909153323Srodrigc	xfs_extlen_t	len,		/* length of extent */
910153323Srodrigc	int		*stat)		/* out: 1 for allocated, 0 for not */
911153323Srodrigc{
912153323Srodrigc	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
913153323Srodrigc
914153323Srodrigc	return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat);
915153323Srodrigc}
916153323Srodrigc#endif
917153323Srodrigc
918153323Srodrigc#ifdef DEBUG
919153323Srodrigc/*
920153323Srodrigc * Check whether the given block in the bitmap has the given value.
921153323Srodrigc */
922153323SrodrigcSTATIC int				/* 1 for matches, 0 for not */
923153323Srodrigcxfs_rtcheck_bit(
924153323Srodrigc	xfs_mount_t	*mp,		/* file system mount structure */
925153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
926153323Srodrigc	xfs_rtblock_t	start,		/* bit (block) to check */
927153323Srodrigc	int		val)		/* 1 for free, 0 for allocated */
928153323Srodrigc{
929153323Srodrigc	int		bit;		/* bit number in the word */
930153323Srodrigc	xfs_rtblock_t	block;		/* bitmap block number */
931153323Srodrigc	xfs_buf_t	*bp;		/* buf for the block */
932153323Srodrigc	xfs_rtword_t	*bufp;		/* pointer into the buffer */
933153323Srodrigc	/* REFERENCED */
934153323Srodrigc	int		error;		/* error value */
935153323Srodrigc	xfs_rtword_t	wdiff;		/* difference between bit & expected */
936153323Srodrigc	int		word;		/* word number in the buffer */
937153323Srodrigc	xfs_rtword_t	wval;		/* word value from buffer */
938153323Srodrigc
939153323Srodrigc	block = XFS_BITTOBLOCK(mp, start);
940153323Srodrigc	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
941153323Srodrigc	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
942153323Srodrigc	word = XFS_BITTOWORD(mp, start);
943153323Srodrigc	bit = (int)(start & (XFS_NBWORD - 1));
944153323Srodrigc	wval = bufp[word];
945153323Srodrigc	xfs_trans_brelse(tp, bp);
946153323Srodrigc	wdiff = (wval ^ -val) & ((xfs_rtword_t)1 << bit);
947153323Srodrigc	return !wdiff;
948153323Srodrigc}
949153323Srodrigc#endif	/* DEBUG */
950153323Srodrigc
951153323Srodrigc#if 0
952153323Srodrigc/*
953153323Srodrigc * Check that the given extent (block range) is free already.
954153323Srodrigc */
955153323SrodrigcSTATIC int				/* error */
956153323Srodrigcxfs_rtcheck_free_range(
957153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
958153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
959153323Srodrigc	xfs_rtblock_t	bno,		/* starting block number of extent */
960153323Srodrigc	xfs_extlen_t	len,		/* length of extent */
961153323Srodrigc	int		*stat)		/* out: 1 for free, 0 for not */
962153323Srodrigc{
963153323Srodrigc	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
964153323Srodrigc
965153323Srodrigc	return xfs_rtcheck_range(mp, tp, bno, len, 1, &new, stat);
966153323Srodrigc}
967153323Srodrigc#endif
968153323Srodrigc
969153323Srodrigc/*
970153323Srodrigc * Check that the given range is either all allocated (val = 0) or
971153323Srodrigc * all free (val = 1).
972153323Srodrigc */
973153323SrodrigcSTATIC int				/* error */
974153323Srodrigcxfs_rtcheck_range(
975153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
976153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
977153323Srodrigc	xfs_rtblock_t	start,		/* starting block number of extent */
978153323Srodrigc	xfs_extlen_t	len,		/* length of extent */
979153323Srodrigc	int		val,		/* 1 for free, 0 for allocated */
980153323Srodrigc	xfs_rtblock_t	*new,		/* out: first block not matching */
981153323Srodrigc	int		*stat)		/* out: 1 for matches, 0 for not */
982153323Srodrigc{
983153323Srodrigc	xfs_rtword_t	*b;		/* current word in buffer */
984153323Srodrigc	int		bit;		/* bit number in the word */
985153323Srodrigc	xfs_rtblock_t	block;		/* bitmap block number */
986153323Srodrigc	xfs_buf_t	*bp;		/* buf for the block */
987153323Srodrigc	xfs_rtword_t	*bufp;		/* starting word in buffer */
988153323Srodrigc	int		error;		/* error value */
989153323Srodrigc	xfs_rtblock_t	i;		/* current bit number rel. to start */
990153323Srodrigc	xfs_rtblock_t	lastbit;	/* last useful bit in word */
991153323Srodrigc	xfs_rtword_t	mask;		/* mask of relevant bits for value */
992153323Srodrigc	xfs_rtword_t	wdiff;		/* difference from wanted value */
993153323Srodrigc	int		word;		/* word number in the buffer */
994153323Srodrigc
995153323Srodrigc	/*
996153323Srodrigc	 * Compute starting bitmap block number
997153323Srodrigc	 */
998153323Srodrigc	block = XFS_BITTOBLOCK(mp, start);
999153323Srodrigc	/*
1000153323Srodrigc	 * Read the bitmap block.
1001153323Srodrigc	 */
1002153323Srodrigc	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1003153323Srodrigc	if (error) {
1004153323Srodrigc		return error;
1005153323Srodrigc	}
1006153323Srodrigc	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1007153323Srodrigc	/*
1008153323Srodrigc	 * Compute the starting word's address, and starting bit.
1009153323Srodrigc	 */
1010153323Srodrigc	word = XFS_BITTOWORD(mp, start);
1011153323Srodrigc	b = &bufp[word];
1012153323Srodrigc	bit = (int)(start & (XFS_NBWORD - 1));
1013153323Srodrigc	/*
1014153323Srodrigc	 * 0 (allocated) => all zero's; 1 (free) => all one's.
1015153323Srodrigc	 */
1016153323Srodrigc	val = -val;
1017153323Srodrigc	/*
1018153323Srodrigc	 * If not starting on a word boundary, deal with the first
1019153323Srodrigc	 * (partial) word.
1020153323Srodrigc	 */
1021153323Srodrigc	if (bit) {
1022153323Srodrigc		/*
1023153323Srodrigc		 * Compute first bit not examined.
1024153323Srodrigc		 */
1025153323Srodrigc		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1026153323Srodrigc		/*
1027153323Srodrigc		 * Mask of relevant bits.
1028153323Srodrigc		 */
1029153323Srodrigc		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1030153323Srodrigc		/*
1031153323Srodrigc		 * Compute difference between actual and desired value.
1032153323Srodrigc		 */
1033153323Srodrigc		if ((wdiff = (*b ^ val) & mask)) {
1034153323Srodrigc			/*
1035153323Srodrigc			 * Different, compute first wrong bit and return.
1036153323Srodrigc			 */
1037153323Srodrigc			xfs_trans_brelse(tp, bp);
1038153323Srodrigc			i = XFS_RTLOBIT(wdiff) - bit;
1039153323Srodrigc			*new = start + i;
1040153323Srodrigc			*stat = 0;
1041153323Srodrigc			return 0;
1042153323Srodrigc		}
1043153323Srodrigc		i = lastbit - bit;
1044153323Srodrigc		/*
1045153323Srodrigc		 * Go on to next block if that's where the next word is
1046153323Srodrigc		 * and we need the next word.
1047153323Srodrigc		 */
1048153323Srodrigc		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1049153323Srodrigc			/*
1050153323Srodrigc			 * If done with this block, get the next one.
1051153323Srodrigc			 */
1052153323Srodrigc			xfs_trans_brelse(tp, bp);
1053153323Srodrigc			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1054153323Srodrigc			if (error) {
1055153323Srodrigc				return error;
1056153323Srodrigc			}
1057153323Srodrigc			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1058153323Srodrigc			word = 0;
1059153323Srodrigc		} else {
1060153323Srodrigc			/*
1061153323Srodrigc			 * Go on to the next word in the buffer.
1062153323Srodrigc			 */
1063153323Srodrigc			b++;
1064153323Srodrigc		}
1065153323Srodrigc	} else {
1066153323Srodrigc		/*
1067153323Srodrigc		 * Starting on a word boundary, no partial word.
1068153323Srodrigc		 */
1069153323Srodrigc		i = 0;
1070153323Srodrigc	}
1071153323Srodrigc	/*
1072153323Srodrigc	 * Loop over whole words in buffers.  When we use up one buffer
1073153323Srodrigc	 * we move on to the next one.
1074153323Srodrigc	 */
1075153323Srodrigc	while (len - i >= XFS_NBWORD) {
1076153323Srodrigc		/*
1077153323Srodrigc		 * Compute difference between actual and desired value.
1078153323Srodrigc		 */
1079153323Srodrigc		if ((wdiff = *b ^ val)) {
1080153323Srodrigc			/*
1081153323Srodrigc			 * Different, compute first wrong bit and return.
1082153323Srodrigc			 */
1083153323Srodrigc			xfs_trans_brelse(tp, bp);
1084153323Srodrigc			i += XFS_RTLOBIT(wdiff);
1085153323Srodrigc			*new = start + i;
1086153323Srodrigc			*stat = 0;
1087153323Srodrigc			return 0;
1088153323Srodrigc		}
1089153323Srodrigc		i += XFS_NBWORD;
1090153323Srodrigc		/*
1091153323Srodrigc		 * Go on to next block if that's where the next word is
1092153323Srodrigc		 * and we need the next word.
1093153323Srodrigc		 */
1094153323Srodrigc		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1095153323Srodrigc			/*
1096153323Srodrigc			 * If done with this block, get the next one.
1097153323Srodrigc			 */
1098153323Srodrigc			xfs_trans_brelse(tp, bp);
1099153323Srodrigc			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1100153323Srodrigc			if (error) {
1101153323Srodrigc				return error;
1102153323Srodrigc			}
1103153323Srodrigc			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1104153323Srodrigc			word = 0;
1105153323Srodrigc		} else {
1106153323Srodrigc			/*
1107153323Srodrigc			 * Go on to the next word in the buffer.
1108153323Srodrigc			 */
1109153323Srodrigc			b++;
1110153323Srodrigc		}
1111153323Srodrigc	}
1112153323Srodrigc	/*
1113153323Srodrigc	 * If not ending on a word boundary, deal with the last
1114153323Srodrigc	 * (partial) word.
1115153323Srodrigc	 */
1116153323Srodrigc	if ((lastbit = len - i)) {
1117153323Srodrigc		/*
1118153323Srodrigc		 * Mask of relevant bits.
1119153323Srodrigc		 */
1120153323Srodrigc		mask = ((xfs_rtword_t)1 << lastbit) - 1;
1121153323Srodrigc		/*
1122153323Srodrigc		 * Compute difference between actual and desired value.
1123153323Srodrigc		 */
1124153323Srodrigc		if ((wdiff = (*b ^ val) & mask)) {
1125153323Srodrigc			/*
1126153323Srodrigc			 * Different, compute first wrong bit and return.
1127153323Srodrigc			 */
1128153323Srodrigc			xfs_trans_brelse(tp, bp);
1129153323Srodrigc			i += XFS_RTLOBIT(wdiff);
1130153323Srodrigc			*new = start + i;
1131153323Srodrigc			*stat = 0;
1132153323Srodrigc			return 0;
1133153323Srodrigc		} else
1134153323Srodrigc			i = len;
1135153323Srodrigc	}
1136153323Srodrigc	/*
1137153323Srodrigc	 * Successful, return.
1138153323Srodrigc	 */
1139153323Srodrigc	xfs_trans_brelse(tp, bp);
1140153323Srodrigc	*new = start + i;
1141153323Srodrigc	*stat = 1;
1142153323Srodrigc	return 0;
1143153323Srodrigc}
1144153323Srodrigc
1145153323Srodrigc/*
1146153323Srodrigc * Copy and transform the summary file, given the old and new
1147153323Srodrigc * parameters in the mount structures.
1148153323Srodrigc */
1149153323SrodrigcSTATIC int				/* error */
1150153323Srodrigcxfs_rtcopy_summary(
1151153323Srodrigc	xfs_mount_t	*omp,		/* old file system mount point */
1152153323Srodrigc	xfs_mount_t	*nmp,		/* new file system mount point */
1153153323Srodrigc	xfs_trans_t	*tp)		/* transaction pointer */
1154153323Srodrigc{
1155153323Srodrigc	xfs_rtblock_t	bbno;		/* bitmap block number */
1156153323Srodrigc	xfs_buf_t	*bp;		/* summary buffer */
1157153323Srodrigc	int		error;		/* error return value */
1158153323Srodrigc	int		log;		/* summary level number (log length) */
1159153323Srodrigc	xfs_suminfo_t	sum;		/* summary data */
1160153323Srodrigc	xfs_fsblock_t	sumbno;		/* summary block number */
1161153323Srodrigc
1162153323Srodrigc	bp = NULL;
1163153323Srodrigc	for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
1164153323Srodrigc		for (bbno = omp->m_sb.sb_rbmblocks - 1;
1165153323Srodrigc		     (xfs_srtblock_t)bbno >= 0;
1166153323Srodrigc		     bbno--) {
1167153323Srodrigc			error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
1168153323Srodrigc				&sumbno, &sum);
1169153323Srodrigc			if (error)
1170153323Srodrigc				return error;
1171153323Srodrigc			if (sum == 0)
1172153323Srodrigc				continue;
1173153323Srodrigc			error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
1174153323Srodrigc				&bp, &sumbno);
1175153323Srodrigc			if (error)
1176153323Srodrigc				return error;
1177153323Srodrigc			error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
1178153323Srodrigc				&bp, &sumbno);
1179153323Srodrigc			if (error)
1180153323Srodrigc				return error;
1181153323Srodrigc			ASSERT(sum > 0);
1182153323Srodrigc		}
1183153323Srodrigc	}
1184153323Srodrigc	return 0;
1185153323Srodrigc}
1186153323Srodrigc
1187153323Srodrigc/*
1188153323Srodrigc * Searching backward from start to limit, find the first block whose
1189153323Srodrigc * allocated/free state is different from start's.
1190153323Srodrigc */
1191153323SrodrigcSTATIC int				/* error */
1192153323Srodrigcxfs_rtfind_back(
1193153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
1194153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
1195153323Srodrigc	xfs_rtblock_t	start,		/* starting block to look at */
1196153323Srodrigc	xfs_rtblock_t	limit,		/* last block to look at */
1197153323Srodrigc	xfs_rtblock_t	*rtblock)	/* out: start block found */
1198153323Srodrigc{
1199153323Srodrigc	xfs_rtword_t	*b;		/* current word in buffer */
1200153323Srodrigc	int		bit;		/* bit number in the word */
1201153323Srodrigc	xfs_rtblock_t	block;		/* bitmap block number */
1202153323Srodrigc	xfs_buf_t	*bp;		/* buf for the block */
1203153323Srodrigc	xfs_rtword_t	*bufp;		/* starting word in buffer */
1204153323Srodrigc	int		error;		/* error value */
1205153323Srodrigc	xfs_rtblock_t	firstbit;	/* first useful bit in the word */
1206153323Srodrigc	xfs_rtblock_t	i;		/* current bit number rel. to start */
1207153323Srodrigc	xfs_rtblock_t	len;		/* length of inspected area */
1208153323Srodrigc	xfs_rtword_t	mask;		/* mask of relevant bits for value */
1209153323Srodrigc	xfs_rtword_t	want;		/* mask for "good" values */
1210153323Srodrigc	xfs_rtword_t	wdiff;		/* difference from wanted value */
1211153323Srodrigc	int		word;		/* word number in the buffer */
1212153323Srodrigc
1213153323Srodrigc	/*
1214153323Srodrigc	 * Compute and read in starting bitmap block for starting block.
1215153323Srodrigc	 */
1216153323Srodrigc	block = XFS_BITTOBLOCK(mp, start);
1217153323Srodrigc	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1218153323Srodrigc	if (error) {
1219153323Srodrigc		return error;
1220153323Srodrigc	}
1221153323Srodrigc	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1222153323Srodrigc	/*
1223153323Srodrigc	 * Get the first word's index & point to it.
1224153323Srodrigc	 */
1225153323Srodrigc	word = XFS_BITTOWORD(mp, start);
1226153323Srodrigc	b = &bufp[word];
1227153323Srodrigc	bit = (int)(start & (XFS_NBWORD - 1));
1228153323Srodrigc	len = start - limit + 1;
1229153323Srodrigc	/*
1230153323Srodrigc	 * Compute match value, based on the bit at start: if 1 (free)
1231153323Srodrigc	 * then all-ones, else all-zeroes.
1232153323Srodrigc	 */
1233153323Srodrigc	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1234153323Srodrigc	/*
1235153323Srodrigc	 * If the starting position is not word-aligned, deal with the
1236153323Srodrigc	 * partial word.
1237153323Srodrigc	 */
1238153323Srodrigc	if (bit < XFS_NBWORD - 1) {
1239153323Srodrigc		/*
1240153323Srodrigc		 * Calculate first (leftmost) bit number to look at,
1241153323Srodrigc		 * and mask for all the relevant bits in this word.
1242153323Srodrigc		 */
1243153323Srodrigc		firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
1244153323Srodrigc		mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
1245153323Srodrigc			firstbit;
1246153323Srodrigc		/*
1247153323Srodrigc		 * Calculate the difference between the value there
1248153323Srodrigc		 * and what we're looking for.
1249153323Srodrigc		 */
1250153323Srodrigc		if ((wdiff = (*b ^ want) & mask)) {
1251153323Srodrigc			/*
1252153323Srodrigc			 * Different.  Mark where we are and return.
1253153323Srodrigc			 */
1254153323Srodrigc			xfs_trans_brelse(tp, bp);
1255153323Srodrigc			i = bit - XFS_RTHIBIT(wdiff);
1256153323Srodrigc			*rtblock = start - i + 1;
1257153323Srodrigc			return 0;
1258153323Srodrigc		}
1259153323Srodrigc		i = bit - firstbit + 1;
1260153323Srodrigc		/*
1261153323Srodrigc		 * Go on to previous block if that's where the previous word is
1262153323Srodrigc		 * and we need the previous word.
1263153323Srodrigc		 */
1264153323Srodrigc		if (--word == -1 && i < len) {
1265153323Srodrigc			/*
1266153323Srodrigc			 * If done with this block, get the previous one.
1267153323Srodrigc			 */
1268153323Srodrigc			xfs_trans_brelse(tp, bp);
1269153323Srodrigc			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1270153323Srodrigc			if (error) {
1271153323Srodrigc				return error;
1272153323Srodrigc			}
1273153323Srodrigc			bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1274153323Srodrigc			word = XFS_BLOCKWMASK(mp);
1275153323Srodrigc			b = &bufp[word];
1276153323Srodrigc		} else {
1277153323Srodrigc			/*
1278153323Srodrigc			 * Go on to the previous word in the buffer.
1279153323Srodrigc			 */
1280153323Srodrigc			b--;
1281153323Srodrigc		}
1282153323Srodrigc	} else {
1283153323Srodrigc		/*
1284153323Srodrigc		 * Starting on a word boundary, no partial word.
1285153323Srodrigc		 */
1286153323Srodrigc		i = 0;
1287153323Srodrigc	}
1288153323Srodrigc	/*
1289153323Srodrigc	 * Loop over whole words in buffers.  When we use up one buffer
1290153323Srodrigc	 * we move on to the previous one.
1291153323Srodrigc	 */
1292153323Srodrigc	while (len - i >= XFS_NBWORD) {
1293153323Srodrigc		/*
1294153323Srodrigc		 * Compute difference between actual and desired value.
1295153323Srodrigc		 */
1296153323Srodrigc		if ((wdiff = *b ^ want)) {
1297153323Srodrigc			/*
1298153323Srodrigc			 * Different, mark where we are and return.
1299153323Srodrigc			 */
1300153323Srodrigc			xfs_trans_brelse(tp, bp);
1301153323Srodrigc			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1302153323Srodrigc			*rtblock = start - i + 1;
1303153323Srodrigc			return 0;
1304153323Srodrigc		}
1305153323Srodrigc		i += XFS_NBWORD;
1306153323Srodrigc		/*
1307153323Srodrigc		 * Go on to previous block if that's where the previous word is
1308153323Srodrigc		 * and we need the previous word.
1309153323Srodrigc		 */
1310153323Srodrigc		if (--word == -1 && i < len) {
1311153323Srodrigc			/*
1312153323Srodrigc			 * If done with this block, get the previous one.
1313153323Srodrigc			 */
1314153323Srodrigc			xfs_trans_brelse(tp, bp);
1315153323Srodrigc			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1316153323Srodrigc			if (error) {
1317153323Srodrigc				return error;
1318153323Srodrigc			}
1319153323Srodrigc			bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1320153323Srodrigc			word = XFS_BLOCKWMASK(mp);
1321153323Srodrigc			b = &bufp[word];
1322153323Srodrigc		} else {
1323153323Srodrigc			/*
1324153323Srodrigc			 * Go on to the previous word in the buffer.
1325153323Srodrigc			 */
1326153323Srodrigc			b--;
1327153323Srodrigc		}
1328153323Srodrigc	}
1329153323Srodrigc	/*
1330153323Srodrigc	 * If not ending on a word boundary, deal with the last
1331153323Srodrigc	 * (partial) word.
1332153323Srodrigc	 */
1333153323Srodrigc	if (len - i) {
1334153323Srodrigc		/*
1335153323Srodrigc		 * Calculate first (leftmost) bit number to look at,
1336153323Srodrigc		 * and mask for all the relevant bits in this word.
1337153323Srodrigc		 */
1338153323Srodrigc		firstbit = XFS_NBWORD - (len - i);
1339153323Srodrigc		mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
1340153323Srodrigc		/*
1341153323Srodrigc		 * Compute difference between actual and desired value.
1342153323Srodrigc		 */
1343153323Srodrigc		if ((wdiff = (*b ^ want) & mask)) {
1344153323Srodrigc			/*
1345153323Srodrigc			 * Different, mark where we are and return.
1346153323Srodrigc			 */
1347153323Srodrigc			xfs_trans_brelse(tp, bp);
1348153323Srodrigc			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1349153323Srodrigc			*rtblock = start - i + 1;
1350153323Srodrigc			return 0;
1351153323Srodrigc		} else
1352153323Srodrigc			i = len;
1353153323Srodrigc	}
1354153323Srodrigc	/*
1355153323Srodrigc	 * No match, return that we scanned the whole area.
1356153323Srodrigc	 */
1357153323Srodrigc	xfs_trans_brelse(tp, bp);
1358153323Srodrigc	*rtblock = start - i + 1;
1359153323Srodrigc	return 0;
1360153323Srodrigc}
1361153323Srodrigc
1362153323Srodrigc/*
1363153323Srodrigc * Searching forward from start to limit, find the first block whose
1364153323Srodrigc * allocated/free state is different from start's.
1365153323Srodrigc */
1366153323SrodrigcSTATIC int				/* error */
1367153323Srodrigcxfs_rtfind_forw(
1368153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
1369153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
1370153323Srodrigc	xfs_rtblock_t	start,		/* starting block to look at */
1371153323Srodrigc	xfs_rtblock_t	limit,		/* last block to look at */
1372153323Srodrigc	xfs_rtblock_t	*rtblock)	/* out: start block found */
1373153323Srodrigc{
1374153323Srodrigc	xfs_rtword_t	*b;		/* current word in buffer */
1375153323Srodrigc	int		bit;		/* bit number in the word */
1376153323Srodrigc	xfs_rtblock_t	block;		/* bitmap block number */
1377153323Srodrigc	xfs_buf_t	*bp;		/* buf for the block */
1378153323Srodrigc	xfs_rtword_t	*bufp;		/* starting word in buffer */
1379153323Srodrigc	int		error;		/* error value */
1380153323Srodrigc	xfs_rtblock_t	i;		/* current bit number rel. to start */
1381153323Srodrigc	xfs_rtblock_t	lastbit;	/* last useful bit in the word */
1382153323Srodrigc	xfs_rtblock_t	len;		/* length of inspected area */
1383153323Srodrigc	xfs_rtword_t	mask;		/* mask of relevant bits for value */
1384153323Srodrigc	xfs_rtword_t	want;		/* mask for "good" values */
1385153323Srodrigc	xfs_rtword_t	wdiff;		/* difference from wanted value */
1386153323Srodrigc	int		word;		/* word number in the buffer */
1387153323Srodrigc
1388153323Srodrigc	/*
1389153323Srodrigc	 * Compute and read in starting bitmap block for starting block.
1390153323Srodrigc	 */
1391153323Srodrigc	block = XFS_BITTOBLOCK(mp, start);
1392153323Srodrigc	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1393153323Srodrigc	if (error) {
1394153323Srodrigc		return error;
1395153323Srodrigc	}
1396153323Srodrigc	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1397153323Srodrigc	/*
1398153323Srodrigc	 * Get the first word's index & point to it.
1399153323Srodrigc	 */
1400153323Srodrigc	word = XFS_BITTOWORD(mp, start);
1401153323Srodrigc	b = &bufp[word];
1402153323Srodrigc	bit = (int)(start & (XFS_NBWORD - 1));
1403153323Srodrigc	len = limit - start + 1;
1404153323Srodrigc	/*
1405153323Srodrigc	 * Compute match value, based on the bit at start: if 1 (free)
1406153323Srodrigc	 * then all-ones, else all-zeroes.
1407153323Srodrigc	 */
1408153323Srodrigc	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1409153323Srodrigc	/*
1410153323Srodrigc	 * If the starting position is not word-aligned, deal with the
1411153323Srodrigc	 * partial word.
1412153323Srodrigc	 */
1413153323Srodrigc	if (bit) {
1414153323Srodrigc		/*
1415153323Srodrigc		 * Calculate last (rightmost) bit number to look at,
1416153323Srodrigc		 * and mask for all the relevant bits in this word.
1417153323Srodrigc		 */
1418153323Srodrigc		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1419153323Srodrigc		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1420153323Srodrigc		/*
1421153323Srodrigc		 * Calculate the difference between the value there
1422153323Srodrigc		 * and what we're looking for.
1423153323Srodrigc		 */
1424153323Srodrigc		if ((wdiff = (*b ^ want) & mask)) {
1425153323Srodrigc			/*
1426153323Srodrigc			 * Different.  Mark where we are and return.
1427153323Srodrigc			 */
1428153323Srodrigc			xfs_trans_brelse(tp, bp);
1429153323Srodrigc			i = XFS_RTLOBIT(wdiff) - bit;
1430153323Srodrigc			*rtblock = start + i - 1;
1431153323Srodrigc			return 0;
1432153323Srodrigc		}
1433153323Srodrigc		i = lastbit - bit;
1434153323Srodrigc		/*
1435153323Srodrigc		 * Go on to next block if that's where the next word is
1436153323Srodrigc		 * and we need the next word.
1437153323Srodrigc		 */
1438153323Srodrigc		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1439153323Srodrigc			/*
1440153323Srodrigc			 * If done with this block, get the previous one.
1441153323Srodrigc			 */
1442153323Srodrigc			xfs_trans_brelse(tp, bp);
1443153323Srodrigc			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1444153323Srodrigc			if (error) {
1445153323Srodrigc				return error;
1446153323Srodrigc			}
1447153323Srodrigc			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1448153323Srodrigc			word = 0;
1449153323Srodrigc		} else {
1450153323Srodrigc			/*
1451153323Srodrigc			 * Go on to the previous word in the buffer.
1452153323Srodrigc			 */
1453153323Srodrigc			b++;
1454153323Srodrigc		}
1455153323Srodrigc	} else {
1456153323Srodrigc		/*
1457153323Srodrigc		 * Starting on a word boundary, no partial word.
1458153323Srodrigc		 */
1459153323Srodrigc		i = 0;
1460153323Srodrigc	}
1461153323Srodrigc	/*
1462153323Srodrigc	 * Loop over whole words in buffers.  When we use up one buffer
1463153323Srodrigc	 * we move on to the next one.
1464153323Srodrigc	 */
1465153323Srodrigc	while (len - i >= XFS_NBWORD) {
1466153323Srodrigc		/*
1467153323Srodrigc		 * Compute difference between actual and desired value.
1468153323Srodrigc		 */
1469153323Srodrigc		if ((wdiff = *b ^ want)) {
1470153323Srodrigc			/*
1471153323Srodrigc			 * Different, mark where we are and return.
1472153323Srodrigc			 */
1473153323Srodrigc			xfs_trans_brelse(tp, bp);
1474153323Srodrigc			i += XFS_RTLOBIT(wdiff);
1475153323Srodrigc			*rtblock = start + i - 1;
1476153323Srodrigc			return 0;
1477153323Srodrigc		}
1478153323Srodrigc		i += XFS_NBWORD;
1479153323Srodrigc		/*
1480153323Srodrigc		 * Go on to next block if that's where the next word is
1481153323Srodrigc		 * and we need the next word.
1482153323Srodrigc		 */
1483153323Srodrigc		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1484153323Srodrigc			/*
1485153323Srodrigc			 * If done with this block, get the next one.
1486153323Srodrigc			 */
1487153323Srodrigc			xfs_trans_brelse(tp, bp);
1488153323Srodrigc			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1489153323Srodrigc			if (error) {
1490153323Srodrigc				return error;
1491153323Srodrigc			}
1492153323Srodrigc			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1493153323Srodrigc			word = 0;
1494153323Srodrigc		} else {
1495153323Srodrigc			/*
1496153323Srodrigc			 * Go on to the next word in the buffer.
1497153323Srodrigc			 */
1498153323Srodrigc			b++;
1499153323Srodrigc		}
1500153323Srodrigc	}
1501153323Srodrigc	/*
1502153323Srodrigc	 * If not ending on a word boundary, deal with the last
1503153323Srodrigc	 * (partial) word.
1504153323Srodrigc	 */
1505153323Srodrigc	if ((lastbit = len - i)) {
1506153323Srodrigc		/*
1507153323Srodrigc		 * Calculate mask for all the relevant bits in this word.
1508153323Srodrigc		 */
1509153323Srodrigc		mask = ((xfs_rtword_t)1 << lastbit) - 1;
1510153323Srodrigc		/*
1511153323Srodrigc		 * Compute difference between actual and desired value.
1512153323Srodrigc		 */
1513153323Srodrigc		if ((wdiff = (*b ^ want) & mask)) {
1514153323Srodrigc			/*
1515153323Srodrigc			 * Different, mark where we are and return.
1516153323Srodrigc			 */
1517153323Srodrigc			xfs_trans_brelse(tp, bp);
1518153323Srodrigc			i += XFS_RTLOBIT(wdiff);
1519153323Srodrigc			*rtblock = start + i - 1;
1520153323Srodrigc			return 0;
1521153323Srodrigc		} else
1522153323Srodrigc			i = len;
1523153323Srodrigc	}
1524153323Srodrigc	/*
1525153323Srodrigc	 * No match, return that we scanned the whole area.
1526153323Srodrigc	 */
1527153323Srodrigc	xfs_trans_brelse(tp, bp);
1528153323Srodrigc	*rtblock = start + i - 1;
1529153323Srodrigc	return 0;
1530153323Srodrigc}
1531153323Srodrigc
1532153323Srodrigc/*
1533153323Srodrigc * Mark an extent specified by start and len freed.
1534153323Srodrigc * Updates all the summary information as well as the bitmap.
1535153323Srodrigc */
1536153323SrodrigcSTATIC int				/* error */
1537153323Srodrigcxfs_rtfree_range(
1538153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
1539153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
1540153323Srodrigc	xfs_rtblock_t	start,		/* starting block to free */
1541153323Srodrigc	xfs_extlen_t	len,		/* length to free */
1542153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
1543153323Srodrigc	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
1544153323Srodrigc{
1545153323Srodrigc	xfs_rtblock_t	end;		/* end of the freed extent */
1546153323Srodrigc	int		error;		/* error value */
1547153323Srodrigc	xfs_rtblock_t	postblock;	/* first block freed > end */
1548153323Srodrigc	xfs_rtblock_t	preblock;	/* first block freed < start */
1549153323Srodrigc
1550153323Srodrigc	end = start + len - 1;
1551153323Srodrigc	/*
1552153323Srodrigc	 * Modify the bitmap to mark this extent freed.
1553153323Srodrigc	 */
1554153323Srodrigc	error = xfs_rtmodify_range(mp, tp, start, len, 1);
1555153323Srodrigc	if (error) {
1556153323Srodrigc		return error;
1557153323Srodrigc	}
1558153323Srodrigc	/*
1559153323Srodrigc	 * Assume we're freeing out of the middle of an allocated extent.
1560153323Srodrigc	 * We need to find the beginning and end of the extent so we can
1561153323Srodrigc	 * properly update the summary.
1562153323Srodrigc	 */
1563153323Srodrigc	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
1564153323Srodrigc	if (error) {
1565153323Srodrigc		return error;
1566153323Srodrigc	}
1567153323Srodrigc	/*
1568153323Srodrigc	 * Find the next allocated block (end of allocated extent).
1569153323Srodrigc	 */
1570153323Srodrigc	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
1571153323Srodrigc		&postblock);
1572153323Srodrigc	/*
1573153323Srodrigc	 * If there are blocks not being freed at the front of the
1574153323Srodrigc	 * old extent, add summary data for them to be allocated.
1575153323Srodrigc	 */
1576153323Srodrigc	if (preblock < start) {
1577153323Srodrigc		error = xfs_rtmodify_summary(mp, tp,
1578153323Srodrigc			XFS_RTBLOCKLOG(start - preblock),
1579153323Srodrigc			XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
1580153323Srodrigc		if (error) {
1581153323Srodrigc			return error;
1582153323Srodrigc		}
1583153323Srodrigc	}
1584153323Srodrigc	/*
1585153323Srodrigc	 * If there are blocks not being freed at the end of the
1586153323Srodrigc	 * old extent, add summary data for them to be allocated.
1587153323Srodrigc	 */
1588153323Srodrigc	if (postblock > end) {
1589153323Srodrigc		error = xfs_rtmodify_summary(mp, tp,
1590153323Srodrigc			XFS_RTBLOCKLOG(postblock - end),
1591153323Srodrigc			XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
1592153323Srodrigc		if (error) {
1593153323Srodrigc			return error;
1594153323Srodrigc		}
1595153323Srodrigc	}
1596153323Srodrigc	/*
1597153323Srodrigc	 * Increment the summary information corresponding to the entire
1598153323Srodrigc	 * (new) free extent.
1599153323Srodrigc	 */
1600153323Srodrigc	error = xfs_rtmodify_summary(mp, tp,
1601153323Srodrigc		XFS_RTBLOCKLOG(postblock + 1 - preblock),
1602153323Srodrigc		XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
1603153323Srodrigc	return error;
1604153323Srodrigc}
1605153323Srodrigc
1606153323Srodrigc/*
1607153323Srodrigc * Read and return the summary information for a given extent size,
1608153323Srodrigc * bitmap block combination.
1609153323Srodrigc * Keeps track of a current summary block, so we don't keep reading
1610153323Srodrigc * it from the buffer cache.
1611153323Srodrigc */
1612153323SrodrigcSTATIC int				/* error */
1613153323Srodrigcxfs_rtget_summary(
1614153323Srodrigc	xfs_mount_t	*mp,		/* file system mount structure */
1615153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
1616153323Srodrigc	int		log,		/* log2 of extent size */
1617153323Srodrigc	xfs_rtblock_t	bbno,		/* bitmap block number */
1618153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
1619153323Srodrigc	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
1620153323Srodrigc	xfs_suminfo_t	*sum)		/* out: summary info for this block */
1621153323Srodrigc{
1622153323Srodrigc	xfs_buf_t	*bp;		/* buffer for summary block */
1623153323Srodrigc	int		error;		/* error value */
1624153323Srodrigc	xfs_fsblock_t	sb;		/* summary fsblock */
1625153323Srodrigc	int		so;		/* index into the summary file */
1626153323Srodrigc	xfs_suminfo_t	*sp;		/* pointer to returned data */
1627153323Srodrigc
1628153323Srodrigc	/*
1629153323Srodrigc	 * Compute entry number in the summary file.
1630153323Srodrigc	 */
1631153323Srodrigc	so = XFS_SUMOFFS(mp, log, bbno);
1632153323Srodrigc	/*
1633153323Srodrigc	 * Compute the block number in the summary file.
1634153323Srodrigc	 */
1635153323Srodrigc	sb = XFS_SUMOFFSTOBLOCK(mp, so);
1636153323Srodrigc	/*
1637153323Srodrigc	 * If we have an old buffer, and the block number matches, use that.
1638153323Srodrigc	 */
1639153323Srodrigc	if (rbpp && *rbpp && *rsb == sb)
1640153323Srodrigc		bp = *rbpp;
1641153323Srodrigc	/*
1642153323Srodrigc	 * Otherwise we have to get the buffer.
1643153323Srodrigc	 */
1644153323Srodrigc	else {
1645153323Srodrigc		/*
1646153323Srodrigc		 * If there was an old one, get rid of it first.
1647153323Srodrigc		 */
1648153323Srodrigc		if (rbpp && *rbpp)
1649153323Srodrigc			xfs_trans_brelse(tp, *rbpp);
1650153323Srodrigc		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1651153323Srodrigc		if (error) {
1652153323Srodrigc			return error;
1653153323Srodrigc		}
1654153323Srodrigc		/*
1655153323Srodrigc		 * Remember this buffer and block for the next call.
1656153323Srodrigc		 */
1657153323Srodrigc		if (rbpp) {
1658153323Srodrigc			*rbpp = bp;
1659153323Srodrigc			*rsb = sb;
1660153323Srodrigc		}
1661153323Srodrigc	}
1662153323Srodrigc	/*
1663153323Srodrigc	 * Point to the summary information & copy it out.
1664153323Srodrigc	 */
1665153323Srodrigc	sp = XFS_SUMPTR(mp, bp, so);
1666153323Srodrigc	*sum = *sp;
1667153323Srodrigc	/*
1668153323Srodrigc	 * Drop the buffer if we're not asked to remember it.
1669153323Srodrigc	 */
1670153323Srodrigc	if (!rbpp)
1671153323Srodrigc		xfs_trans_brelse(tp, bp);
1672153323Srodrigc	return 0;
1673153323Srodrigc}
1674153323Srodrigc
1675153323Srodrigc/*
1676153323Srodrigc * Set the given range of bitmap bits to the given value.
1677153323Srodrigc * Do whatever I/O and logging is required.
1678153323Srodrigc */
1679153323SrodrigcSTATIC int				/* error */
1680153323Srodrigcxfs_rtmodify_range(
1681153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
1682153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
1683153323Srodrigc	xfs_rtblock_t	start,		/* starting block to modify */
1684153323Srodrigc	xfs_extlen_t	len,		/* length of extent to modify */
1685153323Srodrigc	int		val)		/* 1 for free, 0 for allocated */
1686153323Srodrigc{
1687153323Srodrigc	xfs_rtword_t	*b;		/* current word in buffer */
1688153323Srodrigc	int		bit;		/* bit number in the word */
1689153323Srodrigc	xfs_rtblock_t	block;		/* bitmap block number */
1690153323Srodrigc	xfs_buf_t	*bp;		/* buf for the block */
1691153323Srodrigc	xfs_rtword_t	*bufp;		/* starting word in buffer */
1692153323Srodrigc	int		error;		/* error value */
1693153323Srodrigc	xfs_rtword_t	*first;		/* first used word in the buffer */
1694153323Srodrigc	int		i;		/* current bit number rel. to start */
1695153323Srodrigc	int		lastbit;	/* last useful bit in word */
1696153323Srodrigc	xfs_rtword_t	mask;		/* mask o frelevant bits for value */
1697153323Srodrigc	int		word;		/* word number in the buffer */
1698153323Srodrigc
1699153323Srodrigc	/*
1700153323Srodrigc	 * Compute starting bitmap block number.
1701153323Srodrigc	 */
1702153323Srodrigc	block = XFS_BITTOBLOCK(mp, start);
1703153323Srodrigc	/*
1704153323Srodrigc	 * Read the bitmap block, and point to its data.
1705153323Srodrigc	 */
1706153323Srodrigc	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1707153323Srodrigc	if (error) {
1708153323Srodrigc		return error;
1709153323Srodrigc	}
1710153323Srodrigc	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1711153323Srodrigc	/*
1712153323Srodrigc	 * Compute the starting word's address, and starting bit.
1713153323Srodrigc	 */
1714153323Srodrigc	word = XFS_BITTOWORD(mp, start);
1715153323Srodrigc	first = b = &bufp[word];
1716153323Srodrigc	bit = (int)(start & (XFS_NBWORD - 1));
1717153323Srodrigc	/*
1718153323Srodrigc	 * 0 (allocated) => all zeroes; 1 (free) => all ones.
1719153323Srodrigc	 */
1720153323Srodrigc	val = -val;
1721153323Srodrigc	/*
1722153323Srodrigc	 * If not starting on a word boundary, deal with the first
1723153323Srodrigc	 * (partial) word.
1724153323Srodrigc	 */
1725153323Srodrigc	if (bit) {
1726153323Srodrigc		/*
1727153323Srodrigc		 * Compute first bit not changed and mask of relevant bits.
1728153323Srodrigc		 */
1729153323Srodrigc		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1730153323Srodrigc		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1731153323Srodrigc		/*
1732153323Srodrigc		 * Set/clear the active bits.
1733153323Srodrigc		 */
1734153323Srodrigc		if (val)
1735153323Srodrigc			*b |= mask;
1736153323Srodrigc		else
1737153323Srodrigc			*b &= ~mask;
1738153323Srodrigc		i = lastbit - bit;
1739153323Srodrigc		/*
1740153323Srodrigc		 * Go on to the next block if that's where the next word is
1741153323Srodrigc		 * and we need the next word.
1742153323Srodrigc		 */
1743153323Srodrigc		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1744153323Srodrigc			/*
1745153323Srodrigc			 * Log the changed part of this block.
1746153323Srodrigc			 * Get the next one.
1747153323Srodrigc			 */
1748153323Srodrigc			xfs_trans_log_buf(tp, bp,
1749153323Srodrigc				(uint)((char *)first - (char *)bufp),
1750153323Srodrigc				(uint)((char *)b - (char *)bufp));
1751153323Srodrigc			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1752153323Srodrigc			if (error) {
1753153323Srodrigc				return error;
1754153323Srodrigc			}
1755153323Srodrigc			first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1756153323Srodrigc			word = 0;
1757153323Srodrigc		} else {
1758153323Srodrigc			/*
1759153323Srodrigc			 * Go on to the next word in the buffer
1760153323Srodrigc			 */
1761153323Srodrigc			b++;
1762153323Srodrigc		}
1763153323Srodrigc	} else {
1764153323Srodrigc		/*
1765153323Srodrigc		 * Starting on a word boundary, no partial word.
1766153323Srodrigc		 */
1767153323Srodrigc		i = 0;
1768153323Srodrigc	}
1769153323Srodrigc	/*
1770153323Srodrigc	 * Loop over whole words in buffers.  When we use up one buffer
1771153323Srodrigc	 * we move on to the next one.
1772153323Srodrigc	 */
1773153323Srodrigc	while (len - i >= XFS_NBWORD) {
1774153323Srodrigc		/*
1775153323Srodrigc		 * Set the word value correctly.
1776153323Srodrigc		 */
1777153323Srodrigc		*b = val;
1778153323Srodrigc		i += XFS_NBWORD;
1779153323Srodrigc		/*
1780153323Srodrigc		 * Go on to the next block if that's where the next word is
1781153323Srodrigc		 * and we need the next word.
1782153323Srodrigc		 */
1783153323Srodrigc		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1784153323Srodrigc			/*
1785153323Srodrigc			 * Log the changed part of this block.
1786153323Srodrigc			 * Get the next one.
1787153323Srodrigc			 */
1788153323Srodrigc			xfs_trans_log_buf(tp, bp,
1789153323Srodrigc				(uint)((char *)first - (char *)bufp),
1790153323Srodrigc				(uint)((char *)b - (char *)bufp));
1791153323Srodrigc			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1792153323Srodrigc			if (error) {
1793153323Srodrigc				return error;
1794153323Srodrigc			}
1795153323Srodrigc			first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1796153323Srodrigc			word = 0;
1797153323Srodrigc		} else {
1798153323Srodrigc			/*
1799153323Srodrigc			 * Go on to the next word in the buffer
1800153323Srodrigc			 */
1801153323Srodrigc			b++;
1802153323Srodrigc		}
1803153323Srodrigc	}
1804153323Srodrigc	/*
1805153323Srodrigc	 * If not ending on a word boundary, deal with the last
1806153323Srodrigc	 * (partial) word.
1807153323Srodrigc	 */
1808153323Srodrigc	if ((lastbit = len - i)) {
1809153323Srodrigc		/*
1810153323Srodrigc		 * Compute a mask of relevant bits.
1811153323Srodrigc		 */
1812153323Srodrigc		bit = 0;
1813153323Srodrigc		mask = ((xfs_rtword_t)1 << lastbit) - 1;
1814153323Srodrigc		/*
1815153323Srodrigc		 * Set/clear the active bits.
1816153323Srodrigc		 */
1817153323Srodrigc		if (val)
1818153323Srodrigc			*b |= mask;
1819153323Srodrigc		else
1820153323Srodrigc			*b &= ~mask;
1821153323Srodrigc		b++;
1822153323Srodrigc	}
1823153323Srodrigc	/*
1824153323Srodrigc	 * Log any remaining changed bytes.
1825153323Srodrigc	 */
1826153323Srodrigc	if (b > first)
1827153323Srodrigc		xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
1828153323Srodrigc			(uint)((char *)b - (char *)bufp - 1));
1829153323Srodrigc	return 0;
1830153323Srodrigc}
1831153323Srodrigc
1832153323Srodrigc/*
1833153323Srodrigc * Read and modify the summary information for a given extent size,
1834153323Srodrigc * bitmap block combination.
1835153323Srodrigc * Keeps track of a current summary block, so we don't keep reading
1836153323Srodrigc * it from the buffer cache.
1837153323Srodrigc */
1838153323SrodrigcSTATIC int				/* error */
1839153323Srodrigcxfs_rtmodify_summary(
1840153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
1841153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
1842153323Srodrigc	int		log,		/* log2 of extent size */
1843153323Srodrigc	xfs_rtblock_t	bbno,		/* bitmap block number */
1844153323Srodrigc	int		delta,		/* change to make to summary info */
1845153323Srodrigc	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
1846153323Srodrigc	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
1847153323Srodrigc{
1848153323Srodrigc	xfs_buf_t	*bp;		/* buffer for the summary block */
1849153323Srodrigc	int		error;		/* error value */
1850153323Srodrigc	xfs_fsblock_t	sb;		/* summary fsblock */
1851153323Srodrigc	int		so;		/* index into the summary file */
1852153323Srodrigc	xfs_suminfo_t	*sp;		/* pointer to returned data */
1853153323Srodrigc
1854153323Srodrigc	/*
1855153323Srodrigc	 * Compute entry number in the summary file.
1856153323Srodrigc	 */
1857153323Srodrigc	so = XFS_SUMOFFS(mp, log, bbno);
1858153323Srodrigc	/*
1859153323Srodrigc	 * Compute the block number in the summary file.
1860153323Srodrigc	 */
1861153323Srodrigc	sb = XFS_SUMOFFSTOBLOCK(mp, so);
1862153323Srodrigc	/*
1863153323Srodrigc	 * If we have an old buffer, and the block number matches, use that.
1864153323Srodrigc	 */
1865153323Srodrigc	if (rbpp && *rbpp && *rsb == sb)
1866153323Srodrigc		bp = *rbpp;
1867153323Srodrigc	/*
1868153323Srodrigc	 * Otherwise we have to get the buffer.
1869153323Srodrigc	 */
1870153323Srodrigc	else {
1871153323Srodrigc		/*
1872153323Srodrigc		 * If there was an old one, get rid of it first.
1873153323Srodrigc		 */
1874153323Srodrigc		if (rbpp && *rbpp)
1875153323Srodrigc			xfs_trans_brelse(tp, *rbpp);
1876153323Srodrigc		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1877153323Srodrigc		if (error) {
1878153323Srodrigc			return error;
1879153323Srodrigc		}
1880153323Srodrigc		/*
1881153323Srodrigc		 * Remember this buffer and block for the next call.
1882153323Srodrigc		 */
1883153323Srodrigc		if (rbpp) {
1884153323Srodrigc			*rbpp = bp;
1885153323Srodrigc			*rsb = sb;
1886153323Srodrigc		}
1887153323Srodrigc	}
1888153323Srodrigc	/*
1889153323Srodrigc	 * Point to the summary information, modify and log it.
1890153323Srodrigc	 */
1891153323Srodrigc	sp = XFS_SUMPTR(mp, bp, so);
1892153323Srodrigc	*sp += delta;
1893153323Srodrigc	xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)XFS_BUF_PTR(bp)),
1894153323Srodrigc		(uint)((char *)sp - (char *)XFS_BUF_PTR(bp) + sizeof(*sp) - 1));
1895153323Srodrigc	return 0;
1896153323Srodrigc}
1897153323Srodrigc
1898153323Srodrigc/*
1899153323Srodrigc * Visible (exported) functions.
1900153323Srodrigc */
1901153323Srodrigc
1902153323Srodrigc/*
1903153323Srodrigc * Grow the realtime area of the filesystem.
1904153323Srodrigc */
1905153323Srodrigcint
1906153323Srodrigcxfs_growfs_rt(
1907153323Srodrigc	xfs_mount_t	*mp,		/* mount point for filesystem */
1908153323Srodrigc	xfs_growfs_rt_t	*in)		/* growfs rt input struct */
1909153323Srodrigc{
1910153323Srodrigc	xfs_rtblock_t	bmbno;		/* bitmap block number */
1911153323Srodrigc	xfs_buf_t	*bp;		/* temporary buffer */
1912153323Srodrigc	int		cancelflags;	/* flags for xfs_trans_cancel */
1913153323Srodrigc	int		error;		/* error return value */
1914153323Srodrigc	xfs_inode_t	*ip;		/* bitmap inode, used as lock */
1915153323Srodrigc	xfs_mount_t	*nmp;		/* new (fake) mount structure */
1916153323Srodrigc	xfs_drfsbno_t	nrblocks;	/* new number of realtime blocks */
1917153323Srodrigc	xfs_extlen_t	nrbmblocks;	/* new number of rt bitmap blocks */
1918153323Srodrigc	xfs_drtbno_t	nrextents;	/* new number of realtime extents */
1919153323Srodrigc	uint8_t		nrextslog;	/* new log2 of sb_rextents */
1920153323Srodrigc	xfs_extlen_t	nrsumblocks;	/* new number of summary blocks */
1921153323Srodrigc	uint		nrsumlevels;	/* new rt summary levels */
1922153323Srodrigc	uint		nrsumsize;	/* new size of rt summary, bytes */
1923153323Srodrigc	xfs_sb_t	*nsbp;		/* new superblock */
1924153323Srodrigc	xfs_extlen_t	rbmblocks;	/* current number of rt bitmap blocks */
1925153323Srodrigc	xfs_extlen_t	rsumblocks;	/* current number of rt summary blks */
1926153323Srodrigc	xfs_sb_t	*sbp;		/* old superblock */
1927153323Srodrigc	xfs_fsblock_t	sumbno;		/* summary block number */
1928153323Srodrigc	xfs_trans_t	*tp;		/* transaction pointer */
1929153323Srodrigc
1930153323Srodrigc	sbp = &mp->m_sb;
1931153323Srodrigc	/*
1932153323Srodrigc	 * Initial error checking.
1933153323Srodrigc	 */
1934153323Srodrigc	if (mp->m_rtdev_targp || mp->m_rbmip == NULL ||
1935153323Srodrigc	    (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
1936153323Srodrigc	    (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
1937153323Srodrigc		return XFS_ERROR(EINVAL);
1938153323Srodrigc	/*
1939153323Srodrigc	 * Read in the last block of the device, make sure it exists.
1940153323Srodrigc	 */
1941153323Srodrigc	error = xfs_read_buf(mp, mp->m_rtdev_targp,
1942153323Srodrigc			XFS_FSB_TO_BB(mp, in->newblocks - 1),
1943153323Srodrigc			XFS_FSB_TO_BB(mp, 1), 0, &bp);
1944153323Srodrigc	if (error)
1945153323Srodrigc		return error;
1946153323Srodrigc	ASSERT(bp);
1947153323Srodrigc	xfs_buf_relse(bp);
1948153323Srodrigc	/*
1949153323Srodrigc	 * Calculate new parameters.  These are the final values to be reached.
1950153323Srodrigc	 */
1951159451Srodrigc	nrextents = nrblocks;
1952159451Srodrigc	do_div(nrextents, in->extsize);
1953153323Srodrigc	nrbmblocks = roundup_64(nrextents, NBBY * sbp->sb_blocksize);
1954153323Srodrigc	nrextslog = xfs_highbit32(nrextents);
1955153323Srodrigc	nrsumlevels = nrextslog + 1;
1956153323Srodrigc	nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
1957153323Srodrigc	nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
1958153323Srodrigc	nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
1959153323Srodrigc	/*
1960153323Srodrigc	 * New summary size can't be more than half the size of
1961153323Srodrigc	 * the log.  This prevents us from getting a log overflow,
1962153323Srodrigc	 * since we'll log basically the whole summary file at once.
1963153323Srodrigc	 */
1964153323Srodrigc	if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1))
1965153323Srodrigc		return XFS_ERROR(EINVAL);
1966153323Srodrigc	/*
1967153323Srodrigc	 * Get the old block counts for bitmap and summary inodes.
1968153323Srodrigc	 * These can't change since other growfs callers are locked out.
1969153323Srodrigc	 */
1970153323Srodrigc	rbmblocks = XFS_B_TO_FSB(mp, mp->m_rbmip->i_d.di_size);
1971153323Srodrigc	rsumblocks = XFS_B_TO_FSB(mp, mp->m_rsumip->i_d.di_size);
1972153323Srodrigc	/*
1973153323Srodrigc	 * Allocate space to the bitmap and summary files, as necessary.
1974153323Srodrigc	 */
1975153323Srodrigc	if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks,
1976153323Srodrigc			mp->m_sb.sb_rbmino)))
1977153323Srodrigc		return error;
1978153323Srodrigc	if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks,
1979153323Srodrigc			mp->m_sb.sb_rsumino)))
1980153323Srodrigc		return error;
1981153323Srodrigc	nmp = NULL;
1982153323Srodrigc	/*
1983153323Srodrigc	 * Loop over the bitmap blocks.
1984153323Srodrigc	 * We will do everything one bitmap block at a time.
1985153323Srodrigc	 * Skip the current block if it is exactly full.
1986153323Srodrigc	 * This also deals with the case where there were no rtextents before.
1987153323Srodrigc	 */
1988153323Srodrigc	for (bmbno = sbp->sb_rbmblocks -
1989153323Srodrigc		     ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
1990153323Srodrigc	     bmbno < nrbmblocks;
1991153323Srodrigc	     bmbno++) {
1992153323Srodrigc		/*
1993153323Srodrigc		 * Allocate a new (fake) mount/sb.
1994153323Srodrigc		 */
1995153323Srodrigc		nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
1996153323Srodrigc		*nmp = *mp;
1997153323Srodrigc		nsbp = &nmp->m_sb;
1998153323Srodrigc		/*
1999153323Srodrigc		 * Calculate new sb and mount fields for this round.
2000153323Srodrigc		 */
2001153323Srodrigc		nsbp->sb_rextsize = in->extsize;
2002153323Srodrigc		nsbp->sb_rbmblocks = bmbno + 1;
2003153323Srodrigc		nsbp->sb_rblocks =
2004153323Srodrigc			XFS_RTMIN(nrblocks,
2005153323Srodrigc				  nsbp->sb_rbmblocks * NBBY *
2006153323Srodrigc				  nsbp->sb_blocksize * nsbp->sb_rextsize);
2007159451Srodrigc		nsbp->sb_rextents = nsbp->sb_rblocks;
2008159451Srodrigc		do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
2009153323Srodrigc		nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
2010153323Srodrigc		nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
2011153323Srodrigc		nrsumsize =
2012153323Srodrigc			(uint)sizeof(xfs_suminfo_t) * nrsumlevels *
2013153323Srodrigc			nsbp->sb_rbmblocks;
2014153323Srodrigc		nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
2015153323Srodrigc		nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
2016153323Srodrigc		/*
2017153323Srodrigc		 * Start a transaction, get the log reservation.
2018153323Srodrigc		 */
2019153323Srodrigc		tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_FREE);
2020153323Srodrigc		cancelflags = 0;
2021153323Srodrigc		if ((error = xfs_trans_reserve(tp, 0,
2022153323Srodrigc				XFS_GROWRTFREE_LOG_RES(nmp), 0, 0, 0)))
2023153323Srodrigc			goto error_exit;
2024153323Srodrigc		/*
2025153323Srodrigc		 * Lock out other callers by grabbing the bitmap inode lock.
2026153323Srodrigc		 */
2027159451Srodrigc		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
2028159451Srodrigc						XFS_ILOCK_EXCL, &ip)))
2029153323Srodrigc			goto error_exit;
2030153323Srodrigc		ASSERT(ip == mp->m_rbmip);
2031153323Srodrigc		/*
2032153323Srodrigc		 * Update the bitmap inode's size.
2033153323Srodrigc		 */
2034153323Srodrigc		mp->m_rbmip->i_d.di_size =
2035153323Srodrigc			nsbp->sb_rbmblocks * nsbp->sb_blocksize;
2036153323Srodrigc		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
2037153323Srodrigc		cancelflags |= XFS_TRANS_ABORT;
2038153323Srodrigc		/*
2039153323Srodrigc		 * Get the summary inode into the transaction.
2040153323Srodrigc		 */
2041159451Srodrigc		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0,
2042159451Srodrigc						XFS_ILOCK_EXCL, &ip)))
2043153323Srodrigc			goto error_exit;
2044153323Srodrigc		ASSERT(ip == mp->m_rsumip);
2045153323Srodrigc		/*
2046153323Srodrigc		 * Update the summary inode's size.
2047153323Srodrigc		 */
2048153323Srodrigc		mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
2049153323Srodrigc		xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
2050153323Srodrigc		/*
2051153323Srodrigc		 * Copy summary data from old to new sizes.
2052153323Srodrigc		 * Do this when the real size (not block-aligned) changes.
2053153323Srodrigc		 */
2054153323Srodrigc		if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
2055153323Srodrigc		    mp->m_rsumlevels != nmp->m_rsumlevels) {
2056153323Srodrigc			error = xfs_rtcopy_summary(mp, nmp, tp);
2057153323Srodrigc			if (error)
2058153323Srodrigc				goto error_exit;
2059153323Srodrigc		}
2060153323Srodrigc		/*
2061153323Srodrigc		 * Update superblock fields.
2062153323Srodrigc		 */
2063153323Srodrigc		if (nsbp->sb_rextsize != sbp->sb_rextsize)
2064153323Srodrigc			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
2065153323Srodrigc				nsbp->sb_rextsize - sbp->sb_rextsize);
2066153323Srodrigc		if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
2067153323Srodrigc			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
2068153323Srodrigc				nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
2069153323Srodrigc		if (nsbp->sb_rblocks != sbp->sb_rblocks)
2070153323Srodrigc			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
2071153323Srodrigc				nsbp->sb_rblocks - sbp->sb_rblocks);
2072153323Srodrigc		if (nsbp->sb_rextents != sbp->sb_rextents)
2073153323Srodrigc			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
2074153323Srodrigc				nsbp->sb_rextents - sbp->sb_rextents);
2075153323Srodrigc		if (nsbp->sb_rextslog != sbp->sb_rextslog)
2076153323Srodrigc			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
2077153323Srodrigc				nsbp->sb_rextslog - sbp->sb_rextslog);
2078153323Srodrigc		/*
2079153323Srodrigc		 * Free new extent.
2080153323Srodrigc		 */
2081153323Srodrigc		bp = NULL;
2082153323Srodrigc		error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
2083153323Srodrigc			nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
2084153323Srodrigc		if (error)
2085153323Srodrigc			goto error_exit;
2086153323Srodrigc		/*
2087153323Srodrigc		 * Mark more blocks free in the superblock.
2088153323Srodrigc		 */
2089153323Srodrigc		xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
2090153323Srodrigc			nsbp->sb_rextents - sbp->sb_rextents);
2091153323Srodrigc		/*
2092153323Srodrigc		 * Free the fake mp structure.
2093153323Srodrigc		 */
2094153323Srodrigc		kmem_free(nmp, sizeof(*nmp));
2095153323Srodrigc		nmp = NULL;
2096153323Srodrigc		/*
2097153323Srodrigc		 * Update mp values into the real mp structure.
2098153323Srodrigc		 */
2099153323Srodrigc		mp->m_rsumlevels = nrsumlevels;
2100153323Srodrigc		mp->m_rsumsize = nrsumsize;
2101153323Srodrigc		/*
2102153323Srodrigc		 * Commit the transaction.
2103153323Srodrigc		 */
2104153323Srodrigc		xfs_trans_commit(tp, 0, NULL);
2105153323Srodrigc	}
2106153323Srodrigc	return 0;
2107153323Srodrigc
2108153323Srodrigc	/*
2109153323Srodrigc	 * Error paths come here.
2110153323Srodrigc	 */
2111153323Srodrigcerror_exit:
2112153323Srodrigc	if (nmp)
2113153323Srodrigc		kmem_free(nmp, sizeof(*nmp));
2114153323Srodrigc	xfs_trans_cancel(tp, cancelflags);
2115153323Srodrigc	return error;
2116153323Srodrigc}
2117153323Srodrigc
2118153323Srodrigc/*
2119153323Srodrigc * Allocate an extent in the realtime subvolume, with the usual allocation
2120153323Srodrigc * parameters.  The length units are all in realtime extents, as is the
2121153323Srodrigc * result block number.
2122153323Srodrigc */
2123153323Srodrigcint					/* error */
2124153323Srodrigcxfs_rtallocate_extent(
2125153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
2126153323Srodrigc	xfs_rtblock_t	bno,		/* starting block number to allocate */
2127153323Srodrigc	xfs_extlen_t	minlen,		/* minimum length to allocate */
2128153323Srodrigc	xfs_extlen_t	maxlen,		/* maximum length to allocate */
2129153323Srodrigc	xfs_extlen_t	*len,		/* out: actual length allocated */
2130153323Srodrigc	xfs_alloctype_t	type,		/* allocation type XFS_ALLOCTYPE... */
2131153323Srodrigc	int		wasdel,		/* was a delayed allocation extent */
2132153323Srodrigc	xfs_extlen_t	prod,		/* extent product factor */
2133153323Srodrigc	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
2134153323Srodrigc{
2135153323Srodrigc	int		error;		/* error value */
2136153323Srodrigc	xfs_inode_t	*ip;		/* inode for bitmap file */
2137153323Srodrigc	xfs_mount_t	*mp;		/* file system mount structure */
2138153323Srodrigc	xfs_rtblock_t	r;		/* result allocated block */
2139153323Srodrigc	xfs_fsblock_t	sb;		/* summary file block number */
2140153323Srodrigc	xfs_buf_t	*sumbp;		/* summary file block buffer */
2141153323Srodrigc
2142153323Srodrigc	ASSERT(minlen > 0 && minlen <= maxlen);
2143153323Srodrigc	mp = tp->t_mountp;
2144153323Srodrigc	/*
2145153323Srodrigc	 * If prod is set then figure out what to do to minlen and maxlen.
2146153323Srodrigc	 */
2147153323Srodrigc	if (prod > 1) {
2148153323Srodrigc		xfs_extlen_t	i;
2149153323Srodrigc
2150153323Srodrigc		if ((i = maxlen % prod))
2151153323Srodrigc			maxlen -= i;
2152153323Srodrigc		if ((i = minlen % prod))
2153153323Srodrigc			minlen += prod - i;
2154153323Srodrigc		if (maxlen < minlen) {
2155153323Srodrigc			*rtblock = NULLRTBLOCK;
2156153323Srodrigc			return 0;
2157153323Srodrigc		}
2158153323Srodrigc	}
2159153323Srodrigc	/*
2160153323Srodrigc	 * Lock out other callers by grabbing the bitmap inode lock.
2161153323Srodrigc	 */
2162159451Srodrigc	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
2163159451Srodrigc					XFS_ILOCK_EXCL, &ip)))
2164153323Srodrigc		return error;
2165153323Srodrigc	sumbp = NULL;
2166153323Srodrigc	/*
2167153323Srodrigc	 * Allocate by size, or near another block, or exactly at some block.
2168153323Srodrigc	 */
2169153323Srodrigc	switch (type) {
2170153323Srodrigc	case XFS_ALLOCTYPE_ANY_AG:
2171153323Srodrigc		error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
2172153323Srodrigc				&sumbp,	&sb, prod, &r);
2173153323Srodrigc		break;
2174153323Srodrigc	case XFS_ALLOCTYPE_NEAR_BNO:
2175153323Srodrigc		error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
2176153323Srodrigc				len, &sumbp, &sb, prod, &r);
2177153323Srodrigc		break;
2178153323Srodrigc	case XFS_ALLOCTYPE_THIS_BNO:
2179153323Srodrigc		error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen,
2180153323Srodrigc				len, &sumbp, &sb, prod, &r);
2181153323Srodrigc		break;
2182153323Srodrigc	default:
2183153323Srodrigc		ASSERT(0);
2184153323Srodrigc	}
2185153323Srodrigc	if (error) {
2186153323Srodrigc		return error;
2187153323Srodrigc	}
2188153323Srodrigc	/*
2189153323Srodrigc	 * If it worked, update the superblock.
2190153323Srodrigc	 */
2191153323Srodrigc	if (r != NULLRTBLOCK) {
2192153323Srodrigc		long	slen = (long)*len;
2193153323Srodrigc
2194153323Srodrigc		ASSERT(*len >= minlen && *len <= maxlen);
2195153323Srodrigc		if (wasdel)
2196153323Srodrigc			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
2197153323Srodrigc		else
2198153323Srodrigc			xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
2199153323Srodrigc	}
2200153323Srodrigc	*rtblock = r;
2201153323Srodrigc	return 0;
2202153323Srodrigc}
2203153323Srodrigc
2204153323Srodrigc/*
2205153323Srodrigc * Free an extent in the realtime subvolume.  Length is expressed in
2206153323Srodrigc * realtime extents, as is the block number.
2207153323Srodrigc */
2208153323Srodrigcint					/* error */
2209153323Srodrigcxfs_rtfree_extent(
2210153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
2211153323Srodrigc	xfs_rtblock_t	bno,		/* starting block number to free */
2212153323Srodrigc	xfs_extlen_t	len)		/* length of extent freed */
2213153323Srodrigc{
2214153323Srodrigc	int		error;		/* error value */
2215153323Srodrigc	xfs_inode_t	*ip;		/* bitmap file inode */
2216153323Srodrigc	xfs_mount_t	*mp;		/* file system mount structure */
2217153323Srodrigc	xfs_fsblock_t	sb;		/* summary file block number */
2218153323Srodrigc	xfs_buf_t	*sumbp;		/* summary file block buffer */
2219153323Srodrigc
2220153323Srodrigc	mp = tp->t_mountp;
2221153323Srodrigc	/*
2222153323Srodrigc	 * Synchronize by locking the bitmap inode.
2223153323Srodrigc	 */
2224159451Srodrigc	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
2225159451Srodrigc					XFS_ILOCK_EXCL, &ip)))
2226153323Srodrigc		return error;
2227153323Srodrigc#if defined(__KERNEL__) && defined(DEBUG)
2228153323Srodrigc	/*
2229153323Srodrigc	 * Check to see that this whole range is currently allocated.
2230153323Srodrigc	 */
2231153323Srodrigc	{
2232153323Srodrigc		int	stat;		/* result from checking range */
2233153323Srodrigc
2234153323Srodrigc		error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
2235153323Srodrigc		if (error) {
2236153323Srodrigc			return error;
2237153323Srodrigc		}
2238153323Srodrigc		ASSERT(stat);
2239153323Srodrigc	}
2240153323Srodrigc#endif
2241153323Srodrigc	sumbp = NULL;
2242153323Srodrigc	/*
2243153323Srodrigc	 * Free the range of realtime blocks.
2244153323Srodrigc	 */
2245153323Srodrigc	error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
2246153323Srodrigc	if (error) {
2247153323Srodrigc		return error;
2248153323Srodrigc	}
2249153323Srodrigc	/*
2250153323Srodrigc	 * Mark more blocks free in the superblock.
2251153323Srodrigc	 */
2252153323Srodrigc	xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
2253153323Srodrigc	/*
2254153323Srodrigc	 * If we've now freed all the blocks, reset the file sequence
2255153323Srodrigc	 * number to 0.
2256153323Srodrigc	 */
2257153323Srodrigc	if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
2258153323Srodrigc	    mp->m_sb.sb_rextents) {
2259153323Srodrigc		if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
2260153323Srodrigc			ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2261153323Srodrigc		*(__uint64_t *)&ip->i_d.di_atime = 0;
2262153323Srodrigc		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2263153323Srodrigc	}
2264153323Srodrigc	return 0;
2265153323Srodrigc}
2266153323Srodrigc
2267153323Srodrigc/*
2268153323Srodrigc * Initialize realtime fields in the mount structure.
2269153323Srodrigc */
2270153323Srodrigcint				/* error */
2271153323Srodrigcxfs_rtmount_init(
2272153323Srodrigc	xfs_mount_t	*mp)	/* file system mount structure */
2273153323Srodrigc{
2274153323Srodrigc	xfs_buf_t	*bp;	/* buffer for last block of subvolume */
2275153323Srodrigc	xfs_daddr_t	d;	/* address of last block of subvolume */
2276153323Srodrigc	int		error;	/* error return value */
2277153323Srodrigc	xfs_sb_t	*sbp;	/* filesystem superblock copy in mount */
2278153323Srodrigc
2279153323Srodrigc	sbp = &mp->m_sb;
2280153323Srodrigc	if (sbp->sb_rblocks == 0)
2281153323Srodrigc		return 0;
2282153323Srodrigc	if (mp->m_rtdev_targp == NULL) {
2283153323Srodrigc		cmn_err(CE_WARN,
2284153323Srodrigc	"XFS: This filesystem has a realtime volume, use rtdev=device option");
2285153323Srodrigc		return XFS_ERROR(ENODEV);
2286153323Srodrigc	}
2287153323Srodrigc	mp->m_rsumlevels = sbp->sb_rextslog + 1;
2288153323Srodrigc	mp->m_rsumsize =
2289153323Srodrigc		(uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
2290153323Srodrigc		sbp->sb_rbmblocks;
2291153323Srodrigc	mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
2292153323Srodrigc	mp->m_rbmip = mp->m_rsumip = NULL;
2293153323Srodrigc	/*
2294153323Srodrigc	 * Check that the realtime section is an ok size.
2295153323Srodrigc	 */
2296153323Srodrigc	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
2297153323Srodrigc	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
2298153323Srodrigc		cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
2299153323Srodrigc			(unsigned long long) XFS_BB_TO_FSB(mp, d),
2300153323Srodrigc			(unsigned long long) mp->m_sb.sb_rblocks);
2301153323Srodrigc		return XFS_ERROR(E2BIG);
2302153323Srodrigc	}
2303153323Srodrigc	error = xfs_read_buf(mp, mp->m_rtdev_targp,
2304153323Srodrigc				d - XFS_FSB_TO_BB(mp, 1),
2305153323Srodrigc				XFS_FSB_TO_BB(mp, 1), 0, &bp);
2306153323Srodrigc	if (error) {
2307153323Srodrigc		cmn_err(CE_WARN,
2308153323Srodrigc	"XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
2309153323Srodrigc		if (error == ENOSPC)
2310153323Srodrigc			return XFS_ERROR(E2BIG);
2311153323Srodrigc		return error;
2312153323Srodrigc	}
2313153323Srodrigc	xfs_buf_relse(bp);
2314153323Srodrigc	return 0;
2315153323Srodrigc}
2316153323Srodrigc
2317153323Srodrigc/*
2318153323Srodrigc * Get the bitmap and summary inodes into the mount structure
2319153323Srodrigc * at mount time.
2320153323Srodrigc */
2321153323Srodrigcint					/* error */
2322153323Srodrigcxfs_rtmount_inodes(
2323153323Srodrigc	xfs_mount_t	*mp)		/* file system mount structure */
2324153323Srodrigc{
2325153323Srodrigc	int		error;		/* error return value */
2326153323Srodrigc	xfs_sb_t	*sbp;
2327153323Srodrigc
2328153323Srodrigc	sbp = &mp->m_sb;
2329153323Srodrigc	if (sbp->sb_rbmino == NULLFSINO)
2330153323Srodrigc		return 0;
2331159451Srodrigc	error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0);
2332153323Srodrigc	if (error)
2333153323Srodrigc		return error;
2334153323Srodrigc	ASSERT(mp->m_rbmip != NULL);
2335153323Srodrigc	ASSERT(sbp->sb_rsumino != NULLFSINO);
2336159451Srodrigc	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
2337153323Srodrigc	if (error) {
2338159451Srodrigc		VN_RELE(XFS_ITOV(mp->m_rbmip));
2339153323Srodrigc		return error;
2340153323Srodrigc	}
2341153323Srodrigc	ASSERT(mp->m_rsumip != NULL);
2342153323Srodrigc	return 0;
2343153323Srodrigc}
2344153323Srodrigc
2345153323Srodrigc/*
2346153323Srodrigc * Pick an extent for allocation at the start of a new realtime file.
2347153323Srodrigc * Use the sequence number stored in the atime field of the bitmap inode.
2348153323Srodrigc * Translate this to a fraction of the rtextents, and return the product
2349153323Srodrigc * of rtextents and the fraction.
2350153323Srodrigc * The fraction sequence is 0, 1/2, 1/4, 3/4, 1/8, ..., 7/8, 1/16, ...
2351153323Srodrigc */
2352153323Srodrigcint					/* error */
2353153323Srodrigcxfs_rtpick_extent(
2354153323Srodrigc	xfs_mount_t	*mp,		/* file system mount point */
2355153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
2356153323Srodrigc	xfs_extlen_t	len,		/* allocation length (rtextents) */
2357153323Srodrigc	xfs_rtblock_t	*pick)		/* result rt extent */
2358153323Srodrigc{
2359153323Srodrigc	xfs_rtblock_t	b;		/* result block */
2360153323Srodrigc	int		error;		/* error return value */
2361153323Srodrigc	xfs_inode_t	*ip;		/* bitmap incore inode */
2362153323Srodrigc	int		log2;		/* log of sequence number */
2363153323Srodrigc	__uint64_t	resid;		/* residual after log removed */
2364153323Srodrigc	__uint64_t	seq;		/* sequence number of file creation */
2365153323Srodrigc	__uint64_t	*seqp;		/* pointer to seqno in inode */
2366153323Srodrigc
2367159451Srodrigc	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
2368159451Srodrigc					XFS_ILOCK_EXCL, &ip)))
2369153323Srodrigc		return error;
2370153323Srodrigc	ASSERT(ip == mp->m_rbmip);
2371153323Srodrigc	seqp = (__uint64_t *)&ip->i_d.di_atime;
2372153323Srodrigc	if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
2373153323Srodrigc		ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2374153323Srodrigc		*seqp = 0;
2375153323Srodrigc	}
2376153323Srodrigc	seq = *seqp;
2377153323Srodrigc	if ((log2 = xfs_highbit64(seq)) == -1)
2378153323Srodrigc		b = 0;
2379153323Srodrigc	else {
2380153323Srodrigc		resid = seq - (1ULL << log2);
2381153323Srodrigc		b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
2382153323Srodrigc		    (log2 + 1);
2383153323Srodrigc		if (b >= mp->m_sb.sb_rextents)
2384153323Srodrigc			b = do_mod(b, mp->m_sb.sb_rextents);
2385153323Srodrigc		if (b + len > mp->m_sb.sb_rextents)
2386153323Srodrigc			b = mp->m_sb.sb_rextents - len;
2387153323Srodrigc	}
2388153323Srodrigc	*seqp = seq + 1;
2389153323Srodrigc	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2390153323Srodrigc	*pick = b;
2391153323Srodrigc	return 0;
2392153323Srodrigc}
2393153323Srodrigc
2394153323Srodrigc#ifdef DEBUG
2395153323Srodrigc/*
2396153323Srodrigc * Debug code: print out the value of a range in the bitmap.
2397153323Srodrigc */
2398153323Srodrigcvoid
2399153323Srodrigcxfs_rtprint_range(
2400153323Srodrigc	xfs_mount_t	*mp,		/* file system mount structure */
2401153323Srodrigc	xfs_trans_t	*tp,		/* transaction pointer */
2402153323Srodrigc	xfs_rtblock_t	start,		/* starting block to print */
2403153323Srodrigc	xfs_extlen_t	len)		/* length to print */
2404153323Srodrigc{
2405153323Srodrigc	xfs_extlen_t	i;		/* block number in the extent */
2406153323Srodrigc
2407153323Srodrigc	printk("%Ld: ", (long long)start);
2408153323Srodrigc	for (i = 0; i < len; i++)
2409153323Srodrigc		printk("%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
2410153323Srodrigc	printk("\n");
2411153323Srodrigc}
2412153323Srodrigc
2413153323Srodrigc/*
2414153323Srodrigc * Debug code: print the summary file.
2415153323Srodrigc */
2416153323Srodrigcvoid
2417153323Srodrigcxfs_rtprint_summary(
2418153323Srodrigc	xfs_mount_t	*mp,		/* file system mount structure */
2419153323Srodrigc	xfs_trans_t	*tp)		/* transaction pointer */
2420153323Srodrigc{
2421153323Srodrigc	xfs_suminfo_t	c;		/* summary data */
2422153323Srodrigc	xfs_rtblock_t	i;		/* bitmap block number */
2423153323Srodrigc	int		l;		/* summary information level */
2424153323Srodrigc	int		p;		/* flag for printed anything */
2425153323Srodrigc	xfs_fsblock_t	sb;		/* summary block number */
2426153323Srodrigc	xfs_buf_t	*sumbp;		/* summary block buffer */
2427153323Srodrigc
2428153323Srodrigc	sumbp = NULL;
2429153323Srodrigc	for (l = 0; l < mp->m_rsumlevels; l++) {
2430153323Srodrigc		for (p = 0, i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
2431153323Srodrigc			(void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c);
2432153323Srodrigc			if (c) {
2433153323Srodrigc				if (!p) {
2434153323Srodrigc					printk("%Ld-%Ld:", 1LL << l,
2435153323Srodrigc						XFS_RTMIN((1LL << l) +
2436153323Srodrigc							  ((1LL << l) - 1LL),
2437153323Srodrigc							 mp->m_sb.sb_rextents));
2438153323Srodrigc					p = 1;
2439153323Srodrigc				}
2440153323Srodrigc				printk(" %Ld:%d", (long long)i, c);
2441153323Srodrigc			}
2442153323Srodrigc		}
2443153323Srodrigc		if (p)
2444153323Srodrigc			printk("\n");
2445153323Srodrigc	}
2446153323Srodrigc	if (sumbp)
2447153323Srodrigc		xfs_trans_brelse(tp, sumbp);
2448153323Srodrigc}
2449153323Srodrigc#endif	/* DEBUG */
2450