shithub: lwext4

Download patch

ref: a997419af0b0974abce6cd984e3256776dde8c3f
parent: 700ad54c131fe037e5ca995b53cf698249e6b438
author: gkostka <kostka.grzegorz@gmail.com>
date: Fri May 30 12:35:37 EDT 2014

Merge bugfixes from HelenOS mainline.

--- a/lwext4/ext4_balloc.c
+++ b/lwext4/ext4_balloc.c
@@ -117,8 +117,10 @@
     struct ext4_block bitmap_block;
 
     rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
-    if (rc != EOK)
+    if (rc != EOK){
+        ext4_fs_put_block_group_ref(&bg_ref);
         return rc;
+    }
 
     /* Modify bitmap */
     ext4_bmap_bit_clr(bitmap_block.data, index_in_group);
@@ -157,11 +159,7 @@
     bg_ref.dirty = true;
 
     /* Release block group reference */
-    rc = ext4_fs_put_block_group_ref(&bg_ref);
-    if (rc != EOK)
-        return rc;
-
-    return EOK;
+    return ext4_fs_put_block_group_ref(&bg_ref);
 }
 
 int ext4_balloc_free_blocks(struct ext4_inode_ref *inode_ref, uint32_t first,
@@ -194,8 +192,10 @@
     struct ext4_block bitmap_block;
 
     rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
-    if (rc != EOK)
+    if (rc != EOK){
+        ext4_fs_put_block_group_ref(&bg_ref);
         return rc;
+    }
 
     /* Modify bitmap */
     ext4_bmap_bits_free(bitmap_block.data, index_in_group_first, count);
@@ -232,23 +232,19 @@
     bg_ref.dirty = true;
 
     /* Release block group reference */
-    rc = ext4_fs_put_block_group_ref(&bg_ref);
-    if (rc != EOK)
-        return rc;
-
-    return EOK;
+    return ext4_fs_put_block_group_ref(&bg_ref);
 }
 
 
 /**@brief Compute 'goal' for allocation algorithm.
  * @param inode_ref Reference to inode, to allocate block for
- * @return Goal block number
+ * @param goal
+ * @return error code
  */
