feat: (iso9660) implement file read (for both interleaved and non-interleaved mode)
authorMinep <zelong56@gmail.com>
Fri, 11 Nov 2022 21:45:16 +0000 (21:45 +0000)
committerMinep <zelong56@gmail.com>
Fri, 11 Nov 2022 21:58:54 +0000 (21:58 +0000)
fix: (blkio) race condition between blkio_commit and pwait
fix: regression
chore: clean up

lunaix-os/includes/lunaix/blkio.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/kernel/block/blkio.c
lunaix-os/kernel/block/block.c
lunaix-os/kernel/fs/iso9660/directory.c
lunaix-os/kernel/fs/iso9660/file.c

index 07b53ac4ce1ca6276b31e995659789a6ff6170ed..a189a4de8f70735273be3f15aeec889a1c184b7c 100644 (file)
@@ -12,6 +12,8 @@
 #define BLKIO_BUSY 0x4
 #define BLKIO_PENDING 0x8
 
 #define BLKIO_BUSY 0x4
 #define BLKIO_PENDING 0x8
 
+#define BLKIO_WAIT 0x1
+
 // Free on complete
 #define BLKIO_FOC 0x10
 
 // Free on complete
 #define BLKIO_FOC 0x10
 
@@ -96,7 +98,7 @@ blkio_free_req(struct blkio_req* req);
  * @param req
  */
 void
  * @param req
  */
 void
