~ubuntu-branches/debian/stretch/jfsutils/stretch

« back to all changes in this revision

Viewing changes to libfs/inode.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Hornburg (Racke)
  • Date: 2005-01-07 10:12:20 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050107101220-ka3f7smw42zysmk1
Tags: 1.1.7-1
* new upstream release (Closes: #289106)
* start synopsis with lowercase

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *   Copyright (c) International Business Machines  Corp., 2000
 
2
 *   Copyright (c) International Business Machines Corp., 2000-2002
3
3
 *
4
4
 *   This program is free software;  you can redistribute it and/or modify
5
5
 *   it under the terms of the GNU General Public License as published by
18
18
#include <stdio.h>
19
19
#include <stdlib.h>
20
20
#include <string.h>
21
 
#include "jfs_byteorder.h"
 
21
#include "jfs_endian.h"
22
22
#include "jfs_types.h"
23
23
#include <errno.h>
24
24
 
25
 
#include "jfs_filsys.h" 
 
25
#include "jfs_filsys.h"
26
26
#include "jfs_dinode.h"
27
27
#include "devices.h"
28
 
#include "jfs_imap.h" 
 
28
#include "jfs_imap.h"
29
29
#include "inode.h"
30
30
#include "utilsubs.h"
31
31
#include "message.h"
32
32
 
33
 
/* endian routines */
34
 
extern uint32_t type_jfs;
35
 
extern void ujfs_swap_dinode( dinode_t  *, int32_t, uint32_t );
36
 
extern void ujfs_swap_iag_t( iag_t  * );
37
 
extern void ujfs_swap_xtpage_t( xtpage_t * );
38
 
 
39
33
/*
40
34
 * NAME: ujfs_rwinode
41
35
 *                                                                    
71
65
 * RETURNS: 0 for success
72
66
 *      Failure, any other value
73
67
 */
74
 
int32_t ujfs_rwinode( HFILE              fd,
75
 
                              struct dinode      *di,
76
 
                              uint32_t           inum,
77
 
                              int32_t        mode,
78
 
                              int32_t        fs_block_size,
79
 
                              uint32_t           which_table,
80
 
                      uint32_t       sb_flag )
 
68
int ujfs_rwinode(HFILE fd,
 
69
                 struct dinode *di,
 
70
                 uint32_t inum,
 
71
                 int32_t mode, 
 
72
                 int32_t fs_block_size, 
 
73
                 uint32_t which_table, 
 
74
                 uint32_t sb_flag)
81
75
{
82
 
    struct dinode  map_inode;
83
 
    int32_t            rc;
84
 
    int64_t            inode_extent_address, inode_address;
85
 
    int64_t            map_inode_address;
86
 
    uint32_t       iag_key;
87
 
    int32_t            iag_inode_num, inode_ext_index;
88
 
    iag_t              iag_for_inode;
89
 
    int64_t            iag_address;
90
 
    int32_t            l2nbperpage = log2shift(PSIZE/fs_block_size);
91
 
 
92
 
    /*
93
 
     * Determine disk address for the inode to be read or written.
94
 
     *
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.
100
 
     */
101
 
    if( which_table == AGGREGATE_I ) {
102
 
            /*
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
105
 
             * this extent
106
 
             */
107
 
            if( inum >= NUM_INODE_PER_EXTENT ) {
108
 
                fprintf(stderr,
109
 
                            "Internal error: %s(%d): Aggregate inode out of range (%d)\n",
110
 
                            __FILE__, __LINE__, inum );
111
 
                return ERROR_INVALID_ACCESS;
112
 
            }
113
 
 
114
 
            inode_address = (inum * sizeof(struct dinode)) + AGGR_INODE_TABLE_START;
115
 
    } else if( which_table == FILESYSTEM_I ) {
116
 
            /*
117
 
             * Find the IAG which describes this inode.
118
 
             */
119
 
            iag_key = INOTOIAG(inum);
120
 
 
121
 
            /*
122
 
             * Read Fileset inode describing the Fileset Inode Allocation Map so we
123
 
             * have the B+-tree information
124
 
             */
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 ),
128
 
                                                 &map_inode, GET );
129
 
 
130
 
        /* swap if on big endian machine */
131
 
        if (type_jfs & JFS_SWAP_BYTES) {
132
 
                ujfs_swap_dinode( &map_inode, GET, sb_flag );
133
 
        }
134
 
 
135
 
            if( rc != 0 ) return(rc);
136
 
 
137
 
            /*
138
 
             * Get address for IAG describing this inode
139
 
             */
140
 
            rc = ujfs_rwdaddr( fd, &iag_address, &map_inode,
141
 
                                       IAGTOLBLK(iag_key, l2nbperpage), GET, fs_block_size );
142
 
            if( rc != 0 ) return(rc);
143
 
 
144
 
            /*
145
 
             * Read iag which describes the specified inode.
146
 
             */
147
 
            rc = ujfs_rw_diskblocks( fd, iag_address, sizeof(iag_t), &iag_for_inode,
148
 
                                                 GET );
149
 
 
150
 
        /* swap if on big endian machine */
151
 
        if (type_jfs & JFS_SWAP_BYTES) {
152
 
            ujfs_swap_iag_t( &iag_for_inode );
153
 
        }
154
 
 
155
 
            if( rc != 0 ) return(rc);
156
 
 
157
 
            /*
158
 
             * Determine which inode within the found IAG is being referenced
159
 
             */
160
 
            iag_inode_num = inum % NUM_INODE_PER_IAG;
161
 
 
162
 
            /*
163
 
             * Find the inode extent descriptor within the found IAG which describes
164
 
             * the inode extent containing the specified inode.
165
 
             */
166
 
            inode_ext_index = iag_inode_num / NUM_INODE_PER_EXTENT;
167
 
 
168
 
            /*
169
 
             * From the correct inode extent descriptor in the IAG we can determine
170
 
             * the disk address for the specified inode.
171
 
             */
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;
177
 
    } else {
178
 
            fprintf(stderr, "Internal error: %s(%d): Bad map inode number (%d)\n",
179
 
                        __FILE__, __LINE__, which_table );
180
 
            return ERROR_INVALID_HANDLE;
181
 
    }
