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

Commit b069e8ed authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6

* 'linux-next' of git://git.infradead.org/ubi-2.6: (21 commits)
  UBI: add reboot notifier
  UBI: handle more error codes
  UBI: fix multiple spelling typos
  UBI: fix kmem_cache_free on error patch
  UBI: print amount of reserved PEBs
  UBI: improve messages in the WL worker
  UBI: make gluebi a separate module
  UBI: remove built-in gluebi
  UBI: add notification API
  UBI: do not switch to R/O mode on read errors
  UBI: fix and clean-up error paths in WL worker
  UBI: introduce new constants
  UBI: fix race condition
  UBI: minor serialization fix
  UBI: do not panic if volume check fails
  UBI: add dump_stack in checking code
  UBI: fix races in I/O debugging checks
  UBI: small debugging code optimization
  UBI: improve debugging messages
  UBI: re-name volumes_mutex to device_mutex
  ...
parents b7c142db d9dd0887
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -49,15 +49,16 @@ config MTD_UBI_BEB_RESERVE
	  reserved. Leave the default value if unsure.

config MTD_UBI_GLUEBI
	bool "Emulate MTD devices"
	tristate "MTD devices emulation driver (gluebi)"
	default n
	depends on MTD_UBI
	help
	   This option enables MTD devices emulation on top of UBI volumes: for
	   each UBI volumes an MTD device is created, and all I/O to this MTD
	   device is redirected to the UBI volume. This is handy to make
	   MTD-oriented software (like JFFS2) work on top of UBI. Do not enable
	   this if no legacy software will be used.
	   This option enables gluebi - an additional driver which emulates MTD
	   devices on top of UBI volumes: for each UBI volumes an MTD device is
	   created, and all I/O to this MTD device is redirected to the UBI
	   volume. This is handy to make MTD-oriented software (like JFFS2)
	   work on top of UBI. Do not enable this unless you use legacy
	   software.

source "drivers/mtd/ubi/Kconfig.debug"
endmenu
+1 −1
Original line number Diff line number Diff line
@@ -4,4 +4,4 @@ ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o scan.o
ubi-y += misc.o

ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
ubi-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
+150 −11
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <linux/miscdevice.h>
#include <linux/log2.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
#include "ubi.h"

/* Maximum length of the 'mtd=' parameter */
@@ -121,6 +122,94 @@ static struct device_attribute dev_bgt_enabled =
static struct device_attribute dev_mtd_num =
	__ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL);

/**
 * ubi_volume_notify - send a volume change notification.
 * @ubi: UBI device description object
 * @vol: volume description object of the changed volume
 * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
 *
 * This is a helper function which notifies all subscribers about a volume
 * change event (creation, removal, re-sizing, re-naming, updating). Returns
 * zero in case of success and a negative error code in case of failure.
 */
int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype)
{
	struct ubi_notification nt;

	ubi_do_get_device_info(ubi, &nt.di);
	ubi_do_get_volume_info(ubi, vol, &nt.vi);
	return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt);
}

/**
 * ubi_notify_all - send a notification to all volumes.
 * @ubi: UBI device description object
 * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
 * @nb: the notifier to call
 *
 * This function walks all volumes of UBI device @ubi and sends the @ntype
 * notification for each volume. If @nb is %NULL, then all registered notifiers
 * are called, otherwise only the @nb notifier is called. Returns the number of
 * sent notifications.
 */
int ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb)
{
	struct ubi_notification nt;
	int i, count = 0;

	ubi_do_get_device_info(ubi, &nt.di);

	mutex_lock(&ubi->device_mutex);
	for (i = 0; i < ubi->vtbl_slots; i++) {
		/*
		 * Since the @ubi->device is locked, and we are not going to
		 * change @ubi->volumes, we do not have to lock
		 * @ubi->volumes_lock.
		 */
		if (!ubi->volumes[i])
			continue;

		ubi_do_get_volume_info(ubi, ubi->volumes[i], &nt.vi);
		if (nb)
			nb->notifier_call(nb, ntype, &nt);
		else
			blocking_notifier_call_chain(&ubi_notifiers, ntype,
						     &nt);
		count += 1;
	}
	mutex_unlock(&ubi->device_mutex);

	return count;
}

