diff options
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r-- | fs/xfs/xfs_file.c | 88 |
1 files changed, 60 insertions, 28 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 52883ac3cf84..ac0fd32de31e 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -156,9 +156,9 @@ xfs_update_prealloc_flags( | |||
156 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 156 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
157 | 157 | ||
158 | if (!(flags & XFS_PREALLOC_INVISIBLE)) { | 158 | if (!(flags & XFS_PREALLOC_INVISIBLE)) { |
159 | ip->i_d.di_mode &= ~S_ISUID; | 159 | VFS_I(ip)->i_mode &= ~S_ISUID; |
160 | if (ip->i_d.di_mode & S_IXGRP) | 160 | if (VFS_I(ip)->i_mode & S_IXGRP) |
161 | ip->i_d.di_mode &= ~S_ISGID; | 161 | VFS_I(ip)->i_mode &= ~S_ISGID; |
162 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 162 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
163 | } | 163 | } |
164 | 164 | ||
@@ -1337,31 +1337,31 @@ out: | |||
1337 | return found; | 1337 | return found; |
1338 | } | 1338 | } |
1339 | 1339 | ||
1340 | STATIC loff_t | 1340 | /* |
1341 | xfs_seek_hole_data( | 1341 | * caller must lock inode with xfs_ilock_data_map_shared, |
1342 | struct file *file, | 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, | ||
1343 | loff_t start, | 1351 | loff_t start, |
1352 | loff_t end, | ||
1344 | int whence) | 1353 | int whence) |
1345 | { | 1354 | { |
1346 | struct inode *inode = file->f_mapping->host; | ||
1347 | struct xfs_inode *ip = XFS_I(inode); | 1355 | struct xfs_inode *ip = XFS_I(inode); |
1348 | struct xfs_mount *mp = ip->i_mount; | 1356 | struct xfs_mount *mp = ip->i_mount; |
1349 | loff_t uninitialized_var(offset); | 1357 | loff_t uninitialized_var(offset); |
1350 | xfs_fsize_t isize; | ||
1351 | xfs_fileoff_t fsbno; | 1358 | xfs_fileoff_t fsbno; |
1352 | xfs_filblks_t end; | 1359 | xfs_filblks_t lastbno; |
1353 | uint lock; | ||
1354 | int error; | 1360 | int error; |
1355 | 1361 | ||
1356 | if (XFS_FORCED_SHUTDOWN(mp)) | 1362 | if (start >= end) { |
1357 | return -EIO; | ||
1358 | |||
1359 | lock = xfs_ilock_data_map_shared(ip); | ||
1360 | |||
1361 | isize = i_size_read(inode); | ||
1362 | if (start >= isize) { | ||
1363 | error = -ENXIO; | 1363 | error = -ENXIO; |
1364 | goto out_unlock; | 1364 | goto out_error; |
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | /* | 1367 | /* |
@@ -1369,22 +1369,22 @@ xfs_seek_hole_data( | |||
1369 | * by fsbno to the end block of the file. | 1369 | * by fsbno to the end block of the file. |
1370 | */ | 1370 | */ |
1371 | fsbno = XFS_B_TO_FSBT(mp, start); | 1371 | fsbno = XFS_B_TO_FSBT(mp, start); |
1372 | end = XFS_B_TO_FSB(mp, isize); | 1372 | lastbno = XFS_B_TO_FSB(mp, end); |
1373 | 1373 | ||
1374 | for (;;) { | 1374 | for (;;) { |
1375 | struct xfs_bmbt_irec map[2]; | 1375 | struct xfs_bmbt_irec map[2]; |
1376 | int nmap = 2; | 1376 | int nmap = 2; |
1377 | unsigned int i; | 1377 | unsigned int i; |
1378 | 1378 | ||
1379 | error = xfs_bmapi_read(ip, fsbno, end - fsbno, map, &nmap, | 1379 | error = xfs_bmapi_read(ip, fsbno, lastbno - fsbno, map, &nmap, |
1380 | XFS_BMAPI_ENTIRE); | 1380 | XFS_BMAPI_ENTIRE); |
1381 | if (error) | 1381 | if (error) |
1382 | goto out_unlock; | 1382 | goto out_error; |
1383 | 1383 | ||
1384 | /* No extents at given offset, must be beyond EOF */ | 1384 | /* No extents at given offset, must be beyond EOF */ |
1385 | if (nmap == 0) { | 1385 | if (nmap == 0) { |
1386 | error = -ENXIO; | 1386 | error = -ENXIO; |
1387 | goto out_unlock; | 1387 | goto out_error; |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | for (i = 0; i < nmap; i++) { | 1390 | for (i = 0; i < nmap; i++) { |
@@ -1426,7 +1426,7 @@ xfs_seek_hole_data( | |||
1426 | * hole at the end of any file). | 1426 | * hole at the end of any file). |
1427 | */ | 1427 | */ |
1428 | if (whence == SEEK_HOLE) { | 1428 | if (whence == SEEK_HOLE) { |
1429 | offset = isize; | 1429 | offset = end; |
1430 | break; | 1430 | break; |
1431 | } | 1431 | } |
1432 | /* | 1432 | /* |
@@ -1434,7 +1434,7 @@ xfs_seek_hole_data( | |||
1434 | */ | 1434 | */ |
1435 | ASSERT(whence == SEEK_DATA); | 1435 | ASSERT(whence == SEEK_DATA); |
1436 | error = -ENXIO; | 1436 | error = -ENXIO; |
1437 | goto out_unlock; | 1437 | goto out_error; |
1438 | } | 1438 | } |
1439 | 1439 | ||
1440 | ASSERT(i > 1); | 1440 | ASSERT(i > 1); |
@@ -1445,14 +1445,14 @@ xfs_seek_hole_data( | |||
1445 | */ | 1445 | */ |
1446 | fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount; | 1446 | fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount; |
1447 | start = XFS_FSB_TO_B(mp, fsbno); | 1447 | start = XFS_FSB_TO_B(mp, fsbno); |
1448 | if (start >= isize) { | 1448 | if (start >= end) { |
1449 | if (whence == SEEK_HOLE) { | 1449 | if (whence == SEEK_HOLE) { |
1450 | offset = isize; | 1450 | offset = end; |
1451 | break; | 1451 | break; |
1452 | } | 1452 | } |
1453 | ASSERT(whence == SEEK_DATA); | 1453 | ASSERT(whence == SEEK_DATA); |
1454 | error = -ENXIO; | 1454 | error = -ENXIO; |
1455 | goto out_unlock; | 1455 | goto out_error; |
1456 | } | 1456 | } |
1457 | } | 1457 | } |
1458 | 1458 | ||
@@ -1464,7 +1464,39 @@ out: | |||
1464 | * situation in particular. | 1464 | * situation in particular. |
1465 | */ | 1465 | */ |
1466 | if (whence == SEEK_HOLE) | 1466 | 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 | |||
1468 | offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes); | 1500 | offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes); |
1469 | 1501 | ||
1470 | out_unlock: | 1502 | out_unlock: |