182
 
 
183
 
    /*
184
 
     * Now read/write the actual inode
185
 
     */
186
 
 
187
 
    /* swap if on big endian machine */
188
 
    if ( (type_jfs & JFS_SWAP_BYTES) && (mode == PUT) ) {
189
 
        /* copy to buffer for swap */
190
 
        dinode_t  *buffer;
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);
194
 
            return( ENOMEM );
195
 
        }
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 );
199
 
        free( buffer );
200
 
    } else {
201
 
        rc = ujfs_rw_diskblocks( fd, inode_address, sizeof( struct dinode ), di, mode );
202
 
    }
203
 
 
204
 
    /* swap if on big endian machine */
205
 
    if ( (type_jfs & JFS_SWAP_BYTES) && (mode == GET) ) {
206
 
        ujfs_swap_dinode( di, GET, sb_flag );
207
 
    }
208
 
 
209
 
 
210
 
    return rc;
 
76
        struct dinode map_inode;
 
77
        int rc;
 
78
        int64_t inode_extent_address, inode_address;
 
79
        int64_t map_inode_address;
 
80
        uint32_t iag_key;
 
81
        int32_t iag_inode_num, inode_ext_index;
 
82
        struct iag iag_for_inode;
 
83
        int64_t iag_address;
 
84
        int32_t l2nbperpage = log2shift(PSIZE / fs_block_size);
 
85
 
 
86
        /*
 
87
         * Determine disk address for the inode to be read or written.
 
88
         *
 
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.
 
94
         */
 
95
        if (which_table == AGGREGATE_I) {
 
96
                /*
 
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
 
99
                 * this extent
 
100
                 */
 
101
                if (inum >= NUM_INODE_PER_EXTENT) {
 
102
                        fprintf(stderr,
 
103
                                "Internal error: %s(%d): Aggregate inode out of range (%d)\n",
 
104
                                __FILE__, __LINE__, inum);
 
105
                        return ERROR_INVALID_ACCESS;
 
106
                }
 
107
 
 
108
                inode_address = (inum * sizeof (struct dinode)) + AGGR_INODE_TABLE_START;
 
109
        } else if (which_table == FILESYSTEM_I) {
 
110
                /*
 
111
                 * Find the IAG which describes this inode.
 
112
                 */
 
113
                iag_key = INOTOIAG(inum);
 
114
 
 
115
                /*
 
116
                 * Read Fileset inode describing the Fileset Inode Allocation Map so we
 
117
                 * have the B+-tree information
 
118
                 */
 
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);
 
121
 
 
122
                /* swap if on big endian machine */
 
123
                ujfs_swap_dinode(&map_inode, GET, sb_flag);
 
124
 
 
125
                if (rc != 0)
 
126
                        return (rc);
 
127
 
 
128
                /*
 
129
                 * Get address for IAG describing this inode
 
130
                 */
 
131
                rc = ujfs_rwdaddr(fd, &iag_address, &map_inode,
 
132
                                  IAGTOLBLK(iag_key, l2nbperpage), GET, fs_block_size);
 
133
                if (rc != 0)
 
134
                        return (rc);
 
135
 
 
136
                /*
 
137
                 * Read iag which describes the specified inode.
 
138
                 */
 
