Blame view

fs/xfs/xfs_rtalloc.c 36.1 KB
0b61f8a40   Dave Chinner   xfs: convert to S...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
7b7187698   Nathan Scott   [XFS] Update lice...
3
4
   * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
  #include "xfs.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
7
  #include "xfs_fs.h"
70a9883c5   Dave Chinner   xfs: create a sha...
8
  #include "xfs_shared.h"
239880ef6   Dave Chinner   xfs: decouple log...
9
10
11
  #include "xfs_format.h"
  #include "xfs_log_format.h"
  #include "xfs_trans_resv.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
12
  #include "xfs_bit.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #include "xfs_mount.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include "xfs_inode.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include "xfs_bmap.h"
a4fbe6ab1   Dave Chinner   xfs: decouple ino...
16
  #include "xfs_bmap_btree.h"
239880ef6   Dave Chinner   xfs: decouple log...
17
  #include "xfs_trans.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include "xfs_trans_space.h"
33479e054   Dave Chinner   xfs: remove xfs_i...
19
  #include "xfs_icache.h"
c963c6193   Dave Chinner   xfs: split xfs_rt...
20
  #include "xfs_rtalloc.h"
7249c95a3   Darrick J. Wong   xfs: make xfs_gro...
21
  #include "xfs_sb.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
  
  /*
c963c6193   Dave Chinner   xfs: split xfs_rt...
24
25
26
27
   * Read and return the summary information for a given extent size,
   * bitmap block combination.
   * Keeps track of a current summary block, so we don't keep reading
   * it from the buffer cache.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
   */
ea95961df   Fengguang Wu   xfs: xfs_rtget_su...
29
  static int
