[U-Boot] [PATCH 2/8] JFFS2: Speed up and fix comparison functions

Heiko Schocher denx hs at denx.de
Tue Jun 30 11:04:45 CEST 2015


Hello Mark,

Am 29.06.2015 um 07:02 schrieb Mark Tomlinson:
> Copying complete nodes from flash can be slow if the flash is slow
> to read. By only reading the data needed, the sorting operation can
> be made much faster.
>
> The directory entry comparison function also had a two bugs. First, it
> did not ensure the name was copied, so the name comparison may have
> been faulty (although it would have worked with NOR flash).  Second,
> setting the ino to zero to ignore the entry did not work, since this
> was either writing to a temporary buffer, or (for NOR flash) directly
> to flash. Either way, the change was not remembered.
>
> Signed-off-by: Mark Tomlinson <mark.tomlinson at alliedtelesis.co.nz>
> ---
>
>   fs/jffs2/jffs2_1pass.c | 82 ++++++++++++++++++++++++++------------------------
>   1 file changed, 42 insertions(+), 40 deletions(-)
>
> diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
> index 2335db1..079bb73 100644
> --- a/fs/jffs2/jffs2_1pass.c
> +++ b/fs/jffs2/jffs2_1pass.c
> @@ -598,14 +598,17 @@ insert_node(struct b_list *list, u32 offset)
>    */
>   static int compare_inodes(struct b_node *new, struct b_node *old)
>   {
> -	struct jffs2_raw_inode ojNew;
> -	struct jffs2_raw_inode ojOld;
> -	struct jffs2_raw_inode *jNew =
> -		(struct jffs2_raw_inode *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew);
> -	struct jffs2_raw_inode *jOld =
> -		(struct jffs2_raw_inode *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld);
> -
> -	return jNew->version > jOld->version;
> +	/* Only read in the version info from flash, not the entire inode.

please fix your comment style globally, thanks1

> +	 * This can make a big difference to speed if flash is slow.
> +	 */
> +	u32 new_version;
> +	u32 old_version;
> +	get_fl_mem(new->offset + offsetof(struct jffs2_raw_inode, version),
> +		   sizeof(new_version), &new_version);
> +	get_fl_mem(old->offset + offsetof(struct jffs2_raw_inode, version),
> +		   sizeof(old_version), &old_version);
> +
> +	return new_version > old_version;
>   }
>
>   /* Sort directory entries so all entries in the same directory
> @@ -615,42 +618,41 @@ static int compare_inodes(struct b_node *new, struct b_node *old)
>    */
>   static int compare_dirents(struct b_node *new, struct b_node *old)
>   {
> -	struct jffs2_raw_dirent ojNew;
> -	struct jffs2_raw_dirent ojOld;
> -	struct jffs2_raw_dirent *jNew =
> -		(struct jffs2_raw_dirent *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew);
> -	struct jffs2_raw_dirent *jOld =
> -		(struct jffs2_raw_dirent *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld);
> -	int cmp;
> -
> -	/* ascending sort by pino */
> -	if (jNew->pino != jOld->pino)
> -		return jNew->pino > jOld->pino;
> -
> -	/* pino is the same, so use ascending sort by nsize, so
> -	 * we don't do strncmp unless we really must.
> -	 */
> -	if (jNew->nsize != jOld->nsize)
> -		return jNew->nsize > jOld->nsize;
> -
> -	/* length is also the same, so use ascending sort by name
> -	 */
> -	cmp = strncmp((char *)jNew->name, (char *)jOld->name, jNew->nsize);
> -	if (cmp != 0)
> -		return cmp > 0;
> -
> -	/* we have duplicate names in this directory, so use ascending
> -	 * sort by version
> +	/* Using NULL as the buffer for NOR flash prevents the entire node
> +	 * being read. This makes most comparisons much quicker as only one
> +	 * or two entries from the node will be used most of the time.
>   	 */
> -	if (jNew->version > jOld->version) {
> -		/* since jNew is newer, we know jOld is not valid, so
> -		 * mark it with inode 0 and it will not be used
> +	struct jffs2_raw_dirent *jNew = get_node_mem(new->offset, NULL);
> +	struct jffs2_raw_dirent *jOld = get_node_mem(old->offset, NULL);
> +	int cmp;
> +	int ret;
> +
> +	if (jNew->pino != jOld->pino) {
> +		/* ascending sort by pino */
> +		ret = jNew->pino > jOld->pino;
> +	} else if (jNew->nsize != jOld->nsize) {
> +		/* pino is the same, so use ascending sort by nsize, so
> +		 * we don't do strncmp unless we really must.
>   		 */
> -		jOld->ino = 0;
> -		return 1;
> +		ret = jNew->nsize > jOld->nsize;
> +	} else {
> +		/* length is also the same, so use ascending sort by name
> +		 */
> +		cmp = strncmp((char *)jNew->name, (char *)jOld->name,
> +			jNew->nsize);
> +		if (cmp != 0) {
> +			ret = cmp > 0;
> +		} else {
> +			/* we have duplicate names in this directory,
> +			 * so use ascending sort by version
> +			 */
> +			ret = jNew->version > jOld->version;
> +		}
>   	}
> +	put_fl_mem(jNew, NULL);
> +	put_fl_mem(jOld, NULL);
>
> -	return 0;
> +	return ret;
>   }
>   #endif

Reviewed-by: Heiko Schocher <hs at denx.de>

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


More information about the U-Boot mailing list