aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-09-07 17:05:51 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-10-12 14:54:39 -0400
commit6798d35a31c413bbb3f83bbaa844bd2598168ccc (patch)
treeff3e2928ebdfda06f08605d9dbc7002f0413e731 /fs/ocfs2
parent15b1e36bdb487d67ef924a37b0967453143be53a (diff)
ocfs2: Read support for inline data
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>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/aops.c80
-rw-r--r--fs/ocfs2/extent_map.c6
2 files changed, 82 insertions, 4 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 8416e383197c..fef0186a91cd 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -206,9 +206,70 @@ bail:
206 return err; 206 return err;
207} 207}
208 208
209static int ocfs2_read_inline_data(struct inode *inode, struct page *page,
210 struct buffer_head *di_bh)
211{
212 void *kaddr;
213 unsigned int size;
214 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
215
216 if (!(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL)) {
217 ocfs2_error(inode->i_sb, "Inode %llu lost inline data flag",
218 (unsigned long long)OCFS2_I(inode)->ip_blkno);
219 return -EROFS;
220 }
221
222 size = i_size_read(inode);
223
224 if (size > PAGE_CACHE_SIZE ||
225 size > ocfs2_max_inline_data(inode->i_sb)) {
226 ocfs2_error(inode->i_sb,
227 "Inode %llu has with inline data has bad size: %u",
228 (unsigned long long)OCFS2_I(inode)->ip_blkno, size);
229 return -EROFS;
230 }
231
232 kaddr = kmap_atomic(page, KM_USER0);
233 if (size)
234 memcpy(kaddr, di->id2.i_data.id_data, size);
235 /* Clear the remaining part of the page */
236 memset(kaddr + size, 0, PAGE_CACHE_SIZE - size);
237 flush_dcache_page(page);
238 kunmap_atomic(kaddr, KM_USER0);
239
240 SetPageUptodate(page);
241
242 return 0;
243}
244
245static int ocfs2_readpage_inline(struct inode *inode, struct page *page)
246{
247 int ret;
248 struct buffer_head *di_bh = NULL;
249 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
250
251 BUG_ON(!PageLocked(page));
252 BUG_ON(!OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
253
254 ret = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &di_bh,
255 OCFS2_BH_CACHED, inode);
256 if (ret) {
257 mlog_errno(ret);
258 goto out;
259 }
260
261 ret = ocfs2_read_inline_data(inode, page, di_bh);
262out:
263 unlock_page(page);
264
265 brelse(di_bh);
266 return ret;
267}
268
209static int ocfs2_readpage(struct file *file, struct page *page) 269static int ocfs2_readpage(struct file *file, struct page *page)
210{ 270{
211 struct inode *inode = page->mapping->host; 271 struct inode *inode = page->mapping->host;
272 struct ocfs2_inode_info *oi = OCFS2_I(inode);
212 loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; 273 loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT;
213 int ret, unlock = 1; 274 int ret, unlock = 1;
214 275
@@ -222,7 +283,7 @@ static int ocfs2_readpage(struct file *file, struct page *page)
222 goto out; 283 goto out;
223 } 284 }
224 285
225 if (down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem) == 0) { 286 if (down_read_trylock(&oi->ip_alloc_sem) == 0) {
226 ret = AOP_TRUNCATED_PAGE; 287 ret = AOP_TRUNCATED_PAGE;
227 goto out_meta_unlock; 288 goto out_meta_unlock;
228 } 289 }
@@ -252,7 +313,10 @@ static int ocfs2_readpage(struct file *file, struct page *page)
252 goto out_alloc; 313 goto out_alloc;
253 } 314 }
254 315
255 ret = block_read_full_page(page, ocfs2_get_block); 316 if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL)
317 ret = ocfs2_readpage_inline(inode, page);
318 else
319 ret = block_read_full_page(page, ocfs2_get_block);
256 unlock = 0; 320 unlock = 0;
257 321
258 ocfs2_data_unlock(inode, 0); 322 ocfs2_data_unlock(inode, 0);
@@ -397,7 +461,9 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
397 down_read(&OCFS2_I(inode)->ip_alloc_sem); 461 down_read(&OCFS2_I(inode)->ip_alloc_sem);
398 } 462 }
399 463
400 err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL, NULL); 464 if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL))
465 err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
466 NULL);
401 467
402 if (!INODE_JOURNAL(inode)) { 468 if (!INODE_JOURNAL(inode)) {
403 up_read(&OCFS2_I(inode)->ip_alloc_sem); 469 up_read(&OCFS2_I(inode)->ip_alloc_sem);
@@ -411,7 +477,6 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
411 goto bail; 477 goto bail;
412 } 478 }
413 479
414
415bail: 480bail:
416 status = err ? 0 : p_blkno; 481 status = err ? 0 : p_blkno;
417 482
@@ -566,6 +631,13 @@ static ssize_t ocfs2_direct_IO(int rw,
566 631
567 mlog_entry_void(); 632 mlog_entry_void();
568 633
634 /*
635 * Fallback to buffered I/O if we see an inode without
636 * extents.
637 */
638 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
639 return 0;
640
569 if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) { 641 if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) {
570 /* 642 /*
571 * We get PR data locks even for O_DIRECT. This 643 * We get PR data locks even for O_DIRECT. This
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index 03c1d365c78b..c58668a326fe 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -387,6 +387,12 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
387 struct ocfs2_extent_rec *rec; 387 struct ocfs2_extent_rec *rec;
388 u32 coff; 388 u32 coff;
389 389
390 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
391 ret = -ERANGE;
392 mlog_errno(ret);
393 goto out;
394 }
395
390 ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster, 396 ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster,
391 num_clusters, extent_flags); 397 num_clusters, extent_flags);
392 if (ret == 0) 398 if (ret == 0)