/**
 * ubi_enumerate_volumes - send "add" notification for all existing volumes.
 * @nb: the notifier to call
 *
 * This function walks all UBI devices and volumes and sends the
 * %UBI_VOLUME_ADDED notification for each volume. If @nb is %NULL, then all
 * registered notifiers are called, otherwise only the @nb notifier is called.
 * Returns the number of sent notifications.
 */
int ubi_enumerate_volumes(struct notifier_block *nb)
{
	int i, count = 0;

	/*
	 * Since the @ubi_devices_mutex is locked, and we are not going to
	 * change @ubi_devices, we do not have to lock @ubi_devices_lock.
	 */
	for (i = 0; i < UBI_MAX_DEVICES; i++) {
		struct ubi_device *ubi = ubi_devices[i];

		if (!ubi)
			continue;
		count += ubi_notify_all(ubi, UBI_VOLUME_ADDED, nb);
	}

	return count;
}

/**
 * ubi_get_device - get UBI device.
 * @ubi_num: UBI device number
@@ -380,7 +469,7 @@ static void free_user_volumes(struct ubi_device *ubi)
 * @ubi: UBI device description object
 *
 * This function returns zero in case of success and a negative error code in
 * case of failure. Note, this function destroys all volumes if it failes.
 * case of failure. Note, this function destroys all volumes if it fails.
 */
static int uif_init(struct ubi_device *ubi)
{
@@ -632,6 +721,15 @@ static int io_init(struct ubi_device *ubi)
		return -EINVAL;
	}

	/*
	 * Set maximum amount of physical erroneous eraseblocks to be 10%.
	 * Erroneous PEB are those which have read errors.
	 */
	ubi->max_erroneous = ubi->peb_count / 10;
	if (ubi->max_erroneous < 16)
		ubi->max_erroneous = 16;
	dbg_msg("max_erroneous    %d", ubi->max_erroneous);

	/*
	 * It may happen that EC and VID headers are situated in one minimal
	 * I/O unit. In this case we can only accept this UBI image in
@@ -725,6 +823,34 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
	return 0;
}

/**
 * ubi_reboot_notifier - halt UBI transactions immediately prior to a reboot.
 * @n: reboot notifier object
 * @state: SYS_RESTART, SYS_HALT, or SYS_POWER_OFF
 * @cmd: pointer to command string for RESTART2
 *
 * This function stops the UBI background thread so that the flash device
 * remains quiescent when Linux restarts the system. Any queued work will be
 * discarded, but this function will block until do_work() finishes if an
 * operation is already in progress.
 *
 * This function solves a real-life problem observed on NOR flashes when an
 * PEB erase operation starts, then the system is rebooted before the erase is
 * finishes, and the boot loader gets confused and dies. So we prefer to finish
 * the ongoing operation before rebooting.
 */
static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state,
			       void *cmd)
{
	struct ubi_device *ubi;

	ubi = container_of(n, struct ubi_device, reboot_notifier);
	if (ubi->bgt_thread)
		kthread_stop(ubi->bgt_thread);
	ubi_sync(ubi->ubi_num);
	return NOTIFY_DONE;
}

