btrfs-progs: remove NULL-ptr judge before free for btrfs-progs
[platform/upstream/btrfs-progs.git] / btrfs-convert.c
index a9ac9a5..bf3defb 100644 (file)
 
 #include "kerncompat.h"
 
-#ifndef __CHECKER__
 #include <sys/ioctl.h>
 #include <sys/mount.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -33,7 +31,6 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <uuid/uuid.h>
-#include <linux/fs.h>
 
 #include "ctree.h"
 #include "disk-io.h"
@@ -225,7 +222,7 @@ static int custom_free_extent(struct btrfs_root *root, u64 bytenr,
        return intersect_with_sb(bytenr, num_bytes);
 }
 
-struct btrfs_extent_ops extent_ops = {
+static struct btrfs_extent_ops extent_ops = {
        .alloc_extent = custom_alloc_extent,
        .free_extent = custom_free_extent,
 };
@@ -354,124 +351,33 @@ fail:
                ret = -1;
        return ret;
 }
-/*
- * Record a file extent. Do all the required works, such as inserting
- * file extent item, inserting extent item and backref item into extent
- * tree and updating block accounting.
- */
-static int record_file_extent(struct btrfs_trans_handle *trans,
-                             struct btrfs_root *root, u64 objectid,
-                             struct btrfs_inode_item *inode,
-                             u64 file_pos, u64 disk_bytenr,
-                             u64 num_bytes, int checksum)
+
+static int csum_disk_extent(struct btrfs_trans_handle *trans,
+                           struct btrfs_root *root,
+                           u64 disk_bytenr, u64 num_bytes)
 {
-       int ret;
-       struct btrfs_fs_info *info = root->fs_info;
-       struct btrfs_root *extent_root = info->extent_root;
-       struct extent_buffer *leaf;
-       struct btrfs_file_extent_item *fi;
-       struct btrfs_key ins_key;
-       struct btrfs_path path;
-       struct btrfs_extent_item *ei;
        u32 blocksize = root->sectorsize;
-       u64 nbytes;
-
-       if (disk_bytenr == 0) {
-               ret = btrfs_insert_file_extent(trans, root, objectid,
-                                               file_pos, disk_bytenr,
-                                               num_bytes, num_bytes);
-               return ret;
-       }
-
-       btrfs_init_path(&path);
-
-       if (checksum) {
-               u64 offset;
-               char *buffer;
+       u64 offset;
+       char *buffer;
+       int ret = 0;
 
-               ret = -ENOMEM;
-               buffer = malloc(blocksize);
-               if (!buffer)
-                       goto fail;
-               for (offset = 0; offset < num_bytes; offset += blocksize) {
-                       ret = read_disk_extent(root, disk_bytenr + offset,
-                                               blocksize, buffer);
-                       if (ret)
-                               break;
-                       ret = btrfs_csum_file_block(trans,
-                                                   root->fs_info->csum_root,
-                                                   disk_bytenr + num_bytes,
-                                                   disk_bytenr + offset,
-                                                   buffer, blocksize);
-                       if (ret)
-                               break;
-               }
-               free(buffer);
+       buffer = malloc(blocksize);
+       if (!buffer)
+               return -ENOMEM;
+       for (offset = 0; offset < num_bytes; offset += blocksize) {
+               ret = read_disk_extent(root, disk_bytenr + offset,
+                                       blocksize, buffer);
                if (ret)
-                       goto fail;
-       }
-
-       ins_key.objectid = objectid;
-       ins_key.offset = file_pos;
-       btrfs_set_key_type(&ins_key, BTRFS_EXTENT_DATA_KEY);
-       ret = btrfs_insert_empty_item(trans, root, &path, &ins_key,
-                                     sizeof(*fi));
-       if (ret)
-               goto fail;
-       leaf = path.nodes[0];
-       fi = btrfs_item_ptr(leaf, path.slots[0],
-                           struct btrfs_file_extent_item);
-       btrfs_set_file_extent_generation(leaf, fi, trans->transid);
-       btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
-       btrfs_set_file_extent_disk_bytenr(leaf, fi, disk_bytenr);
-       btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes);
-       btrfs_set_file_extent_offset(leaf, fi, 0);
-       btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
-       btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
-       btrfs_set_file_extent_compression(leaf, fi, 0);
-       btrfs_set_file_extent_encryption(leaf, fi, 0);
-       btrfs_set_file_extent_other_encoding(leaf, fi, 0);
-       btrfs_mark_buffer_dirty(leaf);
-
-       nbytes = btrfs_stack_inode_nbytes(inode) + num_bytes;
-       btrfs_set_stack_inode_nbytes(inode, nbytes);
-
-       btrfs_release_path(&path);
-
-       ins_key.objectid = disk_bytenr;
-       ins_key.offset = num_bytes;
-       ins_key.type = BTRFS_EXTENT_ITEM_KEY;
-
-       ret = btrfs_insert_empty_item(trans, extent_root, &path,
-                                     &ins_key, sizeof(*ei));
-       if (ret == 0) {
-               leaf = path.nodes[0];
-               ei = btrfs_item_ptr(leaf, path.slots[0],
-                                   struct btrfs_extent_item);
-
-               btrfs_set_extent_refs(leaf, ei, 0);
-               btrfs_set_extent_generation(leaf, ei, 0);
-               btrfs_set_extent_flags(leaf, ei, BTRFS_EXTENT_FLAG_DATA);
-
-               btrfs_mark_buffer_dirty(leaf);
-
-               ret = btrfs_update_block_group(trans, root, disk_bytenr,
-                                              num_bytes, 1, 0);
+                       break;
+               ret = btrfs_csum_file_block(trans,
+                                           root->fs_info->csum_root,
+                                           disk_bytenr + num_bytes,
+                                           disk_bytenr + offset,
+                                           buffer, blocksize);
                if (ret)
-                       goto fail;
-       } else if (ret != -EEXIST) {
-               goto fail;
+                       break;
        }
-       btrfs_extent_post_op(trans, extent_root);
-
-       ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, 0,
-                                  root->root_key.objectid,
-                                  objectid, file_pos);
-       if (ret)
-               goto fail;
-       ret = 0;
-fail:
-       btrfs_release_path(&path);
+       free(buffer);
        return ret;
 }
 