-blkio_commit(struct blkio_context* ctx, struct blkio_req* req);
+blkio_commit(struct blkio_context* ctx, struct blkio_req* req, int options);
 
 /**
  * @brief Schedule an IO request to be handled.
 
 /**
  * @brief Schedule an IO request to be handled.
index cc850ade16011f1f88708ef4518ef274cbafd7f1..f6a2e6205be6ec74cebfa012a26dd074f7f960cc 100644 (file)
@@ -173,7 +173,8 @@ struct v_fd
     int flags;
 };
 
     int flags;
 };
 
-// FIXME how do we invalidate corresponding v_dnodes given the v_inode?
+//  [v_inode::aka_nodes]
+//  how do we invalidate corresponding v_dnodes given the v_inode?
 /*
     Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
     info of every process being accessible via file system. Each process's
 /*
     Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
     info of every process being accessible via file system. Each process's
index c5d688f633990b7de08ac982bdc93f80af570a58..0427622d9af4dcaf8cbbf0b2f73286feda0834a4 100644 (file)
@@ -2,6 +2,8 @@
 #include <lunaix/mm/cake.h>
 #include <lunaix/mm/valloc.h>
 
 #include <lunaix/mm/cake.h>
 #include <lunaix/mm/valloc.h>
 
+#include <hal/cpu.h>
+
 static struct cake_pile* blkio_reqpile;
 
 void
 static struct cake_pile* blkio_reqpile;
 
 void
@@ -70,7 +72,7 @@ blkio_newctx(req_handler handler)
 }
 
 void
 }
 
 void
-blkio_commit(struct blkio_context* ctx, struct blkio_req* req)
+blkio_commit(struct blkio_context* ctx, struct blkio_req* req, int options)
 {
     req->flags |= BLKIO_PENDING;
     req->io_ctx = ctx;
 {
     req->flags |= BLKIO_PENDING;
     req->io_ctx = ctx;
@@ -78,8 +80,25 @@ blkio_commit(struct blkio_context* ctx, struct blkio_req* req)
 
     // if the pipeline is not running (e.g., stalling). Then we should schedule
     // one immediately and kick it started.
 
     // if the pipeline is not running (e.g., stalling). Then we should schedule
     // one immediately and kick it started.
+    // NOTE: Possible race condition between blkio_commit and pwait.
+    // Consider: what if scheduler complete the request before pwait even get
+    // called?
+    // Two possible work around:
+    //  #1. we disable the interrupt before schedule the request.
+    //  #2. we do scheduling within interrupt context (e.g., attach a timer)
+    // As we don't want to overwhelming the interrupt context and also keep the
+    // request RTT as small as possible, hence #1 is preferred.
+
     if (!ctx->busy) {
     if (!ctx->busy) {
+        if ((options & BLKIO_WAIT)) {
+            cpu_disable_interrupt();
+            blkio_schedule(ctx);
+            pwait(&req->wait);
+            return;
+        }
         blkio_schedule(ctx);
         blkio_schedule(ctx);
+    } else if ((options & BLKIO_WAIT)) {
+        pwait(&req->wait);
     }
 }
 
     }
 }
 
@@ -108,7 +127,6 @@ blkio_complete(struct blkio_req* req)
         req->completed(req);
     }
 
         req->completed(req);
     }
 
-    // FIXME Not working in first process! Need a dummy process.
     // Wake all blocked processes on completion,
     //  albeit should be no more than one process in everycase (by design)
     pwake_all(&req->wait);
     // Wake all blocked processes on completion,
     //  albeit should be no more than one process in everycase (by design)
     pwake_all(&req->wait);
index 494a977d76c927df1dc7a9b7d6938100752b1396..6203fc71a6862891000457bc64ddecce559f7bea 100644 (file)
@@ -74,9 +74,7 @@ __block_read(struct device* dev, void* buf, size_t offset, size_t len)
     }
 
     req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
     }
 
     req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
-    blkio_commit(bdev->blkio, req);
-
-    pwait(&req->wait);
+    blkio_commit(bdev->blkio, req, BLKIO_WAIT);
 
     if (!(errno = req->errcode)) {
         memcpy(buf, head_buf + r, rd_size);
 
     if (!(errno = req->errcode)) {
         memcpy(buf, head_buf + r, rd_size);
@@ -123,13 +121,8 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len)
         vbuf_alloc(&vbuf, buf + wr_size, llen);
     }
 
         vbuf_alloc(&vbuf, buf + wr_size, llen);
     }
 
-    // FIXME race condition between blkio_commit and pwait.
-    //  Consider: what if scheduler complete the request before process enter
-    //  wait state?
     req = blkio_vwr(vbuf, wr_block, NULL, NULL, 0);
     req = blkio_vwr(vbuf, wr_block, NULL, NULL, 0);
-    blkio_commit(bdev->blkio, req);
-
-    pwait(&req->wait);
+    blkio_commit(bdev->blkio, req, BLKIO_WAIT);
 
     int errno = req->errcode;
     if (!errno) {
 
     int errno = req->errcode;
     if (!errno) {
@@ -154,8 +147,7 @@ __block_rd_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count)
     vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
 
     struct blkio_req* req = blkio_vrd(vbuf, start, NULL, NULL, 0);
     vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
 
     struct blkio_req* req = blkio_vrd(vbuf, start, NULL, NULL, 0);
-    blkio_commit(bdev->blkio, req);
-    pwait(&req->wait);
+    blkio_commit(bdev->blkio, req, BLKIO_WAIT);
 
     int errno = req->errcode;
     if (!errno) {
 
     int errno = req->errcode;
     if (!errno) {
@@ -177,8 +169,7 @@ __block_wr_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count)
     vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
 
     struct blkio_req* req = blkio_vwr(vbuf, start, NULL, NULL, 0);
     vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
 
     struct blkio_req* req = blkio_vwr(vbuf, start, NULL, NULL, 0);
-    blkio_commit(bdev->blkio, req);
-    pwait(&req->wait);
+    blkio_commit(bdev->blkio, req, BLKIO_WAIT);
 
     int errno = req->errcode;
     if (!errno) {
 
     int errno = req->errcode;
     if (!errno) {
index d240e1fc60f4bb2a1707d0caa72ad9b76b03e96a..71244a9afe32e0d806f3d10c62e260b939cfdcd1 100644 (file)
@@ -32,7 +32,8 @@ int
 iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode)
 {
     if (!(inode->itype & VFS_IFDIR)) {
 iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode)
 {
     if (!(inode->itype & VFS_IFDIR)) {
-        return;
+        vfs_assign_inode(dnode, inode);
+        return 0;
     }
 
     int errno = 0;
     }
 
     int errno = 0;
@@ -113,9 +114,7 @@ found:
         vfs_i_addhash(inode);
     }
 
         vfs_i_addhash(inode);
     }
 
-    iso9660_setup_dnode(dnode, inode);
-
-    return 0;
+    return iso9660_setup_dnode(dnode, inode);
 }
 
 static int
 }
 
 static int
index 6813c22a484ad50d27183630fb3a820c85b316d1..34d3b47fcf7cfffa091e4791dc53dc9b5a29a9c3 100644 (file)
@@ -1,5 +1,9 @@
 #include <lunaix/fs.h>
 #include <lunaix/fs/iso9660.h>
 #include <lunaix/fs.h>
 #include <lunaix/fs/iso9660.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+#include <klibc/string.h>
 
 int
 iso9660_open(struct v_inode* this, struct v_file* file)
 
 int
 iso9660_open(struct v_inode* this, struct v_file* file)
@@ -18,15 +22,68 @@ iso9660_close(struct v_file* file)
 int
 iso9660_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
 {
 int
 iso9660_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
 {
-    // TODO
-    return 0;
+    // This read implementation handle both interleaved and non-interleaved
+    // structuring
+
+    struct iso_inode* isoino = inode->data;
+    struct device* bdev = inode->sb->dev;
+
+    len = MIN(fpos + len, inode->fsize);
+    if (len <= fpos) {
+        return 0;
+    }
+
+    len -= fpos;
+
+    size_t fu_len = isoino->fu_size * ISO9660_BLKSZ;
+    // if fpos is not FU aligned, then we must do an extra read.
+    size_t fu_to_read =
+      ICEIL(len, fu_len) + (fpos > fu_len && (fpos % fu_len) != 0);
+    size_t sec = (fpos % fu_len) / ISO9660_BLKSZ;
+    size_t wd_start = fpos % ISO9660_BLKSZ,
+           wd_len = MIN(len, ISO9660_BLKSZ - wd_start), i = 0;
+
+    // how many blocks (file unit + gaps) before of our current read position
+    size_t true_offset = (fpos / fu_len);
+    true_offset = true_offset * (isoino->fu_size + isoino->gap_size);
+
+    void* rd_buffer = valloc(ISO9660_BLKSZ);
+
+    true_offset += sec + inode->lb_addr;
+
+    int errno = 0;
+    while (fu_to_read) {
+        for (; sec < isoino->fu_size && i < len; sec++) {
+            errno = bdev->read(
+              bdev, rd_buffer, true_offset * ISO9660_BLKSZ, ISO9660_BLKSZ);
+
+            if (errno < 0) {
+                errno = EIO;
+                goto done;
+            }
+
+            memcpy(buffer + i, rd_buffer + wd_start, wd_len);
+
+            i += wd_len;
+            true_offset++;
+            wd_start = 0;
+            wd_len = MIN(len - i, ISO9660_BLKSZ);
+        }
+        sec = 0;
+        fu_to_read--;
+    }
+    errno = i;
+
+done:
+    vfree(rd_buffer);
+    return errno;
 }
 
 int
 iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
 {
     // TODO
 }
 
 int
 iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
 {
     // TODO
-    return EROFS;
+    return ENOTSUP;
 }
 
 int
 }
 
 int