]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: add GET_DATALOC ioctl to get object location, osd addr
authorSage Weil <sage@newdream.net>
Fri, 18 Sep 2009 19:45:48 +0000 (12:45 -0700)
committerSage Weil <sage@newdream.net>
Fri, 18 Sep 2009 19:45:48 +0000 (12:45 -0700)
src/Makefile.am
src/TODO
src/client/test_ioctls.c [new file with mode: 0644]
src/kernel/import_patch_set_into_linux_git.sh
src/kernel/ioctl.c
src/kernel/ioctl.h

index c737b5589d3255e1f2fe05abe653fbd2dfbacdb1..eb3a40c724c5210be79c2fa13efc37cb0873f296 100644 (file)
@@ -61,6 +61,9 @@ testmsgr_SOURCES = testmsgr.cc msg/SimpleMessenger.cc
 testmsgr_LDADD = libcommon.a
 bin_PROGRAMS += testmsgr
 
+test_ioctls_SOURCES = client/test_ioctls.c
+bin_PROGRAMS += test_ioctls
+
 # fuse targets?
 if WITH_FUSE
 cfuse_SOURCES = cfuse.cc msg/SimpleMessenger.cc client/fuse.cc client/fuse_ll.cc
index 5ef3a3fdff0f70536680e7d028c3924048303b01..490d5e4592faed6e42cd5b8e8a4c8908488fb842 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -4,13 +4,12 @@ v0.15
 /- monclient fixes; ceph detects monitor session drop
 /- msgr: protocol check cleanups; ack seq # fix; 
 /- debian: radosgw package, fix header perms
+/- kclient: GET_DATALOC ioctl
 
 - kclient: retry alloc on ENOMEM when reading from connection?
 - client authentication
-
 - mds: put migration vectors in mdsmap
 
-
 bugs
 - premature filejournal trimming?
 - weird osd_lock contention during osd restart?
diff --git a/src/client/test_ioctls.c b/src/client/test_ioctls.c
new file mode 100644 (file)
index 0000000..93b9bcc
--- /dev/null
@@ -0,0 +1,66 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+
+#include "../kernel/ioctl.h"
+
+#define IPQUADPORT(n)                                                  \
+       (unsigned int)((ntohl((n).sin_addr.s_addr) >> 24)) & 0xFF, \
+       (unsigned int)((ntohl((n).sin_addr.s_addr)) >> 16) & 0xFF, \
+       (unsigned int)((ntohl((n).sin_addr.s_addr))>>8) & 0xFF, \
+       (unsigned int)((ntohl((n).sin_addr.s_addr))) & 0xFF, \
+       (unsigned int)(ntohs((n).sin_port))
+
+int main(int argc, char **argv)
+{
+       char *fn;
+       int fd, err;
+       struct ceph_ioctl_layout l;
+       struct ceph_ioctl_dataloc dl;
+
+       if (argc < 3) {
+               printf("usage: test_ioctls <filename> <offset>\n");
+               return 1;
+       }
+       fn = argv[1];
+
+       fd = open(fn, O_CREAT|O_RDWR);
+       if (fd < 0) {
+               perror("couldn't open file");
+               return 1;
+       }
+       printf("file %s\n", fn);
+
+       /* get layout */
+       err = ioctl(fd, CEPH_IOC_GET_LAYOUT, (unsigned long)&l);
+       if (err < 0) {
+               perror("ioctl IOC_GET_LAYOUT error");
+               return 1;
+       }
+       printf("layout:\n stripe_unit %lld\n stripe_count %lld\n object_size %lld\n data_pool %lld\n",
+              l.stripe_unit, l.stripe_count, l.object_size, l.data_pool);
+
+       /* dataloc */
+       dl.file_offset = atoll(argv[2]);
+       err = ioctl(fd, CEPH_IOC_GET_DATALOC, (unsigned long)&dl);
+       if (err < 0) {
+               perror("ioctl IOC_GET_DATALOC error");
+               return 1;
+       }
+
+       printf("dataloc: file_offset %lld\n", dl.file_offset);
+       printf(" object_offset %lld\n object_size %lld object_no %lld\n",
+              dl.object_offset, dl.object_size, dl.object_no);
+       printf(" block_offset %lld\n block_size %lld\n",
+              dl.block_offset, dl.block_size);
+       printf(" osd%lld %u.%u.%u.%u:%u\n", dl.osd, IPQUADPORT(dl.osd_addr));
+
+       return 0;       
+}
index 402e1dd78a551eb0cee3f94043579a6f817a7340..615a791f1fc1667fad22a9cacf1e159e2f7ba126 100755 (executable)
@@ -321,7 +321,8 @@ git commit -s -F - <<EOF
 ceph: ioctls
 
 A few Ceph ioctls for getting and setting file layout (striping)
