Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2d5ad82 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from Chris Mason:
 "The important part of this pull is Filipe's set of fixes for btrfs
  device replacement.  Filipe fixed a few issues seen on the list and a
  number he found on his own"

* 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: deal with duplciates during extent_map insertion in btrfs_get_extent
  Btrfs: fix race between device replace and read repair
  Btrfs: fix race between device replace and discard
  Btrfs: fix race between device replace and chunk allocation
  Btrfs: fix race setting block group back to RW mode during device replace
  Btrfs: fix unprotected assignment of the left cursor for device replace
  Btrfs: fix race setting block group readonly during device replace
  Btrfs: fix race between device replace and block group removal
  Btrfs: fix race between readahead and device replace/removal
parents a3021a59 8dff9c85
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2042,6 +2042,11 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
	struct btrfs_bio *bbio = NULL;


	/*
	 * Avoid races with device replace and make sure our bbio has devices
	 * associated to its stripes that don't go away while we are discarding.
	 */
	btrfs_bio_counter_inc_blocked(root->fs_info);
	/* Tell the block device(s) that the sectors can be discarded */
	ret = btrfs_map_block(root->fs_info, REQ_DISCARD,
			      bytenr, &num_bytes, &bbio, 0);
@@ -2074,6 +2079,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
		}
		btrfs_put_bbio(bbio);
	}
	btrfs_bio_counter_dec(root->fs_info);

	if (actual_bytes)
		*actual_bytes = discarded_bytes;
+10 −0
Original line number Diff line number Diff line
@@ -2025,9 +2025,16 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
	bio->bi_iter.bi_size = 0;
	map_length = length;

	/*
	 * Avoid races with device replace and make sure our bbio has devices
	 * associated to its stripes that don't go away while we are doing the
	 * read repair operation.
	 */
	btrfs_bio_counter_inc_blocked(fs_info);
	ret = btrfs_map_block(fs_info, WRITE, logical,
			      &map_length, &bbio, mirror_num);
	if (ret) {
		btrfs_bio_counter_dec(fs_info);
		bio_put(bio);
		return -EIO;
	}
@@ -2037,6 +2044,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
	dev = bbio->stripes[mirror_num-1].dev;
	btrfs_put_bbio(bbio);
	if (!dev || !dev->bdev || !dev->writeable) {
		btrfs_bio_counter_dec(fs_info);
		bio_put(bio);
		return -EIO;
	}
@@ -2045,6 +2053,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,

	if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
		/* try to remap that extent elsewhere? */
		btrfs_bio_counter_dec(fs_info);
		bio_put(bio);
		btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
		return -EIO;
@@ -2054,6 +2063,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
		"read error corrected: ino %llu off %llu (dev %s sector %llu)",
				  btrfs_ino(inode), start,
				  rcu_str_deref(dev->name), sector);
	btrfs_bio_counter_dec(fs_info);
	bio_put(bio);
	return 0;
}
+12 −1
Original line number Diff line number Diff line
@@ -6979,7 +6979,18 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
		 * existing will always be non-NULL, since there must be
		 * extent causing the -EEXIST.
		 */
		if (start >= extent_map_end(existing) ||
		if (existing->start == em->start &&
		    extent_map_end(existing) == extent_map_end(em) &&
		    em->block_start == existing->block_start) {
			/*
			 * these two extents are the same, it happens
			 * with inlines especially
			 */
			free_extent_map(em);
			em = existing;
			err = 0;

		} else if (start >= extent_map_end(existing) ||
		    start <= existing->start) {
			/*
			 * The existing extent map is the one nearest to
+5 −1
Original line number Diff line number Diff line
@@ -718,12 +718,13 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
	return count;
}

void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
int btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
			      const u64 range_start, const u64 range_len)
{
	struct btrfs_root *root;
	struct list_head splice;
	int done;
	int total_done = 0;

	INIT_LIST_HEAD(&splice);

@@ -742,6 +743,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
		done = btrfs_wait_ordered_extents(root, nr,
						  range_start, range_len);
		btrfs_put_fs_root(root);
		total_done += done;

		spin_lock(&fs_info->ordered_root_lock);
		if (nr != -1) {
@@ -752,6 +754,8 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
	list_splice_tail(&splice, &fs_info->ordered_roots);
	spin_unlock(&fs_info->ordered_root_lock);
	mutex_unlock(&fs_info->ordered_operations_mutex);

	return total_done;
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -199,7 +199,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
			   u32 *sum, int len);
int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
			       const u64 range_start, const u64 range_len);
void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
int btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
			      const u64 range_start, const u64 range_len);
void btrfs_get_logged_extents(struct inode *inode,
			      struct list_head *logged_list,
Loading