summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
tolerate running out of inodes
-rw-r--r--kernel/fs.c6
-rw-r--r--kernel/sysfile.c6
-rw-r--r--user/usertests.c45
3 files changed, 48 insertions, 9 deletions
diff --git a/kernel/fs.c b/kernel/fs.c
index b220491..dea5864 100644
--- a/kernel/fs.c
+++ b/kernel/fs.c
@@ -193,7 +193,8 @@ static struct inode* iget(uint dev, uint inum);
// Allocate an inode on device dev.
// Mark it as allocated by giving it type type.
-// Returns an unlocked but allocated and referenced inode.
+// Returns an unlocked but allocated and referenced inode,
+// or NULL if there is no free inode..
struct inode*
ialloc(uint dev, short type)
{
@@ -213,7 +214,8 @@ ialloc(uint dev, short type)
}
brelse(bp);
}
- panic("ialloc: no inodes");
+ printf("ialloc: no inodes\n");
+ return 0;
}
// Copy a modified in-memory inode to disk.
diff --git a/kernel/sysfile.c b/kernel/sysfile.c
index d8a6fca..16b668c 100644
--- a/kernel/sysfile.c
+++ b/kernel/sysfile.c
@@ -262,8 +262,10 @@ create(char *path, short type, short major, short minor)
return 0;
}
- if((ip = ialloc(dp->dev, type)) == 0)
- panic("create: ialloc");
+ if((ip = ialloc(dp->dev, type)) == 0){
+ iunlockput(dp);
+ return 0;
+ }
ilock(ip);
ip->major = major;
diff --git a/user/usertests.c b/user/usertests.c
index 23a5048..4f183a5 100644
--- a/user/usertests.c
+++ b/user/usertests.c
@@ -2750,6 +2750,7 @@ diskfull(char *s)
unlink(name);
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
if(fd < 0){
+ // oops, ran out of inodes before running out of blocks.
printf("%s: could not create file %s\n", s, name);
done = 1;
break;
@@ -2767,7 +2768,8 @@ diskfull(char *s)
// now that there are no free blocks, test that dirlink()
// merely fails (doesn't panic) if it can't extend
- // directory content.
+ // directory content. one of these file creations
+ // is expected to fail.
int nzz = 128;
for(int i = 0; i < nzz; i++){
char name[32];
@@ -2778,14 +2780,15 @@ diskfull(char *s)
name[4] = '\0';
unlink(name);
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
- if(fd < 0){
- printf("%s: could not create file %s\n", s, name);
+ if(fd < 0)
break;
- }
close(fd);
}
- mkdir("diskfulldir");
+ // this mkdir() is expected to fail.
+ if(mkdir("diskfulldir") == 0)
+ printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n");
+
unlink("diskfulldir");
for(int i = 0; i < nzz; i++){
@@ -2809,6 +2812,37 @@ diskfull(char *s)
}
}
+void
+outofinodes(char *s)
+{
+ int nzz = 32*32;
+ for(int i = 0; i < nzz; i++){
+ char name[32];
+ name[0] = 'z';
+ name[1] = 'z';
+ name[2] = '0' + (i / 32);
+ name[3] = '0' + (i % 32);
+ name[4] = '\0';
+ unlink(name);
+ int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
+ if(fd < 0){
+ // failure is eventually expected.
+ break;
+ }
+ close(fd);
+ }
+
+ for(int i = 0; i < nzz; i++){
+ char name[32];
+ name[0] = 'z';
+ name[1] = 'z';
+ name[2] = '0' + (i / 32);
+ name[3] = '0' + (i % 32);
+ name[4] = '\0';
+ unlink(name);
+ }
+}
+
//
// use sbrk() to count how many free physical memory pages there are.
// touches the pages to force allocation.
@@ -2986,6 +3020,7 @@ main(int argc, char *argv[])
{badarg, "badarg" },
{execout, "execout"},
{diskfull, "diskfull"},
+ {outofinodes, "outofinodes"},
{ 0, 0},
};