[CRIU] [PATCH 4/4] files: Cache special file IDs

Andrew Vagin avagin at parallels.com
Tue Feb 4 10:50:19 PST 2014


On Tue, Feb 04, 2014 at 08:03:46PM +0400, Pavel Emelyanov wrote:
> We have tons of files with equal IDs, e.g. libraries mapped
> to different tasks. We can avoid writing all this duplicate 
> stuff into images by caching the IDs with dev:ino keys.
> 
> This looks _very_ similar to irmap cache, but the latter one
> caches dev:ino into paths. Need to think how to merge them.
> 
> Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
> ---
>  file-ids.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 63 insertions(+), 1 deletion(-)
> 
> diff --git a/file-ids.c b/file-ids.c
> index 7cac60f..30f1bbc 100644
> --- a/file-ids.c
> +++ b/file-ids.c
> @@ -6,7 +6,7 @@
>  #include <unistd.h>
>  #include <errno.h>
>  #include <string.h>
> -
> +#include <sys/stat.h>
>  #include <sys/types.h>
>  
>  #include "asm/types.h"
> @@ -26,9 +26,68 @@ void fd_id_show_tree(void)
>  	kid_show_tree(&fd_tree);
>  }
>  
> +#define FDID_BITS	5
> +#define FDID_SIZE	(1 << FDID_BITS)
> +#define FDID_MASK	(FDID_SIZE - 1)
> +
> +static inline int fdid_hashfn(unsigned int s_dev, unsigned long i_ino)
> +{
> +	return (s_dev + i_ino) & FDID_MASK;
> +}
> +
> +struct fd_id {
> +	unsigned int dev;
> +	unsigned long ino;
> +	u32 id;
> +	struct fd_id *n;

next is more obvious here

> +};
> +
> +static struct fd_id *fd_id_cache[FDID_SIZE];
> +
> +static void fd_id_cache_one(u32 id, struct stat *st)
> +{
> +	struct fd_id *fi;
> +	unsigned hv;
> +
> +	fi = xmalloc(sizeof(*fi));
> +	if (fi) {
> +		fi->dev = st->st_dev;
> +		fi->ino = st->st_ino;
> +		fi->id = id;
> +
> +		hv = fdid_hashfn(st->st_dev, st->st_ino);
> +		fi->n = fd_id_cache[hv];
> +		fd_id_cache[hv] = fi;
> +	}
> +}
> +
> +static struct fd_id *fd_id_cache_lookup(struct stat *st)
> +{
> +	struct fd_id *fi;
> +
> +	for (fi = fd_id_cache[fdid_hashfn(st->st_dev, st->st_ino)];
> +			fi; fi = fi->n)
> +		if (fi->dev == st->st_dev && fi->ino == st->st_ino)
> +			return fi;

For me the following code is bit more readable

	fi = fd_id_cache[fdid_hashfn(st->st_dev, st->st_ino)];
	while (fi) {
		if (fi->dev == st->st_dev && fi->ino == st->st_ino)
			return fi;
		fi = fi->n;
	}
> +
> +	return NULL;
> +}
> +
>  int fd_id_generate_special(struct stat *st, u32 *id)
>  {
> +	if (st) {
> +		struct fd_id *fi;
> +
> +		fi = fd_id_cache_lookup(st);
> +		if (fi) {
> +			*id = fi->id;
> +			return 0;
> +		}
> +	}
> +
>  	*id = fd_tree.subid++;
> +	if (st)
> +		fd_id_cache_one(*id, st);
>  	return 1;
>  }
>  
> @@ -46,6 +105,9 @@ int fd_id_generate(pid_t pid, FdinfoEntry *fe, struct stat *st)
>  	if (!id)
>  		return -ENOMEM;
>  
> +	if (new_id)
> +		fd_id_cache_one(id, st);
> +
>  	fe->id = id;
>  	return new_id;
>  }
> -- 
> 1.8.4.2
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list