-parameters.
+parameters, and learning the identity and network address of the OSD a
+given region of a file is stored on.
 
 EOF
 
index 0abc2763046e912a5016dbd42b3c5c7010ea664c..f6278933b7b98dfd865866c2c52affcc86cb603f 100644 (file)
@@ -1,3 +1,5 @@
+#include <linux/in.h>
+
 #include "ioctl.h"
 #include "super.h"
 #include "ceph_debug.h"
@@ -84,6 +86,55 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
        return err;
 }
 
+static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
+{
+       struct ceph_ioctl_dataloc dl;
+       struct inode *inode = file->f_dentry->d_inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_osd_client *osdc = &ceph_client(inode->i_sb)->osdc;
+       u64 len = 1, olen;
+       u64 tmp;
+       char oid[80];
+       struct ceph_object_layout ol;
+       union ceph_pg pgid;
+
+       /* copy and validate */
+       if (copy_from_user(&dl, arg, sizeof(dl)))
+               return -EFAULT;
+
+       down_read(&osdc->map_sem);
+       ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, &len,
+                                     &dl.object_no, &dl.object_offset, &olen);
+       dl.file_offset -= dl.object_offset;
+       dl.object_size = ceph_file_layout_object_size(ci->i_layout);
+       dl.block_size = ceph_file_layout_su(ci->i_layout);
+
+       /* block_offset = object_offset % block_size */
+       tmp = dl.object_offset;
+       dl.block_offset = do_div(tmp, dl.block_size);
+
+       sprintf(oid, "%llx.%08llx", ceph_ino(inode), dl.object_no);
+       ceph_calc_object_layout(&ol, oid, &ci->i_layout, osdc->osdmap);
+
+       pgid.pg64 = le64_to_cpu(ol.ol_pgid);
+       dl.osd = ceph_calc_pg_primary(osdc->osdmap, pgid);
+       if (dl.osd >= 0) {
+               struct ceph_entity_addr *a =
+                       ceph_osd_addr(osdc->osdmap, dl.osd);
+               if (a)
+                       memcpy(&dl.osd_addr, &a->ipaddr, sizeof(dl.osd_addr));
+       } else {
+               memset(&dl.osd_addr, 0, sizeof(dl.osd_addr));
+       }
+       up_read(&osdc->map_sem);
+
+       /* send result back to user */
+       if (copy_to_user(arg, &dl, sizeof(dl)))
+               return -EFAULT;
+
+       return 0;
+}
+
 long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        dout("ioctl file %p cmd %u arg %lu\n", file, cmd, arg);
@@ -93,6 +144,9 @@ long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        case CEPH_IOC_SET_LAYOUT:
                return ceph_ioctl_set_layout(file, (void __user *)arg);
+
+       case CEPH_IOC_GET_DATALOC:
+               return ceph_ioctl_get_dataloc(file, (void __user *)arg);
        }
        return -ENOTTY;
 }
index 56f5e2c318dd9c2111b7d462cc0b71c6e106f453..d954c6ae76b8486a4f00c3f1915716f74406f79e 100644 (file)
@@ -17,4 +17,21 @@ struct ceph_ioctl_layout {
 #define CEPH_IOC_SET_LAYOUT _IOW(CEPH_IOCTL_MAGIC, 2,          \
                                   struct ceph_ioctl_layout)
 
+/*
+ * Extract identity, address of the OSD storing a given file offset.
+ */
+struct ceph_ioctl_dataloc {
+       __u64 file_offset;           /* in+out: file offset */
+       __u64 object_offset;         /* out: offset in object */
+       __u64 object_no;             /* out: object # */
+       __u64 object_size;           /* out: object size */
+       __u64 block_offset;          /* out: offset in block */
+       __u64 block_size;            /* out: block length */
+       __s64 osd;                   /* out: osd # */
+       struct sockaddr_in osd_addr; /* out: osd address */
+};
+
+#define CEPH_IOC_GET_DATALOC _IOWR(CEPH_IOCTL_MAGIC, 3,        \
+                                  struct ceph_ioctl_dataloc)
+
 #endif