lab fs done
This commit is contained in:
parent
408565dc36
commit
4a1d663b39
5
Makefile
5
Makefile
@ -61,7 +61,7 @@ endif
|
|||||||
|
|
||||||
# riscv64-unknown-elf- or riscv64-linux-gnu-
|
# riscv64-unknown-elf- or riscv64-linux-gnu-
|
||||||
# perhaps in /opt/riscv/bin
|
# perhaps in /opt/riscv/bin
|
||||||
#TOOLPREFIX =
|
TOOLPREFIX = /opt/riscv/bin/riscv64-unknown-elf-
|
||||||
|
|
||||||
# Try to infer the correct TOOLPREFIX if not set
|
# Try to infer the correct TOOLPREFIX if not set
|
||||||
ifndef TOOLPREFIX
|
ifndef TOOLPREFIX
|
||||||
@ -257,7 +257,8 @@ endif
|
|||||||
|
|
||||||
ifeq ($(LAB),fs)
|
ifeq ($(LAB),fs)
|
||||||
UPROGS += \
|
UPROGS += \
|
||||||
$U/_bigfile
|
$U/_bigfile\
|
||||||
|
$U/_symlinktest
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -238,7 +238,7 @@ def make(*target):
|
|||||||
post_make()
|
post_make()
|
||||||
|
|
||||||
def show_command(cmd):
|
def show_command(cmd):
|
||||||
from pipes import quote
|
from shlex import quote
|
||||||
print("\n$", " ".join(map(quote, cmd)))
|
print("\n$", " ".join(map(quote, cmd)))
|
||||||
|
|
||||||
def maybe_unlink(*paths):
|
def maybe_unlink(*paths):
|
||||||
|
|||||||
@ -187,3 +187,5 @@ void virtio_disk_intr(void);
|
|||||||
|
|
||||||
// number of elements in fixed-size array
|
// number of elements in fixed-size array
|
||||||
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
|
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
#define DEBUG() printf("File: %s, Line: %d, Function: %s\n", __FILE__, __LINE__, __func__)
|
||||||
|
|||||||
@ -3,3 +3,4 @@
|
|||||||
#define O_RDWR 0x002
|
#define O_RDWR 0x002
|
||||||
#define O_CREATE 0x200
|
#define O_CREATE 0x200
|
||||||
#define O_TRUNC 0x400
|
#define O_TRUNC 0x400
|
||||||
|
#define O_NOFOLLOW 0x004
|
||||||
@ -26,7 +26,7 @@ struct inode {
|
|||||||
short minor;
|
short minor;
|
||||||
short nlink;
|
short nlink;
|
||||||
uint size;
|
uint size;
|
||||||
uint addrs[NDIRECT+1];
|
uint addrs[NDIRECT+2];
|
||||||
};
|
};
|
||||||
|
|
||||||
// map major device number to device functions.
|
// map major device number to device functions.
|
||||||
|
|||||||
95
kernel/fs.c
95
kernel/fs.c
@ -398,23 +398,59 @@ bmap(struct inode *ip, uint bn)
|
|||||||
|
|
||||||
if(bn < NINDIRECT){
|
if(bn < NINDIRECT){
|
||||||
// Load indirect block, allocating if necessary.
|
// Load indirect block, allocating if necessary.
|
||||||
if((addr = ip->addrs[NDIRECT]) == 0){
|
if(bn<NINDIRECT1){
|
||||||
addr = balloc(ip->dev);
|
if((addr = ip->addrs[NDIRECT]) == 0){
|
||||||
if(addr == 0)
|
addr = balloc(ip->dev);
|
||||||
return 0;
|
if(addr == 0)
|
||||||
ip->addrs[NDIRECT] = addr;
|
return 0;
|
||||||
}
|
ip->addrs[NDIRECT] = addr;
|
||||||
bp = bread(ip->dev, addr);
|
|
||||||
a = (uint*)bp->data;
|
|
||||||
if((addr = a[bn]) == 0){
|
|
||||||
addr = balloc(ip->dev);
|
|
||||||
if(addr){
|
|
||||||
a[bn] = addr;
|
|
||||||
log_write(bp);
|
|
||||||
}
|
}
|
||||||
|
bp = bread(ip->dev, addr);
|
||||||
|
a = (uint*)bp->data;
|
||||||
|
if((addr = a[bn]) == 0){
|
||||||
|
addr = balloc(ip->dev);
|
||||||
|
if(addr){
|
||||||
|
a[bn] = addr;
|
||||||
|
log_write(bp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
brelse(bp);
|
||||||
|
return addr;
|
||||||
|
}else{
|
||||||
|
bn-=NINDIRECT1;
|
||||||
|
if((addr = ip->addrs[NDIRECT+1])==0){
|
||||||
|
addr = balloc(ip->dev);
|
||||||
|
if(addr == 0)
|
||||||
|
return 0;
|
||||||
|
ip->addrs[NDIRECT+1] = addr;
|
||||||
|
}
|
||||||
|
bp=bread(ip->dev,addr);
|
||||||
|
a = (uint *)bp->data;
|
||||||
|
const uint offset=bn%NINDIRECT1;
|
||||||
|
bn/=NINDIRECT1;
|
||||||
|
if((addr = a[bn])==0){
|
||||||
|
addr=balloc(ip->dev);
|
||||||
|
if(addr){
|
||||||
|
a[bn] = addr;
|
||||||
|
log_write(bp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
struct buf *bp=bread(ip->dev,addr);
|
||||||
|
a = (uint *)bp->data;
|
||||||
|
if((addr = a[offset])==0){
|
||||||
|
addr=balloc(ip->dev);
|
||||||
|
if(addr){
|
||||||
|
a[offset]=addr;
|
||||||
|
log_write(bp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
brelse(bp);
|
||||||
|
}
|
||||||
|
brelse(bp);
|
||||||
|
return addr;
|
||||||
}
|
}
|
||||||
brelse(bp);
|
|
||||||
return addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("bmap: out of range");
|
panic("bmap: out of range");
|
||||||
@ -439,7 +475,7 @@ itrunc(struct inode *ip)
|
|||||||
if(ip->addrs[NDIRECT]){
|
if(ip->addrs[NDIRECT]){
|
||||||
bp = bread(ip->dev, ip->addrs[NDIRECT]);
|
bp = bread(ip->dev, ip->addrs[NDIRECT]);
|
||||||
a = (uint*)bp->data;
|
a = (uint*)bp->data;
|
||||||
for(j = 0; j < NINDIRECT; j++){
|
for(j = 0; j < NINDIRECT1; j++){
|
||||||
if(a[j])
|
if(a[j])
|
||||||
bfree(ip->dev, a[j]);
|
bfree(ip->dev, a[j]);
|
||||||
}
|
}
|
||||||
@ -447,7 +483,25 @@ itrunc(struct inode *ip)
|
|||||||
bfree(ip->dev, ip->addrs[NDIRECT]);
|
bfree(ip->dev, ip->addrs[NDIRECT]);
|
||||||
ip->addrs[NDIRECT] = 0;
|
ip->addrs[NDIRECT] = 0;
|
||||||
}
|
}
|
||||||
|
if(ip->addrs[NDIRECT+1]){
|
||||||
|
bp = bread(ip->dev,ip->addrs[NDIRECT+1]);
|
||||||
|
a = (uint*)bp->data;
|
||||||
|
for(j = 0;j<NINDIRECT1;++j){
|
||||||
|
if(a[j]){
|
||||||
|
struct buf *bp=bread(ip->dev,a[j]);
|
||||||
|
for(int j=0;j<NINDIRECT1;++j){
|
||||||
|
uint *a=(uint*)bp->data;
|
||||||
|
if(a[j])
|
||||||
|
bfree(ip->dev,a[j]);
|
||||||
|
}
|
||||||
|
brelse(bp);
|
||||||
|
bfree(ip->dev,a[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
brelse(bp);
|
||||||
|
bfree(ip->dev,ip->addrs[NDIRECT+1]);
|
||||||
|
ip->addrs[NDIRECT+1] = 0;
|
||||||
|
}
|
||||||
ip->size = 0;
|
ip->size = 0;
|
||||||
iupdate(ip);
|
iupdate(ip);
|
||||||
}
|
}
|
||||||
@ -508,11 +562,12 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n)
|
|||||||
uint tot, m;
|
uint tot, m;
|
||||||
struct buf *bp;
|
struct buf *bp;
|
||||||
|
|
||||||
if(off > ip->size || off + n < off)
|
if(off > ip->size || off + n < off){
|
||||||
return -1;
|
return -1;
|
||||||
if(off + n > MAXFILE*BSIZE)
|
}
|
||||||
|
if(off + n > MAXFILE*BSIZE){
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
for(tot=0; tot<n; tot+=m, off+=m, src+=m){
|
for(tot=0; tot<n; tot+=m, off+=m, src+=m){
|
||||||
uint addr = bmap(ip, off/BSIZE);
|
uint addr = bmap(ip, off/BSIZE);
|
||||||
if(addr == 0)
|
if(addr == 0)
|
||||||
|
|||||||
@ -24,8 +24,9 @@ struct superblock {
|
|||||||
|
|
||||||
#define FSMAGIC 0x10203040
|
#define FSMAGIC 0x10203040
|
||||||
|
|
||||||
#define NDIRECT 12
|
#define NDIRECT 11
|
||||||
#define NINDIRECT (BSIZE / sizeof(uint))
|
#define NINDIRECT1 (BSIZE / sizeof(uint))
|
||||||
|
#define NINDIRECT (NINDIRECT1 + NINDIRECT1 * NINDIRECT1)
|
||||||
#define MAXFILE (NDIRECT + NINDIRECT)
|
#define MAXFILE (NDIRECT + NINDIRECT)
|
||||||
|
|
||||||
// On-disk inode structure
|
// On-disk inode structure
|
||||||
@ -35,7 +36,7 @@ struct dinode {
|
|||||||
short minor; // Minor device number (T_DEVICE only)
|
short minor; // Minor device number (T_DEVICE only)
|
||||||
short nlink; // Number of links to inode in file system
|
short nlink; // Number of links to inode in file system
|
||||||
uint size; // Size of file (bytes)
|
uint size; // Size of file (bytes)
|
||||||
uint addrs[NDIRECT+1]; // Data block addresses
|
uint addrs[NDIRECT+2]; // Data block addresses
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inodes per block.
|
// Inodes per block.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#define T_DIR 1 // Directory
|
#define T_DIR 1 // Directory
|
||||||
#define T_FILE 2 // File
|
#define T_FILE 2 // File
|
||||||
#define T_DEVICE 3 // Device
|
#define T_DEVICE 3 // Device
|
||||||
|
#define T_SYMLINK 4
|
||||||
struct stat {
|
struct stat {
|
||||||
int dev; // File system's disk device
|
int dev; // File system's disk device
|
||||||
uint ino; // Inode number
|
uint ino; // Inode number
|
||||||
|
|||||||
@ -101,7 +101,7 @@ extern uint64 sys_unlink(void);
|
|||||||
extern uint64 sys_link(void);
|
extern uint64 sys_link(void);
|
||||||
extern uint64 sys_mkdir(void);
|
extern uint64 sys_mkdir(void);
|
||||||
extern uint64 sys_close(void);
|
extern uint64 sys_close(void);
|
||||||
|
extern uint64 sys_symlink(void);
|
||||||
// An array mapping syscall numbers from syscall.h
|
// An array mapping syscall numbers from syscall.h
|
||||||
// to the function that handles the system call.
|
// to the function that handles the system call.
|
||||||
static uint64 (*syscalls[])(void) = {
|
static uint64 (*syscalls[])(void) = {
|
||||||
@ -126,6 +126,7 @@ static uint64 (*syscalls[])(void) = {
|
|||||||
[SYS_link] sys_link,
|
[SYS_link] sys_link,
|
||||||
[SYS_mkdir] sys_mkdir,
|
[SYS_mkdir] sys_mkdir,
|
||||||
[SYS_close] sys_close,
|
[SYS_close] sys_close,
|
||||||
|
[SYS_symlink] sys_symlink
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -20,3 +20,4 @@
|
|||||||
#define SYS_link 19
|
#define SYS_link 19
|
||||||
#define SYS_mkdir 20
|
#define SYS_mkdir 20
|
||||||
#define SYS_close 21
|
#define SYS_close 21
|
||||||
|
#define SYS_symlink 22
|
||||||
@ -327,6 +327,27 @@ sys_open(void)
|
|||||||
end_op();
|
end_op();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
int dep=0;
|
||||||
|
if((omode & O_NOFOLLOW)==0){
|
||||||
|
while(1){
|
||||||
|
ilock(ip);
|
||||||
|
if(ip->type!=T_SYMLINK){
|
||||||
|
iunlock(ip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
readi(ip,0,(uint64)path,0,MAXPATH);
|
||||||
|
iunlockput(ip);
|
||||||
|
if((ip = namei(path)) == 0){
|
||||||
|
end_op();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
++dep;
|
||||||
|
if(dep>=10){
|
||||||
|
end_op();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ilock(ip);
|
ilock(ip);
|
||||||
if(ip->type == T_DIR && omode != O_RDONLY){
|
if(ip->type == T_DIR && omode != O_RDONLY){
|
||||||
iunlockput(ip);
|
iunlockput(ip);
|
||||||
@ -348,7 +369,7 @@ sys_open(void)
|
|||||||
end_op();
|
end_op();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ip->type == T_DEVICE){
|
if(ip->type == T_DEVICE){
|
||||||
f->type = FD_DEVICE;
|
f->type = FD_DEVICE;
|
||||||
f->major = ip->major;
|
f->major = ip->major;
|
||||||
@ -474,6 +495,31 @@ sys_exec(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64 sys_symlink(){
|
||||||
|
char target[MAXPATH],path[MAXPATH];
|
||||||
|
if(argstr(0, target, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0)
|
||||||
|
goto ERR1;
|
||||||
|
begin_op();
|
||||||
|
struct inode *ip;
|
||||||
|
if((ip = namei(path)) == 0){
|
||||||
|
if((ip = create(path, T_SYMLINK,0,0))==0)
|
||||||
|
goto ERR2;
|
||||||
|
}else
|
||||||
|
ilock(ip);
|
||||||
|
if(writei(ip,0,(uint64)target,0,MAXPATH)<0){
|
||||||
|
goto ERR3;
|
||||||
|
}
|
||||||
|
iunlockput(ip);
|
||||||
|
end_op();
|
||||||
|
return 0;
|
||||||
|
ERR3:
|
||||||
|
iunlockput(ip);
|
||||||
|
ERR2:
|
||||||
|
end_op();
|
||||||
|
ERR1:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
sys_pipe(void)
|
sys_pipe(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -135,10 +135,10 @@ testsymlink(void)
|
|||||||
if(c!=c2)
|
if(c!=c2)
|
||||||
fail("Value read from 4 differed from value written to 1\n");
|
fail("Value read from 4 differed from value written to 1\n");
|
||||||
|
|
||||||
|
|
||||||
close(fd1);
|
close(fd1);
|
||||||
close(fd2);
|
close(fd2);
|
||||||
fd1 = fd2 = -1;
|
fd1 = fd2 = -1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// check that many symlinks can co-exist.
|
// check that many symlinks can co-exist.
|
||||||
//
|
//
|
||||||
|
|||||||
@ -22,7 +22,7 @@ int getpid(void);
|
|||||||
char* sbrk(int);
|
char* sbrk(int);
|
||||||
int sleep(int);
|
int sleep(int);
|
||||||
int uptime(void);
|
int uptime(void);
|
||||||
|
int symlink(const char *,const char *);
|
||||||
// ulib.c
|
// ulib.c
|
||||||
int stat(const char*, struct stat*);
|
int stat(const char*, struct stat*);
|
||||||
char* strcpy(char*, const char*);
|
char* strcpy(char*, const char*);
|
||||||
|
|||||||
@ -36,3 +36,4 @@ entry("getpid");
|
|||||||
entry("sbrk");
|
entry("sbrk");
|
||||||
entry("sleep");
|
entry("sleep");
|
||||||
entry("uptime");
|
entry("uptime");
|
||||||
|
entry("symlink");
|
||||||
Loading…
Reference in New Issue
Block a user