~ubuntu-branches/ubuntu/precise/ceph/precise

« back to all changes in this revision

Viewing changes to src/rbd.cc

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum, Clint Byrum, Micah Gersten
  • Date: 2011-02-12 22:50:26 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110212225026-yyyw4tk0msgql3ul
Tags: 0.24.2-0ubuntu1
[ Clint Byrum <clint@ubuntu.com> ]
* New upstream release. (LP: #658670, LP: #684011)
* debian/patches/fix-mkcephfs.patch: dropped (applied upstream)
* Removed .la files from libceph1-dev, libcrush1-dev and 
  librados1-dev (per Debian policy v3.9.1 10.2).
* debian/control: adding pkg-config as a build dependency
* debian/control: depend on libcrypto++-dev instead of libssl-dev
* debian/watch: added watch file

[ Micah Gersten <micahg@ubuntu.com> ]
* debian/control: add Homepage

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7
7
 *
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.
12
 
 * 
 
12
 *
13
13
 */
14
14
 
 
15
#define __STDC_FORMAT_MACROS
15
16
#include "config.h"
16
17
 
17
18
#include "common/common_init.h"
19
20
using namespace librados;
20
21
#include "include/byteorder.h"
21
22
 
 
23
#include "include/intarith.h"
22
24
 
 
25
#include <errno.h>
 
26
#include <inttypes.h>
23
27
#include <iostream>
24
 
 
25
28
#include <stdlib.h>
 
29
#include <sys/types.h>
26
30
#include <time.h>
27
 
#include <sys/types.h>
28
 
#include <errno.h>
 
31
 
 
32
#include <sys/ioctl.h>
29
33
 
30
34
#include "include/rbd_types.h"
31
35
 
 
36
#include <linux/fs.h>
 
37
 
 
38
#include "include/fiemap.h"
 
39
 
32
40
struct pools {
33
41
  pool_t md;
34
42
  pool_t data;
121
129
static string get_block_oid(rbd_obj_header_ondisk *header, uint64_t num)
122
130
{
123
131
  char o[RBD_MAX_SEG_NAME_SIZE];
124
 
  sprintf(o, "%s.%012llx", header->block_name, (unsigned long long)num);
 
132
  snprintf(o, RBD_MAX_SEG_NAME_SIZE,
 
133
           "%s.%012" PRIx64, header->block_name, num);
125
134
  return o;
126
135
}
127
136
 
147
156
 
148
157
  return num;
149
158
}
 
159
static uint64_t get_pos_in_block(rbd_obj_header_ondisk *header, uint64_t ofs)
 
160
{
 
161
  int obj_order = header->options.order;
 
162
  uint64_t mask = (1 << obj_order) - 1;
 
163
  return ofs & mask;
 
164
}
 
165
 
 
166
static uint64_t bounded_pos_in_block(rbd_obj_header_ondisk *header, uint64_t end_ofs, unsigned int i)
 
167
{
 
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);
 
172
}
150
173
 
151
174
void trim_image(pools_t& pp, const char *imgname, rbd_obj_header_ondisk *header, uint64_t newsize)
152
175
{
627
650
  for (uint64_t i = 0; i < numseg; i++) {
628
651
    bufferlist bl;
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;
 
655
    off_t bl_ofs = 0;
 
656
    r = rados.sparse_read(pp.data, oid, 0, block_size, m, bl);
631
657
    if (r < 0 && r == -ENOENT)
632
658
      r = 0;
633
659
    if (r < 0) {
635
661
      goto done;
636
662
    }
637
663
 
638
 
    if (bl.length()) {
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);
640
668
      if (ret < 0) {
641
669
        ret = -errno;
642
670
        cerr << "could not seek to pos " << pos << std::endl;
643
671
        goto done;
644
672
      }
645
 
      ret = write(fd, bl.c_str(), bl.length());
 
673
      if (bl_ofs + extent_len > bl.length()) {
 
674
        cerr << "data error!" << std::endl;
 
675
        return -EIO;
 
676
      }
 
677
      ret = write(fd, bl.c_str() + bl_ofs, extent_len);
646
678
      if (ret < 0)
647
679
        goto done;
 
680
      bl_ofs += extent_len;
648
681
    }
649
682
 
650
683
    pos += block_size;
730
763
  uint64_t block_size;
731
764
  struct stat stat_buf;
732
765
  string md_oid;
 
766
  struct fiemap *fiemap;
733
767
 
734
768
  if (fd < 0) {
735
769
    r = -errno;
766
800
    return r;
767
801
  }
768
802
 
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;
774
 
 
775
 
    while (seg_left) {
776
 
      uint64_t len = min(seg_left, block_size);
777
 
      bufferptr p(len);
778
 
      len = read(fd, p.c_str(), len);
779
 
      if (len < 0) {
780
 
        r = -errno;
781
 
        cerr << "error reading file\n" << std::endl;
782
 
        return r;
783
 
      }
784
 
      bufferlist bl;
785
 
      bl.append(p);
786
 
      string oid = get_block_oid(&header, i);
787
 
      r = rados.write(pool, oid, 0, bl, len);
788
 
      if (r < 0) {
789
 
        cerr << "error writing to image block" << std::endl;
790
 
        return r;
791
 
      }
792
 
 
793
 
      seg_left -= len;
794
 
    }
795
 
 
796
 
    seg_pos += seg_size;
797
 
  }
