feat: (vfs) write_page and read_page file operations
authorMinep <zelong56@gmail.com>
Fri, 11 Nov 2022 23:45:51 +0000 (23:45 +0000)
committerMinep <zelong56@gmail.com>
Fri, 11 Nov 2022 23:45:51 +0000 (23:45 +0000)
fix: (iso9660) infinite loop when scanning iso9660 volume descriptors
chore: clean up

15 files changed:
lunaix-os/includes/lunaix/common.h
lunaix-os/includes/lunaix/device.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/mm/page.h
lunaix-os/kernel/block/block.c
lunaix-os/kernel/device/devfs.c
lunaix-os/kernel/device/input.c
lunaix-os/kernel/fs/iso9660/directory.c
lunaix-os/kernel/fs/iso9660/inode.c
lunaix-os/kernel/fs/iso9660/mount.c
lunaix-os/kernel/fs/pcache.c
lunaix-os/kernel/fs/ramfs/ramfs.c
lunaix-os/kernel/fs/twifs/twifs.c
lunaix-os/kernel/process/taskfs.c
lunaix-os/kernel/tty/lxconsole.c

index f5a24a7bdab924bd9d286998f7b8217814051823..1ebf15836f509c7bbd0a5fcb8bcb00c636947166 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __LUNAIX_CONSTANTS_H
 #define __LUNAIX_CONSTANTS_H
 
+#define PG_SIZE_BITS 12
+#define PG_SIZE (1 << PG_SIZE_BITS)
+#define PG_INDEX_BITS 10
+
 #define MEM_1MB 0x100000
 #define MEM_4MB 0x400000
 
index c456df41bc6c08b960d66667a091e7ee54e0e859..fd234f0d91a8880bdba11d2c0d582b1bef21b69a 100644 (file)
@@ -30,6 +30,8 @@ struct device
     void* underlay;
     int (*read)(struct device* dev, void* buf, size_t offset, size_t len);
     int (*write)(struct device* dev, void* buf, size_t offset, size_t len);
+    int (*read_page)(struct device* dev, void* buf, size_t offset);
+    int (*write_page)(struct device* dev, void* buf, size_t offset);
     int (*exec_cmd)(struct device* dev, uint32_t req, va_list args);
 };
 
