aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-01-06 17:05:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-01-06 17:05:40 -0500
commit3b421b80be635d696848b72d3c7700a0e5ee3414 (patch)
tree73475878aac42bb7d2fe6732a191320a49701002 /fs
parentfee7e49d45149fba60156f5b59014f764d3e3728 (diff)
parent363307e6e561cde78572fd22e7fd00cd3e5adb02 (diff)
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bugfixes from Ted Ts'o: "Revert a potential seek_data/hole regression which shows up when using ext4 to handle ext3 file systems, plus two minor bug fixes" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: remove spurious KERN_INFO from ext4_warning call Revert "ext4: fix suboptimal seek_{data,hole} extents traversial" ext4: prevent online resize with backup superblock
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/extents.c4
-rw-r--r--fs/ext4/file.c220
-rw-r--r--fs/ext4/resize.c24
-rw-r--r--fs/ext4/super.c2
4 files changed, 129 insertions, 121 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e5d3eadf47b1..bed43081720f 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -5166,8 +5166,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
5166 5166
5167 /* fallback to generic here if not in extents fmt */ 5167 /* fallback to generic here if not in extents fmt */
5168 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) 5168 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
5169 return __generic_block_fiemap(inode, fieinfo, start, len, 5169 return generic_block_fiemap(inode, fieinfo, start, len,
5170 ext4_get_block); 5170 ext4_get_block);
5171 5171
5172 if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS)) 5172 if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS))
5173 return -EBADR; 5173 return -EBADR;
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 513c12cf444c..8131be8c0af3 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -273,19 +273,24 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
273 * we determine this extent as a data or a hole according to whether the 273 * we determine this extent as a data or a hole according to whether the
274 * page cache has data or not. 274 * page cache has data or not.
275 */ 275 */
276static int ext4_find_unwritten_pgoff(struct inode *inode, int whence, 276static int ext4_find_unwritten_pgoff(struct inode *inode,
277 loff_t endoff, loff_t *offset) 277 int whence,
278 struct ext4_map_blocks *map,
279 loff_t *offset)
278{ 280{
279 struct pagevec pvec; 281 struct pagevec pvec;
282 unsigned int blkbits;
280 pgoff_t index; 283 pgoff_t index;
281 pgoff_t end; 284 pgoff_t end;
285 loff_t endoff;
282 loff_t startoff; 286 loff_t startoff;
283 loff_t lastoff; 287 loff_t lastoff;
284 int found = 0; 288 int found = 0;
285 289
290 blkbits = inode->i_sb->s_blocksize_bits;
286 startoff = *offset; 291 startoff = *offset;
287 lastoff = startoff; 292 lastoff = startoff;
288 293 endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits;
289 294
290 index = startoff >> PAGE_CACHE_SHIFT; 295 index = startoff >> PAGE_CACHE_SHIFT;
291 end = endoff >> PAGE_CACHE_SHIFT; 296 end = endoff >> PAGE_CACHE_SHIFT;
@@ -403,144 +408,147 @@ out:
403static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) 408static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
404{ 409{
405 struct inode *inode = file->f_mapping->host; 410 struct inode *inode = file->f_mapping->host;
406 struct fiemap_extent_info fie; 411 struct ext4_map_blocks map;
407 struct fiemap_extent ext[2]; 412 struct extent_status es;
408 loff_t next; 413 ext4_lblk_t start, last, end;
409 int i, ret = 0; 414 loff_t dataoff, isize;
415 int blkbits;
416 int ret = 0;
410 417
411 mutex_lock(&inode->i_mutex); 418 mutex_lock(&inode->i_mutex);
412 if (offset >= inode->i_size) { 419
420 isize = i_size_read(inode);
421 if (offset >= isize) {
413 mutex_unlock(&inode->i_mutex); 422 mutex_unlock(&inode->i_mutex);
414 return -ENXIO; 423 return -ENXIO;
415 } 424 }
416 fie.fi_flags = 0; 425
417 fie.fi_extents_max = 2; 426 blkbits = inode->i_sb->s_blocksize_bits;
418 fie.fi_extents_start = (struct fiemap_extent __user *) &ext; 427 start = offset >> blkbits;
419 while (1) { 428 last = start;
420 mm_segment_t old_fs = get_fs(); 429 end = isize >> blkbits;
421 430 dataoff = offset;
422 fie.fi_extents_mapped = 0; 431
423 memset(ext, 0, sizeof(*ext) * fie.fi_extents_max); 432 do {
424 433 map.m_lblk = last;
425 set_fs(get_ds()); 434 map.m_len = end - last + 1;
426 ret = ext4_fiemap(inode, &fie, offset, maxsize - offset); 435 ret = ext4_map_blocks(NULL, inode, &map, 0);
427 set_fs(old_fs); 436 if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
428 if (ret) 437 if (last != start)
438 dataoff = (loff_t)last << blkbits;
429 break; 439 break;
440 }
430 441
431 /* No extents found, EOF */ 442 /*
432 if (!fie.fi_extents_mapped) { 443 * If there is a delay extent at this offset,
433 ret = -ENXIO; 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 break; 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) 453 /*
440 offset = (loff_t)ext[i].fe_logical; 454 * If there is a unwritten extent at this offset,
441 /* 455 * it will be as a data or a hole according to page
442 * If extent is not unwritten, then it contains valid 456 * cache that has data or not.
443 * data, mapped or delayed. 457 */
444 */ 458 if (map.m_flags & EXT4_MAP_UNWRITTEN) {
445 if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN)) 459 int unwritten;
446 goto out; 460 unwritten = ext4_find_unwritten_pgoff(inode, SEEK_DATA,
461 &map, &dataoff);
462 if (unwritten)
463 break;
464 }
447 465
448 /* 466 last++;
449 * If there is a unwritten extent at this offset, 467 dataoff = (loff_t)last << blkbits;
450 * it will be as a data or a hole according to page 468 } while (last <= end);
451 * cache that has data or not.
452 */
453 if (ext4_find_unwritten_pgoff(inode, SEEK_DATA,
454 next, &offset))
455 goto out;
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;
466out:
467 mutex_unlock(&inode->i_mutex); 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 */
477static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) 481static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
478{ 482{
479 struct inode *inode = file->f_mapping->host; 483 struct inode *inode = file->f_mapping->host;
480 struct fiemap_extent_info fie; 484 struct ext4_map_blocks map;
481 struct fiemap_extent ext[2]; 485 struct extent_status es;
482 loff_t next; 486 ext4_lblk_t start, last, end;
483 int i, ret = 0; 487 loff_t holeoff, isize;
488 int blkbits;
489 int ret = 0;
484 490
485 mutex_lock(&inode->i_mutex); 491 mutex_lock(&inode->i_mutex);
486 if (offset >= inode->i_size) { 492
493 isize = i_size_read(inode);
494 if (offset >= isize) {
487 mutex_unlock(&inode->i_mutex); 495 mutex_unlock(&inode->i_mutex);
488 return -ENXIO; 496 return -ENXIO;
489 } 497 }
490 498
491 fie.fi_flags = 0; 499 blkbits = inode->i_sb->s_blocksize_bits;
492 fie.fi_extents_max = 2; 500 start = offset >> blkbits;
493 fie.fi_extents_start = (struct fiemap_extent __user *)&ext; 501 last = start;
494 while (1) { 502 end = isize >> blkbits;
495 mm_segment_t old_fs = get_fs(); 503 holeoff = offset;
496
497 fie.fi_extents_mapped = 0;
498 memset(ext, 0, sizeof(*ext));
499 504
500 set_fs(get_ds()); 505 do {
501 ret = ext4_fiemap(inode, &fie, offset, maxsize - offset); 506 map.m_lblk = last;
502 set_fs(old_fs); 507 map.m_len = end - last + 1;
503 if (ret) 508 ret = ext4_map_blocks(NULL, inode, &map, 0);
504 break; 509 if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
510 last += ret;
511 holeoff = (loff_t)last << blkbits;
512 continue;
513 }
505 514
506 /* No extents found */ 515 /*
507 if (!fie.fi_extents_mapped) 516 * If there is a delay extent at this offset,
508 break; 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 }
509 525
510 for (i = 0; i < fie.fi_extents_mapped; i++) { 526 /*
511 next = (loff_t)(ext[i].fe_logical + ext[i].fe_length); 527 * If there is a unwritten extent at this offset,
512 /* 528 * it will be as a data or a hole according to page
513 * If extent is not unwritten, then it contains valid 529 * cache that has data or not.
514 * data, mapped or delayed. 530 */
515 */ 531 if (map.m_flags & EXT4_MAP_UNWRITTEN) {
516 if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN)) { 532 int unwritten;
517 if (offset < (loff_t)ext[i].fe_logical) 533 unwritten = ext4_find_unwritten_pgoff(inode, SEEK_HOLE,
518 goto out; 534 &map, &holeoff);
519 offset = next; 535 if (!unwritten) {
536 last += ret;
537 holeoff = (loff_t)last << blkbits;
520 continue; 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 } 541
536 if (offset > inode->i_size) 542 /* find a hole */
537 offset = inode->i_size; 543 break;
538out: 544 } while (last <= end);
545
539 mutex_unlock(&inode->i_mutex); 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/*
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index bf76f405a5f9..8a8ec6293b19 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -24,6 +24,18 @@ int ext4_resize_begin(struct super_block *sb)
24 return -EPERM; 24 return -EPERM;
25 25
26 /* 26 /*
27 * If we are not using the primary superblock/GDT copy don't resize,
28 * because the user tools have no way of handling this. Probably a
29 * bad time to do it anyways.
30 */
31 if (EXT4_SB(sb)->s_sbh->b_blocknr !=
32 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
33 ext4_warning(sb, "won't resize using backup superblock at %llu",
34 (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
35 return -EPERM;
36 }
37
38 /*
27 * We are not allowed to do online-resizing on a filesystem mounted 39 * We are not allowed to do online-resizing on a filesystem mounted
28 * with error, because it can destroy the filesystem easily. 40 * with error, because it can destroy the filesystem easily.
29 */ 41 */
@@ -758,18 +770,6 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
758 "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n", 770 "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n",
759 gdb_num); 771 gdb_num);
760 772
761 /*
762 * If we are not using the primary superblock/GDT copy don't resize,
763 * because the user tools have no way of handling this. Probably a
764 * bad time to do it anyways.
765 */
766 if (EXT4_SB(sb)->s_sbh->b_blocknr !=
767 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
768 ext4_warning(sb, "won't resize using backup superblock at %llu",
769 (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
770 return -EPERM;
771 }
772
773 gdb_bh = sb_bread(sb, gdblock); 773 gdb_bh = sb_bread(sb, gdblock);
774 if (!gdb_bh) 774 if (!gdb_bh)
775 return -EIO; 775 return -EIO;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 43c92b1685cb..74c5f53595fb 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3482,7 +3482,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3482 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 3482 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
3483 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && 3483 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
3484 EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 3484 EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
3485 ext4_warning(sb, KERN_INFO "metadata_csum and uninit_bg are " 3485 ext4_warning(sb, "metadata_csum and uninit_bg are "
3486 "redundant flags; please run fsck."); 3486 "redundant flags; please run fsck.");
3487 3487
3488 /* Check for a known checksum algorithm */ 3488 /* Check for a known checksum algorithm */