link()
This commit is contained in:
parent
05e975511b
commit
9e5970d596
4
Notes
4
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!
|
OH! recursive interrupts will use up any amount of cpu[].stack!
|
||||||
underflow and wrecks *previous* cpu's struct
|
underflow and wrecks *previous* cpu's struct
|
||||||
|
|
||||||
better buffer cache replacement
|
|
||||||
read/write of open file that's been unlinked
|
|
||||||
disk scheduling
|
disk scheduling
|
||||||
mkdir
|
mkdir
|
||||||
more than one directory content block
|
more than one directory content block
|
||||||
|
@ -365,3 +363,5 @@ sh redirection
|
||||||
indirect blocks
|
indirect blocks
|
||||||
two bugs in unlink: don't just return if nlink > 0,
|
two bugs in unlink: don't just return if nlink > 0,
|
||||||
and search for name, not inum
|
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?
|
||||||
|
|
1
defs.h
1
defs.h
|
@ -123,3 +123,4 @@ int writei(struct inode *ip, char *addr, uint off, uint n);
|
||||||
struct inode *mknod(char *, short, short, short);
|
struct inode *mknod(char *, short, short, short);
|
||||||
int unlink(char *cp);
|
int unlink(char *cp);
|
||||||
void iupdate (struct inode *ip);
|
void iupdate (struct inode *ip);
|
||||||
|
int link(char *file1, char *file2);
|
||||||
|
|
89
fs.c
89
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 *
|
struct inode *
|
||||||
mknod(char *cp, short type, short major, short minor)
|
mknod(char *cp, short type, short major, short minor)
|
||||||
{
|
{
|
||||||
struct inode *ip, *dp;
|
struct inode *ip, *dp;
|
||||||
struct dirent *ep = 0;
|
|
||||||
int off;
|
|
||||||
int i;
|
|
||||||
struct buf *bp = 0;
|
|
||||||
uint pinum = 0;
|
uint pinum = 0;
|
||||||
|
|
||||||
cprintf("mknod: %s %d %d %d\n", cp, type, major, minor);
|
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
|
iupdate (ip); // write new inode to disk
|
||||||
|
|
||||||
for(off = 0; off < dp->size; off += BSIZE) {
|
wdir(dp, cp, ip->inum);
|
||||||
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);
|
|
||||||
|
|
||||||
iput(dp);
|
iput(dp);
|
||||||
|
|
||||||
|
@ -541,3 +548,35 @@ unlink(char *cp)
|
||||||
iput(ip);
|
iput(ip);
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
2
ide.c
2
ide.c
|
@ -52,14 +52,12 @@ ide_init(void)
|
||||||
}
|
}
|
||||||
ioapic_enable (IRQ_IDE, 1);
|
ioapic_enable (IRQ_IDE, 1);
|
||||||
ide_wait_ready(0);
|
ide_wait_ready(0);
|
||||||
cprintf ("cpu%d: ide_init:done\n", cpu());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ide_intr(void)
|
ide_intr(void)
|
||||||
{
|
{
|
||||||
acquire(&ide_lock);
|
acquire(&ide_lock);
|
||||||
// cprintf("cpu%d: ide_intr\n", cpu());
|
|
||||||
wakeup(&request[tail]);
|
wakeup(&request[tail]);
|
||||||
release(&ide_lock);
|
release(&ide_lock);
|
||||||
}
|
}
|
||||||
|
|
6
main.c
6
main.c
|
@ -87,8 +87,6 @@ main0(void)
|
||||||
lapic_enableintr();
|
lapic_enableintr();
|
||||||
|
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
cprintf("cpu%d: nlock %d before -- and sti\n",
|
|
||||||
cpu(), cpus[0].nlock);
|
|
||||||
cpus[cpu()].nlock--;
|
cpus[cpu()].nlock--;
|
||||||
sti();
|
sti();
|
||||||
|
|
||||||
|
@ -98,7 +96,6 @@ main0(void)
|
||||||
//load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size);
|
//load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size);
|
||||||
load_icode(p, _binary_init_start, (uint) _binary_init_size);
|
load_icode(p, _binary_init_start, (uint) _binary_init_size);
|
||||||
p->state = RUNNABLE;
|
p->state = RUNNABLE;
|
||||||
cprintf("loaded init\n");
|
|
||||||
|
|
||||||
scheduler();
|
scheduler();
|
||||||
}
|
}
|
||||||
|
@ -123,7 +120,6 @@ mpmain(void)
|
||||||
cpus[cpu()].booted = 1;
|
cpus[cpu()].booted = 1;
|
||||||
|
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
cprintf("cpu%d: initial nlock %d\n", cpu(), cpus[cpu()].nlock);
|
|
||||||
cpus[cpu()].nlock--;
|
cpus[cpu()].nlock--;
|
||||||
sti();
|
sti();
|
||||||
|
|
||||||
|
@ -139,7 +135,6 @@ load_icode(struct proc *p, uchar *binary, uint size)
|
||||||
|
|
||||||
// Check magic number on binary
|
// Check magic number on binary
|
||||||
elf = (struct elfhdr*) binary;
|
elf = (struct elfhdr*) binary;
|
||||||
cprintf("elf %x magic %x\n", elf, elf->magic);
|
|
||||||
if (elf->magic != ELF_MAGIC)
|
if (elf->magic != ELF_MAGIC)
|
||||||
panic("load_icode: not an ELF binary");
|
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++) {
|
for (i = 0; i < elf->phnum; i++, ph++) {
|
||||||
if (ph->type != ELF_PROG_LOAD)
|
if (ph->type != ELF_PROG_LOAD)
|
||||||
continue;
|
continue;
|
||||||
cprintf("va %x memsz %d\n", ph->va, ph->memsz);
|
|
||||||
if (ph->va + ph->memsz < ph->va)
|
if (ph->va + ph->memsz < ph->va)
|
||||||
panic("load_icode: overflow in elf header segment");
|
panic("load_icode: overflow in elf header segment");
|
||||||
if (ph->va + ph->memsz >= p->sz)
|
if (ph->va + ph->memsz >= p->sz)
|
||||||
|
|
3
proc.c
3
proc.c
|
@ -140,9 +140,6 @@ scheduler(void)
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cprintf("cpu%d: start scheduler jmpbuf %p\n",
|
|
||||||
cpu(), &cpus[cpu()].jmpbuf);
|
|
||||||
|
|
||||||
if(cpus[cpu()].nlock != 0){
|
if(cpus[cpu()].nlock != 0){
|
||||||
cprintf("la %x lr %x\n", cpus[cpu()].lastacquire, cpus[cpu()].lastrelease );
|
cprintf("la %x lr %x\n", cpus[cpu()].lastacquire, cpus[cpu()].lastrelease );
|
||||||
panic("holding locks at first entry to scheduler");
|
panic("holding locks at first entry to scheduler");
|
||||||
|
|
19
syscall.c
19
syscall.c
|
@ -303,7 +303,6 @@ sys_unlink(void)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sys_fstat(void)
|
sys_fstat(void)
|
||||||
{
|
{
|
||||||
|
@ -325,6 +324,21 @@ sys_fstat(void)
|
||||||
return r;
|
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
|
int
|
||||||
sys_exec(void)
|
sys_exec(void)
|
||||||
{
|
{
|
||||||
|
@ -543,6 +557,9 @@ syscall(void)
|
||||||
case SYS_fstat:
|
case SYS_fstat:
|
||||||
ret = sys_fstat();
|
ret = sys_fstat();
|
||||||
break;
|
break;
|
||||||
|
case SYS_link:
|
||||||
|
ret = sys_link();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cprintf("unknown sys call %d\n", num);
|
cprintf("unknown sys call %d\n", num);
|
||||||
// XXX fault
|
// XXX fault
|
||||||
|
|
|
@ -12,4 +12,5 @@
|
||||||
#define SYS_mknod 15
|
#define SYS_mknod 15
|
||||||
#define SYS_unlink 16
|
#define SYS_unlink 16
|
||||||
#define SYS_fstat 17
|
#define SYS_fstat 17
|
||||||
|
#define SYS_link 18
|
||||||
|
|
||||||
|
|
1
user.h
1
user.h
|
@ -16,6 +16,7 @@ int mknod (char*,short,short,short);
|
||||||
int unlink (char*);
|
int unlink (char*);
|
||||||
struct stat;
|
struct stat;
|
||||||
int fstat (int fd, struct stat *stat);
|
int fstat (int fd, struct stat *stat);
|
||||||
|
int link(char *, char *);
|
||||||
|
|
||||||
int puts(char*);
|
int puts(char*);
|
||||||
char* strcpy(char*, char*);
|
char* strcpy(char*, char*);
|
||||||
|
|
61
usertests.c
61
usertests.c
|
@ -344,11 +344,72 @@ unlinkread()
|
||||||
puts("unlinkread ok\n");
|
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
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
puts("usertests starting\n");
|
puts("usertests starting\n");
|
||||||
|
|
||||||
|
linktest();
|
||||||
unlinkread();
|
unlinkread();
|
||||||
createdelete();
|
createdelete();
|
||||||
twofiles();
|
twofiles();
|
||||||
|
|
Loading…
Reference in a new issue