Commit ad7fefb109b0418bb4f16fc1176fd082f986698b

Authored by Theodore Ts'o
1 parent 011fa99404

Revert "ext4: fix suboptimal seek_{data,hole} extents traversial"

This reverts commit 14516bb7bb6ffbd49f35389f9ece3b2045ba5815.

This was causing regression test failures with generic/285 with an ext3
filesystem using CONFIG_EXT4_USE_FOR_EXT23.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>

Showing 2 changed files with 116 additions and 108 deletions Side-by-side Diff

... ... @@ -5166,8 +5166,8 @@
5166 5166  
5167 5167 /* fallback to generic here if not in extents fmt */
5168 5168 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
5169   - return __generic_block_fiemap(inode, fieinfo, start, len,
5170   - ext4_get_block);
  5169 + return generic_block_fiemap(inode, fieinfo, start, len,
  5170 + ext4_get_block);
5171 5171  
5172 5172 if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS))
5173 5173 return -EBADR;
... ... @@ -273,20 +273,25 @@
273 273 * we determine this extent as a data or a hole according to whether the
274 274 * page cache has data or not.
275 275 */
276   -static int ext4_find_unwritten_pgoff(struct inode *inode, int whence,
277   - loff_t endoff, loff_t *offset)
  276 +static int ext4_find_unwritten_pgoff(struct inode *inode,
  277 + int whence,
  278 + struct ext4_map_blocks *map,
  279 + loff_t *offset)
278 280 {
279 281 struct pagevec pvec;
  282 + unsigned int blkbits;
280 283 pgoff_t index;
281 284 pgoff_t end;
  285 + loff_t endoff;
282 286 loff_t startoff;
283 287 loff_t lastoff;
284 288 int found = 0;
285 289  
  290 + blkbits = inode->i_sb->s_blocksize_bits;
286 291 startoff = *offset;
287 292 lastoff = startoff;
  293 + endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits;
288 294  
289   -
290 295 index = startoff >> PAGE_CACHE_SHIFT;
291 296 end = endoff >> PAGE_CACHE_SHIFT;
292 297  
293 298  
294 299  
295 300  
296 301  
297 302  
298 303  
299 304  
300 305  
301 306  
302 307  
303 308  
304 309  
305 310  
306 311  
307 312  
308 313  
309 314  
310 315  
311 316  
312 317  
313 318  
314 319  
315 320  
... ... @@ -403,144 +408,147 @@
403 408 static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
404 409 {
405 410 struct inode *inode = file->f_mapping->host;
406   - struct fiemap_extent_info fie;
407   - struct fiemap_extent ext[2];
408   - loff_t next;
409   - int i, ret = 0;
  411 + struct ext4_map_blocks map;
  412 + struct extent_status es;
  413 + ext4_lblk_t start, last, end;
  414 + loff_t dataoff, isize;
  415 + int blkbits;
  416 + int ret = 0;
410 417  
411 418 mutex_lock(&inode->i_mutex);
412   - if (offset >= inode->i_size) {
  419 +
  420 + isize = i_size_read(inode);
  421 + if (offset >= isize) {
413 422 mutex_unlock(&inode->i_mutex);
414 423 return -ENXIO;
415 424 }
416   - fie.fi_flags = 0;
417   - fie.fi_extents_max = 2;
418   - fie.fi_extents_start = (struct fiemap_extent __user *) &ext;
419   - while (1) {
420   - mm_segment_t old_fs = get_fs();
421 425  
422   - fie.fi_extents_mapped = 0;
423   - memset(ext, 0, sizeof(*ext) * fie.fi_extents_max);
  426 + blkbits = inode->i_sb->s_blocksize_bits;
  427 + start = offset >> blkbits;
  428 + last = start;
  429 + end = isize >> blkbits;
  430 + dataoff = offset;
424 431  
425   - set_fs(get_ds());
426   - ret = ext4_fiemap(inode, &fie, offset, maxsize - offset);
427   - set_fs(old_fs);
428   - if (ret)
  432 + do {
  433 + map.m_lblk = last;
  434 + map.m_len = end - last + 1;
  435 + ret = ext4_map_blocks(NULL, inode, &map, 0);
  436 + if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
  437 + if (last != start)
  438 + dataoff = (loff_t)last << blkbits;
429 439 break;
  440 + }
430 441  
431   - /* No extents found, EOF */
432   - if (!fie.fi_extents_mapped) {
433   - ret = -ENXIO;
  442 + /*
  443 + * If there is a delay extent at this offset,
  444 + * it will be as a data.
  445 + */
  446 + ext4_es_find_delayed_extent_range(inode, last, last, &es);
  447 + if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
  448 + if (last != start)
  449 + dataoff = (loff_t)last << blkbits;
434 450 break;
435 451 }
436   - for (i = 0; i < fie.fi_extents_mapped; i++) {
437   - next = (loff_t)(ext[i].fe_length + ext[i].fe_logical);
438 452  
439   - if (offset < (loff_t)ext[i].fe_logical)
440   - offset = (loff_t)ext[i].fe_logical;
441   - /*
442   - * If extent is not unwritten, then it contains valid
443   - * data, mapped or delayed.
444   - */
445   - if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN))
446   - goto out;
  453 + /*
  454 + * If there is a unwritten extent at this offset,
  455 + * it will be as a data or a hole according to page
  456 + * cache that has data or not.
  457 + */
  458 + if (map.m_flags & EXT4_MAP_UNWRITTEN) {
  459 + int unwritten;
  460 + unwritten = ext4_find_unwritten_pgoff(inode, SEEK_DATA,
  461 + &map, &dataoff);
  462 + if (unwritten)
  463 + break;
  464 + }
447 465  
448   - /*
449   - * If there is a unwritten extent at this offset,
450   - * it will be as a data or a hole according to page
451   - * cache that has data or not.
452   - */
453   - if (ext4_find_unwritten_pgoff(inode, SEEK_DATA,
454   - next, &offset))
455   - goto out;
  466 + last++;
  467 + dataoff = (loff_t)last << blkbits;
  468 + } while (last <= end);
456 469  
457   - if (ext[i].fe_flags & FIEMAP_EXTENT_LAST) {
458   - ret = -ENXIO;
459   - goto out;
460   - }
461   - offset = next;
462   - }
463   - }
464   - if (offset > inode->i_size)
465   - offset = inode->i_size;
466   -out:
467 470 mutex_unlock(&inode->i_mutex);
468   - if (ret)
469   - return ret;
470 471  
471   - return vfs_setpos(file, offset, maxsize);
  472 + if (dataoff > isize)
  473 + return -ENXIO;
  474 +
  475 + return vfs_setpos(file, dataoff, maxsize);
