summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnand Avati <avati@redhat.com>2013-11-20 15:11:13 -0800
committerAnand Avati <avati@redhat.com>2013-11-21 13:11:18 -0800
commitfee08b2cbf8c118d33dea745e0ae3033b36969da (patch)
treee7f42b21457ba1fe63ad994559dba0d799fb4168
parent544dee895a43ec9bb98fc8ace3d124d44bb617f2 (diff)
fuse: revalidate group id cache on uid/gid change detection
- Remember the uid and gid of the pid at the time of caching the group id list. - Next time when referring to the cache confirm that uid and gid of that pid has not changed since. If it has, treat it like a timeout/cache miss. - Solves group id caching issue caused when Samba runs on gluster FUSE mount and changes the uid/gid on a per syscall basis. Change-Id: I3382b037ff0b6d5eaaa36d9c898232543475aeda BUG: 1032438 Signed-off-by: Anand Avati <avati@redhat.com> Reviewed-on: http://review.gluster.org/6320 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Amar Tumballi <amarts@redhat.com>
-rw-r--r--libglusterfs/src/gidcache.c16
-rw-r--r--libglusterfs/src/gidcache.h4
-rw-r--r--xlators/mount/fuse/src/fuse-helpers.c5
-rw-r--r--xlators/nfs/server/src/nfs-fops.c4
4 files changed, 25 insertions, 4 deletions
diff --git a/libglusterfs/src/gidcache.c b/libglusterfs/src/gidcache.c
index c5bdda92596..f2d98abefc3 100644
--- a/libglusterfs/src/gidcache.c
+++ b/libglusterfs/src/gidcache.c
@@ -54,7 +54,8 @@ int gid_cache_reconf(gid_cache_t *cache, uint32_t timeout)
* an additional allocation and memory copy. The caller should copy the data and
* release (unlock) the cache as soon as possible.
*/
-const gid_list_t *gid_cache_lookup(gid_cache_t *cache, uint64_t id)
+const gid_list_t *gid_cache_lookup(gid_cache_t *cache, uint64_t id,
+ uint64_t uid, uint64_t gid)
{
int bucket;
int i;
@@ -72,6 +73,17 @@ const gid_list_t *gid_cache_lookup(gid_cache_t *cache, uint64_t id)
continue;
/*
+ @uid and @gid reflect the latest UID/GID of the
+ process performing the syscall (taken from frame->root).
+
+ If the UID and GID has changed for the PID since the
+ time we cached it, we should treat the cache as having
+ stale values and query them freshly.
+ */
+ if (agl->gl_uid != uid || agl->gl_gid != gid)
+ break;
+
+ /*
* We don't put new entries in the cache when expiration=0, but
* there might be entries still in there if expiration was
* changed very recently. Writing the check this way ensures
@@ -182,6 +194,8 @@ int gid_cache_add(gid_cache_t *cache, gid_list_t *gl)
}
agl->gl_id = gl->gl_id;
+ agl->gl_uid = gl->gl_uid;
+ agl->gl_gid = gl->gl_gid;
agl->gl_count = gl->gl_count;
agl->gl_list = gl->gl_list;
agl->gl_deadline = now + cache->gc_max_age;
diff --git a/libglusterfs/src/gidcache.h b/libglusterfs/src/gidcache.h
index 9379f8e8b01..886721e719f 100644
--- a/libglusterfs/src/gidcache.h
+++ b/libglusterfs/src/gidcache.h
@@ -32,6 +32,8 @@
typedef struct {
uint64_t gl_id;
+ uint64_t gl_uid;
+ uint64_t gl_gid;
int gl_count;
gid_t *gl_list;
time_t gl_deadline;
@@ -46,7 +48,7 @@ typedef struct {
int gid_cache_init(gid_cache_t *, uint32_t);
int gid_cache_reconf(gid_cache_t *, uint32_t);
-const gid_list_t *gid_cache_lookup(gid_cache_t *, uint64_t);
+const gid_list_t *gid_cache_lookup(gid_cache_t *, uint64_t, uint64_t, uint64_t);
void gid_cache_release(gid_cache_t *, const gid_list_t *);
int gid_cache_add(gid_cache_t *, gid_list_t *);
diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c
index 4d478b919f2..6c54cb88200 100644
--- a/xlators/mount/fuse/src/fuse-helpers.c
+++ b/xlators/mount/fuse/src/fuse-helpers.c
@@ -266,7 +266,8 @@ static void get_groups(fuse_private_t *priv, call_frame_t *frame)
return;
}
- gl = gid_cache_lookup(&priv->gid_cache, frame->root->pid);
+ gl = gid_cache_lookup(&priv->gid_cache, frame->root->pid,
+ frame->root->uid, frame->root->gid);
if (gl) {
if (call_stack_alloc_groups (frame->root, gl->gl_count) != 0)
return;
@@ -280,6 +281,8 @@ static void get_groups(fuse_private_t *priv, call_frame_t *frame)
frame_fill_groups (frame);
agl.gl_id = frame->root->pid;
+ agl.gl_uid = frame->root->uid;
+ agl.gl_gid = frame->root->gid;
agl.gl_count = frame->root->ngrps;
agl.gl_list = GF_CALLOC(frame->root->ngrps, sizeof(gid_t),
gf_fuse_mt_gids_t);
diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c
index 236b80c7620..60a5a9a843c 100644
--- a/xlators/nfs/server/src/nfs-fops.c
+++ b/xlators/nfs/server/src/nfs-fops.c
@@ -47,7 +47,7 @@ nfs_fix_groups (xlator_t *this, call_stack_t *root)
return;
}
- agl = gid_cache_lookup(&priv->gid_cache, root->uid);
+ agl = gid_cache_lookup(&priv->gid_cache, root->uid, 0, 0);
if (agl) {
for (ngroups = 0; ngroups < agl->gl_count; ngroups++)
root->groups[ngroups] = agl->gl_list[ngroups];
@@ -84,6 +84,8 @@ nfs_fix_groups (xlator_t *this, call_stack_t *root)
if (gl.gl_list) {
/* It's not fatal if the alloc failed. */
gl.gl_id = root->uid;
+ gl.gl_uid = 0;
+ gl.gl_gid = 0;
gl.gl_count = ngroups;
memcpy(gl.gl_list, mygroups, sizeof(gid_t) * ngroups);
if (gid_cache_add(&priv->gid_cache, &gl) != 1)