diff options
Diffstat (limited to 'src/libcephfs_proxy/libcephfs_proxy.c')
-rw-r--r-- | src/libcephfs_proxy/libcephfs_proxy.c | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/src/libcephfs_proxy/libcephfs_proxy.c b/src/libcephfs_proxy/libcephfs_proxy.c new file mode 100644 index 00000000000..149fae123f7 --- /dev/null +++ b/src/libcephfs_proxy/libcephfs_proxy.c @@ -0,0 +1,869 @@ + +#include <stdlib.h> + +#include "include/cephfs/libcephfs.h" + +#include "proxy_log.h" +#include "proxy_helpers.h" +#include "proxy_requests.h" + +/* We override the definition of the ceph_mount_info structure to contain + * internal proxy information. This is already a black box for libcephfs users, + * so this won't be noticed. */ +struct ceph_mount_info { + proxy_link_t link; + uint64_t cmount; +}; + +/* The global_cmount is used to stablish an initial connection to serve requests + * not related to a real cmount, like ceph_version or ceph_userperm_new. */ +static struct ceph_mount_info global_cmount = { PROXY_LINK_DISCONNECTED, 0 }; + +static bool client_stop(proxy_link_t *link) +{ + return false; +} + +static int32_t proxy_connect(proxy_link_t *link) +{ + CEPH_REQ(hello, req, 0, ans, 0); + char *path, *env; + int32_t sd, err; + + path = PROXY_SOCKET; + env = getenv(PROXY_SOCKET_ENV); + if (env != NULL) { + path = env; + } + + sd = proxy_link_client(link, path, client_stop); + if (sd < 0) { + return sd; + } + + req.id = LIBCEPHFS_LIB_CLIENT; + err = proxy_link_send(sd, req_iov, 1); + if (err < 0) { + goto failed; + } + err = proxy_link_recv(sd, ans_iov, 1); + if (err < 0) { + goto failed; + } + + proxy_log(LOG_INFO, 0, "Connected to libcephfsd version %d.%d", + ans.major, ans.minor); + + if ((ans.major != LIBCEPHFSD_MAJOR) || + (ans.minor != LIBCEPHFSD_MINOR)) { + err = proxy_log(LOG_ERR, ENOTSUP, "Version not supported"); + goto failed; + } + + return sd; + +failed: + proxy_link_close(link); + + return err; +} + +static void proxy_disconnect(proxy_link_t *link) +{ + proxy_link_close(link); +} + +static int32_t proxy_global_connect(void) +{ + int32_t err; + + err = 0; + + if (!proxy_link_is_connected(&global_cmount.link)) { + err = proxy_connect(&global_cmount.link); + } + + return err; +} + +static int32_t proxy_check(struct ceph_mount_info *cmount, int32_t err, + int32_t result) +{ + if (err < 0) { + proxy_disconnect(&cmount->link); + proxy_log(LOG_ERR, err, "Disconnected from libcephfsd"); + + return err; + } + + return result; +} + +/* Macros to simplify communication with the server. */ +#define CEPH_RUN(_cmount, _op, _req, _ans) \ + ({ \ + int32_t __err = \ + CEPH_CALL((_cmount)->link.sd, _op, _req, _ans); \ + __err = proxy_check(_cmount, __err, (_ans).header.result); \ + __err; \ + }) + +#define CEPH_PROCESS(_cmount, _op, _req, _ans) \ + ({ \ + int32_t __err = -ENOTCONN; \ + if (proxy_link_is_connected(&(_cmount)->link)) { \ + (_req).cmount = (_cmount)->cmount; \ + __err = CEPH_RUN(_cmount, _op, _req, _ans); \ + } \ + __err; \ + }) + +__public int ceph_chdir(struct ceph_mount_info *cmount, const char *path) +{ + CEPH_REQ(ceph_chdir, req, 1, ans, 0); + + CEPH_STR_ADD(req, path, path); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_CHDIR, req, ans); +} + +__public int ceph_conf_get(struct ceph_mount_info *cmount, const char *option, + char *buf, size_t len) +{ + CEPH_REQ(ceph_conf_get, req, 1, ans, 1); + + req.size = len; + + CEPH_STR_ADD(req, option, option); + CEPH_BUFF_ADD(ans, buf, len); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_CONF_GET, req, ans); +} + +__public int ceph_conf_read_file(struct ceph_mount_info *cmount, + const char *path_list) +{ + CEPH_REQ(ceph_conf_read_file, req, 1, ans, 0); + + CEPH_STR_ADD(req, path, path_list); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_CONF_READ_FILE, req, ans); +} + +__public int ceph_conf_set(struct ceph_mount_info *cmount, const char *option, + const char *value) +{ + CEPH_REQ(ceph_conf_set, req, 2, ans, 0); + + CEPH_STR_ADD(req, option, option); + CEPH_STR_ADD(req, value, value); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_CONF_SET, req, ans); +} + +__public int ceph_create(struct ceph_mount_info **cmount, const char *const id) +{ + CEPH_REQ(ceph_create, req, 1, ans, 0); + struct ceph_mount_info *ceph_mount; + int32_t sd, err; + + ceph_mount = proxy_malloc(sizeof(struct ceph_mount_info)); + if (ceph_mount == NULL) { + return -ENOMEM; + } + + err = proxy_connect(&ceph_mount->link); + if (err < 0) { + goto failed; + } + sd = err; + + CEPH_STR_ADD(req, id, id); + + err = CEPH_CALL(sd, LIBCEPHFSD_OP_CREATE, req, ans); + if ((err < 0) || ((err = ans.header.result) < 0)) { + goto failed_link; + } + + ceph_mount->cmount = ans.cmount; + + *cmount = ceph_mount; + + return 0; + +failed_link: + proxy_disconnect(&ceph_mount->link); + +failed: + proxy_free(ceph_mount); + + return err; +} + +__public const char *ceph_getcwd(struct ceph_mount_info *cmount) +{ + static char cwd[PATH_MAX]; + int32_t err; + + CEPH_REQ(ceph_getcwd, req, 0, ans, 1); + + CEPH_BUFF_ADD(ans, cwd, sizeof(cwd)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_GETCWD, req, ans); + if (err >= 0) { + return cwd; + } + + errno = -err; + + return NULL; +} + +__public int ceph_init(struct ceph_mount_info *cmount) +{ + CEPH_REQ(ceph_init, req, 0, ans, 0); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_INIT, req, ans); +} + +__public int ceph_ll_close(struct ceph_mount_info *cmount, + struct Fh *filehandle) +{ + CEPH_REQ(ceph_ll_close, req, 0, ans, 0); + + req.fh = ptr_value(filehandle); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_CLOSE, req, ans); +} + +__public int ceph_ll_create(struct ceph_mount_info *cmount, Inode *parent, + const char *name, mode_t mode, int oflags, + Inode **outp, Fh **fhp, struct ceph_statx *stx, + unsigned want, unsigned lflags, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_create, req, 1, ans, 1); + int32_t err; + + req.userperm = ptr_value(perms); + req.parent = ptr_value(parent); + req.mode = mode; + req.oflags = oflags; + req.want = want; + req.flags = lflags; + + CEPH_STR_ADD(req, name, name); + CEPH_BUFF_ADD(ans, stx, sizeof(*stx)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_CREATE, req, ans); + if (err >= 0) { + *outp = value_ptr(ans.inode); + *fhp = value_ptr(ans.fh); + } + + return err; +} + +__public int ceph_ll_fallocate(struct ceph_mount_info *cmount, struct Fh *fh, + int mode, int64_t offset, int64_t length) +{ + CEPH_REQ(ceph_ll_fallocate, req, 0, ans, 0); + + req.fh = ptr_value(fh); + req.mode = mode; + req.offset = offset; + req.length = length; + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_FALLOCATE, req, ans); +} + +__public int ceph_ll_fsync(struct ceph_mount_info *cmount, struct Fh *fh, + int syncdataonly) +{ + CEPH_REQ(ceph_ll_fsync, req, 0, ans, 0); + + req.fh = ptr_value(fh); + req.dataonly = syncdataonly; + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_FSYNC, req, ans); +} + +__public int ceph_ll_getattr(struct ceph_mount_info *cmount, struct Inode *in, + struct ceph_statx *stx, unsigned int want, + unsigned int flags, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_getattr, req, 0, ans, 1); + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.want = want; + req.flags = flags; + + CEPH_BUFF_ADD(ans, stx, sizeof(*stx)); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_GETATTR, req, ans); +} + +__public int ceph_ll_getxattr(struct ceph_mount_info *cmount, struct Inode *in, + const char *name, void *value, size_t size, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_getxattr, req, 1, ans, 1); + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.size = size; + CEPH_STR_ADD(req, name, name); + + CEPH_BUFF_ADD(ans, value, size); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_GETXATTR, req, ans); +} + +__public int ceph_ll_link(struct ceph_mount_info *cmount, struct Inode *in, + struct Inode *newparent, const char *name, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_link, req, 1, ans, 0); + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.parent = ptr_value(newparent); + CEPH_STR_ADD(req, name, name); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LINK, req, ans); +} + +__public int ceph_ll_listxattr(struct ceph_mount_info *cmount, struct Inode *in, + char *list, size_t buf_size, size_t *list_size, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_listxattr, req, 0, ans, 1); + int32_t err; + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.size = buf_size; + + CEPH_BUFF_ADD(ans, list, buf_size); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LISTXATTR, req, ans); + if (err >= 0) { + *list_size = ans.size; + } + + return err; +} + +__public int ceph_ll_lookup(struct ceph_mount_info *cmount, Inode *parent, + const char *name, Inode **out, + struct ceph_statx *stx, unsigned want, + unsigned flags, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_lookup, req, 1, ans, 1); + int32_t err; + + req.userperm = ptr_value(perms); + req.parent = ptr_value(parent); + req.want = want; + req.flags = flags; + CEPH_STR_ADD(req, name, name); + + CEPH_BUFF_ADD(ans, stx, sizeof(*stx)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LOOKUP, req, ans); + if (err >= 0) { + *out = value_ptr(ans.inode); + } + + return err; +} + +__public int ceph_ll_lookup_inode(struct ceph_mount_info *cmount, + struct inodeno_t ino, Inode **inode) +{ + CEPH_REQ(ceph_ll_lookup_inode, req, 0, ans, 0); + int32_t err; + + req.ino = ino; + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LOOKUP_INODE, req, ans); + if (err >= 0) { + *inode = value_ptr(ans.inode); + } + + return err; +} + +__public int ceph_ll_lookup_root(struct ceph_mount_info *cmount, Inode **parent) +{ + CEPH_REQ(ceph_ll_lookup_root, req, 0, ans, 0); + int32_t err; + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LOOKUP_ROOT, req, ans); + if (err >= 0) { + *parent = value_ptr(ans.inode); + } + + return err; +} + +__public off_t ceph_ll_lseek(struct ceph_mount_info *cmount, + struct Fh *filehandle, off_t offset, int whence) +{ + CEPH_REQ(ceph_ll_lseek, req, 0, ans, 0); + int32_t err; + + req.fh = ptr_value(filehandle); + req.offset = offset; + req.whence = whence; + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LSEEK, req, ans); + if (err >= 0) { + return ans.offset; + } + + return err; +} + +__public int ceph_ll_mkdir(struct ceph_mount_info *cmount, Inode *parent, + const char *name, mode_t mode, Inode **out, + struct ceph_statx *stx, unsigned want, + unsigned flags, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_mkdir, req, 1, ans, 1); + int32_t err; + + req.userperm = ptr_value(perms); + req.parent = ptr_value(parent); + req.mode = mode; + req.want = want; + req.flags = flags; + CEPH_STR_ADD(req, name, name); + + CEPH_BUFF_ADD(ans, stx, sizeof(*stx)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_MKDIR, req, ans); + if (err >= 0) { + *out = value_ptr(ans.inode); + } + + return err; +} + +__public int ceph_ll_mknod(struct ceph_mount_info *cmount, Inode *parent, + const char *name, mode_t mode, dev_t rdev, + Inode **out, struct ceph_statx *stx, unsigned want, + unsigned flags, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_mknod, req, 1, ans, 1); + int32_t err; + + req.userperm = ptr_value(perms); + req.parent = ptr_value(parent); + req.mode = mode; + req.rdev = rdev; + req.want = want; + req.flags = flags; + CEPH_STR_ADD(req, name, name); + + CEPH_BUFF_ADD(ans, stx, sizeof(*stx)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_MKNOD, req, ans); + if (err >= 0) { + *out = value_ptr(ans.inode); + } + + return err; +} + +__public int ceph_ll_open(struct ceph_mount_info *cmount, struct Inode *in, + int flags, struct Fh **fh, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_open, req, 0, ans, 0); + int32_t err; + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.flags = flags; + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_OPEN, req, ans); + if (err >= 0) { + *fh = value_ptr(ans.fh); + } + + return err; +} + +__public int ceph_ll_opendir(struct ceph_mount_info *cmount, struct Inode *in, + struct ceph_dir_result **dirpp, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_opendir, req, 0, ans, 0); + int32_t err; + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_OPENDIR, req, ans); + if (err >= 0) { + *dirpp = value_ptr(ans.dir); + } + + return err; +} + +__public int ceph_ll_put(struct ceph_mount_info *cmount, struct Inode *in) +{ + CEPH_REQ(ceph_ll_put, req, 0, ans, 0); + + req.inode = ptr_value(in); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_PUT, req, ans); +} + +__public int ceph_ll_read(struct ceph_mount_info *cmount, struct Fh *filehandle, + int64_t off, uint64_t len, char *buf) +{ + CEPH_REQ(ceph_ll_read, req, 0, ans, 1); + + req.fh = ptr_value(filehandle); + req.offset = off; + req.len = len; + + CEPH_BUFF_ADD(ans, buf, len); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_READ, req, ans); +} + +__public int ceph_ll_readlink(struct ceph_mount_info *cmount, struct Inode *in, + char *buf, size_t bufsize, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_readlink, req, 0, ans, 1); + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.size = bufsize; + + CEPH_BUFF_ADD(ans, buf, bufsize); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_READLINK, req, ans); +} + +__public int ceph_ll_releasedir(struct ceph_mount_info *cmount, + struct ceph_dir_result *dir) +{ + CEPH_REQ(ceph_ll_releasedir, req, 0, ans, 0); + + req.dir = ptr_value(dir); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_RELEASEDIR, req, ans); +} + +__public int ceph_ll_removexattr(struct ceph_mount_info *cmount, + struct Inode *in, const char *name, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_removexattr, req, 1, ans, 0); + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + CEPH_STR_ADD(req, name, name); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_REMOVEXATTR, req, ans); +} + +__public int ceph_ll_rename(struct ceph_mount_info *cmount, + struct Inode *parent, const char *name, + struct Inode *newparent, const char *newname, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_rename, req, 2, ans, 0); + + req.userperm = ptr_value(perms); + req.old_parent = ptr_value(parent); + req.new_parent = ptr_value(newparent); + CEPH_STR_ADD(req, old_name, name); + CEPH_STR_ADD(req, new_name, newname); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_RENAME, req, ans); +} + +__public void ceph_rewinddir(struct ceph_mount_info *cmount, + struct ceph_dir_result *dirp) +{ + CEPH_REQ(ceph_rewinddir, req, 0, ans, 0); + + req.dir = ptr_value(dirp); + + CEPH_PROCESS(cmount, LIBCEPHFSD_OP_REWINDDIR, req, ans); +} + +__public int ceph_ll_rmdir(struct ceph_mount_info *cmount, struct Inode *in, + const char *name, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_rmdir, req, 1, ans, 0); + + req.userperm = ptr_value(perms); + req.parent = ptr_value(in); + CEPH_STR_ADD(req, name, name); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_RMDIR, req, ans); +} + +__public int ceph_ll_setattr(struct ceph_mount_info *cmount, struct Inode *in, + struct ceph_statx *stx, int mask, + const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_setattr, req, 1, ans, 0); + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.mask = mask; + CEPH_BUFF_ADD(req, stx, sizeof(*stx)); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_SETATTR, req, ans); +} + +__public int ceph_ll_setxattr(struct ceph_mount_info *cmount, struct Inode *in, + const char *name, const void *value, size_t size, + int flags, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_setxattr, req, 2, ans, 0); + + req.userperm = ptr_value(perms); + req.inode = ptr_value(in); + req.size = size; + req.flags = flags; + CEPH_STR_ADD(req, name, name); + CEPH_BUFF_ADD(req, value, size); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_SETXATTR, req, ans); +} + +__public int ceph_ll_statfs(struct ceph_mount_info *cmount, struct Inode *in, + struct statvfs *stbuf) +{ + CEPH_REQ(ceph_ll_statfs, req, 0, ans, 1); + + req.inode = ptr_value(in); + + CEPH_BUFF_ADD(ans, stbuf, sizeof(*stbuf)); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_STATFS, req, ans); +} + +__public int ceph_ll_symlink(struct ceph_mount_info *cmount, Inode *in, + const char *name, const char *value, Inode **out, + struct ceph_statx *stx, unsigned want, + unsigned flags, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_symlink, req, 2, ans, 1); + int32_t err; + + req.userperm = ptr_value(perms); + req.parent = ptr_value(in); + req.want = want; + req.flags = flags; + CEPH_STR_ADD(req, name, name); + CEPH_STR_ADD(req, target, value); + + CEPH_BUFF_ADD(req, stx, sizeof(*stx)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_SYMLINK, req, ans); + if (err >= 0) { + *out = value_ptr(ans.inode); + } + + return err; +} + +__public int ceph_ll_unlink(struct ceph_mount_info *cmount, struct Inode *in, + const char *name, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_unlink, req, 1, ans, 0); + + req.userperm = ptr_value(perms); + req.parent = ptr_value(in); + CEPH_STR_ADD(req, name, name); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_UNLINK, req, ans); +} + +__public int ceph_ll_walk(struct ceph_mount_info *cmount, const char *name, + Inode **i, struct ceph_statx *stx, unsigned int want, + unsigned int flags, const UserPerm *perms) +{ + CEPH_REQ(ceph_ll_walk, req, 1, ans, 1); + int32_t err; + + req.userperm = ptr_value(perms); + req.want = want; + req.flags = flags; + CEPH_STR_ADD(req, path, name); + + CEPH_BUFF_ADD(ans, stx, sizeof(*stx)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_WALK, req, ans); + if (err >= 0) { + *i = value_ptr(ans.inode); + } + + return err; +} + +__public int ceph_ll_write(struct ceph_mount_info *cmount, + struct Fh *filehandle, int64_t off, uint64_t len, + const char *data) +{ + CEPH_REQ(ceph_ll_write, req, 1, ans, 0); + + req.fh = ptr_value(filehandle); + req.offset = off; + req.len = len; + CEPH_BUFF_ADD(req, data, len); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_WRITE, req, ans); +} + +__public int ceph_mount(struct ceph_mount_info *cmount, const char *root) +{ + CEPH_REQ(ceph_mount, req, 1, ans, 0); + + CEPH_STR_ADD(req, root, root); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_MOUNT, req, ans); +} + +__public struct dirent *ceph_readdir(struct ceph_mount_info *cmount, + struct ceph_dir_result *dirp) +{ + static struct dirent de; + int32_t err; + + CEPH_REQ(ceph_readdir, req, 0, ans, 1); + + req.dir = ptr_value(dirp); + + CEPH_BUFF_ADD(ans, &de, sizeof(de)); + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_READDIR, req, ans); + if (err < 0) { + errno = -err; + return NULL; + } + if (ans.eod) { + return NULL; + } + + return &de; +} + +__public int ceph_release(struct ceph_mount_info *cmount) +{ + CEPH_REQ(ceph_release, req, 0, ans, 0); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_RELEASE, req, ans); +} + +__public int ceph_select_filesystem(struct ceph_mount_info *cmount, + const char *fs_name) +{ + CEPH_REQ(ceph_select_filesystem, req, 1, ans, 0); + + CEPH_STR_ADD(req, fs, fs_name); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_SELECT_FILESYSTEM, req, ans); +} + +__public int ceph_unmount(struct ceph_mount_info *cmount) +{ + CEPH_REQ(ceph_unmount, req, 0, ans, 0); + + return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_UNMOUNT, req, ans); +} + +__public void ceph_userperm_destroy(UserPerm *perms) +{ + CEPH_REQ(ceph_userperm_destroy, req, 0, ans, 0); + + req.userperm = ptr_value(perms); + + CEPH_RUN(&global_cmount, LIBCEPHFSD_OP_USERPERM_DESTROY, req, ans); +} + +__public UserPerm *ceph_userperm_new(uid_t uid, gid_t gid, int ngids, + gid_t *gidlist) +{ + CEPH_REQ(ceph_userperm_new, req, 1, ans, 0); + int32_t err; + + req.uid = uid; + req.gid = gid; + req.groups = ngids; + CEPH_BUFF_ADD(req, gidlist, sizeof(gid_t) * ngids); + + err = proxy_global_connect(); + if (err >= 0) { + err = CEPH_RUN(&global_cmount, LIBCEPHFSD_OP_USERPERM_NEW, req, + ans); + } + if (err >= 0) { + return value_ptr(ans.userperm); + } + + errno = -err; + + return NULL; +} + +__public const char *ceph_version(int *major, int *minor, int *patch) +{ + static char cached_version[128]; + static int32_t cached_major = -1, cached_minor, cached_patch; + + if (cached_major < 0) { + CEPH_REQ(ceph_version, req, 0, ans, 1); + int32_t err; + + CEPH_BUFF_ADD(ans, cached_version, sizeof(cached_version)); + + err = proxy_global_connect(); + if (err >= 0) { + err = CEPH_RUN(&global_cmount, LIBCEPHFSD_OP_VERSION, + req, ans); + } + + if (err < 0) { + *major = 0; + *minor = 0; + *patch = 0; + + return "Unknown"; + } + + cached_major = ans.major; + cached_minor = ans.minor; + cached_patch = ans.patch; + } + + *major = cached_major; + *minor = cached_minor; + *patch = cached_patch; + + return cached_version; +} + +__public UserPerm *ceph_mount_perms(struct ceph_mount_info *cmount) +{ + CEPH_REQ(ceph_mount_perms, req, 0, ans, 0); + int32_t err; + + err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_MOUNT_PERMS, req, ans); + if (err < 0) { + errno = -err; + return NULL; + } + + return value_ptr(ans.userperm); +} |