diff options
| -rw-r--r-- | defs.h | 1 | ||||
| -rw-r--r-- | fs.c | 95 | ||||
| -rw-r--r-- | fs.h | 6 | ||||
| -rw-r--r-- | fsvar.h | 2 | ||||
| -rw-r--r-- | syscall.c | 38 | ||||
| -rw-r--r-- | syscall.h | 1 | ||||
| -rw-r--r-- | user.h | 2 | ||||
| -rw-r--r-- | userfs.c | 8 | ||||
| -rw-r--r-- | usys.S | 1 | 
9 files changed, 152 insertions, 2 deletions
| @@ -109,3 +109,4 @@ void idecref(struct inode *ip);  void iput(struct inode *ip);  struct inode * namei(char *path);  int readi(struct inode *ip, void *xdst, uint off, uint n); +struct inode *mknod(struct inode *, char *, short, short, short); @@ -54,6 +54,8 @@ iget(uint dev, uint inum)    bp = bread(dev, inum / IPB + 2);    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)); @@ -62,6 +64,61 @@ iget(uint dev, uint inum)    return nip;  } +// allocate an inode on disk +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; +  ninodes = sb->ninodes; +  brelse(bp); +  +  for (inum = 1; inum < ninodes; inum++) {  // loop over inode blocks +    bp = bread(dev, inum / IPB + 2); +    dip = &((struct dinode *)(bp->data))[inum % IPB]; +    if (dip->type == 0) {  // a free inode +      break; +    } +    brelse(bp); +  } +  +  if (inum >= ninodes) { +    cprintf ("ialloc: no inodes left\n"); +    return 0; +  } + +  cprintf ("ialloc: %d\n", inum); +  dip->type = type; +  bwrite (dev, bp, inum / IPB + 2);   // mark it allocated on the disk +  brelse(bp); +  ip = iget (dev, inum); +  return ip; +} + +void  +iupdate (struct inode *ip) +{ +  struct buf *bp; +  struct dinode *dip; + +  bp = bread(ip->dev, ip->inum / IPB + 2); +  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; +  bwrite (ip->dev, bp, ip->inum / IPB + 2);   // mark it allocated on the disk +  brelse(bp);  +} +  void  ilock(struct inode *ip)  { @@ -214,3 +271,41 @@ namei(char *path)        cp++;    }  } + +struct inode * +mknod(struct inode *dp, char *cp, short type, short major, short minor) +{ +  struct inode *ip; +  struct dirent *ep = 0; +  int off; +  int i; +  struct buf *bp = 0; + +  cprintf("mknod: %s %d %d %d\n", cp, type, major, minor); + +  ip = ialloc(dp->dev, type); +  if (ip == 0) return 0; +  ip->major = major; +  ip->minor = minor; + +  for(off = 0; off < dp->size; off += 512) { +    bp = bread(dp->dev, bmap(dp, off / 512)); +    for(ep = (struct dirent *) bp->data; +	ep < (struct dirent *) (bp->data + 512); +	ep++){ +      if(ep->inum == 0) { +	goto found; +      } +    } +    brelse(bp); +  } +  panic("mknod: no dir entry free\n"); + + found: +  ep->inum = ip->inum; +  for(i = 0; i < DIRSIZ && cp[i]; i++) ep->name[i] = cp[i]; +  bwrite (dp->dev, bp, bmap(dp, off/512));   // write directory +  brelse(bp); +  iupdate (ip); +  return ip; +} @@ -6,18 +6,22 @@ struct superblock{    int ninodes;  }; -#define NDIRECT 14 +#define NDIRECT 13  // inodes start at the third sector  // and blocks start at (ninodes * sizeof(dinode) + 511) / 512  struct dinode {    short type; +  short major; +  short minor;    short nlink;    uint size;    uint addrs[NDIRECT];  }; +  #define T_DIR 1  #define T_FILE 2 +#define T_DEV 3  #define IPB (512 / sizeof(struct dinode)) @@ -6,6 +6,8 @@ struct inode {    int count;    int busy;    short type; +  short major; +  short minor;    short nlink;    uint size;    uint addrs[NDIRECT]; @@ -280,6 +280,41 @@ sys_open(void)  }  int +sys_mknod(void) +{ +  struct proc *cp = curproc[cpu()]; +  struct inode *dp, *nip; +  uint arg0, arg1, arg2, arg3; +  int l; + +  if(fetcharg(0, &arg0) < 0 || fetcharg(1, &arg1) < 0 ||  +     fetcharg(2, &arg2) < 0 || fetcharg(3, &arg3) < 0) +    return -1; + +  if((l = checkstring(arg0)) < 0) +    return -1; + +  if(l >= DIRSIZ) +    return -1; + +  dp = iget(rootdev, 1); + +  cprintf("root inode type: %d\n", dp->type); + +  if (dp->type != T_DIR)  +    return -1; +   +  nip = mknod (dp, cp->mem + arg0, (short) arg1, (short) arg2,  +		   (short) arg3); + +  if (nip == 0) return -1; +  iput(nip); +  iput(dp); +   +  return 0; +} + +int  sys_exec(void)  {    struct proc *cp = curproc[cpu()]; @@ -515,6 +550,9 @@ syscall(void)    case SYS_open:      ret = sys_open();      break; +  case SYS_mknod: +    ret = sys_mknod(); +    break;    default:      cprintf("unknown sys call %d\n", num);      // XXX fault @@ -12,3 +12,4 @@  #define SYS_cons_puts 12  #define SYS_exec 13  #define SYS_open 14 +#define SYS_mknod 15 @@ -10,7 +10,7 @@ int block(void);  int kill(int);  int panic(char*);  int cons_puts(char*); - +int mknod (char*,short,short,short);  int puts(char*);  int puts1(char*);  char* strcpy(char*, char*); @@ -1,4 +1,6 @@  #include "user.h" +#include "types.h" +#include "fs.h"  // file system tests @@ -12,6 +14,12 @@ main(void)    puts("userfs running\n");    block(); + +  if (mknod ("console", T_DEV, 1, 1) < 0) +    puts ("mknod failed\n"); +  else +    puts ("made a node\n"); +    fd = open("echo", 0);    if(fd >= 0){      puts("open echo ok\n"); @@ -22,3 +22,4 @@ STUB(panic)  STUB(cons_puts)  STUB(exec)  STUB(open) +STUB(mknod) | 
