Blame view

fs/xfs/xfs_ialloc.c 42.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
7b7187698   Nathan Scott   [XFS] Update lice...
2
3
   * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
7b7187698   Nathan Scott   [XFS] Update lice...
5
6
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   * published by the Free Software Foundation.
   *
7b7187698   Nathan Scott   [XFS] Update lice...
9
10
11
12
   * This program is distributed in the hope that it would be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
   *
7b7187698   Nathan Scott   [XFS] Update lice...
14
15
16
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write the Free Software Foundation,
   * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include "xfs.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
19
  #include "xfs_fs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include "xfs_types.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
21
  #include "xfs_bit.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include "xfs_log.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
23
  #include "xfs_inum.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
  #include "xfs_trans.h"
  #include "xfs_sb.h"
  #include "xfs_ag.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include "xfs_mount.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include "xfs_bmap_btree.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
29
  #include "xfs_alloc_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include "xfs_ialloc_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  #include "xfs_dinode.h"
  #include "xfs_inode.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
33
34
  #include "xfs_btree.h"
  #include "xfs_ialloc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include "xfs_alloc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
  #include "xfs_rtalloc.h"
  #include "xfs_error.h"
  #include "xfs_bmap.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
  
  /*
   * Allocation group level functions.
   */
75de2a91c   David Chinner   [XFS] Account for...
43
44
45
46
47
48
49
50
51
52
  static inline int
  xfs_ialloc_cluster_alignment(
  	xfs_alloc_arg_t	*args)
  {
  	if (xfs_sb_version_hasalign(&args->mp->m_sb) &&
  	    args->mp->m_sb.sb_inoalignmt >=
  	     XFS_B_TO_FSBT(args->mp, XFS_INODE_CLUSTER_SIZE(args->mp)))
  		return args->mp->m_sb.sb_inoalignmt;
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
  
  /*
218755052   Christoph Hellwig   xfs: rationalize ...
55
   * Lookup a record by ino in the btree given by cur.
fe033cc84   Christoph Hellwig   [XFS] implement g...
56
   */
81e251766   Christoph Hellwig   xfs: un-static xf...
57
  int					/* error */
218755052   Christoph Hellwig   xfs: rationalize ...
58
  xfs_inobt_lookup(
fe033cc84   Christoph Hellwig   [XFS] implement g...
59
60
  	struct xfs_btree_cur	*cur,	/* btree cursor */
  	xfs_agino_t		ino,	/* starting inode of chunk */
218755052   Christoph Hellwig   xfs: rationalize ...
61
  	xfs_lookup_t		dir,	/* <=, >=, == */
fe033cc84   Christoph Hellwig   [XFS] implement g...
62
63
64
  	int			*stat)	/* success/failure */
  {
  	cur->bc_rec.i.ir_startino = ino;
218755052   Christoph Hellwig   xfs: rationalize ...
65
66
67
  	cur->bc_rec.i.ir_freecount = 0;
  	cur->bc_rec.i.ir_free = 0;
  	return xfs_btree_lookup(cur, dir, stat);
fe033cc84   Christoph Hellwig   [XFS] implement g...
68
69
70
  }
  
  /*
afabc24a7   Christoph Hellwig   xfs: improve xfs_...
71
   * Update the record referred to by cur to the value given.
278d0ca14   Christoph Hellwig   [XFS] implement g...
72
73
74
75
76
   * This either works (return 0) or gets an EFSCORRUPTED error.
   */
  STATIC int				/* error */
  xfs_inobt_update(
  	struct xfs_btree_cur	*cur,	/* btree cursor */
afabc24a7   Christoph Hellwig   xfs: improve xfs_...
77
  	xfs_inobt_rec_incore_t	*irec)	/* btree record */
278d0ca14   Christoph Hellwig   [XFS] implement g...
78
79
  {
  	union xfs_btree_rec	rec;
afabc24a7   Christoph Hellwig   xfs: improve xfs_...
80
81
82
  	rec.inobt.ir_startino = cpu_to_be32(irec->ir_startino);
  	rec.inobt.ir_freecount = cpu_to_be32(irec->ir_freecount);
  	rec.inobt.ir_free = cpu_to_be64(irec->ir_free);
278d0ca14   Christoph Hellwig   [XFS] implement g...
83
84
85
86
  	return xfs_btree_update(cur, &rec);
  }
  
  /*
8cc938fe4   Christoph Hellwig   [XFS] implement g...
87
88
89
90
91
   * Get the data from the pointed-to record.
   */
  int					/* error */
  xfs_inobt_get_rec(
  	struct xfs_btree_cur	*cur,	/* btree cursor */
2e287a731   Christoph Hellwig   xfs: improve xfs_...
92
  	xfs_inobt_rec_incore_t	*irec,	/* btree record */
8cc938fe4   Christoph Hellwig   [XFS] implement g...
93
94
95
96
97
98
99
  	int			*stat)	/* output: success/failure */
  {
  	union xfs_btree_rec	*rec;
  	int			error;
  
  	error = xfs_btree_get_rec(cur, &rec, stat);
  	if (!error && *stat == 1) {
2e287a731   Christoph Hellwig   xfs: improve xfs_...
100
101
102
  		irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino);
  		irec->ir_freecount = be32_to_cpu(rec->inobt.ir_freecount);
  		irec->ir_free = be64_to_cpu(rec->inobt.ir_free);
8cc938fe4   Christoph Hellwig   [XFS] implement g...
103
104
105
106
107
  	}
  	return error;
  }
  
  /*
0b48db80b   Dave Chinner   xfs: factor out d...
108
109
110
111
112
113
114
115
116
117
118
119
120
   * Verify that the number of free inodes in the AGI is correct.
   */
  #ifdef DEBUG
  STATIC int
  xfs_check_agi_freecount(
  	struct xfs_btree_cur	*cur,
  	struct xfs_agi		*agi)
  {
  	if (cur->bc_nlevels == 1) {
  		xfs_inobt_rec_incore_t rec;
  		int		freecount = 0;
  		int		error;
  		int		i;
218755052   Christoph Hellwig   xfs: rationalize ...
121
  		error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i);
0b48db80b   Dave Chinner   xfs: factor out d...
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
  		if (error)
  			return error;
  
  		do {
  			error = xfs_inobt_get_rec(cur, &rec, &i);
  			if (error)
  				return error;
  
  			if (i) {
  				freecount += rec.ir_freecount;
  				error = xfs_btree_increment(cur, 0, &i);
  				if (error)
  					return error;
  			}
  		} while (i == 1);
  
  		if (!XFS_FORCED_SHUTDOWN(cur->bc_mp))
  			ASSERT(freecount == be32_to_cpu(agi->agi_freecount));
  	}
  	return 0;
  }
  #else
  #define xfs_check_agi_freecount(cur, agi)	0
  #endif
  
  /*
85c0b2ab5   Dave Chinner   xfs: factor out i...
148
149
   * Initialise a new set of inodes.
   */
2a30f36d9   Chandra Seetharaman   xfs: Check the re...
150
  STATIC int
85c0b2ab5   Dave Chinner   xfs: factor out i...
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
  xfs_ialloc_inode_init(
  	struct xfs_mount	*mp,
  	struct xfs_trans	*tp,
  	xfs_agnumber_t		agno,
  	xfs_agblock_t		agbno,
  	xfs_agblock_t		length,
  	unsigned int		gen)
  {
  	struct xfs_buf		*fbuf;
  	struct xfs_dinode	*free;
  	int			blks_per_cluster, nbufs, ninodes;
  	int			version;
  	int			i, j;
  	xfs_daddr_t		d;
  
  	/*
  	 * Loop over the new block(s), filling in the inodes.
  	 * For small block sizes, manipulate the inodes in buffers
  	 * which are multiples of the blocks size.
  	 */
  	if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
  		blks_per_cluster = 1;
  		nbufs = length;
  		ninodes = mp->m_sb.sb_inopblock;
  	} else {
  		blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) /
  				   mp->m_sb.sb_blocksize;
  		nbufs = length / blks_per_cluster;
  		ninodes = blks_per_cluster * mp->m_sb.sb_inopblock;
  	}
  
  	/*
  	 * Figure out what version number to use in the inodes we create.
  	 * If the superblock version has caught up to the one that supports
  	 * the new inode format, then use the new inode version.  Otherwise
  	 * use the old version so that old kernels will continue to be
  	 * able to use the file system.
  	 */
  	if (xfs_sb_version_hasnlink(&mp->m_sb))
  		version = 2;
  	else
  		version = 1;
  
  	for (j = 0; j < nbufs; j++) {
  		/*
  		 * Get the block.
  		 */
  		d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster));
  		fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
  					 mp->m_bsize * blks_per_cluster,
