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

Configure Feed

Select the types of activity you want to include in your feed.

fs/ntfs3: improve readahead for bitmap initialization and large directory scans

Previously sequential reads operations relied solely on single-page reads,
causing the block layer to perform many synchronous I/O requests,
especially for large volumes or large directories. This patch introduces
explicit readahead via page_cache_sync_readahead() and file_ra_state to
reduce I/O latency and improve sequential throughput.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>

+79 -25
+17
fs/ntfs3/bitmap.c
··· 508 508 size_t wpos, wbit, iw, vbo; 509 509 struct buffer_head *bh = NULL; 510 510 CLST lcn, clen; 511 + struct file_ra_state *ra; 512 + struct address_space *mapping = sb->s_bdev->bd_mapping; 511 513 512 514 wnd->uptodated = 0; 513 515 wnd->extent_max = 0; ··· 517 515 wnd->total_zeroes = 0; 518 516 519 517 vbo = 0; 518 + 519 + /* Allocate in memory instead of stack. Not critical if failed. */ 520 + ra = kzalloc(sizeof(*ra), GFP_NOFS); 521 + if (ra) { 522 + file_ra_state_init(ra, mapping); 523 + ra->ra_pages = (wnd->nbits / 8 + PAGE_SIZE - 1) >> PAGE_SHIFT; 524 + } 520 525 521 526 for (iw = 0; iw < wnd->nwnd; iw++) { 522 527 if (iw + 1 == wnd->nwnd) ··· 559 550 560 551 lbo = ((u64)lcn << cluster_bits) + off; 561 552 len = ((u64)clen << cluster_bits) - off; 553 + } 554 + 555 + if (ra) { 556 + pgoff_t idx = lbo >> PAGE_SHIFT; 557 + if (!ra_has_index(ra, idx)) 558 + page_cache_sync_readahead(mapping, ra, NULL, 559 + idx, 1); 562 560 } 563 561 564 562 bh = ntfs_bread(sb, lbo >> sb->s_blocksize_bits); ··· 654 638 } 655 639 656 640 out: 641 + kfree(ra); 657 642 return err; 658 643 } 659 644
+2 -2
fs/ntfs3/dir.c
··· 487 487 goto out; 488 488 } 489 489 490 - err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits, 491 - &node); 490 + err = indx_read_ra(&ni->dir, ni, bit << ni->dir.idx2vbn_bits, 491 + &node, &file->f_ra); 492 492 if (err) 493 493 goto out; 494 494
+4 -2
fs/ntfs3/fslog.c
··· 1074 1074 u32 client_undo_commit; 1075 1075 1076 1076 struct restart_info rst_info, rst_info2; 1077 + 1078 + struct file_ra_state read_ahead; 1077 1079 }; 1078 1080 1079 1081 static inline u32 lsn_to_vbo(struct ntfs_log *log, const u64 lsn) ··· 1166 1164 1167 1165 page_buf = page_off ? log->one_page_buf : *buffer; 1168 1166 1169 - err = ntfs_read_run_nb(ni->mi.sbi, &ni->file.run, page_vbo, page_buf, 1170 - log->page_size, NULL); 1167 + err = ntfs_read_run_nb_ra(ni->mi.sbi, &ni->file.run, page_vbo, page_buf, 1168 + log->page_size, NULL, &log->read_ahead); 1171 1169 if (err) 1172 1170 goto out; 1173 1171
+21 -8
fs/ntfs3/fsntfs.c
··· 1164 1164 return ntfs_bread(sb, lbo >> sb->s_blocksize_bits); 1165 1165 } 1166 1166 1167 - int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run, 1168 - u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb) 1167 + int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run, 1168 + u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb, 1169 + struct file_ra_state *ra) 1169 1170 { 1170 1171 int err; 1171 1172 struct super_block *sb = sbi->sb; 1173 + struct address_space *mapping = sb->s_bdev->bd_mapping; 1172 1174 u32 blocksize = sb->s_blocksize; 1173 1175 u8 cluster_bits = sbi->cluster_bits; 1174 1176 u32 off = vbo & sbi->cluster_mask; ··· 1210 1208 nb->bytes = bytes; 1211 1209 } 1212 1210 1211 + if (ra && !ra->ra_pages) 1212 + file_ra_state_init(ra, mapping); 1213 + 1213 1214 for (;;) { 1214 1215 u32 len32 = len >= bytes ? bytes : len; 1215 1216 sector_t block = lbo >> sb->s_blocksize_bits; 1217 + 1218 + if (ra) { 1219 + pgoff_t index = lbo >> PAGE_SHIFT; 1220 + if (!ra_has_index(ra, index)) { 1221 + page_cache_sync_readahead(mapping, ra, NULL, 1222 + index, 1); 1223 + ra->prev_pos = (loff_t)index << PAGE_SHIFT; 1224 + } 1225 + } 1216 1226 1217 1227 do { 1218 1228 u32 op = blocksize - off; ··· 1296 1282 * 1297 1283 * Return: < 0 if error, 0 if ok, -E_NTFS_FIXUP if need to update fixups. 1298 1284 */ 1299 - int ntfs_read_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo, 1300 - struct NTFS_RECORD_HEADER *rhdr, u32 bytes, 1301 - struct ntfs_buffers *nb) 1285 + int ntfs_read_bh_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run, 1286 + u64 vbo, struct NTFS_RECORD_HEADER *rhdr, u32 bytes, 1287 + struct ntfs_buffers *nb, struct file_ra_state *ra) 1302 1288 { 1303 - int err = ntfs_read_run_nb(sbi, run, vbo, rhdr, bytes, nb); 1289 + int err = ntfs_read_run_nb_ra(sbi, run, vbo, rhdr, bytes, nb, ra); 1304 1290 1305 1291 if (err) 1306 1292 return err; ··· 1361 1347 wait_on_buffer(bh); 1362 1348 1363 1349 lock_buffer(bh); 1364 - if (!buffer_uptodate(bh)) 1365 - { 1350 + if (!buffer_uptodate(bh)) { 1366 1351 memset(bh->b_data, 0, blocksize); 1367 1352 set_buffer_uptodate(bh); 1368 1353 }
+7 -6
fs/ntfs3/index.c
··· 1026 1026 } 1027 1027 1028 1028 /* 1029 - * indx_read 1029 + * indx_read_ra 1030 1030 * 1031 1031 * If ntfs_readdir calls this function 1032 1032 * inode is shared locked and no ni_lock. 1033 1033 * Use rw_semaphore for read/write access to alloc_run. 1034 1034 */ 1035 - int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn, 1036 - struct indx_node **node) 1035 + int indx_read_ra(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn, 1036 + struct indx_node **node, struct file_ra_state *ra) 1037 1037 { 1038 1038 int err; 1039 1039 struct INDEX_BUFFER *ib; 1040 + struct ntfs_sb_info *sbi = ni->mi.sbi; 1040 1041 struct runs_tree *run = &indx->alloc_run; 1041 1042 struct rw_semaphore *lock = &indx->run_lock; 1042 1043 u64 vbo = (u64)vbn << indx->vbn2vbo_bits; ··· 1063 1062 } 1064 1063 1065 1064 down_read(lock); 1066 - err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb); 1065 + err = ntfs_read_bh_ra(sbi, run, vbo, &ib->rhdr, bytes, &in->nb, ra); 1067 1066 up_read(lock); 1068 1067 if (!err) 1069 1068 goto ok; ··· 1083 1082 goto out; 1084 1083 1085 1084 down_read(lock); 1086 - err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb); 1085 + err = ntfs_read_bh_ra(sbi, run, vbo, &ib->rhdr, bytes, &in->nb, ra); 1087 1086 up_read(lock); 1088 1087 if (err == -E_NTFS_FIXUP) 1089 1088 goto ok; ··· 1099 1098 } 1100 1099 1101 1100 if (err == -E_NTFS_FIXUP) { 1102 - ntfs_write_bh(ni->mi.sbi, &ib->rhdr, &in->nb, 0); 1101 + ntfs_write_bh(sbi, &ib->rhdr, &in->nb, 0); 1103 1102 err = 0; 1104 1103 } 1105 1104
+28 -7
fs/ntfs3/ntfs_fs.h
··· 625 625 u64 vbo, const void *buf, size_t bytes, int sync); 626 626 struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi, 627 627 const struct runs_tree *run, u64 vbo); 628 - int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run, 629 - u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb); 630 - int ntfs_read_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo, 631 - struct NTFS_RECORD_HEADER *rhdr, u32 bytes, 632 - struct ntfs_buffers *nb); 628 + int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run, 629 + u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb, 630 + struct file_ra_state *ra); 631 + static inline int ntfs_read_run_nb(struct ntfs_sb_info *sbi, 632 + const struct runs_tree *run, u64 vbo, 633 + void *buf, u32 bytes, 634 + struct ntfs_buffers *nb) 635 + { 636 + return ntfs_read_run_nb_ra(sbi, run, vbo, buf, bytes, nb, NULL); 637 + } 638 + int ntfs_read_bh_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run, 639 + u64 vbo, struct NTFS_RECORD_HEADER *rhdr, u32 bytes, 640 + struct ntfs_buffers *nb, struct file_ra_state *ra); 641 + static inline int ntfs_read_bh(struct ntfs_sb_info *sbi, 642 + const struct runs_tree *run, u64 vbo, 643 + struct NTFS_RECORD_HEADER *rhdr, u32 bytes, 644 + struct ntfs_buffers *nb) 645 + { 646 + return ntfs_read_bh_ra(sbi, run, vbo, rhdr, bytes, nb, NULL); 647 + } 648 + 633 649 int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo, 634 650 u32 bytes, struct ntfs_buffers *nb); 635 651 int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr, ··· 711 695 const struct ATTRIB *attr, enum index_mutex_classed type); 712 696 struct INDEX_ROOT *indx_get_root(struct ntfs_index *indx, struct ntfs_inode *ni, 713 697 struct ATTRIB **attr, struct mft_inode **mi); 714 - int indx_read(struct ntfs_index *idx, struct ntfs_inode *ni, CLST vbn, 715 - struct indx_node **node); 698 + int indx_read_ra(struct ntfs_index *idx, struct ntfs_inode *ni, CLST vbn, 699 + struct indx_node **node, struct file_ra_state *ra); 700 + static inline int indx_read(struct ntfs_index *idx, struct ntfs_inode *ni, 701 + CLST vbn, struct indx_node **node) 702 + { 703 + return indx_read_ra(idx, ni, vbn, node, NULL); 704 + } 716 705 int indx_find(struct ntfs_index *indx, struct ntfs_inode *dir, 717 706 const struct INDEX_ROOT *root, const void *Key, size_t KeyLen, 718 707 const void *param, int *diff, struct NTFS_DE **entry,