@@ -481,11 +387,17 @@ static int record_file_blocks(struct btrfs_trans_handle *trans,
                              u64 file_block, u64 disk_block,
                              u64 num_blocks, int checksum)
 {
+       int ret;
        u64 file_pos = file_block * root->sectorsize;
        u64 disk_bytenr = disk_block * root->sectorsize;
        u64 num_bytes = num_blocks * root->sectorsize;
-       return record_file_extent(trans, root, objectid, inode, file_pos,
-                                 disk_bytenr, num_bytes, checksum);
+       ret = btrfs_record_file_extent(trans, root, objectid, inode, file_pos,
+                                       disk_bytenr, num_bytes);
+
+       if (ret || !checksum)
+               return ret;
+
+       return csum_disk_extent(trans, root, disk_bytenr, num_bytes);
 }
 
 struct blk_iterate_data {
@@ -635,8 +547,7 @@ static int create_file_extents(struct btrfs_trans_handle *trans,
                                         data.first_block, data.checksum);
        }
 fail:
-       if (buffer)
-               free(buffer);
+       free(buffer);
        return ret;
 error:
        fprintf(stderr, "ext2fs_block_iterate2: %s\n", error_message(err));
@@ -873,8 +784,7 @@ static int copy_single_xattr(struct btrfs_trans_handle *trans,
        ret = btrfs_insert_xattr_item(trans, root, namebuf, name_len,
                                      data, datalen, objectid);
 out:
-       if (databuf)
-               free(databuf);
+       free(databuf);
        return ret;
 }
 
@@ -980,8 +890,7 @@ static int copy_extended_attrs(struct btrfs_trans_handle *trans,
                entry = EXT2_EXT_ATTR_NEXT(entry);
        }
 out:
-       if (buffer != NULL)
-               free(buffer);
+       free(buffer);
        if ((void *)ext2_inode != inode_buf)
                free(ext2_inode);
        return ret;
@@ -1296,9 +1205,9 @@ static int create_ext2_image(struct btrfs_root *root, ext2_filsys ext2_fs,
                                       sectorsize);
                if (ret)
                        goto fail;
-               ret = record_file_extent(trans, root, objectid,
-                                        &btrfs_inode, last_byte,
-                                        key.objectid, sectorsize, 0);
+               ret = btrfs_record_file_extent(trans, root, objectid,
+                                              &btrfs_inode, last_byte,
+                                              key.objectid, sectorsize);
                if (ret)
                        goto fail;
        }
@@ -1357,8 +1266,9 @@ next:
                        if (ret)
                                goto fail;
                }
-               ret = record_file_extent(trans, root, objectid, &btrfs_inode,
-                                        bytenr, bytenr, num_bytes, 0);
+               ret = btrfs_record_file_extent(trans, root, objectid,
+                                              &btrfs_inode, bytenr, bytenr,
+                                              num_bytes);
                if (ret)
                        goto fail;
                last_byte = bytenr + num_bytes;
@@ -1418,8 +1328,8 @@ fail:
        return ret;
 }
 
