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

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
...@@ -33,16 +33,6 @@ config MTD_UBI_DEBUG_DISABLE_BGT ...@@ -33,16 +33,6 @@ config MTD_UBI_DEBUG_DISABLE_BGT
This option switches the background thread off by default. The thread This option switches the background thread off by default. The thread
may be also be enabled/disabled via UBI sysfs. 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 config MTD_UBI_DEBUG_EMULATE_BITFLIPS
bool "Emulate flash bit-flips" bool "Emulate flash bit-flips"
depends on MTD_UBI_DEBUG depends on MTD_UBI_DEBUG
......
...@@ -259,12 +259,9 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, ...@@ -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; return err ? err : count_save - count;
} }
#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
/* /*
* This function allows to directly write to dynamic UBI volumes, without * This function allows to directly write to dynamic UBI volumes, without
* issuing the volume update operation. Available only as a debugging feature. * issuing the volume update operation.
* Very useful for testing UBI.
*/ */
static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
size_t count, loff_t *offp) size_t count, loff_t *offp)
...@@ -276,6 +273,9 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, ...@@ -276,6 +273,9 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
size_t count_save = count; size_t count_save = count;
char *tbuf; char *tbuf;
if (!vol->direct_writes)
return -EPERM;
dbg_gen("requested: write %zd bytes to offset %lld of volume %u", dbg_gen("requested: write %zd bytes to offset %lld of volume %u",
count, *offp, vol->vol_id); count, *offp, vol->vol_id);
...@@ -339,10 +339,6 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, ...@@ -339,10 +339,6 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
return err ? err : count_save - count; 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, static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
size_t count, loff_t *offp) size_t count, loff_t *offp)
{ {
...@@ -552,6 +548,30 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, ...@@ -552,6 +548,30 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
break; 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: default:
err = -ENOTTY; err = -ENOTTY;
break; break;
......
...@@ -206,6 +206,7 @@ struct ubi_volume_desc; ...@@ -206,6 +206,7 @@ struct ubi_volume_desc;
* @upd_marker: %1 if the update marker is set for this volume * @upd_marker: %1 if the update marker is set for this volume
* @updating: %1 if the volume is being updated * @updating: %1 if the volume is being updated
* @changing_leb: %1 if the atomic LEB change ioctl command is in progress * @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_desc: gluebi UBI volume descriptor
* @gluebi_refcount: reference count of the gluebi MTD device * @gluebi_refcount: reference count of the gluebi MTD device
...@@ -253,6 +254,7 @@ struct ubi_volume { ...@@ -253,6 +254,7 @@ struct ubi_volume {
unsigned int upd_marker:1; unsigned int upd_marker:1;
unsigned int updating:1; unsigned int updating:1;
unsigned int changing_leb:1; unsigned int changing_leb:1;
unsigned int direct_writes:1;
#ifdef CONFIG_MTD_UBI_GLUEBI #ifdef CONFIG_MTD_UBI_GLUEBI
/* /*
...@@ -304,7 +306,8 @@ struct ubi_wl_entry; ...@@ -304,7 +306,8 @@ struct ubi_wl_entry;
* @vtbl_size: size of the volume table in bytes * @vtbl_size: size of the volume table in bytes
* @vtbl: in-RAM volume table copy * @vtbl: in-RAM volume table copy
* @volumes_mutex: protects on-flash volume table and serializes volume * @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 * @max_ec: current highest erase counter value
* @mean_ec: current mean erase counter value * @mean_ec: current mean erase counter value
......
...@@ -124,6 +124,14 @@ ...@@ -124,6 +124,14 @@
* To check if a logical eraseblock is mapped to a physical eraseblock, the * 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 * %UBI_IOCEBISMAP ioctl command should be used. It returns %0 if the LEB is
* not mapped, and %1 if it is mapped. * 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 @@ ...@@ -175,6 +183,8 @@
#define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, int32_t) #define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, int32_t)
/* Check if LEB is mapped command */ /* Check if LEB is mapped command */
#define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, int32_t) #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 */ /* Maximum MTD device name length supported by UBI */
#define MAX_UBI_MTD_NAME_LEN 127 #define MAX_UBI_MTD_NAME_LEN 127
...@@ -210,6 +220,16 @@ enum { ...@@ -210,6 +220,16 @@ enum {
UBI_STATIC_VOLUME = 4, 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. * struct ubi_attach_req - attach MTD device request.
* @ubi_num: UBI device number to create * @ubi_num: UBI device number to create
...@@ -373,4 +393,18 @@ struct ubi_map_req { ...@@ -373,4 +393,18 @@ struct ubi_map_req {
int8_t padding[3]; int8_t padding[3];
} __attribute__ ((packed)); } __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__ */ #endif /* __UBI_USER_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment