Messages in this thread Patch in this message | | | Date | Fri, 2 Jul 1999 00:59:21 -0400 (EDT) | From | Alexander Viro <> | Subject | Re: Linux 2.2.10ac6 |
| |
On Thu, 1 Jul 1999, Alan Cox wrote:
> ftp://ftp.*.kernel.org/pub/linux/kernel/alan/... [snip]
Alan, here is one more patch to FAT/VFAT. It tries to optimize the lookup time (it does cyclic search from the postition of last hit; in case of directory change or negative lookup postion is reset to 0, indeed). It works here and it *does* speed ls -l up (well, actually anything that does lookups in the order given by readdir - globbing, for one). It's a BSD thing and they do it on all local filesystems. I didn't want to start from ext2 ;-/ The thing passes Gordon's testsuite. Cheers, Al
diff -urN linux-2.2.10-ac6/fs/fat/dir.c linux-bird.dir/fs/fat/dir.c --- linux-2.2.10-ac6/fs/fat/dir.c Fri Jul 2 00:39:12 1999 +++ linux-bird.dir/fs/fat/dir.c Fri Jul 2 00:40:11 1999 @@ -137,7 +137,8 @@ char c; struct buffer_head *bh = NULL; struct msdos_dir_entry *de; - loff_t cpos = 0; + loff_t cpos = MSDOS_I(dir)->i_last_pos; + loff_t barrier = 0; char bufname[14]; unsigned char long_slots; int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate; @@ -147,6 +148,9 @@ int res = 0; while(1) { + if (barrier && cpos>=barrier) + goto EODir; +rescan: if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1) goto EODir; parse_record: @@ -265,11 +269,22 @@ res = long_slots + 1; *spos = cpos - sizeof(struct msdos_dir_entry); *lpos = cpos - res*sizeof(struct msdos_dir_entry); -EODir: + MSDOS_I(dir)->i_last_pos = cpos; +exit: if (unicode) { free_page((unsigned long) unicode); } return res; +EODir: + if (!MSDOS_I(dir)->i_last_pos) + goto exit; + if (barrier) { + MSDOS_I(dir)->i_last_pos = 0; + goto exit; + } + barrier = MSDOS_I(dir)->i_last_pos; + cpos = 0; + goto rescan; } static int fat_readdirx( diff -urN linux-2.2.10-ac6/fs/fat/inode.c linux-bird.dir/fs/fat/inode.c --- linux-2.2.10-ac6/fs/fat/inode.c Fri Jul 2 00:39:12 1999 +++ linux-bird.dir/fs/fat/inode.c Fri Jul 2 00:40:11 1999 @@ -371,6 +371,7 @@ inode->i_uid = MSDOS_SB(sb)->options.fs_uid; inode->i_gid = MSDOS_SB(sb)->options.fs_gid; inode->i_version = ++event; + MSDOS_I(inode)->i_last_pos = 0; inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(sb)->options.fs_umask) | S_IFDIR; inode->i_op = MSDOS_SB(sb)->dir_ops; if (MSDOS_SB(sb)->fat_bits == 32) { @@ -760,6 +761,7 @@ inode->i_gid = MSDOS_SB(sb)->options.fs_gid; inode->i_version = ++event; if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { + MSDOS_I(inode)->i_last_pos = 0; inode->i_mode = MSDOS_MKMODE(de->attr,S_IRWXUGO & ~MSDOS_SB(sb)->options.fs_umask) | S_IFDIR; inode->i_op = MSDOS_SB(inode->i_sb)->dir_ops; diff -urN linux-2.2.10-ac6/fs/fat/misc.c linux-bird.dir/fs/fat/misc.c --- linux-2.2.10-ac6/fs/fat/misc.c Fri Jul 2 00:39:12 1999 +++ linux-bird.dir/fs/fat/misc.c Fri Jul 2 00:40:11 1999 @@ -353,8 +353,6 @@ *bh = NULL; if ((sector = fat_smap(dir,offset >> SECTOR_BITS)) == -1) return -1; - PRINTK (("get_entry sector %d %p\n",sector,*bh)); - PRINTK (("get_entry sector apres brelse\n")); if (!sector) return -1; /* beyond EOF */ *pos += sizeof(struct msdos_dir_entry); @@ -362,13 +360,12 @@ printk("Directory sread (sector 0x%x) failed\n",sector); continue; } - PRINTK (("get_entry apres sread\n")); - *de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset & - (SECTOR_SIZE-1))); - *ino = (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >> - MSDOS_DIR_BITS); - return 0; + break; } + *de = (struct msdos_dir_entry*)((*bh)->b_data+(offset&(SECTOR_SIZE-1))); + *ino = (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >> + MSDOS_DIR_BITS); + return 0; } diff -urN linux-2.2.10-ac6/fs/vfat/namei.c linux-bird.dir/fs/vfat/namei.c --- linux-2.2.10-ac6/fs/vfat/namei.c Fri Jul 2 00:39:14 1999 +++ linux-bird.dir/fs/vfat/namei.c Fri Jul 2 00:40:11 1999 @@ -977,6 +977,7 @@ mark_inode_dirty(inode); inode->i_version = ++event; dir->i_version = event; + MSDOS_I(dir)->i_last_pos = 0; dentry->d_time = dentry->d_parent->d_inode->i_version; d_instantiate(dentry,inode); return 0; @@ -1022,6 +1023,7 @@ dir->i_mtime = CURRENT_TIME; dir->i_atime = CURRENT_TIME; dir->i_version = ++event; + MSDOS_I(dir)->i_last_pos = 0; mark_inode_dirty(dir); de->name[0] = DELETED_FLAG; fat_mark_buffer_dirty(sb, bh, 1); @@ -1108,6 +1110,7 @@ mark_inode_dirty(inode); inode->i_version = ++event; dir->i_version = event; + MSDOS_I(dir)->i_last_pos = 0; dir->i_nlink++; inode->i_nlink = 2; /* no need to mark them dirty */ @@ -1179,6 +1182,7 @@ } new_dir->i_version = ++event; + MSDOS_I(new_dir)->i_last_pos = 0; /* releases old_bh */ vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de); diff -urN linux-2.2.10-ac6/include/linux/msdos_fs_i.h linux-bird.dir/include/linux/msdos_fs_i.h --- linux-2.2.10-ac6/include/linux/msdos_fs_i.h Fri Jul 2 00:39:17 1999 +++ linux-bird.dir/include/linux/msdos_fs_i.h Fri Jul 2 00:40:11 1999 @@ -29,12 +29,11 @@ int i_logstart; /* logical first cluster */ int i_attrs; /* unused attribute bits */ int i_ctime_ms; /* unused change time in milliseconds */ - int i_busy; /* file is either deleted but still open, or - inconsistent (mkdir) */ int i_binary; /* file contains non-text data */ int i_location; /* on-disk position of directory entry or 0 */ struct inode *i_fat_inode; /* struct inode of this one */ struct list_head i_fat_hash; /* hash by i_location */ + off_t i_last_pos;/* position of last lookup */ }; #endif
| |