Unverified Commit 989e2945 authored by Konstantin Komarov's avatar Konstantin Komarov
Browse files

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: default avatarKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
parent 4248f563
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -508,6 +508,8 @@ static int wnd_rescan(struct wnd_bitmap *wnd)
	size_t wpos, wbit, iw, vbo;
	struct buffer_head *bh = NULL;
	CLST lcn, clen;
	struct file_ra_state *ra;
	struct address_space *mapping = sb->s_bdev->bd_mapping;

	wnd->uptodated = 0;
	wnd->extent_max = 0;
@@ -516,6 +518,13 @@ static int wnd_rescan(struct wnd_bitmap *wnd)

	vbo = 0;

	/* Allocate in memory instead of stack. Not critical if failed. */
	ra = kzalloc(sizeof(*ra), GFP_NOFS);
	if (ra) {
		file_ra_state_init(ra, mapping);
		ra->ra_pages = (wnd->nbits / 8 + PAGE_SIZE - 1) >> PAGE_SHIFT;
	}

	for (iw = 0; iw < wnd->nwnd; iw++) {
		if (iw + 1 == wnd->nwnd)
			wbits = wnd->bits_last;
@@ -552,6 +561,13 @@ static int wnd_rescan(struct wnd_bitmap *wnd)
			len = ((u64)clen << cluster_bits) - off;
		}

		if (ra) {
			pgoff_t idx = lbo >> PAGE_SHIFT;
			if (!ra_has_index(ra, idx))
				page_cache_sync_readahead(mapping, ra, NULL,
							  idx, 1);
		}

		bh = ntfs_bread(sb, lbo >> sb->s_blocksize_bits);
		if (!bh) {
			err = -EIO;
@@ -638,6 +654,7 @@ static int wnd_rescan(struct wnd_bitmap *wnd)
	}

out:
	kfree(ra);
	return err;
}

+2 −2
Original line number Diff line number Diff line
@@ -487,8 +487,8 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
			goto out;
		}

		err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
				&node);
		err = indx_read_ra(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
				   &node, &file->f_ra);
		if (err)
			goto out;

+4 −2
Original line number Diff line number Diff line
@@ -1074,6 +1074,8 @@ struct ntfs_log {
	u32 client_undo_commit;

	struct restart_info rst_info, rst_info2;

	struct file_ra_state read_ahead;
};

static inline u32 lsn_to_vbo(struct ntfs_log *log, const u64 lsn)
@@ -1164,8 +1166,8 @@ static int read_log_page(struct ntfs_log *log, u32 vbo,

	page_buf = page_off ? log->one_page_buf : *buffer;

	err = ntfs_read_run_nb(ni->mi.sbi, &ni->file.run, page_vbo, page_buf,
			       log->page_size, NULL);
	err = ntfs_read_run_nb_ra(ni->mi.sbi, &ni->file.run, page_vbo, page_buf,
				  log->page_size, NULL, &log->read_ahead);
	if (err)
		goto out;

+21 −8
Original line number Diff line number Diff line
@@ -1164,11 +1164,13 @@ struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi,
	return ntfs_bread(sb, lbo >> sb->s_blocksize_bits);
}

int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run,
		     u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb)
int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run,
			u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb,
			struct file_ra_state *ra)
{
	int err;
	struct super_block *sb = sbi->sb;
	struct address_space *mapping = sb->s_bdev->bd_mapping;
	u32 blocksize = sb->s_blocksize;
	u8 cluster_bits = sbi->cluster_bits;
	u32 off = vbo & sbi->cluster_mask;
@@ -1208,10 +1210,22 @@ int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run,
		nb->bytes = bytes;
	}

	if (ra && !ra->ra_pages)
		file_ra_state_init(ra, mapping);

	for (;;) {
		u32 len32 = len >= bytes ? bytes : len;
		sector_t block = lbo >> sb->s_blocksize_bits;

		if (ra) {
			pgoff_t index = lbo >> PAGE_SHIFT;
			if (!ra_has_index(ra, index)) {
				page_cache_sync_readahead(mapping, ra, NULL,
							  index, 1);
				ra->prev_pos = (loff_t)index << PAGE_SHIFT;
			}
		}

		do {
			u32 op = blocksize - off;

@@ -1282,11 +1296,11 @@ int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run,
 *
 * Return: < 0 if error, 0 if ok, -E_NTFS_FIXUP if need to update fixups.
 */
int ntfs_read_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
		 struct NTFS_RECORD_HEADER *rhdr, u32 bytes,
		 struct ntfs_buffers *nb)
int ntfs_read_bh_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run,
		    u64 vbo, struct NTFS_RECORD_HEADER *rhdr, u32 bytes,
		    struct ntfs_buffers *nb, struct file_ra_state *ra)
{
	int err = ntfs_read_run_nb(sbi, run, vbo, rhdr, bytes, nb);
	int err = ntfs_read_run_nb_ra(sbi, run, vbo, rhdr, bytes, nb, ra);

	if (err)
		return err;
@@ -1347,8 +1361,7 @@ int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
				wait_on_buffer(bh);

				lock_buffer(bh);
				if (!buffer_uptodate(bh))
				{
				if (!buffer_uptodate(bh)) {
					memset(bh->b_data, 0, blocksize);
					set_buffer_uptodate(bh);
				}
+7 −6
Original line number Diff line number Diff line
@@ -1026,17 +1026,18 @@ static int indx_write(struct ntfs_index *indx, struct ntfs_inode *ni,
}

/*
 * indx_read
 * indx_read_ra
 *
 * If ntfs_readdir calls this function
 * inode is shared locked and no ni_lock.
 * Use rw_semaphore for read/write access to alloc_run.
 */
int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn,
	      struct indx_node **node)
int indx_read_ra(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn,
		 struct indx_node **node, struct file_ra_state *ra)
{
	int err;
	struct INDEX_BUFFER *ib;
	struct ntfs_sb_info *sbi = ni->mi.sbi;
	struct runs_tree *run = &indx->alloc_run;
	struct rw_semaphore *lock = &indx->run_lock;
	u64 vbo = (u64)vbn << indx->vbn2vbo_bits;
@@ -1062,7 +1063,7 @@ int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn,
	}

	down_read(lock);
	err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb);
	err = ntfs_read_bh_ra(sbi, run, vbo, &ib->rhdr, bytes, &in->nb, ra);
	up_read(lock);
	if (!err)
		goto ok;
@@ -1082,7 +1083,7 @@ int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn,
		goto out;

	down_read(lock);
	err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb);
	err = ntfs_read_bh_ra(sbi, run, vbo, &ib->rhdr, bytes, &in->nb, ra);
	up_read(lock);
	if (err == -E_NTFS_FIXUP)
		goto ok;
@@ -1098,7 +1099,7 @@ int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn,
	}

	if (err == -E_NTFS_FIXUP) {
		ntfs_write_bh(ni->mi.sbi, &ib->rhdr, &in->nb, 0);
		ntfs_write_bh(sbi, &ib->rhdr, &in->nb, 0);
		err = 0;
	}

Loading