/**
 * ubi_attach_mtd_dev - attach an MTD device.
 * @mtd: MTD device description object
@@ -806,8 +932,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)

	mutex_init(&ubi->buf_mutex);
	mutex_init(&ubi->ckvol_mutex);
	mutex_init(&ubi->mult_mutex);
	mutex_init(&ubi->volumes_mutex);
	mutex_init(&ubi->device_mutex);
	spin_lock_init(&ubi->volumes_lock);

	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
@@ -825,7 +950,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
	if (!ubi->peb_buf2)
		goto out_free;

#ifdef CONFIG_MTD_UBI_DEBUG
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
	mutex_init(&ubi->dbg_buf_mutex);
	ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
	if (!ubi->dbg_peb_buf)
@@ -872,11 +997,23 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
		ubi->beb_rsvd_pebs);
	ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);

	/*
	 * The below lock makes sure we do not race with 'ubi_thread()' which
	 * checks @ubi->thread_enabled. Otherwise we may fail to wake it up.
	 */
	spin_lock(&ubi->wl_lock);
	if (!DBG_DISABLE_BGT)
		ubi->thread_enabled = 1;
	wake_up_process(ubi->bgt_thread);
	spin_unlock(&ubi->wl_lock);

	/* Flash device priority is 0 - UBI needs to shut down first */
	ubi->reboot_notifier.priority = 1;
	ubi->reboot_notifier.notifier_call = ubi_reboot_notifier;
	register_reboot_notifier(&ubi->reboot_notifier);

	ubi_devices[ubi_num] = ubi;
	ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
	return ubi_num;

out_uif:
@@ -892,7 +1029,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
out_free:
	vfree(ubi->peb_buf1);
	vfree(ubi->peb_buf2);
#ifdef CONFIG_MTD_UBI_DEBUG
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
	vfree(ubi->dbg_peb_buf);
#endif
	kfree(ubi);
@@ -919,13 +1056,13 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
		return -EINVAL;

	spin_lock(&ubi_devices_lock);
	ubi = ubi_devices[ubi_num];
	if (!ubi) {
		spin_unlock(&ubi_devices_lock);
	ubi = ubi_get_device(ubi_num);
	if (!ubi)
		return -EINVAL;
	}

	spin_lock(&ubi_devices_lock);
	put_device(&ubi->dev);
	ubi->ref_count -= 1;
	if (ubi->ref_count) {
		if (!anyway) {
			spin_unlock(&ubi_devices_lock);
@@ -939,12 +1076,14 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
	spin_unlock(&ubi_devices_lock);

	ubi_assert(ubi_num == ubi->ubi_num);
	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
	dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);

	/*
	 * Before freeing anything, we have to stop the background thread to
	 * prevent it from doing anything on this device while we are freeing.
	 */
	unregister_reboot_notifier(&ubi->reboot_notifier);
	if (ubi->bgt_thread)
		kthread_stop(ubi->bgt_thread);

@@ -961,7 +1100,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
	put_mtd_device(ubi->mtd);
	vfree(ubi->peb_buf1);
	vfree(ubi->peb_buf2);
#ifdef CONFIG_MTD_UBI_DEBUG
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
	vfree(ubi->dbg_peb_buf);
#endif
	ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
+16 −16
Original line number Diff line number Diff line
@@ -113,7 +113,8 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
	else
		mode = UBI_READONLY;

	dbg_gen("open volume %d, mode %d", vol_id, mode);
	dbg_gen("open device %d, volume %d, mode %d",
	        ubi_num, vol_id, mode);

	desc = ubi_open_volume(ubi_num, vol_id, mode);
	if (IS_ERR(desc))
@@ -128,7 +129,8 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
	struct ubi_volume_desc *desc = file->private_data;
	struct ubi_volume *vol = desc->vol;

	dbg_gen("release volume %d, mode %d", vol->vol_id, desc->mode);
	dbg_gen("release device %d, volume %d, mode %d",
		vol->ubi->ubi_num, vol->vol_id, desc->mode);

	if (vol->updating) {
		ubi_warn("update of volume %d not finished, volume is damaged",
@@ -393,7 +395,7 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
			vol->corrupted = 1;
		}
		vol->checked = 1;
		ubi_gluebi_updated(vol);
		ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED);
		revoke_exclusive(desc, UBI_READWRITE);
	}

