Commit 225cf4cdf9ffd73978f4a266d3ecc6c88b048a74

Authored by Mark Tomlinson
Committed by Tom Rini
1 parent 3799b3f4ad

JFFS2: Speed up and fix comparison functions

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@alliedtelesis.co.nz>

Showing 1 changed file with 47 additions and 40 deletions Side-by-side Diff

fs/jffs2/jffs2_1pass.c
... ... @@ -598,14 +598,18 @@
598 598 */
599 599 static int compare_inodes(struct b_node *new, struct b_node *old)
600 600 {
601   - struct jffs2_raw_inode ojNew;
602   - struct jffs2_raw_inode ojOld;
603   - struct jffs2_raw_inode *jNew =
604   - (struct jffs2_raw_inode *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew);
605   - struct jffs2_raw_inode *jOld =
606   - (struct jffs2_raw_inode *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld);
  601 + /*
  602 + * Only read in the version info from flash, not the entire inode.
  603 + * This can make a big difference to speed if flash is slow.
  604 + */
  605 + u32 new_version;
  606 + u32 old_version;
  607 + get_fl_mem(new->offset + offsetof(struct jffs2_raw_inode, version),
  608 + sizeof(new_version), &new_version);
  609 + get_fl_mem(old->offset + offsetof(struct jffs2_raw_inode, version),
  610 + sizeof(old_version), &old_version);
607 611  
608   - return jNew->version > jOld->version;
  612 + return new_version > old_version;
609 613 }
610 614  
611 615 /* Sort directory entries so all entries in the same directory
612 616  
613 617  
614 618  
615 619  
616 620  
... ... @@ -615,42 +619,45 @@
615 619 */
616 620 static int compare_dirents(struct b_node *new, struct b_node *old)
617 621 {
618   - struct jffs2_raw_dirent ojNew;
619   - struct jffs2_raw_dirent ojOld;
620   - struct jffs2_raw_dirent *jNew =
621   - (struct jffs2_raw_dirent *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew);
622   - struct jffs2_raw_dirent *jOld =
623   - (struct jffs2_raw_dirent *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld);
  622 + /*
  623 + * Using NULL as the buffer for NOR flash prevents the entire node
  624 + * being read. This makes most comparisons much quicker as only one
  625 + * or two entries from the node will be used most of the time.
  626 + */
  627 + struct jffs2_raw_dirent *jNew = get_node_mem(new->offset, NULL);
  628 + struct jffs2_raw_dirent *jOld = get_node_mem(old->offset, NULL);
624 629 int cmp;
  630 + int ret;
625 631  
626   - /* ascending sort by pino */
627   - if (jNew->pino != jOld->pino)
628   - return jNew->pino > jOld->pino;
629   -
630   - /* pino is the same, so use ascending sort by nsize, so
631   - * we don't do strncmp unless we really must.
632   - */
633   - if (jNew->nsize != jOld->nsize)
634   - return jNew->nsize > jOld->nsize;
635   -
636   - /* length is also the same, so use ascending sort by name
637   - */
638   - cmp = strncmp((char *)jNew->name, (char *)jOld->name, jNew->nsize);
639   - if (cmp != 0)
640   - return cmp > 0;
641   -
642   - /* we have duplicate names in this directory, so use ascending
643   - * sort by version
644   - */
645   - if (jNew->version > jOld->version) {
646   - /* since jNew is newer, we know jOld is not valid, so
647   - * mark it with inode 0 and it will not be used
  632 + if (jNew->pino != jOld->pino) {
  633 + /* ascending sort by pino */
  634 + ret = jNew->pino > jOld->pino;
  635 + } else if (jNew->nsize != jOld->nsize) {
  636 + /*
  637 + * pino is the same, so use ascending sort by nsize,
  638 + * so we don't do strncmp unless we really must.
648 639 */
649   - jOld->ino = 0;
650   - return 1;
  640 + ret = jNew->nsize > jOld->nsize;
  641 + } else {
  642 + /*
  643 + * length is also the same, so use ascending sort by name
  644 + */
  645 + cmp = strncmp((char *)jNew->name, (char *)jOld->name,
  646 + jNew->nsize);
  647 + if (cmp != 0) {
  648 + ret = cmp > 0;
  649 + } else {
  650 + /*
  651 + * we have duplicate names in this directory,
  652 + * so use ascending sort by version
  653 + */
  654 + ret = jNew->version > jOld->version;
  655 + }
651 656 }
  657 + put_fl_mem(jNew, NULL);
  658 + put_fl_mem(jOld, NULL);
652 659  
653   - return 0;
  660 + return ret;
654 661 }
655 662 #endif
656 663