Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  3 * All Rights Reserved.
  4 *
  5 * This program is free software; you can redistribute it and/or
  6 * modify it under the terms of the GNU General Public License as
  7 * published by the Free Software Foundation.
  8 *
  9 * This program is distributed in the hope that it would be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 * GNU General Public License for more details.
 13 *
 14 * You should have received a copy of the GNU General Public License
 15 * along with this program; if not, write the Free Software Foundation,
 16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 17 */
 18#include "xfs.h"
 19#include "xfs_fs.h"
 20#include "xfs_shared.h"
 21#include "xfs_format.h"
 22#include "xfs_log_format.h"
 23#include "xfs_trans_resv.h"
 24#include "xfs_bit.h"
 25#include "xfs_sb.h"
 26#include "xfs_ag.h"
 27#include "xfs_mount.h"
 28#include "xfs_inode.h"
 29#include "xfs_bmap.h"
 30#include "xfs_bmap_util.h"
 31#include "xfs_bmap_btree.h"
 32#include "xfs_alloc.h"
 33#include "xfs_error.h"
 34#include "xfs_trans.h"
 35#include "xfs_trans_space.h"
 36#include "xfs_trace.h"
 37#include "xfs_buf.h"
 38#include "xfs_icache.h"
 39#include "xfs_dinode.h"
 40#include "xfs_rtalloc.h"
 41
 42
 43/*
 44 * Realtime allocator bitmap functions shared with userspace.
 45 */
 46
 47/*
 48 * Get a buffer for the bitmap or summary file block specified.
 49 * The buffer is returned read and locked.
 50 */
 51int
 52xfs_rtbuf_get(
 53	xfs_mount_t	*mp,		/* file system mount structure */
 54	xfs_trans_t	*tp,		/* transaction pointer */
 55	xfs_rtblock_t	block,		/* block number in bitmap or summary */
 56	int		issum,		/* is summary not bitmap */
 57	xfs_buf_t	**bpp)		/* output: buffer for the block */
 58{
 59	xfs_buf_t	*bp;		/* block buffer, result */
 60	xfs_inode_t	*ip;		/* bitmap or summary inode */
 61	xfs_bmbt_irec_t	map;
 62	int		nmap = 1;
 63	int		error;		/* error value */
 64
 65	ip = issum ? mp->m_rsumip : mp->m_rbmip;
 66
 67	error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
 68	if (error)
 69		return error;
 70
 71	ASSERT(map.br_startblock != NULLFSBLOCK);
 72	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 73				   XFS_FSB_TO_DADDR(mp, map.br_startblock),
 74				   mp->m_bsize, 0, &bp, NULL);
 75	if (error)
 76		return error;
 77	ASSERT(!xfs_buf_geterror(bp));
 78	*bpp = bp;
 79	return 0;
 80}
 81
 82/*
 83 * Searching backward from start to limit, find the first block whose
 84 * allocated/free state is different from start's.
 85 */
 86int
 87xfs_rtfind_back(
 88	xfs_mount_t	*mp,		/* file system mount point */
 89	xfs_trans_t	*tp,		/* transaction pointer */
 90	xfs_rtblock_t	start,		/* starting block to look at */
 91	xfs_rtblock_t	limit,		/* last block to look at */
 92	xfs_rtblock_t	*rtblock)	/* out: start block found */
 93{
 94	xfs_rtword_t	*b;		/* current word in buffer */
 95	int		bit;		/* bit number in the word */
 96	xfs_rtblock_t	block;		/* bitmap block number */
 97	xfs_buf_t	*bp;		/* buf for the block */
 98	xfs_rtword_t	*bufp;		/* starting word in buffer */
 99	int		error;		/* error value */
100	xfs_rtblock_t	firstbit;	/* first useful bit in the word */
101	xfs_rtblock_t	i;		/* current bit number rel. to start */
102	xfs_rtblock_t	len;		/* length of inspected area */
103	xfs_rtword_t	mask;		/* mask of relevant bits for value */
104	xfs_rtword_t	want;		/* mask for "good" values */
105	xfs_rtword_t	wdiff;		/* difference from wanted value */
106	int		word;		/* word number in the buffer */
107
108	/*
109	 * Compute and read in starting bitmap block for starting block.
110	 */
111	block = XFS_BITTOBLOCK(mp, start);
112	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
113	if (error) {
114		return error;
115	}
116	bufp = bp->b_addr;
117	/*
118	 * Get the first word's index & point to it.
119	 */
120	word = XFS_BITTOWORD(mp, start);
121	b = &bufp[word];
122	bit = (int)(start & (XFS_NBWORD - 1));
123	len = start - limit + 1;
124	/*
125	 * Compute match value, based on the bit at start: if 1 (free)
126	 * then all-ones, else all-zeroes.
127	 */
128	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
129	/*
130	 * If the starting position is not word-aligned, deal with the
131	 * partial word.
132	 */
133	if (bit < XFS_NBWORD - 1) {
134		/*
135		 * Calculate first (leftmost) bit number to look at,
136		 * and mask for all the relevant bits in this word.
137		 */
138		firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
139		mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
140			firstbit;
141		/*
142		 * Calculate the difference between the value there
143		 * and what we're looking for.
144		 */
145		if ((wdiff = (*b ^ want) & mask)) {
146			/*
147			 * Different.  Mark where we are and return.
148			 */
149			xfs_trans_brelse(tp, bp);
150			i = bit - XFS_RTHIBIT(wdiff);
151			*rtblock = start - i + 1;
152			return 0;
153		}
154		i = bit - firstbit + 1;
155		/*
156		 * Go on to previous block if that's where the previous word is
157		 * and we need the previous word.
158		 */
159		if (--word == -1 && i < len) {
160			/*
161			 * If done with this block, get the previous one.
162			 */
163			xfs_trans_brelse(tp, bp);
164			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
165			if (error) {
166				return error;
167			}
168			bufp = bp->b_addr;
169			word = XFS_BLOCKWMASK(mp);
170			b = &bufp[word];
171		} else {
172			/*
173			 * Go on to the previous word in the buffer.
174			 */
175			b--;
176		}
177	} else {
178		/*
179		 * Starting on a word boundary, no partial word.
180		 */
181		i = 0;
182	}
183	/*
184	 * Loop over whole words in buffers.  When we use up one buffer
185	 * we move on to the previous one.
186	 */
187	while (len - i >= XFS_NBWORD) {
188		/*
189		 * Compute difference between actual and desired value.
190		 */
191		if ((wdiff = *b ^ want)) {
192			/*
193			 * Different, mark where we are and return.
194			 */
195			xfs_trans_brelse(tp, bp);
196			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
197			*rtblock = start - i + 1;
198			return 0;
199		}
200		i += XFS_NBWORD;
201		/*
202		 * Go on to previous block if that's where the previous word is
203		 * and we need the previous word.
204		 */
205		if (--word == -1 && i < len) {
206			/*
207			 * If done with this block, get the previous one.
208			 */
209			xfs_trans_brelse(tp, bp);
210			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
211			if (error) {
212				return error;
213			}
214			bufp = bp->b_addr;
215			word = XFS_BLOCKWMASK(mp);
216			b = &bufp[word];
217		} else {
218			/*
219			 * Go on to the previous word in the buffer.
220			 */
221			b--;
222		}
223	}
224	/*
225	 * If not ending on a word boundary, deal with the last
226	 * (partial) word.
227	 */
228	if (len - i) {
229		/*
230		 * Calculate first (leftmost) bit number to look at,
231		 * and mask for all the relevant bits in this word.
232		 */
233		firstbit = XFS_NBWORD - (len - i);
234		mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
235		/*
236		 * Compute difference between actual and desired value.
237		 */
238		if ((wdiff = (*b ^ want) & mask)) {
239			/*
240			 * Different, mark where we are and return.
241			 */
242			xfs_trans_brelse(tp, bp);
243			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
244			*rtblock = start - i + 1;
245			return 0;
246		} else
247			i = len;
248	}
249	/*
250	 * No match, return that we scanned the whole area.
251	 */
252	xfs_trans_brelse(tp, bp);
253	*rtblock = start - i + 1;
254	return 0;
255}
256
257/*
258 * Searching forward from start to limit, find the first block whose
259 * allocated/free state is different from start's.
260 */
261int
262xfs_rtfind_forw(
263	xfs_mount_t	*mp,		/* file system mount point */
264	xfs_trans_t	*tp,		/* transaction pointer */
265	xfs_rtblock_t	start,		/* starting block to look at */
266	xfs_rtblock_t	limit,		/* last block to look at */
267	xfs_rtblock_t	*rtblock)	/* out: start block found */
268{
269	xfs_rtword_t	*b;		/* current word in buffer */
270	int		bit;		/* bit number in the word */
271	xfs_rtblock_t	block;		/* bitmap block number */
272	xfs_buf_t	*bp;		/* buf for the block */
273	xfs_rtword_t	*bufp;		/* starting word in buffer */
274	int		error;		/* error value */
275	xfs_rtblock_t	i;		/* current bit number rel. to start */
276	xfs_rtblock_t	lastbit;	/* last useful bit in the word */
277	xfs_rtblock_t	len;		/* length of inspected area */
278	xfs_rtword_t	mask;		/* mask of relevant bits for value */
279	xfs_rtword_t	want;		/* mask for "good" values */
280	xfs_rtword_t	wdiff;		/* difference from wanted value */
281	int		word;		/* word number in the buffer */
282
283	/*
284	 * Compute and read in starting bitmap block for starting block.
285	 */
286	block = XFS_BITTOBLOCK(mp, start);
287	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
288	if (error) {
289		return error;
290	}
291	bufp = bp->b_addr;
292	/*
293	 * Get the first word's index & point to it.
294	 */
295	word = XFS_BITTOWORD(mp, start);
296	b = &bufp[word];
297	bit = (int)(start & (XFS_NBWORD - 1));
298	len = limit - start + 1;
299	/*
300	 * Compute match value, based on the bit at start: if 1 (free)
301	 * then all-ones, else all-zeroes.
302	 */
303	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
304	/*
305	 * If the starting position is not word-aligned, deal with the
306	 * partial word.
307	 */
308	if (bit) {
309		/*
310		 * Calculate last (rightmost) bit number to look at,
311		 * and mask for all the relevant bits in this word.
312		 */
313		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
314		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
315		/*
316		 * Calculate the difference between the value there
317		 * and what we're looking for.
318		 */
319		if ((wdiff = (*b ^ want) & mask)) {
320			/*
321			 * Different.  Mark where we are and return.
322			 */
323			xfs_trans_brelse(tp, bp);
324			i = XFS_RTLOBIT(wdiff) - bit;
325			*rtblock = start + i - 1;
326			return 0;
327		}
328		i = lastbit - bit;
329		/*
330		 * Go on to next block if that's where the next word is
331		 * and we need the next word.
332		 */
333		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
334			/*
335			 * If done with this block, get the previous one.
336			 */
337			xfs_trans_brelse(tp, bp);
338			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
339			if (error) {
340				return error;
341			}
342			b = bufp = bp->b_addr;
343			word = 0;
344		} else {
345			/*
346			 * Go on to the previous word in the buffer.
347			 */
348			b++;
349		}
350	} else {
351		/*
352		 * Starting on a word boundary, no partial word.
353		 */
354		i = 0;
355	}
356	/*
357	 * Loop over whole words in buffers.  When we use up one buffer
358	 * we move on to the next one.
359	 */
360	while (len - i >= XFS_NBWORD) {
361		/*
362		 * Compute difference between actual and desired value.
363		 */
364		if ((wdiff = *b ^ want)) {
365			/*
366			 * Different, mark where we are and return.
367			 */
368			xfs_trans_brelse(tp, bp);
369			i += XFS_RTLOBIT(wdiff);
370			*rtblock = start + i - 1;
371			return 0;
372		}
373		i += XFS_NBWORD;
374		/*
375		 * Go on to next block if that's where the next word is
376		 * and we need the next word.
377		 */
378		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
379			/*
380			 * If done with this block, get the next one.
381			 */
382			xfs_trans_brelse(tp, bp);
383			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
384			if (error) {
385				return error;
386			}
387			b = bufp = bp->b_addr;
388			word = 0;
389		} else {
390			/*
391			 * Go on to the next word in the buffer.
392			 */
393			b++;
394		}
395	}
396	/*
397	 * If not ending on a word boundary, deal with the last
398	 * (partial) word.
399	 */
400	if ((lastbit = len - i)) {
401		/*
402		 * Calculate mask for all the relevant bits in this word.
403		 */
404		mask = ((xfs_rtword_t)1 << lastbit) - 1;
405		/*
406		 * Compute difference between actual and desired value.
407		 */
408		if ((wdiff = (*b ^ want) & mask)) {
409			/*
410			 * Different, mark where we are and return.
411			 */
412			xfs_trans_brelse(tp, bp);
413			i += XFS_RTLOBIT(wdiff);
414			*rtblock = start + i - 1;
415			return 0;
416		} else
417			i = len;
418	}
419	/*
420	 * No match, return that we scanned the whole area.
421	 */
422	xfs_trans_brelse(tp, bp);
423	*rtblock = start + i - 1;
424	return 0;
425}
426
427/*
428 * Read and modify the summary information for a given extent size,
429 * bitmap block combination.
430 * Keeps track of a current summary block, so we don't keep reading
431 * it from the buffer cache.
432 */
433int
434xfs_rtmodify_summary(
435	xfs_mount_t	*mp,		/* file system mount point */
436	xfs_trans_t	*tp,		/* transaction pointer */
437	int		log,		/* log2 of extent size */
438	xfs_rtblock_t	bbno,		/* bitmap block number */
439	int		delta,		/* change to make to summary info */
440	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
441	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
442{
443	xfs_buf_t	*bp;		/* buffer for the summary block */
444	int		error;		/* error value */
445	xfs_fsblock_t	sb;		/* summary fsblock */
446	int		so;		/* index into the summary file */
447	xfs_suminfo_t	*sp;		/* pointer to returned data */
448
449	/*
450	 * Compute entry number in the summary file.
451	 */
452	so = XFS_SUMOFFS(mp, log, bbno);
453	/*
454	 * Compute the block number in the summary file.
455	 */
456	sb = XFS_SUMOFFSTOBLOCK(mp, so);
457	/*
458	 * If we have an old buffer, and the block number matches, use that.
459	 */
460	if (rbpp && *rbpp && *rsb == sb)
461		bp = *rbpp;
462	/*
463	 * Otherwise we have to get the buffer.
464	 */
465	else {
466		/*
467		 * If there was an old one, get rid of it first.
468		 */
469		if (rbpp && *rbpp)
470			xfs_trans_brelse(tp, *rbpp);
471		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
472		if (error) {
473			return error;
474		}
475		/*
476		 * Remember this buffer and block for the next call.
477		 */
478		if (rbpp) {
479			*rbpp = bp;
480			*rsb = sb;
481		}
482	}
483	/*
484	 * Point to the summary information, modify and log it.
485	 */
486	sp = XFS_SUMPTR(mp, bp, so);
487	*sp += delta;
488	xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
489		(uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
490	return 0;
491}
492
493/*
494 * Set the given range of bitmap bits to the given value.
495 * Do whatever I/O and logging is required.
496 */
497int
498xfs_rtmodify_range(
499	xfs_mount_t	*mp,		/* file system mount point */
500	xfs_trans_t	*tp,		/* transaction pointer */
501	xfs_rtblock_t	start,		/* starting block to modify */
502	xfs_extlen_t	len,		/* length of extent to modify */
503	int		val)		/* 1 for free, 0 for allocated */
504{
505	xfs_rtword_t	*b;		/* current word in buffer */
506	int		bit;		/* bit number in the word */
507	xfs_rtblock_t	block;		/* bitmap block number */
508	xfs_buf_t	*bp;		/* buf for the block */
509	xfs_rtword_t	*bufp;		/* starting word in buffer */
510	int		error;		/* error value */
511	xfs_rtword_t	*first;		/* first used word in the buffer */
512	int		i;		/* current bit number rel. to start */
513	int		lastbit;	/* last useful bit in word */
514	xfs_rtword_t	mask;		/* mask o frelevant bits for value */
515	int		word;		/* word number in the buffer */
516
517	/*
518	 * Compute starting bitmap block number.
519	 */
520	block = XFS_BITTOBLOCK(mp, start);
521	/*
522	 * Read the bitmap block, and point to its data.
523	 */
524	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
525	if (error) {
526		return error;
527	}
528	bufp = bp->b_addr;
529	/*
530	 * Compute the starting word's address, and starting bit.
531	 */
532	word = XFS_BITTOWORD(mp, start);
533	first = b = &bufp[word];
534	bit = (int)(start & (XFS_NBWORD - 1));
535	/*
536	 * 0 (allocated) => all zeroes; 1 (free) => all ones.
537	 */
538	val = -val;
539	/*
540	 * If not starting on a word boundary, deal with the first
541	 * (partial) word.
542	 */
543	if (bit) {
544		/*
545		 * Compute first bit not changed and mask of relevant bits.
546		 */
547		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
548		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
549		/*
550		 * Set/clear the active bits.
551		 */
552		if (val)
553			*b |= mask;
554		else
555			*b &= ~mask;
556		i = lastbit - bit;
557		/*
558		 * Go on to the next block if that's where the next word is
559		 * and we need the next word.
560		 */
561		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
562			/*
563			 * Log the changed part of this block.
564			 * Get the next one.
565			 */
566			xfs_trans_log_buf(tp, bp,
567				(uint)((char *)first - (char *)bufp),
568				(uint)((char *)b - (char *)bufp));
569			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
570			if (error) {
571				return error;
572			}
573			first = b = bufp = bp->b_addr;
574			word = 0;
575		} else {
576			/*
577			 * Go on to the next word in the buffer
578			 */
579			b++;
580		}
581	} else {
582		/*
583		 * Starting on a word boundary, no partial word.
584		 */
585		i = 0;
586	}
587	/*
588	 * Loop over whole words in buffers.  When we use up one buffer
589	 * we move on to the next one.
590	 */
591	while (len - i >= XFS_NBWORD) {
592		/*
593		 * Set the word value correctly.
594		 */
595		*b = val;
596		i += XFS_NBWORD;
597		/*
598		 * Go on to the next block if that's where the next word is
599		 * and we need the next word.
600		 */
601		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
602			/*
603			 * Log the changed part of this block.
604			 * Get the next one.
605			 */
606			xfs_trans_log_buf(tp, bp,
607				(uint)((char *)first - (char *)bufp),
608				(uint)((char *)b - (char *)bufp));
609			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
610			if (error) {
611				return error;
612			}
613			first = b = bufp = bp->b_addr;
614			word = 0;
615		} else {
616			/*
617			 * Go on to the next word in the buffer
618			 */
619			b++;
620		}
621	}
622	/*
623	 * If not ending on a word boundary, deal with the last
624	 * (partial) word.
625	 */
626	if ((lastbit = len - i)) {
627		/*
628		 * Compute a mask of relevant bits.
629		 */
630		bit = 0;
631		mask = ((xfs_rtword_t)1 << lastbit) - 1;
632		/*
633		 * Set/clear the active bits.
634		 */
635		if (val)
636			*b |= mask;
637		else
638			*b &= ~mask;
639		b++;
640	}
641	/*
642	 * Log any remaining changed bytes.
643	 */
644	if (b > first)
645		xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
646			(uint)((char *)b - (char *)bufp - 1));
647	return 0;
648}
649
650/*
651 * Mark an extent specified by start and len freed.
652 * Updates all the summary information as well as the bitmap.
653 */
654int
655xfs_rtfree_range(
656	xfs_mount_t	*mp,		/* file system mount point */
657	xfs_trans_t	*tp,		/* transaction pointer */
658	xfs_rtblock_t	start,		/* starting block to free */
659	xfs_extlen_t	len,		/* length to free */
660	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
661	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
662{
663	xfs_rtblock_t	end;		/* end of the freed extent */
664	int		error;		/* error value */
665	xfs_rtblock_t	postblock;	/* first block freed > end */
666	xfs_rtblock_t	preblock;	/* first block freed < start */
667
668	end = start + len - 1;
669	/*
670	 * Modify the bitmap to mark this extent freed.
671	 */
672	error = xfs_rtmodify_range(mp, tp, start, len, 1);
673	if (error) {
674		return error;
675	}
676	/*
677	 * Assume we're freeing out of the middle of an allocated extent.
678	 * We need to find the beginning and end of the extent so we can
679	 * properly update the summary.
680	 */
681	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
682	if (error) {
683		return error;
684	}
685	/*
686	 * Find the next allocated block (end of allocated extent).
687	 */
688	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
689		&postblock);
690	if (error)
691		return error;
692	/*
693	 * If there are blocks not being freed at the front of the
694	 * old extent, add summary data for them to be allocated.
695	 */
696	if (preblock < start) {
697		error = xfs_rtmodify_summary(mp, tp,
698			XFS_RTBLOCKLOG(start - preblock),
699			XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
700		if (error) {
701			return error;
702		}
703	}
704	/*
705	 * If there are blocks not being freed at the end of the
706	 * old extent, add summary data for them to be allocated.
707	 */
708	if (postblock > end) {
709		error = xfs_rtmodify_summary(mp, tp,
710			XFS_RTBLOCKLOG(postblock - end),
711			XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
712		if (error) {
713			return error;
714		}
715	}
716	/*
717	 * Increment the summary information corresponding to the entire
718	 * (new) free extent.
719	 */
720	error = xfs_rtmodify_summary(mp, tp,
721		XFS_RTBLOCKLOG(postblock + 1 - preblock),
722		XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
723	return error;
724}
725
726/*
727 * Check that the given range is either all allocated (val = 0) or
728 * all free (val = 1).
729 */
730int
731xfs_rtcheck_range(
732	xfs_mount_t	*mp,		/* file system mount point */
733	xfs_trans_t	*tp,		/* transaction pointer */
734	xfs_rtblock_t	start,		/* starting block number of extent */
735	xfs_extlen_t	len,		/* length of extent */
736	int		val,		/* 1 for free, 0 for allocated */
737	xfs_rtblock_t	*new,		/* out: first block not matching */
738	int		*stat)		/* out: 1 for matches, 0 for not */
739{
740	xfs_rtword_t	*b;		/* current word in buffer */
741	int		bit;		/* bit number in the word */
742	xfs_rtblock_t	block;		/* bitmap block number */
743	xfs_buf_t	*bp;		/* buf for the block */
744	xfs_rtword_t	*bufp;		/* starting word in buffer */
745	int		error;		/* error value */
746	xfs_rtblock_t	i;		/* current bit number rel. to start */
747	xfs_rtblock_t	lastbit;	/* last useful bit in word */
748	xfs_rtword_t	mask;		/* mask of relevant bits for value */
749	xfs_rtword_t	wdiff;		/* difference from wanted value */
750	int		word;		/* word number in the buffer */
751
752	/*
753	 * Compute starting bitmap block number
754	 */
755	block = XFS_BITTOBLOCK(mp, start);
756	/*
757	 * Read the bitmap block.
758	 */
759	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
760	if (error) {
761		return error;
762	}
763	bufp = bp->b_addr;
764	/*
765	 * Compute the starting word's address, and starting bit.
766	 */
767	word = XFS_BITTOWORD(mp, start);
768	b = &bufp[word];
769	bit = (int)(start & (XFS_NBWORD - 1));
770	/*
771	 * 0 (allocated) => all zero's; 1 (free) => all one's.
772	 */
773	val = -val;
774	/*
775	 * If not starting on a word boundary, deal with the first
776	 * (partial) word.
777	 */
778	if (bit) {
779		/*
780		 * Compute first bit not examined.
781		 */
782		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
783		/*
784		 * Mask of relevant bits.
785		 */
786		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
787		/*
788		 * Compute difference between actual and desired value.
789		 */
790		if ((wdiff = (*b ^ val) & mask)) {
791			/*
792			 * Different, compute first wrong bit and return.
793			 */
794			xfs_trans_brelse(tp, bp);
795			i = XFS_RTLOBIT(wdiff) - bit;
796			*new = start + i;
797			*stat = 0;
798			return 0;
799		}
800		i = lastbit - bit;
801		/*
802		 * Go on to next block if that's where the next word is
803		 * and we need the next word.
804		 */
805		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
806			/*
807			 * If done with this block, get the next one.
808			 */
809			xfs_trans_brelse(tp, bp);
810			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
811			if (error) {
812				return error;
813			}
814			b = bufp = bp->b_addr;
815			word = 0;
816		} else {
817			/*
818			 * Go on to the next word in the buffer.
819			 */
820			b++;
821		}
822	} else {
823		/*
824		 * Starting on a word boundary, no partial word.
825		 */
826		i = 0;
827	}
828	/*
829	 * Loop over whole words in buffers.  When we use up one buffer
830	 * we move on to the next one.
831	 */
832	while (len - i >= XFS_NBWORD) {
833		/*
834		 * Compute difference between actual and desired value.
835		 */
836		if ((wdiff = *b ^ val)) {
837			/*
838			 * Different, compute first wrong bit and return.
839			 */
840			xfs_trans_brelse(tp, bp);
841			i += XFS_RTLOBIT(wdiff);
842			*new = start + i;
843			*stat = 0;
844			return 0;
845		}
846		i += XFS_NBWORD;
847		/*
848		 * Go on to next block if that's where the next word is
849		 * and we need the next word.
850		 */
851		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
852			/*
853			 * If done with this block, get the next one.
854			 */
855			xfs_trans_brelse(tp, bp);
856			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
857			if (error) {
858				return error;
859			}
860			b = bufp = bp->b_addr;
861			word = 0;
862		} else {
863			/*
864			 * Go on to the next word in the buffer.
865			 */
866			b++;
867		}
868	}
869	/*
870	 * If not ending on a word boundary, deal with the last
871	 * (partial) word.
872	 */
873	if ((lastbit = len - i)) {
874		/*
875		 * Mask of relevant bits.
876		 */
877		mask = ((xfs_rtword_t)1 << lastbit) - 1;
878		/*
879		 * Compute difference between actual and desired value.
880		 */
881		if ((wdiff = (*b ^ val) & mask)) {
882			/*
883			 * Different, compute first wrong bit and return.
884			 */
885			xfs_trans_brelse(tp, bp);
886			i += XFS_RTLOBIT(wdiff);
887			*new = start + i;
888			*stat = 0;
889			return 0;
890		} else
891			i = len;
892	}
893	/*
894	 * Successful, return.
895	 */
896	xfs_trans_brelse(tp, bp);
897	*new = start + i;
898	*stat = 1;
899	return 0;
900}
901
902#ifdef DEBUG
903/*
904 * Check that the given extent (block range) is allocated already.
905 */
906STATIC int				/* error */
907xfs_rtcheck_alloc_range(
908	xfs_mount_t	*mp,		/* file system mount point */
909	xfs_trans_t	*tp,		/* transaction pointer */
910	xfs_rtblock_t	bno,		/* starting block number of extent */
911	xfs_extlen_t	len)		/* length of extent */
912{
913	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
914	int		stat;
915	int		error;
916
917	error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
918	if (error)
919		return error;
920	ASSERT(stat);
921	return 0;
922}
923#else
924#define xfs_rtcheck_alloc_range(m,t,b,l)	(0)
925#endif
926/*
927 * Free an extent in the realtime subvolume.  Length is expressed in
928 * realtime extents, as is the block number.
929 */
930int					/* error */
931xfs_rtfree_extent(
932	xfs_trans_t	*tp,		/* transaction pointer */
933	xfs_rtblock_t	bno,		/* starting block number to free */
934	xfs_extlen_t	len)		/* length of extent freed */
935{
936	int		error;		/* error value */
937	xfs_mount_t	*mp;		/* file system mount structure */
938	xfs_fsblock_t	sb;		/* summary file block number */
939	xfs_buf_t	*sumbp = NULL;	/* summary file block buffer */
940
941	mp = tp->t_mountp;
942
943	ASSERT(mp->m_rbmip->i_itemp != NULL);
944	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
945
946	error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
947	if (error)
948		return error;
949
950	/*
951	 * Free the range of realtime blocks.
952	 */
953	error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
954	if (error) {
955		return error;
956	}
957	/*
958	 * Mark more blocks free in the superblock.
959	 */
960	xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
961	/*
962	 * If we've now freed all the blocks, reset the file sequence
963	 * number to 0.
964	 */
965	if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
966	    mp->m_sb.sb_rextents) {
967		if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
968			mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
969		*(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
970		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
971	}
972	return 0;
973}
974