Browse Source

fix: fat32 filesystem

greatbridf 9 tháng trước cách đây
mục cha
commit
0d8f6f019b
2 tập tin đã thay đổi với 26 bổ sung45 xóa
  1. 1 1
      include/fs/fat.hpp
  2. 25 44
      src/fs/fat.cpp

+ 1 - 1
include/fs/fat.hpp

@@ -126,10 +126,10 @@ private:
     char label[12];
     std::vector<cluster_t> fat;
 
+    // TODO: dirty flag
     struct buf_object {
         char* data;
         int ref;
-        // bool dirty;
     };
     std::map<cluster_t, buf_object> buf;
 

+ 25 - 44
src/fs/fat.cpp

@@ -9,6 +9,8 @@
 #include <types/allocator.hpp>
 
 #include <fs/fat.hpp>
+#include <kernel/mem/paging.hpp>
+#include <kernel/mem/phys.hpp>
 #include <kernel/module.hpp>
 #include <kernel/vfs.hpp>
 
@@ -67,14 +69,15 @@ char* fat32::read_cluster(cluster_t no)
         ++buf.ref;
         return buf.data;
     }
-    auto* data = new char[sectors_per_cluster * SECTOR_SIZE];
+    // TODO: page buffer class
+    using namespace kernel::mem;
+    using namespace paging;
+    assert(sectors_per_cluster * SECTOR_SIZE <= 0x1000);
+
+    char* data = physaddr<char>{page_to_pfn(alloc_page())};
     _raw_read_cluster(data, no);
-    buf.emplace(no,
-        buf_object {
-            data,
-            1,
-            // false,
-        });
+    buf.emplace(no, buf_object { data, 1 });
+
     return data;
 }
 
@@ -207,51 +210,29 @@ fat32::fat32(dev_t _device)
 
 size_t fat32::read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
 {
-    cluster_t next = cl(file);
     uint32_t cluster_size = SECTOR_SIZE * sectors_per_cluster;
     size_t orig_n = n;
 
-    do {
-        if (offset == 0) {
-            if (n > cluster_size) {
-                auto* data = read_cluster(next);
-                memcpy(buf, data, cluster_size);
-                release_cluster(next);
-
-                buf_size -= cluster_size;
-                buf += cluster_size;
-                n -= cluster_size;
-            } else {
-                auto* data = read_cluster(next);
-                auto read = _write_buf_n(buf, buf_size, data, n);
-                release_cluster(next);
+    for (cluster_t cno = cl(file); n && cno < EOC; cno = fat[cno]) {
+        if (offset >= cluster_size) {
+            offset -= cluster_size;
+            continue;
+        }
 
-                return orig_n - n + read;
-            }
-        } else {
-            if (offset > cluster_size) {
-                offset -= cluster_size;
-            } else {
-                auto* data = read_cluster(next);
+        auto* data = read_cluster(cno);
+        data += offset;
 
-                auto to_read = cluster_size - offset;
-                if (to_read > n)
-                    to_read = n;
+        auto to_copy = std::min(n, cluster_size - offset);
+        auto ncopied = _write_buf_n(buf, buf_size, data, to_copy);
 
-                auto read = _write_buf_n(buf, buf_size, data + offset, to_read);
-                buf += read;
-                n -= read;
+        buf += ncopied, n -= ncopied;
 
-                release_cluster(next);
-                if (read != to_read) {
-                    return orig_n - n;
-                }
+        release_cluster(cno);
+        if (ncopied != to_copy)
+            break;
 
-                offset = 0;
-            }
-        }
-        next = fat[next];
-    } while (n && next < EOC);
+        offset = 0;
+    }
 
     return orig_n - n;
 }