Commit 766fb95ba06e1bbf531d30dc05e21b2d4a0e8dd2
Committed by
Artem Bityutskiy
1 parent
36b477d005
Exists in
master
and in
7 other branches
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>
Showing 4 changed files with 66 additions and 19 deletions Side-by-side Diff
drivers/mtd/ubi/Kconfig.debug
... | ... | @@ -33,16 +33,6 @@ |
33 | 33 | This option switches the background thread off by default. The thread |
34 | 34 | may be also be enabled/disabled via UBI sysfs. |
35 | 35 | |
36 | -config MTD_UBI_DEBUG_USERSPACE_IO | |
37 | - bool "Direct user-space write/erase support" | |
38 | - default n | |
39 | - depends on MTD_UBI_DEBUG | |
40 | - help | |
41 | - By default, users cannot directly write and erase individual | |
42 | - eraseblocks of dynamic volumes, and have to use update operation | |
43 | - instead. This option enables this capability - it is very useful for | |
44 | - debugging and testing. | |
45 | - | |
46 | 36 | config MTD_UBI_DEBUG_EMULATE_BITFLIPS |
47 | 37 | bool "Emulate flash bit-flips" |
48 | 38 | depends on MTD_UBI_DEBUG |
drivers/mtd/ubi/cdev.c
... | ... | @@ -259,12 +259,9 @@ |
259 | 259 | return err ? err : count_save - count; |
260 | 260 | } |
261 | 261 | |
262 | -#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO | |
263 | - | |
264 | 262 | /* |
265 | 263 | * This function allows to directly write to dynamic UBI volumes, without |
266 | - * issuing the volume update operation. Available only as a debugging feature. | |
267 | - * Very useful for testing UBI. | |
264 | + * issuing the volume update operation. | |
268 | 265 | */ |
269 | 266 | static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, |
270 | 267 | size_t count, loff_t *offp) |
... | ... | @@ -276,6 +273,9 @@ |
276 | 273 | size_t count_save = count; |
277 | 274 | char *tbuf; |
278 | 275 | |
276 | + if (!vol->direct_writes) | |
277 | + return -EPERM; | |
278 | + | |
279 | 279 | dbg_gen("requested: write %zd bytes to offset %lld of volume %u", |
280 | 280 | count, *offp, vol->vol_id); |
281 | 281 | |
... | ... | @@ -339,10 +339,6 @@ |
339 | 339 | return err ? err : count_save - count; |
340 | 340 | } |
341 | 341 | |
342 | -#else | |
343 | -#define vol_cdev_direct_write(file, buf, count, offp) (-EPERM) | |
344 | -#endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */ | |
345 | - | |
346 | 342 | static ssize_t vol_cdev_write(struct file *file, const char __user *buf, |
347 | 343 | size_t count, loff_t *offp) |
348 | 344 | { |
... | ... | @@ -549,6 +545,30 @@ |
549 | 545 | break; |
550 | 546 | } |
551 | 547 | err = ubi_is_mapped(desc, lnum); |
548 | + break; | |
549 | + } | |
550 | + | |
551 | + /* Set volume property command*/ | |
552 | + case UBI_IOCSETPROP: | |
553 | + { | |
554 | + struct ubi_set_prop_req req; | |
555 | + | |
556 | + err = copy_from_user(&req, argp, | |
557 | + sizeof(struct ubi_set_prop_req)); | |
558 | + if (err) { | |
559 | + err = -EFAULT; | |
560 | + break; | |
561 | + } | |
562 | + switch (req.property) { | |
563 | + case UBI_PROP_DIRECT_WRITE: | |
564 | + mutex_lock(&ubi->volumes_mutex); | |
565 | + desc->vol->direct_writes = !!req.value; | |
566 | + mutex_unlock(&ubi->volumes_mutex); | |
567 | + break; | |
568 | + default: | |
569 | + err = -EINVAL; | |
570 | + break; | |
571 | + } | |
552 | 572 | break; |
553 | 573 | } |
554 | 574 |
drivers/mtd/ubi/ubi.h
... | ... | @@ -206,6 +206,7 @@ |
206 | 206 | * @upd_marker: %1 if the update marker is set for this volume |
207 | 207 | * @updating: %1 if the volume is being updated |
208 | 208 | * @changing_leb: %1 if the atomic LEB change ioctl command is in progress |
209 | + * @direct_writes: %1 if direct writes are enabled for this volume | |
209 | 210 | * |
210 | 211 | * @gluebi_desc: gluebi UBI volume descriptor |
211 | 212 | * @gluebi_refcount: reference count of the gluebi MTD device |
... | ... | @@ -253,6 +254,7 @@ |
253 | 254 | unsigned int upd_marker:1; |
254 | 255 | unsigned int updating:1; |
255 | 256 | unsigned int changing_leb:1; |
257 | + unsigned int direct_writes:1; | |
256 | 258 | |
257 | 259 | #ifdef CONFIG_MTD_UBI_GLUEBI |
258 | 260 | /* |
... | ... | @@ -304,7 +306,8 @@ |
304 | 306 | * @vtbl_size: size of the volume table in bytes |
305 | 307 | * @vtbl: in-RAM volume table copy |
306 | 308 | * @volumes_mutex: protects on-flash volume table and serializes volume |
307 | - * changes, like creation, deletion, update, re-size and re-name | |
309 | + * changes, like creation, deletion, update, re-size, | |
310 | + * re-name and set property | |
308 | 311 | * |
309 | 312 | * @max_ec: current highest erase counter value |
310 | 313 | * @mean_ec: current mean erase counter value |
include/mtd/ubi-user.h
... | ... | @@ -124,6 +124,14 @@ |
124 | 124 | * To check if a logical eraseblock is mapped to a physical eraseblock, the |
125 | 125 | * %UBI_IOCEBISMAP ioctl command should be used. It returns %0 if the LEB is |
126 | 126 | * not mapped, and %1 if it is mapped. |
127 | + * | |
128 | + * Set an UBI volume property | |
129 | + * ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
130 | + * | |
131 | + * To set an UBI volume property the %UBI_IOCSETPROP ioctl command should be | |
132 | + * used. A pointer to a &struct ubi_set_prop_req object is expected to be | |
133 | + * passed. The object describes which property should be set, and to which value | |
134 | + * it should be set. | |
127 | 135 | */ |
128 | 136 | |
129 | 137 | /* |
... | ... | @@ -175,6 +183,8 @@ |
175 | 183 | #define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, int32_t) |
176 | 184 | /* Check if LEB is mapped command */ |
177 | 185 | #define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, int32_t) |
186 | +/* Set an UBI volume property */ | |
187 | +#define UBI_IOCSETPROP _IOW(UBI_VOL_IOC_MAGIC, 6, struct ubi_set_prop_req) | |
178 | 188 | |
179 | 189 | /* Maximum MTD device name length supported by UBI */ |
180 | 190 | #define MAX_UBI_MTD_NAME_LEN 127 |
... | ... | @@ -210,6 +220,16 @@ |
210 | 220 | UBI_STATIC_VOLUME = 4, |
211 | 221 | }; |
212 | 222 | |
223 | +/* | |
224 | + * UBI set property ioctl constants | |
225 | + * | |
226 | + * @UBI_PROP_DIRECT_WRITE: allow / disallow user to directly write and | |
227 | + * erase individual eraseblocks on dynamic volumes | |
228 | + */ | |
229 | +enum { | |
230 | + UBI_PROP_DIRECT_WRITE = 1, | |
231 | +}; | |
232 | + | |
213 | 233 | /** |
214 | 234 | * struct ubi_attach_req - attach MTD device request. |
215 | 235 | * @ubi_num: UBI device number to create |
... | ... | @@ -372,6 +392,20 @@ |
372 | 392 | int8_t dtype; |
373 | 393 | int8_t padding[3]; |
374 | 394 | } __attribute__ ((packed)); |
395 | + | |
396 | + | |
397 | +/** | |
398 | + * struct ubi_set_prop_req - a data structure used to set an ubi volume | |
399 | + * property. | |
400 | + * @property: property to set (%UBI_PROP_DIRECT_WRITE) | |
401 | + * @padding: reserved for future, not used, has to be zeroed | |
402 | + * @value: value to set | |
403 | + */ | |
404 | +struct ubi_set_prop_req { | |
405 | + uint8_t property; | |
406 | + uint8_t padding[7]; | |
407 | + uint64_t value; | |
408 | +} __attribute__ ((packed)); | |
375 | 409 | |
376 | 410 | #endif /* __UBI_USER_H__ */ |