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;
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:
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.
*/
#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
}
} 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();
/* 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);
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;