|
|
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.