From fba3ede848d35d91f76427d9b98894fdfe386330 Mon Sep 17 00:00:00 2001 From: John Spray Date: Thu, 18 Sep 2014 18:57:11 +0100 Subject: [PATCH] libcephfs: add ceph_mds_command Wraps the equivalent fn in Client. Signed-off-by: John Spray --- src/include/cephfs/libcephfs.h | 43 +++++++++++ src/libcephfs.cc | 130 +++++++++++++++++++++++++++++---- 2 files changed, 160 insertions(+), 13 deletions(-) diff --git a/src/include/cephfs/libcephfs.h b/src/include/cephfs/libcephfs.h index 282f41b4f9b45..ca386a9f652e5 100644 --- a/src/include/cephfs/libcephfs.h +++ b/src/include/cephfs/libcephfs.h @@ -150,9 +150,20 @@ int ceph_create(struct ceph_mount_info **cmount, const char * const id); */ int ceph_create_with_context(struct ceph_mount_info **cmount, struct CephContext *conf); +/** + * Initialize the filesystem client (but do not mount the filesystem yet) + * + * @returns 0 on success, negative error code on failure + */ +int ceph_init(struct ceph_mount_info *cmount); + + /** * Perform a mount using the path for the root of the mount. * + * It is optional to call ceph_init before this. If ceph_init has + * not already been called, it will be called in the course of this operation. + * * @param cmount the mount info handle * @param root the path for the root of the mount. This can be an existing * directory within the ceph cluster, but most likely it will @@ -161,6 +172,38 @@ int ceph_create_with_context(struct ceph_mount_info **cmount, struct CephContext */ int ceph_mount(struct ceph_mount_info *cmount, const char *root); + +/** + * Execute a management command remotely on an MDS. + * + * Must have called ceph_init or ceph_mount before calling this. + * + * @param mds_spec string representing rank, MDS name, GID or '*' + * @param cmd array of null-terminated strings + * @param cmdlen length of cmd array + * @param inbuf non-null-terminated input data to command + * @param inbuflen length in octets of inbuf + * @param outbuf populated with pointer to buffer (command output data) + * @param outbuflen length of allocated outbuf + * @param outs populated with pointer to buffer (command error strings) + * @param outslen length of allocated outs + * + * @return 0 on success, negative error code on failure + * + */ +int ceph_mds_command(struct ceph_mount_info *cmount, + const char *mds_spec, + const char **cmd, + size_t cmdlen, + const char *inbuf, size_t inbuflen, + char **outbuf, size_t *outbuflen, + char **outs, size_t *outslen); + +/** + * Free a buffer, such as those used for output arrays from ceph_mds_command + */ +void ceph_buffer_free(char *buf); + /** * Unmount a mount handle. * diff --git a/src/libcephfs.cc b/src/libcephfs.cc index 9fd050946cc92..871dbcfe2e38d 100644 --- a/src/libcephfs.cc +++ b/src/libcephfs.cc @@ -64,15 +64,12 @@ public: } } - int mount(const std::string &mount_root) + int init() { - int ret; - - if (mounted) - return -EISCONN; - common_init_finish(cct); + int ret; + //monmap monclient = new MonClient(cct); ret = -1000; @@ -97,19 +94,35 @@ public: goto fail; inited = true; - - ret = client->mount(mount_root); - if (ret) - goto fail; - - mounted = true; return 0; - fail: + fail: shutdown(); return ret; } + int mount(const std::string &mount_root) + { + int ret; + + if (mounted) + return -EISCONN; + + ret = init(); + if (ret != 0) { + return ret; + } + + ret = client->mount(mount_root); + if (ret) { + shutdown(); + return ret; + } else { + mounted = true; + return 0; + } + } + int unmount() { if (!mounted) @@ -144,6 +157,11 @@ public: } } + bool is_initialized() const + { + return inited; + } + bool is_mounted() { return mounted; @@ -225,6 +243,34 @@ private: std::string cwd; }; +static void do_out_buffer(bufferlist& outbl, char **outbuf, size_t *outbuflen) +{ + if (outbuf) { + if (outbl.length() > 0) { + *outbuf = (char *)malloc(outbl.length()); + memcpy(*outbuf, outbl.c_str(), outbl.length()); + } else { + *outbuf = NULL; + } + } + if (outbuflen) + *outbuflen = outbl.length(); +} + +static void do_out_buffer(string& outbl, char **outbuf, size_t *outbuflen) +{ + if (outbuf) { + if (outbl.length() > 0) { + *outbuf = (char *)malloc(outbl.length()); + memcpy(*outbuf, outbl.c_str(), outbl.length()); + } else { + *outbuf = NULL; + } + } + if (outbuflen) + *outbuflen = outbl.length(); +} + extern "C" const char *ceph_version(int *pmajor, int *pminor, int *ppatch) { int major, minor, patch; @@ -316,6 +362,57 @@ extern "C" int ceph_conf_get(struct ceph_mount_info *cmount, const char *option, return cmount->conf_get(option, buf, len); } +extern "C" int ceph_mds_command(struct ceph_mount_info *cmount, + const char *mds_spec, + const char **cmd, + size_t cmdlen, + const char *inbuf, size_t inbuflen, + char **outbuf, size_t *outbuflen, + char **outsbuf, size_t *outsbuflen) +{ + bufferlist inbl; + bufferlist outbl; + std::vector cmdv; + std::string outs; + + if (!cmount->is_initialized()) { + return -ENOTCONN; + } + + // Construct inputs + for (size_t i = 0; i < cmdlen; ++i) { + cmdv.push_back(cmd[i]); + } + inbl.append(inbuf, inbuflen); + + // Issue remote command + C_SaferCond cond; + int r = cmount->get_client()->mds_command( + mds_spec, + cmdv, inbl, + &outbl, &outs, + &cond); + + if (r != 0) { + goto out; + } + + // Wait for completion + r = cond.wait(); + + // Construct outputs + do_out_buffer(outbl, outbuf, outbuflen); + do_out_buffer(outs, outsbuf, outsbuflen); + +out: + return r; +} + +extern "C" int ceph_init(struct ceph_mount_info *cmount) +{ + return cmount->init(); +} + extern "C" int ceph_mount(struct ceph_mount_info *cmount, const char *root) { std::string mount_root; @@ -1517,3 +1614,10 @@ extern "C" uint64_t ceph_ll_get_internal_offset(class ceph_mount_info *cmount, { return (cmount->get_client()->ll_get_internal_offset(in, blockno)); } + +extern "C" void ceph_buffer_free(char *buf) +{ + if (buf) { + free(buf); + } +} -- 2.39.5