xfs: xfs_seek_hole() refinement with lookup hole offset from page cache
PATCH v6 4/4 xfs: xfs_seek_hole() refinement with lookup hole offset from page cache
xfs_seek_hole() refinement with hole searching from page cache for unwritten extent.
Signed-off-by Jie Liu <[email protected]>
--- fs/xfs/xfs_file.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 69 insertions(+), 10 deletions(-)
fs/xfs/xfs_file.c +69 -10
@@ -1295,9 +1295,9 @@ xfs_seek_hole(struct xfs_inode *ip =XFS_I (inode);struct xfs_mount *mp = ip->i_mount;loff_t uninitialized_var (offset ); -loff_t holeoff;xfs_fsize_t isize;xfs_fileoff_t fsbno; +xfs_filblks_t end;uint lock;int error;
@@ -1313,21 +1313,80 @@ xfs_seek_hole( } fsbno =XFS_B_TO_FSBT (mp, start); - error =xfs_bmap_first_unused (NULL , ip,1 , &fsbno,XFS_DATA_FORK ); -if (error) - goto out_unlock; + end =XFS_B_TO_FSB (mp, isize); + +for (;;) { +struct xfs_bmbt_irec map[2 ]; +int nmap =2 ; + + error =xfs_bmapi_read (ip, fsbno, end - fsbno, map, &nmap, +XFS_BMAPI_ENTIRE ); +if (error) + goto out_unlock; + +/* No extents at given offset, must be beyond EOF */ +if (nmap ==0 ) { + error =ENXIO ; + goto out_unlock; + } - holeoff =XFS_FSB_TO_B (mp, fsbno); -if (holeoff <= start) offset = start; -else { +/* Landed in a hole */ +if (map[0 ].br_startblock ==HOLESTARTBLOCK ) +break ; +/* -* xfs_bmap_first_unused() could return a value bigger than -* isize if there are no more holes past the supplied offset. +* Landed in an unwritten extent, try to search hole from +* page cache. */ - offset =min_t (loff_t, holeoff, isize); +if (map[0 ].br_state ==XFS_EXT_UNWRITTEN ) { +if (xfs_find_get_desired_pgoff (inode, &map[0 ], +HOLE_OFF , &offset)) +break ; + } + +/* +* map[0] contains data or its unwritten but contains +* data in page cache, probably means that we are +* reading after EOF. We should fix offset to point +* to the end of the file(i.e., there is an implicit +* hole at the end of any file). +*/ +if (nmap ==1 ) { + offset = isize; +break ; + } + +/* We have two mappings, proceed to check map[1] */ + offset =XFS_FSB_TO_B (mp, map[1 ].br_startoff); +if (map[1 ].br_startblock ==HOLESTARTBLOCK ) +break ; + +if (map[1 ].br_state ==XFS_EXT_UNWRITTEN ) { +if (xfs_find_get_desired_pgoff (inode, &map[1 ], +HOLE_OFF , &offset)) +break ; + } + +/* +* Both mappings contains data, proceed to the next round of +* search if the current reading offset not beyond or hit EOF. +*/ + fsbno = map[1 ].br_startoff + map[1 ].br_blockcount; + start =XFS_FSB_TO_B (mp, fsbno); +if (start >= isize) { + offset = isize; +break ; + } } +/* +* At this point, we must have found a hole. However, the returned +* offset may be bigger than the file size as it may be aligned to +* page boundary for unwritten extents, we need to deal with this +* situation in particular. +*/ + offset =min_t (loff_t, offset, isize);if (offset != file->f_pos) file->f_pos = offset;
Signature · 6 lines
1.7.4.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 6 lines · Jeff Liu
xfs_seek_hole()refinement with hole searching from page cache for unwritten extent.Signed-off-by Jie Liu<[email protected]>---
Looks great.
Reviewed-by Mark Tinguely <[email protected]>
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 1 line · Jeff Liu
xfs_seek_hole()refinement with hole searching from page cache for unwritten extent.
Same comment about duplicate code and loops...
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs