Commit b6a535fa authored by Howard McLauchlan's avatar Howard McLauchlan Committed by David Sterba
Browse files

btrfs: print error if primary super block write fails



Presently, failing a primary super block write but succeeding in at
least one super block write in general will appear to users as if
nothing important went wrong. However, upon unmounting and re-mounting,
the file system will be in a rolled back state. This was discovered
with a BCC program that uses bpf_override_return() to fail super block
writes.

This patch outputs an error clarifying that the primary super block
write has failed, so users can expect potentially erroneous behaviour.
It also forces wait_dev_supers() to return an error to its caller if
the primary super block write fails.

Signed-off-by: default avatarHoward McLauchlan <hmclauchlan@fb.com>
Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 062d4d1f
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -3290,6 +3290,7 @@ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
	struct buffer_head *bh;
	int i;
	int errors = 0;
	bool primary_failed = false;
	u64 bytenr;

	if (max_mirrors == 0)
@@ -3306,11 +3307,16 @@ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
				      BTRFS_SUPER_INFO_SIZE);
		if (!bh) {
			errors++;
			if (i == 0)
				primary_failed = true;
			continue;
		}
		wait_on_buffer(bh);
		if (!buffer_uptodate(bh))
		if (!buffer_uptodate(bh)) {
			errors++;
			if (i == 0)
				primary_failed = true;
		}

		/* drop our reference */
		brelse(bh);
@@ -3319,6 +3325,13 @@ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
		brelse(bh);
	}

	/* log error, force error return */
	if (primary_failed) {
		btrfs_err(device->fs_info, "error writing primary super block to device %llu",
			  device->devid);
		return -1;
	}

	return errors < i ? 0 : -1;
}