Skip to content

Commit

Permalink
ocfs2: Read support for inline data
Browse files Browse the repository at this point in the history
This hooks up ocfs2_readpage() to populate a page with data from an inode
block. Direct IO reads from inline data are modified to fall back to
buffered I/O. Appropriate checks are also placed in the extent map code to
avoid reading an extent list when inline data might be stored.

Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Reviewed-by: Joel Becker <joel.becker@oracle.com>
  • Loading branch information
Mark Fasheh committed Oct 12, 2007
1 parent 15b1e36 commit 6798d35
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 4 deletions.
80 changes: 76 additions & 4 deletions fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,70 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
return err;
}

static int ocfs2_read_inline_data(struct inode *inode, struct page *page,
struct buffer_head *di_bh)
{
void *kaddr;
unsigned int size;
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;

if (!(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL)) {
ocfs2_error(inode->i_sb, "Inode %llu lost inline data flag",
(unsigned long long)OCFS2_I(inode)->ip_blkno);
return -EROFS;
}

size = i_size_read(inode);

if (size > PAGE_CACHE_SIZE ||
size > ocfs2_max_inline_data(inode->i_sb)) {
ocfs2_error(inode->i_sb,
"Inode %llu has with inline data has bad size: %u",
(unsigned long long)OCFS2_I(inode)->ip_blkno, size);
return -EROFS;
}

kaddr = kmap_atomic(page, KM_USER0);
if (size)
memcpy(kaddr, di->id2.i_data.id_data, size);
/* Clear the remaining part of the page */
memset(kaddr + size, 0, PAGE_CACHE_SIZE - size);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);

SetPageUptodate(page);

return 0;
}

static int ocfs2_readpage_inline(struct inode *inode, struct page *page)
{
int ret;
struct buffer_head *di_bh = NULL;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);

BUG_ON(!PageLocked(page));
BUG_ON(!OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);

ret = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &di_bh,
OCFS2_BH_CACHED, inode);
if (ret) {
mlog_errno(ret);
goto out;
}

ret = ocfs2_read_inline_data(inode, page, di_bh);
out:
unlock_page(page);

brelse(di_bh);
return ret;
}

static int ocfs2_readpage(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT;
int ret, unlock = 1;

Expand All @@ -222,7 +283,7 @@ static int ocfs2_readpage(struct file *file, struct page *page)
goto out;
}

if (down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem) == 0) {
if (down_read_trylock(&oi->ip_alloc_sem) == 0) {
ret = AOP_TRUNCATED_PAGE;
goto out_meta_unlock;
}
Expand Down Expand Up @@ -252,7 +313,10 @@ static int ocfs2_readpage(struct file *file, struct page *page)
goto out_alloc;
}

ret = block_read_full_page(page, ocfs2_get_block);
if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL)
ret = ocfs2_readpage_inline(inode, page);
else
ret = block_read_full_page(page, ocfs2_get_block);
unlock = 0;

ocfs2_data_unlock(inode, 0);
Expand Down Expand Up @@ -397,7 +461,9 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
down_read(&OCFS2_I(inode)->ip_alloc_sem);
}

err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL, NULL);
if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL))
err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
NULL);

if (!INODE_JOURNAL(inode)) {
up_read(&OCFS2_I(inode)->ip_alloc_sem);
Expand All @@ -411,7 +477,6 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
goto bail;
}


bail:
status = err ? 0 : p_blkno;

Expand Down Expand Up @@ -566,6 +631,13 @@ static ssize_t ocfs2_direct_IO(int rw,

mlog_entry_void();

/*
* Fallback to buffered I/O if we see an inode without
* extents.
*/
if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
return 0;

if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) {
/*
* We get PR data locks even for O_DIRECT. This
Expand Down
6 changes: 6 additions & 0 deletions fs/ocfs2/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
struct ocfs2_extent_rec *rec;
u32 coff;

if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
ret = -ERANGE;
mlog_errno(ret);
goto out;
}

ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster,
num_clusters, extent_flags);
if (ret == 0)
Expand Down

0 comments on commit 6798d35

Please sign in to comment.