|
|
1.1 ! root 1: /* ! 2: * Handle the indirections in Unix-style file system. ! 3: * ! 4: * Uses a recursive scheme to follow up indirections. ! 5: * ! 6: * Needs optimization. A good place to start would be caching of ! 7: * lookup tables. ! 8: * ! 9: * La Monte H. Yarroll <[email protected]>, September 1991 ! 10: */ ! 11: ! 12: #include <sys/types.h> ! 13: #include <sys/buf.h> ! 14: #include <sys/ino.h> ! 15: #include <sys/inode.h> ! 16: #include <canon.h> ! 17: #include <sys/ptypes.h> ! 18: ! 19: extern BUF *bread(); ! 20: daddr_t vmap(); ! 21: daddr_t indirect(); ! 22: daddr_t ind_lookup(); ! 23: uint16 ind_index(); ! 24: ! 25: /* Convert the given virtual block to a physical block for the given inode. ! 26: * ip points to the in-core inode for a file. ! 27: * vblockno is a block number relative to the start of that file. ! 28: */ ! 29: daddr_t ! 30: vmap(ip, vblockno) ! 31: struct inode *ip; ! 32: daddr_t vblockno; ! 33: { ! 34: uint16 ind_level; ! 35: daddr_t ind_table; ! 36: daddr_t vbno; ! 37: ! 38: if (vblockno < (daddr_t) ND){ ! 39: /* Direct block. */ ! 40: return(ip->i_a.i_addr[vblockno]); ! 41: } else if (vblockno < (daddr_t) (ND + NBN)) { ! 42: /* Single indirect block. */ ! 43: ind_level = 1; ! 44: ind_table = ip->i_a.i_addr[ND]; ! 45: vbno = vblockno - ND; /* Skip over direct blocks. */ ! 46: } else if (vblockno < (daddr_t) (ND + (NBN*NBN))) { ! 47: /* Double indirect block. */ ! 48: ind_level = 2; ! 49: ind_table = ip->i_a.i_addr[ND+1]; ! 50: vbno = vblockno - (ND + NBN); /* Skip over direct ! 51: * and indirect blocks. ! 52: */ ! 53: ! 54: } else { ! 55: /* Triple indirect block. */ ! 56: ind_level = 3; ! 57: ind_table = ip->i_a.i_addr[ND+2]; ! 58: /* Skip over direct, indirect blocks, ! 59: * and double indirect blocks. ! 60: */ ! 61: vbno = vblockno - (ND + NBN + NBN*NBN); ! 62: } ! 63: ! 64: return(indirect(ind_level, ind_table, vbno)); ! 65: } /* vmap() */ ! 66: ! 67: /* indirect(uint16 ind_level, daddr_t ind_table_ptr, daddr_t vblockno) ! 68: * Recursively follow an indirection for a given virtual block number ! 69: * vblockno. ! 70: * ind_level must be the level of indirection still un-resolved. ! 71: * ind_table is the physical block number of the next indirection. ! 72: */ ! 73: daddr_t ! 74: indirect(ind_level, ind_table_ptr, vblockno) ! 75: uint16 ind_level; ! 76: daddr_t ind_table_ptr; ! 77: daddr_t vblockno; ! 78: { ! 79: BUF *bp; ! 80: daddr_t *my_block; ! 81: daddr_t next_ptr; ! 82: ! 83: /* Base case. Direct block. */ ! 84: if (0 == ind_level) { ! 85: /* At this point, the block number in ind_table_ptr ! 86: * is exactly the physical block number we've been ! 87: * looking for. ! 88: */ ! 89: return(ind_table_ptr); ! 90: } ! 91: ! 92: /* Recursive case. Some level of indirection. */ ! 93: ! 94: /* Read the next table. */ ! 95: bp = bread(ind_table_ptr); ! 96: ! 97: /* Pick out the actual disk block. */ ! 98: my_block = (daddr_t *) bp->b_paddr; ! 99: ! 100: /* Fetch the next indirection. */ ! 101: next_ptr = ind_lookup(ind_level, my_block, vblockno); ! 102: ! 103: /* Canonicalize it. */ ! 104: candaddr(next_ptr); ! 105: ! 106: #if 0 ! 107: /* Normally, buffers containing indirection blocks should not ! 108: * be brelease()'d. This is how we try to assure that they ! 109: * do not need to be read off of disk too often. ! 110: */ ! 111: sanity_check("indirect() about to brelease() and recurse"); ! 112: brelease(bp); /* DEBUG */ ! 113: #endif ! 114: ! 115: indirect(ind_level - 1, ! 116: next_ptr, ! 117: vblockno); ! 118: } /* indirect() */ ! 119: ! 120: /* ind_lookup(uint16 ind_level, daddr_t *ind_table, daddr_t vblockno) ! 121: * Look up the next level of block in table ind_table, for virtual ! 122: * block number vblockno. ! 123: * Note that this table is in DISK CANNONICAL format. If the local ! 124: * notion of daddr_t is a different size from DISK CANONICAL daddr_t ! 125: */ ! 126: daddr_t ! 127: ind_lookup(ind_level, ind_table, vblockno) ! 128: uint16 ind_level; ! 129: daddr_t *ind_table; ! 130: daddr_t vblockno; ! 131: { ! 132: return(ind_table[ind_index(ind_level, vblockno)]); ! 133: } ! 134: ! 135: /* uint16 ind_index(uint16 ind_level, daddr_t vblockno); ! 136: * Calculate the index needed for virtual block vblockno into ! 137: * a table of the given indirection level. ! 138: */ ! 139: #define SEVENONES 0x7f /* Mask of address bits for table lookups. ! 140: * NBN = 128 entries = 7 bit address. ! 141: */ ! 142: uint16 ! 143: ind_index(ind_level, vblockno) ! 144: uint16 ind_level; ! 145: daddr_t vblockno; ! 146: { ! 147: /* Move the appropriate 7 bits to the lowest position, ! 148: * and return them. ! 149: */ ! 150: return((vblockno >> (7 * (ind_level - 1))) & SEVENONES); ! 151: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.