@@ -455,6 +455,90 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
455455 return ret ;
456456}
457457
458+ /*
459+ * keep our extent size at 1MB max, this makes it easier to work
460+ * inside the tiny block groups created during mkfs
461+ */
462+ #define MAX_EXTENT_SIZE SZ_1M
463+
464+ struct source_descriptor {
465+ int fd ;
466+ char * buf ;
467+ u64 size ;
468+ const char * path_name ;
469+ };
470+
471+ static int add_file_item_extent (struct btrfs_trans_handle * trans ,
472+ struct btrfs_root * root ,
473+ struct btrfs_inode_item * btrfs_inode ,
474+ u64 objectid ,
475+ const struct source_descriptor * source ,
476+ u64 file_pos )
477+ {
478+ int ret ;
479+ u32 sectorsize = root -> fs_info -> sectorsize ;
480+ u64 bytes_read , first_block , to_read , to_write ;
481+ struct btrfs_key key ;
482+ struct btrfs_file_extent_item stack_fi = { 0 };
483+
484+ to_read = min (file_pos + MAX_EXTENT_SIZE , source -> size ) - file_pos ;
485+
486+ bytes_read = 0 ;
487+
488+ while (bytes_read < to_read ) {
489+ ssize_t ret_read ;
490+
491+ ret_read = pread (source -> fd , source -> buf + bytes_read ,
492+ to_read - bytes_read , file_pos + bytes_read );
493+ if (ret_read < 0 ) {
494+ error ("cannot read %s at offset %llu length %llu: %m" ,
495+ source -> path_name , file_pos + bytes_read ,
496+ to_read - bytes_read );
497+ return - errno ;
498+ }
499+
500+ bytes_read += ret_read ;
501+ }
502+
503+ to_write = round_up (to_read , sectorsize );
504+ memset (source -> buf + to_read , 0 , to_write - to_read );
505+
506+ ret = btrfs_reserve_extent (trans , root , to_write , 0 , 0 ,
507+ (u64 )- 1 , & key , 1 );
508+ if (ret )
509+ return ret ;
510+
511+ first_block = key .objectid ;
512+
513+ ret = write_data_to_disk (root -> fs_info , source -> buf , first_block ,
514+ to_write );
515+ if (ret ) {
516+ error ("failed to write %s" , source -> path_name );
517+ return ret ;
518+ }
519+
520+ for (unsigned int i = 0 ; i < to_write / sectorsize ; i ++ ) {
521+ ret = btrfs_csum_file_block (trans , first_block + (i * sectorsize ),
522+ BTRFS_EXTENT_CSUM_OBJECTID ,
523+ root -> fs_info -> csum_type ,
524+ source -> buf + (i * sectorsize ));
525+ if (ret )
526+ return ret ;
527+ }
528+
529+ btrfs_set_stack_file_extent_type (& stack_fi , BTRFS_FILE_EXTENT_REG );
530+ btrfs_set_stack_file_extent_disk_bytenr (& stack_fi , first_block );
531+ btrfs_set_stack_file_extent_disk_num_bytes (& stack_fi , to_write );
532+ btrfs_set_stack_file_extent_num_bytes (& stack_fi , to_write );
533+ btrfs_set_stack_file_extent_ram_bytes (& stack_fi , to_write );
534+ ret = insert_reserved_file_extent (trans , root , objectid , btrfs_inode ,
535+ file_pos , & stack_fi );
536+ if (ret )
537+ return ret ;
538+
539+ return to_read ;
540+ }
541+
458542static int add_file_items (struct btrfs_trans_handle * trans ,
459543 struct btrfs_root * root ,
460544 struct btrfs_inode_item * btrfs_inode , u64 objectid ,
@@ -463,15 +547,10 @@ static int add_file_items(struct btrfs_trans_handle *trans,
463547 struct btrfs_fs_info * fs_info = trans -> fs_info ;
464548 int ret = -1 ;
465549 ssize_t ret_read ;
466- u64 bytes_read = 0 ;
467- struct btrfs_key key ;
468- int blocks ;
469550 u32 sectorsize = fs_info -> sectorsize ;
470- u64 first_block = 0 ;
471551 u64 file_pos = 0 ;
472- u64 cur_bytes ;
473- u64 total_bytes ;
474- void * buf = NULL ;
552+ char * buf = NULL ;
553+ struct source_descriptor source ;
475554 int fd ;
476555
477556 if (st -> st_size == 0 )
@@ -483,10 +562,6 @@ static int add_file_items(struct btrfs_trans_handle *trans,
483562 return ret ;
484563 }
485564
486- blocks = st -> st_size / sectorsize ;
487- if (st -> st_size % sectorsize )
488- blocks += 1 ;
489-
490565 if (st -> st_size <= BTRFS_MAX_INLINE_DATA_SIZE (fs_info ) &&
491566 st -> st_size < sectorsize ) {
492567 char * buffer = malloc (st -> st_size );
@@ -496,10 +571,10 @@ static int add_file_items(struct btrfs_trans_handle *trans,
496571 goto end ;
497572 }
498573
499- ret_read = pread (fd , buffer , st -> st_size , bytes_read );
574+ ret_read = pread (fd , buffer , st -> st_size , 0 );
500575 if (ret_read == -1 ) {
501- error ("cannot read %s at offset %llu length %llu : %m" ,
502- path_name , bytes_read , ( unsigned long long ) st -> st_size );
576+ error ("cannot read %s at offset %u length %zu : %m" ,
577+ path_name , 0 , st -> st_size );
503578 free (buffer );
504579 goto end ;
505580 }
@@ -512,78 +587,26 @@ static int add_file_items(struct btrfs_trans_handle *trans,
512587 goto end ;
513588 }
514589
515- /* round up our st_size to the FS blocksize */
516- total_bytes = (u64 )blocks * sectorsize ;
517-
518- buf = malloc (sectorsize );
590+ buf = malloc (MAX_EXTENT_SIZE );
519591 if (!buf ) {
520592 ret = - ENOMEM ;
521593 goto end ;
522594 }
523595
524- again :
525-
526- /*
527- * keep our extent size at 1MB max, this makes it easier to work inside
528- * the tiny block groups created during mkfs
529- */
530- cur_bytes = min (total_bytes , (u64 )SZ_1M );
531- ret = btrfs_reserve_extent (trans , root , cur_bytes , 0 , 0 , (u64 )- 1 ,
532- & key , 1 );
533- if (ret )
534- goto end ;
535-
536- first_block = key .objectid ;
537- bytes_read = 0 ;
538-
539- while (bytes_read < cur_bytes ) {
596+ source .fd = fd ;
597+ source .buf = buf ;
598+ source .size = st -> st_size ;
599+ source .path_name = path_name ;
540600
541- memset (buf , 0 , sectorsize );
601+ while (file_pos < st -> st_size ) {
602+ ret = add_file_item_extent (trans , root , btrfs_inode , objectid ,
603+ & source , file_pos );
604+ if (ret < 0 )
605+ break ;
542606
543- ret_read = pread (fd , buf , sectorsize , file_pos + bytes_read );
544- if (ret_read == -1 ) {
545- error ("cannot read %s at offset %llu length %u: %m" ,
546- path_name , file_pos + bytes_read , sectorsize );
547- goto end ;
548- }
549-
550- ret = write_data_to_disk (root -> fs_info , buf ,
551- first_block + bytes_read , sectorsize );
552- if (ret ) {
553- error ("failed to write %s" , path_name );
554- goto end ;
555- }
556-
557- ret = btrfs_csum_file_block (trans , first_block + bytes_read ,
558- BTRFS_EXTENT_CSUM_OBJECTID ,
559- fs_info -> csum_type , buf );
560- if (ret )
561- goto end ;
562-
563- bytes_read += sectorsize ;
607+ file_pos += ret ;
564608 }
565609
566- if (bytes_read ) {
567- struct btrfs_file_extent_item stack_fi = { 0 };
568-
569- btrfs_set_stack_file_extent_type (& stack_fi , BTRFS_FILE_EXTENT_REG );
570- btrfs_set_stack_file_extent_disk_bytenr (& stack_fi , first_block );
571- btrfs_set_stack_file_extent_disk_num_bytes (& stack_fi , cur_bytes );
572- btrfs_set_stack_file_extent_num_bytes (& stack_fi , cur_bytes );
573- btrfs_set_stack_file_extent_ram_bytes (& stack_fi , cur_bytes );
574- ret = insert_reserved_file_extent (trans , root , objectid ,
575- btrfs_inode , file_pos , & stack_fi );
576- if (ret )
577- goto end ;
578-
579- }
580-
581- file_pos += cur_bytes ;
582- total_bytes -= cur_bytes ;
583-
584- if (total_bytes )
585- goto again ;
586-
587610end :
588611 free (buf );
589612 close (fd );
0 commit comments