0cadda1c5   Christoph Hellwig   xfs: remove dupli...
201
  					 XBF_LOCK);
2a30f36d9   Chandra Seetharaman   xfs: Check the re...
202
203
  		if (!fbuf)
  			return ENOMEM;
85c0b2ab5   Dave Chinner   xfs: factor out i...
204
205
206
207
208
209
210
  		/*
  		 * Initialize all inodes in this buffer and then log them.
  		 *
  		 * XXX: It would be much better if we had just one transaction
  		 *	to log a whole cluster of inodes instead of all the
  		 *	individual transactions causing a lot of log traffic.
  		 */
1a1a3e97b   Christoph Hellwig   xfs: remove xfs_b...
211
  		xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
85c0b2ab5   Dave Chinner   xfs: factor out i...
212
213
214
215
216
217
218
219
220
221
222
223
224
  		for (i = 0; i < ninodes; i++) {
  			int	ioffset = i << mp->m_sb.sb_inodelog;
  			uint	isize = sizeof(struct xfs_dinode);
  
  			free = xfs_make_iptr(mp, fbuf, i);
  			free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
  			free->di_version = version;
  			free->di_gen = cpu_to_be32(gen);
  			free->di_next_unlinked = cpu_to_be32(NULLAGINO);
  			xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1);
  		}
  		xfs_trans_inode_alloc_buf(tp, fbuf);
  	}
2a30f36d9   Chandra Seetharaman   xfs: Check the re...
225
  	return 0;
85c0b2ab5   Dave Chinner   xfs: factor out i...
226
227
228
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
233
234
235
236
237
238
239
   * Allocate new inodes in the allocation group specified by agbp.
   * Return 0 for success, else error code.
   */
  STATIC int				/* error code or 0 */
  xfs_ialloc_ag_alloc(
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_buf_t	*agbp,		/* alloc group buffer */
  	int		*alloc)
  {
  	xfs_agi_t	*agi;		/* allocation group header */
  	xfs_alloc_arg_t	args;		/* allocation argument structure */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  	xfs_btree_cur_t	*cur;		/* inode btree cursor */
92821e2ba   David Chinner   [XFS] Lazy Superb...
241
  	xfs_agnumber_t	agno;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  	int		error;
85c0b2ab5   Dave Chinner   xfs: factor out i...
243
  	int		i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
  	xfs_agino_t	newino;		/* new first inode's number */
  	xfs_agino_t	newlen;		/* new number of inodes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  	xfs_agino_t	thisino;	/* current inode number, for loop */
3ccb8b5f6   Glen Overby   [XFS] A change to...
247
  	int		isaligned = 0;	/* inode allocation at stripe unit */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  					/* boundary */
44b56e0a1   Dave Chinner   xfs: convert rema...
249
  	struct xfs_perag *pag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  
  	args.tp = tp;
  	args.mp = tp->t_mountp;
  
  	/*
  	 * Locking will ensure that we don't have two callers in here
  	 * at one time.
  	 */
  	newlen = XFS_IALLOC_INODES(args.mp);
  	if (args.mp->m_maxicount &&
  	    args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
  		return XFS_ERROR(ENOSPC);
  	args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
  	/*
3ccb8b5f6   Glen Overby   [XFS] A change to...
264
265
266
267
  	 * First try to allocate inodes contiguous with the last-allocated
  	 * chunk of inodes.  If the filesystem is striped, this will fill
  	 * an entire stripe unit with inodes.
   	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  	agi = XFS_BUF_TO_AGI(agbp);
3ccb8b5f6   Glen Overby   [XFS] A change to...
269
  	newino = be32_to_cpu(agi->agi_newino);
85c0b2ab5   Dave Chinner   xfs: factor out i...
270
  	agno = be32_to_cpu(agi->agi_seqno);
019ff2d57   Nathan Scott   [XFS] Fix a probl...
271
272
273
274
  	args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
  			XFS_IALLOC_BLOCKS(args.mp);
  	if (likely(newino != NULLAGINO &&
  		  (args.agbno < be32_to_cpu(agi->agi_length)))) {
85c0b2ab5   Dave Chinner   xfs: factor out i...
275
  		args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
3ccb8b5f6   Glen Overby   [XFS] A change to...
276
277
278
279
  		args.type = XFS_ALLOCTYPE_THIS_BNO;
  		args.mod = args.total = args.wasdel = args.isfl =
  			args.userdata = args.minalignslop = 0;
  		args.prod = 1;
75de2a91c   David Chinner   [XFS] Account for...
280

3ccb8b5f6   Glen Overby   [XFS] A change to...
281
  		/*
75de2a91c   David Chinner   [XFS] Account for...
282
283
284
285
286
287
288
289
290
291
292
  		 * We need to take into account alignment here to ensure that
  		 * we don't modify the free list if we fail to have an exact
  		 * block. If we don't have an exact match, and every oher
  		 * attempt allocation attempt fails, we'll end up cancelling
  		 * a dirty transaction and shutting down.
  		 *
  		 * For an exact allocation, alignment must be 1,
  		 * however we need to take cluster alignment into account when
  		 * fixing up the freelist. Use the minalignslop field to
  		 * indicate that extra blocks might be required for alignment,
  		 * but not to use them in the actual exact allocation.
3ccb8b5f6   Glen Overby   [XFS] A change to...
293
  		 */
75de2a91c   David Chinner   [XFS] Account for...
294
295
296
297
  		args.alignment = 1;
  		args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1;
  
  		/* Allow space for the inode btree to split. */
0d87e656d   Christoph Hellwig   xfs: remove super...
298
  		args.minleft = args.mp->m_in_maxlevels - 1;
3ccb8b5f6   Glen Overby   [XFS] A change to...
299
300
301
302
  		if ((error = xfs_alloc_vextent(&args)))
  			return error;
  	} else
  		args.fsbno = NULLFSBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303

3ccb8b5f6   Glen Overby   [XFS] A change to...
304
305
306
307
308
  	if (unlikely(args.fsbno == NULLFSBLOCK)) {
  		/*
  		 * Set the alignment for the allocation.
  		 * If stripe alignment is turned on then align at stripe unit
  		 * boundary.
019ff2d57   Nathan Scott   [XFS] Fix a probl...
309
310
  		 * If the cluster size is smaller than a filesystem block
  		 * then we're doing I/O for inodes in filesystem block size
3ccb8b5f6   Glen Overby   [XFS] A change to...
311
312
313
314
315
316
317
  		 * pieces, so don't need alignment anyway.
  		 */
  		isaligned = 0;
  		if (args.mp->m_sinoalign) {
  			ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
  			args.alignment = args.mp->m_dalign;
  			isaligned = 1;
75de2a91c   David Chinner   [XFS] Account for...
318
319
  		} else
  			args.alignment = xfs_ialloc_cluster_alignment(&args);
3ccb8b5f6   Glen Overby   [XFS] A change to...
320
321
322
323
324
325
  		/*
  		 * Need to figure out where to allocate the inode blocks.
  		 * Ideally they should be spaced out through the a.g.
  		 * For now, just allocate blocks up front.
  		 */
  		args.agbno = be32_to_cpu(agi->agi_root);
85c0b2ab5   Dave Chinner   xfs: factor out i...
326
  		args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
3ccb8b5f6   Glen Overby   [XFS] A change to...
327
328
329
330
331
332
333
334
335
336
  		/*
  		 * Allocate a fixed-size extent of inodes.
  		 */
  		args.type = XFS_ALLOCTYPE_NEAR_BNO;
  		args.mod = args.total = args.wasdel = args.isfl =
  			args.userdata = args.minalignslop = 0;
  		args.prod = 1;
  		/*
  		 * Allow space for the inode btree to split.
  		 */
0d87e656d   Christoph Hellwig   xfs: remove super...
337
  		args.minleft = args.mp->m_in_maxlevels - 1;
3ccb8b5f6   Glen Overby   [XFS] A change to...
338
339
340
  		if ((error = xfs_alloc_vextent(&args)))
  			return error;
  	}
019ff2d57   Nathan Scott   [XFS] Fix a probl...
341

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
344
345
346
347
  	/*
  	 * If stripe alignment is turned on, then try again with cluster
  	 * alignment.
  	 */
  	if (isaligned && args.fsbno == NULLFSBLOCK) {
  		args.type = XFS_ALLOCTYPE_NEAR_BNO;
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
348
  		args.agbno = be32_to_cpu(agi->agi_root);
85c0b2ab5   Dave Chinner   xfs: factor out i...
349
  		args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
75de2a91c   David Chinner   [XFS] Account for...
350
  		args.alignment = xfs_ialloc_cluster_alignment(&args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
359
  		if ((error = xfs_alloc_vextent(&args)))
  			return error;
  	}
  
  	if (args.fsbno == NULLFSBLOCK) {
  		*alloc = 0;
  		return 0;
  	}
  	ASSERT(args.len == args.minlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360

359346a96   David Chinner   [XFS] Don't initi...
361
  	/*
85c0b2ab5   Dave Chinner   xfs: factor out i...
362
363
  	 * Stamp and write the inode buffers.
  	 *
359346a96   David Chinner   [XFS] Don't initi...
364
365
366
367
368
369
  	 * Seed the new inode cluster with a random generation number. This
  	 * prevents short-term reuse of generation numbers if a chunk is
  	 * freed and then immediately reallocated. We use random numbers
  	 * rather than a linear progression to prevent the next generation
  	 * number from being easily guessable.
  	 */
2a30f36d9   Chandra Seetharaman   xfs: Check the re...
370
371
  	error = xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno,
  			args.len, random32());
d42f08f61   Christoph Hellwig   [XFS] kill xfs_ia...
372

2a30f36d9   Chandra Seetharaman   xfs: Check the re...
373
374
  	if (error)
  		return error;
85c0b2ab5   Dave Chinner   xfs: factor out i...
375
376
377
378
  	/*
  	 * Convert the results.
  	 */
  	newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0);
413d57c99   Marcin Slusarz   xfs: convert beX_...
379
380
  	be32_add_cpu(&agi->agi_count, newlen);
  	be32_add_cpu(&agi->agi_freecount, newlen);
44b56e0a1   Dave Chinner   xfs: convert rema...
381
382
383
  	pag = xfs_perag_get(args.mp, agno);
  	pag->pagi_freecount += newlen;
  	xfs_perag_put(pag);
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
384
  	agi->agi_newino = cpu_to_be32(newino);
85c0b2ab5   Dave Chinner   xfs: factor out i...
385

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
  	/*
  	 * Insert records describing the new inode chunk into the btree.
  	 */
561f7d173   Christoph Hellwig   [XFS] split up xf...
389
  	cur = xfs_inobt_init_cursor(args.mp, tp, agbp, agno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
  	for (thisino = newino;
  	     thisino < newino + newlen;
  	     thisino += XFS_INODES_PER_CHUNK) {
218755052   Christoph Hellwig   xfs: rationalize ...
393
394
395
396
397
  		cur->bc_rec.i.ir_startino = thisino;
  		cur->bc_rec.i.ir_freecount = XFS_INODES_PER_CHUNK;
  		cur->bc_rec.i.ir_free = XFS_INOBT_ALL_FREE;
  		error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, &i);
  		if (error) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
  			xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
  			return error;
  		}
  		ASSERT(i == 0);
218755052   Christoph Hellwig   xfs: rationalize ...
402
403
  		error = xfs_btree_insert(cur, &i);
  		if (error) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
  			xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
  			return error;
  		}
  		ASSERT(i == 1);
  	}
  	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
  	/*
  	 * Log allocation group header fields
  	 */
  	xfs_ialloc_log_agi(tp, agbp,
  		XFS_AGI_COUNT | XFS_AGI_FREECOUNT | XFS_AGI_NEWINO);
  	/*
  	 * Modify/log superblock values for inode count and inode free count.
  	 */
  	xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, (long)newlen);
  	xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, (long)newlen);
  	*alloc = 1;
  	return 0;
  }
