]> code.delx.au - refind/blobdiff - filesystems/fsw_core.c
Added primitive cache to most drivers to improve performance,
[refind] / filesystems / fsw_core.c
index 64d70d7f50bc1b104cc3b2621f03fb9af97213b6..b00b2276bb060c45218c26a65a24b79513a43b90 100644 (file)
@@ -190,6 +190,21 @@ fsw_status_t fsw_block_get(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, fsw_u32
     if (cache_level > MAX_CACHE_LEVEL)
         cache_level = MAX_CACHE_LEVEL;
 
+    if (vol->bcache_size > 0 && vol->bcache == NULL) {
+        /* driver set the initial cache size */
+        status = fsw_alloc(vol->bcache_size * sizeof(struct fsw_blockcache), &vol->bcache);
+        if(status)
+            return status;
+        for (i = 0; i < vol->bcache_size; i++) {
+            vol->bcache[i].refcount = 0;
+            vol->bcache[i].cache_level = 0;
+            vol->bcache[i].phys_bno = (fsw_u32)FSW_INVALID_BNO;
+            vol->bcache[i].data = NULL;
+        }
+        i = 0;
+        goto miss;
+    }
+
     // check block cache
     for (i = 0; i < vol->bcache_size; i++) {
         if (vol->bcache[i].phys_bno == phys_bno) {
@@ -243,6 +258,7 @@ fsw_status_t fsw_block_get(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, fsw_u32
         vol->bcache_size = new_bcache_size;
     }
     vol->bcache[i].phys_bno = (fsw_u32)FSW_INVALID_BNO;
+miss:
 
     // read the data
     if (vol->bcache[i].data == NULL) {
@@ -322,7 +338,7 @@ static void fsw_dnode_register(struct fsw_volume *vol, struct fsw_dnode *dno)
  * behaves in the same way as fsw_dnode_create.
  */
 
-fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, struct fsw_dnode **dno_out)
+fsw_status_t fsw_dnode_create_root_with_tree(struct fsw_volume *vol, fsw_u64 tree_id, fsw_u64 dnode_id, struct fsw_dnode **dno_out)
 {
     fsw_status_t    status;
     struct fsw_dnode *dno;
@@ -335,6 +351,7 @@ fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, str
     // fill the structure
     dno->vol = vol;
     dno->parent = NULL;
+    dno->tree_id = tree_id;
     dno->dnode_id = dnode_id;
     dno->type = FSW_DNODE_TYPE_DIR;
     dno->refcount = 1;
@@ -347,6 +364,10 @@ fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, str
     return FSW_SUCCESS;
 }
 
+fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u64 dnode_id, struct fsw_dnode **dno_out)
+{
+       return fsw_dnode_create_root_with_tree( vol, 0, dnode_id, dno_out);
+}
 /**
  * Create a new dnode representing a file system object. This function is called by
  * the file system driver in response to directory lookup or read requests. Note that
@@ -365,7 +386,7 @@ fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, str
  * that must be released by the caller with fsw_dnode_release.
  */
 
-fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, int type,
+fsw_status_t fsw_dnode_create_with_tree(struct fsw_dnode *parent_dno, fsw_u64 tree_id, fsw_u64 dnode_id, int type,
                               struct fsw_string *name, struct fsw_dnode **dno_out)
 {
     fsw_status_t    status;
@@ -374,7 +395,7 @@ fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, in
 
     // check if we already have a dnode with the same id
     for (dno = vol->dnode_head; dno; dno = dno->next) {
-        if (dno->dnode_id == dnode_id) {
+        if (dno->dnode_id == dnode_id && dno->tree_id == tree_id) {
             fsw_dnode_retain(dno);
             *dno_out = dno;
             return FSW_SUCCESS;
@@ -390,6 +411,7 @@ fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, in
     dno->vol = vol;
     dno->parent = parent_dno;
     fsw_dnode_retain(dno->parent);
+    dno->tree_id = tree_id;
     dno->dnode_id = dnode_id;
     dno->type = type;
     dno->refcount = 1;
@@ -405,6 +427,12 @@ fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, in
     return FSW_SUCCESS;
 }
 
+fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u64 dnode_id, int type,
+                              struct fsw_string *name, struct fsw_dnode **dno_out)
+{
+       return fsw_dnode_create_with_tree(parent_dno, 0, dnode_id, type, name, dno_out);
+}
+
 /**
  * Increases the reference count of a dnode. This must be balanced with
  * fsw_dnode_release calls. Note that some dnode functions return a retained
@@ -749,10 +777,12 @@ fsw_status_t fsw_dnode_resolve(struct fsw_dnode *dno, struct fsw_dnode **target_
     fsw_status_t    status;
     struct fsw_string target_name;
     struct fsw_dnode *target_dno;
+    /* Linux kernel max link count is 40 */
+    int link_count = 40;
 
     fsw_dnode_retain(dno);
 
-    while (1) {
+    while (--link_count > 0) {
         // get full information
         status = fsw_dnode_fill(dno);
         if (status)
@@ -782,6 +812,8 @@ fsw_status_t fsw_dnode_resolve(struct fsw_dnode *dno, struct fsw_dnode **target_
         fsw_dnode_release(dno);
         dno = target_dno;   // is already retained
     }
+    if(link_count == 0)
+      status = FSW_NOT_FOUND;
 
 errorexit:
     fsw_dnode_release(dno);