472 476 }
473 477  
474 478 /*
475   - * ext4_seek_hole() retrieves the offset for SEEK_HOLE
  479 + * ext4_seek_hole() retrieves the offset for SEEK_HOLE.
476 480 */
477 481 static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
478 482 {
479 483 struct inode *inode = file->f_mapping->host;
480   - struct fiemap_extent_info fie;
481   - struct fiemap_extent ext[2];
482   - loff_t next;
483   - int i, ret = 0;
  484 + struct ext4_map_blocks map;
  485 + struct extent_status es;
  486 + ext4_lblk_t start, last, end;
  487 + loff_t holeoff, isize;
  488 + int blkbits;
  489 + int ret = 0;
484 490  
485 491 mutex_lock(&inode->i_mutex);
486   - if (offset >= inode->i_size) {
  492 +
  493 + isize = i_size_read(inode);
  494 + if (offset >= isize) {
487 495 mutex_unlock(&inode->i_mutex);
488 496 return -ENXIO;
489 497 }
490 498  
491   - fie.fi_flags = 0;
492   - fie.fi_extents_max = 2;
493   - fie.fi_extents_start = (struct fiemap_extent __user *)&ext;
494   - while (1) {
495   - mm_segment_t old_fs = get_fs();
  499 + blkbits = inode->i_sb->s_blocksize_bits;
  500 + start = offset >> blkbits;
  501 + last = start;
  502 + end = isize >> blkbits;
  503 + holeoff = offset;
496 504  
497   - fie.fi_extents_mapped = 0;
498   - memset(ext, 0, sizeof(*ext));
  505 + do {
  506 + map.m_lblk = last;
  507 + map.m_len = end - last + 1;
  508 + ret = ext4_map_blocks(NULL, inode, &map, 0);
  509 + if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
  510 + last += ret;
  511 + holeoff = (loff_t)last << blkbits;
  512 + continue;
  513 + }
499 514  
500   - set_fs(get_ds());
501   - ret = ext4_fiemap(inode, &fie, offset, maxsize - offset);
502   - set_fs(old_fs);
503   - if (ret)
504   - break;
  515 + /*
  516 + * If there is a delay extent at this offset,
  517 + * we will skip this extent.
  518 + */
  519 + ext4_es_find_delayed_extent_range(inode, last, last, &es);
  520 + if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
  521 + last = es.es_lblk + es.es_len;
  522 + holeoff = (loff_t)last << blkbits;
  523 + continue;
  524 + }
505 525  
506   - /* No extents found */
507   - if (!fie.fi_extents_mapped)
508   - break;
509   -
510   - for (i = 0; i < fie.fi_extents_mapped; i++) {
511   - next = (loff_t)(ext[i].fe_logical + ext[i].fe_length);
512   - /*
513   - * If extent is not unwritten, then it contains valid
514   - * data, mapped or delayed.
515   - */
516   - if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
517   - if (offset < (loff_t)ext[i].fe_logical)
518   - goto out;
519   - offset = next;
  526 + /*
  527 + * If there is a unwritten extent at this offset,
  528 + * it will be as a data or a hole according to page
  529 + * cache that has data or not.
  530 + */
  531 + if (map.m_flags & EXT4_MAP_UNWRITTEN) {
  532 + int unwritten;
  533 + unwritten = ext4_find_unwritten_pgoff(inode, SEEK_HOLE,
  534 + &map, &holeoff);
  535 + if (!unwritten) {
  536 + last += ret;
  537 + holeoff = (loff_t)last << blkbits;
520 538 continue;
521 539 }
522   - /*
523   - * If there is a unwritten extent at this offset,
524   - * it will be as a data or a hole according to page
525   - * cache that has data or not.
526   - */
527   - if (ext4_find_unwritten_pgoff(inode, SEEK_HOLE,
528   - next, &offset))
529   - goto out;
530   -
531   - offset = next;
532   - if (ext[i].fe_flags & FIEMAP_EXTENT_LAST)
533   - goto out;
534 540 }
535   - }
536   - if (offset > inode->i_size)
537   - offset = inode->i_size;
538   -out:
  541 +
  542 + /* find a hole */
  543 + break;
  544 + } while (last <= end);
  545 +
539 546 mutex_unlock(&inode->i_mutex);
540   - if (ret)
541   - return ret;
542 547  
543   - return vfs_setpos(file, offset, maxsize);
  548 + if (holeoff > isize)
  549 + holeoff = isize;
  550 +
  551 + return vfs_setpos(file, holeoff, maxsize);
544 552 }
545 553  
546 554 /*