@@ -1289,9 +1289,9 @@ xfs_seek_hole(
12891289 struct xfs_inode * ip = XFS_I (inode );
12901290 struct xfs_mount * mp = ip -> i_mount ;
12911291 loff_t uninitialized_var (offset );
1292- loff_t holeoff ;
12931292 xfs_fsize_t isize ;
12941293 xfs_fileoff_t fsbno ;
1294+ xfs_filblks_t end ;
12951295 uint lock ;
12961296 int error ;
12971297
@@ -1307,21 +1307,77 @@ xfs_seek_hole(
13071307 }
13081308
13091309 fsbno = XFS_B_TO_FSBT (mp , start );
1310- error = xfs_bmap_first_unused (NULL , ip , 1 , & fsbno , XFS_DATA_FORK );
1311- if (error )
1312- goto out_unlock ;
1310+ end = XFS_B_TO_FSB (mp , isize );
1311+
1312+ for (;;) {
1313+ struct xfs_bmbt_irec map [2 ];
1314+ int nmap = 2 ;
1315+ unsigned int i ;
1316+
1317+ error = xfs_bmapi_read (ip , fsbno , end - fsbno , map , & nmap ,
1318+ XFS_BMAPI_ENTIRE );
1319+ if (error )
1320+ goto out_unlock ;
1321+
1322+ /* No extents at given offset, must be beyond EOF */
1323+ if (nmap == 0 ) {
1324+ error = ENXIO ;
1325+ goto out_unlock ;
1326+ }
1327+
1328+ for (i = 0 ; i < nmap ; i ++ ) {
1329+ offset = max_t (loff_t , start ,
1330+ XFS_FSB_TO_B (mp , map [i ].br_startoff ));
1331+
1332+ /* Landed in a hole */
1333+ if (map [i ].br_startblock == HOLESTARTBLOCK )
1334+ goto out ;
1335+
1336+ /*
1337+ * Landed in an unwritten extent, try to search hole
1338+ * from page cache.
1339+ */
1340+ if (map [i ].br_state == XFS_EXT_UNWRITTEN ) {
1341+ if (xfs_find_get_desired_pgoff (inode , & map [i ],
1342+ HOLE_OFF , & offset ))
1343+ goto out ;
1344+ }
1345+ }
13131346
1314- holeoff = XFS_FSB_TO_B (mp , fsbno );
1315- if (holeoff <= start )
1316- offset = start ;
1317- else {
13181347 /*
1319- * xfs_bmap_first_unused() could return a value bigger than
1320- * isize if there are no more holes past the supplied offset.
1348+ * map[0] contains data or its unwritten but contains
1349+ * data in page cache, probably means that we are
1350+ * reading after EOF. We should fix offset to point
1351+ * to the end of the file(i.e., there is an implicit
1352+ * hole at the end of any file).
13211353 */
1322- offset = min_t (loff_t , holeoff , isize );
1354+ if (nmap == 1 ) {
1355+ offset = isize ;
1356+ break ;
1357+ }
1358+
1359+ ASSERT (i > 1 );
1360+
1361+ /*
1362+ * Both mappings contains data, proceed to the next round of
1363+ * search if the current reading offset not beyond or hit EOF.
1364+ */
1365+ fsbno = map [i - 1 ].br_startoff + map [i - 1 ].br_blockcount ;
1366+ start = XFS_FSB_TO_B (mp , fsbno );
1367+ if (start >= isize ) {
1368+ offset = isize ;
1369+ break ;
1370+ }
13231371 }
13241372
1373+ out :
1374+ /*
1375+ * At this point, we must have found a hole. However, the returned
1376+ * offset may be bigger than the file size as it may be aligned to
1377+ * page boundary for unwritten extents, we need to deal with this
1378+ * situation in particular.
1379+ */
1380+ offset = min_t (loff_t , offset , isize );
13251381 if (offset != file -> f_pos )
13261382 file -> f_pos = offset ;
13271383
0 commit comments