From 7c1810e1ae9268581de6bec30cdb696c25bae030 Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Tue, 23 Aug 2022 12:26:26 -0400 Subject: [PATCH] tolerate running out of inodes --- kernel/fs.c | 6 ++++-- kernel/sysfile.c | 6 ++++-- user/usertests.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 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}, };