139
                rc = ujfs_rw_diskblocks(fd, iag_address, sizeof (struct iag), &iag_for_inode, GET);
 
140
 
 
141
                /* swap if on big endian machine */
 
142
                ujfs_swap_iag(&iag_for_inode);
 
143
 
 
144
                if (rc != 0)
 
145
                        return (rc);
 
146
 
 
147
                /*
 
148
                 * Determine which inode within the found IAG is being referenced
 
149
                 */
 
150
                iag_inode_num = inum % NUM_INODE_PER_IAG;
 
151
 
 
152
                /*
 
153
                 * Find the inode extent descriptor within the found IAG which describes
 
154
                 * the inode extent containing the specified inode.
 
155
                 */
 
156
                inode_ext_index = iag_inode_num / NUM_INODE_PER_EXTENT;
 
157
 
 
158
                /*
 
159
                 * From the correct inode extent descriptor in the IAG we can determine
 
160
                 * the disk address for the specified inode.
 
161
                 */
 
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;
 
165
        } else {
 
166
                fprintf(stderr, "Internal error: %s(%d): Bad map inode number (%d)\n",
 
167
                        __FILE__, __LINE__, which_table);
 
168
                return ERROR_INVALID_HANDLE;
 
169
        }
 
170
 
 
171
        /*
 
172
         * Now read/write the actual inode
 
173
         */
 
174
 
 
175
        /* swap if on big endian machine */
 
176
        if (mode == PUT)
 
177
                ujfs_swap_dinode(di, PUT, sb_flag);
 
178
 
 
179
        rc = ujfs_rw_diskblocks(fd, inode_address, sizeof (struct dinode), di, mode);
 
180
 
 
181
        /* swap if on big endian machine */
 
182
        ujfs_swap_dinode(di, GET, sb_flag);
 
183
 
 
184
        return rc;
211
185
}
212
186
 
213
 
 
214
187
/*
215
188
 * NAME: ujfs_rwdaddr
216
189
 *                                                                    
237
210
 * RETURNS: 0 for success
238
211
 *      Failure, any other value
239
212
 */
240
 
int32_t ujfs_rwdaddr( HFILE              fd,
241
 
                              int64_t        *offset,
242
 
                              struct dinode      *di,
243
 
                              int64_t        lbno,
244
 
                              int32_t        mode,
245
 
                              int32_t        fs_block_size )
 
213
int ujfs_rwdaddr(HFILE fd,
 
214
                 int64_t * offset,
 
215
                 struct dinode * di, 
 
216
                 int64_t lbno, 
 
217
                 int32_t mode, 
 
218
                 int32_t fs_block_size)
246
219
{
247
 
    xad_t         *disk_extent;
248
 
    int64_t       disk_extent_offset;
249
 
    xtpage_t  *page;
250
 
    int32_t       lim, base, index;
251
 
    int32_t       cmp, rc;
252
 
    char          buffer[PSIZE];
253
 
    int64_t       offset64;
254
 
 
255
 
    page = (xtpage_t *)&(di->di_btroot);
256
 
 
257
 
descend:
258
 
    /* Binary search */
259
 
    for( base = XTENTRYSTART, lim = page->header.nextindex - XTENTRYSTART;
260
 
             lim; lim >>=1) {
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 ;
265
 
          if (cmp == 0) {
266
 
            /* HIT! */
267
 
            if (page->header.flag & BT_LEAF) {
268
 
                  *offset = (addressXAD(&(page->xad[index])) +
269
 
                            (lbno - offsetXAD(&(page->xad[index])))) * fs_block_size;
270
 
                  return 0;
271
 
            } else {
272
 
                  rc = ujfs_rw_diskblocks(fd,
273
 
                                              addressXAD(&(page->xad[index])) * fs_block_size, PSIZE,
274
 
                                              buffer, GET);
275
 
 
276
 
          /* swap if on big endian machine */
277
 
          if (type_jfs & JFS_SWAP_BYTES) {
278
 
              ujfs_swap_xtpage_t( (xtpage_t *)buffer );
279
 
          }
280
 
 
281
 
                  if (rc) {
282
 
                    fprintf(stderr,
283
 
                                "Internal error: %s(%d): Error reading btree node\n",
284
 
                                __FILE__, __LINE__);
285
 
                    return rc;
286
 
                  }
287
 
                  page = (xtpage_t *)buffer;
288
 
                  goto descend;
289
 
            }
290
 
          } else if (cmp > 0) {
291
 
            base = index + 1;
292
 
            --lim;
293
 
          }
294
 
    }
295
 
 
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.
300
 
           */
301
 
          index = base ? base - 1 : base;
302
 
 
303
 
          rc = ujfs_rw_diskblocks(fd,
304
 
                                          addressXAD(&(page->xad[index])) * fs_block_size, PSIZE,
305
 
                                          buffer, GET);
306
 
 
307
 
      /* swap if on big endian machine */
308
 
      if (type_jfs & JFS_SWAP_BYTES) {
309
 
          ujfs_swap_xtpage_t( (xtpage_t *)buffer );
310
 
      }
311
 
 
312
 
          if (rc) {
313
 
            fprintf(stderr,
314
 
                        "Internal error: %s(%d): Error reading btree node\n", __FILE__,
315
 
                        __LINE__);
316
 
            return rc;
317
 
          }
318
 
          page = (xtpage_t *)buffer;
319
 
          goto descend;
320
 
    }
321
 
 
322
 
    /* Not found! */
323
 
    fprintf(stderr, "Internal error: %s(%d): Block %lld not found!\n", __FILE__,
324
 
                    __LINE__, (long long)lbno);
325
 
    return EINVAL;
326
 
 
327
 
    /*
328
 
     * This is really stupid right now, doesn't understand multiple extents
329
 
     */
330
 
    switch(mode) {
331
 
          case GET:
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;
335
 
            break;
336
 
          case PUT:
337
 
            fprintf(stderr, "Internal error: %s(%d): does not handle PUT\n",
338
 
                __FILE__, __LINE__);
339
 
            return EPERM;
340
 
            break;
341
 
          default:
342
 
            return EINVAL;
343
 
    }
344
 
    return 0;
 
220
        xad_t *disk_extent;
 
221
        int64_t disk_extent_offset;
 
222
        xtpage_t *page;
 
223
        int32_t lim, base, index;
 
224
        int rc;
 
225
        int32_t cmp;
 
226
        char buffer[PSIZE];
 
227
        int64_t offset64;
 
228
 
 
229
        page = (xtpage_t *) & (di->di_btroot);
 
230
 
 
231
      descend:
 
232
        /* Binary search */
 
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;
 
237
                if (cmp == 0) {
 
238
                        /* HIT! */
 
239
                        if (page->header.flag & BT_LEAF) {
 
240
                                *offset = (addressXAD(&(page->xad[index])) +
 
241
                                           (lbno - offsetXAD(&(page->xad[index])))) * fs_block_size;
 
242
                                return 0;
 
243
                        } else {
 
244
                                rc = ujfs_rw_diskblocks(fd, addressXAD(&(page->xad[index])) *
 
245
                                                        fs_block_size, PSIZE, buffer, GET);
 
246
 
 
247
                                /* swap if on big endian machine */
 
248
                                ujfs_swap_xtpage_t((xtpage_t *) buffer);
 
249
 
 
250
                                if (rc) {
 
251
                                        fprintf(stderr,
 
252
                                                "Internal error: %s(%d): Error reading btree node\n",
 
253
                                                __FILE__, __LINE__);
 
254
                                        return rc;
 
255
                                }
 
256
                                page = (xtpage_t *) buffer;
 
257
                                goto descend;
 
258
                        }
 
259
                } else if (cmp > 0) {
 
260
                        base = index + 1;
 
261
                        --lim;
 
262
                }
 
263
        }
 
264
 
 
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.
 
269
                 */
 
270
                index = base ? base - 1 : base;
 
271
 
 
272
                rc = ujfs_rw_diskblocks(fd, addressXAD(&(page->xad[index])) * fs_block_size, 
 
273
                                        PSIZE, buffer, GET);
 
274
 
 
275
                /* swap if on big endian machine */
 
276
                ujfs_swap_xtpage_t((xtpage_t *) buffer);
 
277
 
 
278
                if (rc) {
 
279
                        fprintf(stderr,
 
280
                                "Internal error: %s(%d): Error reading btree node\n", __FILE__, __LINE__);
 
281
                        return rc;
 
282
                }
 
283
                page = (xtpage_t *) buffer;
 
284
                goto descend;
 
285
        }
 
286
 
 
287
        /* Not found! */
 
288
        fprintf(stderr, "Internal error: %s(%d): Block %lld not found!\n", __FILE__,
 
289
                __LINE__, (long long) lbno);
 
290
        return EINVAL;
 
291
 
 
292
        /*
 
293
         * This is really stupid right now, doesn't understand multiple extents
 
294
         */
 
295
        switch (mode) {
 
296
        case GET:
 
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;
 
300
                break;
 
301
        case PUT:
 
302
                fprintf(stderr, "Internal error: %s(%d): does not handle PUT\n",
 
303
                        __FILE__, __LINE__);
 
304
                return EPERM;
 
305
                break;
 
306
        default:
 
307
                return EINVAL;
 
308
        }
 
309
        return 0;
345
310
}