b8f82a4a6   Christoph Hellwig   xfs: kill the STA...
423
  STATIC xfs_agnumber_t
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  xfs_ialloc_next_ag(
  	xfs_mount_t	*mp)
  {
  	xfs_agnumber_t	agno;
  
  	spin_lock(&mp->m_agirotor_lock);
  	agno = mp->m_agirotor;
  	if (++mp->m_agirotor == mp->m_maxagi)
  		mp->m_agirotor = 0;
  	spin_unlock(&mp->m_agirotor_lock);
  
  	return agno;
  }
  
  /*
   * Select an allocation group to look for a free inode in, based on the parent
   * inode and then mode.  Return the allocation group buffer.
   */
  STATIC xfs_buf_t *			/* allocation group buffer */
  xfs_ialloc_ag_select(
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_ino_t	parent,		/* parent directory inode number */
576b1d67c   Al Viro   xfs: propagate um...
446
  	umode_t		mode,		/* bits set to indicate file type */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  	int		okalloc)	/* ok to allocate more space */
  {
  	xfs_buf_t	*agbp;		/* allocation group header buffer */
  	xfs_agnumber_t	agcount;	/* number of ag's in the filesystem */
  	xfs_agnumber_t	agno;		/* current ag number */
  	int		flags;		/* alloc buffer locking flags */
  	xfs_extlen_t	ineed;		/* blocks needed for inode allocation */
  	xfs_extlen_t	longest = 0;	/* longest extent available */
  	xfs_mount_t	*mp;		/* mount point structure */
  	int		needspace;	/* file mode implies space allocated */
  	xfs_perag_t	*pag;		/* per allocation group data */
  	xfs_agnumber_t	pagno;		/* parent (starting) ag number */
  
  	/*
  	 * Files of these types need at least one block if length > 0
  	 * (and they won't fit in the inode, but that's hard to figure out).
  	 */
  	needspace = S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode);
  	mp = tp->t_mountp;
  	agcount = mp->m_maxagi;
  	if (S_ISDIR(mode))
  		pagno = xfs_ialloc_next_ag(mp);
  	else {
  		pagno = XFS_INO_TO_AGNO(mp, parent);
  		if (pagno >= agcount)
  			pagno = 0;
  	}
  	ASSERT(pagno < agcount);
  	/*
  	 * Loop through allocation groups, looking for one with a little
  	 * free space in it.  Note we don't look for free inodes, exactly.
  	 * Instead, we include whether there is a need to allocate inodes
  	 * to mean that blocks must be allocated for them,
  	 * if none are currently free.
  	 */
  	agno = pagno;
  	flags = XFS_ALLOC_FLAG_TRYLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  	for (;;) {
44b56e0a1   Dave Chinner   xfs: convert rema...
485
  		pag = xfs_perag_get(mp, agno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  		if (!pag->pagi_init) {
  			if (xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
  				agbp = NULL;
  				goto nextag;
  			}
  		} else
  			agbp = NULL;
  
  		if (!pag->pagi_inodeok) {
  			xfs_ialloc_next_ag(mp);
  			goto unlock_nextag;
  		}
  
  		/*
  		 * Is there enough free space for the file plus a block
  		 * of inodes (if we need to allocate some)?
  		 */
  		ineed = pag->pagi_freecount ? 0 : XFS_IALLOC_BLOCKS(mp);
  		if (ineed && !pag->pagf_init) {
  			if (agbp == NULL &&
  			    xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
  				agbp = NULL;
  				goto nextag;
  			}
  			(void)xfs_alloc_pagf_init(mp, tp, agno, flags);
  		}
  		if (!ineed || pag->pagf_init) {
  			if (ineed && !(longest = pag->pagf_longest))
  				longest = pag->pagf_flcount > 0;
  			if (!ineed ||
  			    (pag->pagf_freeblks >= needspace + ineed &&
  			     longest >= ineed &&
  			     okalloc)) {
  				if (agbp == NULL &&
  				    xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
  					agbp = NULL;
  					goto nextag;
  				}
44b56e0a1   Dave Chinner   xfs: convert rema...
524
  				xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
529
530
531
  				return agbp;
  			}
  		}
  unlock_nextag:
  		if (agbp)
  			xfs_trans_brelse(tp, agbp);
  nextag:
44b56e0a1   Dave Chinner   xfs: convert rema...
532
  		xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
536
  		/*
  		 * No point in iterating over the rest, if we're shutting
  		 * down.
  		 */
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
537
  		if (XFS_FORCED_SHUTDOWN(mp))
1121b219b   Nathan Scott   [XFS] use NULL fo...
538
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
541
542
  		agno++;
  		if (agno >= agcount)
  			agno = 0;
  		if (agno == pagno) {
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
543
  			if (flags == 0)
1121b219b   Nathan Scott   [XFS] use NULL fo...
544
  				return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
547
548
  			flags = 0;
  		}
  	}
  }
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
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
  /*
   * Try to retrieve the next record to the left/right from the current one.
   */
  STATIC int
  xfs_ialloc_next_rec(
  	struct xfs_btree_cur	*cur,
  	xfs_inobt_rec_incore_t	*rec,
  	int			*done,
  	int			left)
  {
  	int                     error;
  	int			i;
  
  	if (left)
  		error = xfs_btree_decrement(cur, 0, &i);
  	else
  		error = xfs_btree_increment(cur, 0, &i);
  
  	if (error)
  		return error;
  	*done = !i;
  	if (i) {
  		error = xfs_inobt_get_rec(cur, rec, &i);
  		if (error)
  			return error;
  		XFS_WANT_CORRUPTED_RETURN(i == 1);
  	}
  
  	return 0;
  }