-static uint32_t ext4_balloc_find_goal(struct ext4_inode_ref *inode_ref)
+static int ext4_balloc_find_goal(struct ext4_inode_ref *inode_ref, uint32_t *goal)
 {
-    uint32_t goal = 0;
-
     struct ext4_sblock *sb = &inode_ref->fs->sb;
+    *goal = 0;
 
     uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
     uint32_t block_size = ext4_sb_get_block_size(sb);
@@ -260,13 +256,13 @@
     /* If inode has some blocks, get last block address + 1 */
     if (inode_block_count > 0) {
         int rc = ext4_fs_get_inode_data_block_index(inode_ref,
-                inode_block_count - 1, &goal);
+                inode_block_count - 1, goal);
         if (rc != EOK)
-            return 0;
+            return rc;
 
-        if (goal != 0) {
-            goal++;
-            return goal;
+        if (*goal != 0) {
+            (*goal)++;
+            return rc;
         }
 
         /* If goal == 0, sparse file -> continue */
@@ -283,7 +279,7 @@
     int rc = ext4_fs_get_block_group_ref(inode_ref->fs,
             block_group, &bg_ref);
     if (rc != EOK)
-        return 0;
+        return rc;
 
     /* Compute indexes */
     uint32_t block_group_count = ext4_block_group_cnt(sb);
@@ -309,11 +305,9 @@
     if (inode_table_bytes % block_size)
         inode_table_blocks++;
 
-    goal = inode_table_first_block + inode_table_blocks;
+    *goal = inode_table_first_block + inode_table_blocks;
 
-    ext4_fs_put_block_group_ref(&bg_ref);
-
-    return goal;
+    return  ext4_fs_put_block_group_ref(&bg_ref);
 }
 
 
@@ -323,14 +317,14 @@
     uint32_t allocated_block = 0;
     uint32_t bitmap_block_addr;
     uint32_t rel_block_idx = 0;
-
+    uint32_t free_blocks;
+    uint32_t goal;
     struct ext4_block bitmap_block;
 
-    /* Find GOAL */
-    uint32_t goal = ext4_balloc_find_goal(inode_ref);
-    if (goal == 0) {
+    int rc = ext4_balloc_find_goal(inode_ref, &goal);
+    if (rc != EOK) {
         /* no goal found => partition is full */
-        return ENOSPC;
+        return rc;
     }
 
     struct ext4_sblock *sb = &inode_ref->fs->sb;
@@ -342,11 +336,18 @@
 
     /* Load block group reference */
     struct ext4_block_group_ref bg_ref;
-    int rc = ext4_fs_get_block_group_ref(inode_ref->fs,
+    rc = ext4_fs_get_block_group_ref(inode_ref->fs,
             block_group, &bg_ref);
     if (rc != EOK)
         return rc;
 
+    free_blocks =
+            ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+    if (free_blocks == 0) {
+        /* This group has no free blocks */
+        goto goal_failed;
+    }
+
     /* Compute indexes */
     uint32_t first_in_group =
             ext4_balloc_get_first_data_block_in_group(sb, &bg_ref);
@@ -432,9 +433,19 @@
     }
 
     /* No free block found yet */
-    ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
-    ext4_fs_put_block_group_ref(&bg_ref);
+    rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+    if(rc != EOK){
+        ext4_fs_put_block_group_ref(&bg_ref);
+        return rc;
+    }
 
+goal_failed:
+
+    rc = ext4_fs_put_block_group_ref(&bg_ref);
+    if(rc != EOK)
+        return rc;
+
+
     /* Try other block groups */
     uint32_t block_group_count = ext4_block_group_cnt(sb);
 
@@ -447,6 +458,13 @@
         if (rc != EOK)
             return rc;
 
+        free_blocks =
+                ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+        if (free_blocks == 0) {
+            /* This group has no free blocks */
+            goto next_group;
+        }
+
         /* Load block with bitmap */
         bitmap_block_addr =
                 ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
@@ -482,8 +500,10 @@
 
             bitmap_block.dirty = true;
             rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
-            if (rc != EOK)
+            if (rc != EOK){
+                ext4_fs_put_block_group_ref(&bg_ref);
                 return rc;
+            }
 
             allocated_block =
                     ext4_fs_index_in_group2_baddr(sb, rel_block_idx,
@@ -492,9 +512,18 @@
             goto success;
         }
 
-        ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
-        ext4_fs_put_block_group_ref(&bg_ref);
+        rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+        if(rc != EOK){
+            ext4_fs_put_block_group_ref(&bg_ref);
+            return rc;
+        }
 
+next_group:
+        rc = ext4_fs_put_block_group_ref(&bg_ref);
+        if(rc != EOK){
+            return rc;
+        }
+
         /* Goto next group */
         bgid = (bgid + 1) % block_group_count;
         count--;
@@ -529,16 +558,16 @@
 
     bg_ref.dirty = true;
 
-    ext4_fs_put_block_group_ref(&bg_ref);
+    rc = ext4_fs_put_block_group_ref(&bg_ref);
 
     *fblock = allocated_block;
-    return EOK;
+    return rc;
 }
 
 int ext4_balloc_try_alloc_block(struct ext4_inode_ref *inode_ref,
     uint32_t baddr, bool *free)
 {
-    int rc = EOK;
+    int rc;
 
     struct ext4_fs *fs = inode_ref->fs;
     struct ext4_sblock *sb = &fs->sb;
@@ -562,8 +591,10 @@
     struct ext4_block bitmap_block;
 
     rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
-    if (rc != EOK)
+    if (rc != EOK){
+        ext4_fs_put_block_group_ref(&bg_ref);
         return rc;
+    }
 
     /* Check if block is free */
     *free = ext4_bmap_is_bit_clr(bitmap_block.data, index_in_group);
--- a/lwext4/ext4_dir_idx.c
+++ b/lwext4/ext4_dir_idx.c
@@ -428,7 +428,7 @@
 
         int rc = ext4_fs_get_inode_data_block_index(inode_ref,
                 block_idx, &block_addr);
-        if (rc != EOK)
+        if(rc != EOK)
             return rc;
 
 
@@ -440,10 +440,11 @@
         p++;
 
         /* Don't forget to put old block (prevent memory leak) */
-        ext4_block_set(inode_ref->fs->bdev, &p->block);
+        rc = ext4_block_set(inode_ref->fs->bdev, &p->block);
+        if(rc != EOK)
+            return rc;
 
 
-
         memcpy(&p->block, &p->block, sizeof(block));
         p->entries = ((struct ext4_directory_dx_node *) block.data)->entries;
         p->position = p->entries;
@@ -459,6 +460,7 @@
 {
     /* Load direct block 0 (index root) */
     uint32_t root_block_addr;
+    int rc2;
     int rc = ext4_fs_get_inode_data_block_index(inode_ref, 0,
             &root_block_addr);
     if (rc != EOK)
@@ -524,7 +526,9 @@
         }
 
         /* Not found, leave untouched */
-        ext4_block_set(fs->bdev, &leaf_block);
+        rc2 = ext4_block_set(fs->bdev, &leaf_block);
+        if(rc2 != EOK)
+            goto cleanup;
 
         if (rc != ENOENT)
             goto cleanup;
@@ -539,12 +543,14 @@
     /* Entry not found */
     rc = ENOENT;
 
-    cleanup:
+cleanup:
     /* The whole path must be released (preventing memory leak) */
     tmp = dx_blocks;
 
     while (tmp <= dx_block) {
-        ext4_block_set(fs->bdev, &tmp->block);
+        rc2 = ext4_block_set(fs->bdev, &tmp->block);
+        if (rc == EOK && rc2 != EOK)
+            rc = rc2;
         ++tmp;
     }
 
--- a/lwext4/ext4_extent.c
+++ b/lwext4/ext4_extent.c
@@ -255,6 +255,7 @@
 int ext4_extent_find_block(struct ext4_inode_ref *inode_ref, uint32_t iblock,
     uint32_t *fblock)
 {
+    int rc;
     /* Compute bound defined by i-node size */
     uint64_t inode_size =
         ext4_inode_get_size(&inode_ref->fs->sb, inode_ref->inode);
@@ -285,8 +286,11 @@
         /* Load child node and set values for the next iteration */
         uint64_t child = ext4_extent_index_get_leaf(index);
 
-        if (block.lb_id)
-            ext4_block_set(inode_ref->fs->bdev, &block);
+        if (block.lb_id){
+            rc = ext4_block_set(inode_ref->fs->bdev, &block);
+            if(rc != EOK)
+                return rc;
+        }
 
 
         int rc = ext4_block_get(inode_ref->fs->bdev, &block, child);
@@ -313,8 +317,11 @@
     }
 
     /* Cleanup */
-    if (block.lb_id)
-        ext4_block_set(inode_ref->fs->bdev, &block);
+    if (block.lb_id){
+        rc = ext4_block_set(inode_ref->fs->bdev, &block);
+        if(rc != EOK)
+            return rc;
+    }
 
     return EOK;
 }
@@ -389,8 +396,11 @@
      * From 1: 0 is a block with inode data
      */
     for (i = 1; i < tmp_path->depth; ++i) {
-        if (tmp_path[i].block.lb_id)
-            ext4_block_set(inode_ref->fs->bdev, &tmp_path[i].block);
+        if (tmp_path[i].block.lb_id){
+            int r = ext4_block_set(inode_ref->fs->bdev, &tmp_path[i].block);
+            if(r != EOK)
+                rc = r;
+        }
     }
 
     /* Destroy temporary data structure */
@@ -462,9 +472,7 @@
     if (rc != EOK)
         return rc;
 
-    ext4_balloc_free_block(inode_ref, fblock);
-
-    return EOK;
+    return ext4_balloc_free_block(inode_ref, fblock);
 }
 
 