798
 
 
799
 
  return 0;
 
803
  fiemap = read_fiemap(fd);
 
804
  if (!fiemap) {
 
805
    fiemap = (struct fiemap *)malloc(sizeof(struct fiemap) +  sizeof(struct fiemap_extent));
 
806
    if (!fiemap) {
 
807
      cerr << "Failed to allocate fiemap, not enough memory." << std::endl;
 
808
      return -ENOMEM;
 
809
    }
 
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;
 
819
  }
 
820
 
 
821
  uint64_t extent = 0;
 
822
 
 
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;
 
827
 
 
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 */
 
830
 
 
831
    do { /* try to merge consecutive extents */
 
832
#define LARGE_ENOUGH_EXTENT (32 * 1024 * 1024)
 
833
      if (extent_len &&
 
834
          extent_len + fiemap->fm_extents[extent].fe_length > LARGE_ENOUGH_EXTENT)
 
835
        break; /* don't try to merge if we're big enough */
 
836
 
 
837
      extent_len += fiemap->fm_extents[extent].fe_length;  /* length of current extent */
 
838
      end_ofs = MIN(size, file_pos + extent_len);
 
839
 
 
840
      end_block = get_block_num(&header, end_ofs - 1); /* ending block */
 
841
 
 
842
      extent++;
 
843
      if (extent == fiemap->fm_mapped_extents)
 
844
        break;
 
845
      
 
846
    } while (end_ofs == (off_t)fiemap->fm_extents[extent].fe_logical);
 
847
 
 
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;
 
853
 
 
854
      cerr << "i=" << i << " (" << start_block << "/" << end_block << ") "
 
855
           << "seg_size=" << seg_size << " seg_left=" << seg_left << std::endl;
 
856
      while (seg_left) {
 
857
        uint64_t len = seg_left;
 
858
        bufferptr p(len);
 
859
        cerr << "reading " << len << " bytes at offset " << file_pos << std::endl;
 
860
        len = pread(fd, p.c_str(), len, file_pos);
 
861
        if (len < 0) {
 
862
          r = -errno;
 
863
          cerr << "error reading file\n" << std::endl;
 
864
          goto done;
 
865
        }
 
866
        bufferlist bl;
 
867
        bl.append(p);
 
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);
 
871
        if (r < 0) {
 
872
          cerr << "error writing to image block" << std::endl;
 
873
          goto done;
 
874
        }
 
875
 
 
876
        seg_left -= len;
 
877
        file_pos += len;
 
878
        ofs_in_block += len;
 
879
      }
 
880
    }
 
881
  }
 
882
 
 
883
  r = 0;
 
884
 
 
885
done:
 
886
  free(fiemap);
 
887
 
 
888
  return r;
800
889
}
801
890
 
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++) {
836
925
    bufferlist bl;
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)
840
932
      r = 0;
841
933
    if (r < 0)
842
934
      return r;
843
935
 
844
 
    if (bl.length()) {
845
 
      string dest_oid = get_block_oid(&dest_header, i);
846
 
      r = rados.write(pp.dest, dest_oid, 0, bl, bl.length());
847
 
      if (r < 0) {
848
 
        cerr << "failed to write block " << dest_oid << std::endl;
849
 
        return r;
 
936
 
 
937
    for (iter = m.begin(); iter != m.end(); ++iter) {
 
938
      off_t extent_ofs = iter->first;
 
939
      size_t extent_len = iter->second;
 
940
      bufferlist wrbl;
 
941
      if (extent_ofs + extent_len > bl.length()) {
 
942
        cerr << "data error!" << std::endl;
 
943
        return -EIO;
850
944
      }
 
945
      bl.copy(extent_ofs, extent_len, wrbl);
 
946
      r = rados.write(pp.dest, dest_oid, extent_ofs, wrbl, extent_len);
 
947
      if (r < 0)
 
948
        goto done;
851
949
    }
852
950
  }
 
951
  r = 0;
853
952
 
854
 
  return 0;
 
953
done:
 
954
  return r;
855
955
}
856
956
 
857
957
static void err_exit(pools_t& pp)