bd1695659   Dave Chinner   xfs: speed up fre...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
  STATIC int
  xfs_ialloc_get_rec(
  	struct xfs_btree_cur	*cur,
  	xfs_agino_t		agino,
  	xfs_inobt_rec_incore_t	*rec,
  	int			*done,
  	int			left)
  {
  	int                     error;
  	int			i;
  
  	error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_EQ, &i);
  	if (error)
  		return error;
  	*done = !i;
  	if (i) {
  		error = xfs_inobt_get_rec(cur, rec, &i);
  		if (error)
  			return error;
  		XFS_WANT_CORRUPTED_RETURN(i == 1);
  	}
  
  	return 0;
  }
0b48db80b   Dave Chinner   xfs: factor out d...
603

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  /*
   * Visible inode allocation functions.
   */
  
  /*
   * Allocate an inode on disk.
   * Mode is used to tell whether the new inode will need space, and whether
   * it is a directory.
   *
   * The arguments IO_agbp and alloc_done are defined to work within
   * the constraint of one allocation per transaction.
   * xfs_dialloc() is designed to be called twice if it has to do an
   * allocation to make more free inodes.  On the first call,
   * IO_agbp should be set to NULL. If an inode is available,
   * i.e., xfs_dialloc() did not need to do an allocation, an inode
   * number is returned.  In this case, IO_agbp would be set to the
   * current ag_buf and alloc_done set to false.
   * If an allocation needed to be done, xfs_dialloc would return
   * the current ag_buf in IO_agbp and set alloc_done to true.
   * The caller should then commit the current transaction, allocate a new
   * transaction, and call xfs_dialloc() again, passing in the previous
   * value of IO_agbp.  IO_agbp should be held across the transactions.
   * Since the agbp is locked across the two calls, the second call is
   * guaranteed to have a free inode available.
   *
   * Once we successfully pick an inode its number is returned and the
   * on-disk data structures are updated.  The inode itself is not read
   * in, since doing so would break ordering constraints with xfs_reclaim.
   */
  int
  xfs_dialloc(
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_ino_t	parent,		/* parent inode (directory) */
576b1d67c   Al Viro   xfs: propagate um...
637
  	umode_t		mode,		/* mode bits for new inode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  	int		okalloc,	/* ok to allocate more space */
  	xfs_buf_t	**IO_agbp,	/* in/out ag header's buffer */
  	boolean_t	*alloc_done,	/* true if we needed to replenish
  					   inode freelist */
  	xfs_ino_t	*inop)		/* inode number allocated */
  {
  	xfs_agnumber_t	agcount;	/* number of allocation groups */
  	xfs_buf_t	*agbp;		/* allocation group header's buffer */
  	xfs_agnumber_t	agno;		/* allocation group number */
  	xfs_agi_t	*agi;		/* allocation group header structure */
  	xfs_btree_cur_t	*cur;		/* inode allocation btree cursor */
  	int		error;		/* error return value */
  	int		i;		/* result code */
  	int		ialloced;	/* inode allocation status */
  	int		noroom = 0;	/* no space for inode blk allocation */
  	xfs_ino_t	ino;		/* fs-relative inode to be returned */
  	/* REFERENCED */
  	int		j;		/* result code */
  	xfs_mount_t	*mp;		/* file system mount structure */
  	int		offset;		/* index of inode in chunk */
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
658
659
  	xfs_agino_t	pagino;		/* parent's AG relative inode # */
  	xfs_agnumber_t	pagno;		/* parent's AG number */
61a258486   Christoph Hellwig   [XFS] endianess a...
660
  	xfs_inobt_rec_incore_t rec;	/* inode allocation record */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
  	xfs_agnumber_t	tagno;		/* testing allocation group number */
  	xfs_btree_cur_t	*tcur;		/* temp cursor */
61a258486   Christoph Hellwig   [XFS] endianess a...
663
  	xfs_inobt_rec_incore_t trec;	/* temp inode allocation record */
44b56e0a1   Dave Chinner   xfs: convert rema...
664
  	struct xfs_perag *pag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  
  
  	if (*IO_agbp == NULL) {
  		/*
  		 * We do not have an agbp, so select an initial allocation
  		 * group for inode allocation.
  		 */
  		agbp = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
  		/*
  		 * Couldn't find an allocation group satisfying the
  		 * criteria, give up.
  		 */
  		if (!agbp) {
  			*inop = NULLFSINO;
  			return 0;
  		}
  		agi = XFS_BUF_TO_AGI(agbp);
69ef921b5   Christoph Hellwig   xfs: byteswap con...
682
  		ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
684
685
686
687
688
689
  	} else {
  		/*
  		 * Continue where we left off before.  In this case, we
  		 * know that the allocation group has free inodes.
  		 */
  		agbp = *IO_agbp;
  		agi = XFS_BUF_TO_AGI(agbp);
69ef921b5   Christoph Hellwig   xfs: byteswap con...
690
  		ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
691
  		ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
  	}
  	mp = tp->t_mountp;
  	agcount = mp->m_sb.sb_agcount;
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
695
  	agno = be32_to_cpu(agi->agi_seqno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
  	tagno = agno;
  	pagno = XFS_INO_TO_AGNO(mp, parent);
  	pagino = XFS_INO_TO_AGINO(mp, parent);
  
  	/*
  	 * If we have already hit the ceiling of inode blocks then clear
  	 * okalloc so we scan all available agi structures for a free
  	 * inode.
  	 */
  
  	if (mp->m_maxicount &&
  	    mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) {
  		noroom = 1;
  		okalloc = 0;
  	}
  
  	/*
  	 * Loop until we find an allocation group that either has free inodes
  	 * or in which we can allocate some inodes.  Iterate through the
  	 * allocation groups upward, wrapping at the end.
  	 */
  	*alloc_done = B_FALSE;
  	while (!agi->agi_freecount) {
  		/*
  		 * Don't do anything if we're not supposed to allocate
  		 * any blocks, just go on to the next ag.
  		 */
  		if (okalloc) {
  			/*
  			 * Try to allocate some new inodes in the allocation
  			 * group.
  			 */
  			if ((error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced))) {
  				xfs_trans_brelse(tp, agbp);
  				if (error == ENOSPC) {
  					*inop = NULLFSINO;
  					return 0;
  				} else
  					return error;
  			}
  			if (ialloced) {
  				/*
  				 * We successfully allocated some inodes, return
  				 * the current context to the caller so that it
  				 * can commit the current transaction and call
  				 * us again where we left off.
  				 */
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
743
  				ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
  				*alloc_done = B_TRUE;
  				*IO_agbp = agbp;
  				*inop = NULLFSINO;
  				return 0;
  			}
  		}
  		/*
  		 * If it failed, give up on this ag.
  		 */
  		xfs_trans_brelse(tp, agbp);
  		/*
  		 * Go on to the next ag: get its ag header.
  		 */
  nextag:
  		if (++tagno == agcount)
  			tagno = 0;
  		if (tagno == agno) {
  			*inop = NULLFSINO;
  			return noroom ? ENOSPC : 0;
  		}
44b56e0a1   Dave Chinner   xfs: convert rema...
764
765
766
  		pag = xfs_perag_get(mp, tagno);
  		if (pag->pagi_inodeok == 0) {
  			xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
769
  			goto nextag;
  		}
  		error = xfs_ialloc_read_agi(mp, tp, tagno, &agbp);
44b56e0a1   Dave Chinner   xfs: convert rema...
770
  		xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
773
  		if (error)
  			goto nextag;
  		agi = XFS_BUF_TO_AGI(agbp);
69ef921b5   Christoph Hellwig   xfs: byteswap con...
774
  		ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
777
778
779
780
781
782
  	}
  	/*
  	 * Here with an allocation group that has a free inode.
  	 * Reset agno since we may have chosen a new ag in the
  	 * loop above.
  	 */
  	agno = tagno;
  	*IO_agbp = NULL;
44b56e0a1   Dave Chinner   xfs: convert rema...
783
  	pag = xfs_perag_get(mp, agno);
bd1695659   Dave Chinner   xfs: speed up fre...
784
785
  
   restart_pagno:
561f7d173   Christoph Hellwig   [XFS] split up xf...
786
  	cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
788
789
790
791
  	/*
  	 * If pagino is 0 (this is the root inode allocation) use newino.
  	 * This must work because we've just allocated some.
  	 */
  	if (!pagino)
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
792
  		pagino = be32_to_cpu(agi->agi_newino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793

0b48db80b   Dave Chinner   xfs: factor out d...
794
795
796
  	error = xfs_check_agi_freecount(cur, agi);
  	if (error)
  		goto error0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  	/*
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
799
  	 * If in the same AG as the parent, try to get near the parent.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
  	 */
  	if (pagno == agno) {
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
802
803
  		int		doneleft;	/* done, to the left */
  		int		doneright;	/* done, to the right */
bd1695659   Dave Chinner   xfs: speed up fre...
804
  		int		searchdistance = 10;
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
805

218755052   Christoph Hellwig   xfs: rationalize ...
806
  		error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i);
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
807
  		if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  			goto error0;
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
809
810
811
812
813
814
815
816
  		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  
  		error = xfs_inobt_get_rec(cur, &rec, &j);
  		if (error)
  			goto error0;
  		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  
  		if (rec.ir_freecount > 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  			/*
  			 * Found a free inode in the same chunk
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
819
  			 * as the parent, done.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  			 */
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
821
  			goto alloc_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  		}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
823

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  		/*
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
825
  		 * In the same AG as parent, but parent's chunk is full.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827

4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
828
829
830
831
  		/* duplicate the cursor, search left & right simultaneously */
  		error = xfs_btree_dup_cursor(cur, &tcur);
  		if (error)
  			goto error0;
bd1695659   Dave Chinner   xfs: speed up fre...
832
833
834
835
836
837
838
839
840
841
842
  		/*
  		 * Skip to last blocks looked up if same parent inode.
  		 */
  		if (pagino != NULLAGINO &&
  		    pag->pagl_pagino == pagino &&
  		    pag->pagl_leftrec != NULLAGINO &&
  		    pag->pagl_rightrec != NULLAGINO) {
  			error = xfs_ialloc_get_rec(tcur, pag->pagl_leftrec,
  						   &trec, &doneleft, 1);
  			if (error)
  				goto error1;
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
843

bd1695659   Dave Chinner   xfs: speed up fre...
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
  			error = xfs_ialloc_get_rec(cur, pag->pagl_rightrec,
  						   &rec, &doneright, 0);
  			if (error)
  				goto error1;
  		} else {
  			/* search left with tcur, back up 1 record */
  			error = xfs_ialloc_next_rec(tcur, &trec, &doneleft, 1);
  			if (error)
  				goto error1;
  
  			/* search right with cur, go forward 1 record. */
  			error = xfs_ialloc_next_rec(cur, &rec, &doneright, 0);
  			if (error)
  				goto error1;
  		}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
859
860
861
862
863
864
  
  		/*
  		 * Loop until we find an inode chunk with a free inode.
  		 */
  		while (!doneleft || !doneright) {
  			int	useleft;  /* using left inode chunk this time */
bd1695659   Dave Chinner   xfs: speed up fre...
865
866
867
868
869
  			if (!--searchdistance) {
  				/*
  				 * Not in range - save last search
  				 * location and allocate a new inode
  				 */
3b826386d   Eric Sandeen   xfs: free tempora...
870
  				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
bd1695659   Dave Chinner   xfs: speed up fre...
871
872
873
874
875
  				pag->pagl_leftrec = trec.ir_startino;
  				pag->pagl_rightrec = rec.ir_startino;
  				pag->pagl_pagino = pagino;
  				goto newino;
  			}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
876
877
878
879
880
881
882
  			/* figure out the closer block if both are valid. */
  			if (!doneleft && !doneright) {
  				useleft = pagino -
  				 (trec.ir_startino + XFS_INODES_PER_CHUNK - 1) <
  				  rec.ir_startino - pagino;
  			} else {
  				useleft = !doneleft;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
  			}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
884
885
886
887
888
889
  
  			/* free inodes to the left? */
  			if (useleft && trec.ir_freecount) {
  				rec = trec;
  				xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
  				cur = tcur;
bd1695659   Dave Chinner   xfs: speed up fre...
890
891
892
893
  
  				pag->pagl_leftrec = trec.ir_startino;
  				pag->pagl_rightrec = rec.ir_startino;
  				pag->pagl_pagino = pagino;
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
894
  				goto alloc_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896

4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
897
898
899
  			/* free inodes to the right? */
  			if (!useleft && rec.ir_freecount) {
  				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
bd1695659   Dave Chinner   xfs: speed up fre...
900
901
902
903
  
  				pag->pagl_leftrec = trec.ir_startino;
  				pag->pagl_rightrec = rec.ir_startino;
  				pag->pagl_pagino = pagino;
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
904
  				goto alloc_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  			}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
906
907
908
909
910
911
912
913
914
915
916
  
  			/* get next record to check */
  			if (useleft) {
  				error = xfs_ialloc_next_rec(tcur, &trec,
  								 &doneleft, 1);
  			} else {
  				error = xfs_ialloc_next_rec(cur, &rec,
  								 &doneright, 0);
  			}
  			if (error)
  				goto error1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
  		}
bd1695659   Dave Chinner   xfs: speed up fre...
918
919
920
921
922
923
924
925
926
927
928
929
930
931
  
  		/*
  		 * We've reached the end of the btree. because
  		 * we are only searching a small chunk of the
  		 * btree each search, there is obviously free
  		 * inodes closer to the parent inode than we
  		 * are now. restart the search again.
  		 */
  		pag->pagl_pagino = NULLAGINO;
  		pag->pagl_leftrec = NULLAGINO;
  		pag->pagl_rightrec = NULLAGINO;
  		xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
  		goto restart_pagno;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
  	}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
933

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
  	/*
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
935
  	 * In a different AG from the parent.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
  	 * See if the most recently allocated block has any free.
  	 */
bd1695659   Dave Chinner   xfs: speed up fre...
938
  newino:
69ef921b5   Christoph Hellwig   xfs: byteswap con...
939
  	if (agi->agi_newino != cpu_to_be32(NULLAGINO)) {
218755052   Christoph Hellwig   xfs: rationalize ...
940
941
  		error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino),
  					 XFS_LOOKUP_EQ, &i);
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
942
  		if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
  			goto error0;
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
944
945
946
947
948
949
950
951
952
953
954
955
956
  
  		if (i == 1) {
  			error = xfs_inobt_get_rec(cur, &rec, &j);
  			if (error)
  				goto error0;
  
  			if (j == 1 && rec.ir_freecount > 0) {
  				/*
  				 * The last chunk allocated in the group
  				 * still has a free inode.
  				 */
  				goto alloc_inode;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
  		}
bd1695659   Dave Chinner   xfs: speed up fre...
958
  	}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
959

bd1695659   Dave Chinner   xfs: speed up fre...
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
  	/*
  	 * None left in the last group, search the whole AG
  	 */
  	error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i);
  	if (error)
  		goto error0;
  	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  
  	for (;;) {
  		error = xfs_inobt_get_rec(cur, &rec, &i);
  		if (error)
  			goto error0;
  		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  		if (rec.ir_freecount > 0)
  			break;
  		error = xfs_btree_increment(cur, 0, &i);
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
976
977
978
  		if (error)
  			goto error0;
  		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  	}