@@ -593,8 +601,11 @@
      * starting from 1: 0 is a block with inode data
      */
     for (i = 1; i <= path->depth; ++i) {
-        if (path[i].block.lb_id)
-            ext4_block_set(inode_ref->fs->bdev, &path[i].block);
+        if (path[i].block.lb_id){
+            int r = ext4_block_set(inode_ref->fs->bdev, &path[i].block);
+            if(r != EOK)
+                rc = r;
+        }
     }
 
     /* Destroy temporary data structure */
@@ -640,7 +651,11 @@
             }
 
             /* Put back not modified old block */
-            ext4_block_set(inode_ref->fs->bdev, &path_ptr->block);
+            rc = ext4_block_set(inode_ref->fs->bdev, &path_ptr->block);
+            if (rc != EOK) {
+                ext4_balloc_free_block(inode_ref, fblock);
+                return rc;
+            }
 
             /* Initialize newly allocated block and remember it */
             memset(block.data, 0, block_size);
@@ -923,8 +938,11 @@
      * starting from 1: 0 is a block with inode data
      */
     for (i = 1; i <= path->depth; ++i) {
-        if (path[i].block.lb_id)
-            ext4_block_set(inode_ref->fs->bdev, &path[i].block);
+        if (path[i].block.lb_id){
+            int r = ext4_block_set(inode_ref->fs->bdev, &path[i].block);
+            if(r != EOK)
+                rc = r;
+        }
     }
 
     /* Destroy temporary data structure */
--- a/lwext4/ext4_ialloc.c
+++ b/lwext4/ext4_ialloc.c
@@ -192,8 +192,10 @@
 
             struct ext4_block bitmap_block;
             rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
-            if (rc != EOK)
+            if (rc != EOK){
+                ext4_fs_put_block_group_ref(&bg_ref);
                 return rc;
+            }
 
             /* Try to allocate i-node in the bitmap */
             uint32_t inodes_in_group = ext4_inodes_in_group_cnt(sb, bgid);
@@ -203,8 +205,16 @@
                     &index_in_group);
             /* Block group has not any free i-node */
             if (rc == ENOSPC) {
-                ext4_block_set(fs->bdev, &bitmap_block);
-                ext4_fs_put_block_group_ref(&bg_ref);
+                rc = ext4_block_set(fs->bdev, &bitmap_block);
+                if(rc != EOK){
+                    ext4_fs_put_block_group_ref(&bg_ref);
+                    return rc;
+                }
+
+                rc = ext4_fs_put_block_group_ref(&bg_ref);
+                if (rc != EOK)
+                    return rc;
+
                 continue;
             }
 
@@ -214,8 +224,10 @@
             bitmap_block.dirty = true;
 
             ext4_block_set(fs->bdev, &bitmap_block);
-            if (rc != EOK)
+            if (rc != EOK){
+                ext4_fs_put_block_group_ref(&bg_ref);
                 return rc;
+            }
 
             /* Modify filesystem counters */
             free_inodes--;
@@ -267,6 +279,9 @@
 
         /* Block group not modified, put it and jump to the next block group */
         ext4_fs_put_block_group_ref(&bg_ref);
+        if (rc != EOK)
+            return rc;
+
         ++bgid;
     }