xfs: xfs_seek_hole() refinement with hole searching from page cache for unwritten extent
PATCH v7 4/4 xfs: xfs_seek_hole() refinement with hole searching from page cache for unwritten extent
Improve xfs_seek_hole() to search hole offset from page cache for unwritten extents.
Signed-off-by Jie Liu <[email protected]>
--- fs/xfs/xfs_file.c | 76 +++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 65 insertions(+), 11 deletions(-)
fs/xfs/xfs_file.c +65 -11
@@ -1288,9 +1288,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;
@@ -1306,21 +1306,75 @@ 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 ; +unsigned int i; + + 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; + } + +for (i =0 ; i < nmap; i++) { + offset =max_t (loff_t, start, +XFS_FSB_TO_B (mp, map[i].br_startoff)); + +/* Landed in a hole */ +if (map[i].br_startblock ==HOLESTARTBLOCK ) + goto out; + +/* +* Landed in an unwritten extent, try to search hole +* from page cache. +*/ +if (map[i].br_state ==XFS_EXT_UNWRITTEN ) { +if (xfs_find_get_desired_pgoff (inode, &map[i], +HOLE_OFF , &offset)) + goto out; + } + } + +/* +* 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 ; + } - holeoff =XFS_FSB_TO_B (mp, fsbno); -if (holeoff <= start) - offset = start; -else {/* -* xfs_bmap_first_unused() could return a value bigger than -* isize if there are no more holes past the supplied offset. +* Both mappings contains data, proceed to the next round of +* search if the current reading offset not beyond or hit EOF. */ - offset =min_t (loff_t, holeoff, isize); + fsbno = map[i -1 ].br_startoff + map[i -1 ].br_blockcount; + start =XFS_FSB_TO_B (mp, fsbno); +if (start >= isize) { + offset = isize; +break ; + } } +out: +/* +* 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 3 lines · Jeff Liu
Improve
xfs_seek_hole()to search hole offset from page cache for unwritten extents.Signed-off-by Jie Liu<[email protected]>
Looks good.
Reviewed-by Mark Tinguely <[email protected]>
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 3 lines · Jeff Liu
Improve
xfs_seek_hole()to search hole offset from page cache for unwritten extents.Signed-off-by Jie Liu <[email protected]>
same as previous patch.
Reviewed-by Dave Chinner <[email protected]>
Quoted 7 lines
fs/xfs/xfs_file.c +5
-1+*/ +if (nmap ==1 ) { + offset = isize; +break ; + } - holeoff =XFS_FSB_TO_B (mp, fsbno);
fs/xfs/xfs_file.c xfs_seek_hole( · line 1321
Quoted 10 lines
fs/xfs/xfs_file.c +2
-6-if (holeoff <= start) - offset = start; -else {/* -* xfs_bmap_first_unused() could return a value bigger than -* isize if there are no more holes past the supplied offset. +* Both mappings contains data, proceed to the next round of +* search if the current reading offset not beyond or hit EOF. */ - offset =min_t (loff_t, holeoff, isize);
ASSERT(i > 1);
fs/xfs/xfs_file.c xfs_seek_hole( · line 1368
Quoted 7 lines
fs/xfs/xfs_file.c +6
-0+ fsbno = map[i -1 ].br_startoff + map[i -1 ].br_blockcount; + start =XFS_FSB_TO_B (mp, fsbno); +if (start >= isize) { + offset = isize; +break ; + } }
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs