Skip to content

Commit 8aa7d37

Browse files
Eric Sandeendchinner
authored andcommitted
xfs: Factor xfs_seek_hole_data into helper
Factor xfs_seek_hole_data into an unlocked helper which takes an xfs inode rather than a file for internal use. Also allow specification of "end" - the vfs lseek interface is defined such that any offset past eof/i_size shall return -ENXIO, but we will use this for quota code which does not maintain i_size, and we want to be able to SEEK_DATA past i_size as well. So the lseek path can send in i_size, and the quota code can determine its own ending offset. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
1 parent 4d4d952 commit 8aa7d37

File tree

2 files changed

+59
-25
lines changed

2 files changed

+59
-25
lines changed

fs/xfs/xfs_file.c

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,54 +1337,54 @@ xfs_find_get_desired_pgoff(
13371337
return found;
13381338
}
13391339

1340-
STATIC loff_t
1341-
xfs_seek_hole_data(
1342-
struct file *file,
1340+
/*
1341+
* caller must lock inode with xfs_ilock_data_map_shared,
1342+
* can we craft an appropriate ASSERT?
1343+
*
1344+
* end is because the VFS-level lseek interface is defined such that any
1345+
* offset past i_size shall return -ENXIO, but we use this for quota code
1346+
* which does not maintain i_size, and we want to SEEK_DATA past i_size.
1347+
*/
1348+
loff_t
1349+
__xfs_seek_hole_data(
1350+
struct inode *inode,
13431351
loff_t start,
1352+
loff_t end,
13441353
int whence)
13451354
{
1346-
struct inode *inode = file->f_mapping->host;
13471355
struct xfs_inode *ip = XFS_I(inode);
13481356
struct xfs_mount *mp = ip->i_mount;
13491357
loff_t uninitialized_var(offset);
1350-
xfs_fsize_t isize;
13511358
xfs_fileoff_t fsbno;
1352-
xfs_filblks_t end;
1353-
uint lock;
1359+
xfs_filblks_t lastbno;
13541360
int error;
13551361

1356-
if (XFS_FORCED_SHUTDOWN(mp))
1357-
return -EIO;
1358-
1359-
lock = xfs_ilock_data_map_shared(ip);
1360-
1361-
isize = i_size_read(inode);
1362-
if (start >= isize) {
1362+
if (start >= end) {
13631363
error = -ENXIO;
1364-
goto out_unlock;
1364+
goto out_error;
13651365
}
13661366

13671367
/*
13681368
* Try to read extents from the first block indicated
13691369
* by fsbno to the end block of the file.
13701370
*/
13711371
fsbno = XFS_B_TO_FSBT(mp, start);
1372-
end = XFS_B_TO_FSB(mp, isize);
1372+
lastbno = XFS_B_TO_FSB(mp, end);
13731373

13741374
for (;;) {
13751375
struct xfs_bmbt_irec map[2];
13761376
int nmap = 2;
13771377
unsigned int i;
13781378

1379-
error = xfs_bmapi_read(ip, fsbno, end - fsbno, map, &nmap,
1379+
error = xfs_bmapi_read(ip, fsbno, lastbno - fsbno, map, &nmap,
13801380
XFS_BMAPI_ENTIRE);
13811381
if (error)
1382-
goto out_unlock;
1382+
goto out_error;
13831383

13841384
/* No extents at given offset, must be beyond EOF */
13851385
if (nmap == 0) {
13861386
error = -ENXIO;
1387-
goto out_unlock;
1387+
goto out_error;
13881388
}
13891389

13901390
for (i = 0; i < nmap; i++) {
@@ -1426,15 +1426,15 @@ xfs_seek_hole_data(
14261426
* hole at the end of any file).
14271427
*/
14281428
if (whence == SEEK_HOLE) {
1429-
offset = isize;
1429+
offset = end;
14301430
break;
14311431
}
14321432
/*
14331433
* If we were looking for data, it's nowhere to be found
14341434
*/
14351435
ASSERT(whence == SEEK_DATA);
14361436
error = -ENXIO;
1437-
goto out_unlock;
1437+
goto out_error;
14381438
}
14391439

14401440
ASSERT(i > 1);
@@ -1445,14 +1445,14 @@ xfs_seek_hole_data(
14451445
*/
14461446
fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount;
14471447
start = XFS_FSB_TO_B(mp, fsbno);
1448-
if (start >= isize) {
1448+
if (start >= end) {
14491449
if (whence == SEEK_HOLE) {
1450-
offset = isize;
1450+
offset = end;
14511451
break;
14521452
}
14531453
ASSERT(whence == SEEK_DATA);
14541454
error = -ENXIO;
1455-
goto out_unlock;
1455+
goto out_error;
14561456
}
14571457
}
14581458

@@ -1464,7 +1464,39 @@ xfs_seek_hole_data(
14641464
* situation in particular.
14651465
*/
14661466
if (whence == SEEK_HOLE)
1467-
offset = min_t(loff_t, offset, isize);
1467+
offset = min_t(loff_t, offset, end);
1468+
1469+
return offset;
1470+
1471+
out_error:
1472+
return error;
1473+
}
1474+
1475+
STATIC loff_t
1476+
xfs_seek_hole_data(
1477+
struct file *file,
1478+
loff_t start,
1479+
int whence)
1480+
{
1481+
struct inode *inode = file->f_mapping->host;
1482+
struct xfs_inode *ip = XFS_I(inode);
1483+
struct xfs_mount *mp = ip->i_mount;
1484+
uint lock;
1485+
loff_t offset, end;
1486+
int error = 0;
1487+
1488+
if (XFS_FORCED_SHUTDOWN(mp))
1489+
return -EIO;
1490+
1491+
lock = xfs_ilock_data_map_shared(ip);
1492+
1493+
end = i_size_read(inode);
1494+
offset = __xfs_seek_hole_data(inode, start, end, whence);
1495+
if (offset < 0) {
1496+
error = offset;
1497+
goto out_unlock;
1498+
}
1499+
14681500
offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
14691501

14701502
out_unlock:

fs/xfs/xfs_inode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ int xfs_update_prealloc_flags(struct xfs_inode *ip,
437437
int xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset,
438438
xfs_fsize_t isize, bool *did_zeroing);
439439
int xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count);
440+
loff_t __xfs_seek_hole_data(struct inode *inode, loff_t start,
441+
loff_t eof, int whence);
440442

441443

442444
/* from xfs_iops.c */

0 commit comments

Comments
 (0)