]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: expose extent/osd mapping
authorNoah Watkins <noahwatkins@gmail.com>
Fri, 22 Feb 2013 23:46:02 +0000 (15:46 -0800)
committerNoah Watkins <noahwatkins@gmail.com>
Wed, 6 Mar 2013 00:04:55 +0000 (16:04 -0800)
Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
src/client/Client.cc
src/client/Client.h
src/include/cephfs/libcephfs.h
src/libcephfs.cc
src/test/libcephfs/test.cc

index d5ff08ba55d2113003cb81e146362b138fd2579e..d8ba59adb600018e221550ea82a4a73a2bdcfbeb 100644 (file)
@@ -7530,6 +7530,46 @@ int Client::get_pool_replication(int64_t pool)
   return osdmap->get_pg_pool(pool)->get_size();
 }
 
+int Client::get_file_extent_osds(int fd, loff_t off, loff_t *len, vector<int>& osds)
+{
+  Mutex::Locker lock(client_lock);
+
+  Fh *f = get_filehandle(fd);
+  if (!f)
+    return -EBADF;
+  Inode *in = f->inode;
+
+  vector<ObjectExtent> extents;
+  Striper::file_to_extents(cct, in->ino, &in->layout, off, 1, extents);
+  assert(extents.size() == 1);
+
+  pg_t pg = osdmap->object_locator_to_pg(extents[0].oid, extents[0].oloc);
+  osdmap->pg_to_acting_osds(pg, osds);
+  if (osds.empty())
+    return -EINVAL;
+
+  /*
+   * Return the remainder of the extent (stripe unit)
+   *
+   * If length = 1 is passed to Striper::file_to_extents we get a single
+   * extent back, but its length is one so we still need to compute the length
+   * to the end of the stripe unit.
+   *
+   * If length = su then we may get 1 or 2 objects back in the extents vector
+   * which would have to be examined. Even then, the offsets are local to the
+   * object, so matching up to the file offset is extra work.
+   *
+   * It seems simpler to stick with length = 1 and manually compute the
+   * remainder.
+   */
+  if (len) {
+    uint64_t su = in->layout.fl_stripe_unit;
+    *len = su - (off % su);
+  }
+
+  return 0;
+}
+
 int Client::get_file_stripe_address(int fd, loff_t offset, vector<entity_addr_t>& address)
 {
   Mutex::Locker lock(client_lock);
index 8846e3f9ad72b3209c92afee8478fd0ebcfa88b3..b0dd069bbe55eee295c367ad27c1fbd24c1ef439 100644 (file)
@@ -666,6 +666,7 @@ public:
   // expose file layout
   int describe_layout(int fd, ceph_file_layout* layout);
   int get_file_stripe_address(int fd, loff_t offset, vector<entity_addr_t>& address);
+  int get_file_extent_osds(int fd, loff_t off, loff_t *len, vector<int>& osds);
 
   // expose osdmap 
   int get_local_osd();
index abfd25cfd7e9d4f19063e290ff37e6ed2e2e6657..afad8cf1e3d3aac6102425fef7fdf6e96bc706d7 100644 (file)
@@ -896,6 +896,22 @@ int ceph_get_pool_replication(struct ceph_mount_info *cmount, int pool_id);
 int ceph_get_file_stripe_address(struct ceph_mount_info *cmount, int fd, loff_t offset,
                                 struct sockaddr_storage *addr, int naddr);
 
+/**
+ * Get the list of OSDs where the objects containing a file offset are located.
+ *
+ * @param cmount the ceph mount handle to use.
+ * @param fd the open file descriptor referring to the file.
+ * @param offset the offset within the file.
+ * @param length return the number of bytes between the offset and the end of
+ * the stripe unit (optional).
+ * @param osds an integer array to hold the OSD ids.
+ * @param nosds the size of the integer array.
+ * @returns the number of items stored in the output array, or -ERANGE if the
+ * array is not large enough.
+ */
+int ceph_get_file_extent_osds(struct ceph_mount_info *cmount, int fh,
+                              loff_t offset, loff_t *length, int *osds, int nosds);
+
 /**
  * Get the file layout stripe unit granularity.
  * @param cmount the ceph mount handle.
index d2fe0dac861b0f2d6c3df34713bbff491b9bcd87..0c77125fb50ba2411319b0363a99b76066c77658 100644 (file)
@@ -790,6 +790,32 @@ extern "C" int ceph_set_default_preferred_pg(struct ceph_mount_info *cmount, int
   return -EOPNOTSUPP;
 }
 
+extern "C" int ceph_get_file_extent_osds(struct ceph_mount_info *cmount, int fh,
+    loff_t offset, loff_t *length, int *osds, int nosds)
+{
+  if (nosds < 0)
+    return -EINVAL;
+
+  if (!cmount->is_mounted())
+    return -ENOTCONN;
+
+  vector<int> vosds;
+  int ret = cmount->get_client()->get_file_extent_osds(fh, offset, length, vosds);
+  if (ret < 0)
+    return ret;
+
+  if (!nosds)
+    return vosds.size();
+
+  if ((int)vosds.size() > nosds)
+    return -ERANGE;
+
+  for (int i = 0; i < (int)vosds.size(); i++)
+    osds[i] = vosds[i];
+
+  return vosds.size();
+}
+
 extern "C" int ceph_get_file_stripe_address(struct ceph_mount_info *cmount, int fh,
                                            loff_t offset, struct sockaddr_storage *addr, int naddr)
 {
index eaf38dba509a011e6acc2272465e9cdec9803a53..4afe01c32d05469726a9f02d8f4e37c12c367209 100644 (file)
@@ -930,3 +930,53 @@ TEST(LibCephFS, GetPoolReplication) {
 
   ceph_shutdown(cmount);
 }
+
+TEST(LibCephFS, GetExtentOsds) {
+  struct ceph_mount_info *cmount;
+  ASSERT_EQ(ceph_create(&cmount, NULL), 0);
+
+  EXPECT_EQ(-ENOTCONN, ceph_get_file_extent_osds(cmount, 0, 0, NULL, NULL, 0));
+
+  ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
+  ASSERT_EQ(ceph_mount(cmount, NULL), 0);
+
+  int stripe_unit = (1<<18);
+
+  /* make a file! */
+  char test_file[256];
+  sprintf(test_file, "test_extent_osds_%d", getpid());
+  int fd = ceph_open_layout(cmount, test_file, O_CREAT|O_RDWR, 0666,
+      stripe_unit, 2, stripe_unit*2, NULL);
+  ASSERT_GT(fd, 0);
+
+  /* get back how many osds > 0 */
+  int ret = ceph_get_file_extent_osds(cmount, fd, 0, NULL, NULL, 0);
+  EXPECT_GT(ret, 0);
+
+  loff_t len;
+  int osds[ret];
+
+  /* full stripe extent */
+  EXPECT_EQ(ret, ceph_get_file_extent_osds(cmount, fd, 0, &len, osds, ret));
+  EXPECT_EQ(len, (loff_t)stripe_unit);
+
+  /* half stripe extent */
+  EXPECT_EQ(ret, ceph_get_file_extent_osds(cmount, fd, stripe_unit/2, &len, osds, ret));
+  EXPECT_EQ(len, (loff_t)stripe_unit/2);
+
+  /* 1.5 stripe unit offset -1 byte */
+  EXPECT_EQ(ret, ceph_get_file_extent_osds(cmount, fd, 3*stripe_unit/2-1, &len, osds, ret));
+  EXPECT_EQ(len, (loff_t)stripe_unit/2+1);
+
+  /* 1.5 stripe unit offset +1 byte */
+  EXPECT_EQ(ret, ceph_get_file_extent_osds(cmount, fd, 3*stripe_unit/2+1, &len, osds, ret));
+  EXPECT_EQ(len, (loff_t)stripe_unit/2-1);
+
+  /* only when more than 1 osd */
+  if (ret > 1)
+    EXPECT_EQ(-ERANGE, ceph_get_file_extent_osds(cmount, fd, 0, NULL, osds, 1));
+
+  ceph_close(cmount, fd);
+
+  ceph_shutdown(cmount);
+}