Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2371 → Rev 2372

/branches/fs/uspace/fs/inode.c
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++;
}