c963c6193   Dave Chinner   xfs: split xfs_rt...
30
31
32
33
34
35
36
37
  xfs_rtget_summary(
  	xfs_mount_t	*mp,		/* file system mount structure */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	int		log,		/* log2 of extent size */
  	xfs_rtblock_t	bbno,		/* bitmap block number */
  	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
  	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
  	xfs_suminfo_t	*sum)		/* out: summary info for this block */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  {
afabfd30d   Eric Sandeen   xfs: combine xfs_...
39
  	return xfs_rtmodify_summary_int(mp, tp, log, bbno, 0, rbpp, rsb, sum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
  }
  
  /*
c963c6193   Dave Chinner   xfs: split xfs_rt...
43
44
   * Return whether there are any free extents in the size range given
   * by low and high, for the bitmap block bbno.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
   */
  STATIC int				/* error */
c963c6193   Dave Chinner   xfs: split xfs_rt...
47
48
  xfs_rtany_summary(
  	xfs_mount_t	*mp,		/* file system mount structure */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  	xfs_trans_t	*tp,		/* transaction pointer */
c963c6193   Dave Chinner   xfs: split xfs_rt...
50
51
  	int		low,		/* low log2 extent size */
  	int		high,		/* high log2 extent size */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  	xfs_rtblock_t	bbno,		/* bitmap block number */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
  	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
  	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
c963c6193   Dave Chinner   xfs: split xfs_rt...
55
  	int		*stat)		/* out: any good extents here? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  	int		error;		/* error value */
c963c6193   Dave Chinner   xfs: split xfs_rt...
58
59
  	int		log;		/* loop counter, log2 of ext. size */
  	xfs_suminfo_t	sum;		/* summary data */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60

355e35321   Omar Sandoval   xfs: cache minimu...
61
62
63
  	/* There are no extents at levels < m_rsum_cache[bbno]. */
  	if (mp->m_rsum_cache && low < mp->m_rsum_cache[bbno])
  		low = mp->m_rsum_cache[bbno];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  	/*
355e35321   Omar Sandoval   xfs: cache minimu...
65
  	 * Loop over logs of extent sizes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  	 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
67
  	for (log = low; log <= high; log++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  		/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
69
  		 * Get one summary datum.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  		 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
71
  		error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
  		if (error) {
  			return error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  		/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
76
  		 * If there are any, return success.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  		 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
78
79
  		if (sum) {
  			*stat = 1;
355e35321   Omar Sandoval   xfs: cache minimu...
80
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
  	}
  	/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
84
  	 * Found nothing, return failure.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  	 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
86
  	*stat = 0;
355e35321   Omar Sandoval   xfs: cache minimu...
87
88
89
90
  out:
  	/* There were no extents at levels < log. */
  	if (mp->m_rsum_cache && log > mp->m_rsum_cache[bbno])
  		mp->m_rsum_cache[bbno] = log;
c963c6193   Dave Chinner   xfs: split xfs_rt...
91
92
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93

c963c6193   Dave Chinner   xfs: split xfs_rt...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  
  /*
   * Copy and transform the summary file, given the old and new
   * parameters in the mount structures.
   */
  STATIC int				/* error */
  xfs_rtcopy_summary(
  	xfs_mount_t	*omp,		/* old file system mount point */
  	xfs_mount_t	*nmp,		/* new file system mount point */
  	xfs_trans_t	*tp)		/* transaction pointer */
  {
  	xfs_rtblock_t	bbno;		/* bitmap block number */
  	xfs_buf_t	*bp;		/* summary buffer */
  	int		error;		/* error return value */
  	int		log;		/* summary level number (log length) */
  	xfs_suminfo_t	sum;		/* summary data */
  	xfs_fsblock_t	sumbno;		/* summary block number */
  
  	bp = NULL;
  	for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
  		for (bbno = omp->m_sb.sb_rbmblocks - 1;
  		     (xfs_srtblock_t)bbno >= 0;
  		     bbno--) {
  			error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
  				&sumbno, &sum);
  			if (error)
  				return error;
  			if (sum == 0)
  				continue;
  			error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
  				&bp, &sumbno);
  			if (error)
  				return error;
  			error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
  				&bp, &sumbno);
  			if (error)
  				return error;
  			ASSERT(sum > 0);
  		}
  	}
  	return 0;
  }
  /*
   * Mark an extent specified by start and len allocated.
   * Updates all the summary information as well as the bitmap.
   */
  STATIC int				/* error */
  xfs_rtallocate_range(
  	xfs_mount_t	*mp,		/* file system mount point */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_rtblock_t	start,		/* start block to allocate */
  	xfs_extlen_t	len,		/* length to allocate */
  	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
  	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
  {
  	xfs_rtblock_t	end;		/* end of the allocated extent */
  	int		error;		/* error value */
  	xfs_rtblock_t	postblock = 0;	/* first block allocated > end */
  	xfs_rtblock_t	preblock = 0;	/* first block allocated < start */
  
  	end = start + len - 1;
  	/*
  	 * Assume we're allocating out of the middle of a free extent.
  	 * We need to find the beginning and end of the extent so we can
  	 * properly update the summary.
  	 */
  	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
  	if (error) {
  		return error;
  	}
  	/*
  	 * Find the next allocated block (end of free extent).
  	 */
  	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
  		&postblock);
  	if (error) {
  		return error;
  	}
  	/*
  	 * Decrement the summary information corresponding to the entire
  	 * (old) free extent.
  	 */
  	error = xfs_rtmodify_summary(mp, tp,
  		XFS_RTBLOCKLOG(postblock + 1 - preblock),
  		XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
  	if (error) {
  		return error;
  	}
  	/*
  	 * If there are blocks not being allocated at the front of the
  	 * old extent, add summary data for them to be free.
  	 */
  	if (preblock < start) {
  		error = xfs_rtmodify_summary(mp, tp,
  			XFS_RTBLOCKLOG(start - preblock),
  			XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
  		if (error) {
  			return error;
  		}
  	}
  	/*
  	 * If there are blocks not being allocated at the end of the
  	 * old extent, add summary data for them to be free.
  	 */
  	if (postblock > end) {
  		error = xfs_rtmodify_summary(mp, tp,
  			XFS_RTBLOCKLOG(postblock - end),
  			XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
  		if (error) {
  			return error;
  		}
  	}
  	/*
  	 * Modify the bitmap to mark this extent allocated.
  	 */
  	error = xfs_rtmodify_range(mp, tp, start, len, 0);
  	return error;
  }
  
  /*
   * Attempt to allocate an extent minlen<=len<=maxlen starting from
   * bitmap block bbno.  If we don't get maxlen then use prod to trim
   * the length, if given.  Returns error; returns starting block in *rtblock.
   * The lengths are all in rtextents.
   */
  STATIC int				/* error */
  xfs_rtallocate_extent_block(
  	xfs_mount_t	*mp,		/* file system mount point */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_rtblock_t	bbno,		/* bitmap block number */
  	xfs_extlen_t	minlen,		/* minimum length to allocate */
  	xfs_extlen_t	maxlen,		/* maximum length to allocate */
  	xfs_extlen_t	*len,		/* out: actual length allocated */
  	xfs_rtblock_t	*nextp,		/* out: next block to try */
  	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
  	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
  	xfs_extlen_t	prod,		/* extent product factor */
  	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
  {
  	xfs_rtblock_t	besti;		/* best rtblock found so far */
  	xfs_rtblock_t	bestlen;	/* best length found so far */
  	xfs_rtblock_t	end;		/* last rtblock in chunk */
  	int		error;		/* error value */
  	xfs_rtblock_t	i;		/* current rtblock trying */
  	xfs_rtblock_t	next;		/* next rtblock to try */
  	int		stat;		/* status from internal calls */
  
  	/*
  	 * Loop over all the extents starting in this bitmap block,
  	 * looking for one that's long enough.
  	 */
  	for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0,
  		end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1;
  	     i <= end;
  	     i++) {
2a6ca4bae   Darrick J. Wong   xfs: make sure th...
249
250
  		/* Make sure we don't scan off the end of the rt volume. */
  		maxlen = min(mp->m_sb.sb_rextents, i + maxlen) - i;
c963c6193   Dave Chinner   xfs: split xfs_rt...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  		/*
  		 * See if there's a free extent of maxlen starting at i.
  		 * If it's not so then next will contain the first non-free.
  		 */
  		error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat);
  		if (error) {
  			return error;
  		}
  		if (stat) {
  			/*
  			 * i for maxlen is all free, allocate and return that.
  			 */
  			error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp,
  				rsb);
  			if (error) {
  				return error;
  			}
  			*len = maxlen;
  			*rtblock = i;
  			return 0;
  		}
  		/*
  		 * In the case where we have a variable-sized allocation
  		 * request, figure out how big this free piece is,
  		 * and if it's big enough for the minimum, and the best
  		 * so far, remember it.
  		 */
  		if (minlen < maxlen) {
  			xfs_rtblock_t	thislen;	/* this extent size */
  
  			thislen = next - i;
  			if (thislen >= minlen && thislen > bestlen) {
  				besti = i;
  				bestlen = thislen;
  			}
  		}
  		/*
  		 * If not done yet, find the start of the next free space.
  		 */
  		if (next < end) {
  			error = xfs_rtfind_forw(mp, tp, next, end, &i);
  			if (error) {
  				return error;
  			}
  		} else
  			break;
  	}
  	/*
  	 * Searched the whole thing & didn't find a maxlen free extent.
  	 */
  	if (minlen < maxlen && besti != -1) {
  		xfs_extlen_t	p;	/* amount to trim length by */
  
  		/*
  		 * If size should be a multiple of prod, make that so.
  		 */
0703a8e1c   Dave Chinner   xfs: replace do_m...
307
308
309
310
311
  		if (prod > 1) {
  			div_u64_rem(bestlen, prod, &p);
  			if (p)
  				bestlen -= p;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  		/*
  		 * Allocate besti for bestlen & return that.
  		 */
  		error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb);
  		if (error) {
  			return error;
  		}
  		*len = bestlen;
  		*rtblock = besti;
  		return 0;
  	}
  	/*
  	 * Allocation failed.  Set *nextp to the next block to try.
  	 */
  	*nextp = next;
  	*rtblock = NULLRTBLOCK;
  	return 0;
  }
  
  /*
   * Allocate an extent of length minlen<=len<=maxlen, starting at block
   * bno.  If we don't get maxlen then use prod to trim the length, if given.
   * Returns error; returns starting block in *rtblock.
   * The lengths are all in rtextents.
   */
  STATIC int				/* error */
  xfs_rtallocate_extent_exact(
  	xfs_mount_t	*mp,		/* file system mount point */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_rtblock_t	bno,		/* starting block number to allocate */
  	xfs_extlen_t	minlen,		/* minimum length to allocate */
  	xfs_extlen_t	maxlen,		/* maximum length to allocate */
  	xfs_extlen_t	*len,		/* out: actual length allocated */
  	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
  	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
  	xfs_extlen_t	prod,		/* extent product factor */
  	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
  {
  	int		error;		/* error value */
  	xfs_extlen_t	i;		/* extent length trimmed due to prod */
  	int		isfree;		/* extent is free */
  	xfs_rtblock_t	next;		/* next block to try (dummy) */
  
  	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
  	/*
  	 * Check if the range in question (for maxlen) is free.
  	 */
  	error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree);
  	if (error) {
  		return error;
  	}
  	if (isfree) {
  		/*
  		 * If it is, allocate it and return success.
  		 */
  		error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
  		if (error) {
  			return error;
  		}
  		*len = maxlen;
  		*rtblock = bno;
  		return 0;
  	}
  	/*
  	 * If not, allocate what there is, if it's at least minlen.
  	 */
  	maxlen = next - bno;
  	if (maxlen < minlen) {
  		/*
  		 * Failed, return failure status.
  		 */
  		*rtblock = NULLRTBLOCK;
  		return 0;
  	}
  	/*
  	 * Trim off tail of extent, if prod is specified.
  	 */
  	if (prod > 1 && (i = maxlen % prod)) {
  		maxlen -= i;
  		if (maxlen < minlen) {
  			/*
  			 * Now we can't do it, return failure status.
  			 */
  			*rtblock = NULLRTBLOCK;
  			return 0;
  		}
  	}
  	/*
  	 * Allocate what we can and return it.
  	 */
  	error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
  	if (error) {
  		return error;
  	}
  	*len = maxlen;
  	*rtblock = bno;
  	return 0;
  }
  
  /*
   * Allocate an extent of length minlen<=len<=maxlen, starting as near
   * to bno as possible.  If we don't get maxlen then use prod to trim
   * the length, if given.  The lengths are all in rtextents.
   */
  STATIC int				/* error */
  xfs_rtallocate_extent_near(
  	xfs_mount_t	*mp,		/* file system mount point */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_rtblock_t	bno,		/* starting block number to allocate */
  	xfs_extlen_t	minlen,		/* minimum length to allocate */
  	xfs_extlen_t	maxlen,		/* maximum length to allocate */
  	xfs_extlen_t	*len,		/* out: actual length allocated */
  	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
  	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
  	xfs_extlen_t	prod,		/* extent product factor */
  	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
  {
  	int		any;		/* any useful extents from summary */
  	xfs_rtblock_t	bbno;		/* bitmap block number */
  	int		error;		/* error value */
  	int		i;		/* bitmap block offset (loop control) */
  	int		j;		/* secondary loop control */
  	int		log2len;	/* log2 of minlen */
  	xfs_rtblock_t	n;		/* next block to try */
  	xfs_rtblock_t	r;		/* result block */
  
  	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
  	/*
  	 * If the block number given is off the end, silently set it to
  	 * the last block.
  	 */
  	if (bno >= mp->m_sb.sb_rextents)
  		bno = mp->m_sb.sb_rextents - 1;
2a6ca4bae   Darrick J. Wong   xfs: make sure th...
445
446
447
448
449
450
451
  
  	/* Make sure we don't run off the end of the rt volume. */
  	maxlen = min(mp->m_sb.sb_rextents, bno + maxlen) - bno;
  	if (maxlen < minlen) {
  		*rtblock = NULLRTBLOCK;
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  	/*
  	 * Try the exact allocation first.
  	 */
  	error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len,
  		rbpp, rsb, prod, &r);
  	if (error) {
  		return error;
  	}
  	/*
  	 * If the exact allocation worked, return that.
  	 */
  	if (r != NULLRTBLOCK) {
  		*rtblock = r;
  		return 0;
  	}
  	bbno = XFS_BITTOBLOCK(mp, bno);
  	i = 0;
79071eb0b   David Chinner   [XFS] Use the gen...
469
  	ASSERT(minlen != 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
  	log2len = xfs_highbit32(minlen);
  	/*
  	 * Loop over all bitmap blocks (bbno + i is current block).
  	 */
  	for (;;) {
  		/*
  		 * Get summary information of extents of all useful levels
  		 * starting in this bitmap block.
  		 */
  		error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1,
  			bbno + i, rbpp, rsb, &any);
  		if (error) {
  			return error;
  		}
  		/*
  		 * If there are any useful extents starting here, try
  		 * allocating one.
  		 */
  		if (any) {
  			/*
  			 * On the positive side of the starting location.
  			 */
  			if (i >= 0) {
  				/*
  				 * Try to allocate an extent starting in
  				 * this block.
  				 */
  				error = xfs_rtallocate_extent_block(mp, tp,
  					bbno + i, minlen, maxlen, len, &n, rbpp,
  					rsb, prod, &r);
  				if (error) {
  					return error;
  				}
  				/*
  				 * If it worked, return it.
  				 */
  				if (r != NULLRTBLOCK) {
  					*rtblock = r;
  					return 0;
  				}
  			}
  			/*
  			 * On the negative side of the starting location.
  			 */
  			else {		/* i < 0 */
  				/*
  				 * Loop backwards through the bitmap blocks from
  				 * the starting point-1 up to where we are now.
  				 * There should be an extent which ends in this
  				 * bitmap block and is long enough.
  				 */
  				for (j = -1; j > i; j--) {
  					/*
  					 * Grab the summary information for
  					 * this bitmap block.
  					 */
  					error = xfs_rtany_summary(mp, tp,
  						log2len, mp->m_rsumlevels - 1,
  						bbno + j, rbpp, rsb, &any);
  					if (error) {
  						return error;
  					}
  					/*
  					 * If there's no extent given in the
  					 * summary that means the extent we
  					 * found must carry over from an
  					 * earlier block.  If there is an
  					 * extent given, we've already tried
  					 * that allocation, don't do it again.
  					 */
  					if (any)
  						continue;
  					error = xfs_rtallocate_extent_block(mp,
  						tp, bbno + j, minlen, maxlen,
  						len, &n, rbpp, rsb, prod, &r);
  					if (error) {
  						return error;
  					}
  					/*
  					 * If it works, return the extent.
  					 */
  					if (r != NULLRTBLOCK) {
  						*rtblock = r;
  						return 0;
  					}
  				}
  				/*
  				 * There weren't intervening bitmap blocks
  				 * with a long enough extent, or the
  				 * allocation didn't work for some reason
  				 * (i.e. it's a little * too short).
  				 * Try to allocate from the summary block
  				 * that we found.
  				 */
  				error = xfs_rtallocate_extent_block(mp, tp,
  					bbno + i, minlen, maxlen, len, &n, rbpp,
  					rsb, prod, &r);
  				if (error) {
  					return error;
  				}
  				/*
  				 * If it works, return the extent.
  				 */
  				if (r != NULLRTBLOCK) {
  					*rtblock = r;
  					return 0;
  				}
  			}
  		}
  		/*
  		 * Loop control.  If we were on the positive side, and there's
  		 * still more blocks on the negative side, go there.
  		 */
  		if (i > 0 && (int)bbno - i >= 0)
  			i = -i;
  		/*
  		 * If positive, and no more negative, but there are more
  		 * positive, go there.
  		 */
  		else if (i > 0 && (int)bbno + i < mp->m_sb.sb_rbmblocks - 1)
  			i++;
  		/*
  		 * If negative or 0 (just started), and there are positive
  		 * blocks to go, go there.  The 0 case moves to block 1.
  		 */
  		else if (i <= 0 && (int)bbno - i < mp->m_sb.sb_rbmblocks - 1)
  			i = 1 - i;
  		/*
  		 * If negative or 0 and there are more negative blocks,
  		 * go there.
  		 */
  		else if (i <= 0 && (int)bbno + i > 0)
  			i--;
  		/*
  		 * Must be done.  Return failure.
  		 */
  		else
  			break;
  	}
  	*rtblock = NULLRTBLOCK;
  	return 0;
  }
  
  /*
   * Allocate an extent of length minlen<=len<=maxlen, with no position
   * specified.  If we don't get maxlen then use prod to trim
   * the length, if given.  The lengths are all in rtextents.
   */
  STATIC int				/* error */
  xfs_rtallocate_extent_size(
  	xfs_mount_t	*mp,		/* file system mount point */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_extlen_t	minlen,		/* minimum length to allocate */
  	xfs_extlen_t	maxlen,		/* maximum length to allocate */
  	xfs_extlen_t	*len,		/* out: actual length allocated */
  	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
  	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
  	xfs_extlen_t	prod,		/* extent product factor */
  	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
  {
  	int		error;		/* error value */
  	int		i;		/* bitmap block number */
  	int		l;		/* level number (loop control) */
  	xfs_rtblock_t	n;		/* next block to be tried */
  	xfs_rtblock_t	r;		/* result block number */
  	xfs_suminfo_t	sum;		/* summary information for extents */
  
  	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
79071eb0b   David Chinner   [XFS] Use the gen...
638
  	ASSERT(maxlen != 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
  	/*
  	 * Loop over all the levels starting with maxlen.
  	 * At each level, look at all the bitmap blocks, to see if there
  	 * are extents starting there that are long enough (>= maxlen).
  	 * Note, only on the initial level can the allocation fail if
  	 * the summary says there's an extent.
  	 */
  	for (l = xfs_highbit32(maxlen); l < mp->m_rsumlevels; l++) {
  		/*
  		 * Loop over all the bitmap blocks.
  		 */
  		for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
  			/*
  			 * Get the summary for this level/block.
  			 */
  			error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
  				&sum);
  			if (error) {
  				return error;
  			}
  			/*
  			 * Nothing there, on to the next block.
  			 */
  			if (!sum)
  				continue;
  			/*
  			 * Try allocating the extent.
  			 */
  			error = xfs_rtallocate_extent_block(mp, tp, i, maxlen,
  				maxlen, len, &n, rbpp, rsb, prod, &r);
  			if (error) {
  				return error;
  			}
  			/*
  			 * If it worked, return that.
  			 */
  			if (r != NULLRTBLOCK) {
  				*rtblock = r;
c963c6193   Dave Chinner   xfs: split xfs_rt...
677
678
679
680
681
682
683
684
685
686
  				return 0;
  			}
  			/*
  			 * If the "next block to try" returned from the
  			 * allocator is beyond the next bitmap block,
  			 * skip to that bitmap block.
  			 */
  			if (XFS_BITTOBLOCK(mp, n) > i + 1)
  				i = XFS_BITTOBLOCK(mp, n) - 1;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
  	/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
689
690
  	 * Didn't find any maxlen blocks.  Try smaller ones, unless
  	 * we're asking for a fixed size extent.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  	 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
692
693
694
695
696
697
  	if (minlen > --maxlen) {
  		*rtblock = NULLRTBLOCK;
  		return 0;
  	}
  	ASSERT(minlen != 0);
  	ASSERT(maxlen != 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  	/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
699
700
701
  	 * Loop over sizes, from maxlen down to minlen.
  	 * This time, when we do the allocations, allow smaller ones
  	 * to succeed.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  	 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
703
  	for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  		/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
705
706
  		 * Loop over all the bitmap blocks, try an allocation
  		 * starting in that block.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
  		 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
708
  		for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
  			/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
710
  			 * Get the summary information for this level/block.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  			 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
712
713
  			error =	xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
  						  &sum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
  			if (error) {
  				return error;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
  			/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
718
  			 * If nothing there, go on to next.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
  			 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
720
721
  			if (!sum)
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  			/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
723
724
725
  			 * Try the allocation.  Make sure the specified
  			 * minlen/maxlen are in the possible range for
  			 * this summary level.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  			 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
727
728
729
730
  			error = xfs_rtallocate_extent_block(mp, tp, i,
  					XFS_RTMAX(minlen, 1 << l),
  					XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
  					len, &n, rbpp, rsb, prod, &r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
733
  			if (error) {
  				return error;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  			/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
735
736
737
738
739
740
741
742
743
744
  			 * If it worked, return that extent.
  			 */
  			if (r != NULLRTBLOCK) {
  				*rtblock = r;
  				return 0;
  			}
  			/*
  			 * If the "next block to try" returned from the
  			 * allocator is beyond the next bitmap block,
  			 * skip to that bitmap block.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  			 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
746
747
  			if (XFS_BITTOBLOCK(mp, n) > i + 1)
  				i = XFS_BITTOBLOCK(mp, n) - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
749
750
  		}
  	}
  	/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
751
  	 * Got nothing, return failure.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
  	 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
753
  	*rtblock = NULLRTBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
757
  	return 0;
  }
  
  /*
c963c6193   Dave Chinner   xfs: split xfs_rt...
758
   * Allocate space to the bitmap or summary file, and zero it, for growfs.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
   */
d4a97a042   Brian Foster   xfs: add missing ...
760
  STATIC int
c963c6193   Dave Chinner   xfs: split xfs_rt...
761
  xfs_growfs_rt_alloc(
d4a97a042   Brian Foster   xfs: add missing ...
762
763
764
765
  	struct xfs_mount	*mp,		/* file system mount point */
  	xfs_extlen_t		oblocks,	/* old count of blocks */
  	xfs_extlen_t		nblocks,	/* new count of blocks */
  	struct xfs_inode	*ip)		/* inode (bitmap/summary) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  {
d4a97a042   Brian Foster   xfs: add missing ...
767
768
  	xfs_fileoff_t		bno;		/* block number in file */
  	struct xfs_buf		*bp;	/* temporary buffer for zeroing */
d4a97a042   Brian Foster   xfs: add missing ...
769
770
  	xfs_daddr_t		d;		/* disk block address */
  	int			error;		/* error return value */
d4a97a042   Brian Foster   xfs: add missing ...
771
772
773
774
  	xfs_fsblock_t		fsbno;		/* filesystem block for bno */
  	struct xfs_bmbt_irec	map;		/* block map output */
  	int			nmap;		/* number of block maps */
  	int			resblks;	/* space reservation */
72cc95132   Chandan Babu R   xfs: Set xfs_buf ...
775
  	enum xfs_blft		buf_type;
d4a97a042   Brian Foster   xfs: add missing ...
776
  	struct xfs_trans	*tp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777

72cc95132   Chandan Babu R   xfs: Set xfs_buf ...
778
779
780
781
  	if (ip == mp->m_rsumip)
  		buf_type = XFS_BLFT_RTSUMMARY_BUF;
  	else
  		buf_type = XFS_BLFT_RTBITMAP_BUF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
  	/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
783
  	 * Allocate space to the file, as necessary.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  	 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
785
  	while (oblocks < nblocks) {
c963c6193   Dave Chinner   xfs: split xfs_rt...
786
  		resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  		/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
788
  		 * Reserve space & log for one extent added to the file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  		 */
253f4911f   Christoph Hellwig   xfs: better xfs_t...
790
791
  		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtalloc, resblks,
  				0, 0, &tp);
c963c6193   Dave Chinner   xfs: split xfs_rt...
792
  		if (error)
253f4911f   Christoph Hellwig   xfs: better xfs_t...
793
  			return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
  		/*
c963c6193   Dave Chinner   xfs: split xfs_rt...
795
  		 * Lock the inode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  		 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
797
798
  		xfs_ilock(ip, XFS_ILOCK_EXCL);
  		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
c963c6193   Dave Chinner   xfs: split xfs_rt...
799
800
801
802
  		/*
  		 * Allocate blocks to the bitmap file.
  		 */
  		nmap = 1;
c963c6193   Dave Chinner   xfs: split xfs_rt...
803
  		error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
da781e64b   Brian Foster   xfs: don't set bm...
804
  					XFS_BMAPI_METADATA, 0, &map, &nmap);
c963c6193   Dave Chinner   xfs: split xfs_rt...
805
  		if (!error && nmap < 1)
2451337dd   Dave Chinner   xfs: global error...
806
  			error = -ENOSPC;
c963c6193   Dave Chinner   xfs: split xfs_rt...
807
  		if (error)
c8eac49ef   Brian Foster   xfs: remove all b...
808
  			goto out_trans_cancel;
c963c6193   Dave Chinner   xfs: split xfs_rt...
809
810
811
  		/*
  		 * Free any blocks freed up in the transaction, then commit.
  		 */
70393313d   Christoph Hellwig   xfs: saner xfs_tr...
812
  		error = xfs_trans_commit(tp);
c963c6193   Dave Chinner   xfs: split xfs_rt...
813
  		if (error)
d4a97a042   Brian Foster   xfs: add missing ...
814
  			return error;
c963c6193   Dave Chinner   xfs: split xfs_rt...
815
816
817
818
  		/*
  		 * Now we need to clear the allocated blocks.
  		 * Do this one block per transaction, to keep it simple.
  		 */
c963c6193   Dave Chinner   xfs: split xfs_rt...
819
820
821
  		for (bno = map.br_startoff, fsbno = map.br_startblock;
  		     bno < map.br_startoff + map.br_blockcount;
  		     bno++, fsbno++) {
c963c6193   Dave Chinner   xfs: split xfs_rt...
822
823
824
  			/*
  			 * Reserve log for one block zeroing.
  			 */
253f4911f   Christoph Hellwig   xfs: better xfs_t...
825
826
  			error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtzero,
  					0, 0, 0, &tp);
c963c6193   Dave Chinner   xfs: split xfs_rt...
827
  			if (error)
253f4911f   Christoph Hellwig   xfs: better xfs_t...
828
  				return error;
c963c6193   Dave Chinner   xfs: split xfs_rt...
829
830
831
832
833
834
835
836
837
  			/*
  			 * Lock the bitmap inode.
  			 */
  			xfs_ilock(ip, XFS_ILOCK_EXCL);
  			xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
  			/*
  			 * Get a buffer for the block.
  			 */
  			d = XFS_FSB_TO_DADDR(mp, fsbno);
ce92464c1   Darrick J. Wong   xfs: make xfs_tra...
838
839
840
  			error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
  					mp->m_bsize, 0, &bp);
  			if (error)
d4a97a042   Brian Foster   xfs: add missing ...
841
  				goto out_trans_cancel;
72cc95132   Chandan Babu R   xfs: Set xfs_buf ...
842
843
  
  			xfs_trans_buf_set_type(tp, bp, buf_type);
c54e14d15   Chandan Babu R   xfs: Set xfs_buf'...
844
  			bp->b_ops = &xfs_rtbuf_ops;
c963c6193   Dave Chinner   xfs: split xfs_rt...
845
846
847
848
849
  			memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
  			xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
  			/*
  			 * Commit the transaction.
  			 */
70393313d   Christoph Hellwig   xfs: saner xfs_tr...
850
  			error = xfs_trans_commit(tp);
c963c6193   Dave Chinner   xfs: split xfs_rt...
851
  			if (error)
d4a97a042   Brian Foster   xfs: add missing ...
852
  				return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
  		}
c963c6193   Dave Chinner   xfs: split xfs_rt...
854
855
856
857
  		/*
  		 * Go on to the next extent, if any.
  		 */
  		oblocks = map.br_startoff + map.br_blockcount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
  	}
d4a97a042   Brian Foster   xfs: add missing ...
859

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
  	return 0;
c963c6193   Dave Chinner   xfs: split xfs_rt...
861

d4a97a042   Brian Foster   xfs: add missing ...
862
863
  out_trans_cancel:
  	xfs_trans_cancel(tp);
c963c6193   Dave Chinner   xfs: split xfs_rt...
864
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
  }
65eed012d   Omar Sandoval   xfs: reallocate r...
866
867
868
869
870
871
872
873
874
875
  static void
  xfs_alloc_rsum_cache(
  	xfs_mount_t	*mp,		/* file system mount structure */
  	xfs_extlen_t	rbmblocks)	/* number of rt bitmap blocks */
  {
  	/*
  	 * The rsum cache is initialized to all zeroes, which is trivially a
  	 * lower bound on the minimum level with any free extents. We can
  	 * continue without the cache if it couldn't be allocated.
  	 */
8ca79df85   Carlos Maiolino   xfs: Remove kmem_...
876
  	mp->m_rsum_cache = kvzalloc(rbmblocks, GFP_KERNEL);
65eed012d   Omar Sandoval   xfs: reallocate r...
877
878
879
  	if (!mp->m_rsum_cache)
  		xfs_warn(mp, "could not allocate realtime summary cache");
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
882
883
884
885
886
887
888
889
890
891
892
893
  /*
   * Visible (exported) functions.
   */
  
  /*
   * Grow the realtime area of the filesystem.
   */
  int
  xfs_growfs_rt(
  	xfs_mount_t	*mp,		/* mount point for filesystem */
  	xfs_growfs_rt_t	*in)		/* growfs rt input struct */
  {
  	xfs_rtblock_t	bmbno;		/* bitmap block number */
  	xfs_buf_t	*bp;		/* temporary buffer */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
  	int		error;		/* error return value */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
  	xfs_mount_t	*nmp;		/* new (fake) mount structure */
d5cf09bac   Christoph Hellwig   xfs: require 64-b...
896
  	xfs_rfsblock_t	nrblocks;	/* new number of realtime blocks */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
  	xfs_extlen_t	nrbmblocks;	/* new number of rt bitmap blocks */
d5cf09bac   Christoph Hellwig   xfs: require 64-b...
898
  	xfs_rtblock_t	nrextents;	/* new number of realtime extents */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
899
900
901
902
903
904
905
906
907
  	uint8_t		nrextslog;	/* new log2 of sb_rextents */
  	xfs_extlen_t	nrsumblocks;	/* new number of summary blocks */
  	uint		nrsumlevels;	/* new rt summary levels */
  	uint		nrsumsize;	/* new size of rt summary, bytes */
  	xfs_sb_t	*nsbp;		/* new superblock */
  	xfs_extlen_t	rbmblocks;	/* current number of rt bitmap blocks */
  	xfs_extlen_t	rsumblocks;	/* current number of rt summary blks */
  	xfs_sb_t	*sbp;		/* old superblock */
  	xfs_fsblock_t	sumbno;		/* summary block number */
65eed012d   Omar Sandoval   xfs: reallocate r...
908
  	uint8_t		*rsum_cache;	/* old summary cache */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
910
911
912
913
  
  	sbp = &mp->m_sb;
  	/*
  	 * Initial error checking.
  	 */
743bb4650   sandeen@sandeen.net   [XFS] Move copy_f...
914
  	if (!capable(CAP_SYS_ADMIN))
2451337dd   Dave Chinner   xfs: global error...
915
  		return -EPERM;
73024cf11   Eric Sesterhenn   [XFS] Fix realtim...
916
  	if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
  	    (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
  	    (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
2451337dd   Dave Chinner   xfs: global error...
919
  		return -EINVAL;
4cc929ee3   Nathan Scott   [XFS] Don't grow ...
920
921
  	if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
923
924
  	/*
  	 * Read in the last block of the device, make sure it exists.
  	 */
ba3726742   Dave Chinner   xfs: check xfs_bu...
925
  	error = xfs_buf_read_uncached(mp->m_rtdev_targp,
1922c949c   Dave Chinner   xfs: use unhashed...
926
  				XFS_FSB_TO_BB(mp, nrblocks - 1),
ba3726742   Dave Chinner   xfs: check xfs_bu...
927
928
  				XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
  	if (error)
eab4e6336   Dave Chinner   xfs: uncached buf...
929
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  	xfs_buf_relse(bp);
1922c949c   Dave Chinner   xfs: use unhashed...
931

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
934
935
936
  	/*
  	 * Calculate new parameters.  These are the final values to be reached.
  	 */
  	nrextents = nrblocks;
  	do_div(nrextents, in->extsize);
68c327151   Nathan Scott   [XFS] Fix a porti...
937
  	nrbmblocks = howmany_64(nrextents, NBBY * sbp->sb_blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
941
942
943
944
945
946
947
948
  	nrextslog = xfs_highbit32(nrextents);
  	nrsumlevels = nrextslog + 1;
  	nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
  	nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
  	nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
  	/*
  	 * New summary size can't be more than half the size of
  	 * the log.  This prevents us from getting a log overflow,
  	 * since we'll log basically the whole summary file at once.
  	 */
  	if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1))
2451337dd   Dave Chinner   xfs: global error...
949
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
951
952
953
954
955
956
957
958
  	/*
  	 * Get the old block counts for bitmap and summary inodes.
  	 * These can't change since other growfs callers are locked out.
  	 */
  	rbmblocks = XFS_B_TO_FSB(mp, mp->m_rbmip->i_d.di_size);
  	rsumblocks = XFS_B_TO_FSB(mp, mp->m_rsumip->i_d.di_size);
  	/*
  	 * Allocate space to the bitmap and summary files, as necessary.
  	 */
1050c71e2   Christoph Hellwig   xfs: stop using x...
959
960
  	error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip);
  	if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  		return error;
1050c71e2   Christoph Hellwig   xfs: stop using x...
962
963
  	error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
  	if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  		return error;
65eed012d   Omar Sandoval   xfs: reallocate r...
965
966
967
968
  
  	rsum_cache = mp->m_rsum_cache;
  	if (nrbmblocks != sbp->sb_rbmblocks)
  		xfs_alloc_rsum_cache(mp, nrbmblocks);
d432c80e6   Nathan Scott   [XFS] Minor code ...
969
970
971
  	/*
  	 * Allocate a new (fake) mount/sb.
  	 */
707e0ddaf   Tetsuo Handa   fs: xfs: Remove K...
972
  	nmp = kmem_alloc(sizeof(*nmp), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
974
975
976
977
978
979
980
981
982
  	/*
  	 * Loop over the bitmap blocks.
  	 * We will do everything one bitmap block at a time.
  	 * Skip the current block if it is exactly full.
  	 * This also deals with the case where there were no rtextents before.
  	 */
  	for (bmbno = sbp->sb_rbmblocks -
  		     ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
  	     bmbno < nrbmblocks;
  	     bmbno++) {
0924b585f   Dave Chinner   [XFS] fix uniniti...
983
  		xfs_trans_t	*tp;
0924b585f   Dave Chinner   [XFS] fix uniniti...
984

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
987
988
989
990
991
992
993
994
995
996
997
  		*nmp = *mp;
  		nsbp = &nmp->m_sb;
  		/*
  		 * Calculate new sb and mount fields for this round.
  		 */
  		nsbp->sb_rextsize = in->extsize;
  		nsbp->sb_rbmblocks = bmbno + 1;
  		nsbp->sb_rblocks =
  			XFS_RTMIN(nrblocks,
  				  nsbp->sb_rbmblocks * NBBY *
  				  nsbp->sb_blocksize * nsbp->sb_rextsize);
  		nsbp->sb_rextents = nsbp->sb_rblocks;
  		do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
79071eb0b   David Chinner   [XFS] Use the gen...
998
  		ASSERT(nsbp->sb_rextents != 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  		nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
  		nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
  		nrsumsize =
  			(uint)sizeof(xfs_suminfo_t) * nrsumlevels *
  			nsbp->sb_rbmblocks;
  		nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
  		nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
  		/*
  		 * Start a transaction, get the log reservation.
  		 */
253f4911f   Christoph Hellwig   xfs: better xfs_t...
1009
1010
  		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtfree, 0, 0, 0,
  				&tp);
3d3c8b522   Jie Liu   xfs: refactor xfs...
1011
  		if (error)
253f4911f   Christoph Hellwig   xfs: better xfs_t...
1012
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
1014
1015
  		/*
  		 * Lock out other callers by grabbing the bitmap inode lock.
  		 */
ace74e797   Darrick J. Wong   xfs: annotate gra...
1016
  		xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
ddc3415ab   Christoph Hellwig   xfs: simplify xfs...
1017
  		xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
  		/*
f4c32e87d   Darrick J. Wong   xfs: fix realtime...
1019
1020
1021
  		 * Update the bitmap inode's size ondisk and incore.  We need
  		 * to update the incore size so that inode inactivation won't
  		 * punch what it thinks are "posteof" blocks.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
  		 */
  		mp->m_rbmip->i_d.di_size =
  			nsbp->sb_rbmblocks * nsbp->sb_blocksize;
f4c32e87d   Darrick J. Wong   xfs: fix realtime...
1025
  		i_size_write(VFS_I(mp->m_rbmip), mp->m_rbmip->i_d.di_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
  		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
1028
1029
  		/*
  		 * Get the summary inode into the transaction.
  		 */
ace74e797   Darrick J. Wong   xfs: annotate gra...
1030
  		xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM);
ddc3415ab   Christoph Hellwig   xfs: simplify xfs...
1031
  		xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
  		/*
f4c32e87d   Darrick J. Wong   xfs: fix realtime...
1033
1034
1035
  		 * Update the summary inode's size.  We need to update the
  		 * incore size so that inode inactivation won't punch what it
  		 * thinks are "posteof" blocks.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
  		 */
  		mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
f4c32e87d   Darrick J. Wong   xfs: fix realtime...
1038
  		i_size_write(VFS_I(mp->m_rsumip), mp->m_rsumip->i_d.di_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
1040
1041
1042
1043
1044
1045
1046
1047
  		xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
  		/*
  		 * Copy summary data from old to new sizes.
  		 * Do this when the real size (not block-aligned) changes.
  		 */
  		if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
  		    mp->m_rsumlevels != nmp->m_rsumlevels) {
  			error = xfs_rtcopy_summary(mp, nmp, tp);
  			if (error)
0924b585f   Dave Chinner   [XFS] fix uniniti...
1048
  				goto error_cancel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
  		}
  		/*
  		 * Update superblock fields.
  		 */
  		if (nsbp->sb_rextsize != sbp->sb_rextsize)
  			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
  				nsbp->sb_rextsize - sbp->sb_rextsize);
  		if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
  			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
  				nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
  		if (nsbp->sb_rblocks != sbp->sb_rblocks)
  			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
  				nsbp->sb_rblocks - sbp->sb_rblocks);
  		if (nsbp->sb_rextents != sbp->sb_rextents)
  			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
  				nsbp->sb_rextents - sbp->sb_rextents);
  		if (nsbp->sb_rextslog != sbp->sb_rextslog)
  			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
  				nsbp->sb_rextslog - sbp->sb_rextslog);
  		/*
  		 * Free new extent.
  		 */
  		bp = NULL;
  		error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
  			nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
0924b585f   Dave Chinner   [XFS] fix uniniti...
1074
1075
  		if (error) {
  error_cancel:
4906e2154   Christoph Hellwig   xfs: remove the f...
1076
  			xfs_trans_cancel(tp);
d432c80e6   Nathan Scott   [XFS] Minor code ...
1077
  			break;
0924b585f   Dave Chinner   [XFS] fix uniniti...
1078
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1079
1080
1081
1082
1083
1084
  		/*
  		 * Mark more blocks free in the superblock.
  		 */
  		xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
  			nsbp->sb_rextents - sbp->sb_rextents);
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085
1086
1087
1088
  		 * Update mp values into the real mp structure.
  		 */
  		mp->m_rsumlevels = nrsumlevels;
  		mp->m_rsumsize = nrsumsize;
e5720eec0   David Chinner   [XFS] Propagate e...
1089

70393313d   Christoph Hellwig   xfs: saner xfs_tr...
1090
  		error = xfs_trans_commit(tp);
0924b585f   Dave Chinner   [XFS] fix uniniti...
1091
  		if (error)
e5720eec0   David Chinner   [XFS] Propagate e...
1092
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1093
  	}
7249c95a3   Darrick J. Wong   xfs: make xfs_gro...
1094
1095
1096
1097
1098
  	if (error)
  		goto out_free;
  
  	/* Update secondary superblocks now the physical grow has completed */
  	error = xfs_update_secondary_sbs(mp);
d432c80e6   Nathan Scott   [XFS] Minor code ...
1099

7249c95a3   Darrick J. Wong   xfs: make xfs_gro...
1100
  out_free:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  	/*
d432c80e6   Nathan Scott   [XFS] Minor code ...
1102
  	 * Free the fake mp structure.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103
  	 */
f0e2d93c2   Denys Vlasenko   [XFS] Remove unus...
1104
  	kmem_free(nmp);
d432c80e6   Nathan Scott   [XFS] Minor code ...
1105

65eed012d   Omar Sandoval   xfs: reallocate r...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
  	/*
  	 * If we had to allocate a new rsum_cache, we either need to free the
  	 * old one (if we succeeded) or free the new one and restore the old one
  	 * (if there was an error).
  	 */
  	if (rsum_cache != mp->m_rsum_cache) {
  		if (error) {
  			kmem_free(mp->m_rsum_cache);
  			mp->m_rsum_cache = rsum_cache;
  		} else {
  			kmem_free(rsum_cache);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
  	return error;
  }
  
  /*
   * Allocate an extent in the realtime subvolume, with the usual allocation
   * parameters.  The length units are all in realtime extents, as is the
   * result block number.
   */
  int					/* error */
  xfs_rtallocate_extent(
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_rtblock_t	bno,		/* starting block number to allocate */
  	xfs_extlen_t	minlen,		/* minimum length to allocate */
  	xfs_extlen_t	maxlen,		/* maximum length to allocate */
  	xfs_extlen_t	*len,		/* out: actual length allocated */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
1135
1136
1137
  	int		wasdel,		/* was a delayed allocation extent */
  	xfs_extlen_t	prod,		/* extent product factor */
  	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
  {
04e99455e   Christoph Hellwig   xfs: only lock th...
1138
  	xfs_mount_t	*mp = tp->t_mountp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
  	int		error;		/* error value */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1140
1141
1142
  	xfs_rtblock_t	r;		/* result allocated block */
  	xfs_fsblock_t	sb;		/* summary file block number */
  	xfs_buf_t	*sumbp;		/* summary file block buffer */
04e99455e   Christoph Hellwig   xfs: only lock th...
1143
  	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
  	ASSERT(minlen > 0 && minlen <= maxlen);
04e99455e   Christoph Hellwig   xfs: only lock th...
1145

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
  	/*
  	 * If prod is set then figure out what to do to minlen and maxlen.
  	 */
  	if (prod > 1) {
  		xfs_extlen_t	i;
  
  		if ((i = maxlen % prod))
  			maxlen -= i;
  		if ((i = minlen % prod))
  			minlen += prod - i;
  		if (maxlen < minlen) {
  			*rtblock = NULLRTBLOCK;
  			return 0;
  		}
  	}
04e99455e   Christoph Hellwig   xfs: only lock th...
1161

089ec2f87   Christoph Hellwig   xfs: simplify xfs...
1162
  retry:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163
  	sumbp = NULL;
089ec2f87   Christoph Hellwig   xfs: simplify xfs...
1164
  	if (bno == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1165
1166
  		error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
  				&sumbp,	&sb, prod, &r);
089ec2f87   Christoph Hellwig   xfs: simplify xfs...
1167
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
1169
  		error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
  				len, &sumbp, &sb, prod, &r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
  	}
089ec2f87   Christoph Hellwig   xfs: simplify xfs...
1171

04e99455e   Christoph Hellwig   xfs: only lock th...
1172
  	if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173
  		return error;
04e99455e   Christoph Hellwig   xfs: only lock th...
1174

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
  	/*
  	 * If it worked, update the superblock.
  	 */
  	if (r != NULLRTBLOCK) {
  		long	slen = (long)*len;
  
  		ASSERT(*len >= minlen && *len <= maxlen);
  		if (wasdel)
  			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
  		else
  			xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
089ec2f87   Christoph Hellwig   xfs: simplify xfs...
1186
1187
1188
  	} else if (prod > 1) {
  		prod = 1;
  		goto retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
  	}
089ec2f87   Christoph Hellwig   xfs: simplify xfs...
1190

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191
1192
1193
1194
1195
  	*rtblock = r;
  	return 0;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196
1197
1198
1199
   * Initialize realtime fields in the mount structure.
   */
  int				/* error */
  xfs_rtmount_init(
ba3726742   Dave Chinner   xfs: check xfs_bu...
1200
  	struct xfs_mount	*mp)	/* file system mount structure */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
  {
ba3726742   Dave Chinner   xfs: check xfs_bu...
1202
1203
1204
1205
  	struct xfs_buf		*bp;	/* buffer for last block of subvolume */
  	struct xfs_sb		*sbp;	/* filesystem superblock copy in mount */
  	xfs_daddr_t		d;	/* address of last block of subvolume */
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
1208
1209
1210
  
  	sbp = &mp->m_sb;
  	if (sbp->sb_rblocks == 0)
  		return 0;
  	if (mp->m_rtdev_targp == NULL) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1211
1212
  		xfs_warn(mp,
  	"Filesystem has a realtime volume, use rtdev=device option");
2451337dd   Dave Chinner   xfs: global error...
1213
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
  	}
  	mp->m_rsumlevels = sbp->sb_rextslog + 1;
  	mp->m_rsumsize =
  		(uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
  		sbp->sb_rbmblocks;
  	mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
  	mp->m_rbmip = mp->m_rsumip = NULL;
  	/*
  	 * Check that the realtime section is an ok size.
  	 */
  	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
  	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1226
  		xfs_warn(mp, "realtime mount -- %llu != %llu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
  			(unsigned long long) XFS_BB_TO_FSB(mp, d),
  			(unsigned long long) mp->m_sb.sb_rblocks);
2451337dd   Dave Chinner   xfs: global error...
1229
  		return -EFBIG;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
  	}
ba3726742   Dave Chinner   xfs: check xfs_bu...
1231
  	error = xfs_buf_read_uncached(mp->m_rtdev_targp,
1922c949c   Dave Chinner   xfs: use unhashed...
1232
  					d - XFS_FSB_TO_BB(mp, 1),
ba3726742   Dave Chinner   xfs: check xfs_bu...
1233
1234
  					XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1235
  		xfs_warn(mp, "realtime device size check failed");
ba3726742   Dave Chinner   xfs: check xfs_bu...
1236
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
1240
1241
1242
  	}
  	xfs_buf_relse(bp);
  	return 0;
  }
  
  /*
355e35321   Omar Sandoval   xfs: cache minimu...
1243
1244
   * Get the bitmap and summary inodes and the summary cache into the mount
   * structure at mount time.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
1246
1247
1248
1249
1250
1251
1252
1253
   */
  int					/* error */
  xfs_rtmount_inodes(
  	xfs_mount_t	*mp)		/* file system mount structure */
  {
  	int		error;		/* error return value */
  	xfs_sb_t	*sbp;
  
  	sbp = &mp->m_sb;
7b6259e7a   Dave Chinner   xfs: remove block...
1254
  	error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
1256
1257
  	if (error)
  		return error;
  	ASSERT(mp->m_rbmip != NULL);
64bafd2f1   Darrick J. Wong   xfs: require both...
1258

7b6259e7a   Dave Chinner   xfs: remove block...
1259
  	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
  	if (error) {
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1261
  		xfs_irele(mp->m_rbmip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
1263
1264
  		return error;
  	}
  	ASSERT(mp->m_rsumip != NULL);
65eed012d   Omar Sandoval   xfs: reallocate r...
1265
  	xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266
1267
  	return 0;
  }
b93b6e434   Christoph Hellwig   xfs: make sure to...
1268
1269
1270
1271
  void
  xfs_rtunmount_inodes(
  	struct xfs_mount	*mp)
  {
355e35321   Omar Sandoval   xfs: cache minimu...
1272
  	kmem_free(mp->m_rsum_cache);
b93b6e434   Christoph Hellwig   xfs: make sure to...
1273
  	if (mp->m_rbmip)
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1274
  		xfs_irele(mp->m_rbmip);
b93b6e434   Christoph Hellwig   xfs: make sure to...
1275
  	if (mp->m_rsumip)
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1276
  		xfs_irele(mp->m_rsumip);
b93b6e434   Christoph Hellwig   xfs: make sure to...
1277
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
  /*
   * Pick an extent for allocation at the start of a new realtime file.
   * Use the sequence number stored in the atime field of the bitmap inode.
   * Translate this to a fraction of the rtextents, and return the product
   * of rtextents and the fraction.
   * The fraction sequence is 0, 1/2, 1/4, 3/4, 1/8, ..., 7/8, 1/16, ...
   */
  int					/* error */
  xfs_rtpick_extent(
  	xfs_mount_t	*mp,		/* file system mount point */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_extlen_t	len,		/* allocation length (rtextents) */
  	xfs_rtblock_t	*pick)		/* result rt extent */
  {
  	xfs_rtblock_t	b;		/* result block */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
  	int		log2;		/* log of sequence number */
c8ce540db   Darrick J. Wong   xfs: remove doubl...
1294
1295
1296
  	uint64_t	resid;		/* residual after log removed */
  	uint64_t	seq;		/* sequence number of file creation */
  	uint64_t	*seqp;		/* pointer to seqno in inode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297

04e99455e   Christoph Hellwig   xfs: only lock th...
1298
  	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
c8ce540db   Darrick J. Wong   xfs: remove doubl...
1299
  	seqp = (uint64_t *)&VFS_I(mp->m_rbmip)->i_atime;
04e99455e   Christoph Hellwig   xfs: only lock th...
1300
1301
  	if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
  		mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
  		*seqp = 0;
  	}
  	seq = *seqp;
  	if ((log2 = xfs_highbit64(seq)) == -1)
  		b = 0;
  	else {
  		resid = seq - (1ULL << log2);
  		b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
  		    (log2 + 1);
  		if (b >= mp->m_sb.sb_rextents)
0703a8e1c   Dave Chinner   xfs: replace do_m...
1312
  			div64_u64_rem(b, mp->m_sb.sb_rextents, &b);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
1314
1315
1316
  		if (b + len > mp->m_sb.sb_rextents)
  			b = mp->m_sb.sb_rextents - len;
  	}
  	*seqp = seq + 1;
04e99455e   Christoph Hellwig   xfs: only lock th...
1317
  	xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
1319
1320
  	*pick = b;
  	return 0;
  }