shithub: lwext4

Download patch

ref: a09a05013d92a98e5e8cf104bed7c8cc4288beb7
parent: 9befc593b01aee9c468ec7a4cb0de2e3b0c7594a
author: gkostka <[email protected]>
date: Sun Oct 11 12:06:49 EDT 2015

Introduce bdev_write_sb to mkfs module

--- a/lwext4/ext4_mkfs.c
+++ b/lwext4/ext4_mkfs.c
@@ -48,7 +48,6 @@
 
 struct fs_aux_info {
 	struct ext4_sblock *sb;
-	struct ext4_sblock *sb_block;
 	struct ext4_bgroup *bg_desc;
 	struct xattr_list_element *xattrs;
 	uint32_t first_data_block;
@@ -92,15 +91,6 @@
 	return EOK;
 }
 
-static int info2sb(struct ext4_mkfs_info *info, struct ext4_sblock *sb)
-{
-	(void)info;
-	memset(sb, 0, sizeof(struct ext4_sblock));
-	/*TODO: Fill superblock with proper values*/
-
-	return EOK;
-}
-
 static uint32_t compute_blocks_per_group(struct ext4_mkfs_info *info)
 {
 	return info->block_size * 8;
@@ -161,7 +151,7 @@
 	return ext4_sb_sparse(bgid);
 }
 
-static void create_fs_aux_info(struct fs_aux_info *aux_info, struct ext4_mkfs_info *info)
+static int create_fs_aux_info(struct fs_aux_info *aux_info, struct ext4_mkfs_info *info)
 {
 	aux_info->first_data_block = (info->block_size > 1024) ? 0 : 1;
 	aux_info->len_blocks = info->len / info->block_size;
@@ -190,27 +180,28 @@
 		aux_info->len_blocks -= last_group_size;
 	}
 
-	/* The write_data* functions expect only block aligned calls.
-	 * This is not an issue, except when we write out the super
-	 * block on a system with a block size > 1K.  So, we need to
-	 * deal with that here.
-	 */
-	aux_info->sb_block = calloc(1, info->block_size);
-	ext4_assert(aux_info->sb_block);
+	aux_info->sb = calloc(1, sizeof(struct ext4_sblock));
+	if (!aux_info->sb)
+		return ENOMEM;
 
+	aux_info->bg_desc = calloc(sizeof(struct ext4_bgroup),
+			aux_info->bg_desc_blocks);
+	if (!aux_info->bg_desc)
+		return ENOMEM;
 
-	if (info->block_size > 1024)
-		aux_info->sb = (struct ext4_sblock *)((char *)aux_info->sb_block + 1024);
-	else
-		aux_info->sb = aux_info->sb_block;
-
-	aux_info->bg_desc = calloc(info->block_size, aux_info->bg_desc_blocks);
-	ext4_assert(aux_info->bg_desc);
-
 	aux_info->xattrs = NULL;
+	return EOK;
 }
 
+static void release_fs_aux_info(struct fs_aux_info *aux_info)
+{
+	if (aux_info->sb)
+		free(aux_info->sb);
+	if (aux_info->sb)
+		free(aux_info->bg_desc);
+}
 
+
 /* Fill in the superblock memory buffer based on the filesystem parameters */
 static void fill_in_sb(struct fs_aux_info *aux_info, struct ext4_mkfs_info *info)
 {
@@ -298,18 +289,10 @@
 			info->blocks_per_group;
 		uint32_t header_size = 0;
 
-		if (has_superblock(info, i)) {
-			if (i != 0) {
-
-				/* Update the block group nr of this backup superblock */
-				sb->block_group_index  = i;
-				/*TODO: write superblock i*/
-
-			}
-
+		if (has_superblock(info, i))
 			header_size = 1 + aux_info->bg_desc_blocks + info->bg_desc_reserve_blocks;
-		}
 
+
 		aux_info->bg_desc[i].block_bitmap_lo = group_start_block + header_size;
 		aux_info->bg_desc[i].inode_bitmap_lo = group_start_block + header_size + 1;
 		aux_info->bg_desc[i].inode_table_first_block_lo = group_start_block + header_size + 2;
@@ -318,17 +301,31 @@
 		aux_info->bg_desc[i].free_inodes_count_lo = sb->inodes_per_group;
 		aux_info->bg_desc[i].used_dirs_count_lo = 0;
 	}
+}
 
-	/* Queue the primary superblock to be written out - if it's a block device,
-	 * queue a zero-filled block first, the correct version of superblock will
-	 * be written to the block device after all other blocks are written.
-	 *
-	 * The file-system on the block device will not be valid until the correct
-	 * version of superblocks are written, this is to avoid the likelihood of a
-	 * partially created file-system.
-	 */
-	sb->block_group_index  = 0;
-	/*TODO: write superblock 0*/
+static int bdev_write_sb(struct ext4_blockdev *bd, struct fs_aux_info *aux_info,
+			  struct ext4_mkfs_info *info)
+{
+	uint64_t offset;
+	uint32_t i;
+	int r;
+
+	/* write out the backup superblocks */
+	for (i = 1; i < aux_info->groups; i++) {
+		if (has_superblock(info, i)) {
+			offset = info->block_size * (aux_info->first_data_block
+				+ i * info->blocks_per_group);
+
+			aux_info->sb->block_group_index = i;
+			r = ext4_block_writebytes(bd, offset, aux_info->sb, 1024);
+			if (r != EOK)
+				return r;
+		}
+	}
+
+	/* write out the primary superblock */
+	aux_info->sb->block_group_index = 0;
+	return ext4_block_writebytes(bd, 1024, aux_info->sb, 1024);
 }
 
 
@@ -361,15 +358,10 @@
 int ext4_mkfs(struct ext4_blockdev *bd, struct ext4_mkfs_info *info)
 {
 	int r;
-	struct ext4_sblock *sb = NULL;
 	r = ext4_block_init(bd);
 	if (r != EOK)
 		return r;
 
-	sb = malloc(sizeof(struct ext4_sblock));
-	if (!sb)
-		goto Finish;
-
 	if (info->len == 0)
 		info->len = bd->ph_bcnt * bd->ph_bsize;
 
@@ -405,10 +397,6 @@
 
 	info->bg_desc_reserve_blocks = compute_bg_desc_reserve_blocks(info);
 
-	r = info2sb(info, sb);
-	if (r != EOK)
-		return r;
-
 	ext4_dbg(DEBUG_MKFS, DBG_INFO "Creating filesystem with parameters:\n");
 	ext4_dbg(DEBUG_MKFS, DBG_NONE "Size: %"PRIu64"\n", info->len);
 	ext4_dbg(DEBUG_MKFS, DBG_NONE "Block size: %d\n", info->block_size);
@@ -433,13 +421,21 @@
 	ext4_dbg(DEBUG_MKFS, DBG_NONE "Label: %s\n", info->label);
 
 	struct fs_aux_info aux_info;
-	create_fs_aux_info(&aux_info, info);
+	memset(&aux_info, 0, sizeof(struct fs_aux_info));
 
-	/*TODO: write filesystem metadata*/
+	r = create_fs_aux_info(&aux_info, info);
+	if (r != EOK)
+		goto Finish;
 
+	fill_in_sb(&aux_info, info);
+
+
+	r = bdev_write_sb(bd, &aux_info, info);
+	if (r != EOK)
+		goto Finish;
+
 	Finish:
-	if (sb)
-		free(sb);
+	release_fs_aux_info(&aux_info);
 	ext4_block_fini(bd);
 	return r;
 }