@@ -571,9 +573,9 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
		}
		switch (req.property) {
		case UBI_PROP_DIRECT_WRITE:
			mutex_lock(&ubi->volumes_mutex);
			mutex_lock(&ubi->device_mutex);
			desc->vol->direct_writes = !!req.value;
			mutex_unlock(&ubi->volumes_mutex);
			mutex_unlock(&ubi->device_mutex);
			break;
		default:
			err = -EINVAL;
@@ -810,9 +812,9 @@ static int rename_volumes(struct ubi_device *ubi,
			re->desc->vol->vol_id, re->desc->vol->name);
	}

	mutex_lock(&ubi->volumes_mutex);
	mutex_lock(&ubi->device_mutex);
	err = ubi_rename_volumes(ubi, &rename_list);
	mutex_unlock(&ubi->volumes_mutex);
	mutex_unlock(&ubi->device_mutex);

out_free:
	list_for_each_entry_safe(re, re1, &rename_list, list) {
@@ -856,9 +858,9 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
		if (err)
			break;

		mutex_lock(&ubi->volumes_mutex);
		mutex_lock(&ubi->device_mutex);
		err = ubi_create_volume(ubi, &req);
		mutex_unlock(&ubi->volumes_mutex);
		mutex_unlock(&ubi->device_mutex);
		if (err)
			break;

@@ -887,9 +889,9 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
			break;
		}

		mutex_lock(&ubi->volumes_mutex);
		mutex_lock(&ubi->device_mutex);
		err = ubi_remove_volume(desc, 0);
		mutex_unlock(&ubi->volumes_mutex);
		mutex_unlock(&ubi->device_mutex);

		/*
		 * The volume is deleted (unless an error occurred), and the
@@ -926,9 +928,9 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
		pebs = div_u64(req.bytes + desc->vol->usable_leb_size - 1,
			       desc->vol->usable_leb_size);

		mutex_lock(&ubi->volumes_mutex);
		mutex_lock(&ubi->device_mutex);
		err = ubi_resize_volume(desc, pebs);
		mutex_unlock(&ubi->volumes_mutex);
		mutex_unlock(&ubi->device_mutex);
		ubi_close_volume(desc);
		break;
	}
@@ -952,9 +954,7 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
			break;
		}

		mutex_lock(&ubi->mult_mutex);
		err = rename_volumes(ubi, req);
		mutex_unlock(&ubi->mult_mutex);
		kfree(req);
		break;
	}
+64 −35
Original line number Diff line number Diff line
@@ -419,8 +419,9 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
				 * not implemented.
				 */
				if (err == UBI_IO_BAD_VID_HDR) {
					ubi_warn("bad VID header at PEB %d, LEB"
						 "%d:%d", pnum, vol_id, lnum);
					ubi_warn("corrupted VID header at PEB "
						 "%d, LEB %d:%d", pnum, vol_id,
						 lnum);
					err = -EBADMSG;
				} else
					ubi_ro_mode(ubi);
@@ -939,6 +940,33 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
	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: UBI device description object