4254b0bbb   Christoph Hellwig   xfs: untangle xfs...
980
981
  
  alloc_inode:
9d87c3192   Eric Sandeen   [XFS] Remove the ...
982
  	offset = xfs_ialloc_find_free(&rec.ir_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
985
986
987
  	ASSERT(offset >= 0);
  	ASSERT(offset < XFS_INODES_PER_CHUNK);
  	ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
  				   XFS_INODES_PER_CHUNK) == 0);
  	ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
0d87e656d   Christoph Hellwig   xfs: remove super...
988
  	rec.ir_free &= ~XFS_INOBT_MASK(offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  	rec.ir_freecount--;
afabc24a7   Christoph Hellwig   xfs: improve xfs_...
990
991
  	error = xfs_inobt_update(cur, &rec);
  	if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992
  		goto error0;
413d57c99   Marcin Slusarz   xfs: convert beX_...
993
  	be32_add_cpu(&agi->agi_freecount, -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  	xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
44b56e0a1   Dave Chinner   xfs: convert rema...
995
  	pag->pagi_freecount--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996

0b48db80b   Dave Chinner   xfs: factor out d...
997
998
999
  	error = xfs_check_agi_freecount(cur, agi);
  	if (error)
  		goto error0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
1001
  	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
  	xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1);
44b56e0a1   Dave Chinner   xfs: convert rema...
1002
  	xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
1004
1005
1006
1007
1008
  	*inop = ino;
  	return 0;
  error1:
  	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
  error0:
  	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
44b56e0a1   Dave Chinner   xfs: convert rema...
1009
  	xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
  	return error;
  }
  
  /*
   * Free disk inode.  Carefully avoids touching the incore inode, all
   * manipulations incore are the caller's responsibility.
   * The on-disk inode is not changed by this operation, only the
   * btree (free inode mask) is changed.
   */
  int
  xfs_difree(
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_ino_t	inode,		/* inode to be freed */
  	xfs_bmap_free_t	*flist,		/* extents to free */
  	int		*delete,	/* set if inode cluster was deleted */
  	xfs_ino_t	*first_ino)	/* first inode in deleted cluster */
  {
  	/* REFERENCED */
  	xfs_agblock_t	agbno;	/* block number containing inode */
  	xfs_buf_t	*agbp;	/* buffer containing allocation group header */
  	xfs_agino_t	agino;	/* inode number relative to allocation group */
  	xfs_agnumber_t	agno;	/* allocation group number */
  	xfs_agi_t	*agi;	/* allocation group header */
  	xfs_btree_cur_t	*cur;	/* inode btree cursor */
  	int		error;	/* error return value */
  	int		i;	/* result code */
  	int		ilen;	/* inodes in an inode cluster */
  	xfs_mount_t	*mp;	/* mount structure for filesystem */
  	int		off;	/* offset of inode in inode chunk */
61a258486   Christoph Hellwig   [XFS] endianess a...
1039
  	xfs_inobt_rec_incore_t rec;	/* btree record */
44b56e0a1   Dave Chinner   xfs: convert rema...
1040
  	struct xfs_perag *pag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
1042
1043
1044
1045
1046
1047
1048
  
  	mp = tp->t_mountp;
  
  	/*
  	 * Break up inode number into its components.
  	 */
  	agno = XFS_INO_TO_AGNO(mp, inode);
  	if (agno >= mp->m_sb.sb_agcount)  {
0b932cccb   Dave Chinner   xfs: Convert rema...
1049
1050
  		xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).",
  			__func__, agno, mp->m_sb.sb_agcount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
1052
1053
1054
1055
  		ASSERT(0);
  		return XFS_ERROR(EINVAL);
  	}
  	agino = XFS_INO_TO_AGINO(mp, inode);
  	if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  {
0b932cccb   Dave Chinner   xfs: Convert rema...
1056
1057
1058
  		xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).",
  			__func__, (unsigned long long)inode,
  			(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
1060
1061
1062
1063
  		ASSERT(0);
  		return XFS_ERROR(EINVAL);
  	}
  	agbno = XFS_AGINO_TO_AGBNO(mp, agino);
  	if (agbno >= mp->m_sb.sb_agblocks)  {
0b932cccb   Dave Chinner   xfs: Convert rema...
1064
1065
  		xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
  			__func__, agbno, mp->m_sb.sb_agblocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
1067
1068
1069
1070
1071
  		ASSERT(0);
  		return XFS_ERROR(EINVAL);
  	}
  	/*
  	 * Get the allocation group header.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1072
  	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1074
1075
  		xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.",
  			__func__, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
  		return error;
  	}
  	agi = XFS_BUF_TO_AGI(agbp);
69ef921b5   Christoph Hellwig   xfs: byteswap con...
1079
  	ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
1080
  	ASSERT(agbno < be32_to_cpu(agi->agi_length));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081
1082
1083
  	/*
  	 * Initialize the cursor.
  	 */
561f7d173   Christoph Hellwig   [XFS] split up xf...
1084
  	cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085

0b48db80b   Dave Chinner   xfs: factor out d...
1086
1087
1088
  	error = xfs_check_agi_freecount(cur, agi);
  	if (error)
  		goto error0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
1091
  	/*
  	 * Look for the entry describing this inode.
  	 */
218755052   Christoph Hellwig   xfs: rationalize ...
1092
  	if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1093
1094
  		xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.",
  			__func__, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
1096
1097
  		goto error0;
  	}
  	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2e287a731   Christoph Hellwig   xfs: improve xfs_...
1098
1099
  	error = xfs_inobt_get_rec(cur, &rec, &i);
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1100
1101
  		xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.",
  			__func__, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102
1103
1104
1105
1106
1107
1108
1109
  		goto error0;
  	}
  	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  	/*
  	 * Get the offset in the inode chunk.
  	 */
  	off = agino - rec.ir_startino;
  	ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK);
0d87e656d   Christoph Hellwig   xfs: remove super...
1110
  	ASSERT(!(rec.ir_free & XFS_INOBT_MASK(off)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
  	/*
  	 * Mark the inode free & increment the count.
  	 */
0d87e656d   Christoph Hellwig   xfs: remove super...
1114
  	rec.ir_free |= XFS_INOBT_MASK(off);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
  	rec.ir_freecount++;
  
  	/*
c41564b5a   Nathan Scott   [XFS] We really s...
1118
  	 * When an inode cluster is free, it becomes eligible for removal
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
  	 */
1bd960ee2   Josef Jeff Sipek   [XFS] If you moun...
1120
  	if (!(mp->m_flags & XFS_MOUNT_IKEEP) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  	    (rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
  
  		*delete = 1;
  		*first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);
  
  		/*
  		 * Remove the inode cluster from the AGI B+Tree, adjust the
  		 * AGI and Superblock inode counts, and mark the disk space
  		 * to be freed when the transaction is committed.
  		 */
  		ilen = XFS_IALLOC_INODES(mp);
413d57c99   Marcin Slusarz   xfs: convert beX_...
1132
1133
  		be32_add_cpu(&agi->agi_count, -ilen);
  		be32_add_cpu(&agi->agi_freecount, -(ilen - 1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
  		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
44b56e0a1   Dave Chinner   xfs: convert rema...
1135
1136
1137
  		pag = xfs_perag_get(mp, agno);
  		pag->pagi_freecount -= ilen - 1;
  		xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
1139
  		xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen);
  		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));
91cca5df9   Christoph Hellwig   [XFS] implement g...
1140
  		if ((error = xfs_btree_delete(cur, &i))) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1141
1142
  			xfs_warn(mp, "%s: xfs_btree_delete returned error %d.",
  				__func__, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
1145
1146
1147
1148
1149
1150
  			goto error0;
  		}
  
  		xfs_bmap_add_free(XFS_AGB_TO_FSB(mp,
  				agno, XFS_INO_TO_AGBNO(mp,rec.ir_startino)),
  				XFS_IALLOC_BLOCKS(mp), flist, mp);
  	} else {
  		*delete = 0;
afabc24a7   Christoph Hellwig   xfs: improve xfs_...
1151
1152
  		error = xfs_inobt_update(cur, &rec);
  		if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1153
1154
  			xfs_warn(mp, "%s: xfs_inobt_update returned error %d.",
  				__func__, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
1156
  			goto error0;
  		}
afabc24a7   Christoph Hellwig   xfs: improve xfs_...
1157

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
1159
1160
  		/* 
  		 * Change the inode free counts and log the ag/sb changes.
  		 */
413d57c99   Marcin Slusarz   xfs: convert beX_...
1161
  		be32_add_cpu(&agi->agi_freecount, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
  		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
44b56e0a1   Dave Chinner   xfs: convert rema...
1163
1164
1165
  		pag = xfs_perag_get(mp, agno);
  		pag->pagi_freecount++;
  		xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
1167
  		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1);
  	}
0b48db80b   Dave Chinner   xfs: factor out d...
1168
1169
1170
  	error = xfs_check_agi_freecount(cur, agi);
  	if (error)
  		goto error0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
1173
1174
1175
1176
1177
1178
  	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
  	return 0;
  
  error0:
  	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
  	return error;
  }
