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
/- 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?
--- /dev/null
+
+#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;
+}
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
+#include <linux/in.h>
+
#include "ioctl.h"
#include "super.h"
#include "ceph_debug.h"
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);
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;
}
#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