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 v2.6.34-rc2 383 lines 8.8 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_dir2.h" 28#include "xfs_dmapi.h" 29#include "xfs_mount.h" 30#include "xfs_bmap_btree.h" 31#include "xfs_alloc_btree.h" 32#include "xfs_ialloc_btree.h" 33#include "xfs_dir2_sf.h" 34#include "xfs_attr_sf.h" 35#include "xfs_dinode.h" 36#include "xfs_inode.h" 37#include "xfs_btree.h" 38#include "xfs_btree_trace.h" 39#include "xfs_ialloc.h" 40#include "xfs_alloc.h" 41#include "xfs_error.h" 42 43 44STATIC int 45xfs_inobt_get_minrecs( 46 struct xfs_btree_cur *cur, 47 int level) 48{ 49 return cur->bc_mp->m_inobt_mnr[level != 0]; 50} 51 52STATIC struct xfs_btree_cur * 53xfs_inobt_dup_cursor( 54 struct xfs_btree_cur *cur) 55{ 56 return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, 57 cur->bc_private.a.agbp, cur->bc_private.a.agno); 58} 59 60STATIC void 61xfs_inobt_set_root( 62 struct xfs_btree_cur *cur, 63 union xfs_btree_ptr *nptr, 64 int inc) /* level change */ 65{ 66 struct xfs_buf *agbp = cur->bc_private.a.agbp; 67 struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); 68 69 agi->agi_root = nptr->s; 70 be32_add_cpu(&agi->agi_level, inc); 71 xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); 72} 73 74STATIC int 75xfs_inobt_alloc_block( 76 struct xfs_btree_cur *cur, 77 union xfs_btree_ptr *start, 78 union xfs_btree_ptr *new, 79 int length, 80 int *stat) 81{ 82 xfs_alloc_arg_t args; /* block allocation args */ 83 int error; /* error return value */ 84 xfs_agblock_t sbno = be32_to_cpu(start->s); 85 86 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); 87 88 memset(&args, 0, sizeof(args)); 89 args.tp = cur->bc_tp; 90 args.mp = cur->bc_mp; 91 args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); 92 args.minlen = 1; 93 args.maxlen = 1; 94 args.prod = 1; 95 args.type = XFS_ALLOCTYPE_NEAR_BNO; 96 97 error = xfs_alloc_vextent(&args); 98 if (error) { 99 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); 100 return error; 101 } 102 if (args.fsbno == NULLFSBLOCK) { 103 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 104 *stat = 0; 105 return 0; 106 } 107 ASSERT(args.len == 1); 108 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 109 110 new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno)); 111 *stat = 1; 112 return 0; 113} 114 115STATIC int 116xfs_inobt_free_block( 117 struct xfs_btree_cur *cur, 118 struct xfs_buf *bp) 119{ 120 xfs_fsblock_t fsbno; 121 int error; 122 123 fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)); 124 error = xfs_free_extent(cur->bc_tp, fsbno, 1); 125 if (error) 126 return error; 127 128 xfs_trans_binval(cur->bc_tp, bp); 129 return error; 130} 131 132STATIC int 133xfs_inobt_get_maxrecs( 134 struct xfs_btree_cur *cur, 135 int level) 136{ 137 return cur->bc_mp->m_inobt_mxr[level != 0]; 138} 139 140STATIC void 141xfs_inobt_init_key_from_rec( 142 union xfs_btree_key *key, 143 union xfs_btree_rec *rec) 144{ 145 key->inobt.ir_startino = rec->inobt.ir_startino; 146} 147 148STATIC void 149xfs_inobt_init_rec_from_key( 150 union xfs_btree_key *key, 151 union xfs_btree_rec *rec) 152{ 153 rec->inobt.ir_startino = key->inobt.ir_startino; 154} 155 156STATIC void 157xfs_inobt_init_rec_from_cur( 158 struct xfs_btree_cur *cur, 159 union xfs_btree_rec *rec) 160{ 161 rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); 162 rec->inobt.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); 163 rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); 164} 165 166/* 167 * initial value of ptr for lookup 168 */ 169STATIC void 170xfs_inobt_init_ptr_from_cur( 171 struct xfs_btree_cur *cur, 172 union xfs_btree_ptr *ptr) 173{ 174 struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); 175 176 ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); 177 178 ptr->s = agi->agi_root; 179} 180 181STATIC __int64_t 182xfs_inobt_key_diff( 183 struct xfs_btree_cur *cur, 184 union xfs_btree_key *key) 185{ 186 return (__int64_t)be32_to_cpu(key->inobt.ir_startino) - 187 cur->bc_rec.i.ir_startino; 188} 189 190STATIC int 191xfs_inobt_kill_root( 192 struct xfs_btree_cur *cur, 193 struct xfs_buf *bp, 194 int level, 195 union xfs_btree_ptr *newroot) 196{ 197 int error; 198 199 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); 200 XFS_BTREE_STATS_INC(cur, killroot); 201 202 /* 203 * Update the root pointer, decreasing the level by 1 and then 204 * free the old root. 205 */ 206 xfs_inobt_set_root(cur, newroot, -1); 207 error = xfs_inobt_free_block(cur, bp); 208 if (error) { 209 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); 210 return error; 211 } 212 213 XFS_BTREE_STATS_INC(cur, free); 214 215 cur->bc_bufs[level] = NULL; 216 cur->bc_nlevels--; 217 218 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 219 return 0; 220} 221 222#ifdef DEBUG 223STATIC int 224xfs_inobt_keys_inorder( 225 struct xfs_btree_cur *cur, 226 union xfs_btree_key *k1, 227 union xfs_btree_key *k2) 228{ 229 return be32_to_cpu(k1->inobt.ir_startino) < 230 be32_to_cpu(k2->inobt.ir_startino); 231} 232 233STATIC int 234xfs_inobt_recs_inorder( 235 struct xfs_btree_cur *cur, 236 union xfs_btree_rec *r1, 237 union xfs_btree_rec *r2) 238{ 239 return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <= 240 be32_to_cpu(r2->inobt.ir_startino); 241} 242#endif /* DEBUG */ 243 244#ifdef XFS_BTREE_TRACE 245ktrace_t *xfs_inobt_trace_buf; 246 247STATIC void 248xfs_inobt_trace_enter( 249 struct xfs_btree_cur *cur, 250 const char *func, 251 char *s, 252 int type, 253 int line, 254 __psunsigned_t a0, 255 __psunsigned_t a1, 256 __psunsigned_t a2, 257 __psunsigned_t a3, 258 __psunsigned_t a4, 259 __psunsigned_t a5, 260 __psunsigned_t a6, 261 __psunsigned_t a7, 262 __psunsigned_t a8, 263 __psunsigned_t a9, 264 __psunsigned_t a10) 265{ 266 ktrace_enter(xfs_inobt_trace_buf, (void *)(__psint_t)type, 267 (void *)func, (void *)s, NULL, (void *)cur, 268 (void *)a0, (void *)a1, (void *)a2, (void *)a3, 269 (void *)a4, (void *)a5, (void *)a6, (void *)a7, 270 (void *)a8, (void *)a9, (void *)a10); 271} 272 273STATIC void 274xfs_inobt_trace_cursor( 275 struct xfs_btree_cur *cur, 276 __uint32_t *s0, 277 __uint64_t *l0, 278 __uint64_t *l1) 279{ 280 *s0 = cur->bc_private.a.agno; 281 *l0 = cur->bc_rec.i.ir_startino; 282 *l1 = cur->bc_rec.i.ir_free; 283} 284 285STATIC void 286xfs_inobt_trace_key( 287 struct xfs_btree_cur *cur, 288 union xfs_btree_key *key, 289 __uint64_t *l0, 290 __uint64_t *l1) 291{ 292 *l0 = be32_to_cpu(key->inobt.ir_startino); 293 *l1 = 0; 294} 295 296STATIC void 297xfs_inobt_trace_record( 298 struct xfs_btree_cur *cur, 299 union xfs_btree_rec *rec, 300 __uint64_t *l0, 301 __uint64_t *l1, 302 __uint64_t *l2) 303{ 304 *l0 = be32_to_cpu(rec->inobt.ir_startino); 305 *l1 = be32_to_cpu(rec->inobt.ir_freecount); 306 *l2 = be64_to_cpu(rec->inobt.ir_free); 307} 308#endif /* XFS_BTREE_TRACE */ 309 310static const struct xfs_btree_ops xfs_inobt_ops = { 311 .rec_len = sizeof(xfs_inobt_rec_t), 312 .key_len = sizeof(xfs_inobt_key_t), 313 314 .dup_cursor = xfs_inobt_dup_cursor, 315 .set_root = xfs_inobt_set_root, 316 .kill_root = xfs_inobt_kill_root, 317 .alloc_block = xfs_inobt_alloc_block, 318 .free_block = xfs_inobt_free_block, 319 .get_minrecs = xfs_inobt_get_minrecs, 320 .get_maxrecs = xfs_inobt_get_maxrecs, 321 .init_key_from_rec = xfs_inobt_init_key_from_rec, 322 .init_rec_from_key = xfs_inobt_init_rec_from_key, 323 .init_rec_from_cur = xfs_inobt_init_rec_from_cur, 324 .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, 325 .key_diff = xfs_inobt_key_diff, 326 327#ifdef DEBUG 328 .keys_inorder = xfs_inobt_keys_inorder, 329 .recs_inorder = xfs_inobt_recs_inorder, 330#endif 331 332#ifdef XFS_BTREE_TRACE 333 .trace_enter = xfs_inobt_trace_enter, 334 .trace_cursor = xfs_inobt_trace_cursor, 335 .trace_key = xfs_inobt_trace_key, 336 .trace_record = xfs_inobt_trace_record, 337#endif 338}; 339 340/* 341 * Allocate a new inode btree cursor. 342 */ 343struct xfs_btree_cur * /* new inode btree cursor */ 344xfs_inobt_init_cursor( 345 struct xfs_mount *mp, /* file system mount point */ 346 struct xfs_trans *tp, /* transaction pointer */ 347 struct xfs_buf *agbp, /* buffer for agi structure */ 348 xfs_agnumber_t agno) /* allocation group number */ 349{ 350 struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); 351 struct xfs_btree_cur *cur; 352 353 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); 354 355 cur->bc_tp = tp; 356 cur->bc_mp = mp; 357 cur->bc_nlevels = be32_to_cpu(agi->agi_level); 358 cur->bc_btnum = XFS_BTNUM_INO; 359 cur->bc_blocklog = mp->m_sb.sb_blocklog; 360 361 cur->bc_ops = &xfs_inobt_ops; 362 363 cur->bc_private.a.agbp = agbp; 364 cur->bc_private.a.agno = agno; 365 366 return cur; 367} 368 369/* 370 * Calculate number of records in an inobt btree block. 371 */ 372int 373xfs_inobt_maxrecs( 374 struct xfs_mount *mp, 375 int blocklen, 376 int leaf) 377{ 378 blocklen -= XFS_INOBT_BLOCK_LEN(mp); 379 380 if (leaf) 381 return blocklen / sizeof(xfs_inobt_rec_t); 382 return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t)); 383}