summaryrefslogtreecommitdiffstats
path: root/libglusterfs
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/src/globals.c57
-rw-r--r--libglusterfs/src/globals.h4
-rw-r--r--libglusterfs/src/mem-types.h5
-rw-r--r--libglusterfs/src/syncop.c154
-rw-r--r--libglusterfs/src/syncop.h78
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;