-struct btrfs_root *link_subvol(struct btrfs_root *root, const char *base,
-                              u64 root_objectid)
+static struct btrfs_root * link_subvol(struct btrfs_root *root,
+               const char *base, u64 root_objectid)
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -1431,10 +1341,15 @@ struct btrfs_root *link_subvol(struct btrfs_root *root, const char *base,
        struct btrfs_key key;
        u64 dirid = btrfs_root_dirid(&root->root_item);
        u64 index = 2;
-       char buf[64];
+       char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */
+       int len;
        int i;
        int ret;
 
+       len = strlen(base);
+       if (len < 1 || len > BTRFS_NAME_LEN)
+               return NULL;
+
        path = btrfs_alloc_path();
        BUG_ON(!path);
 
@@ -1470,18 +1385,22 @@ struct btrfs_root *link_subvol(struct btrfs_root *root, const char *base,
        key.offset = (u64)-1;
        key.type = BTRFS_ROOT_ITEM_KEY;
 
-       strcpy(buf, base);
+       memcpy(buf, base, len);
        for (i = 0; i < 1024; i++) {
-               ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf),
+               ret = btrfs_insert_dir_item(trans, root, buf, len,
                                            dirid, &key, BTRFS_FT_DIR, index);
                if (ret != -EEXIST)
                        break;
-               sprintf(buf, "%s%d", base, i);
+               len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
+               if (len < 1 || len > BTRFS_NAME_LEN) {
+                       ret = -EINVAL;
+                       break;
+               }
        }
        if (ret)
                goto fail;
 
-       btrfs_set_inode_size(leaf, inode_item, strlen(buf) * 2 +
+       btrfs_set_inode_size(leaf, inode_item, len * 2 +
                             btrfs_inode_size(leaf, inode_item));
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(path);
@@ -1490,13 +1409,13 @@ struct btrfs_root *link_subvol(struct btrfs_root *root, const char *base,
        ret = btrfs_add_root_ref(trans, tree_root, root_objectid,
                                 BTRFS_ROOT_BACKREF_KEY,
                                 root->root_key.objectid,
-                                dirid, index, buf, strlen(buf));
+                                dirid, index, buf, len);
        BUG_ON(ret);
 
        /* now add the forward ref */
        ret = btrfs_add_root_ref(trans, tree_root, root->root_key.objectid,
                                 BTRFS_ROOT_REF_KEY, root_objectid,
-                                dirid, index, buf, strlen(buf));
+                                dirid, index, buf, len);
 
        ret = btrfs_commit_transaction(trans, root);
        BUG_ON(ret);
@@ -1712,6 +1631,7 @@ static int init_btrfs(struct btrfs_root *root)
        ret = create_subvol(trans, root, BTRFS_DATA_RELOC_TREE_OBJECTID);
        BUG_ON(ret);
 
+       extent_buffer_get(fs_info->csum_root->node);
        ret = __btrfs_cow_block(trans, fs_info->csum_root,
                                fs_info->csum_root->node, NULL, 0, &tmp, 0, 0);
        BUG_ON(ret);
@@ -2277,7 +2197,8 @@ err:
        return ret;
 }
 
-int do_convert(const char *devname, int datacsum, int packing, int noxattr)
+static int do_convert(const char *devname, int datacsum, int packing,
+               int noxattr)
 {
        int i, ret;
        int fd = -1;
@@ -2321,7 +2242,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
        }
        ret = make_btrfs(fd, devname, ext2_fs->super->s_volume_name,
                         blocks, total_bytes, blocksize, blocksize,
-                        blocksize, blocksize);
+                        blocksize, blocksize, 0);
        if (ret) {
                fprintf(stderr, "unable to create initial ctree: %s\n",
                        strerror(-ret));
@@ -2333,7 +2254,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
                fprintf(stderr, "unable to update system chunk\n");
                goto fail;
        }
-       root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR);
+       root = open_ctree_fd(fd, devname, super_bytenr, OPEN_CTREE_WRITES);
        if (!root) {
                fprintf(stderr, "unable to open ctree\n");
                goto fail;
@@ -2394,7 +2315,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
                goto fail;
        }
 
-       root = open_ctree_fd(fd, devname, 0, O_RDWR);
+       root = open_ctree_fd(fd, devname, 0, OPEN_CTREE_WRITES);
        if (!root) {
                fprintf(stderr, "unable to open ctree\n");
                goto fail;
@@ -2456,7 +2377,7 @@ fail:
        return -1;
 }
 
-int do_rollback(const char *devname, int force)
+static int do_rollback(const char *devname, int force)
 {
        int fd = -1;
        int ret;
@@ -2495,7 +2416,7 @@ int do_rollback(const char *devname, int force)
                fprintf(stderr, "unable to open %s\n", devname);
                goto fail;
        }
-       root = open_ctree_fd(fd, devname, 0, O_RDWR);
+       root = open_ctree_fd(fd, devname, 0, OPEN_CTREE_WRITES);
        if (!root) {
                fprintf(stderr, "unable to open ctree\n");
                goto fail;