[pve-devel] applied: [PATCH cluster] cfs-func-plug: use RW lock for save cached data access

Wolfgang Bumiller w.bumiller at proxmox.com
Thu Sep 21 14:27:41 CEST 2017


applied with commit message fixups
(save -> safe and 1504 instead of 1505)

On Thu, Sep 21, 2017 at 02:08:00PM +0200, Thomas Lamprecht wrote:
> fuse may spawn multiple threads if there are concurrent accesses.
> 
> Our virtual files, e.g. ".members", ".rrd", are registered over our
> "func" cfs plug which is a bit special.
> 
> For each unique virtual file there exists a single cfs_plug_func_t
> instance, shared between all threads.
> As we directly operated unlocked on members of this structure
> parallel accesses raced between each other.
> This could result in quite visible problems like a crash after a
> double free (Bug 1504) or in less noticeable effects where one thread
> may read from an inconsistent, or already freed memory region.
> 
> Add a Reader/Writer lock to efficiently address this problem.
> Other plugs implement more functions and use a mutex to ensure
> consistency and thus do not have this problem.
> 
> Fixes: #1505
> Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
> ---
> 
> As this can lead to crashes I suggest master and stable-4 as apply
> targets
> 
>  data/src/cfs-plug-func.c | 12 ++++++++++--
>  data/src/cfs-plug.h      |  1 +
>  2 files changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/data/src/cfs-plug-func.c b/data/src/cfs-plug-func.c
> index 1982390..c369688 100644
> --- a/data/src/cfs-plug-func.c
> +++ b/data/src/cfs-plug-func.c
> @@ -79,18 +79,22 @@ cfs_plug_func_getattr(
>  
>  	cfs_plug_func_t *fplug = (cfs_plug_func_t *)plug;
>  
>  	memset(stbuf, 0, sizeof(struct stat));
>  
> +	g_rw_lock_writer_lock(&fplug->data_rw_lock);
>  	if (fplug->data)
>  		g_free(fplug->data);
>  
>  	fplug->data = fplug->update_callback(plug);
>  
> +	stbuf->st_size = fplug->data ? strlen(fplug->data) : 0;
> +
> +	g_rw_lock_writer_unlock(&fplug->data_rw_lock);
> +
>  	stbuf->st_mode = fplug->mode;
>  	stbuf->st_nlink = 1;
> -	stbuf->st_size = fplug->data ? strlen(fplug->data) : 0;
>  
>  	return 0;
>  }
>  
>  static int 
> @@ -109,26 +113,30 @@ cfs_plug_func_read(
>  	g_return_val_if_fail(path != NULL, PARAM_CHECK_ERRNO);
>  	g_return_val_if_fail(buf != NULL, PARAM_CHECK_ERRNO);
>  
>  	cfs_plug_func_t *fplug = (cfs_plug_func_t *)plug;
>  
> +	g_rw_lock_reader_lock(&fplug->data_rw_lock);
>  	char *data = fplug->data;
>  
>  	cfs_debug("enter cfs_plug_func_read %s", data);
>  
> -	if (!data)
> +	if (!data) {
> +		g_rw_lock_reader_unlock(&fplug->data_rw_lock);
>  		return 0;
> +	}
>  
>  	int len = strlen(data);
>  
>  	if (offset < len) {
>  		if (offset + size > len)
>  			size = len - offset;
>  		memcpy(buf, data + offset, size);
>  	} else {
>  		size = 0;
>  	}
> +	g_rw_lock_reader_unlock(&fplug->data_rw_lock);
>  
>  	return size;
>  }
>  
>  static int 
> diff --git a/data/src/cfs-plug.h b/data/src/cfs-plug.h
> index 1aef6ce..ac12ad6 100644
> --- a/data/src/cfs-plug.h
> +++ b/data/src/cfs-plug.h
> @@ -83,10 +83,11 @@ typedef int (*cfs_plug_func_write_data_fn_t)(
>  	size_t size);
>  
>  typedef struct {
>  	cfs_plug_t plug;
>  	char *data;
> +	GRWLock data_rw_lock;
>  	mode_t mode;
>  	cfs_plug_func_udpate_data_fn_t update_callback;
>  	cfs_plug_func_write_data_fn_t write_callback;
>  } cfs_plug_func_t;
>  
> -- 
> 2.11.0




More information about the pve-devel mailing list