6
6
* Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8
8
* This is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License version 2.1, as published by the Free Software
9
* modify it under the terms of the GNU General Public
10
* License version 2, as published by the Free Software
11
11
* Foundation. See file COPYING.
15
#define __STDC_FORMAT_MACROS
15
16
#include "config.h"
17
18
#include "common/common_init.h"
159
static uint64_t get_pos_in_block(rbd_obj_header_ondisk *header, uint64_t ofs)
161
int obj_order = header->options.order;
162
uint64_t mask = (1 << obj_order) - 1;
166
static uint64_t bounded_pos_in_block(rbd_obj_header_ondisk *header, uint64_t end_ofs, unsigned int i)
168
int obj_order = header->options.order;
169
if (end_ofs >> obj_order > i)
170
return (1 << obj_order);
171
return get_pos_in_block(header, end_ofs);
151
174
void trim_image(pools_t& pp, const char *imgname, rbd_obj_header_ondisk *header, uint64_t newsize)
627
650
for (uint64_t i = 0; i < numseg; i++) {
629
652
string oid = get_block_oid(&header, i);
630
r = rados.read(pp.data, oid, 0, bl, block_size);
653
map<off_t, size_t> m;
654
map<off_t, size_t>::iterator iter;
656
r = rados.sparse_read(pp.data, oid, 0, block_size, m, bl);
631
657
if (r < 0 && r == -ENOENT)
639
ret = lseek64(fd, pos, SEEK_SET);
664
for (iter = m.begin(); iter != m.end(); ++iter) {
665
off_t extent_ofs = iter->first;
666
size_t extent_len = iter->second;
667
ret = lseek64(fd, pos + extent_ofs, SEEK_SET);
642
670
cerr << "could not seek to pos " << pos << std::endl;
645
ret = write(fd, bl.c_str(), bl.length());
673
if (bl_ofs + extent_len > bl.length()) {
674
cerr << "data error!" << std::endl;
677
ret = write(fd, bl.c_str() + bl_ofs, extent_len);
680
bl_ofs += extent_len;
650
683
pos += block_size;
769
uint64_t numseg = get_max_block(&header);
770
uint64_t seg_pos = 0;
771
for (uint64_t i=0; i<numseg; i++) {
772
uint64_t seg_size = min(size - seg_pos, block_size);
773
uint64_t seg_left = seg_size;
776
uint64_t len = min(seg_left, block_size);
778
len = read(fd, p.c_str(), len);
781
cerr << "error reading file\n" << std::endl;
786
string oid = get_block_oid(&header, i);
787
r = rados.write(pool, oid, 0, bl, len);
789
cerr << "error writing to image block" << std::endl;
803
fiemap = read_fiemap(fd);
805
fiemap = (struct fiemap *)malloc(sizeof(struct fiemap) + sizeof(struct fiemap_extent));
807
cerr << "Failed to allocate fiemap, not enough memory." << std::endl;
810
fiemap->fm_start = 0;
811
fiemap->fm_length = size;
812
fiemap->fm_flags = 0;
813
fiemap->fm_extent_count = 1;
814
fiemap->fm_mapped_extents = 1;
815
fiemap->fm_extents[0].fe_logical = 0;
816
fiemap->fm_extents[0].fe_physical = 0;
817
fiemap->fm_extents[0].fe_length = size;
818
fiemap->fm_extents[0].fe_flags = 0;
823
while (extent < fiemap->fm_mapped_extents) {
824
uint64_t start_block, end_block;
825
off_t file_pos, end_ofs;
826
size_t extent_len = 0;
828
file_pos = fiemap->fm_extents[extent].fe_logical; /* position within the file we're reading */
829
start_block = get_block_num(&header, file_pos); /* starting block */
831
do { /* try to merge consecutive extents */
832
#define LARGE_ENOUGH_EXTENT (32 * 1024 * 1024)
834
extent_len + fiemap->fm_extents[extent].fe_length > LARGE_ENOUGH_EXTENT)
835
break; /* don't try to merge if we're big enough */
837
extent_len += fiemap->fm_extents[extent].fe_length; /* length of current extent */
838
end_ofs = MIN(size, file_pos + extent_len);
840
end_block = get_block_num(&header, end_ofs - 1); /* ending block */
843
if (extent == fiemap->fm_mapped_extents)
846
} while (end_ofs == (off_t)fiemap->fm_extents[extent].fe_logical);
848
cerr << "rbd import file_pos=" << file_pos << " extent_len=" << extent_len << std::endl;
849
for (uint64_t i = start_block; i <= end_block; i++) {
850
uint64_t ofs_in_block = get_pos_in_block(&header, file_pos); /* the offset within the starting block */
851
uint64_t seg_size = bounded_pos_in_block(&header, end_ofs, i) - ofs_in_block;
852
uint64_t seg_left = seg_size;
854
cerr << "i=" << i << " (" << start_block << "/" << end_block << ") "
855
<< "seg_size=" << seg_size << " seg_left=" << seg_left << std::endl;
857
uint64_t len = seg_left;
859
cerr << "reading " << len << " bytes at offset " << file_pos << std::endl;
860
len = pread(fd, p.c_str(), len, file_pos);
863
cerr << "error reading file\n" << std::endl;
868
string oid = get_block_oid(&header, i);
869
cerr << "writing " << len << " bytes at offset " << ofs_in_block << " at block " << oid << std::endl;
870
r = rados.write(pool, oid, ofs_in_block, bl, len);
872
cerr << "error writing to image block" << std::endl;
802
891
static int do_copy(pools_t& pp, const char *imgname, const char *destname)
835
924
for (uint64_t i = 0; i < numseg; i++) {
837
926
string oid = get_block_oid(&header, i);
838
r = rados.read(pp.data, oid, 0, bl, block_size);
927
string dest_oid = get_block_oid(&dest_header, i);
928
map<off_t, size_t> m;
929
map<off_t, size_t>::iterator iter;
930
r = rados.sparse_read(pp.data, oid, 0, block_size, m, bl);
839
931
if (r < 0 && r == -ENOENT)
845
string dest_oid = get_block_oid(&dest_header, i);
846
r = rados.write(pp.dest, dest_oid, 0, bl, bl.length());
848
cerr << "failed to write block " << dest_oid << std::endl;
937
for (iter = m.begin(); iter != m.end(); ++iter) {
938
off_t extent_ofs = iter->first;
939
size_t extent_len = iter->second;
941
if (extent_ofs + extent_len > bl.length()) {
942
cerr << "data error!" << std::endl;
945
bl.copy(extent_ofs, extent_len, wrbl);
946
r = rados.write(pp.dest, dest_oid, extent_ofs, wrbl, extent_len);
857
957
static void err_exit(pools_t& pp)