From e8d11c2e846ad15b32caacc8a919722b76d00f79 Mon Sep 17 00:00:00 2001 From: kaashoek Date: Tue, 8 Aug 2006 18:07:37 +0000 Subject: [PATCH] mknod,ialloc,iupdate --- defs.h | 1 + fs.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs.h | 6 +++- fsvar.h | 2 ++ syscall.c | 38 ++++++++++++++++++++++ syscall.h | 1 + user.h | 2 +- userfs.c | 8 +++++ usys.S | 1 + 9 files changed, 152 insertions(+), 2 deletions(-) diff --git a/defs.h b/defs.h index 51c4d34..30b803d 100644 --- a/defs.h +++ b/defs.h @@ -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); diff --git a/fs.c b/fs.c index 0e987c2..6774350 100644 --- a/fs.c +++ b/fs.c @@ -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; +} diff --git a/fs.h b/fs.h index a842e64..48a1c13 100644 --- a/fs.h +++ b/fs.h @@ -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)) diff --git a/fsvar.h b/fsvar.h index dba45d5..ef678dd 100644 --- a/fsvar.h +++ b/fsvar.h @@ -6,6 +6,8 @@ struct inode { int count; int busy; short type; + short major; + short minor; short nlink; uint size; uint addrs[NDIRECT]; diff --git a/syscall.c b/syscall.c index 29ebee8..498078e 100644 --- a/syscall.c +++ b/syscall.c @@ -279,6 +279,41 @@ sys_open(void) return ufd; } +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) { @@ -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 diff --git a/syscall.h b/syscall.h index e894200..959f015 100644 --- a/syscall.h +++ b/syscall.h @@ -12,3 +12,4 @@ #define SYS_cons_puts 12 #define SYS_exec 13 #define SYS_open 14 +#define SYS_mknod 15 diff --git a/user.h b/user.h index 16664ca..cf98816 100644 --- a/user.h +++ b/user.h @@ -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*); diff --git a/userfs.c b/userfs.c index c263868..0b2e9c3 100644 --- a/userfs.c +++ b/userfs.c @@ -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"); diff --git a/usys.S b/usys.S index 2c3c855..3622f82 100644 --- a/usys.S +++ b/usys.S @@ -22,3 +22,4 @@ STUB(panic) STUB(cons_puts) STUB(exec) STUB(open) +STUB(mknod)