7124fe0a5   Dave Chinner   xfs: validate unt...
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
  STATIC int
  xfs_imap_lookup(
  	struct xfs_mount	*mp,
  	struct xfs_trans	*tp,
  	xfs_agnumber_t		agno,
  	xfs_agino_t		agino,
  	xfs_agblock_t		agbno,
  	xfs_agblock_t		*chunk_agbno,
  	xfs_agblock_t		*offset_agbno,
  	int			flags)
  {
  	struct xfs_inobt_rec_incore rec;
  	struct xfs_btree_cur	*cur;
  	struct xfs_buf		*agbp;
7124fe0a5   Dave Chinner   xfs: validate unt...
1193
1194
1195
1196
1197
  	int			error;
  	int			i;
  
  	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
  	if (error) {
534877869   Dave Chinner   xfs: convert xfs_...
1198
1199
1200
  		xfs_alert(mp,
  			"%s: xfs_ialloc_read_agi() returned error %d, agno %d",
  			__func__, error, agno);
7124fe0a5   Dave Chinner   xfs: validate unt...
1201
1202
1203
1204
  		return error;
  	}
  
  	/*
4536f2ad8   Dave Chinner   xfs: fix untruste...
1205
1206
1207
1208
  	 * Lookup the inode record for the given agino. If the record cannot be
  	 * found, then it's an invalid inode number and we should abort. Once
  	 * we have a record, we need to ensure it contains the inode number
  	 * we are looking up.
7124fe0a5   Dave Chinner   xfs: validate unt...
1209
1210
  	 */
  	cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
4536f2ad8   Dave Chinner   xfs: fix untruste...
1211
  	error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
7124fe0a5   Dave Chinner   xfs: validate unt...
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
  	if (!error) {
  		if (i)
  			error = xfs_inobt_get_rec(cur, &rec, &i);
  		if (!error && i == 0)
  			error = EINVAL;
  	}
  
  	xfs_trans_brelse(tp, agbp);
  	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
  	if (error)
  		return error;
4536f2ad8   Dave Chinner   xfs: fix untruste...
1223
1224
1225
1226
  	/* check that the returned record contains the required inode */
  	if (rec.ir_startino > agino ||
  	    rec.ir_startino + XFS_IALLOC_INODES(mp) <= agino)
  		return EINVAL;
7124fe0a5   Dave Chinner   xfs: validate unt...
1227
  	/* for untrusted inodes check it is allocated first */
1920779e6   Dave Chinner   xfs: rename XFS_I...
1228
  	if ((flags & XFS_IGET_UNTRUSTED) &&
7124fe0a5   Dave Chinner   xfs: validate unt...
1229
1230
1231
1232
1233
1234
1235
  	    (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino)))
  		return EINVAL;
  
  	*chunk_agbno = XFS_AGINO_TO_AGBNO(mp, rec.ir_startino);
  	*offset_agbno = agbno - *chunk_agbno;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  /*
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1237
   * Return the location of the inode in imap, for mapping it into a buffer.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
  int
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1240
1241
1242
  xfs_imap(
  	xfs_mount_t	 *mp,	/* file system mount structure */
  	xfs_trans_t	 *tp,	/* transaction pointer */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
  	xfs_ino_t	ino,	/* inode to locate */
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1244
1245
  	struct xfs_imap	*imap,	/* location map structure */
  	uint		flags)	/* flags for inode btree lookup */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
1247
  {
  	xfs_agblock_t	agbno;	/* block number of inode in the alloc group */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1248
1249
1250
1251
  	xfs_agino_t	agino;	/* inode number within alloc group */
  	xfs_agnumber_t	agno;	/* allocation group number */
  	int		blks_per_cluster; /* num blocks per inode cluster */
  	xfs_agblock_t	chunk_agbno;	/* first block in inode chunk */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
  	xfs_agblock_t	cluster_agbno;	/* first block in inode cluster */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
  	int		error;	/* error code */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
1257
  	int		offset;	/* index of inode in its buffer */
  	int		offset_agbno;	/* blks from chunk start to inode */
  
  	ASSERT(ino != NULLFSINO);
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1258

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
1260
1261
1262
1263
1264
1265
1266
1267
  	/*
  	 * Split up the inode number into its parts.
  	 */
  	agno = XFS_INO_TO_AGNO(mp, ino);
  	agino = XFS_INO_TO_AGINO(mp, ino);
  	agbno = XFS_AGINO_TO_AGBNO(mp, agino);
  	if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
  	    ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
  #ifdef DEBUG
1920779e6   Dave Chinner   xfs: rename XFS_I...
1268
1269
1270
1271
1272
  		/*
  		 * Don't output diagnostic information for untrusted inodes
  		 * as they can be invalid without implying corruption.
  		 */
  		if (flags & XFS_IGET_UNTRUSTED)
4d1a2ed3d   Nathan Scott   [XFS] Fix up debu...
1273
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
  		if (agno >= mp->m_sb.sb_agcount) {
534877869   Dave Chinner   xfs: convert xfs_...
1275
1276
1277
  			xfs_alert(mp,
  				"%s: agno (%d) >= mp->m_sb.sb_agcount (%d)",
  				__func__, agno, mp->m_sb.sb_agcount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
  		}
  		if (agbno >= mp->m_sb.sb_agblocks) {
534877869   Dave Chinner   xfs: convert xfs_...
1280
1281
1282
1283
  			xfs_alert(mp,
  		"%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)",
  				__func__, (unsigned long long)agbno,
  				(unsigned long)mp->m_sb.sb_agblocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
  		}
  		if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
534877869   Dave Chinner   xfs: convert xfs_...
1286
1287
1288
1289
  			xfs_alert(mp,
  		"%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)",
  				__func__, ino,
  				XFS_AGINO_TO_INO(mp, agno, agino));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
  		}
745b1f47f   Nathan Scott   [XFS] Remove last...
1291
  		xfs_stack_trace();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1292
1293
1294
  #endif /* DEBUG */
  		return XFS_ERROR(EINVAL);
  	}
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1295

7124fe0a5   Dave Chinner   xfs: validate unt...
1296
1297
1298
1299
1300
1301
1302
1303
1304
  	blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
  
  	/*
  	 * For bulkstat and handle lookups, we have an untrusted inode number
  	 * that we have to verify is valid. We cannot do this just by reading
  	 * the inode buffer as it may have been unlinked and removed leaving
  	 * inodes in stale state on disk. Hence we have to do a btree lookup
  	 * in all cases where an untrusted inode number is passed.
  	 */
1920779e6   Dave Chinner   xfs: rename XFS_I...
1305
  	if (flags & XFS_IGET_UNTRUSTED) {
7124fe0a5   Dave Chinner   xfs: validate unt...
1306
1307
1308
1309
1310
1311
  		error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
  					&chunk_agbno, &offset_agbno, flags);
  		if (error)
  			return error;
  		goto out_map;
  	}
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1312
1313
1314
1315
1316
  	/*
  	 * If the inode cluster size is the same as the blocksize or
  	 * smaller we get to the buffer by simple arithmetics.
  	 */
  	if (XFS_INODE_CLUSTER_SIZE(mp) <= mp->m_sb.sb_blocksize) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
1318
  		offset = XFS_INO_TO_OFFSET(mp, ino);
  		ASSERT(offset < mp->m_sb.sb_inopblock);
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1319
1320
1321
1322
  
  		imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno);
  		imap->im_len = XFS_FSB_TO_BB(mp, 1);
  		imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
  		return 0;
  	}
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1325

