⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs.c

📁 类unix x86平台的简单操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "types.h"#include "stat.h"#include "param.h"#include "x86.h"#include "mmu.h"#include "proc.h"#include "defs.h"#include "spinlock.h"#include "buf.h"#include "fs.h"#include "fsvar.h"#include "dev.h"// Inode table.  The inode table is an in-memory cache of the // on-disk inode structures.  If an inode in the table has a non-zero// reference count, then some open files refer to it and it must stay// in memory.  If an inode has a zero reference count, it is only in// memory as a cache in hopes of being used again (avoiding a disk read).// Any inode with reference count zero can be evicted from the table.// // In addition to having a reference count, inodes can be marked busy// (just like bufs), meaning that some code has logically locked the // inode, and others are not allowed to look at it. // This locking can last for a long// time (for example, if the inode is busy during a disk access),// so we don't use spin locks.  Instead, if a process wants to use// a particular inode, it must sleep(ip) to wait for it to be not busy.// See iget below.struct inode inode[NINODE];struct spinlock inode_table_lock;uint rootdev = 1;voidiinit(void){  initlock(&inode_table_lock, "inode_table");}// Allocate a disk block.static uintballoc(uint dev){  int b;  struct buf *bp;  struct superblock *sb;  int bi = 0;  int size;  int ninodes;  uchar m;  bp = bread(dev, 1);  sb = (struct superblock*) bp->data;  size = sb->size;  ninodes = sb->ninodes;  for(b = 0; b < size; b++) {    if(b % BPB == 0) {      brelse(bp);      bp = bread(dev, BBLOCK(b, ninodes));    }    bi = b % BPB;    m = 0x1 << (bi % 8);    if((bp->data[bi/8] & m) == 0) {  // is block free?      break;    }  }  if(b >= size)    panic("balloc: out of blocks");  bp->data[bi/8] |= 0x1 << (bi % 8);  bwrite(bp, BBLOCK(b, ninodes));  // mark it allocated on disk  brelse(bp);  return b;}// Free a disk block.static voidbfree(int dev, uint b){  struct buf *bp;  struct superblock *sb;  int bi;  int ninodes;  uchar m;  bp = bread(dev, 1);  sb = (struct superblock*) bp->data;  ninodes = sb->ninodes;  brelse(bp);  bp = bread(dev, b);  memset(bp->data, 0, BSIZE);  bwrite(bp, b);  brelse(bp);  bp = bread(dev, BBLOCK(b, ninodes));  bi = b % BPB;  m = ~(0x1 << (bi %8));  bp->data[bi/8] &= m;  bwrite(bp, BBLOCK(b, ninodes));  // mark it free on disk  brelse(bp);}// Find the inode with number inum on device dev// and return an in-memory copy.  Loads the inode// from disk into the in-core table if necessary.// The returned inode has busy set and has its ref count incremented.// Caller must iput the return value when done with it.struct inode*iget(uint dev, uint inum){  struct inode *ip, *nip;  struct dinode *dip;  struct buf *bp;  acquire(&inode_table_lock); loop:  nip = 0;  for(ip = &inode[0]; ip < &inode[NINODE]; ip++){    if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){      if(ip->busy){        sleep(ip, &inode_table_lock);        // Since we droped inode_table_lock, ip might have been reused        // for some other inode entirely.  Must start the scan over,        // and hopefully this time we will find the inode we want         // and it will not be busy.        goto loop;      }      ip->ref++;      ip->busy = 1;      release(&inode_table_lock);      return ip;    }    if(nip == 0 && ip->ref == 0)      nip = ip;  }  if(nip == 0)    panic("out of inodes");  nip->dev = dev;  nip->inum = inum;  nip->ref = 1;  nip->busy = 1;  release(&inode_table_lock);  bp = bread(dev, IBLOCK(inum));  dip = &((struct dinode*)(bp->data))[inum % IPB];  nip->type = dip->type;  nip->major = dip->major;  nip->minor = dip->minor;  nip->nlink = dip->nlink;  nip->size = dip->size;  memmove(nip->addrs, dip->addrs, sizeof(nip->addrs));  brelse(bp);  return nip;}// Copy inode in memory, which has changed, to disk.// Caller must have locked ip.voidiupdate(struct inode *ip){  struct buf *bp;  struct dinode *dip;  bp = bread(ip->dev, IBLOCK(ip->inum));  dip = &((struct dinode*)(bp->data))[ip->inum % IPB];  dip->type = ip->type;  dip->major = ip->major;  dip->minor = ip->minor;  dip->nlink = ip->nlink;  dip->size = ip->size;  memmove(dip->addrs, ip->addrs, sizeof(ip->addrs));  bwrite(bp, IBLOCK(ip->inum));   // mark it allocated on the disk  brelse(bp);}// Allocate a new inode with the given type// from the file system on device dev.struct inode*ialloc(uint dev, short type){  struct inode *ip;  struct dinode *dip = 0;  struct superblock *sb;  int ninodes;  int inum;  struct buf *bp;  bp = bread(dev, 1);  sb = (struct superblock*) bp->data;  ninodes = sb->ninodes;  brelse(bp);  for(inum = 1; inum < ninodes; inum++) {  // loop over inode blocks    bp = bread(dev, IBLOCK(inum));    dip = &((struct dinode*)(bp->data))[inum % IPB];    if(dip->type == 0) {  // a free inode      break;    }    brelse(bp);  }  if(inum >= ninodes)    panic("ialloc: no inodes left");  memset(dip, 0, sizeof(*dip));  dip->type = type;  bwrite(bp, IBLOCK(inum));   // mark it allocated on the disk  brelse(bp);  ip = iget(dev, inum);  return ip;}// Free the given inode from its file system.static voidifree(struct inode *ip){  ip->type = 0;  iupdate(ip);}// Lock the given inode (wait for it to be not busy,// and then ip->busy).  // Caller must already hold a reference to ip.// Otherwise, if all the references to ip go away,// it might be reused underfoot.voidilock(struct inode *ip){  if(ip->ref < 1)    panic("ilock");  acquire(&inode_table_lock);  while(ip->busy)    sleep(ip, &inode_table_lock);  ip->busy = 1;  release(&inode_table_lock);}// Caller holds reference to ip and has locked it.// Caller no longer needs to examine / change it.// Unlock it, but keep the reference.voidiunlock(struct inode *ip){  if(ip->busy != 1 || ip->ref < 1)    panic("iunlock");  acquire(&inode_table_lock);  ip->busy = 0;  wakeup(ip);  release(&inode_table_lock);}// Return the disk block address of the nth block in inode ip.uintbmap(struct inode *ip, uint bn){  unsigned x;  uint *a;  struct buf *inbp;  if(bn >= MAXFILE)    panic("bmap 1");  if(bn < NDIRECT) {    x = ip->addrs[bn];    if(x == 0)      panic("bmap 2");  } else {    if(ip->addrs[INDIRECT] == 0)      panic("bmap 3");    inbp = bread(ip->dev, ip->addrs[INDIRECT]);    a = (uint*) inbp->data;    x = a[bn - NDIRECT];    brelse(inbp);    if(x == 0)      panic("bmap 4");  }  return x;}// Truncate the inode ip, discarding all its data blocks.voiditrunc(struct inode *ip){  int i, j;  struct buf *inbp;  for(i = 0; i < NADDRS; i++) {    if(ip->addrs[i] != 0) {      if(i == INDIRECT) {        inbp = bread(ip->dev, ip->addrs[INDIRECT]);        uint *a = (uint*) inbp->data;        for(j = 0; j < NINDIRECT; j++) {          if(a[j] != 0) {            bfree(ip->dev, a[j]);            a[j] = 0;          }        }        brelse(inbp);      }      bfree(ip->dev, ip->addrs[i]);      ip->addrs[i] = 0;    }  }  ip->size = 0;  iupdate(ip);}// Caller holds reference to ip and has locked it,// possibly editing it.// Release lock and drop the reference.voidiput(struct inode *ip){  if(ip->ref < 1 || ip->busy != 1)    panic("iput");  if((ip->ref == 1) && (ip->nlink == 0)) {    itrunc(ip);    ifree(ip);  }  acquire(&inode_table_lock);  ip->ref -= 1;  ip->busy = 0;  wakeup(ip);  release(&inode_table_lock);}// Caller holds reference to ip but not lock.// Drop reference.voididecref(struct inode *ip){  ilock(ip);  iput(ip);}// Increment reference count for ip.voidiincref(struct inode *ip){  ilock(ip);  ip->ref++;  iunlock(ip);}// Copy stat information from inode.voidstati(struct inode *ip, struct stat *st){  st->dev = ip->dev;  st->ino = ip->inum;  st->type = ip->type;  st->nlink = ip->nlink;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -