Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1-rc8 386 lines 9.7 kB view raw
1/* 2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#include "xfs.h" 19#include "xfs_fs.h" 20#include "xfs_types.h" 21#include "xfs_bit.h" 22#include "xfs_log.h" 23#include "xfs_inum.h" 24#include "xfs_trans.h" 25#include "xfs_sb.h" 26#include "xfs_ag.h" 27#include "xfs_mount.h" 28#include "xfs_bmap_btree.h" 29#include "xfs_alloc_btree.h" 30#include "xfs_ialloc_btree.h" 31#include "xfs_dinode.h" 32#include "xfs_inode.h" 33#include "xfs_btree.h" 34#include "xfs_alloc.h" 35#include "xfs_error.h" 36#include "xfs_trace.h" 37 38 39STATIC struct xfs_btree_cur * 40xfs_allocbt_dup_cursor( 41 struct xfs_btree_cur *cur) 42{ 43 return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, 44 cur->bc_private.a.agbp, cur->bc_private.a.agno, 45 cur->bc_btnum); 46} 47 48STATIC void 49xfs_allocbt_set_root( 50 struct xfs_btree_cur *cur, 51 union xfs_btree_ptr *ptr, 52 int inc) 53{ 54 struct xfs_buf *agbp = cur->bc_private.a.agbp; 55 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 56 xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); 57 int btnum = cur->bc_btnum; 58 struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); 59 60 ASSERT(ptr->s != 0); 61 62 agf->agf_roots[btnum] = ptr->s; 63 be32_add_cpu(&agf->agf_levels[btnum], inc); 64 pag->pagf_levels[btnum] += inc; 65 xfs_perag_put(pag); 66 67 xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); 68} 69 70STATIC int 71xfs_allocbt_alloc_block( 72 struct xfs_btree_cur *cur, 73 union xfs_btree_ptr *start, 74 union xfs_btree_ptr *new, 75 int length, 76 int *stat) 77{ 78 int error; 79 xfs_agblock_t bno; 80 81 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); 82 83 /* Allocate the new block from the freelist. If we can't, give up. */ 84 error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp, 85 &bno, 1); 86 if (error) { 87 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); 88 return error; 89 } 90 91 if (bno == NULLAGBLOCK) { 92 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 93 *stat = 0; 94 return 0; 95 } 96 97 xfs_alloc_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1, false); 98 99 xfs_trans_agbtree_delta(cur->bc_tp, 1); 100 new->s = cpu_to_be32(bno); 101 102 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 103 *stat = 1; 104 return 0; 105} 106 107STATIC int 108xfs_allocbt_free_block( 109 struct xfs_btree_cur *cur, 110 struct xfs_buf *bp) 111{ 112 struct xfs_buf *agbp = cur->bc_private.a.agbp; 113 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 114 xfs_agblock_t bno; 115 int error; 116 117 bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp)); 118 error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); 119 if (error) 120 return error; 121 122 xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, 123 XFS_ALLOC_BUSY_SKIP_DISCARD); 124 xfs_trans_agbtree_delta(cur->bc_tp, -1); 125 return 0; 126} 127 128/* 129 * Update the longest extent in the AGF 130 */ 131STATIC void 132xfs_allocbt_update_lastrec( 133 struct xfs_btree_cur *cur, 134 struct xfs_btree_block *block, 135 union xfs_btree_rec *rec, 136 int ptr, 137 int reason) 138{ 139 struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); 140 xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); 141 struct xfs_perag *pag; 142 __be32 len; 143 int numrecs; 144 145 ASSERT(cur->bc_btnum == XFS_BTNUM_CNT); 146 147 switch (reason) { 148 case LASTREC_UPDATE: 149 /* 150 * If this is the last leaf block and it's the last record, 151 * then update the size of the longest extent in the AG. 152 */ 153 if (ptr != xfs_btree_get_numrecs(block)) 154 return; 155 len = rec->alloc.ar_blockcount; 156 break; 157 case LASTREC_INSREC: 158 if (be32_to_cpu(rec->alloc.ar_blockcount) <= 159 be32_to_cpu(agf->agf_longest)) 160 return; 161 len = rec->alloc.ar_blockcount; 162 break; 163 case LASTREC_DELREC: 164 numrecs = xfs_btree_get_numrecs(block); 165 if (ptr <= numrecs) 166 return; 167 ASSERT(ptr == numrecs + 1); 168 169 if (numrecs) { 170 xfs_alloc_rec_t *rrp; 171 172 rrp = XFS_ALLOC_REC_ADDR(cur->bc_mp, block, numrecs); 173 len = rrp->ar_blockcount; 174 } else { 175 len = 0; 176 } 177 178 break; 179 default: 180 ASSERT(0); 181 return; 182 } 183 184 agf->agf_longest = len; 185 pag = xfs_perag_get(cur->bc_mp, seqno); 186 pag->pagf_longest = be32_to_cpu(len); 187 xfs_perag_put(pag); 188 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST); 189} 190 191STATIC int 192xfs_allocbt_get_minrecs( 193 struct xfs_btree_cur *cur, 194 int level) 195{ 196 return cur->bc_mp->m_alloc_mnr[level != 0]; 197} 198 199STATIC int 200xfs_allocbt_get_maxrecs( 201 struct xfs_btree_cur *cur, 202 int level) 203{ 204 return cur->bc_mp->m_alloc_mxr[level != 0]; 205} 206 207STATIC void 208xfs_allocbt_init_key_from_rec( 209 union xfs_btree_key *key, 210 union xfs_btree_rec *rec) 211{ 212 ASSERT(rec->alloc.ar_startblock != 0); 213 214 key->alloc.ar_startblock = rec->alloc.ar_startblock; 215 key->alloc.ar_blockcount = rec->alloc.ar_blockcount; 216} 217 218STATIC void 219xfs_allocbt_init_rec_from_key( 220 union xfs_btree_key *key, 221 union xfs_btree_rec *rec) 222{ 223 ASSERT(key->alloc.ar_startblock != 0); 224 225 rec->alloc.ar_startblock = key->alloc.ar_startblock; 226 rec->alloc.ar_blockcount = key->alloc.ar_blockcount; 227} 228 229STATIC void 230xfs_allocbt_init_rec_from_cur( 231 struct xfs_btree_cur *cur, 232 union xfs_btree_rec *rec) 233{ 234 ASSERT(cur->bc_rec.a.ar_startblock != 0); 235 236 rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock); 237 rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount); 238} 239 240STATIC void 241xfs_allocbt_init_ptr_from_cur( 242 struct xfs_btree_cur *cur, 243 union xfs_btree_ptr *ptr) 244{ 245 struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); 246 247 ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); 248 ASSERT(agf->agf_roots[cur->bc_btnum] != 0); 249 250 ptr->s = agf->agf_roots[cur->bc_btnum]; 251} 252 253STATIC __int64_t 254xfs_allocbt_key_diff( 255 struct xfs_btree_cur *cur, 256 union xfs_btree_key *key) 257{ 258 xfs_alloc_rec_incore_t *rec = &cur->bc_rec.a; 259 xfs_alloc_key_t *kp = &key->alloc; 260 __int64_t diff; 261 262 if (cur->bc_btnum == XFS_BTNUM_BNO) { 263 return (__int64_t)be32_to_cpu(kp->ar_startblock) - 264 rec->ar_startblock; 265 } 266 267 diff = (__int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount; 268 if (diff) 269 return diff; 270 271 return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock; 272} 273 274#ifdef DEBUG 275STATIC int 276xfs_allocbt_keys_inorder( 277 struct xfs_btree_cur *cur, 278 union xfs_btree_key *k1, 279 union xfs_btree_key *k2) 280{ 281 if (cur->bc_btnum == XFS_BTNUM_BNO) { 282 return be32_to_cpu(k1->alloc.ar_startblock) < 283 be32_to_cpu(k2->alloc.ar_startblock); 284 } else { 285 return be32_to_cpu(k1->alloc.ar_blockcount) < 286 be32_to_cpu(k2->alloc.ar_blockcount) || 287 (k1->alloc.ar_blockcount == k2->alloc.ar_blockcount && 288 be32_to_cpu(k1->alloc.ar_startblock) < 289 be32_to_cpu(k2->alloc.ar_startblock)); 290 } 291} 292 293STATIC int 294xfs_allocbt_recs_inorder( 295 struct xfs_btree_cur *cur, 296 union xfs_btree_rec *r1, 297 union xfs_btree_rec *r2) 298{ 299 if (cur->bc_btnum == XFS_BTNUM_BNO) { 300 return be32_to_cpu(r1->alloc.ar_startblock) + 301 be32_to_cpu(r1->alloc.ar_blockcount) <= 302 be32_to_cpu(r2->alloc.ar_startblock); 303 } else { 304 return be32_to_cpu(r1->alloc.ar_blockcount) < 305 be32_to_cpu(r2->alloc.ar_blockcount) || 306 (r1->alloc.ar_blockcount == r2->alloc.ar_blockcount && 307 be32_to_cpu(r1->alloc.ar_startblock) < 308 be32_to_cpu(r2->alloc.ar_startblock)); 309 } 310} 311#endif /* DEBUG */ 312 313static const struct xfs_btree_ops xfs_allocbt_ops = { 314 .rec_len = sizeof(xfs_alloc_rec_t), 315 .key_len = sizeof(xfs_alloc_key_t), 316 317 .dup_cursor = xfs_allocbt_dup_cursor, 318 .set_root = xfs_allocbt_set_root, 319 .alloc_block = xfs_allocbt_alloc_block, 320 .free_block = xfs_allocbt_free_block, 321 .update_lastrec = xfs_allocbt_update_lastrec, 322 .get_minrecs = xfs_allocbt_get_minrecs, 323 .get_maxrecs = xfs_allocbt_get_maxrecs, 324 .init_key_from_rec = xfs_allocbt_init_key_from_rec, 325 .init_rec_from_key = xfs_allocbt_init_rec_from_key, 326 .init_rec_from_cur = xfs_allocbt_init_rec_from_cur, 327 .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, 328 .key_diff = xfs_allocbt_key_diff, 329#ifdef DEBUG 330 .keys_inorder = xfs_allocbt_keys_inorder, 331 .recs_inorder = xfs_allocbt_recs_inorder, 332#endif 333}; 334 335/* 336 * Allocate a new allocation btree cursor. 337 */ 338struct xfs_btree_cur * /* new alloc btree cursor */ 339xfs_allocbt_init_cursor( 340 struct xfs_mount *mp, /* file system mount point */ 341 struct xfs_trans *tp, /* transaction pointer */ 342 struct xfs_buf *agbp, /* buffer for agf structure */ 343 xfs_agnumber_t agno, /* allocation group number */ 344 xfs_btnum_t btnum) /* btree identifier */ 345{ 346 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 347 struct xfs_btree_cur *cur; 348 349 ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); 350 351 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); 352 353 cur->bc_tp = tp; 354 cur->bc_mp = mp; 355 cur->bc_btnum = btnum; 356 cur->bc_blocklog = mp->m_sb.sb_blocklog; 357 cur->bc_ops = &xfs_allocbt_ops; 358 359 if (btnum == XFS_BTNUM_CNT) { 360 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); 361 cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; 362 } else { 363 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); 364 } 365 366 cur->bc_private.a.agbp = agbp; 367 cur->bc_private.a.agno = agno; 368 369 return cur; 370} 371 372/* 373 * Calculate number of records in an alloc btree block. 374 */ 375int 376xfs_allocbt_maxrecs( 377 struct xfs_mount *mp, 378 int blocklen, 379 int leaf) 380{ 381 blocklen -= XFS_ALLOC_BLOCK_LEN(mp); 382 383 if (leaf) 384 return blocklen / sizeof(xfs_alloc_rec_t); 385 return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t)); 386}