diff options
author | Shehjar Tikoo <shehjart@zresearch.com> | 2009-05-05 15:59:32 +0530 |
---|---|---|
committer | Anand V. Avati <avati@amp.gluster.com> | 2009-05-05 17:41:54 +0530 |
commit | d470dd599c8dbf609411e52e587ea5c171214b21 (patch) | |
tree | 00189ee1939c4030ca860d55250908c6bab81a4a /booster | |
parent | 3364e5eb2d5f5110e86924112dfe3f10597c9c9f (diff) |
booster: Add VMP-based open support
In brief, when an open is called the VMP-based open is called first.
If that fails, the fallback is the Mount-Point Bypass(MBP) technique
which uses entended attributes to determine if the given
path is a gluster mount. If it is, it goes ahead to create a
glusterfsclient handle. All subsequent calls to this real mount point
get redirected to the glusterfsclient handle. The other fallback is
the actual open syscall on the local file system itself. This happens
when the absence of an extended attribute tells us that the path is
not even a glusterfs mount point.
Signed-off-by: Anand V. Avati <avati@amp.gluster.com>
Diffstat (limited to 'booster')
-rw-r--r-- | booster/src/booster.c | 166 |
1 files changed, 146 insertions, 20 deletions
diff --git a/booster/src/booster.c b/booster/src/booster.c index 903ad8e8f37..026e03ce31c 100644 --- a/booster/src/booster.c +++ b/booster/src/booster.c @@ -38,12 +38,14 @@ #include <assert.h> #include <errno.h> #include <ctype.h> +#include <logging.h> #ifndef GF_UNIT_KB #define GF_UNIT_KB 1024 #endif +extern int pipe (int filedes[2]); /* We define these flags so that we can remove fcntl.h from the include path. * fcntl.h has certain defines and other lines of code that redirect the * application's open and open64 calls to the syscalls defined by @@ -172,6 +174,18 @@ typedef struct booster_mount_table booster_mount_table_t; static fdtable_t *booster_glfs_fdtable = NULL; static booster_mount_table_t *booster_mount_table = NULL; +/* This is dup'ed every time VMP open/creat wants a new fd. + * This is needed so we occupy an entry in the process' file + * table. + */ +int process_piped_fd = -1; + +static int +booster_get_process_fd () +{ + return real_dup (process_piped_fd); +} + #define DEFAULT_BOOSTER_CONF "/etc/booster.conf" int @@ -459,27 +473,138 @@ do_open (int fd, int flags, mode_t mode) } int -open (const char *pathname, int flags, ...) +vmp_open (const char *pathname, int flags, ...) { - int ret; - mode_t mode = 0; - va_list ap; + mode_t mode = 0; + int fd = -1; + glusterfs_file_t fh = NULL; + va_list ap; + + if (flags & GF_O_CREAT) { + va_start (ap, flags); + mode = va_arg (ap, mode_t); + va_end (ap); + + fh = glusterfs_open (pathname, flags, mode); + } + else + fh = glusterfs_open (pathname, flags); + + if (!fh) + goto out; + + fd = booster_get_process_fd (); + if (fd == -1) + goto fh_close_out; + + if (booster_get_unused_fd (booster_glfs_fdtable, fh, fd) == -1) + goto realfd_close_out; + + return fd; + +realfd_close_out: + real_close (fd); + fd = -1; + +fh_close_out: + glusterfs_close (fh); + +out: + return fd; +} + +#define BOOSTER_USE_OPEN64 1 +#define BOOSTER_DONT_USE_OPEN64 0 + +int +booster_open (const char *pathname, int use64, int flags, ...) +{ + int ret = -1; + mode_t mode = 0; + va_list ap; + int (*my_open) (const char *pathname, int flags, ...); + + if (!pathname) { + errno = EINVAL; + goto out; + } + + /* First try opening through the virtual mount point. + * The difference lies in the fact that: + * 1. We depend on libglusterfsclient library to perform + * the translation from the path to handle. + * 2. We do not go to the file system for the fd, instead + * we use booster_get_process_fd (), which returns a dup'ed + * fd of a pipe created in booster_init. + */ + if (flags & GF_O_CREAT) { + va_start (ap, flags); + mode = va_arg (ap, mode_t); + va_end (ap); + ret = vmp_open (pathname, flags, mode); + } + else + ret = vmp_open (pathname, flags); + + /* We receive an ENODEV if the VMP does not exist. If we + * receive an error other than ENODEV, it means, there + * actually was an error performing vmp_open. This must + * be returned to the user. + */ + if (((ret < 0) && (errno != ENODEV)) || (ret > 0)) + goto out; + + if (use64) + my_open = real_open64; + else + my_open = real_open; + + /* It is possible the RESOLVE macro is not able + * to resolve the symbol of a function, in that case + * we dont want to seg-fault on calling a NULL functor. + */ + if (my_open == NULL) { + ret = -1; + errno = ENOSYS; + goto out; + } if (flags & GF_O_CREAT) { va_start (ap, flags); mode = va_arg (ap, mode_t); va_end (ap); - ret = real_open (pathname, flags, mode); - } else { - ret = real_open (pathname, flags); - } + ret = my_open (pathname, flags, mode); + } else + ret = my_open (pathname, flags); if (ret != -1) { flags &= ~ GF_O_CREAT; do_open (ret, flags, mode); } +out: + return ret; +} + +int +open (const char *pathname, int flags, ...) +{ + int ret = -1; + mode_t mode = 0; + va_list ap; + + if (flags & GF_O_CREAT) { + va_start (ap, flags); + mode = va_arg (ap, mode_t); + va_end (ap); + + ret = booster_open (pathname, BOOSTER_DONT_USE_OPEN64, + flags, mode); + } + else + ret = booster_open (pathname, BOOSTER_DONT_USE_OPEN64, flags); + return ret; } @@ -491,20 +616,15 @@ open64 (const char *pathname, int flags, ...) mode_t mode = 0; va_list ap; - if (flags & GF_O_CREAT) { - va_start (ap, flags); - mode = va_arg (ap, mode_t); - va_end (ap); - - ret = real_open64 (pathname, flags, mode); - } else { - ret = real_open64 (pathname, flags); - } + if (flags & GF_O_CREAT) { + va_start (ap, flags); + mode = va_arg (ap, mode_t); + va_end (ap); - if (ret != -1) { - flags &= ~GF_O_CREAT; - do_open (ret, flags, mode); + ret = booster_open (pathname, BOOSTER_USE_OPEN64, flags, mode); } + else + ret = booster_open (pathname, BOOSTER_USE_OPEN64, flags); return ret; } @@ -891,6 +1011,7 @@ booster_init (void) int i = 0; char *booster_conf_path = NULL; int ret = -1; + int pipefd[2]; booster_glfs_fdtable = gf_fd_fdtable_alloc (); if (!booster_glfs_fdtable) { @@ -921,6 +1042,11 @@ booster_init (void) INIT_LIST_HEAD (&booster_mount_table->mounts[i]); } + if (pipe (pipefd) == -1) + goto err; + + process_piped_fd = pipefd[0]; + real_close (pipefd[1]); /* libglusterfsclient based VMPs should be inited only * after the file tables are inited so that if the socket * calls use the fd based syscalls, the fd tables are |