Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fat: small optimization to __fat_readdir()

This removes unnecessary parsing for directory entries.

If short_only, we don't need to parse longname. And if !both and it found
the longname, we don't need shortname.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

OGAWA Hirofumi and committed by
Linus Torvalds
dcd8c53f 98a15160

+39 -32
+39 -32
fs/fat/dir.c
··· 481 481 unsigned short opt_shortname = sbi->options.shortname; 482 482 int isvfat = sbi->options.isvfat; 483 483 int nocase = sbi->options.nocase; 484 - const char *fill_name; 484 + const char *fill_name = NULL; 485 485 unsigned long inum; 486 486 unsigned long lpos, dummy, *furrfu = &lpos; 487 487 loff_t cpos; 488 - int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len; 488 + int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0; 489 489 int ret = 0; 490 490 491 491 lock_super(sb); ··· 516 516 goto end_of_dir; 517 517 parse_record: 518 518 nr_slots = 0; 519 - /* Check for long filename entry */ 520 - if (isvfat) { 519 + /* 520 + * Check for long filename entry, but if short_only, we don't 521 + * need to parse long filename. 522 + */ 523 + if (isvfat && !short_only) { 521 524 if (de->name[0] == DELETED_FLAG) 522 525 goto record_end; 523 526 if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) ··· 545 542 goto parse_record; 546 543 else if (status == PARSE_EOF) 547 544 goto end_of_dir; 545 + 546 + if (nr_slots) { 547 + void *longname = unicode + FAT_MAX_UNI_CHARS; 548 + int size = PATH_MAX - FAT_MAX_UNI_SIZE; 549 + int len = fat_uni_to_x8(sbi, unicode, longname, size); 550 + 551 + fill_name = longname; 552 + fill_len = len; 553 + /* !both && !short_only, so we don't need shortname. */ 554 + if (!both) 555 + goto start_filldir; 556 + } 548 557 } 549 558 550 559 if (sbi->options.dotsOK) { ··· 623 608 i = last + dotoffset; 624 609 j = last_u; 625 610 611 + if (isvfat) { 612 + bufuname[j] = 0x0000; 613 + i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); 614 + } 615 + if (nr_slots) { 616 + /* hack for fat_ioctl_filldir() */ 617 + struct fat_ioctl_filldir_callback *p = dirent; 618 + 619 + p->longname = fill_name; 620 + p->long_len = fill_len; 621 + p->shortname = bufname; 622 + p->short_len = i; 623 + fill_name = NULL; 624 + fill_len = 0; 625 + } else { 626 + fill_name = bufname; 627 + fill_len = i; 628 + } 629 + 630 + start_filldir: 626 631 lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); 627 632 if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) 628 633 inum = inode->i_ino; ··· 658 623 inum = iunique(sb, MSDOS_ROOT_INO); 659 624 } 660 625 661 - if (isvfat) { 662 - bufuname[j] = 0x0000; 663 - i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); 664 - } 665 - 666 - fill_name = bufname; 667 - fill_len = i; 668 - if (!short_only && nr_slots) { 669 - void *longname = unicode + FAT_MAX_UNI_CHARS; 670 - int long_len, size = PATH_MAX - FAT_MAX_UNI_SIZE; 671 - 672 - long_len = fat_uni_to_x8(sbi, unicode, longname, size); 673 - 674 - if (!both) { 675 - fill_name = longname; 676 - fill_len = long_len; 677 - } else { 678 - /* hack for fat_ioctl_filldir() */ 679 - struct fat_ioctl_filldir_callback *p = dirent; 680 - 681 - p->longname = longname; 682 - p->long_len = long_len; 683 - p->shortname = bufname; 684 - p->short_len = i; 685 - fill_name = NULL; 686 - fill_len = 0; 687 - } 688 - } 689 626 if (filldir(dirent, fill_name, fill_len, *furrfu, inum, 690 627 (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) 691 628 goto fill_failed;