Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 0/9] btrfs-progs: some fixes for bugs spotted by valgrind
tmp branch recently got very nice feature: ''mkfs.btrfs -r /some/directory''. It''s very useful, when you need to creare minimal root: /bin/sh and fs_mark. But there is another hidden feature! As ''-r'' can create whole filesystem we can effectively valgrind a lot of code paths in btrfs and pick bugs. This patch series is mostly (with one exception) dumb obvous holes plugs (sometimes they are backports from kernel). Patchset based on git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git#tmp commit e6bd18d8938986c997c45f0ea95b221d4edec095 Author: Christoph Hellwig <hch@lst.de> Date: Thu Apr 21 16:24:07 2011 -0400 First off the exception: In order to make --mixed produce proper filesystems with meta+data only blocks (and not meta+data/data ones, which confused space_cache and led to an oops for me) I ask to consider for pulling Arne''s patch:> Subject: [PATCH v2 1/9] btrfs progs: fix extra metadata chunk allocation in --mixed caseThe rest of patches should be obvoius. They don''t fix all the fair valgrind compaints, but reduce them severely. Changes since v1: - "[PATCH 8/9] mkfs.btrfs: fix memory leak caused by ''scandir()'' calls": ''free_namelist()'' now works correctly if ''count == -1''. It happens when ''free_namelist()'' is called right after ''scandir()'' returning an error. Some stats: convert.c | 2 +- extent-tree.c | 7 ++++--- extent_io.c | 1 + file-item.c | 1 + mkfs.c | 39 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 43 insertions(+), 7 deletions(-) Arne Jansen (1): btrfs progs: fix extra metadata chunk allocation in --mixed case Sergei Trofimovich (8): btrfs-convert: fix typo: ''all inode'' -> ''all inodes'' mkfs.btrfs: fail on scandir error (-r mode) mkfs.btrfs: return some defined value instead of garbage when lookup checksum mkfs.btrfs: fix symlink names writing mkfs.btrfs: write zeroes instead on uninitialized data. mkfs.btrfs: free buffers allocated by pretty_sizes mkfs.btrfs: fix memory leak caused by ''scandir()'' calls mkfs.btrfs: fix error text in ''-r'' mode -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 1/9] btrfs progs: fix extra metadata chunk allocation in --mixed case
From: Arne Jansen <sensille@gmx.net> When creating a mixed fs with mkfs, an extra metadata chunk got allocated. This is because btrfs_reserve_extent calls do_chunk_alloc for METADATA, which in turn wasn''t able to find the proper space_info, as __find_space_info did a hard compare of the flags. It is now sufficient for the space_info to include the proper flag. This reflects the change done to the kernel code to support mixed chunks. Also for a subsequent chunk allocation (which should not be hit in the mkfs case), the chunk is now created with the flags from the space_info instead of the requested flags. A better solution would be to pull the full changeset for the mixed case from the kernel into the user mode (or, even better, share the code) The additional chunk probably confused block_rsv calculation, which in turn led to severeal ENOSPC Oopses. Signed-off-by: Arne Jansen <sensille@gmx.net> --- extent-tree.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/extent-tree.c b/extent-tree.c index b2f9bb2..c6c77c6 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -1718,41 +1718,41 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, clear_extent_bits(block_group_cache, start, end, BLOCK_GROUP_DIRTY, GFP_NOFS); cache = (struct btrfs_block_group_cache *)(unsigned long)ptr; ret = write_one_cache_group(trans, root, path, cache); BUG_ON(ret); } btrfs_free_path(path); return 0; } static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, u64 flags) { struct list_head *head = &info->space_info; struct list_head *cur; struct btrfs_space_info *found; list_for_each(cur, head) { found = list_entry(cur, struct btrfs_space_info, list); - if (found->flags == flags) + if (found->flags & flags) return found; } return NULL; } static int update_space_info(struct btrfs_fs_info *info, u64 flags, u64 total_bytes, u64 bytes_used, struct btrfs_space_info **space_info) { struct btrfs_space_info *found; found = __find_space_info(info, flags); if (found) { found->total_bytes += total_bytes; found->bytes_used += bytes_used; WARN_ON(found->total_bytes < found->bytes_used); *space_info = found; return 0; } @@ -1795,49 +1795,50 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 start; u64 num_bytes; int ret; space_info = __find_space_info(extent_root->fs_info, flags); if (!space_info) { ret = update_space_info(extent_root->fs_info, flags, 0, 0, &space_info); BUG_ON(ret); } BUG_ON(!space_info); if (space_info->full) return 0; thresh = div_factor(space_info->total_bytes, 7); if ((space_info->bytes_used + space_info->bytes_pinned + alloc_bytes) < thresh) return 0; - ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); + ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, + space_info->flags); if (ret == -ENOSPC) { space_info->full = 1; return 0; } BUG_ON(ret); - ret = btrfs_make_block_group(trans, extent_root, 0, flags, + ret = btrfs_make_block_group(trans, extent_root, 0, space_info->flags, BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); BUG_ON(ret); return 0; } static int update_block_group(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u64 num_bytes, int alloc, int mark_free) { struct btrfs_block_group_cache *cache; struct btrfs_fs_info *info = root->fs_info; u64 total = num_bytes; u64 old_val; u64 byte_in_group; u64 start; u64 end; /* block accounting for super block */ old_val = btrfs_super_bytes_used(&info->super_copy); -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 2/9] btrfs-convert: fix typo: ''all inode'' -> ''all inodes''
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- convert.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/convert.c b/convert.c index fbcf4a3..291dc27 100644 --- a/convert.c +++ b/convert.c @@ -1103,41 +1103,41 @@ static int copy_disk_extent(struct btrfs_root *root, u64 dst_bytenr, char *buffer; struct btrfs_fs_devices *fs_devs = root->fs_info->fs_devices; buffer = malloc(num_bytes); if (!buffer) return -ENOMEM; ret = pread(fs_devs->latest_bdev, buffer, num_bytes, src_bytenr); if (ret != num_bytes) goto fail; ret = pwrite(fs_devs->latest_bdev, buffer, num_bytes, dst_bytenr); if (ret != num_bytes) goto fail; ret = 0; fail: free(buffer); if (ret > 0) ret = -1; return ret; } /* - * scan ext2''s inode bitmap and copy all used inode. + * scan ext2''s inode bitmap and copy all used inodes. */ static int copy_inodes(struct btrfs_root *root, ext2_filsys ext2_fs, int datacsum, int packing, int noxattr) { int ret; errcode_t err; ext2_inode_scan ext2_scan; struct ext2_inode ext2_inode; ext2_ino_t ext2_ino; u64 objectid; struct btrfs_trans_handle *trans; trans = btrfs_start_transaction(root, 1); if (!trans) return -ENOMEM; err = ext2fs_open_inode_scan(ext2_fs, 0, &ext2_scan); if (err) { fprintf(stderr, "ext2fs_open_inode_scan: %s\n", error_message(err)); return -1; } -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 3/9] mkfs.btrfs: fail on scandir error (-r mode)
mkfs.btrfs does not handle relative pathnames for now. When they are passed to it it creates empty image. So first time I thought it does not work at all. This patch adds error handling for scandir(). With patch it behaves this way: $ mkfs.btrfs -r ./root ... fs created label (null) on output.img nodesize 4096 leafsize 4096 sectorsize 4096 size 256.00MB Btrfs v0.19-52-g438c5ff-dirty scandir for ./root failed: No such file or directory unable to traverse_directory Making image is aborted. mkfs.btrfs: mkfs.c:1402: main: Assertion `!(ret)'' failed. Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- mkfs.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/mkfs.c b/mkfs.c index 57c88f9..9d7b792 100644 --- a/mkfs.c +++ b/mkfs.c @@ -878,40 +878,46 @@ static int traverse_directory(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(leaf); btrfs_release_path(root, &path); do { parent_dir_entry = list_entry(dir_head->list.next, struct directory_name_entry, list); list_del(&parent_dir_entry->list); parent_inum = parent_dir_entry->inum; parent_dir_name = parent_dir_entry->dir_name; if (chdir(parent_dir_entry->path)) { fprintf(stderr, "chdir error for %s\n", parent_dir_name); goto fail; } count = scandir(parent_dir_entry->path, &files, directory_select, NULL); + if (count == -1) + { + fprintf(stderr, "scandir for %s failed: %s\n", + parent_dir_name, strerror (errno)); + goto fail; + } for (i = 0; i < count; i++) { cur_file = files[i]; if (lstat(cur_file->d_name, &st) == -1) { fprintf(stderr, "lstat failed for file %s\n", cur_file->d_name); goto fail; } cur_inum = ++highest_inum + BTRFS_FIRST_FREE_OBJECTID; ret = add_directory_items(trans, root, cur_inum, parent_inum, cur_file->d_name, &st, &dir_index_cnt); if (ret) { fprintf(stderr, "add_directory_items failed\n"); goto fail; } -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 4/9] mkfs.btrfs: return some defined value instead of garbage when lookup checksum
==31873== Command: ./mkfs.btrfs -r /some/root/ ==31873== Parent PID: 31872 ==31873===31873== Conditional jump or move depends on uninitialised value(s) ==31873== at 0x42C3D0: add_file_items (mkfs.c:792) ==31873== by 0x42CAB3: traverse_directory (mkfs.c:948) ==31873== by 0x42CF11: make_image (mkfs.c:1047) ==31873== by 0x42DE53: main (mkfs.c:1401) ==31873== Uninitialised value was created by a stack allocation ==31873== at 0x41B1B1: btrfs_csum_file_block (file-item.c:195) ''ret'' value was not initialized for ''found'' branch. The same fix sits in kernel:> commit 639cb58675ce9b507eed9c3d6b3335488079b21a > Author: Chris Mason <chris.mason@oracle.com> > Date: Thu Aug 28 06:15:25 2008 -0400 > > Btrfs: Fix variable init during csum creation > > Signed-off-by: Chris Mason <chris.mason@oracle.com>Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- file-item.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/file-item.c b/file-item.c index 9732282..47f6ad2 100644 --- a/file-item.c +++ b/file-item.c @@ -201,40 +201,41 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, struct btrfs_path *path; struct btrfs_csum_item *item; struct extent_buffer *leaf = NULL; u64 csum_offset; u32 csum_result = ~(u32)0; u32 nritems; u32 ins_size; u16 csum_size btrfs_super_csum_size(&root->fs_info->super_copy); path = btrfs_alloc_path(); BUG_ON(!path); file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; file_key.offset = bytenr; file_key.type = BTRFS_EXTENT_CSUM_KEY; item = btrfs_lookup_csum(trans, root, path, bytenr, 1); if (!IS_ERR(item)) { leaf = path->nodes[0]; + ret = 0; goto found; } ret = PTR_ERR(item); if (ret == -EFBIG) { u32 item_size; /* we found one, but it isn''t big enough yet */ leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, path->slots[0]); if ((item_size / csum_size) >= MAX_CSUM_ITEMS(root, csum_size)) { /* already at max size, make a new one */ goto insert; } } else { int slot = path->slots[0] + 1; /* we didn''t find a csum item, insert one */ nritems = btrfs_header_nritems(path->nodes[0]); if (path->slots[0] >= nritems - 1) { ret = btrfs_next_leaf(root, path); if (ret == 1) found_next = 1; -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 5/9] mkfs.btrfs: fix symlink names writing
Found by valgrind: ==8968== Use of uninitialised value of size 8 ==8968== at 0x41CE7D: crc32c_le (crc32c.c:98) ==8968== by 0x40A1D0: csum_tree_block_size (disk-io.c:82) ==8968== by 0x40A2D4: csum_tree_block (disk-io.c:105) ==8968== by 0x40A7D6: write_tree_block (disk-io.c:241) ==8968== by 0x40ACEE: __commit_transaction (disk-io.c:354) ==8968== by 0x40AE9E: btrfs_commit_transaction (disk-io.c:385) ==8968== by 0x42CF66: make_image (mkfs.c:1061) ==8968== by 0x42DE63: main (mkfs.c:1410) ==8968== Uninitialised value was created by a stack allocation ==8968== at 0x42B5FB: add_inode_items (mkfs.c:493) readlink(2) does not write ''\0'' for us, so make it manually. Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- mkfs.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/mkfs.c b/mkfs.c index 9d7b792..8ff2b1e 100644 --- a/mkfs.c +++ b/mkfs.c @@ -692,45 +692,47 @@ static int record_file_extent(struct btrfs_trans_handle *trans, root->root_key.objectid, objectid, 0); fail: btrfs_release_path(root, &path); return ret; } static int add_symbolic_link(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, const char *path_name) { int ret; u64 sectorsize = root->sectorsize; char *buf = malloc(sectorsize); ret = readlink(path_name, buf, sectorsize); if (ret <= 0) { fprintf(stderr, "readlink failed for %s\n", path_name); goto fail; } - if (ret > sectorsize) { + if (ret >= sectorsize) { fprintf(stderr, "symlink too long for %s", path_name); ret = -1; goto fail; } + + buf[ret] = ''\0''; /* readlink does not do it for us */ ret = btrfs_insert_inline_extent(trans, root, objectid, 0, buf, ret + 1); fail: free(buf); return ret; } static int add_file_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_inode_item *btrfs_inode, u64 objectid, ino_t parent_inum, struct stat *st, const char *path_name, int out_fd) { int ret; ssize_t ret_read; u64 bytes_read = 0; char *buffer = NULL; struct btrfs_key key; int blocks; u32 sectorsize = root->sectorsize; -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 6/9] mkfs.btrfs: write zeroes instead on uninitialized data.
Found by valgrind: ==8968== Use of uninitialised value of size 8 ==8968== at 0x41CE7D: crc32c_le (crc32c.c:98) ==8968== by 0x40A1D0: csum_tree_block_size (disk-io.c:82) ==8968== by 0x40A2D4: csum_tree_block (disk-io.c:105) ==8968== by 0x40A7D6: write_tree_block (disk-io.c:241) ==8968== by 0x40ACEE: __commit_transaction (disk-io.c:354) ==8968== by 0x40AE9E: btrfs_commit_transaction (disk-io.c:385) ==8968== by 0x42CF66: make_image (mkfs.c:1061) ==8968== by 0x42DE63: main (mkfs.c:1410) ==8968== Uninitialised value was created by a stack allocation ==8968== at 0x42B5FB: add_inode_items (mkfs.c:493) 1. On-disk inode format has reserved (and thus, random at alloc time) fields: btrfs_inode_item: __le64 reserved[4] 2. Sometimes extents are created on disk without writing data there. (Or at least not all data is written there). Kernel code always had it kzalloc''ed. Zero them all. Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- extent_io.c | 1 + mkfs.c | 7 +++++++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/extent_io.c b/extent_io.c index 069c199..a93d4d6 100644 --- a/extent_io.c +++ b/extent_io.c @@ -555,40 +555,41 @@ static int free_some_buffers(struct extent_io_tree *tree) } else { list_move_tail(&eb->lru, &tree->lru); } if (nrscan++ > 64) break; } return 0; } static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, u64 bytenr, u32 blocksize) { struct extent_buffer *eb; int ret; eb = malloc(sizeof(struct extent_buffer) + blocksize); if (!eb) { BUG(); return NULL; } + memset (eb, 0, sizeof(struct extent_buffer) + blocksize); eb->start = bytenr; eb->len = blocksize; eb->refs = 2; eb->flags = 0; eb->tree = tree; eb->fd = -1; eb->dev_bytenr = (u64)-1; eb->cache_node.start = bytenr; eb->cache_node.size = blocksize; free_some_buffers(tree); ret = insert_existing_cache_extent(&tree->cache, &eb->cache_node); if (ret) { free(eb); return NULL; } list_add_tail(&eb->lru, &tree->lru); tree->cache_size += blocksize; return eb; diff --git a/mkfs.c b/mkfs.c index 8ff2b1e..32f25f5 100644 --- a/mkfs.c +++ b/mkfs.c @@ -394,40 +394,47 @@ static int add_directory_items(struct btrfs_trans_handle *trans, if (S_ISLNK(st->st_mode)) filetype = BTRFS_FT_SYMLINK; ret = btrfs_insert_dir_item(trans, root, name, name_len, parent_inum, &location, filetype, index_cnt); *dir_index_cnt = index_cnt; index_cnt++; return ret; } static int fill_inode_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_inode_item *dst, struct stat *src) { u64 blocks = 0; u64 sectorsize = root->sectorsize; + /* + * btrfs_inode_item has some reserved fields + * and represents on-disk inode entry, so + * zero everything to prevent information leak + */ + memset (dst, 0, sizeof (*dst)); + btrfs_set_stack_inode_generation(dst, trans->transid); btrfs_set_stack_inode_size(dst, src->st_size); btrfs_set_stack_inode_nbytes(dst, 0); btrfs_set_stack_inode_block_group(dst, 0); btrfs_set_stack_inode_nlink(dst, src->st_nlink); btrfs_set_stack_inode_uid(dst, src->st_uid); btrfs_set_stack_inode_gid(dst, src->st_gid); btrfs_set_stack_inode_mode(dst, src->st_mode); btrfs_set_stack_inode_rdev(dst, 0); btrfs_set_stack_inode_flags(dst, 0); btrfs_set_stack_timespec_sec(&dst->atime, src->st_atime); btrfs_set_stack_timespec_nsec(&dst->atime, 0); btrfs_set_stack_timespec_sec(&dst->ctime, src->st_ctime); btrfs_set_stack_timespec_nsec(&dst->ctime, 0); btrfs_set_stack_timespec_sec(&dst->mtime, src->st_mtime); btrfs_set_stack_timespec_nsec(&dst->mtime, 0); btrfs_set_stack_timespec_sec(&dst->otime, 0); btrfs_set_stack_timespec_nsec(&dst->otime, 0); if (S_ISDIR(src->st_mode)) { -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 7/9] mkfs.btrfs: free buffers allocated by pretty_sizes
found by valgrind: ==2559== 16 bytes in 1 blocks are definitely lost in loss record 3 of 19 ==2559== at 0x4C2720E: malloc (vg_replace_malloc.c:236) ==2559== by 0x412F7E: pretty_sizes (utils.c:1054) ==2559== by 0x4179E9: main (mkfs.c:1395) Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- mkfs.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/mkfs.c b/mkfs.c index 32f25f5..c8b19c1 100644 --- a/mkfs.c +++ b/mkfs.c @@ -1159,40 +1159,41 @@ int main(int ac, char **av) u64 data_profile = BTRFS_BLOCK_GROUP_RAID0; u32 leafsize = getpagesize(); u32 sectorsize = 4096; u32 nodesize = leafsize; u32 stripesize = 4096; int zero_end = 1; int option_index = 0; int fd; int first_fd; int ret; int i; int mixed = 0; int data_profile_opt = 0; int metadata_profile_opt = 0; char *source_dir = NULL; int source_dir_set = 0; char *output = "output.img"; u64 num_of_meta_chunks = 0; u64 size_of_data = 0; + char * pretty_buf; while(1) { int c; c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VM", long_options, &option_index); if (c < 0) break; switch(c) { case ''A'': alloc_start = parse_size(optarg); break; case ''d'': data_profile = parse_profile(optarg); data_profile_opt = 1; break; case ''l'': leafsize = parse_size(optarg); break; case ''L'': label = parse_label(optarg); @@ -1378,41 +1379,42 @@ raid_groups: if (!source_dir_set) { ret = create_raid_groups(trans, root, data_profile, metadata_profile, mixed); BUG_ON(ret); } ret = create_data_reloc_tree(trans, root); BUG_ON(ret); if (mixed) { struct btrfs_super_block *super = &root->fs_info->super_copy; u64 flags = btrfs_super_incompat_flags(super); flags |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS; btrfs_set_super_incompat_flags(super, flags); } printf("fs created label %s on %s\n\tnodesize %u leafsize %u " "sectorsize %u size %s\n", label, first_file, nodesize, leafsize, sectorsize, - pretty_sizes(btrfs_super_total_bytes(&root->fs_info->super_copy))); + pretty_buf = pretty_sizes(btrfs_super_total_bytes(&root->fs_info->super_copy))); + free (pretty_buf); printf("%s\n", BTRFS_BUILD_VERSION); btrfs_commit_transaction(trans, root); if (source_dir_set) { trans = btrfs_start_transaction(root, 1); ret = create_chunks(trans, root, num_of_meta_chunks, size_of_data); BUG_ON(ret); btrfs_commit_transaction(trans, root); ret = make_image(source_dir, root, fd); BUG_ON(ret); } ret = close_ctree(root); BUG_ON(ret); free(label); return 0; -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 8/9] mkfs.btrfs: fix memory leak caused by ''scandir()'' calls
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- mkfs.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/mkfs.c b/mkfs.c index c8b19c1..a65fb4d 100644 --- a/mkfs.c +++ b/mkfs.c @@ -451,53 +451,67 @@ static int fill_inode_item(struct btrfs_trans_handle *trans, blocks += 1; blocks *= sectorsize; btrfs_set_stack_inode_nbytes(dst, blocks); } } if (S_ISLNK(src->st_mode)) btrfs_set_stack_inode_nbytes(dst, src->st_size + 1); return 0; } static int directory_select(const struct direct *entry) { if ((strncmp(entry->d_name, ".", entry->d_reclen) == 0) || (strncmp(entry->d_name, "..", entry->d_reclen) == 0)) return 0; else return 1; } +static void free_namelist(struct direct **files, int count) +{ + int i; + + if (count < 0) + return; + + for (i = 0; i < count; ++i) + free(files[i]); + free (files); +} + static u64 calculate_dir_inode_size(char *dirname) { int count, i; struct direct **files, *cur_file; u64 dir_inode_size = 0; count = scandir(dirname, &files, directory_select, NULL); for (i = 0; i < count; i++) { cur_file = files[i]; dir_inode_size += strlen(cur_file->d_name); } + free_namelist(files, count); + dir_inode_size *= 2; return dir_inode_size; } static int add_inode_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct stat *st, char *name, u64 self_objectid, ino_t parent_inum, int dir_index_cnt, struct btrfs_inode_item *inode_ret) { int ret; struct btrfs_key inode_key; struct btrfs_inode_item btrfs_inode; u64 objectid; u64 inode_size = 0; int name_len; name_len = strlen(name); fill_inode_item(trans, root, &btrfs_inode, st); objectid = self_objectid; @@ -954,49 +968,51 @@ static int traverse_directory(struct btrfs_trans_handle *trans, dir_entry->inum = cur_inum; list_add_tail(&dir_entry->list, &dir_head->list); } else if (S_ISREG(st.st_mode)) { ret = add_file_items(trans, root, &cur_inode, cur_inum, parent_inum, &st, cur_file->d_name, out_fd); if (ret) { fprintf(stderr, "add_file_items failed\n"); goto fail; } } else if (S_ISLNK(st.st_mode)) { ret = add_symbolic_link(trans, root, cur_inum, cur_file->d_name); if (ret) { fprintf(stderr, "add_symbolic_link failed\n"); goto fail; } } } + free_namelist(files, count); free(parent_dir_entry->path); free(parent_dir_entry); index_cnt = 2; } while (!list_empty(&dir_head->list)); return 0; fail: + free_namelist(files, count); free(parent_dir_entry->path); free(parent_dir_entry); return -1; } static int open_target(char *output_name) { int output_fd; output_fd = open(output_name, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); return output_fd; } static int create_chunks(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 num_of_meta_chunks, u64 size_of_data) { u64 chunk_start; u64 chunk_size; -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich
2011-Jun-04 08:19 UTC
[PATCH v2 9/9] mkfs.btrfs: fix error text in ''-r'' mode
Smart gcc noticed use of uninitialized warning when compiled with -O0 flags: mkfs.c:1291: error: ''file'' may be used uninitialized in this function Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> --- mkfs.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/mkfs.c b/mkfs.c index a65fb4d..44a05e8 100644 --- a/mkfs.c +++ b/mkfs.c @@ -1272,47 +1272,47 @@ int main(int ac, char **av) fprintf(stderr, "error checking %s mount status\n", file); exit(1); } if (ret == 1) { fprintf(stderr, "%s is mounted\n", file); exit(1); } ac--; fd = open(file, O_RDWR); if (fd < 0) { fprintf(stderr, "unable to open %s\n", file); exit(1); } first_fd = fd; first_file = file; ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count, &mixed); if (block_count == 0) block_count = dev_block_count; } else { ac = 0; + file = output; fd = open_target(output); if (fd < 0) { fprintf(stderr, "unable to open the %s\n", file); exit(1); } - file = output; first_fd = fd; first_file = file; block_count = size_sourcedir(source_dir, sectorsize, &num_of_meta_chunks, &size_of_data); ret = zero_output_file(fd, block_count, sectorsize); if (ret) { fprintf(stderr, "unable to zero the output file\n"); exit(1); } } if (mixed) { if (!metadata_profile_opt) metadata_profile = 0; if (!data_profile_opt) data_profile = 0; if (metadata_profile != data_profile) { fprintf(stderr, "With mixed block groups data and metadata " "profiles must be the same\n"); exit(1); -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html