94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1326
  	/*
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1327
1328
1329
1330
  	 * If the inode chunks are aligned then use simple maths to
  	 * find the location. Otherwise we have to do a btree
  	 * lookup to find the location.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
1332
1333
1334
  	if (mp->m_inoalign_mask) {
  		offset_agbno = agbno & mp->m_inoalign_mask;
  		chunk_agbno = agbno - offset_agbno;
  	} else {
7124fe0a5   Dave Chinner   xfs: validate unt...
1335
1336
  		error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
  					&chunk_agbno, &offset_agbno, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
  		if (error)
  			return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
  	}
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1340

7124fe0a5   Dave Chinner   xfs: validate unt...
1341
  out_map:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1342
1343
1344
1345
1346
  	ASSERT(agbno >= chunk_agbno);
  	cluster_agbno = chunk_agbno +
  		((offset_agbno / blks_per_cluster) * blks_per_cluster);
  	offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
  		XFS_INO_TO_OFFSET(mp, ino);
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
  
  	imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno);
  	imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
  	imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
  
  	/*
  	 * If the inode number maps to a block outside the bounds
  	 * of the file system then return NULL rather than calling
  	 * read_buf and panicing when we get an error from the
  	 * driver.
  	 */
  	if ((imap->im_blkno + imap->im_len) >
  	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
534877869   Dave Chinner   xfs: convert xfs_...
1360
1361
1362
  		xfs_alert(mp,
  	"%s: (im_blkno (0x%llx) + im_len (0x%llx)) > sb_dblocks (0x%llx)",
  			__func__, (unsigned long long) imap->im_blkno,
94e1b69d1   Christoph Hellwig   [XFS] merge xfs_i...
1363
1364
1365
1366
  			(unsigned long long) imap->im_len,
  			XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
  		return XFS_ERROR(EINVAL);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
  }
  
  /*
   * Compute and fill in value of m_in_maxlevels.
   */
  void
  xfs_ialloc_compute_maxlevels(
  	xfs_mount_t	*mp)		/* file system mount structure */
  {
  	int		level;
  	uint		maxblocks;
  	uint		maxleafents;
  	int		minleafrecs;
  	int		minnoderecs;
  
  	maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >>
  		XFS_INODES_PER_CHUNK_LOG;
  	minleafrecs = mp->m_alloc_mnr[0];
  	minnoderecs = mp->m_alloc_mnr[1];
  	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
  	for (level = 1; maxblocks > 1; level++)
  		maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
  	mp->m_in_maxlevels = level;
  }
  
  /*
   * Log specified fields for the ag hdr (inode section)
   */
  void
  xfs_ialloc_log_agi(
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_buf_t	*bp,		/* allocation group header buffer */
  	int		fields)		/* bitmask of fields to log */
  {
  	int			first;		/* first byte number */
  	int			last;		/* last byte number */
  	static const short	offsets[] = {	/* field starting offsets */
  					/* keep in sync with bit definitions */
  		offsetof(xfs_agi_t, agi_magicnum),
  		offsetof(xfs_agi_t, agi_versionnum),
  		offsetof(xfs_agi_t, agi_seqno),
  		offsetof(xfs_agi_t, agi_length),
  		offsetof(xfs_agi_t, agi_count),
  		offsetof(xfs_agi_t, agi_root),
  		offsetof(xfs_agi_t, agi_level),
  		offsetof(xfs_agi_t, agi_freecount),
  		offsetof(xfs_agi_t, agi_newino),
  		offsetof(xfs_agi_t, agi_dirino),
  		offsetof(xfs_agi_t, agi_unlinked),
  		sizeof(xfs_agi_t)
  	};
  #ifdef DEBUG
  	xfs_agi_t		*agi;	/* allocation group header */
  
  	agi = XFS_BUF_TO_AGI(bp);
69ef921b5   Christoph Hellwig   xfs: byteswap con...
1423
  	ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
  #endif
  	/*
  	 * Compute byte offsets for the first and last fields.
  	 */
  	xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS, &first, &last);
  	/*
  	 * Log the allocation group inode header buffer.
  	 */
  	xfs_trans_log_buf(tp, bp, first, last);
  }
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
  #ifdef DEBUG
  STATIC void
  xfs_check_agi_unlinked(
  	struct xfs_agi		*agi)
  {
  	int			i;
  
  	for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
  		ASSERT(agi->agi_unlinked[i]);
  }
  #else
  #define xfs_check_agi_unlinked(agi)
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
1448
1449
1450
  /*
   * Read in the allocation group header (inode allocation section)
   */
  int
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1451
1452
1453
1454
1455
  xfs_read_agi(
  	struct xfs_mount	*mp,	/* file system mount structure */
  	struct xfs_trans	*tp,	/* transaction pointer */
  	xfs_agnumber_t		agno,	/* allocation group number */
  	struct xfs_buf		**bpp)	/* allocation group hdr buf */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
  {
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1457
1458
1459
  	struct xfs_agi		*agi;	/* allocation group header */
  	int			agi_ok;	/* agi is consistent */
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
  
  	ASSERT(agno != NULLAGNUMBER);
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1462
1463
  
  	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
  			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1465
  			XFS_FSS_TO_BB(mp, 1), 0, bpp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
1467
  	if (error)
  		return error;
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1468

5a52c2a58   Chandra Seetharaman   xfs: Remove the m...
1469
  	ASSERT(!xfs_buf_geterror(*bpp));
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1470
  	agi = XFS_BUF_TO_AGI(*bpp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1471
1472
1473
1474
  
  	/*
  	 * Validate the magic number of the agi block.
  	 */
69ef921b5   Christoph Hellwig   xfs: byteswap con...
1475
  	agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) &&
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1476
1477
  		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)) &&
  		be32_to_cpu(agi->agi_seqno) == agno;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
1479
  	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
  			XFS_RANDOM_IALLOC_READ_AGI))) {
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1480
  		XFS_CORRUPTION_ERROR("xfs_read_agi", XFS_ERRLEVEL_LOW,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
  				     mp, agi);
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1482
  		xfs_trans_brelse(tp, *bpp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
  		return XFS_ERROR(EFSCORRUPTED);
  	}
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1485

38f232324   Christoph Hellwig   xfs: remove XFS_B...
1486
  	xfs_buf_set_ref(*bpp, XFS_AGI_REF);
5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
  
  	xfs_check_agi_unlinked(agi);
  	return 0;
  }
  
  int
  xfs_ialloc_read_agi(
  	struct xfs_mount	*mp,	/* file system mount structure */
  	struct xfs_trans	*tp,	/* transaction pointer */
  	xfs_agnumber_t		agno,	/* allocation group number */
  	struct xfs_buf		**bpp)	/* allocation group hdr buf */
  {
  	struct xfs_agi		*agi;	/* allocation group header */
  	struct xfs_perag	*pag;	/* per allocation group data */
  	int			error;
  
  	error = xfs_read_agi(mp, tp, agno, bpp);
  	if (error)
  		return error;
  
  	agi = XFS_BUF_TO_AGI(*bpp);
44b56e0a1   Dave Chinner   xfs: convert rema...
1508
  	pag = xfs_perag_get(mp, agno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509
  	if (!pag->pagi_init) {
16259e7d9   Christoph Hellwig   [XFS] Endianess a...
1510
  		pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
92821e2ba   David Chinner   [XFS] Lazy Superb...
1511
  		pag->pagi_count = be32_to_cpu(agi->agi_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1512
  		pag->pagi_init = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1514

5e1be0fb1   Christoph Hellwig   [XFS] factor out ...
1515
1516
1517
1518
1519
1520
  	/*
  	 * It's possible for these to be out of sync if
  	 * we are in the middle of a forced shutdown.
  	 */
  	ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) ||
  		XFS_FORCED_SHUTDOWN(mp));
44b56e0a1   Dave Chinner   xfs: convert rema...
1521
  	xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1522
1523
  	return 0;
  }
92821e2ba   David Chinner   [XFS] Lazy Superb...
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  
  /*
   * Read in the agi to initialise the per-ag data in the mount structure
   */
  int
  xfs_ialloc_pagi_init(
  	xfs_mount_t	*mp,		/* file system mount structure */
  	xfs_trans_t	*tp,		/* transaction pointer */
  	xfs_agnumber_t	agno)		/* allocation group number */
  {
  	xfs_buf_t	*bp = NULL;
  	int		error;
  
  	error = xfs_ialloc_read_agi(mp, tp, agno, &bp);
  	if (error)
  		return error;
  	if (bp)
  		xfs_trans_brelse(tp, bp);
  	return 0;
  }