diff options
author | R.Shyamsundar <srangana@redhat.com> | 2013-09-16 16:39:24 +0530 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2013-10-11 12:16:46 -0700 |
commit | d573f170cf3305c066f8b191f872d2d2f22f2025 (patch) | |
tree | 51debc2bc323f4347482c0bfcda919cff5182b1f /libglusterfs | |
parent | d3558ae5c4b1cf6909e27e8fabd6ec44fe6aa971 (diff) |
gfapi: object handle based API extensions
There is an ongoing effort to integrate NFS Ganesha (
https://github.com/nfs-ganesha/nfs-ganesha/wiki ) with GlusterFS as one of
the file system back ends.
Towards this we need extensions to gfapi that can handle object based
operations. Meaning, instead of using full paths or relative paths from
cwd, it is required that we can work with APIs, like the *at POSIX
variants, to be able to create, lookup, open etc. files and directories.
Hence the objects are the files or directories themselves and we give out
handles to these objects that can be used for further operations.
This code drop is an initial implementation of the proposed APIs.
The new APIs are implemented as glfs_h_XXX variants in the file
glfs-handleops.c to mirror glfs-fops.c style. The code leverages holding
onto inode references and doling these out as opaque/cookie type objects to
the callers, to enable them to be used as handles in other operations.
An fd based approach was considered, but due to the extra footprint that
the fd structure and its counterparts would incur, this was dropped to take
the approach of holding inode references themselves.
Tested by extending glfsxmp.c to invoke and exercise the added APIs, and
further tested with a reference integration of the same as an FSAL with NFS
Ganesha.
Change-Id: I23629c99e905b54070fa2e6565147812e5f3fa5d
BUG: 1016000
Signed-off-by: R.Shyamsundar <srangana@redhat.com>
Reviewed-on: http://review.gluster.org/5936
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r-- | libglusterfs/src/globals.c | 57 | ||||
-rw-r--r-- | libglusterfs/src/globals.h | 4 | ||||
-rw-r--r-- | libglusterfs/src/mem-types.h | 5 | ||||
-rw-r--r-- | libglusterfs/src/syncop.c | 154 | ||||
-rw-r--r-- | libglusterfs/src/syncop.h | 78 |
5 files changed, 278 insertions, 20 deletions
diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c index 459291b3309..1e4cbf0edeb 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -19,6 +19,7 @@ #include "globals.h" #include "xlator.h" #include "mem-pool.h" +#include "syncop.h" const char *gf_fop_list[GF_FOP_MAXVALUE] = { [GF_FOP_NULL] = "NULL", @@ -164,6 +165,54 @@ glusterfs_this_set (xlator_t *this) return 0; } +/* SYNCOPCTX */ +static pthread_key_t syncopctx_key; + +static void +syncopctx_key_destroy (void *ptr) +{ + struct syncopctx *opctx = ptr; + + if (opctx) { + if (opctx->groups) + GF_FREE (opctx->groups); + + GF_FREE (opctx); + } + + return; +} + +void * +syncopctx_getctx () +{ + void *opctx = NULL; + + opctx = pthread_getspecific (syncopctx_key); + + return opctx; +} + +int +syncopctx_setctx (void *ctx) +{ + int ret = 0; + + ret = pthread_setspecific (syncopctx_key, ctx); + + return ret; +} + +static int +syncopctx_init (void) +{ + int ret; + + ret = pthread_key_create (&syncopctx_key, syncopctx_key_destroy); + + return ret; +} + /* SYNCTASK */ int @@ -176,7 +225,6 @@ synctask_init () return ret; } - void * synctask_get () { @@ -300,6 +348,13 @@ glusterfs_globals_init (glusterfs_ctx_t *ctx) "ERROR: glusterfs synctask init failed"); goto out; } + + ret = syncopctx_init (); + if (ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs syncopctx init failed"); + goto out; + } out: return ret; } diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h index 857965bb458..3085db21c1a 100644 --- a/libglusterfs/src/globals.h +++ b/libglusterfs/src/globals.h @@ -41,6 +41,10 @@ xlator_t **__glusterfs_this_location (); xlator_t *glusterfs_this_get (); int glusterfs_this_set (xlator_t *); +/* syncopctx */ +void *syncopctx_getctx (); +int syncopctx_setctx (void *ctx); + /* task */ void *synctask_get (); int synctask_set (void *); diff --git a/libglusterfs/src/mem-types.h b/libglusterfs/src/mem-types.h index 3b0f7d27667..9aadbcaec2a 100644 --- a/libglusterfs/src/mem-types.h +++ b/libglusterfs/src/mem-types.h @@ -115,7 +115,8 @@ enum gf_common_mem_types_ { gf_common_mt_client_ctx = 99, gf_common_mt_lock_table = 100, gf_common_mt_locker = 101, - gf_common_mt_auxgids = 102, - gf_common_mt_end = 103 + gf_common_mt_auxgids = 102, + gf_common_mt_syncopctx = 103, + gf_common_mt_end = 104 }; #endif diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c index cd267cacc57..866dca50ea4 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -15,6 +15,160 @@ #include "syncop.h" +int +syncopctx_setfsuid (void *uid) +{ + struct syncopctx *opctx = NULL; + int ret = 0; + + /* In args check */ + if (!uid) { + ret = -1; + errno = EINVAL; + goto out; + } + + opctx = syncopctx_getctx (); + + /* alloc for this thread the first time */ + if (!opctx) { + opctx = GF_CALLOC (1, sizeof (*opctx), gf_common_mt_syncopctx); + if (!opctx) { + ret = -1; + goto out; + } + + ret = syncopctx_setctx (opctx); + if (ret != 0) { + GF_FREE (opctx); + opctx = NULL; + goto out; + } + } + +out: + if (opctx && uid) { + opctx->uid = *(uid_t *)uid; + opctx->valid |= SYNCOPCTX_UID; + } + + return ret; +} + +int +syncopctx_setfsgid (void *gid) +{ + struct syncopctx *opctx = NULL; + int ret = 0; + + /* In args check */ + if (!gid) { + ret = -1; + errno = EINVAL; + goto out; + } + + opctx = syncopctx_getctx (); + + /* alloc for this thread the first time */ + if (!opctx) { + opctx = GF_CALLOC (1, sizeof (*opctx), gf_common_mt_syncopctx); + if (!opctx) { + ret = -1; + goto out; + } + + ret = syncopctx_setctx (opctx); + if (ret != 0) { + GF_FREE (opctx); + opctx = NULL; + goto out; + } + } + +out: + if (opctx && gid) { + opctx->gid = *(gid_t *)gid; + opctx->valid |= SYNCOPCTX_GID; + } + + return ret; +} + +int +syncopctx_setfsgroups (int count, const void *groups) +{ + struct syncopctx *opctx = NULL; + gid_t *tmpgroups = NULL; + int ret = 0; + + /* In args check */ + if (count != 0 && !groups) { + ret = -1; + errno = EINVAL; + goto out; + } + + opctx = syncopctx_getctx (); + + /* alloc for this thread the first time */ + if (!opctx) { + opctx = GF_CALLOC (1, sizeof (*opctx), gf_common_mt_syncopctx); + if (!opctx) { + ret = -1; + goto out; + } + + ret = syncopctx_setctx (opctx); + if (ret != 0) { + GF_FREE (opctx); + opctx = NULL; + goto out; + } + } + + /* resize internal groups as required */ + if (count && opctx->grpsize < count) { + if (opctx->groups) { + tmpgroups = GF_REALLOC (opctx->groups, + (sizeof (gid_t) * count)); + /* NOTE: Not really required to zero the reallocation, + * as ngrps controls the validity of data, + * making a note irrespective */ + if (tmpgroups == NULL) { + opctx->grpsize = 0; + GF_FREE (opctx->groups); + opctx->groups = NULL; + ret = -1; + goto out; + } + } + else { + tmpgroups = GF_CALLOC (count, sizeof (gid_t), + gf_common_mt_syncopctx); + if (tmpgroups == NULL) { + opctx->grpsize = 0; + ret = -1; + goto out; + } + } + + opctx->groups = tmpgroups; + opctx->grpsize = count; + } + + /* copy out the groups passed */ + if (count) + memcpy (opctx->groups, groups, (sizeof (gid_t) * count)); + + /* set/reset the ngrps, this is where reset of groups is handled */ + opctx->ngrps = count; + opctx->valid |= SYNCOPCTX_GROUPS; + +out: + return ret; +} + static void __run (struct synctask *task) { diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index 64350030e56..0fc9e14ba0f 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -25,6 +25,13 @@ #define SYNCENV_PROC_MIN 2 #define SYNCPROC_IDLE_TIME 600 +/* + * Flags for syncopctx valid elements + */ +#define SYNCOPCTX_UID 0x00000001 +#define SYNCOPCTX_GID 0x00000002 +#define SYNCOPCTX_GROUPS 0x00000004 + struct synctask; struct syncproc; struct syncenv; @@ -150,6 +157,14 @@ struct syncargs { int done; }; +struct syncopctx { + unsigned int valid; /* valid flags for elements that are set */ + uid_t uid; + gid_t gid; + int grpsize; + int ngrps; + gid_t *groups; +}; #define __yawn(args) do { \ args->task = synctask_get (); \ @@ -242,34 +257,63 @@ void synctask_waitfor (struct synctask *task, int count); int synctask_setid (struct synctask *task, uid_t uid, gid_t gid); #define SYNCTASK_SETID(uid, gid) synctask_setid (synctask_get(), uid, gid); +int syncopctx_setfsuid (void *uid); +int syncopctx_setfsgid (void *gid); +int syncopctx_setfsgroups (int count, const void *groups); static inline call_frame_t * syncop_create_frame (xlator_t *this) { - call_frame_t *frame = NULL; - int ngrps = -1; + call_frame_t *frame = NULL; + int ngrps = -1; + struct syncopctx *opctx = NULL; frame = create_frame (this, this->ctx->pool); if (!frame) return NULL; - frame->root->pid = getpid(); - frame->root->uid = geteuid (); - frame->root->gid = getegid (); - ngrps = getgroups (0, 0); - if (ngrps < 0) { - STACK_DESTROY (frame->root); - return NULL; - } + frame->root->pid = getpid (); - if (call_stack_alloc_groups (frame->root, ngrps) != 0) { - STACK_DESTROY (frame->root); - return NULL; - } + opctx = syncopctx_getctx (); + if (opctx && (opctx->valid & SYNCOPCTX_UID)) + frame->root->uid = opctx->uid; + else + frame->root->uid = geteuid (); - if (getgroups (ngrps, frame->root->groups) < 0) { - STACK_DESTROY (frame->root); - return NULL; + if (opctx && (opctx->valid & SYNCOPCTX_GID)) + frame->root->gid = opctx->gid; + else + frame->root->gid = getegid (); + + if (opctx && (opctx->valid & SYNCOPCTX_GROUPS)) { + ngrps = opctx->ngrps; + + if (ngrps != 0 && opctx->groups != NULL) { + if (call_stack_alloc_groups (frame->root, ngrps) != 0) { + STACK_DESTROY (frame->root); + return NULL; + } + + memcpy (frame->root->groups, opctx->groups, + (sizeof (gid_t) * ngrps)); + } + } + else { + ngrps = getgroups (0, 0); + if (ngrps < 0) { + STACK_DESTROY (frame->root); + return NULL; + } + + if (call_stack_alloc_groups (frame->root, ngrps) != 0) { + STACK_DESTROY (frame->root); + return NULL; + } + + if (getgroups (ngrps, frame->root->groups) < 0) { + STACK_DESTROY (frame->root); + return NULL; + } } return frame; |