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.7 270 lines 6.5 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_trans.h" 24#include "xfs_sb.h" 25#include "xfs_ag.h" 26#include "xfs_mount.h" 27#include "xfs_bmap_btree.h" 28#include "xfs_alloc_btree.h" 29#include "xfs_ialloc_btree.h" 30#include "xfs_dinode.h" 31#include "xfs_inode.h" 32#include "xfs_btree.h" 33#include "xfs_ialloc.h" 34#include "xfs_alloc.h" 35#include "xfs_error.h" 36 37 38STATIC int 39xfs_inobt_get_minrecs( 40 struct xfs_btree_cur *cur, 41 int level) 42{ 43 return cur->bc_mp->m_inobt_mnr[level != 0]; 44} 45 46STATIC struct xfs_btree_cur * 47xfs_inobt_dup_cursor( 48 struct xfs_btree_cur *cur) 49{ 50 return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, 51 cur->bc_private.a.agbp, cur->bc_private.a.agno); 52} 53 54STATIC void 55xfs_inobt_set_root( 56 struct xfs_btree_cur *cur, 57 union xfs_btree_ptr *nptr, 58 int inc) /* level change */ 59{ 60 struct xfs_buf *agbp = cur->bc_private.a.agbp; 61 struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); 62 63 agi->agi_root = nptr->s; 64 be32_add_cpu(&agi->agi_level, inc); 65 xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); 66} 67 68STATIC int 69xfs_inobt_alloc_block( 70 struct xfs_btree_cur *cur, 71 union xfs_btree_ptr *start, 72 union xfs_btree_ptr *new, 73 int length, 74 int *stat) 75{ 76 xfs_alloc_arg_t args; /* block allocation args */ 77 int error; /* error return value */ 78 xfs_agblock_t sbno = be32_to_cpu(start->s); 79 80 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); 81 82 memset(&args, 0, sizeof(args)); 83 args.tp = cur->bc_tp; 84 args.mp = cur->bc_mp; 85 args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); 86 args.minlen = 1; 87 args.maxlen = 1; 88 args.prod = 1; 89 args.type = XFS_ALLOCTYPE_NEAR_BNO; 90 91 error = xfs_alloc_vextent(&args); 92 if (error) { 93 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); 94 return error; 95 } 96 if (args.fsbno == NULLFSBLOCK) { 97 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 98 *stat = 0; 99 return 0; 100 } 101 ASSERT(args.len == 1); 102 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 103 104 new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno)); 105 *stat = 1; 106 return 0; 107} 108 109STATIC int 110xfs_inobt_free_block( 111 struct xfs_btree_cur *cur, 112 struct xfs_buf *bp) 113{ 114 xfs_fsblock_t fsbno; 115 int error; 116 117 fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)); 118 error = xfs_free_extent(cur->bc_tp, fsbno, 1); 119 if (error) 120 return error; 121 122 xfs_trans_binval(cur->bc_tp, bp); 123 return error; 124} 125 126STATIC int 127xfs_inobt_get_maxrecs( 128 struct xfs_btree_cur *cur, 129 int level) 130{ 131 return cur->bc_mp->m_inobt_mxr[level != 0]; 132} 133 134STATIC void 135xfs_inobt_init_key_from_rec( 136 union xfs_btree_key *key, 137 union xfs_btree_rec *rec) 138{ 139 key->inobt.ir_startino = rec->inobt.ir_startino; 140} 141 142STATIC void 143xfs_inobt_init_rec_from_key( 144 union xfs_btree_key *key, 145 union xfs_btree_rec *rec) 146{ 147 rec->inobt.ir_startino = key->inobt.ir_startino; 148} 149 150STATIC void 151xfs_inobt_init_rec_from_cur( 152 struct xfs_btree_cur *cur, 153 union xfs_btree_rec *rec) 154{ 155 rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); 156 rec->inobt.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); 157 rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); 158} 159 160/* 161 * initial value of ptr for lookup 162 */ 163STATIC void 164xfs_inobt_init_ptr_from_cur( 165 struct xfs_btree_cur *cur, 166 union xfs_btree_ptr *ptr) 167{ 168 struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); 169 170 ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); 171 172 ptr->s = agi->agi_root; 173} 174 175STATIC __int64_t 176xfs_inobt_key_diff( 177 struct xfs_btree_cur *cur, 178 union xfs_btree_key *key) 179{ 180 return (__int64_t)be32_to_cpu(key->inobt.ir_startino) - 181 cur->bc_rec.i.ir_startino; 182} 183 184#ifdef DEBUG 185STATIC int 186xfs_inobt_keys_inorder( 187 struct xfs_btree_cur *cur, 188 union xfs_btree_key *k1, 189 union xfs_btree_key *k2) 190{ 191 return be32_to_cpu(k1->inobt.ir_startino) < 192 be32_to_cpu(k2->inobt.ir_startino); 193} 194 195STATIC int 196xfs_inobt_recs_inorder( 197 struct xfs_btree_cur *cur, 198 union xfs_btree_rec *r1, 199 union xfs_btree_rec *r2) 200{ 201 return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <= 202 be32_to_cpu(r2->inobt.ir_startino); 203} 204#endif /* DEBUG */ 205 206static const struct xfs_btree_ops xfs_inobt_ops = { 207 .rec_len = sizeof(xfs_inobt_rec_t), 208 .key_len = sizeof(xfs_inobt_key_t), 209 210 .dup_cursor = xfs_inobt_dup_cursor, 211 .set_root = xfs_inobt_set_root, 212 .alloc_block = xfs_inobt_alloc_block, 213 .free_block = xfs_inobt_free_block, 214 .get_minrecs = xfs_inobt_get_minrecs, 215 .get_maxrecs = xfs_inobt_get_maxrecs, 216 .init_key_from_rec = xfs_inobt_init_key_from_rec, 217 .init_rec_from_key = xfs_inobt_init_rec_from_key, 218 .init_rec_from_cur = xfs_inobt_init_rec_from_cur, 219 .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, 220 .key_diff = xfs_inobt_key_diff, 221#ifdef DEBUG 222 .keys_inorder = xfs_inobt_keys_inorder, 223 .recs_inorder = xfs_inobt_recs_inorder, 224#endif 225}; 226 227/* 228 * Allocate a new inode btree cursor. 229 */ 230struct xfs_btree_cur * /* new inode btree cursor */ 231xfs_inobt_init_cursor( 232 struct xfs_mount *mp, /* file system mount point */ 233 struct xfs_trans *tp, /* transaction pointer */ 234 struct xfs_buf *agbp, /* buffer for agi structure */ 235 xfs_agnumber_t agno) /* allocation group number */ 236{ 237 struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); 238 struct xfs_btree_cur *cur; 239 240 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); 241 242 cur->bc_tp = tp; 243 cur->bc_mp = mp; 244 cur->bc_nlevels = be32_to_cpu(agi->agi_level); 245 cur->bc_btnum = XFS_BTNUM_INO; 246 cur->bc_blocklog = mp->m_sb.sb_blocklog; 247 248 cur->bc_ops = &xfs_inobt_ops; 249 250 cur->bc_private.a.agbp = agbp; 251 cur->bc_private.a.agno = agno; 252 253 return cur; 254} 255 256/* 257 * Calculate number of records in an inobt btree block. 258 */ 259int 260xfs_inobt_maxrecs( 261 struct xfs_mount *mp, 262 int blocklen, 263 int leaf) 264{ 265 blocklen -= XFS_INOBT_BLOCK_LEN(mp); 266 267 if (leaf) 268 return blocklen / sizeof(xfs_inobt_rec_t); 269 return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t)); 270}