@@ -950,12 +978,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
 * physical eraseblock @to. The @vid_hdr buffer may be changed by this
 * function. Returns:
 *   o %0 in case of success;
 *   o %1 if the operation was canceled because the volume is being deleted
 *        or because the PEB was put meanwhile;
 *   o %2 if the operation was canceled because there was a write error to the
 *        target PEB;
 *   o %-EAGAIN if the operation was canceled because a bit-flip was detected
 *     in the target PEB;
 *   o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_CANCEL_BITFLIPS, etc;
 *   o a negative error code in case of failure.
 */
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
@@ -968,7 +991,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	vol_id = be32_to_cpu(vid_hdr->vol_id);
	lnum = be32_to_cpu(vid_hdr->lnum);

	dbg_eba("copy LEB %d:%d, PEB %d to PEB %d", vol_id, lnum, from, to);
	dbg_wl("copy LEB %d:%d, PEB %d to PEB %d", vol_id, lnum, from, to);

	if (vid_hdr->vol_type == UBI_VID_STATIC) {
		data_size = be32_to_cpu(vid_hdr->data_size);
@@ -986,13 +1009,12 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	 * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish.
	 */
	vol = ubi->volumes[idx];
	spin_unlock(&ubi->volumes_lock);
	if (!vol) {
		/* No need to do further work, cancel */
		dbg_eba("volume %d is being removed, cancel", vol_id);
		spin_unlock(&ubi->volumes_lock);
		return 1;
		dbg_wl("volume %d is being removed, cancel", vol_id);
		return MOVE_CANCEL_RACE;
	}
	spin_unlock(&ubi->volumes_lock);

	/*
	 * We do not want anybody to write to this logical eraseblock while we
@@ -1004,12 +1026,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	 * (@from). This task locks the LEB and goes sleep in the
	 * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are
	 * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the
	 * LEB is already locked, we just do not move it and return %1.
	 * LEB is already locked, we just do not move it and return
	 * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later.
	 */
	err = leb_write_trylock(ubi, vol_id, lnum);
	if (err) {
		dbg_eba("contention on LEB %d:%d, cancel", vol_id, lnum);
		return err;
		dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum);
		return MOVE_CANCEL_RACE;
	}

	/*
@@ -1018,25 +1041,26 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	 * cancel it.
	 */
	if (vol->eba_tbl[lnum] != from) {
		dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to "
		dbg_wl("LEB %d:%d is no longer mapped to PEB %d, mapped to "
		       "PEB %d, cancel", vol_id, lnum, from,
		       vol->eba_tbl[lnum]);
		err = 1;
		err = MOVE_CANCEL_RACE;
		goto out_unlock_leb;
	}

	/*
	 * OK, now the LEB is locked and we can safely start moving it. Since
	 * this function utilizes the @ubi->peb1_buf buffer which is shared
	 * with some other functions, so lock the buffer by taking the
	 * this function utilizes the @ubi->peb_buf1 buffer which is shared
	 * with some other functions - we lock the buffer by taking the
	 * @ubi->buf_mutex.
	 */
	mutex_lock(&ubi->buf_mutex);
	dbg_eba("read %d bytes of data", aldata_size);
	dbg_wl("read %d bytes of data", aldata_size);
	err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size);
	if (err && err != UBI_IO_BITFLIPS) {
		ubi_warn("error %d while reading data from PEB %d",
			 err, from);
		err = MOVE_SOURCE_RD_ERR;
		goto out_unlock_buf;
	}

@@ -1059,7 +1083,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	cond_resched();

	/*
	 * It may turn out to me that the whole @from physical eraseblock
	 * It may turn out to be that the whole @from physical eraseblock
	 * contains only 0xFF bytes. Then we have to only write the VID header
	 * and do not write any data. This also means we should not set
	 * @vid_hdr->copy_flag, @vid_hdr->data_size, and @vid_hdr->data_crc.
@@ -1074,7 +1098,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
	if (err) {
		if (err == -EIO)
			err = 2;
			err = MOVE_TARGET_WR_ERR;
		goto out_unlock_buf;
	}

@@ -1083,10 +1107,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
	/* Read the VID header back and check if it was written correctly */
	err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
	if (err) {
		if (err != UBI_IO_BITFLIPS)
			ubi_warn("cannot read VID header back from PEB %d", to);
		else
			err = -EAGAIN;
		if (err != UBI_IO_BITFLIPS) {
			ubi_warn("error %d while reading VID header back from "
				  "PEB %d", err, to);
			if (is_error_sane(err))
				err = MOVE_TARGET_RD_ERR;
		} else
			err = MOVE_CANCEL_BITFLIPS;
		goto out_unlock_buf;
	}

@@ -1094,7 +1121,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
		err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
		if (err) {
			if (err == -EIO)
				err = 2;
				err = MOVE_TARGET_WR_ERR;
			goto out_unlock_buf;
		}

@@ -1107,11 +1134,13 @@ 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);
		if (err) {
			if (err != UBI_IO_BITFLIPS)
				ubi_warn("cannot read data back from PEB %d",
					 to);
			else
				err = -EAGAIN;
			if (err != UBI_IO_BITFLIPS) {
				ubi_warn("error %d while reading data back "
					 "from PEB %d", err, to);
				if (is_error_sane(err))
					err = MOVE_TARGET_RD_ERR;
			} else
				err = MOVE_CANCEL_BITFLIPS;
			goto out_unlock_buf;
		}

Loading