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

Commit 6b5c94c6 authored by Artem Bityutskiy's avatar Artem Bityutskiy
Browse files

UBI: handle more error codes



The UBIFS WL worker may encounter read errors and there is logic
which makes a decision whether we should do one of:

1. cancel the operation and move the PEB with the read errors to
   the 'erroneous' list;
2. switch to R/O mode.

ATM, only -EIO errors trigger 1., other errors trigger 2. The idea
is that if we know we encountered an I/O error, do 1. Otherwise,
we do not know how to react, and do 2., just in case. E.g., if
the underlying driver became crazy because of a bug, we do not
want to harm any data, and switch to R/O mode.

This patch does 2 things:
1. Makes sure reads from the source PEB always cause 1. This is
   more consistent with other reads which come from the upper
   layers and never cause R/O.
2. Teaches UBI to do 1. also on -EBADMSG, UBI_IO_BAD_VID_HDR,
   -ENOMEM, and -ETIMEOUT. But this is only when reading the
   target PEB.

This preblems were hunted by Adrian Hunter.

Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 815bc5f8
Loading
Loading
Loading
Loading
+34 −7
Original line number Original line Diff line number Diff line
@@ -940,6 +940,33 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
	goto retry;
	goto retry;
}
}


/**
 * is_error_sane - check whether a read error is sane.
 * @err: code of the error happened during reading
 *
 * This is a helper function for 'ubi_eba_copy_leb()' which is called when we
 * cannot read data from the target PEB (an error @err happened). If the error
 * code is sane, then we treat this error as non-fatal. Otherwise the error is
 * fatal and UBI will be switched to R/O mode later.
 *
 * The idea is that we try not to switch to R/O mode if the read error is
 * something which suggests there was a real read problem. E.g., %-EIO. Or a
 * memory allocation failed (-%ENOMEM). Otherwise, it is safer to switch to R/O
 * mode, simply because we do not know what happened at the MTD level, and we
 * cannot handle this. E.g., the underlying driver may have become crazy, and
 * it is safer to switch to R/O mode to preserve the data.
 *
 * And bear in mind, this is about reading from the target PEB, i.e. the PEB
 * which we have just written.
 */
static int is_error_sane(int err)
{
	if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_VID_HDR ||
	    err == -ETIMEDOUT)
		return 0;
	return 1;
}

/**
/**
 * ubi_eba_copy_leb - copy logical eraseblock.
 * ubi_eba_copy_leb - copy logical eraseblock.
 * @ubi: UBI device description object
 * @ubi: UBI device description object
@@ -1033,7 +1060,6 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	if (err && err != UBI_IO_BITFLIPS) {
	if (err && err != UBI_IO_BITFLIPS) {
		ubi_warn("error %d while reading data from PEB %d",
		ubi_warn("error %d while reading data from PEB %d",
			 err, from);
			 err, from);
		if (err == -EIO)
		err = MOVE_SOURCE_RD_ERR;
		err = MOVE_SOURCE_RD_ERR;
		goto out_unlock_buf;
		goto out_unlock_buf;
	}
	}
@@ -1082,8 +1108,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
	err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
	if (err) {
	if (err) {
		if (err != UBI_IO_BITFLIPS) {
		if (err != UBI_IO_BITFLIPS) {
			ubi_warn("cannot read VID header back from PEB %d", to);
			ubi_warn("error %d while reading VID header back from "
			if (err == -EIO)
				  "PEB %d", err, to);
			if (is_error_sane(err))
				err = MOVE_TARGET_RD_ERR;
				err = MOVE_TARGET_RD_ERR;
		} else
		} else
			err = MOVE_CANCEL_BITFLIPS;
			err = MOVE_CANCEL_BITFLIPS;
@@ -1108,9 +1135,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
		err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
		err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
		if (err) {
		if (err) {
			if (err != UBI_IO_BITFLIPS) {
			if (err != UBI_IO_BITFLIPS) {
				ubi_warn("cannot read data back from PEB %d",
				ubi_warn("error %d while reading data back "
					 to);
					 "from PEB %d", err, to);
				if (err == -EIO)
				if (is_error_sane(err))
					err = MOVE_TARGET_RD_ERR;
					err = MOVE_TARGET_RD_ERR;
			} else
			} else
				err = MOVE_CANCEL_BITFLIPS;
				err = MOVE_CANCEL_BITFLIPS;