71
65
* RETURNS: 0 for success
72
66
* Failure, any other value
74
int32_t ujfs_rwinode( HFILE fd,
78
int32_t fs_block_size,
68
int ujfs_rwinode(HFILE fd,
72
int32_t fs_block_size,
82
struct dinode map_inode;
84
int64_t inode_extent_address, inode_address;
85
int64_t map_inode_address;
87
int32_t iag_inode_num, inode_ext_index;
90
int32_t l2nbperpage = log2shift(PSIZE/fs_block_size);
93
* Determine disk address for the inode to be read or written.
95
* If the inode we want is from the Aggregate Inode Table we can just
96
* determine the address for the inode directly since we know where this
97
* table lives. If the inode we want is from the Fileset Inode Table we
98
* will need to read the Fileset Inode first and then follow its B+-tree to
99
* determine where the inode we want is.
101
if( which_table == AGGREGATE_I ) {
103
* Since the Aggregate Inode Table is just one inode extent for the
104
* first release we won't attempt to read an inode which is outside of
107
if( inum >= NUM_INODE_PER_EXTENT ) {
109
"Internal error: %s(%d): Aggregate inode out of range (%d)\n",
110
__FILE__, __LINE__, inum );
111
return ERROR_INVALID_ACCESS;
114
inode_address = (inum * sizeof(struct dinode)) + AGGR_INODE_TABLE_START;
115
} else if( which_table == FILESYSTEM_I ) {
117
* Find the IAG which describes this inode.
119
iag_key = INOTOIAG(inum);
122
* Read Fileset inode describing the Fileset Inode Allocation Map so we
123
* have the B+-tree information
125
map_inode_address = AGGR_INODE_TABLE_START +
126
(which_table * sizeof(struct dinode));
127
rc = ujfs_rw_diskblocks( fd, map_inode_address, sizeof( struct dinode ),
130
/* swap if on big endian machine */
131
if (type_jfs & JFS_SWAP_BYTES) {
132
ujfs_swap_dinode( &map_inode, GET, sb_flag );
135
if( rc != 0 ) return(rc);
138
* Get address for IAG describing this inode
140
rc = ujfs_rwdaddr( fd, &iag_address, &map_inode,
141
IAGTOLBLK(iag_key, l2nbperpage), GET, fs_block_size );
142
if( rc != 0 ) return(rc);
145
* Read iag which describes the specified inode.
147
rc = ujfs_rw_diskblocks( fd, iag_address, sizeof(iag_t), &iag_for_inode,
150
/* swap if on big endian machine */
151
if (type_jfs & JFS_SWAP_BYTES) {
152
ujfs_swap_iag_t( &iag_for_inode );
155
if( rc != 0 ) return(rc);
158
* Determine which inode within the found IAG is being referenced
160
iag_inode_num = inum % NUM_INODE_PER_IAG;
163
* Find the inode extent descriptor within the found IAG which describes
164
* the inode extent containing the specified inode.
166
inode_ext_index = iag_inode_num / NUM_INODE_PER_EXTENT;
169
* From the correct inode extent descriptor in the IAG we can determine
170
* the disk address for the specified inode.
172
inode_extent_address = addressPXD(
173
&(iag_for_inode.inoext[inode_ext_index]) );
174
inode_extent_address *= fs_block_size;
175
inode_address = (inum % NUM_INODE_PER_EXTENT * sizeof(struct dinode)) +
176
inode_extent_address;
178
fprintf(stderr, "Internal error: %s(%d): Bad map inode number (%d)\n",
179
__FILE__, __LINE__, which_table );
180
return ERROR_INVALID_HANDLE;
184
* Now read/write the actual inode
187
/* swap if on big endian machine */
188
if ( (type_jfs & JFS_SWAP_BYTES) && (mode == PUT) ) {
189
/* copy to buffer for swap */
191
buffer = malloc(sizeof(struct dinode));
192
if ( buffer == NULL) {
193
message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, STDOUT_CODE, NO_RESPONSE, OSO_MSG);
196
memcpy( (dinode_t *)buffer, di, sizeof(struct dinode));
197
ujfs_swap_dinode( (dinode_t *)buffer, PUT, sb_flag );
198
rc = ujfs_rw_diskblocks( fd, inode_address, sizeof( struct dinode ), buffer, mode );
201
rc = ujfs_rw_diskblocks( fd, inode_address, sizeof( struct dinode ), di, mode );
204
/* swap if on big endian machine */
205
if ( (type_jfs & JFS_SWAP_BYTES) && (mode == GET) ) {
206
ujfs_swap_dinode( di, GET, sb_flag );
76
struct dinode map_inode;
78
int64_t inode_extent_address, inode_address;
79
int64_t map_inode_address;
81
int32_t iag_inode_num, inode_ext_index;
82
struct iag iag_for_inode;
84
int32_t l2nbperpage = log2shift(PSIZE / fs_block_size);
87
* Determine disk address for the inode to be read or written.
89
* If the inode we want is from the Aggregate Inode Table we can just
90
* determine the address for the inode directly since we know where this
91
* table lives. If the inode we want is from the Fileset Inode Table we
92
* will need to read the Fileset Inode first and then follow its B+-tree to
93
* determine where the inode we want is.
95
if (which_table == AGGREGATE_I) {
97
* Since the Aggregate Inode Table is just one inode extent for the
98
* first release we won't attempt to read an inode which is outside of
101
if (inum >= NUM_INODE_PER_EXTENT) {
103
"Internal error: %s(%d): Aggregate inode out of range (%d)\n",
104
__FILE__, __LINE__, inum);
105
return ERROR_INVALID_ACCESS;
108
inode_address = (inum * sizeof (struct dinode)) + AGGR_INODE_TABLE_START;
109
} else if (which_table == FILESYSTEM_I) {
111
* Find the IAG which describes this inode.
113
iag_key = INOTOIAG(inum);
116
* Read Fileset inode describing the Fileset Inode Allocation Map so we
117
* have the B+-tree information
119
map_inode_address = AGGR_INODE_TABLE_START + (which_table * sizeof (struct dinode));
120
rc = ujfs_rw_diskblocks(fd, map_inode_address, sizeof (struct dinode), &map_inode, GET);
122
/* swap if on big endian machine */
123
ujfs_swap_dinode(&map_inode, GET, sb_flag);
129
* Get address for IAG describing this inode
131
rc = ujfs_rwdaddr(fd, &iag_address, &map_inode,
132
IAGTOLBLK(iag_key, l2nbperpage), GET, fs_block_size);
137
* Read iag which describes the specified inode.
139
rc = ujfs_rw_diskblocks(fd, iag_address, sizeof (struct iag), &iag_for_inode, GET);
141
/* swap if on big endian machine */
142
ujfs_swap_iag(&iag_for_inode);
148
* Determine which inode within the found IAG is being referenced
150
iag_inode_num = inum % NUM_INODE_PER_IAG;
153
* Find the inode extent descriptor within the found IAG which describes
154
* the inode extent containing the specified inode.
156
inode_ext_index = iag_inode_num / NUM_INODE_PER_EXTENT;
159
* From the correct inode extent descriptor in the IAG we can determine
160
* the disk address for the specified inode.
162
inode_extent_address = addressPXD(&(iag_for_inode.inoext[inode_ext_index]));
163
inode_extent_address *= fs_block_size;
164
inode_address = (inum % NUM_INODE_PER_EXTENT * sizeof (struct dinode)) + inode_extent_address;
166
fprintf(stderr, "Internal error: %s(%d): Bad map inode number (%d)\n",
167
__FILE__, __LINE__, which_table);
168
return ERROR_INVALID_HANDLE;
172
* Now read/write the actual inode
175
/* swap if on big endian machine */
177
ujfs_swap_dinode(di, PUT, sb_flag);
179
rc = ujfs_rw_diskblocks(fd, inode_address, sizeof (struct dinode), di, mode);
181
/* swap if on big endian machine */
182
ujfs_swap_dinode(di, GET, sb_flag);
215
188
* NAME: ujfs_rwdaddr
237
210
* RETURNS: 0 for success
238
211
* Failure, any other value
240
int32_t ujfs_rwdaddr( HFILE fd,
245
int32_t fs_block_size )
213
int ujfs_rwdaddr(HFILE fd,
218
int32_t fs_block_size)
248
int64_t disk_extent_offset;
250
int32_t lim, base, index;
255
page = (xtpage_t *)&(di->di_btroot);
259
for( base = XTENTRYSTART, lim = page->header.nextindex - XTENTRYSTART;
261
index = base + (lim >> 1);
262
offset64 = offsetXAD(&(page->xad[index]));
263
cmp = (lbno >= offset64 + lengthXAD(&(page->xad[index]))) ? 1 :
264
(lbno < offset64) ? -1 : 0 ;
267
if (page->header.flag & BT_LEAF) {
268
*offset = (addressXAD(&(page->xad[index])) +
269
(lbno - offsetXAD(&(page->xad[index])))) * fs_block_size;
272
rc = ujfs_rw_diskblocks(fd,
273
addressXAD(&(page->xad[index])) * fs_block_size, PSIZE,
276
/* swap if on big endian machine */
277
if (type_jfs & JFS_SWAP_BYTES) {
278
ujfs_swap_xtpage_t( (xtpage_t *)buffer );
283
"Internal error: %s(%d): Error reading btree node\n",
287
page = (xtpage_t *)buffer;
290
} else if (cmp > 0) {
296
if (page->header.flag & BT_INTERNAL ) {
297
/* Traverse internal page, it might hit down there
298
* If base is non-zero, decrement base by one to get the parent
299
* entry of the child page to search.
301
index = base ? base - 1 : base;
303
rc = ujfs_rw_diskblocks(fd,
304
addressXAD(&(page->xad[index])) * fs_block_size, PSIZE,
307
/* swap if on big endian machine */
308
if (type_jfs & JFS_SWAP_BYTES) {
309
ujfs_swap_xtpage_t( (xtpage_t *)buffer );
314
"Internal error: %s(%d): Error reading btree node\n", __FILE__,
318
page = (xtpage_t *)buffer;
323
fprintf(stderr, "Internal error: %s(%d): Block %lld not found!\n", __FILE__,
324
__LINE__, (long long)lbno);
328
* This is really stupid right now, doesn't understand multiple extents
332
disk_extent = &(((xtpage_t *)&(di->di_DASD))->xad[XTENTRYSTART]);
333
disk_extent_offset = addressXAD( disk_extent );
334
*offset = (disk_extent_offset + lbno) * fs_block_size;
337
fprintf(stderr, "Internal error: %s(%d): does not handle PUT\n",
221
int64_t disk_extent_offset;
223
int32_t lim, base, index;
229
page = (xtpage_t *) & (di->di_btroot);
233
for (base = XTENTRYSTART, lim = page->header.nextindex - XTENTRYSTART; lim; lim >>= 1) {
234
index = base + (lim >> 1);
235
offset64 = offsetXAD(&(page->xad[index]));
236
cmp = (lbno >= offset64 + lengthXAD(&(page->xad[index]))) ? 1 : (lbno < offset64) ? -1 : 0;
239
if (page->header.flag & BT_LEAF) {
240
*offset = (addressXAD(&(page->xad[index])) +
241
(lbno - offsetXAD(&(page->xad[index])))) * fs_block_size;
244
rc = ujfs_rw_diskblocks(fd, addressXAD(&(page->xad[index])) *
245
fs_block_size, PSIZE, buffer, GET);
247
/* swap if on big endian machine */
248
ujfs_swap_xtpage_t((xtpage_t *) buffer);
252
"Internal error: %s(%d): Error reading btree node\n",
256
page = (xtpage_t *) buffer;
259
} else if (cmp > 0) {
265
if (page->header.flag & BT_INTERNAL) {
266
/* Traverse internal page, it might hit down there
267
* If base is non-zero, decrement base by one to get the parent
268
* entry of the child page to search.
270
index = base ? base - 1 : base;
272
rc = ujfs_rw_diskblocks(fd, addressXAD(&(page->xad[index])) * fs_block_size,
275
/* swap if on big endian machine */
276
ujfs_swap_xtpage_t((xtpage_t *) buffer);
280
"Internal error: %s(%d): Error reading btree node\n", __FILE__, __LINE__);
283
page = (xtpage_t *) buffer;
288
fprintf(stderr, "Internal error: %s(%d): Block %lld not found!\n", __FILE__,
289
__LINE__, (long long) lbno);
293
* This is really stupid right now, doesn't understand multiple extents
297
disk_extent = &(((xtpage_t *) & (di->di_DASD))->xad[XTENTRYSTART]);
298
disk_extent_offset = addressXAD(disk_extent);
299
*offset = (disk_extent_offset + lbno) * fs_block_size;
302
fprintf(stderr, "Internal error: %s(%d): does not handle PUT\n",