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

Commit 766fb95b authored by Sidney Amani's avatar Sidney Amani Committed by Artem Bityutskiy
Browse files

UBI: allow direct user-space I/O



Introduce a new ioctl UBI_IOCSETPROP to set properties
on a volume. Also add the first property:
UBI_PROP_DIRECT_WRITE, this property is used to set the
ability to use direct writes in userspace

Signed-off-by: default avatarSidney Amani <seed@uffs.org>
Signed-off-by: default avatarCorentin Chary <corentincj@iksaif.net>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 36b477d0
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -33,16 +33,6 @@ config MTD_UBI_DEBUG_DISABLE_BGT
	  This option switches the background thread off by default. The thread
	  may be also be enabled/disabled via UBI sysfs.

config MTD_UBI_DEBUG_USERSPACE_IO
	bool "Direct user-space write/erase support"
	default n
	depends on MTD_UBI_DEBUG
	help
	  By default, users cannot directly write and erase individual
	  eraseblocks of dynamic volumes, and have to use update operation
	  instead. This option enables this capability - it is very useful for
	  debugging and testing.

config MTD_UBI_DEBUG_EMULATE_BITFLIPS
	bool "Emulate flash bit-flips"
	depends on MTD_UBI_DEBUG
+28 −8
Original line number Diff line number Diff line
@@ -259,12 +259,9 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
	return err ? err : count_save - count;
}

#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO

/*
 * This function allows to directly write to dynamic UBI volumes, without
 * issuing the volume update operation. Available only as a debugging feature.
 * Very useful for testing UBI.
 * issuing the volume update operation.
 */
static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
				     size_t count, loff_t *offp)
@@ -276,6 +273,9 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
	size_t count_save = count;
	char *tbuf;

	if (!vol->direct_writes)
		return -EPERM;

	dbg_gen("requested: write %zd bytes to offset %lld of volume %u",
		count, *offp, vol->vol_id);

@@ -339,10 +339,6 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
	return err ? err : count_save - count;
}

#else
#define vol_cdev_direct_write(file, buf, count, offp) (-EPERM)
#endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */

static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *offp)
{
@@ -552,6 +548,30 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
		break;
	}

	/* Set volume property command*/
	case UBI_IOCSETPROP:
	{
		struct ubi_set_prop_req req;

		err = copy_from_user(&req, argp,
				sizeof(struct ubi_set_prop_req));
		if (err) {
			err = -EFAULT;
			break;
		}
		switch (req.property) {
		case UBI_PROP_DIRECT_WRITE:
			mutex_lock(&ubi->volumes_mutex);
			desc->vol->direct_writes = !!req.value;
			mutex_unlock(&ubi->volumes_mutex);
			break;
		default:
			err = -EINVAL;
			break;
		}
		break;
	}

	default:
		err = -ENOTTY;
		break;
+4 −1
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ struct ubi_volume_desc;
 * @upd_marker: %1 if the update marker is set for this volume
 * @updating: %1 if the volume is being updated
 * @changing_leb: %1 if the atomic LEB change ioctl command is in progress
 * @direct_writes: %1 if direct writes are enabled for this volume
 *
 * @gluebi_desc: gluebi UBI volume descriptor
 * @gluebi_refcount: reference count of the gluebi MTD device
@@ -253,6 +254,7 @@ struct ubi_volume {
	unsigned int upd_marker:1;
	unsigned int updating:1;
	unsigned int changing_leb:1;
	unsigned int direct_writes:1;

#ifdef CONFIG_MTD_UBI_GLUEBI
	/*
@@ -304,7 +306,8 @@ struct ubi_wl_entry;
 * @vtbl_size: size of the volume table in bytes
 * @vtbl: in-RAM volume table copy
 * @volumes_mutex: protects on-flash volume table and serializes volume
 *                 changes, like creation, deletion, update, re-size and re-name
 *                 changes, like creation, deletion, update, re-size,
 *                 re-name and set property
 *
 * @max_ec: current highest erase counter value
 * @mean_ec: current mean erase counter value
+34 −0
Original line number Diff line number Diff line
@@ -124,6 +124,14 @@
 * To check if a logical eraseblock is mapped to a physical eraseblock, the
 * %UBI_IOCEBISMAP ioctl command should be used. It returns %0 if the LEB is
 * not mapped, and %1 if it is mapped.
 *
 * Set an UBI volume property
 * ~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * To set an UBI volume property the %UBI_IOCSETPROP ioctl command should be
 * used. A pointer to a &struct ubi_set_prop_req object is expected to be
 * passed. The object describes which property should be set, and to which value
 * it should be set.
 */

/*
@@ -175,6 +183,8 @@
#define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, int32_t)
/* Check if LEB is mapped command */
#define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, int32_t)
/* Set an UBI volume property */
#define UBI_IOCSETPROP _IOW(UBI_VOL_IOC_MAGIC, 6, struct ubi_set_prop_req)

/* Maximum MTD device name length supported by UBI */
#define MAX_UBI_MTD_NAME_LEN 127
@@ -210,6 +220,16 @@ enum {
	UBI_STATIC_VOLUME  = 4,
};

/*
 * UBI set property ioctl constants
 *
 * @UBI_PROP_DIRECT_WRITE: allow / disallow user to directly write and
 *                         erase individual eraseblocks on dynamic volumes
 */
enum {
       UBI_PROP_DIRECT_WRITE = 1,
};

/**
 * struct ubi_attach_req - attach MTD device request.
 * @ubi_num: UBI device number to create
@@ -373,4 +393,18 @@ struct ubi_map_req {
	int8_t  padding[3];
} __attribute__ ((packed));


/**
 * struct ubi_set_prop_req - a data structure used to set an ubi volume
 *                           property.
 * @property: property to set (%UBI_PROP_DIRECT_WRITE)
 * @padding: reserved for future, not used, has to be zeroed
 * @value: value to set
 */
struct ubi_set_prop_req {
       uint8_t  property;
       uint8_t  padding[7];
       uint64_t value;
}  __attribute__ ((packed));

#endif /* __UBI_USER_H__ */