aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r--fs/xfs/xfs_file.c88
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
1340STATIC loff_t 1340/*
1341xfs_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 */
1348loff_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
1471out_error:
1472 return error;
1473}
1474
1475STATIC loff_t
1476xfs_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
1470out_unlock: 1502out_unlock: