From: Alan Cox Date: Thu, 29 Mar 2018 14:39:42 +0000 (+0100) Subject: inode: file system updates X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=06c3c70e9d94867b81156f6ccb73d0bdd0fa3fba;p=FUZIX.git inode: file system updates Add a superblock index to inodes. It does cost us a byte per inode but it also speeds things up somewhat. Also we will need it for big fs support. Fix inode * errors as inoptr should be used Set the basis for big file system support (nowhere near complete yet) --- diff --git a/Kernel/devio.c b/Kernel/devio.c index 8f4a32ba..3181d0f4 100644 --- a/Kernel/devio.c +++ b/Kernel/devio.c @@ -167,7 +167,7 @@ void *tmpbuf(void) * Allocate an empty _disk cache_ buffer. We use this when dealing with file * holes. It would be nice if this API could go way and readi just use uzero() * - * This won't be able to use tmpbuf if we split disk and temporary buffers. + * This won't be able to use tmpbuf if we split disk and temporary buffers. */ void *zerobuf(void) { diff --git a/Kernel/filesys.c b/Kernel/filesys.c index 19574067..ead41e65 100644 --- a/Kernel/filesys.c +++ b/Kernel/filesys.c @@ -112,7 +112,7 @@ inoptr n_open(char *namep, inoptr *parent) name += 2; continue; } - temp = fs_tab_get(wd->c_dev)->m_fs.s_mntpt; + temp = fs_tab[wd->c_super].m_fs.s_mntpt; ++temp->c_refs; i_deref(wd); wd = temp; @@ -263,6 +263,7 @@ inoptr i_open(uint16_t dev, uint16_t ino) nindex->c_dev = dev; nindex->c_num = ino; + nindex->c_super = m - fs_tab; nindex->c_magic = CMAGIC; nindex->c_flags = (m->m_flags & MS_RDONLY) ? CRDONLY : 0; found: @@ -1040,6 +1041,66 @@ blkno_t bmap(inoptr ip, blkno_t bn, int rwflg) return(nb); } +#ifdef CONFIG_BIG_FS +/* + * On systems with 32bit blkno_t we support larger block sizes but + * keeping the same fundamental layout. That keeps our file system + * changes right down. i_shift comes from the superblock. For bigger + * systems we should instead consider a fast index into superblock tables + * + * We support shifts of: + * + * 0 512 byte blocks 32MB classic Fuzix + * 1 1024 64MB + * 2 2048 128MB + * 3 4096 256MB + * 4 8192 512MB + * 5 16384 1GB just to beat cp/m 8) + * + * All our low level I/O is still done in 512 byte chunks, they are just + * linear extents so we don't blow our buffer budget or need to handle + * alignment and buffer cache size problems. It also means our fsck scales + * even on tiny machines + * + * TODO: + * fsck and mkfs support + * truncate checks + * hole allocation (the one ugly). When we allocate a new block we must + * zero the entire real block (could be 16K). + * hinting to the underlying block layer the fs alignment (so it can + * try to do bigger I/O requests when it wants to be clever on a big + * system). + * Split blkno_t into blkno_t and fs_blkno_t or similar so you can have + * 32bit physical blocks. + * + */ + +static const uint16_t blkmask[] = { + 0x00, /* 512 */ + 0x01, /* 1024 */ + 0x03, /* 2048 */ + 0x07, /* 4096 */ + 0x0F, /* 8192 */ + 0x1F /* 16384 */ +}; + +blkno_t bmap(inoptr ip, blkno_t blk, int rwflg) +{ + /* Linear bits */ + uint8_t shift = fs_tab[ip->c_super].m_fs.s_shift; + uint8_t blklo = ((uint8_t)blk) & blkmask[shift]; + /* Non linear index bits */ + blk >>= shift; + blk = do_bmap(ip, blk, rwflg); + /* Holes are full sized of course */ + if (blk == 0) + return 0; + blk <<= shift;; + blk |= blklo; + return blk; +} +#endif + /* Validblk panics if the given block number is not a valid * data block for the given device. */ @@ -1206,7 +1267,8 @@ bool fmount(uint16_t dev, inoptr ino, uint16_t flags) #endif /* See if there really is a filesystem on the device */ - if(fp->s_mounted != SMOUNTED || fp->s_isize >= fp->s_fsize) { + if(fp->s_mounted != SMOUNTED || fp->s_isize >= fp->s_fsize || + fp->s_shift > FS_MAX_SHIFT) { udata.u_error = EINVAL; return true; // failure } diff --git a/Kernel/inode.c b/Kernel/inode.c index 438cd670..a3cbb3ad 100644 --- a/Kernel/inode.c +++ b/Kernel/inode.c @@ -111,6 +111,9 @@ void readi(regptr inoptr ino, uint8_t flag) } else #endif { + /* FIXME: for big file system support we need + to zero the rest of the logical extent here + and then allocate and write the one we want */ /* we transfer through the buffer pool */ if (pblk == NULLBLK) bp = zerobuf(); @@ -391,7 +394,7 @@ void sync(void) /* ptab is an array so won't exceed 64K so this crude cast works nicely */ -static void i_lock(struct inode *i) +static void i_lock(inoptr i) { if (i->lock == (uint16_t)udata.u_ptab) panic(LOCKLOCK); @@ -400,36 +403,36 @@ static void i_lock(struct inode *i) i->i_lock = (uint16_t)udata.u_ptab; } -static void i_unlock(struct inode *i) +static void i_unlock(inoptr i) { i_islocked(i); i->i_lock = 0; pwakeup_nosig(i); } -static void i_unlock_deref(struct inode *i) +static void i_unlock_deref(inoptr i) { i->i_lock = 0; i_deref(i); } -void i_islocked(struct inode *i) +void i_islocked(inoptr i) { if (i->lock != (uint16_t)udata.u_ptab) panic(IUNLOCK); } -struct inode *n_open_lock(char *uname, struct inode **parent) +inoptr n_open_lock(char *uname, inoptr *parent) { - struct inode *i = n_open(uname, parent); + inoptr i = n_open(uname, parent); if (i) i_lock(i); return i; } -struct inode *getinode_lock(uint8_t uindex) +inoptr getinode_lock(uint8_t uindex) { - struct inode *i = getinode(uindex); + inoptr i = getinode(uindex); if (i) i_lock(i); return i;