From 9e5970d596d7b1634200d50e96130886f593cede Mon Sep 17 00:00:00 2001 From: rtm Date: Sun, 13 Aug 2006 02:12:44 +0000 Subject: [PATCH] link() --- Notes | 4 +-- defs.h | 1 + fs.c | 89 ++++++++++++++++++++++++++++++++++++++--------------- ide.c | 2 -- main.c | 6 ---- proc.c | 3 -- syscall.c | 19 +++++++++++- syscall.h | 1 + user.h | 1 + usertests.c | 61 ++++++++++++++++++++++++++++++++++++ usys.S | 1 + 11 files changed, 149 insertions(+), 39 deletions(-) diff --git a/Notes b/Notes index 7e3edd5..386bc2f 100644 --- a/Notes +++ b/Notes @@ -355,8 +355,6 @@ HMM maybe the variables at the end of struct cpu are being overwritten OH! recursive interrupts will use up any amount of cpu[].stack! underflow and wrecks *previous* cpu's struct -better buffer cache replacement -read/write of open file that's been unlinked disk scheduling mkdir more than one directory content block @@ -365,3 +363,5 @@ sh redirection indirect blocks two bugs in unlink: don't just return if nlink > 0, and search for name, not inum +is there a create/create race for same file name? + resulting in two entries w/ same name in directory? diff --git a/defs.h b/defs.h index 6a4f1c2..c8e1870 100644 --- a/defs.h +++ b/defs.h @@ -123,3 +123,4 @@ int writei(struct inode *ip, char *addr, uint off, uint n); struct inode *mknod(char *, short, short, short); int unlink(char *cp); void iupdate (struct inode *ip); +int link(char *file1, char *file2); diff --git a/fs.c b/fs.c index e01b4fb..7f0d2ea 100644 --- a/fs.c +++ b/fs.c @@ -439,14 +439,41 @@ namei(char *path, uint *ret_pinum) } } +void +wdir(struct inode *dp, char *name, uint ino) +{ + uint off; + struct buf *bp = 0; + struct dirent *ep = 0; + int i; + + for(off = 0; off < dp->size; off += BSIZE) { + bp = bread(dp->dev, bmap(dp, off / BSIZE)); + for(ep = (struct dirent *) bp->data; + ep < (struct dirent *) (bp->data + BSIZE); + ep++){ + if(ep->inum == 0) + goto found; + } + brelse(bp); + } + + panic("mknod: XXXX no dir entry free\n"); + + found: + ep->inum = ino; + for(i = 0; i < DIRSIZ && name[i]; i++) + ep->name[i] = name[i]; + for( ; i < DIRSIZ; i++) + ep->name[i] = '\0'; + bwrite (bp, bmap(dp, off/BSIZE)); // write directory block + brelse(bp); +} + struct inode * mknod(char *cp, short type, short major, short minor) { struct inode *ip, *dp; - struct dirent *ep = 0; - int off; - int i; - struct buf *bp = 0; uint pinum = 0; cprintf("mknod: %s %d %d %d\n", cp, type, major, minor); @@ -469,27 +496,7 @@ mknod(char *cp, short type, short major, short minor) iupdate (ip); // write new inode to disk - for(off = 0; off < dp->size; off += BSIZE) { - bp = bread(dp->dev, bmap(dp, off / BSIZE)); - for(ep = (struct dirent *) bp->data; - ep < (struct dirent *) (bp->data + BSIZE); - ep++){ - if(ep->inum == 0) { - goto found; - } - } - brelse(bp); - } - panic("mknod: XXXX no dir entry free\n"); - - found: - ep->inum = ip->inum; - for(i = 0; i < DIRSIZ && cp[i]; i++) - ep->name[i] = cp[i]; - for( ; i < DIRSIZ; i++) - ep->name[i] = '\0'; - bwrite (bp, bmap(dp, off/BSIZE)); // write directory block - brelse(bp); + wdir(dp, cp, ip->inum); iput(dp); @@ -541,3 +548,35 @@ unlink(char *cp) iput(ip); return 0; } + +int +link(char *name1, char *name2) +{ + struct inode *ip, *dp, *xip; + uint pinum = 0; + + cprintf("link(%s, %s)\n", name1, name2); + + if ((xip = namei(name2, &pinum)) != 0) { + cprintf(" failed %s exists\n", name2); + iput(xip); + return -1; + } + + if ((ip = namei(name1, &pinum)) == 0){ + cprintf(" failed %s does not exist\n", name1); + return -1; + } + + ip->nlink += 1; + iupdate (ip); + + dp = iget(rootdev, pinum); + wdir(dp, name2, ip->inum); + iput(dp); + iput(ip); + + cprintf(" succeeded\n"); + + return 0; +} diff --git a/ide.c b/ide.c index 3532121..331553f 100644 --- a/ide.c +++ b/ide.c @@ -52,14 +52,12 @@ ide_init(void) } ioapic_enable (IRQ_IDE, 1); ide_wait_ready(0); - cprintf ("cpu%d: ide_init:done\n", cpu()); } void ide_intr(void) { acquire(&ide_lock); - // cprintf("cpu%d: ide_intr\n", cpu()); wakeup(&request[tail]); release(&ide_lock); } diff --git a/main.c b/main.c index c164c48..a2ee845 100644 --- a/main.c +++ b/main.c @@ -87,8 +87,6 @@ main0(void) lapic_enableintr(); // Enable interrupts on this processor. - cprintf("cpu%d: nlock %d before -- and sti\n", - cpu(), cpus[0].nlock); cpus[cpu()].nlock--; sti(); @@ -98,7 +96,6 @@ main0(void) //load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size); load_icode(p, _binary_init_start, (uint) _binary_init_size); p->state = RUNNABLE; - cprintf("loaded init\n"); scheduler(); } @@ -123,7 +120,6 @@ mpmain(void) cpus[cpu()].booted = 1; // Enable interrupts on this processor. - cprintf("cpu%d: initial nlock %d\n", cpu(), cpus[cpu()].nlock); cpus[cpu()].nlock--; sti(); @@ -139,7 +135,6 @@ load_icode(struct proc *p, uchar *binary, uint size) // Check magic number on binary elf = (struct elfhdr*) binary; - cprintf("elf %x magic %x\n", elf, elf->magic); if (elf->magic != ELF_MAGIC) panic("load_icode: not an ELF binary"); @@ -151,7 +146,6 @@ load_icode(struct proc *p, uchar *binary, uint size) for (i = 0; i < elf->phnum; i++, ph++) { if (ph->type != ELF_PROG_LOAD) continue; - cprintf("va %x memsz %d\n", ph->va, ph->memsz); if (ph->va + ph->memsz < ph->va) panic("load_icode: overflow in elf header segment"); if (ph->va + ph->memsz >= p->sz) diff --git a/proc.c b/proc.c index 5f8769b..7290693 100644 --- a/proc.c +++ b/proc.c @@ -140,9 +140,6 @@ scheduler(void) struct proc *p; int i; - cprintf("cpu%d: start scheduler jmpbuf %p\n", - cpu(), &cpus[cpu()].jmpbuf); - if(cpus[cpu()].nlock != 0){ cprintf("la %x lr %x\n", cpus[cpu()].lastacquire, cpus[cpu()].lastrelease ); panic("holding locks at first entry to scheduler"); diff --git a/syscall.c b/syscall.c index 48da287..4505c89 100644 --- a/syscall.c +++ b/syscall.c @@ -303,7 +303,6 @@ sys_unlink(void) return r; } - int sys_fstat(void) { @@ -325,6 +324,21 @@ sys_fstat(void) return r; } +int +sys_link(void) +{ + struct proc *cp = curproc[cpu()]; + uint name1, name2; + int r; + + if(fetcharg(0, &name1) < 0 || checkstring(name1) < 0) + return -1; + if(fetcharg(1, &name2) < 0 || checkstring(name2) < 0) + return -1; + r = link(cp->mem + name1, cp->mem + name2); + return r; +} + int sys_exec(void) { @@ -543,6 +557,9 @@ syscall(void) case SYS_fstat: ret = sys_fstat(); break; + case SYS_link: + ret = sys_link(); + break; default: cprintf("unknown sys call %d\n", num); // XXX fault diff --git a/syscall.h b/syscall.h index ca2855c..01d09ff 100644 --- a/syscall.h +++ b/syscall.h @@ -12,4 +12,5 @@ #define SYS_mknod 15 #define SYS_unlink 16 #define SYS_fstat 17 +#define SYS_link 18 diff --git a/user.h b/user.h index 9dd1684..52b804b 100644 --- a/user.h +++ b/user.h @@ -16,6 +16,7 @@ int mknod (char*,short,short,short); int unlink (char*); struct stat; int fstat (int fd, struct stat *stat); +int link(char *, char *); int puts(char*); char* strcpy(char*, char*); diff --git a/usertests.c b/usertests.c index 3cb4a37..2d6b065 100644 --- a/usertests.c +++ b/usertests.c @@ -344,11 +344,72 @@ unlinkread() puts("unlinkread ok\n"); } +void +linktest() +{ + int fd; + + unlink("lf1"); + unlink("lf2"); + + fd = open("lf1", O_CREATE|O_RDWR); + if(fd < 0){ + puts("create lf1 failed\n"); + exit(); + } + if(write(fd, "hello", 5) != 5){ + puts("write lf1 failed\n"); + exit(); + } + close(fd); + + if(link("lf1", "lf2") < 0){ + puts("link lf1 lf2 failed\n"); + exit(); + } + unlink("lf1"); + + if(open("lf1", 0) >= 0){ + puts("unlinked lf1 but it is still there!\n"); + exit(); + } + + fd = open("lf2", 0); + if(fd < 0){ + puts("open lf2 failed\n"); + exit(); + } + if(read(fd, buf, sizeof(buf)) != 5){ + puts("read lf2 failed\n"); + exit(); + } + close(fd); + + if(link("lf2", "lf2") >= 0){ + puts("link lf2 lf2 succeeded! oops\n"); + exit(); + } + + unlink("lf2"); + if(link("lf2", "lf1") >= 0){ + puts("link non-existant succeeded! oops\n"); + exit(); + } + + if(link(".", "lf1") >= 0){ + puts("link . lf1 succeeded! oops\n"); + exit(); + } + + puts("linktest ok\n"); +} + int main(int argc, char *argv[]) { puts("usertests starting\n"); + linktest(); unlinkread(); createdelete(); twofiles(); diff --git a/usys.S b/usys.S index f9565e5..73170c3 100644 --- a/usys.S +++ b/usys.S @@ -22,3 +22,4 @@ STUB(open) STUB(mknod) STUB(unlink) STUB(fstat) +STUB(link)