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;
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;
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;
}
out:
+ kfree(ra);
return err;
}
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;
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)
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;
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;
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;
*
* 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;
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);
}
}
/*
- * 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;
}
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;
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;
}
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;
}
u64 vbo, const void *buf, size_t bytes, int sync);
struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi,
const struct runs_tree *run, u64 vbo);
-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_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_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);
+static inline 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)
+{
+ return ntfs_read_run_nb_ra(sbi, run, vbo, buf, bytes, nb, NULL);
+}
+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);
+static inline 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)
+{
+ return ntfs_read_bh_ra(sbi, run, vbo, rhdr, bytes, nb, NULL);
+}
+
int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
u32 bytes, struct ntfs_buffers *nb);
int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr,
const struct ATTRIB *attr, enum index_mutex_classed type);
struct INDEX_ROOT *indx_get_root(struct ntfs_index *indx, struct ntfs_inode *ni,
struct ATTRIB **attr, struct mft_inode **mi);
-int indx_read(struct ntfs_index *idx, struct ntfs_inode *ni, CLST vbn,
- struct indx_node **node);
+int indx_read_ra(struct ntfs_index *idx, struct ntfs_inode *ni, CLST vbn,
+ struct indx_node **node, struct file_ra_state *ra);
+static inline int indx_read(struct ntfs_index *idx, struct ntfs_inode *ni,
+ CLST vbn, struct indx_node **node)
+{
+ return indx_read_ra(idx, ni, vbn, node, NULL);
+}
int indx_find(struct ntfs_index *indx, struct ntfs_inode *dir,
const struct INDEX_ROOT *root, const void *Key, size_t KeyLen,
const void *param, int *diff, struct NTFS_DE **entry,