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.c178
1 files changed, 53 insertions, 125 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index de5368c803f9..eb596b419942 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -983,7 +983,7 @@ xfs_vm_page_mkwrite(
983 983
984/* 984/*
985 * This type is designed to indicate the type of offset we would like 985 * This type is designed to indicate the type of offset we would like
986 * to search from page cache for either xfs_seek_data() or xfs_seek_hole(). 986 * to search from page cache for xfs_seek_hole_data().
987 */ 987 */
988enum { 988enum {
989 HOLE_OFF = 0, 989 HOLE_OFF = 0,
@@ -1040,7 +1040,7 @@ xfs_lookup_buffer_offset(
1040/* 1040/*
1041 * This routine is called to find out and return a data or hole offset 1041 * This routine is called to find out and return a data or hole offset
1042 * from the page cache for unwritten extents according to the desired 1042 * from the page cache for unwritten extents according to the desired
1043 * type for xfs_seek_data() or xfs_seek_hole(). 1043 * type for xfs_seek_hole_data().
1044 * 1044 *
1045 * The argument offset is used to tell where we start to search from the 1045 * The argument offset is used to tell where we start to search from the
1046 * page cache. Map is used to figure out the end points of the range to 1046 * page cache. Map is used to figure out the end points of the range to
@@ -1200,9 +1200,10 @@ out:
1200} 1200}
1201 1201
1202STATIC loff_t 1202STATIC loff_t
1203xfs_seek_data( 1203xfs_seek_hole_data(
1204 struct file *file, 1204 struct file *file,
1205 loff_t start) 1205 loff_t start,
1206 int whence)
1206{ 1207{
1207 struct inode *inode = file->f_mapping->host; 1208 struct inode *inode = file->f_mapping->host;
1208 struct xfs_inode *ip = XFS_I(inode); 1209 struct xfs_inode *ip = XFS_I(inode);
@@ -1214,6 +1215,9 @@ xfs_seek_data(
1214 uint lock; 1215 uint lock;
1215 int error; 1216 int error;
1216 1217
1218 if (XFS_FORCED_SHUTDOWN(mp))
1219 return -EIO;
1220
1217 lock = xfs_ilock_data_map_shared(ip); 1221 lock = xfs_ilock_data_map_shared(ip);
1218 1222
1219 isize = i_size_read(inode); 1223 isize = i_size_read(inode);
@@ -1228,6 +1232,7 @@ xfs_seek_data(
1228 */ 1232 */
1229 fsbno = XFS_B_TO_FSBT(mp, start); 1233 fsbno = XFS_B_TO_FSBT(mp, start);
1230 end = XFS_B_TO_FSB(mp, isize); 1234 end = XFS_B_TO_FSB(mp, isize);
1235
1231 for (;;) { 1236 for (;;) {
1232 struct xfs_bmbt_irec map[2]; 1237 struct xfs_bmbt_irec map[2];
1233 int nmap = 2; 1238 int nmap = 2;
@@ -1248,29 +1253,48 @@ xfs_seek_data(
1248 offset = max_t(loff_t, start, 1253 offset = max_t(loff_t, start,
1249 XFS_FSB_TO_B(mp, map[i].br_startoff)); 1254 XFS_FSB_TO_B(mp, map[i].br_startoff));
1250 1255
1251 /* Landed in a data extent */ 1256 /* Landed in the hole we wanted? */
1252 if (map[i].br_startblock == DELAYSTARTBLOCK || 1257 if (whence == SEEK_HOLE &&
1253 (map[i].br_state == XFS_EXT_NORM && 1258 map[i].br_startblock == HOLESTARTBLOCK)
1254 !isnullstartblock(map[i].br_startblock))) 1259 goto out;
1260
1261 /* Landed in the data extent we wanted? */
1262 if (whence == SEEK_DATA &&
1263 (map[i].br_startblock == DELAYSTARTBLOCK ||
1264 (map[i].br_state == XFS_EXT_NORM &&
1265 !isnullstartblock(map[i].br_startblock))))
1255 goto out; 1266 goto out;
1256 1267
1257 /* 1268 /*
1258 * Landed in an unwritten extent, try to search data 1269 * Landed in an unwritten extent, try to search
1259 * from page cache. 1270 * for hole or data from page cache.
1260 */ 1271 */
1261 if (map[i].br_state == XFS_EXT_UNWRITTEN) { 1272 if (map[i].br_state == XFS_EXT_UNWRITTEN) {
1262 if (xfs_find_get_desired_pgoff(inode, &map[i], 1273 if (xfs_find_get_desired_pgoff(inode, &map[i],
1263 DATA_OFF, &offset)) 1274 whence == SEEK_HOLE ? HOLE_OFF : DATA_OFF,
1275 &offset))
1264 goto out; 1276 goto out;
1265 } 1277 }
1266 } 1278 }
1267 1279
1268 /* 1280 /*
1269 * map[0] is hole or its an unwritten extent but 1281 * We only received one extent out of the two requested. This
1270 * without data in page cache. Probably means that 1282 * means we've hit EOF and didn't find what we are looking for.
1271 * we are reading after EOF if nothing in map[1].
1272 */ 1283 */
1273 if (nmap == 1) { 1284 if (nmap == 1) {
1285 /*
1286 * If we were looking for a hole, set offset to
1287 * the end of the file (i.e., there is an implicit
1288 * hole at the end of any file).
1289 */
1290 if (whence == SEEK_HOLE) {
1291 offset = isize;
1292 break;
1293 }
1294 /*
1295 * If we were looking for data, it's nowhere to be found
1296 */
1297 ASSERT(whence == SEEK_DATA);
1274 error = -ENXIO; 1298 error = -ENXIO;
1275 goto out_unlock; 1299 goto out_unlock;
1276 } 1300 }
@@ -1279,125 +1303,30 @@ xfs_seek_data(
1279 1303
1280 /* 1304 /*
1281 * Nothing was found, proceed to the next round of search 1305 * Nothing was found, proceed to the next round of search
1282 * if reading offset not beyond or hit EOF. 1306 * if the next reading offset is not at or beyond EOF.
1283 */ 1307 */
1284 fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount; 1308 fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount;
1285 start = XFS_FSB_TO_B(mp, fsbno); 1309 start = XFS_FSB_TO_B(mp, fsbno);
1286 if (start >= isize) { 1310 if (start >= isize) {
1311 if (whence == SEEK_HOLE) {
1312 offset = isize;
1313 break;
1314 }
1315 ASSERT(whence == SEEK_DATA);
1287 error = -ENXIO; 1316 error = -ENXIO;
1288 goto out_unlock; 1317 goto out_unlock;
1289 } 1318 }
1290 } 1319 }
1291 1320
1292out: 1321out:
1293 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
1294
1295out_unlock:
1296 xfs_iunlock(ip, lock);
1297
1298 if (error)
1299 return error;
1300 return offset;
1301}
1302
1303STATIC loff_t
1304xfs_seek_hole(
1305 struct file *file,
1306 loff_t start)
1307{
1308 struct inode *inode = file->f_mapping->host;
1309 struct xfs_inode *ip = XFS_I(inode);
1310 struct xfs_mount *mp = ip->i_mount;
1311 loff_t uninitialized_var(offset);
1312 xfs_fsize_t isize;
1313 xfs_fileoff_t fsbno;
1314 xfs_filblks_t end;
1315 uint lock;
1316 int error;
1317
1318 if (XFS_FORCED_SHUTDOWN(mp))
1319 return -EIO;
1320
1321 lock = xfs_ilock_data_map_shared(ip);
1322
1323 isize = i_size_read(inode);
1324 if (start >= isize) {
1325 error = -ENXIO;
1326 goto out_unlock;
1327 }
1328
1329 fsbno = XFS_B_TO_FSBT(mp, start);
1330 end = XFS_B_TO_FSB(mp, isize);
1331
1332 for (;;) {
1333 struct xfs_bmbt_irec map[2];
1334 int nmap = 2;
1335 unsigned int i;
1336
1337 error = xfs_bmapi_read(ip, fsbno, end - fsbno, map, &nmap,
1338 XFS_BMAPI_ENTIRE);
1339 if (error)
1340 goto out_unlock;
1341
1342 /* No extents at given offset, must be beyond EOF */
1343 if (nmap == 0) {
1344 error = -ENXIO;
1345 goto out_unlock;
1346 }
1347
1348 for (i = 0; i < nmap; i++) {
1349 offset = max_t(loff_t, start,
1350 XFS_FSB_TO_B(mp, map[i].br_startoff));
1351
1352 /* Landed in a hole */
1353 if (map[i].br_startblock == HOLESTARTBLOCK)
1354 goto out;
1355
1356 /*
1357 * Landed in an unwritten extent, try to search hole
1358 * from page cache.
1359 */
1360 if (map[i].br_state == XFS_EXT_UNWRITTEN) {
1361 if (xfs_find_get_desired_pgoff(inode, &map[i],
1362 HOLE_OFF, &offset))
1363 goto out;
1364 }
1365 }
1366
1367 /*
1368 * map[0] contains data or its unwritten but contains
1369 * data in page cache, probably means that we are
1370 * reading after EOF. We should fix offset to point
1371 * to the end of the file(i.e., there is an implicit
1372 * hole at the end of any file).
1373 */
1374 if (nmap == 1) {
1375 offset = isize;
1376 break;
1377 }
1378
1379 ASSERT(i > 1);
1380
1381 /*
1382 * Both mappings contains data, proceed to the next round of
1383 * search if the current reading offset not beyond or hit EOF.
1384 */
1385 fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount;
1386 start = XFS_FSB_TO_B(mp, fsbno);
1387 if (start >= isize) {
1388 offset = isize;
1389 break;
1390 }
1391 }
1392
1393out:
1394 /* 1322 /*
1395 * At this point, we must have found a hole. However, the returned 1323 * If at this point we have found the hole we wanted, the returned
1396 * offset may be bigger than the file size as it may be aligned to 1324 * offset may be bigger than the file size as it may be aligned to
1397 * page boundary for unwritten extents, we need to deal with this 1325 * page boundary for unwritten extents. We need to deal with this
1398 * situation in particular. 1326 * situation in particular.
1399 */ 1327 */
1400 offset = min_t(loff_t, offset, isize); 1328 if (whence == SEEK_HOLE)
1329 offset = min_t(loff_t, offset, isize);
1401 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes); 1330 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
1402 1331
1403out_unlock: 1332out_unlock:
@@ -1412,17 +1341,16 @@ STATIC loff_t
1412xfs_file_llseek( 1341xfs_file_llseek(
1413 struct file *file, 1342 struct file *file,
1414 loff_t offset, 1343 loff_t offset,
1415 int origin) 1344 int whence)
1416{ 1345{
1417 switch (origin) { 1346 switch (whence) {
1418 case SEEK_END: 1347 case SEEK_END:
1419 case SEEK_CUR: 1348 case SEEK_CUR:
1420 case SEEK_SET: 1349 case SEEK_SET:
1421 return generic_file_llseek(file, offset, origin); 1350 return generic_file_llseek(file, offset, whence);
1422 case SEEK_DATA:
1423 return xfs_seek_data(file, offset);
1424 case SEEK_HOLE: 1351 case SEEK_HOLE:
1425 return xfs_seek_hole(file, offset); 1352 case SEEK_DATA:
1353 return xfs_seek_hole_data(file, offset, whence);
1426 default: 1354 default:
1427 return -EINVAL; 1355 return -EINVAL;
1428 } 1356 }