0,0 → 1,170 |
/* This file manages the inode table. There are procedures to allocate and |
* deallocate inodes, acquire, erase, and release them, and read and write |
* them from the disk. |
*/ |
|
/* Methods: |
* get_inode: search inode table for a given inode; if not there, read it |
* read_inode: read a disk block and extract an inode |
* v1_copy_inode copy from disk inode (V1.x) to in-memory inode struct |
* v2_copy_inode copy from disk inode (V2.x) to in-memory inode structs |
* put_inode indicate that an inode is no longer needed in memory |
* dup_inode: indicate that someone else is using an inode table entry |
*/ |
|
#include "fs.h" |
#include "block.h" |
#include "file.h" |
#include "fproc.h" |
#include "inode.h" |
#include "super.h" |
|
|
inode_t inode[NR_INODES]; |
|
static void v1_copy_inode(inode_t *rip, d1_inode_t *dip, int normal); |
static void v2_copy_inode(inode_t *rip, d2_inode_t *dip, int normal); |
|
|
inode_t *get_inode(int numb) |
{ |
/* Find a slot in the inode table, load the specified inode into it, and |
* return a pointer to the slot. |
*/ |
|
register inode_t *rip, *xp; |
|
/* Search the inode table both for numb and a free slot. */ |
xp = NIL_INODE; |
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) { |
if (rip->i_count > 0) { /* only check used slots for numb */ |
if (rip->i_num == numb) { |
/* This is the inode that we are looking for. */ |
rip->i_count++; |
return rip; /* numb found */ |
} |
} |
else { |
xp = rip; /* remember this free slot for later */ |
} |
|
} |
|
/* Inode we want is not currently in use. Did we find a free slot? */ |
if (xp == NIL_INODE) { /* inode table completely full */ |
err_code = FS_ENFILE; |
return NIL_INODE; |
} |
|
/* A free inode slot has been located. Load the inode into it. */ |
xp->i_num = numb; |
xp->i_count = 1; |
read_inode(xp); |
|
return xp; |
} |
|
void read_inode(register inode_t *rip) |
{ |
|
/* An entry in the inode table is to be copied from the disk. */ |
|
register block_t *bp; |
register super_block_t *sp; |
d1_inode_t *dip1; |
d2_inode_t *dip2; |
block_num_t b, offset; |
|
/* Get the block where the inode resides. */ |
sp = get_super(); /* get pointer to super block */ |
rip->i_sp = sp; /* inode must contain super block pointer */ |
offset = sp->s_imap_blocks + sp->s_zmap_blocks + 2; |
b = (block_num_t)(rip->i_num - 1)/sp->s_inodes_per_block + offset; |
bp = get_block(b); |
dip1 = bp->b.b__v1_ino + (rip->i_num - 1) % V1_INODES_PER_BLOCK; |
dip2 = bp->b.b__v2_ino + (rip->i_num - 1) % V2_INODES_PER_BLOCK; |
|
/* Copy inode to the in-core table, swapping bytes if need be. */ |
if (sp->s_version == V1) { |
v1_copy_inode(rip, dip1, sp->s_native); |
} |
else { |
v2_copy_inode(rip, dip2, sp->s_native); |
} |
} |
|
void v1_copy_inode(inode_t *rip, d1_inode_t *dip, int normal) |
{ |
|
|
/* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and |
* 68000) all have different inode layouts. When an inode is read or written |
* this routine handles the conversions so that the information in the inode |
* table is independent of the disk structure from which the inode came. |
* This routine copies from V1 disks. |
*/ |
|
int i; |
|
/* Some check is made for valid number of inode. */ |
if (rip == NIL_INODE || dip == NULL) |
return; |
|
/* Copy V1.x inode to the in-memory table, swapping bytes if need be. */ |
rip->i_mode = conv2(normal, dip->d1_mode); |
rip->i_size = conv4(normal, dip->d1_size); |
rip->i_nlinks = (nlink_t)dip->d1_nlinks; /* 1 char */ |
rip->i_ndzones = V1_NR_DZONES; |
rip->i_nindirs = V1_INDIRECTS; |
|
for (i = 0; i < V1_NR_TZONES; i++) |
rip->i_zone[i] = conv2(normal, dip->d1_zone[i]); |
} |
|
void v2_copy_inode(inode_t *rip, d2_inode_t *dip, int normal) |
{ |
|
|
/* Same as old_icopy, but to/from V2 disk layout. */ |
|
int i; |
|
/* Some check is made for valid number of inode. */ |
if (rip == NIL_INODE || dip == NULL) |
return; |
|
/* Copy V2.x inode to the in-core table, swapping bytes if need be. */ |
rip->i_mode = conv2(normal, dip->d2_mode); |
rip->i_size = conv4(normal, dip->d2_size); |
rip->i_nlinks = conv2(normal, dip->d2_nlinks); |
rip->i_ndzones = V2_NR_DZONES; |
rip->i_nindirs = V2_INDIRECTS; |
|
for (i = 0; i < V2_NR_TZONES; i++) |
rip->i_zone[i] = conv4(normal, dip->d2_zone[i]); |
} |
|
void put_inode(inode_t *rip) |
{ |
|
/* The caller is no longer using this inode. */ |
|
if (rip == NIL_INODE) |
return; |
|
rip->i_count--; |
} |
|
void dup_inode(inode_t *rip) |
{ |
|
/* This routine is a simplified form of get_inode() for the case where |
* the inode pointer is already known. |
*/ |
|
if (rip == NIL_INODE) |
return; |
|
rip->i_count++; |
} |
|