inode: file system updates
authorAlan Cox <alan@linux.intel.com>
Thu, 29 Mar 2018 14:39:42 +0000 (15:39 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 29 Mar 2018 14:39:42 +0000 (15:39 +0100)
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)

Kernel/devio.c
Kernel/filesys.c
Kernel/inode.c

index 8f4a32b..3181d0f 100644 (file)
@@ -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)
 {
index 1957406..ead41e6 100644 (file)
@@ -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
     }
index 438cd67..a3cbb3a 100644 (file)
@@ -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;