diff options
| author | Anand Avati <avati@redhat.com> | 2013-11-20 15:11:13 -0800 | 
|---|---|---|
| committer | Anand Avati <avati@redhat.com> | 2013-11-21 13:11:18 -0800 | 
| commit | fee08b2cbf8c118d33dea745e0ae3033b36969da (patch) | |
| tree | e7f42b21457ba1fe63ad994559dba0d799fb4168 | |
| parent | 544dee895a43ec9bb98fc8ace3d124d44bb617f2 (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.c | 16 | ||||
| -rw-r--r-- | libglusterfs/src/gidcache.h | 4 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-helpers.c | 5 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-fops.c | 4 | 
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)  | 
