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: Sidney Amani <seed@uffs.org> Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
parent
36b477d005
commit
766fb95ba0
4 changed files with 66 additions and 19 deletions
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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;
|
||||||
* @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 {
|
||||||
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;
|
||||||
* @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 @@
|
||||||
* 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 @@
|
||||||
#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 {
|
||||||
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 {
|
||||||
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__ */
|
||||||
|
|
Loading…
Reference in a new issue