"Fossies" - the Fresh Open Source Software Archive

Member "btrfs-progs-v5.4/convert/source-ext2.c" (3 Dec 2019, 24374 Bytes) of package /linux/misc/btrfs-progs-v5.4.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "source-ext2.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: v5.1.1_vs_v5.2.

    1 /*
    2  * This program is free software; you can redistribute it and/or
    3  * modify it under the terms of the GNU General Public
    4  * License v2 as published by the Free Software Foundation.
    5  *
    6  * This program is distributed in the hope that it will be useful,
    7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    9  * General Public License for more details.
   10  *
   11  * You should have received a copy of the GNU General Public
   12  * License along with this program; if not, write to the
   13  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   14  * Boston, MA 021110-1307, USA.
   15  */
   16 
   17 #if BTRFSCONVERT_EXT2
   18 
   19 #include "kerncompat.h"
   20 #include <linux/limits.h>
   21 #include <pthread.h>
   22 #include "disk-io.h"
   23 #include "transaction.h"
   24 #include "common/utils.h"
   25 #include "convert/common.h"
   26 #include "convert/source-ext2.h"
   27 
   28 /*
   29  * Open Ext2fs in readonly mode, read block allocation bitmap and
   30  * inode bitmap into memory.
   31  */
   32 static int ext2_open_fs(struct btrfs_convert_context *cctx, const char *name)
   33 {
   34     errcode_t ret;
   35     ext2_filsys ext2_fs;
   36     ext2_ino_t ino;
   37     u32 ro_feature;
   38     int open_flag = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS;
   39 
   40     ret = ext2fs_open(name, open_flag, 0, 0, unix_io_manager, &ext2_fs);
   41     if (ret) {
   42         if (ret != EXT2_ET_BAD_MAGIC)
   43             fprintf(stderr, "ext2fs_open: %s\n", error_message(ret));
   44         return -1;
   45     }
   46     /*
   47      * We need to know exactly the used space, some RO compat flags like
   48      * BIGALLOC will affect how used space is present.
   49      * So we need manuall check any unsupported RO compat flags
   50      */
   51     ro_feature = ext2_fs->super->s_feature_ro_compat;
   52     if (ro_feature & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
   53         error(
   54 "unsupported RO features detected: %x, abort convert to avoid possible corruption",
   55               ro_feature & ~EXT2_LIB_FEATURE_COMPAT_SUPP);
   56         goto fail;
   57     }
   58     ret = ext2fs_read_inode_bitmap(ext2_fs);
   59     if (ret) {
   60         fprintf(stderr, "ext2fs_read_inode_bitmap: %s\n",
   61             error_message(ret));
   62         goto fail;
   63     }
   64     ret = ext2fs_read_block_bitmap(ext2_fs);
   65     if (ret) {
   66         fprintf(stderr, "ext2fs_read_block_bitmap: %s\n",
   67             error_message(ret));
   68         goto fail;
   69     }
   70     /*
   71      * search each block group for a free inode. this set up
   72      * uninit block/inode bitmaps appropriately.
   73      */
   74     ino = 1;
   75     while (ino <= ext2_fs->super->s_inodes_count) {
   76         ext2_ino_t foo;
   77         ext2fs_new_inode(ext2_fs, ino, 0, NULL, &foo);
   78         ino += EXT2_INODES_PER_GROUP(ext2_fs->super);
   79     }
   80 
   81     if (!(ext2_fs->super->s_feature_incompat &
   82           EXT2_FEATURE_INCOMPAT_FILETYPE)) {
   83         error("filetype feature is missing");
   84         goto fail;
   85     }
   86 
   87     cctx->fs_data = ext2_fs;
   88     cctx->blocksize = ext2_fs->blocksize;
   89     cctx->block_count = ext2_fs->super->s_blocks_count;
   90     cctx->total_bytes = ext2_fs->blocksize * ext2_fs->super->s_blocks_count;
   91     cctx->volume_name = strndup(ext2_fs->super->s_volume_name, 16);
   92     cctx->first_data_block = ext2_fs->super->s_first_data_block;
   93     cctx->inodes_count = ext2_fs->super->s_inodes_count;
   94     cctx->free_inodes_count = ext2_fs->super->s_free_inodes_count;
   95     return 0;
   96 fail:
   97     ext2fs_close(ext2_fs);
   98     ext2fs_free(ext2_fs);
   99     return -1;
  100 }
  101 
  102 static int __ext2_add_one_block(ext2_filsys fs, char *bitmap,
  103                 unsigned long group_nr, struct cache_tree *used)
  104 {
  105     unsigned long offset;
  106     unsigned i;
  107     int ret = 0;
  108 
  109     offset = fs->super->s_first_data_block;
  110     offset /= EXT2FS_CLUSTER_RATIO(fs);
  111     offset += group_nr * EXT2_CLUSTERS_PER_GROUP(fs->super);
  112     for (i = 0; i < EXT2_CLUSTERS_PER_GROUP(fs->super); i++) {
  113         if ((i + offset) >= ext2fs_blocks_count(fs->super))
  114             break;
  115 
  116         if (ext2fs_test_bit(i, bitmap)) {
  117             u64 start;
  118 
  119             start = (i + offset) * EXT2FS_CLUSTER_RATIO(fs);
  120             start *= fs->blocksize;
  121             ret = add_merge_cache_extent(used, start,
  122                              fs->blocksize);
  123             if (ret < 0)
  124                 break;
  125         }
  126     }
  127     return ret;
  128 }
  129 
  130 /*
  131  * Read all used ext2 space into cctx->used cache tree
  132  */
  133 static int ext2_read_used_space(struct btrfs_convert_context *cctx)
  134 {
  135     ext2_filsys fs = (ext2_filsys)cctx->fs_data;
  136     blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
  137     struct cache_tree *used_tree = &cctx->used_space;
  138     char *block_bitmap = NULL;
  139     unsigned long i;
  140     int block_nbytes;
  141     int ret = 0;
  142 
  143     block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
  144     if (!block_nbytes) {
  145         error("EXT2_CLUSTERS_PER_GROUP too small: %llu",
  146             (unsigned long long)(EXT2_CLUSTERS_PER_GROUP(fs->super)));
  147         return -EINVAL;
  148     }
  149 
  150     block_bitmap = malloc(block_nbytes);
  151     if (!block_bitmap)
  152         return -ENOMEM;
  153 
  154     for (i = 0; i < fs->group_desc_count; i++) {
  155         ret = ext2fs_get_block_bitmap_range2(fs->block_map, blk_itr,
  156                         block_nbytes * 8, block_bitmap);
  157         if (ret) {
  158             error("fail to get bitmap from ext2, %s",
  159                 error_message(ret));
  160             ret = -EINVAL;
  161             break;
  162         }
  163         ret = __ext2_add_one_block(fs, block_bitmap, i, used_tree);
  164         if (ret < 0) {
  165             errno = -ret;
  166             error("fail to build used space tree, %m");
  167             break;
  168         }
  169         blk_itr += EXT2_CLUSTERS_PER_GROUP(fs->super);
  170     }
  171 
  172     free(block_bitmap);
  173     return ret;
  174 }
  175 
  176 static void ext2_close_fs(struct btrfs_convert_context *cctx)
  177 {
  178     if (cctx->volume_name) {
  179         free(cctx->volume_name);
  180         cctx->volume_name = NULL;
  181     }
  182     ext2fs_close(cctx->fs_data);
  183     ext2fs_free(cctx->fs_data);
  184 }
  185 
  186 static u8 ext2_filetype_conversion_table[EXT2_FT_MAX] = {
  187     [EXT2_FT_UNKNOWN]   = BTRFS_FT_UNKNOWN,
  188     [EXT2_FT_REG_FILE]  = BTRFS_FT_REG_FILE,
  189     [EXT2_FT_DIR]       = BTRFS_FT_DIR,
  190     [EXT2_FT_CHRDEV]    = BTRFS_FT_CHRDEV,
  191     [EXT2_FT_BLKDEV]    = BTRFS_FT_BLKDEV,
  192     [EXT2_FT_FIFO]      = BTRFS_FT_FIFO,
  193     [EXT2_FT_SOCK]      = BTRFS_FT_SOCK,
  194     [EXT2_FT_SYMLINK]   = BTRFS_FT_SYMLINK,
  195 };
  196 
  197 static int ext2_dir_iterate_proc(ext2_ino_t dir, int entry,
  198                 struct ext2_dir_entry *dirent,
  199                 int offset, int blocksize,
  200                 char *buf,void *priv_data)
  201 {
  202     int ret;
  203     int file_type;
  204     u64 objectid;
  205     char dotdot[] = "..";
  206     struct dir_iterate_data *idata = (struct dir_iterate_data *)priv_data;
  207     int name_len;
  208 
  209     name_len = dirent->name_len & 0xFF;
  210 
  211     objectid = dirent->inode + INO_OFFSET;
  212     if (!strncmp(dirent->name, dotdot, name_len)) {
  213         if (name_len == 2) {
  214             BUG_ON(idata->parent != 0);
  215             idata->parent = objectid;
  216         }
  217         return 0;
  218     }
  219     if (dirent->inode < EXT2_GOOD_OLD_FIRST_INO)
  220         return 0;
  221 
  222     file_type = dirent->name_len >> 8;
  223     BUG_ON(file_type > EXT2_FT_SYMLINK);
  224 
  225     ret = convert_insert_dirent(idata->trans, idata->root, dirent->name,
  226                     name_len, idata->objectid, objectid,
  227                     ext2_filetype_conversion_table[file_type],
  228                     idata->index_cnt, idata->inode);
  229     if (ret < 0) {
  230         idata->errcode = ret;
  231         return BLOCK_ABORT;
  232     }
  233 
  234     idata->index_cnt++;
  235     return 0;
  236 }
  237 
  238 static int ext2_create_dir_entries(struct btrfs_trans_handle *trans,
  239                   struct btrfs_root *root, u64 objectid,
  240                   struct btrfs_inode_item *btrfs_inode,
  241                   ext2_filsys ext2_fs, ext2_ino_t ext2_ino)
  242 {
  243     int ret;
  244     errcode_t err;
  245     struct dir_iterate_data data = {
  246         .trans      = trans,
  247         .root       = root,
  248         .inode      = btrfs_inode,
  249         .objectid   = objectid,
  250         .index_cnt  = 2,
  251         .parent     = 0,
  252         .errcode    = 0,
  253     };
  254 
  255     err = ext2fs_dir_iterate2(ext2_fs, ext2_ino, 0, NULL,
  256                   ext2_dir_iterate_proc, &data);
  257     if (err)
  258         goto error;
  259     ret = data.errcode;
  260     if (ret == 0 && data.parent == objectid) {
  261         ret = btrfs_insert_inode_ref(trans, root, "..", 2,
  262                          objectid, objectid, 0);
  263     }
  264     return ret;
  265 error:
  266     fprintf(stderr, "ext2fs_dir_iterate2: %s\n", error_message(err));
  267     return -1;
  268 }
  269 
  270 static int ext2_block_iterate_proc(ext2_filsys fs, blk_t *blocknr,
  271                     e2_blkcnt_t blockcnt, blk_t ref_block,
  272                     int ref_offset, void *priv_data)
  273 {
  274     int ret;
  275     struct blk_iterate_data *idata;
  276     idata = (struct blk_iterate_data *)priv_data;
  277     ret = block_iterate_proc(*blocknr, blockcnt, idata);
  278     if (ret) {
  279         idata->errcode = ret;
  280         return BLOCK_ABORT;
  281     }
  282     return 0;
  283 }
  284 
  285 /*
  286  * traverse file's data blocks, record these data blocks as file extents.
  287  */
  288 static int ext2_create_file_extents(struct btrfs_trans_handle *trans,
  289                    struct btrfs_root *root, u64 objectid,
  290                    struct btrfs_inode_item *btrfs_inode,
  291                    ext2_filsys ext2_fs, ext2_ino_t ext2_ino,
  292                    u32 convert_flags)
  293 {
  294     int ret;
  295     char *buffer = NULL;
  296     errcode_t err;
  297     u32 last_block;
  298     u32 sectorsize = root->fs_info->sectorsize;
  299     u64 inode_size = btrfs_stack_inode_size(btrfs_inode);
  300     struct blk_iterate_data data;
  301 
  302     init_blk_iterate_data(&data, trans, root, btrfs_inode, objectid,
  303             convert_flags & CONVERT_FLAG_DATACSUM);
  304 
  305     err = ext2fs_block_iterate2(ext2_fs, ext2_ino, BLOCK_FLAG_DATA_ONLY,
  306                     NULL, ext2_block_iterate_proc, &data);
  307     if (err)
  308         goto error;
  309     ret = data.errcode;
  310     if (ret)
  311         goto fail;
  312     if ((convert_flags & CONVERT_FLAG_INLINE_DATA) && data.first_block == 0
  313         && data.num_blocks > 0 && inode_size < sectorsize
  314         && inode_size <= BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info)) {
  315         u64 num_bytes = data.num_blocks * sectorsize;
  316         u64 disk_bytenr = data.disk_block * sectorsize;
  317         u64 nbytes;
  318 
  319         buffer = malloc(num_bytes);
  320         if (!buffer)
  321             return -ENOMEM;
  322         ret = read_disk_extent(root, disk_bytenr, num_bytes, buffer);
  323         if (ret)
  324             goto fail;
  325         if (num_bytes > inode_size)
  326             num_bytes = inode_size;
  327         ret = btrfs_insert_inline_extent(trans, root, objectid,
  328                          0, buffer, num_bytes);
  329         if (ret)
  330             goto fail;
  331         nbytes = btrfs_stack_inode_nbytes(btrfs_inode) + num_bytes;
  332         btrfs_set_stack_inode_nbytes(btrfs_inode, nbytes);
  333     } else if (data.num_blocks > 0) {
  334         ret = record_file_blocks(&data, data.first_block,
  335                      data.disk_block, data.num_blocks);
  336         if (ret)
  337             goto fail;
  338     }
  339     data.first_block += data.num_blocks;
  340     last_block = (inode_size + sectorsize - 1) / sectorsize;
  341     if (last_block > data.first_block) {
  342         ret = record_file_blocks(&data, data.first_block, 0,
  343                      last_block - data.first_block);
  344     }
  345 fail:
  346     free(buffer);
  347     return ret;
  348 error:
  349     fprintf(stderr, "ext2fs_block_iterate2: %s\n", error_message(err));
  350     return -1;
  351 }
  352 
  353 static int ext2_create_symlink(struct btrfs_trans_handle *trans,
  354                   struct btrfs_root *root, u64 objectid,
  355                   struct btrfs_inode_item *btrfs_inode,
  356                   ext2_filsys ext2_fs, ext2_ino_t ext2_ino,
  357                   struct ext2_inode *ext2_inode)
  358 {
  359     int ret;
  360     char *pathname;
  361     u64 inode_size = btrfs_stack_inode_size(btrfs_inode);
  362     if (ext2fs_inode_data_blocks2(ext2_fs, ext2_inode)) {
  363         btrfs_set_stack_inode_size(btrfs_inode, inode_size + 1);
  364         ret = ext2_create_file_extents(trans, root, objectid,
  365                 btrfs_inode, ext2_fs, ext2_ino,
  366                 CONVERT_FLAG_DATACSUM |
  367                 CONVERT_FLAG_INLINE_DATA);
  368         btrfs_set_stack_inode_size(btrfs_inode, inode_size);
  369         return ret;
  370     }
  371 
  372     pathname = (char *)&(ext2_inode->i_block[0]);
  373     BUG_ON(pathname[inode_size] != 0);
  374     ret = btrfs_insert_inline_extent(trans, root, objectid, 0,
  375                      pathname, inode_size + 1);
  376     btrfs_set_stack_inode_nbytes(btrfs_inode, inode_size + 1);
  377     return ret;
  378 }
  379 
  380 /*
  381  * Following xattr/acl related codes are based on codes in
  382  * fs/ext3/xattr.c and fs/ext3/acl.c
  383  */
  384 #define EXT2_XATTR_BHDR(ptr) ((struct ext2_ext_attr_header *)(ptr))
  385 #define EXT2_XATTR_BFIRST(ptr) \
  386     ((struct ext2_ext_attr_entry *)(EXT2_XATTR_BHDR(ptr) + 1))
  387 #define EXT2_XATTR_IHDR(inode) \
  388     ((struct ext2_ext_attr_header *) ((void *)(inode) + \
  389         EXT2_GOOD_OLD_INODE_SIZE + (inode)->i_extra_isize))
  390 #define EXT2_XATTR_IFIRST(inode) \
  391     ((struct ext2_ext_attr_entry *) ((void *)EXT2_XATTR_IHDR(inode) + \
  392         sizeof(EXT2_XATTR_IHDR(inode)->h_magic)))
  393 
  394 static int ext2_xattr_check_names(struct ext2_ext_attr_entry *entry,
  395                   const void *end)
  396 {
  397     struct ext2_ext_attr_entry *next;
  398 
  399     while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
  400         next = EXT2_EXT_ATTR_NEXT(entry);
  401         if ((void *)next >= end)
  402             return -EIO;
  403         entry = next;
  404     }
  405     return 0;
  406 }
  407 
  408 static int ext2_xattr_check_block(const char *buf, size_t size)
  409 {
  410     int error;
  411     struct ext2_ext_attr_header *header = EXT2_XATTR_BHDR(buf);
  412 
  413     if (header->h_magic != EXT2_EXT_ATTR_MAGIC ||
  414         header->h_blocks != 1)
  415         return -EIO;
  416     error = ext2_xattr_check_names(EXT2_XATTR_BFIRST(buf), buf + size);
  417     return error;
  418 }
  419 
  420 static int ext2_xattr_check_entry(struct ext2_ext_attr_entry *entry,
  421                   size_t size)
  422 {
  423     size_t value_size = entry->e_value_size;
  424 
  425     if (value_size > size || entry->e_value_offs + value_size > size)
  426         return -EIO;
  427     return 0;
  428 }
  429 
  430 static int ext2_acl_to_xattr(void *dst, const void *src,
  431                  size_t dst_size, size_t src_size)
  432 {
  433     int i, count;
  434     const void *end = src + src_size;
  435     acl_ea_header *ext_acl = (acl_ea_header *)dst;
  436     acl_ea_entry *dst_entry = ext_acl->a_entries;
  437     ext2_acl_entry *src_entry;
  438 
  439     if (src_size < sizeof(ext2_acl_header))
  440         goto fail;
  441     if (((ext2_acl_header *)src)->a_version !=
  442         cpu_to_le32(EXT2_ACL_VERSION))
  443         goto fail;
  444     src += sizeof(ext2_acl_header);
  445     count = ext2_acl_count(src_size);
  446     if (count <= 0)
  447         goto fail;
  448 
  449     BUG_ON(dst_size < acl_ea_size(count));
  450     ext_acl->a_version = cpu_to_le32(ACL_EA_VERSION);
  451     for (i = 0; i < count; i++, dst_entry++) {
  452         src_entry = (ext2_acl_entry *)src;
  453         if (src + sizeof(ext2_acl_entry_short) > end)
  454             goto fail;
  455         dst_entry->e_tag = src_entry->e_tag;
  456         dst_entry->e_perm = src_entry->e_perm;
  457         switch (le16_to_cpu(src_entry->e_tag)) {
  458         case ACL_USER_OBJ:
  459         case ACL_GROUP_OBJ:
  460         case ACL_MASK:
  461         case ACL_OTHER:
  462             src += sizeof(ext2_acl_entry_short);
  463             dst_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
  464             break;
  465         case ACL_USER:
  466         case ACL_GROUP:
  467             src += sizeof(ext2_acl_entry);
  468             if (src > end)
  469                 goto fail;
  470             dst_entry->e_id = src_entry->e_id;
  471             break;
  472         default:
  473             goto fail;
  474         }
  475     }
  476     if (src != end)
  477         goto fail;
  478     return 0;
  479 fail:
  480     return -EINVAL;
  481 }
  482 
  483 static char *xattr_prefix_table[] = {
  484     [1] =   "user.",
  485     [2] =   "system.posix_acl_access",
  486     [3] =   "system.posix_acl_default",
  487     [4] =   "trusted.",
  488     [6] =   "security.",
  489 };
  490 
  491 static int ext2_copy_single_xattr(struct btrfs_trans_handle *trans,
  492                  struct btrfs_root *root, u64 objectid,
  493                  struct ext2_ext_attr_entry *entry,
  494                  const void *data, u32 datalen)
  495 {
  496     int ret = 0;
  497     int name_len;
  498     int name_index;
  499     void *databuf = NULL;
  500     char namebuf[XATTR_NAME_MAX + 1];
  501 
  502     name_index = entry->e_name_index;
  503     if (name_index >= ARRAY_SIZE(xattr_prefix_table) ||
  504         xattr_prefix_table[name_index] == NULL)
  505         return -EOPNOTSUPP;
  506     name_len = strlen(xattr_prefix_table[name_index]) +
  507            entry->e_name_len;
  508     if (name_len >= sizeof(namebuf))
  509         return -ERANGE;
  510 
  511     if (name_index == 2 || name_index == 3) {
  512         size_t bufsize = acl_ea_size(ext2_acl_count(datalen));
  513         databuf = malloc(bufsize);
  514         if (!databuf)
  515                return -ENOMEM;
  516         ret = ext2_acl_to_xattr(databuf, data, bufsize, datalen);
  517         if (ret)
  518             goto out;
  519         data = databuf;
  520         datalen = bufsize;
  521     }
  522     strncpy(namebuf, xattr_prefix_table[name_index], XATTR_NAME_MAX);
  523     strncat(namebuf, EXT2_EXT_ATTR_NAME(entry), entry->e_name_len);
  524     if (name_len + datalen > BTRFS_LEAF_DATA_SIZE(root->fs_info) -
  525         sizeof(struct btrfs_item) - sizeof(struct btrfs_dir_item)) {
  526         fprintf(stderr, "skip large xattr on inode %Lu name %.*s\n",
  527             objectid - INO_OFFSET, name_len, namebuf);
  528         goto out;
  529     }
  530     ret = btrfs_insert_xattr_item(trans, root, namebuf, name_len,
  531                       data, datalen, objectid);
  532 out:
  533     free(databuf);
  534     return ret;
  535 }
  536 
  537 static int ext2_copy_extended_attrs(struct btrfs_trans_handle *trans,
  538                    struct btrfs_root *root, u64 objectid,
  539                    struct btrfs_inode_item *btrfs_inode,
  540                    ext2_filsys ext2_fs, ext2_ino_t ext2_ino)
  541 {
  542     int ret = 0;
  543     int inline_ea = 0;
  544     errcode_t err;
  545     u32 datalen;
  546     u32 block_size = ext2_fs->blocksize;
  547     u32 inode_size = EXT2_INODE_SIZE(ext2_fs->super);
  548     struct ext2_inode_large *ext2_inode;
  549     struct ext2_ext_attr_entry *entry;
  550     void *data;
  551     char *buffer = NULL;
  552     char inode_buf[EXT2_GOOD_OLD_INODE_SIZE];
  553 
  554     if (inode_size <= EXT2_GOOD_OLD_INODE_SIZE) {
  555         ext2_inode = (struct ext2_inode_large *)inode_buf;
  556     } else {
  557         ext2_inode = (struct ext2_inode_large *)malloc(inode_size);
  558         if (!ext2_inode)
  559                return -ENOMEM;
  560     }
  561     err = ext2fs_read_inode_full(ext2_fs, ext2_ino, (void *)ext2_inode,
  562                      inode_size);
  563     if (err) {
  564         fprintf(stderr, "ext2fs_read_inode_full: %s\n",
  565             error_message(err));
  566         ret = -1;
  567         goto out;
  568     }
  569 
  570     if (ext2_ino > ext2_fs->super->s_first_ino &&
  571         inode_size > EXT2_GOOD_OLD_INODE_SIZE) {
  572         if (EXT2_GOOD_OLD_INODE_SIZE +
  573             ext2_inode->i_extra_isize > inode_size) {
  574             ret = -EIO;
  575             goto out;
  576         }
  577         if (ext2_inode->i_extra_isize != 0 &&
  578             EXT2_XATTR_IHDR(ext2_inode)->h_magic ==
  579             EXT2_EXT_ATTR_MAGIC) {
  580             inline_ea = 1;
  581         }
  582     }
  583     if (inline_ea) {
  584         int total;
  585         void *end = (void *)ext2_inode + inode_size;
  586         entry = EXT2_XATTR_IFIRST(ext2_inode);
  587         total = end - (void *)entry;
  588         ret = ext2_xattr_check_names(entry, end);
  589         if (ret)
  590             goto out;
  591         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
  592             ret = ext2_xattr_check_entry(entry, total);
  593             if (ret)
  594                 goto out;
  595             data = (void *)EXT2_XATTR_IFIRST(ext2_inode) +
  596                 entry->e_value_offs;
  597             datalen = entry->e_value_size;
  598             ret = ext2_copy_single_xattr(trans, root, objectid,
  599                         entry, data, datalen);
  600             if (ret)
  601                 goto out;
  602             entry = EXT2_EXT_ATTR_NEXT(entry);
  603         }
  604     }
  605 
  606     if (ext2_inode->i_file_acl == 0)
  607         goto out;
  608 
  609     buffer = malloc(block_size);
  610     if (!buffer) {
  611         ret = -ENOMEM;
  612         goto out;
  613     }
  614     err = ext2fs_read_ext_attr2(ext2_fs, ext2_inode->i_file_acl, buffer);
  615     if (err) {
  616         fprintf(stderr, "ext2fs_read_ext_attr2: %s\n",
  617             error_message(err));
  618         ret = -1;
  619         goto out;
  620     }
  621     ret = ext2_xattr_check_block(buffer, block_size);
  622     if (ret)
  623         goto out;
  624 
  625     entry = EXT2_XATTR_BFIRST(buffer);
  626     while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
  627         ret = ext2_xattr_check_entry(entry, block_size);
  628         if (ret)
  629             goto out;
  630         data = buffer + entry->e_value_offs;
  631         datalen = entry->e_value_size;
  632         ret = ext2_copy_single_xattr(trans, root, objectid,
  633                     entry, data, datalen);
  634         if (ret)
  635             goto out;
  636         entry = EXT2_EXT_ATTR_NEXT(entry);
  637     }
  638 out:
  639     free(buffer);
  640     if ((void *)ext2_inode != inode_buf)
  641         free(ext2_inode);
  642     return ret;
  643 }
  644 
  645 static inline dev_t old_decode_dev(u16 val)
  646 {
  647     return MKDEV((val >> 8) & 255, val & 255);
  648 }
  649 
  650 static void ext2_copy_inode_item(struct btrfs_inode_item *dst,
  651                struct ext2_inode *src, u32 blocksize)
  652 {
  653     btrfs_set_stack_inode_generation(dst, 1);
  654     btrfs_set_stack_inode_sequence(dst, 0);
  655     btrfs_set_stack_inode_transid(dst, 1);
  656     btrfs_set_stack_inode_size(dst, src->i_size);
  657     btrfs_set_stack_inode_nbytes(dst, 0);
  658     btrfs_set_stack_inode_block_group(dst, 0);
  659     btrfs_set_stack_inode_nlink(dst, src->i_links_count);
  660     btrfs_set_stack_inode_uid(dst, src->i_uid | (src->i_uid_high << 16));
  661     btrfs_set_stack_inode_gid(dst, src->i_gid | (src->i_gid_high << 16));
  662     btrfs_set_stack_inode_mode(dst, src->i_mode);
  663     btrfs_set_stack_inode_rdev(dst, 0);
  664     btrfs_set_stack_inode_flags(dst, 0);
  665     btrfs_set_stack_timespec_sec(&dst->atime, src->i_atime);
  666     btrfs_set_stack_timespec_nsec(&dst->atime, 0);
  667     btrfs_set_stack_timespec_sec(&dst->ctime, src->i_ctime);
  668     btrfs_set_stack_timespec_nsec(&dst->ctime, 0);
  669     btrfs_set_stack_timespec_sec(&dst->mtime, src->i_mtime);
  670     btrfs_set_stack_timespec_nsec(&dst->mtime, 0);
  671     btrfs_set_stack_timespec_sec(&dst->otime, 0);
  672     btrfs_set_stack_timespec_nsec(&dst->otime, 0);
  673 
  674     if (S_ISDIR(src->i_mode)) {
  675         btrfs_set_stack_inode_size(dst, 0);
  676         btrfs_set_stack_inode_nlink(dst, 1);
  677     }
  678     if (S_ISREG(src->i_mode)) {
  679         btrfs_set_stack_inode_size(dst, (u64)src->i_size_high << 32 |
  680                        (u64)src->i_size);
  681     }
  682     if (!S_ISREG(src->i_mode) && !S_ISDIR(src->i_mode) &&
  683         !S_ISLNK(src->i_mode)) {
  684         if (src->i_block[0]) {
  685             btrfs_set_stack_inode_rdev(dst,
  686                 old_decode_dev(src->i_block[0]));
  687         } else {
  688             btrfs_set_stack_inode_rdev(dst,
  689                 decode_dev(src->i_block[1]));
  690         }
  691     }
  692     memset(&dst->reserved, 0, sizeof(dst->reserved));
  693 }
  694 static int ext2_check_state(struct btrfs_convert_context *cctx)
  695 {
  696     ext2_filsys fs = cctx->fs_data;
  697 
  698         if (!(fs->super->s_state & EXT2_VALID_FS))
  699         return 1;
  700     else if (fs->super->s_state & EXT2_ERROR_FS)
  701         return 1;
  702     else
  703         return 0;
  704 }
  705 
  706 /* EXT2_*_FL to BTRFS_INODE_FLAG_* stringification helper */
  707 #define COPY_ONE_EXT2_FLAG(flags, ext2_inode, name) ({          \
  708     if (ext2_inode->i_flags & EXT2_##name##_FL)         \
  709         flags |= BTRFS_INODE_##name;                \
  710 })
  711 
  712 /*
  713  * Convert EXT2_*_FL to corresponding BTRFS_INODE_* flags
  714  *
  715  * Only a subset of EXT_*_FL is supported in btrfs.
  716  */
  717 static void ext2_convert_inode_flags(struct btrfs_inode_item *dst,
  718                      struct ext2_inode *src)
  719 {
  720     u64 flags = btrfs_stack_inode_flags(dst);
  721 
  722     COPY_ONE_EXT2_FLAG(flags, src, APPEND);
  723     COPY_ONE_EXT2_FLAG(flags, src, SYNC);
  724     COPY_ONE_EXT2_FLAG(flags, src, IMMUTABLE);
  725     COPY_ONE_EXT2_FLAG(flags, src, NODUMP);
  726     COPY_ONE_EXT2_FLAG(flags, src, NOATIME);
  727     COPY_ONE_EXT2_FLAG(flags, src, DIRSYNC);
  728     btrfs_set_stack_inode_flags(dst, flags);
  729 }
  730 
  731 /*
  732  * copy a single inode. do all the required works, such as cloning
  733  * inode item, creating file extents and creating directory entries.
  734  */
  735 static int ext2_copy_single_inode(struct btrfs_trans_handle *trans,
  736                  struct btrfs_root *root, u64 objectid,
  737                  ext2_filsys ext2_fs, ext2_ino_t ext2_ino,
  738                  struct ext2_inode *ext2_inode,
  739                  u32 convert_flags)
  740 {
  741     int ret;
  742     struct btrfs_inode_item btrfs_inode;
  743 
  744     if (ext2_inode->i_links_count == 0)
  745         return 0;
  746 
  747     ext2_copy_inode_item(&btrfs_inode, ext2_inode, ext2_fs->blocksize);
  748     if (!(convert_flags & CONVERT_FLAG_DATACSUM)
  749         && S_ISREG(ext2_inode->i_mode)) {
  750         u32 flags = btrfs_stack_inode_flags(&btrfs_inode) |
  751                 BTRFS_INODE_NODATASUM;
  752         btrfs_set_stack_inode_flags(&btrfs_inode, flags);
  753     }
  754     ext2_convert_inode_flags(&btrfs_inode, ext2_inode);
  755 
  756     switch (ext2_inode->i_mode & S_IFMT) {
  757     case S_IFREG:
  758         ret = ext2_create_file_extents(trans, root, objectid,
  759             &btrfs_inode, ext2_fs, ext2_ino, convert_flags);
  760         break;
  761     case S_IFDIR:
  762         ret = ext2_create_dir_entries(trans, root, objectid,
  763                 &btrfs_inode, ext2_fs, ext2_ino);
  764         break;
  765     case S_IFLNK:
  766         ret = ext2_create_symlink(trans, root, objectid,
  767                 &btrfs_inode, ext2_fs, ext2_ino, ext2_inode);
  768         break;
  769     default:
  770         ret = 0;
  771         break;
  772     }
  773     if (ret)
  774         return ret;
  775 
  776     if (convert_flags & CONVERT_FLAG_XATTR) {
  777         ret = ext2_copy_extended_attrs(trans, root, objectid,
  778                 &btrfs_inode, ext2_fs, ext2_ino);
  779         if (ret)
  780             return ret;
  781     }
  782     return btrfs_insert_inode(trans, root, objectid, &btrfs_inode);
  783 }
  784 
  785 static int ext2_is_special_inode(ext2_ino_t ino)
  786 {
  787     if (ino < EXT2_GOOD_OLD_FIRST_INO && ino != EXT2_ROOT_INO)
  788         return 1;
  789     return 0;
  790 }
  791 
  792 /*
  793  * scan ext2's inode bitmap and copy all used inodes.
  794  */
  795 static int ext2_copy_inodes(struct btrfs_convert_context *cctx,
  796                 struct btrfs_root *root,
  797                 u32 convert_flags, struct task_ctx *p)
  798 {
  799     ext2_filsys ext2_fs = cctx->fs_data;
  800     int ret;
  801     errcode_t err;
  802     ext2_inode_scan ext2_scan;
  803     struct ext2_inode ext2_inode;
  804     ext2_ino_t ext2_ino;
  805     u64 objectid;
  806     struct btrfs_trans_handle *trans;
  807 
  808     trans = btrfs_start_transaction(root, 1);
  809     if (IS_ERR(trans))
  810         return PTR_ERR(trans);
  811     err = ext2fs_open_inode_scan(ext2_fs, 0, &ext2_scan);
  812     if (err) {
  813         fprintf(stderr, "ext2fs_open_inode_scan: %s\n", error_message(err));
  814         return -1;
  815     }
  816     while (!(err = ext2fs_get_next_inode(ext2_scan, &ext2_ino,
  817                          &ext2_inode))) {
  818         /* no more inodes */
  819         if (ext2_ino == 0)
  820             break;
  821         if (ext2_is_special_inode(ext2_ino))
  822             continue;
  823         objectid = ext2_ino + INO_OFFSET;
  824         ret = ext2_copy_single_inode(trans, root,
  825                     objectid, ext2_fs, ext2_ino,
  826                     &ext2_inode, convert_flags);
  827         pthread_mutex_lock(&p->mutex);
  828         p->cur_copy_inodes++;
  829         pthread_mutex_unlock(&p->mutex);
  830         if (ret)
  831             return ret;
  832         /*
  833          * blocks_used is the number of new tree blocks allocated in
  834          * current transaction.
  835          * Use a small amount of it to workaround a bug where delayed
  836          * ref may fail to locate tree blocks in extent tree.
  837          *
  838          * 2M is the threshold to kick chunk preallocator into work,
  839          * For default (16K) nodesize it will be 128 tree blocks,
  840          * large enough to contain over 300 inlined files or
  841          * around 26k file extents. Which should be good enough.
  842          */
  843         if (trans->blocks_used >= SZ_2M / root->fs_info->nodesize) {
  844             ret = btrfs_commit_transaction(trans, root);
  845             BUG_ON(ret);
  846             trans = btrfs_start_transaction(root, 1);
  847             BUG_ON(IS_ERR(trans));
  848         }
  849     }
  850     if (err) {
  851         fprintf(stderr, "ext2fs_get_next_inode: %s\n", error_message(err));
  852         return -1;
  853     }
  854     ret = btrfs_commit_transaction(trans, root);
  855     BUG_ON(ret);
  856     ext2fs_close_inode_scan(ext2_scan);
  857 
  858     return ret;
  859 }
  860 
  861 const struct btrfs_convert_operations ext2_convert_ops = {
  862     .name           = "ext2",
  863     .open_fs        = ext2_open_fs,
  864     .read_used_space    = ext2_read_used_space,
  865     .copy_inodes        = ext2_copy_inodes,
  866     .close_fs       = ext2_close_fs,
  867     .check_state        = ext2_check_state,
  868 };
  869 
  870 #endif  /* BTRFSCONVERT_EXT2 */