From: Sage Weil Date: Fri, 18 Sep 2009 19:45:48 +0000 (-0700) Subject: kclient: add GET_DATALOC ioctl to get object location, osd addr X-Git-Tag: v0.15~32 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=dbfb0f0debc4dac00c220a3d6c10324f3a4d79f5;p=ceph.git kclient: add GET_DATALOC ioctl to get object location, osd addr --- diff --git a/src/Makefile.am b/src/Makefile.am index c737b5589d3..eb3a40c724c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/TODO b/src/TODO index 5ef3a3fdff0..490d5e4592f 100644 --- 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 index 00000000000..93b9bcc4d4e --- /dev/null +++ b/src/client/test_ioctls.c @@ -0,0 +1,66 @@ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 \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; +} diff --git a/src/kernel/import_patch_set_into_linux_git.sh b/src/kernel/import_patch_set_into_linux_git.sh index 402e1dd78a5..615a791f1fc 100755 --- a/src/kernel/import_patch_set_into_linux_git.sh +++ b/src/kernel/import_patch_set_into_linux_git.sh @@ -321,7 +321,8 @@ git commit -s -F - < + #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; } diff --git a/src/kernel/ioctl.h b/src/kernel/ioctl.h index 56f5e2c318d..d954c6ae76b 100644 --- a/src/kernel/ioctl.h +++ b/src/kernel/ioctl.h @@ -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