diff options
Diffstat (limited to 'fs/xfs/xfs_ialloc.c')
-rw-r--r-- | fs/xfs/xfs_ialloc.c | 805 |
1 files changed, 406 insertions, 399 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 3120a3a5e20f..ab64f3efb43b 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -57,75 +57,35 @@ xfs_ialloc_cluster_alignment( | |||
57 | } | 57 | } |
58 | 58 | ||
59 | /* | 59 | /* |
60 | * Lookup the record equal to ino in the btree given by cur. | 60 | * Lookup a record by ino in the btree given by cur. |
61 | */ | ||
62 | STATIC int /* error */ | ||
63 | xfs_inobt_lookup_eq( | ||
64 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
65 | xfs_agino_t ino, /* starting inode of chunk */ | ||
66 | __int32_t fcnt, /* free inode count */ | ||
67 | xfs_inofree_t free, /* free inode mask */ | ||
68 | int *stat) /* success/failure */ | ||
69 | { | ||
70 | cur->bc_rec.i.ir_startino = ino; | ||
71 | cur->bc_rec.i.ir_freecount = fcnt; | ||
72 | cur->bc_rec.i.ir_free = free; | ||
73 | return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Lookup the first record greater than or equal to ino | ||
78 | * in the btree given by cur. | ||
79 | */ | 61 | */ |
80 | int /* error */ | 62 | int /* error */ |
81 | xfs_inobt_lookup_ge( | 63 | xfs_inobt_lookup( |
82 | struct xfs_btree_cur *cur, /* btree cursor */ | 64 | struct xfs_btree_cur *cur, /* btree cursor */ |
83 | xfs_agino_t ino, /* starting inode of chunk */ | 65 | xfs_agino_t ino, /* starting inode of chunk */ |
84 | __int32_t fcnt, /* free inode count */ | 66 | xfs_lookup_t dir, /* <=, >=, == */ |
85 | xfs_inofree_t free, /* free inode mask */ | ||
86 | int *stat) /* success/failure */ | 67 | int *stat) /* success/failure */ |
87 | { | 68 | { |
88 | cur->bc_rec.i.ir_startino = ino; | 69 | cur->bc_rec.i.ir_startino = ino; |
89 | cur->bc_rec.i.ir_freecount = fcnt; | 70 | cur->bc_rec.i.ir_freecount = 0; |
90 | cur->bc_rec.i.ir_free = free; | 71 | cur->bc_rec.i.ir_free = 0; |
91 | return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); | 72 | return xfs_btree_lookup(cur, dir, stat); |
92 | } | 73 | } |
93 | 74 | ||
94 | /* | 75 | /* |
95 | * Lookup the first record less than or equal to ino | 76 | * Update the record referred to by cur to the value given. |
96 | * in the btree given by cur. | ||
97 | */ | ||
98 | int /* error */ | ||
99 | xfs_inobt_lookup_le( | ||
100 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
101 | xfs_agino_t ino, /* starting inode of chunk */ | ||
102 | __int32_t fcnt, /* free inode count */ | ||
103 | xfs_inofree_t free, /* free inode mask */ | ||
104 | int *stat) /* success/failure */ | ||
105 | { | ||
106 | cur->bc_rec.i.ir_startino = ino; | ||
107 | cur->bc_rec.i.ir_freecount = fcnt; | ||
108 | cur->bc_rec.i.ir_free = free; | ||
109 | return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Update the record referred to by cur to the value given | ||
114 | * by [ino, fcnt, free]. | ||
115 | * This either works (return 0) or gets an EFSCORRUPTED error. | 77 | * This either works (return 0) or gets an EFSCORRUPTED error. |
116 | */ | 78 | */ |
117 | STATIC int /* error */ | 79 | STATIC int /* error */ |
118 | xfs_inobt_update( | 80 | xfs_inobt_update( |
119 | struct xfs_btree_cur *cur, /* btree cursor */ | 81 | struct xfs_btree_cur *cur, /* btree cursor */ |
120 | xfs_agino_t ino, /* starting inode of chunk */ | 82 | xfs_inobt_rec_incore_t *irec) /* btree record */ |
121 | __int32_t fcnt, /* free inode count */ | ||
122 | xfs_inofree_t free) /* free inode mask */ | ||
123 | { | 83 | { |
124 | union xfs_btree_rec rec; | 84 | union xfs_btree_rec rec; |
125 | 85 | ||
126 | rec.inobt.ir_startino = cpu_to_be32(ino); | 86 | rec.inobt.ir_startino = cpu_to_be32(irec->ir_startino); |
127 | rec.inobt.ir_freecount = cpu_to_be32(fcnt); | 87 | rec.inobt.ir_freecount = cpu_to_be32(irec->ir_freecount); |
128 | rec.inobt.ir_free = cpu_to_be64(free); | 88 | rec.inobt.ir_free = cpu_to_be64(irec->ir_free); |
129 | return xfs_btree_update(cur, &rec); | 89 | return xfs_btree_update(cur, &rec); |
130 | } | 90 | } |
131 | 91 | ||
@@ -135,9 +95,7 @@ xfs_inobt_update( | |||
135 | int /* error */ | 95 | int /* error */ |
136 | xfs_inobt_get_rec( | 96 | xfs_inobt_get_rec( |
137 | struct xfs_btree_cur *cur, /* btree cursor */ | 97 | struct xfs_btree_cur *cur, /* btree cursor */ |
138 | xfs_agino_t *ino, /* output: starting inode of chunk */ | 98 | xfs_inobt_rec_incore_t *irec, /* btree record */ |
139 | __int32_t *fcnt, /* output: number of free inodes */ | ||
140 | xfs_inofree_t *free, /* output: free inode mask */ | ||
141 | int *stat) /* output: success/failure */ | 99 | int *stat) /* output: success/failure */ |
142 | { | 100 | { |
143 | union xfs_btree_rec *rec; | 101 | union xfs_btree_rec *rec; |
@@ -145,14 +103,136 @@ xfs_inobt_get_rec( | |||
145 | 103 | ||
146 | error = xfs_btree_get_rec(cur, &rec, stat); | 104 | error = xfs_btree_get_rec(cur, &rec, stat); |
147 | if (!error && *stat == 1) { | 105 | if (!error && *stat == 1) { |
148 | *ino = be32_to_cpu(rec->inobt.ir_startino); | 106 | irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino); |
149 | *fcnt = be32_to_cpu(rec->inobt.ir_freecount); | 107 | irec->ir_freecount = be32_to_cpu(rec->inobt.ir_freecount); |
150 | *free = be64_to_cpu(rec->inobt.ir_free); | 108 | irec->ir_free = be64_to_cpu(rec->inobt.ir_free); |
151 | } | 109 | } |
152 | return error; | 110 | return error; |
153 | } | 111 | } |
154 | 112 | ||
155 | /* | 113 | /* |
114 | * Verify that the number of free inodes in the AGI is correct. | ||
115 | */ | ||
116 | #ifdef DEBUG | ||
117 | STATIC int | ||
118 | xfs_check_agi_freecount( | ||
119 | struct xfs_btree_cur *cur, | ||
120 | struct xfs_agi *agi) | ||
121 | { | ||
122 | if (cur->bc_nlevels == 1) { | ||
123 | xfs_inobt_rec_incore_t rec; | ||
124 | int freecount = 0; | ||
125 | int error; | ||
126 | int i; | ||
127 | |||
128 | error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); | ||
129 | if (error) | ||
130 | return error; | ||
131 | |||
132 | do { | ||
133 | error = xfs_inobt_get_rec(cur, &rec, &i); | ||
134 | if (error) | ||
135 | return error; | ||
136 | |||
137 | if (i) { | ||
138 | freecount += rec.ir_freecount; | ||
139 | error = xfs_btree_increment(cur, 0, &i); | ||
140 | if (error) | ||
141 | return error; | ||
142 | } | ||
143 | } while (i == 1); | ||
144 | |||
145 | if (!XFS_FORCED_SHUTDOWN(cur->bc_mp)) | ||
146 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount)); | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | #else | ||
151 | #define xfs_check_agi_freecount(cur, agi) 0 | ||
152 | #endif | ||
153 | |||
154 | /* | ||
155 | * Initialise a new set of inodes. | ||
156 | */ | ||
157 | STATIC void | ||
158 | xfs_ialloc_inode_init( | ||
159 | struct xfs_mount *mp, | ||
160 | struct xfs_trans *tp, | ||
161 | xfs_agnumber_t agno, | ||
162 | xfs_agblock_t agbno, | ||
163 | xfs_agblock_t length, | ||
164 | unsigned int gen) | ||
165 | { | ||
166 | struct xfs_buf *fbuf; | ||
167 | struct xfs_dinode *free; | ||
168 | int blks_per_cluster, nbufs, ninodes; | ||
169 | int version; | ||
170 | int i, j; | ||
171 | xfs_daddr_t d; | ||
172 | |||
173 | /* | ||
174 | * Loop over the new block(s), filling in the inodes. | ||
175 | * For small block sizes, manipulate the inodes in buffers | ||
176 | * which are multiples of the blocks size. | ||
177 | */ | ||
178 | if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) { | ||
179 | blks_per_cluster = 1; | ||
180 | nbufs = length; | ||
181 | ninodes = mp->m_sb.sb_inopblock; | ||
182 | } else { | ||
183 | blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) / | ||
184 | mp->m_sb.sb_blocksize; | ||
185 | nbufs = length / blks_per_cluster; | ||
186 | ninodes = blks_per_cluster * mp->m_sb.sb_inopblock; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Figure out what version number to use in the inodes we create. | ||
191 | * If the superblock version has caught up to the one that supports | ||
192 | * the new inode format, then use the new inode version. Otherwise | ||
193 | * use the old version so that old kernels will continue to be | ||
194 | * able to use the file system. | ||
195 | */ | ||
196 | if (xfs_sb_version_hasnlink(&mp->m_sb)) | ||
197 | version = 2; | ||
198 | else | ||
199 | version = 1; | ||
200 | |||
201 | for (j = 0; j < nbufs; j++) { | ||
202 | /* | ||
203 | * Get the block. | ||
204 | */ | ||
205 | d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster)); | ||
206 | fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, | ||
207 | mp->m_bsize * blks_per_cluster, | ||
208 | XFS_BUF_LOCK); | ||
209 | ASSERT(fbuf); | ||
210 | ASSERT(!XFS_BUF_GETERROR(fbuf)); | ||
211 | |||
212 | /* | ||
213 | * Initialize all inodes in this buffer and then log them. | ||
214 | * | ||
215 | * XXX: It would be much better if we had just one transaction | ||
216 | * to log a whole cluster of inodes instead of all the | ||
217 | * individual transactions causing a lot of log traffic. | ||
218 | */ | ||
219 | xfs_biozero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog); | ||
220 | for (i = 0; i < ninodes; i++) { | ||
221 | int ioffset = i << mp->m_sb.sb_inodelog; | ||
222 | uint isize = sizeof(struct xfs_dinode); | ||
223 | |||
224 | free = xfs_make_iptr(mp, fbuf, i); | ||
225 | free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); | ||
226 | free->di_version = version; | ||
227 | free->di_gen = cpu_to_be32(gen); | ||
228 | free->di_next_unlinked = cpu_to_be32(NULLAGINO); | ||
229 | xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1); | ||
230 | } | ||
231 | xfs_trans_inode_alloc_buf(tp, fbuf); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | /* | ||
156 | * Allocate new inodes in the allocation group specified by agbp. | 236 | * Allocate new inodes in the allocation group specified by agbp. |
157 | * Return 0 for success, else error code. | 237 | * Return 0 for success, else error code. |
158 | */ | 238 | */ |
@@ -164,24 +244,15 @@ xfs_ialloc_ag_alloc( | |||
164 | { | 244 | { |
165 | xfs_agi_t *agi; /* allocation group header */ | 245 | xfs_agi_t *agi; /* allocation group header */ |
166 | xfs_alloc_arg_t args; /* allocation argument structure */ | 246 | xfs_alloc_arg_t args; /* allocation argument structure */ |
167 | int blks_per_cluster; /* fs blocks per inode cluster */ | ||
168 | xfs_btree_cur_t *cur; /* inode btree cursor */ | 247 | xfs_btree_cur_t *cur; /* inode btree cursor */ |
169 | xfs_daddr_t d; /* disk addr of buffer */ | ||
170 | xfs_agnumber_t agno; | 248 | xfs_agnumber_t agno; |
171 | int error; | 249 | int error; |
172 | xfs_buf_t *fbuf; /* new free inodes' buffer */ | 250 | int i; |
173 | xfs_dinode_t *free; /* new free inode structure */ | ||
174 | int i; /* inode counter */ | ||
175 | int j; /* block counter */ | ||
176 | int nbufs; /* num bufs of new inodes */ | ||
177 | xfs_agino_t newino; /* new first inode's number */ | 251 | xfs_agino_t newino; /* new first inode's number */ |
178 | xfs_agino_t newlen; /* new number of inodes */ | 252 | xfs_agino_t newlen; /* new number of inodes */ |
179 | int ninodes; /* num inodes per buf */ | ||
180 | xfs_agino_t thisino; /* current inode number, for loop */ | 253 | xfs_agino_t thisino; /* current inode number, for loop */ |
181 | int version; /* inode version number to use */ | ||
182 | int isaligned = 0; /* inode allocation at stripe unit */ | 254 | int isaligned = 0; /* inode allocation at stripe unit */ |
183 | /* boundary */ | 255 | /* boundary */ |
184 | unsigned int gen; | ||
185 | 256 | ||
186 | args.tp = tp; | 257 | args.tp = tp; |
187 | args.mp = tp->t_mountp; | 258 | args.mp = tp->t_mountp; |
@@ -202,12 +273,12 @@ xfs_ialloc_ag_alloc( | |||
202 | */ | 273 | */ |
203 | agi = XFS_BUF_TO_AGI(agbp); | 274 | agi = XFS_BUF_TO_AGI(agbp); |
204 | newino = be32_to_cpu(agi->agi_newino); | 275 | newino = be32_to_cpu(agi->agi_newino); |
276 | agno = be32_to_cpu(agi->agi_seqno); | ||
205 | args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) + | 277 | args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) + |
206 | XFS_IALLOC_BLOCKS(args.mp); | 278 | XFS_IALLOC_BLOCKS(args.mp); |
207 | if (likely(newino != NULLAGINO && | 279 | if (likely(newino != NULLAGINO && |
208 | (args.agbno < be32_to_cpu(agi->agi_length)))) { | 280 | (args.agbno < be32_to_cpu(agi->agi_length)))) { |
209 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | 281 | args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); |
210 | be32_to_cpu(agi->agi_seqno), args.agbno); | ||
211 | args.type = XFS_ALLOCTYPE_THIS_BNO; | 282 | args.type = XFS_ALLOCTYPE_THIS_BNO; |
212 | args.mod = args.total = args.wasdel = args.isfl = | 283 | args.mod = args.total = args.wasdel = args.isfl = |
213 | args.userdata = args.minalignslop = 0; | 284 | args.userdata = args.minalignslop = 0; |
@@ -258,8 +329,7 @@ xfs_ialloc_ag_alloc( | |||
258 | * For now, just allocate blocks up front. | 329 | * For now, just allocate blocks up front. |
259 | */ | 330 | */ |
260 | args.agbno = be32_to_cpu(agi->agi_root); | 331 | args.agbno = be32_to_cpu(agi->agi_root); |
261 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | 332 | args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); |
262 | be32_to_cpu(agi->agi_seqno), args.agbno); | ||
263 | /* | 333 | /* |
264 | * Allocate a fixed-size extent of inodes. | 334 | * Allocate a fixed-size extent of inodes. |
265 | */ | 335 | */ |
@@ -282,8 +352,7 @@ xfs_ialloc_ag_alloc( | |||
282 | if (isaligned && args.fsbno == NULLFSBLOCK) { | 352 | if (isaligned && args.fsbno == NULLFSBLOCK) { |
283 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 353 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
284 | args.agbno = be32_to_cpu(agi->agi_root); | 354 | args.agbno = be32_to_cpu(agi->agi_root); |
285 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | 355 | args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); |
286 | be32_to_cpu(agi->agi_seqno), args.agbno); | ||
287 | args.alignment = xfs_ialloc_cluster_alignment(&args); | 356 | args.alignment = xfs_ialloc_cluster_alignment(&args); |
288 | if ((error = xfs_alloc_vextent(&args))) | 357 | if ((error = xfs_alloc_vextent(&args))) |
289 | return error; | 358 | return error; |
@@ -294,85 +363,30 @@ xfs_ialloc_ag_alloc( | |||
294 | return 0; | 363 | return 0; |
295 | } | 364 | } |
296 | ASSERT(args.len == args.minlen); | 365 | ASSERT(args.len == args.minlen); |
297 | /* | ||
298 | * Convert the results. | ||
299 | */ | ||
300 | newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0); | ||
301 | /* | ||
302 | * Loop over the new block(s), filling in the inodes. | ||
303 | * For small block sizes, manipulate the inodes in buffers | ||
304 | * which are multiples of the blocks size. | ||
305 | */ | ||
306 | if (args.mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(args.mp)) { | ||
307 | blks_per_cluster = 1; | ||
308 | nbufs = (int)args.len; | ||
309 | ninodes = args.mp->m_sb.sb_inopblock; | ||
310 | } else { | ||
311 | blks_per_cluster = XFS_INODE_CLUSTER_SIZE(args.mp) / | ||
312 | args.mp->m_sb.sb_blocksize; | ||
313 | nbufs = (int)args.len / blks_per_cluster; | ||
314 | ninodes = blks_per_cluster * args.mp->m_sb.sb_inopblock; | ||
315 | } | ||
316 | /* | ||
317 | * Figure out what version number to use in the inodes we create. | ||
318 | * If the superblock version has caught up to the one that supports | ||
319 | * the new inode format, then use the new inode version. Otherwise | ||
320 | * use the old version so that old kernels will continue to be | ||
321 | * able to use the file system. | ||
322 | */ | ||
323 | if (xfs_sb_version_hasnlink(&args.mp->m_sb)) | ||
324 | version = 2; | ||
325 | else | ||
326 | version = 1; | ||
327 | 366 | ||
328 | /* | 367 | /* |
368 | * Stamp and write the inode buffers. | ||
369 | * | ||
329 | * Seed the new inode cluster with a random generation number. This | 370 | * Seed the new inode cluster with a random generation number. This |
330 | * prevents short-term reuse of generation numbers if a chunk is | 371 | * prevents short-term reuse of generation numbers if a chunk is |
331 | * freed and then immediately reallocated. We use random numbers | 372 | * freed and then immediately reallocated. We use random numbers |
332 | * rather than a linear progression to prevent the next generation | 373 | * rather than a linear progression to prevent the next generation |
333 | * number from being easily guessable. | 374 | * number from being easily guessable. |
334 | */ | 375 | */ |
335 | gen = random32(); | 376 | xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno, args.len, |
336 | for (j = 0; j < nbufs; j++) { | 377 | random32()); |
337 | /* | ||
338 | * Get the block. | ||
339 | */ | ||
340 | d = XFS_AGB_TO_DADDR(args.mp, be32_to_cpu(agi->agi_seqno), | ||
341 | args.agbno + (j * blks_per_cluster)); | ||
342 | fbuf = xfs_trans_get_buf(tp, args.mp->m_ddev_targp, d, | ||
343 | args.mp->m_bsize * blks_per_cluster, | ||
344 | XFS_BUF_LOCK); | ||
345 | ASSERT(fbuf); | ||
346 | ASSERT(!XFS_BUF_GETERROR(fbuf)); | ||
347 | 378 | ||
348 | /* | 379 | /* |
349 | * Initialize all inodes in this buffer and then log them. | 380 | * Convert the results. |
350 | * | 381 | */ |
351 | * XXX: It would be much better if we had just one transaction to | 382 | newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0); |
352 | * log a whole cluster of inodes instead of all the individual | ||
353 | * transactions causing a lot of log traffic. | ||
354 | */ | ||
355 | xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog); | ||
356 | for (i = 0; i < ninodes; i++) { | ||
357 | int ioffset = i << args.mp->m_sb.sb_inodelog; | ||
358 | uint isize = sizeof(struct xfs_dinode); | ||
359 | |||
360 | free = xfs_make_iptr(args.mp, fbuf, i); | ||
361 | free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); | ||
362 | free->di_version = version; | ||
363 | free->di_gen = cpu_to_be32(gen); | ||
364 | free->di_next_unlinked = cpu_to_be32(NULLAGINO); | ||
365 | xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1); | ||
366 | } | ||
367 | xfs_trans_inode_alloc_buf(tp, fbuf); | ||
368 | } | ||
369 | be32_add_cpu(&agi->agi_count, newlen); | 383 | be32_add_cpu(&agi->agi_count, newlen); |
370 | be32_add_cpu(&agi->agi_freecount, newlen); | 384 | be32_add_cpu(&agi->agi_freecount, newlen); |
371 | agno = be32_to_cpu(agi->agi_seqno); | ||
372 | down_read(&args.mp->m_peraglock); | 385 | down_read(&args.mp->m_peraglock); |
373 | args.mp->m_perag[agno].pagi_freecount += newlen; | 386 | args.mp->m_perag[agno].pagi_freecount += newlen; |
374 | up_read(&args.mp->m_peraglock); | 387 | up_read(&args.mp->m_peraglock); |
375 | agi->agi_newino = cpu_to_be32(newino); | 388 | agi->agi_newino = cpu_to_be32(newino); |
389 | |||
376 | /* | 390 | /* |
377 | * Insert records describing the new inode chunk into the btree. | 391 | * Insert records describing the new inode chunk into the btree. |
378 | */ | 392 | */ |
@@ -380,13 +394,17 @@ xfs_ialloc_ag_alloc( | |||
380 | for (thisino = newino; | 394 | for (thisino = newino; |
381 | thisino < newino + newlen; | 395 | thisino < newino + newlen; |
382 | thisino += XFS_INODES_PER_CHUNK) { | 396 | thisino += XFS_INODES_PER_CHUNK) { |
383 | if ((error = xfs_inobt_lookup_eq(cur, thisino, | 397 | cur->bc_rec.i.ir_startino = thisino; |
384 | XFS_INODES_PER_CHUNK, XFS_INOBT_ALL_FREE, &i))) { | 398 | cur->bc_rec.i.ir_freecount = XFS_INODES_PER_CHUNK; |
399 | cur->bc_rec.i.ir_free = XFS_INOBT_ALL_FREE; | ||
400 | error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, &i); | ||
401 | if (error) { | ||
385 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | 402 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); |
386 | return error; | 403 | return error; |
387 | } | 404 | } |
388 | ASSERT(i == 0); | 405 | ASSERT(i == 0); |
389 | if ((error = xfs_btree_insert(cur, &i))) { | 406 | error = xfs_btree_insert(cur, &i); |
407 | if (error) { | ||
390 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | 408 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); |
391 | return error; | 409 | return error; |
392 | } | 410 | } |
@@ -539,6 +557,62 @@ nextag: | |||
539 | } | 557 | } |
540 | 558 | ||
541 | /* | 559 | /* |
560 | * Try to retrieve the next record to the left/right from the current one. | ||
561 | */ | ||
562 | STATIC int | ||
563 | xfs_ialloc_next_rec( | ||
564 | struct xfs_btree_cur *cur, | ||
565 | xfs_inobt_rec_incore_t *rec, | ||
566 | int *done, | ||
567 | int left) | ||
568 | { | ||
569 | int error; | ||
570 | int i; | ||
571 | |||
572 | if (left) | ||
573 | error = xfs_btree_decrement(cur, 0, &i); | ||
574 | else | ||
575 | error = xfs_btree_increment(cur, 0, &i); | ||
576 | |||
577 | if (error) | ||
578 | return error; | ||
579 | *done = !i; | ||
580 | if (i) { | ||
581 | error = xfs_inobt_get_rec(cur, rec, &i); | ||
582 | if (error) | ||
583 | return error; | ||
584 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
585 | } | ||
586 | |||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | STATIC int | ||
591 | xfs_ialloc_get_rec( | ||
592 | struct xfs_btree_cur *cur, | ||
593 | xfs_agino_t agino, | ||
594 | xfs_inobt_rec_incore_t *rec, | ||
595 | int *done, | ||
596 | int left) | ||
597 | { | ||
598 | int error; | ||
599 | int i; | ||
600 | |||
601 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_EQ, &i); | ||
602 | if (error) | ||
603 | return error; | ||
604 | *done = !i; | ||
605 | if (i) { | ||
606 | error = xfs_inobt_get_rec(cur, rec, &i); | ||
607 | if (error) | ||
608 | return error; | ||
609 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | /* | ||
542 | * Visible inode allocation functions. | 616 | * Visible inode allocation functions. |
543 | */ | 617 | */ |
544 | 618 | ||
@@ -592,8 +666,8 @@ xfs_dialloc( | |||
592 | int j; /* result code */ | 666 | int j; /* result code */ |
593 | xfs_mount_t *mp; /* file system mount structure */ | 667 | xfs_mount_t *mp; /* file system mount structure */ |
594 | int offset; /* index of inode in chunk */ | 668 | int offset; /* index of inode in chunk */ |
595 | xfs_agino_t pagino; /* parent's a.g. relative inode # */ | 669 | xfs_agino_t pagino; /* parent's AG relative inode # */ |
596 | xfs_agnumber_t pagno; /* parent's allocation group number */ | 670 | xfs_agnumber_t pagno; /* parent's AG number */ |
597 | xfs_inobt_rec_incore_t rec; /* inode allocation record */ | 671 | xfs_inobt_rec_incore_t rec; /* inode allocation record */ |
598 | xfs_agnumber_t tagno; /* testing allocation group number */ | 672 | xfs_agnumber_t tagno; /* testing allocation group number */ |
599 | xfs_btree_cur_t *tcur; /* temp cursor */ | 673 | xfs_btree_cur_t *tcur; /* temp cursor */ |
@@ -716,6 +790,8 @@ nextag: | |||
716 | */ | 790 | */ |
717 | agno = tagno; | 791 | agno = tagno; |
718 | *IO_agbp = NULL; | 792 | *IO_agbp = NULL; |
793 | |||
794 | restart_pagno: | ||
719 | cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno)); | 795 | cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno)); |
720 | /* | 796 | /* |
721 | * If pagino is 0 (this is the root inode allocation) use newino. | 797 | * If pagino is 0 (this is the root inode allocation) use newino. |
@@ -723,220 +799,199 @@ nextag: | |||
723 | */ | 799 | */ |
724 | if (!pagino) | 800 | if (!pagino) |
725 | pagino = be32_to_cpu(agi->agi_newino); | 801 | pagino = be32_to_cpu(agi->agi_newino); |
726 | #ifdef DEBUG | ||
727 | if (cur->bc_nlevels == 1) { | ||
728 | int freecount = 0; | ||
729 | 802 | ||
730 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 803 | error = xfs_check_agi_freecount(cur, agi); |
731 | goto error0; | 804 | if (error) |
732 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 805 | goto error0; |
733 | do { | ||
734 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, | ||
735 | &rec.ir_freecount, &rec.ir_free, &i))) | ||
736 | goto error0; | ||
737 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
738 | freecount += rec.ir_freecount; | ||
739 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
740 | goto error0; | ||
741 | } while (i == 1); | ||
742 | 806 | ||
743 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
744 | XFS_FORCED_SHUTDOWN(mp)); | ||
745 | } | ||
746 | #endif | ||
747 | /* | 807 | /* |
748 | * If in the same a.g. as the parent, try to get near the parent. | 808 | * If in the same AG as the parent, try to get near the parent. |
749 | */ | 809 | */ |
750 | if (pagno == agno) { | 810 | if (pagno == agno) { |
751 | if ((error = xfs_inobt_lookup_le(cur, pagino, 0, 0, &i))) | 811 | xfs_perag_t *pag = &mp->m_perag[agno]; |
812 | int doneleft; /* done, to the left */ | ||
813 | int doneright; /* done, to the right */ | ||
814 | int searchdistance = 10; | ||
815 | |||
816 | error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i); | ||
817 | if (error) | ||
818 | goto error0; | ||
819 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
820 | |||
821 | error = xfs_inobt_get_rec(cur, &rec, &j); | ||
822 | if (error) | ||
752 | goto error0; | 823 | goto error0; |
753 | if (i != 0 && | 824 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
754 | (error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 825 | |
755 | &rec.ir_freecount, &rec.ir_free, &j)) == 0 && | 826 | if (rec.ir_freecount > 0) { |
756 | j == 1 && | ||
757 | rec.ir_freecount > 0) { | ||
758 | /* | 827 | /* |
759 | * Found a free inode in the same chunk | 828 | * Found a free inode in the same chunk |
760 | * as parent, done. | 829 | * as the parent, done. |
761 | */ | 830 | */ |
831 | goto alloc_inode; | ||
762 | } | 832 | } |
833 | |||
834 | |||
835 | /* | ||
836 | * In the same AG as parent, but parent's chunk is full. | ||
837 | */ | ||
838 | |||
839 | /* duplicate the cursor, search left & right simultaneously */ | ||
840 | error = xfs_btree_dup_cursor(cur, &tcur); | ||
841 | if (error) | ||
842 | goto error0; | ||
843 | |||
763 | /* | 844 | /* |
764 | * In the same a.g. as parent, but parent's chunk is full. | 845 | * Skip to last blocks looked up if same parent inode. |
765 | */ | 846 | */ |
766 | else { | 847 | if (pagino != NULLAGINO && |
767 | int doneleft; /* done, to the left */ | 848 | pag->pagl_pagino == pagino && |
768 | int doneright; /* done, to the right */ | 849 | pag->pagl_leftrec != NULLAGINO && |
850 | pag->pagl_rightrec != NULLAGINO) { | ||
851 | error = xfs_ialloc_get_rec(tcur, pag->pagl_leftrec, | ||
852 | &trec, &doneleft, 1); | ||
853 | if (error) | ||
854 | goto error1; | ||
769 | 855 | ||
856 | error = xfs_ialloc_get_rec(cur, pag->pagl_rightrec, | ||
857 | &rec, &doneright, 0); | ||
770 | if (error) | 858 | if (error) |
771 | goto error0; | ||
772 | ASSERT(i == 1); | ||
773 | ASSERT(j == 1); | ||
774 | /* | ||
775 | * Duplicate the cursor, search left & right | ||
776 | * simultaneously. | ||
777 | */ | ||
778 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) | ||
779 | goto error0; | ||
780 | /* | ||
781 | * Search left with tcur, back up 1 record. | ||
782 | */ | ||
783 | if ((error = xfs_btree_decrement(tcur, 0, &i))) | ||
784 | goto error1; | 859 | goto error1; |
785 | doneleft = !i; | 860 | } else { |
786 | if (!doneleft) { | 861 | /* search left with tcur, back up 1 record */ |
787 | if ((error = xfs_inobt_get_rec(tcur, | 862 | error = xfs_ialloc_next_rec(tcur, &trec, &doneleft, 1); |
788 | &trec.ir_startino, | 863 | if (error) |
789 | &trec.ir_freecount, | ||
790 | &trec.ir_free, &i))) | ||
791 | goto error1; | ||
792 | XFS_WANT_CORRUPTED_GOTO(i == 1, error1); | ||
793 | } | ||
794 | /* | ||
795 | * Search right with cur, go forward 1 record. | ||
796 | */ | ||
797 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
798 | goto error1; | 864 | goto error1; |
799 | doneright = !i; | ||
800 | if (!doneright) { | ||
801 | if ((error = xfs_inobt_get_rec(cur, | ||
802 | &rec.ir_startino, | ||
803 | &rec.ir_freecount, | ||
804 | &rec.ir_free, &i))) | ||
805 | goto error1; | ||
806 | XFS_WANT_CORRUPTED_GOTO(i == 1, error1); | ||
807 | } | ||
808 | /* | ||
809 | * Loop until we find the closest inode chunk | ||
810 | * with a free one. | ||
811 | */ | ||
812 | while (!doneleft || !doneright) { | ||
813 | int useleft; /* using left inode | ||
814 | chunk this time */ | ||
815 | 865 | ||
866 | /* search right with cur, go forward 1 record. */ | ||
867 | error = xfs_ialloc_next_rec(cur, &rec, &doneright, 0); | ||
868 | if (error) | ||
869 | goto error1; | ||
870 | } | ||
871 | |||
872 | /* | ||
873 | * Loop until we find an inode chunk with a free inode. | ||
874 | */ | ||
875 | while (!doneleft || !doneright) { | ||
876 | int useleft; /* using left inode chunk this time */ | ||
877 | |||
878 | if (!--searchdistance) { | ||
816 | /* | 879 | /* |
817 | * Figure out which block is closer, | 880 | * Not in range - save last search |
818 | * if both are valid. | 881 | * location and allocate a new inode |
819 | */ | ||
820 | if (!doneleft && !doneright) | ||
821 | useleft = | ||
822 | pagino - | ||
823 | (trec.ir_startino + | ||
824 | XFS_INODES_PER_CHUNK - 1) < | ||
825 | rec.ir_startino - pagino; | ||
826 | else | ||
827 | useleft = !doneleft; | ||
828 | /* | ||
829 | * If checking the left, does it have | ||
830 | * free inodes? | ||
831 | */ | ||
832 | if (useleft && trec.ir_freecount) { | ||
833 | /* | ||
834 | * Yes, set it up as the chunk to use. | ||
835 | */ | ||
836 | rec = trec; | ||
837 | xfs_btree_del_cursor(cur, | ||
838 | XFS_BTREE_NOERROR); | ||
839 | cur = tcur; | ||
840 | break; | ||
841 | } | ||
842 | /* | ||
843 | * If checking the right, does it have | ||
844 | * free inodes? | ||
845 | */ | ||
846 | if (!useleft && rec.ir_freecount) { | ||
847 | /* | ||
848 | * Yes, it's already set up. | ||
849 | */ | ||
850 | xfs_btree_del_cursor(tcur, | ||
851 | XFS_BTREE_NOERROR); | ||
852 | break; | ||
853 | } | ||
854 | /* | ||
855 | * If used the left, get another one | ||
856 | * further left. | ||
857 | */ | ||
858 | if (useleft) { | ||
859 | if ((error = xfs_btree_decrement(tcur, 0, | ||
860 | &i))) | ||
861 | goto error1; | ||
862 | doneleft = !i; | ||
863 | if (!doneleft) { | ||
864 | if ((error = xfs_inobt_get_rec( | ||
865 | tcur, | ||
866 | &trec.ir_startino, | ||
867 | &trec.ir_freecount, | ||
868 | &trec.ir_free, &i))) | ||
869 | goto error1; | ||
870 | XFS_WANT_CORRUPTED_GOTO(i == 1, | ||
871 | error1); | ||
872 | } | ||
873 | } | ||
874 | /* | ||
875 | * If used the right, get another one | ||
876 | * further right. | ||
877 | */ | 882 | */ |
878 | else { | 883 | pag->pagl_leftrec = trec.ir_startino; |
879 | if ((error = xfs_btree_increment(cur, 0, | 884 | pag->pagl_rightrec = rec.ir_startino; |
880 | &i))) | 885 | pag->pagl_pagino = pagino; |
881 | goto error1; | 886 | goto newino; |
882 | doneright = !i; | 887 | } |
883 | if (!doneright) { | 888 | |
884 | if ((error = xfs_inobt_get_rec( | 889 | /* figure out the closer block if both are valid. */ |
885 | cur, | 890 | if (!doneleft && !doneright) { |
886 | &rec.ir_startino, | 891 | useleft = pagino - |
887 | &rec.ir_freecount, | 892 | (trec.ir_startino + XFS_INODES_PER_CHUNK - 1) < |
888 | &rec.ir_free, &i))) | 893 | rec.ir_startino - pagino; |
889 | goto error1; | 894 | } else { |
890 | XFS_WANT_CORRUPTED_GOTO(i == 1, | 895 | useleft = !doneleft; |
891 | error1); | ||
892 | } | ||
893 | } | ||
894 | } | 896 | } |
895 | ASSERT(!doneleft || !doneright); | 897 | |
898 | /* free inodes to the left? */ | ||
899 | if (useleft && trec.ir_freecount) { | ||
900 | rec = trec; | ||
901 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
902 | cur = tcur; | ||
903 | |||
904 | pag->pagl_leftrec = trec.ir_startino; | ||
905 | pag->pagl_rightrec = rec.ir_startino; | ||
906 | pag->pagl_pagino = pagino; | ||
907 | goto alloc_inode; | ||
908 | } | ||
909 | |||
910 | /* free inodes to the right? */ | ||
911 | if (!useleft && rec.ir_freecount) { | ||
912 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
913 | |||
914 | pag->pagl_leftrec = trec.ir_startino; | ||
915 | pag->pagl_rightrec = rec.ir_startino; | ||
916 | pag->pagl_pagino = pagino; | ||
917 | goto alloc_inode; | ||
918 | } | ||
919 | |||
920 | /* get next record to check */ | ||
921 | if (useleft) { | ||
922 | error = xfs_ialloc_next_rec(tcur, &trec, | ||
923 | &doneleft, 1); | ||
924 | } else { | ||
925 | error = xfs_ialloc_next_rec(cur, &rec, | ||
926 | &doneright, 0); | ||
927 | } | ||
928 | if (error) | ||
929 | goto error1; | ||
896 | } | 930 | } |
931 | |||
932 | /* | ||
933 | * We've reached the end of the btree. because | ||
934 | * we are only searching a small chunk of the | ||
935 | * btree each search, there is obviously free | ||
936 | * inodes closer to the parent inode than we | ||
937 | * are now. restart the search again. | ||
938 | */ | ||
939 | pag->pagl_pagino = NULLAGINO; | ||
940 | pag->pagl_leftrec = NULLAGINO; | ||
941 | pag->pagl_rightrec = NULLAGINO; | ||
942 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
943 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
944 | goto restart_pagno; | ||
897 | } | 945 | } |
946 | |||
898 | /* | 947 | /* |
899 | * In a different a.g. from the parent. | 948 | * In a different AG from the parent. |
900 | * See if the most recently allocated block has any free. | 949 | * See if the most recently allocated block has any free. |
901 | */ | 950 | */ |
902 | else if (be32_to_cpu(agi->agi_newino) != NULLAGINO) { | 951 | newino: |
903 | if ((error = xfs_inobt_lookup_eq(cur, | 952 | if (be32_to_cpu(agi->agi_newino) != NULLAGINO) { |
904 | be32_to_cpu(agi->agi_newino), 0, 0, &i))) | 953 | error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino), |
954 | XFS_LOOKUP_EQ, &i); | ||
955 | if (error) | ||
905 | goto error0; | 956 | goto error0; |
906 | if (i == 1 && | 957 | |
907 | (error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 958 | if (i == 1) { |
908 | &rec.ir_freecount, &rec.ir_free, &j)) == 0 && | 959 | error = xfs_inobt_get_rec(cur, &rec, &j); |
909 | j == 1 && | ||
910 | rec.ir_freecount > 0) { | ||
911 | /* | ||
912 | * The last chunk allocated in the group still has | ||
913 | * a free inode. | ||
914 | */ | ||
915 | } | ||
916 | /* | ||
917 | * None left in the last group, search the whole a.g. | ||
918 | */ | ||
919 | else { | ||
920 | if (error) | 960 | if (error) |
921 | goto error0; | 961 | goto error0; |
922 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 962 | |
923 | goto error0; | 963 | if (j == 1 && rec.ir_freecount > 0) { |
924 | ASSERT(i == 1); | 964 | /* |
925 | for (;;) { | 965 | * The last chunk allocated in the group |
926 | if ((error = xfs_inobt_get_rec(cur, | 966 | * still has a free inode. |
927 | &rec.ir_startino, | 967 | */ |
928 | &rec.ir_freecount, &rec.ir_free, | 968 | goto alloc_inode; |
929 | &i))) | ||
930 | goto error0; | ||
931 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
932 | if (rec.ir_freecount > 0) | ||
933 | break; | ||
934 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
935 | goto error0; | ||
936 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
937 | } | 969 | } |
938 | } | 970 | } |
939 | } | 971 | } |
972 | |||
973 | /* | ||
974 | * None left in the last group, search the whole AG | ||
975 | */ | ||
976 | error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); | ||
977 | if (error) | ||
978 | goto error0; | ||
979 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
980 | |||
981 | for (;;) { | ||
982 | error = xfs_inobt_get_rec(cur, &rec, &i); | ||
983 | if (error) | ||
984 | goto error0; | ||
985 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
986 | if (rec.ir_freecount > 0) | ||
987 | break; | ||
988 | error = xfs_btree_increment(cur, 0, &i); | ||
989 | if (error) | ||
990 | goto error0; | ||
991 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
992 | } | ||
993 | |||
994 | alloc_inode: | ||
940 | offset = xfs_ialloc_find_free(&rec.ir_free); | 995 | offset = xfs_ialloc_find_free(&rec.ir_free); |
941 | ASSERT(offset >= 0); | 996 | ASSERT(offset >= 0); |
942 | ASSERT(offset < XFS_INODES_PER_CHUNK); | 997 | ASSERT(offset < XFS_INODES_PER_CHUNK); |
@@ -945,33 +1000,19 @@ nextag: | |||
945 | ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); | 1000 | ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); |
946 | rec.ir_free &= ~XFS_INOBT_MASK(offset); | 1001 | rec.ir_free &= ~XFS_INOBT_MASK(offset); |
947 | rec.ir_freecount--; | 1002 | rec.ir_freecount--; |
948 | if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, | 1003 | error = xfs_inobt_update(cur, &rec); |
949 | rec.ir_free))) | 1004 | if (error) |
950 | goto error0; | 1005 | goto error0; |
951 | be32_add_cpu(&agi->agi_freecount, -1); | 1006 | be32_add_cpu(&agi->agi_freecount, -1); |
952 | xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); | 1007 | xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); |
953 | down_read(&mp->m_peraglock); | 1008 | down_read(&mp->m_peraglock); |
954 | mp->m_perag[tagno].pagi_freecount--; | 1009 | mp->m_perag[tagno].pagi_freecount--; |
955 | up_read(&mp->m_peraglock); | 1010 | up_read(&mp->m_peraglock); |
956 | #ifdef DEBUG | ||
957 | if (cur->bc_nlevels == 1) { | ||
958 | int freecount = 0; | ||
959 | 1011 | ||
960 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 1012 | error = xfs_check_agi_freecount(cur, agi); |
961 | goto error0; | 1013 | if (error) |
962 | do { | 1014 | goto error0; |
963 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 1015 | |
964 | &rec.ir_freecount, &rec.ir_free, &i))) | ||
965 | goto error0; | ||
966 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
967 | freecount += rec.ir_freecount; | ||
968 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
969 | goto error0; | ||
970 | } while (i == 1); | ||
971 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
972 | XFS_FORCED_SHUTDOWN(mp)); | ||
973 | } | ||
974 | #endif | ||
975 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 1016 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
976 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1); | 1017 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1); |
977 | *inop = ino; | 1018 | *inop = ino; |
@@ -1062,38 +1103,23 @@ xfs_difree( | |||
1062 | * Initialize the cursor. | 1103 | * Initialize the cursor. |
1063 | */ | 1104 | */ |
1064 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); | 1105 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); |
1065 | #ifdef DEBUG | ||
1066 | if (cur->bc_nlevels == 1) { | ||
1067 | int freecount = 0; | ||
1068 | 1106 | ||
1069 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 1107 | error = xfs_check_agi_freecount(cur, agi); |
1070 | goto error0; | 1108 | if (error) |
1071 | do { | 1109 | goto error0; |
1072 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 1110 | |
1073 | &rec.ir_freecount, &rec.ir_free, &i))) | ||
1074 | goto error0; | ||
1075 | if (i) { | ||
1076 | freecount += rec.ir_freecount; | ||
1077 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
1078 | goto error0; | ||
1079 | } | ||
1080 | } while (i == 1); | ||
1081 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
1082 | XFS_FORCED_SHUTDOWN(mp)); | ||
1083 | } | ||
1084 | #endif | ||
1085 | /* | 1111 | /* |
1086 | * Look for the entry describing this inode. | 1112 | * Look for the entry describing this inode. |
1087 | */ | 1113 | */ |
1088 | if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) { | 1114 | if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) { |
1089 | cmn_err(CE_WARN, | 1115 | cmn_err(CE_WARN, |
1090 | "xfs_difree: xfs_inobt_lookup_le returned() an error %d on %s. Returning error.", | 1116 | "xfs_difree: xfs_inobt_lookup returned() an error %d on %s. Returning error.", |
1091 | error, mp->m_fsname); | 1117 | error, mp->m_fsname); |
1092 | goto error0; | 1118 | goto error0; |
1093 | } | 1119 | } |
1094 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1120 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1095 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, &rec.ir_freecount, | 1121 | error = xfs_inobt_get_rec(cur, &rec, &i); |
1096 | &rec.ir_free, &i))) { | 1122 | if (error) { |
1097 | cmn_err(CE_WARN, | 1123 | cmn_err(CE_WARN, |
1098 | "xfs_difree: xfs_inobt_get_rec() returned an error %d on %s. Returning error.", | 1124 | "xfs_difree: xfs_inobt_get_rec() returned an error %d on %s. Returning error.", |
1099 | error, mp->m_fsname); | 1125 | error, mp->m_fsname); |
@@ -1148,12 +1174,14 @@ xfs_difree( | |||
1148 | } else { | 1174 | } else { |
1149 | *delete = 0; | 1175 | *delete = 0; |
1150 | 1176 | ||
1151 | if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, rec.ir_free))) { | 1177 | error = xfs_inobt_update(cur, &rec); |
1178 | if (error) { | ||
1152 | cmn_err(CE_WARN, | 1179 | cmn_err(CE_WARN, |
1153 | "xfs_difree: xfs_inobt_update() returned an error %d on %s. Returning error.", | 1180 | "xfs_difree: xfs_inobt_update returned an error %d on %s.", |
1154 | error, mp->m_fsname); | 1181 | error, mp->m_fsname); |
1155 | goto error0; | 1182 | goto error0; |
1156 | } | 1183 | } |
1184 | |||
1157 | /* | 1185 | /* |
1158 | * Change the inode free counts and log the ag/sb changes. | 1186 | * Change the inode free counts and log the ag/sb changes. |
1159 | */ | 1187 | */ |
@@ -1165,28 +1193,10 @@ xfs_difree( | |||
1165 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1); | 1193 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1); |
1166 | } | 1194 | } |
1167 | 1195 | ||
1168 | #ifdef DEBUG | 1196 | error = xfs_check_agi_freecount(cur, agi); |
1169 | if (cur->bc_nlevels == 1) { | 1197 | if (error) |
1170 | int freecount = 0; | 1198 | goto error0; |
1171 | 1199 | ||
1172 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | ||
1173 | goto error0; | ||
1174 | do { | ||
1175 | if ((error = xfs_inobt_get_rec(cur, | ||
1176 | &rec.ir_startino, | ||
1177 | &rec.ir_freecount, | ||
1178 | &rec.ir_free, &i))) | ||
1179 | goto error0; | ||
1180 | if (i) { | ||
1181 | freecount += rec.ir_freecount; | ||
1182 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
1183 | goto error0; | ||
1184 | } | ||
1185 | } while (i == 1); | ||
1186 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
1187 | XFS_FORCED_SHUTDOWN(mp)); | ||
1188 | } | ||
1189 | #endif | ||
1190 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 1200 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
1191 | return 0; | 1201 | return 0; |
1192 | 1202 | ||
@@ -1297,9 +1307,7 @@ xfs_imap( | |||
1297 | chunk_agbno = agbno - offset_agbno; | 1307 | chunk_agbno = agbno - offset_agbno; |
1298 | } else { | 1308 | } else { |
1299 | xfs_btree_cur_t *cur; /* inode btree cursor */ | 1309 | xfs_btree_cur_t *cur; /* inode btree cursor */ |
1300 | xfs_agino_t chunk_agino; /* first agino in inode chunk */ | 1310 | xfs_inobt_rec_incore_t chunk_rec; |
1301 | __int32_t chunk_cnt; /* count of free inodes in chunk */ | ||
1302 | xfs_inofree_t chunk_free; /* mask of free inodes in chunk */ | ||
1303 | xfs_buf_t *agbp; /* agi buffer */ | 1311 | xfs_buf_t *agbp; /* agi buffer */ |
1304 | int i; /* temp state */ | 1312 | int i; /* temp state */ |
1305 | 1313 | ||
@@ -1315,15 +1323,14 @@ xfs_imap( | |||
1315 | } | 1323 | } |
1316 | 1324 | ||
1317 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); | 1325 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); |
1318 | error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i); | 1326 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i); |
1319 | if (error) { | 1327 | if (error) { |
1320 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " | 1328 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " |
1321 | "xfs_inobt_lookup_le() failed"); | 1329 | "xfs_inobt_lookup() failed"); |
1322 | goto error0; | 1330 | goto error0; |
1323 | } | 1331 | } |
1324 | 1332 | ||
1325 | error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt, | 1333 | error = xfs_inobt_get_rec(cur, &chunk_rec, &i); |
1326 | &chunk_free, &i); | ||
1327 | if (error) { | 1334 | if (error) { |
1328 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " | 1335 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " |
1329 | "xfs_inobt_get_rec() failed"); | 1336 | "xfs_inobt_get_rec() failed"); |
@@ -1341,7 +1348,7 @@ xfs_imap( | |||
1341 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 1348 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
1342 | if (error) | 1349 | if (error) |
1343 | return error; | 1350 | return error; |
1344 | chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_agino); | 1351 | chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_rec.ir_startino); |
1345 | offset_agbno = agbno - chunk_agbno; | 1352 | offset_agbno = agbno - chunk_agbno; |
1346 | } | 1353 | } |
1347 | 1354 | ||