index f6a2e6205be6ec74cebfa012a26dd074f7f960cc..024b4ea591ff952d4f94bacbf94c61b7faecccec 100644 (file)
@@ -120,6 +120,16 @@ struct v_file_ops
 {
     int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
     int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
+
+    // for operatiosn {write|read}_page, following are true:
+    //  + `len` always equals to PG_SIZE
+    //  + `fpos` always PG_SIZE aligned.
+    // These additional operations allow underlying fs to use more specialized
+    // and optimized code.
+
+    int (*write_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
+    int (*read_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
+
     int (*readdir)(struct v_file* file, struct dir_context* dctx);
     int (*seek)(struct v_inode* inode, size_t offset); // optional
     int (*close)(struct v_file* file);
index 9458277eac1db33a61b8bfc6fd31f929bb7d2724..781a4cee34468291985fbf49cb0f1e876822b33f 100644 (file)
@@ -3,10 +3,6 @@
 #include <lunaix/common.h>
 #include <stdint.h>
 
-#define PG_SIZE_BITS 12
-#define PG_SIZE (1 << PG_SIZE_BITS)
-#define PG_INDEX_BITS 10
-
 #define PG_MAX_ENTRIES 1024U
 #define PG_LAST_TABLE PG_MAX_ENTRIES - 1
 #define PG_FIRST_TABLE 0
index 6203fc71a6862891000457bc64ddecce559f7bea..1cade0c78106650c595bcea492a4c399b1132214 100644 (file)
@@ -140,6 +140,72 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len)
     return errno;
 }
 
+int
+__block_read_page(struct device* dev, void* buf, size_t offset)
+{
+    struct vecbuf* vbuf = NULL;
+    struct block_dev* bdev = (struct block_dev*)dev->underlay;
+
+    u32_t lba = offset / bdev->blk_size + bdev->start_lba;
+    u32_t rd_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
+
+    if (rd_lba <= lba) {
+        return 0;
+    }
+
+    rd_lba -= lba;
+
+    vbuf_alloc(&vbuf, buf, rd_lba * bdev->blk_size);
+
+    struct blkio_req* req = blkio_vrd(vbuf, lba, NULL, NULL, 0);
+
+    blkio_commit(bdev->blkio, req, BLKIO_WAIT);
+
+    int errno = req->errcode;
+    if (!errno) {
+        errno = rd_lba * bdev->blk_size;
+    } else {
+        errno = -errno;
+    }
+
+    blkio_free_req(req);
+    vbuf_free(vbuf);
+    return errno;
+}
+
+int
+__block_write_page(struct device* dev, void* buf, size_t offset)
+{
+    struct vecbuf* vbuf = NULL;
+    struct block_dev* bdev = (struct block_dev*)dev->underlay;
+
+    u32_t lba = offset / bdev->blk_size + bdev->start_lba;
+    u32_t rd_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
+
+    if (rd_lba <= lba) {
+        return 0;
+    }
+
+    rd_lba -= lba;
+
+    vbuf_alloc(&vbuf, buf, rd_lba * bdev->blk_size);
+
+    struct blkio_req* req = blkio_vwr(vbuf, lba, NULL, NULL, 0);
+
+    blkio_commit(bdev->blkio, req, BLKIO_WAIT);
+
+    int errno = req->errcode;
+    if (!errno) {
+        errno = rd_lba * bdev->blk_size;
+    } else {
+        errno = -errno;
+    }
+
+    blkio_free_req(req);
+    vbuf_free(vbuf);
+    return errno;
+}
+
 int
 __block_rd_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count)
 {
@@ -250,7 +316,9 @@ __block_register(struct block_dev* bdev)
 
     struct device* dev = device_addvol(NULL, bdev, "sd%c", 'a' + free_slot);
     dev->write = __block_write;
+    dev->write_page = __block_write_page;
     dev->read = __block_read;
+    dev->read_page = __block_read_page;
 
     bdev->dev = dev;
     strcpy(bdev->bdev_id, dev->name_val);
@@ -271,7 +339,9 @@ blk_mount_part(struct block_dev* bdev,
     struct device* dev =
       device_addvol(NULL, pbdev, "%sp%d", bdev->bdev_id, index + 1);
     dev->write = __block_write;
+    dev->write_page = __block_write_page;
     dev->read = __block_read;
+    dev->read_page = __block_read_page;
 
     pbdev->start_lba = start_lba;
     pbdev->end_lba = end_lba;
index 012f9190f7b1b54433eba624adf4fca4987dd07a..c265c4b36aa3b08e4e2b598ad8edd57da28b7b6e 100644 (file)
@@ -35,6 +35,34 @@ devfs_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
     return dev->write(dev, buffer, fpos, len);
 }
 
+int
+devfs_read_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+    assert(inode->data);
+
+    struct device* dev = (struct device*)inode->data;
+
+    if (!dev->read_page) {
+        return ENOTSUP;
+    }
+
+    return dev->read_page(dev, buffer, fpos);
+}
+
+int
+devfs_write_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+    assert(inode->data);
+
+    struct device* dev = (struct device*)inode->data;
+
+    if (!dev->read_page) {
+        return ENOTSUP;
+    }
+
+    return dev->read_page(dev, buffer, fpos);
+}
+
 int
 devfs_get_itype(struct device* dev)
 {
@@ -157,6 +185,8 @@ struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
 
 struct v_file_ops devfs_file_ops = { .close = default_file_close,
                                      .read = devfs_read,
+                                     .read_page = devfs_read_page,
                                      .write = devfs_write,
+                                     .write_page = devfs_write_page,
                                      .seek = default_file_seek,
                                      .readdir = devfs_readdir };
\ No newline at end of file
index 5ddf6a4ce3cc0067b58e2a31aa1630b3e33c9d94..a96cb007f29e0e129c9d15cd0d427706fc5502a2 100644 (file)
@@ -62,6 +62,12 @@ __input_dev_read(struct device* dev, void* buf, size_t offset, size_t len)
     return sizeof(struct input_evt_pkt);
 }
 
+int
+__input_dev_read_pg(struct device* dev, void* buf, size_t offset)
+{
+    return __input_dev_read(dev, buf, offset, PG_SIZE);
+}
+
 struct input_device*
 input_add_device(char* name_fmt, ...)
 {
@@ -78,6 +84,7 @@ input_add_device(char* name_fmt, ...)
 
     idev->dev_if = dev;
     dev->read = __input_dev_read;
+    dev->read_page = __input_dev_read_pg;
 
     va_end(args);
 
index 71244a9afe32e0d806f3d10c62e260b939cfdcd1..816f6eb6b398e083181267ca162cda7e59303047 100644 (file)
@@ -21,8 +21,10 @@ iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec)
     u32_t l = drec->name.len;
     while (l < (u32_t)-1 && drec->name.content[l--] != ';')
         ;
-    l = (l + 1) ? l : drec->name.len;
-    l = MIN(l, ISO9660_IDLEN);
+    l++;
+    l = l ? l : drec->name.len;
+    l = MIN(l, ISO9660_IDLEN - 1);
+
     strncpy(cache->name_val, drec->name.content, l);
     cache->name = HSTR(cache->name_val, l);
     hstr_rehash(&cache->name, HSTR_FULL_HASH);
index 31f85cea173bdc1e4a539040809afc6b47522904..f88eee5e4d0cc684fe060adcdaee6ea4b3ca6a3a 100644 (file)
@@ -11,7 +11,9 @@ static struct v_inode_ops iso_inode_ops = {
 
 static struct v_file_ops iso_file_ops = { .close = iso9660_close,
                                           .read = iso9660_read,
+                                          .read_page = iso9660_read,
                                           .write = iso9660_write,
+                                          .write_page = iso9660_write,
                                           .seek = iso9660_seek,
                                           .readdir = iso9660_readdir };
 
index f6bb2fc66a1935f77bfdcea62d690a4eecc6bcf4..5d7bb819735d4df7e255df774bba58c3960386ea 100644 (file)
@@ -24,9 +24,10 @@ iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
     struct device* dev = vsb->dev;
     struct iso_vol* vdesc = (struct iso_vol*)valloc(ISO9660_BLKSZ);
     struct iso_vol_primary* vprim = NULL;
+    u32_t lba = 16;
     int errno = 0;
     do {
-        errno = dev->read(dev, vdesc, ISO9660_BLKSZ * 16, ISO9660_BLKSZ);
+        errno = dev->read(dev, vdesc, ISO9660_BLKSZ * lba, ISO9660_BLKSZ);
         if (errno < 0) {
             errno = EIO;
             goto done;
@@ -39,7 +40,7 @@ iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
             vprim = (struct iso_vol_primary*)vdesc;
             break;
         }
-
+        lba++;
     } while (vdesc->type != ISO_VOLTERM);
 
     if (!vprim) {
@@ -81,10 +82,11 @@ iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
     }
 
     vfs_i_addhash(rootino);
+    return 0;
 
 done:
     vfree(vdesc);
-    return 0;
+    return errno;
 }
 
 int
index c27f78ba6bf8282139c0f487eb761acb4e456f9d..317e491a336284268a6f827ae82d7aec1841e4ae 100644 (file)
@@ -84,9 +84,10 @@ pcache_get_page(struct pcache* pcache,
 {
     struct pcache_pg* pg = btrie_get(&pcache->tree, index);
     int is_new = 0;
-    *offset = index & ((1 << pcache->tree.truncated) - 1);
+    u32_t mask = ((1 << pcache->tree.truncated) - 1);
+    *offset = index & mask;
     if (!pg && (pg = pcache_new_page(pcache, index))) {
-        pg->fpos = index - *offset;
+        pg->fpos = index & ~mask;
         pcache->n_pages++;
         is_new = 1;
     }
@@ -137,7 +138,8 @@ pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos)
             }
 
             // Filling up the page
-            errno = inode->default_fops->read(inode, pg->pg, PG_SIZE, pg->fpos);
+            errno =
+              inode->default_fops->read_page(inode, pg->pg, PG_SIZE, pg->fpos);
             if (errno >= 0 && errno < PG_SIZE) {
                 // EOF
                 len = MIN(len, buf_off + errno);
@@ -176,7 +178,7 @@ pcache_commit(struct v_inode* inode, struct pcache_pg* page)
     }
 
     int errno =
-      inode->default_fops->write(inode, page->pg, PG_SIZE, page->fpos);
+      inode->default_fops->write_page(inode, page->pg, PG_SIZE, page->fpos);
 
     if (!errno) {
         page->flags &= ~PCACHE_DIRTY;
index f33d330818504725a23292fc412f5e8425b63cfc..bcffa1655f072b5b805974d2d99afd4c060c4e6a 100644 (file)
@@ -135,5 +135,7 @@ const struct v_inode_ops ramfs_inode_ops = { .mkdir = ramfs_mkdir,
 const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir,
                                            .close = default_file_close,
                                            .read = default_file_read,
+                                           .read_page = default_file_read,
                                            .write = default_file_write,
+                                           .write_page = default_file_write,
                                            .seek = default_file_seek };
\ No newline at end of file
index 312c0a45b40b13ab6970c41dac92446f37edb618..fcadafdef4b47d270739f2113f9d0195ef58df72 100644 (file)
@@ -268,7 +268,9 @@ twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...)
 
 const struct v_file_ops twifs_file_ops = { .close = default_file_close,
                                            .read = __twifs_fread,
+                                           .read_page = __twifs_fread,
                                            .write = __twifs_fwrite,
+                                           .write_page = __twifs_fwrite,
                                            .readdir = __twifs_iterate_dir };
 
 const struct v_inode_ops twifs_inode_ops = { .dir_lookup = __twifs_dirlookup,
index 28c371346478a5cb83922e35662ccb3246eee4ef..753470306ea4b852bff5154ad543873d8559ceda 100644 (file)
@@ -133,7 +133,9 @@ taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
 
 static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
                                              .read = default_file_read,
+                                             .read_page = default_file_read,
                                              .write = default_file_write,
+                                             .write_page = default_file_write,
                                              .readdir = taskfs_readdir,
                                              .seek = default_file_seek };
 static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup,
index d555175a0e1d663c98a53a19bd3705ba301077d2..80a7be6de25fd2b3140a54ff95da5eba0295f0d4 100644 (file)
@@ -121,12 +121,26 @@ lxconsole_init()
     lx_console.flush_timer = NULL;
 }
 
+int
+__tty_write_pg(struct device* dev, void* buf, size_t offset)
+{
+    return __tty_write(dev, buf, offset, PG_SIZE);
+}
+
+int
+__tty_read_pg(struct device* dev, void* buf, size_t offset)
+{
+    return __tty_read(dev, buf, offset, PG_SIZE);
+}
+
 void
 lxconsole_spawn_ttydev()
 {
     struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
     tty_dev->write = __tty_write;
+    tty_dev->write_page = __tty_write_pg;
     tty_dev->read = __tty_read;
+    tty_dev->read_page = __tty_read_pg;
     tty_dev->exec_cmd = __tty_exec_cmd;
 
     waitq_init(&lx_reader);