Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sidney Amani and committed by
Artem Bityutskiy
766fb95b 36b477d0

+66 -19
-10
drivers/mtd/ubi/Kconfig.debug
··· 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
+28 -8
drivers/mtd/ubi/cdev.c
··· 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) ··· 272 275 int lnum, off, len, tbuf_size, err = 0; 273 276 size_t count_save = count; 274 277 char *tbuf; 278 + 279 + if (!vol->direct_writes) 280 + return -EPERM; 275 281 276 282 dbg_gen("requested: write %zd bytes to offset %lld of volume %u", 277 283 count, *offp, vol->vol_id); ··· 338 338 vfree(tbuf); 339 339 return err ? err : count_save - count; 340 340 } 341 - 342 - #else 343 - #define vol_cdev_direct_write(file, buf, count, offp) (-EPERM) 344 - #endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */ 345 341 346 342 static ssize_t vol_cdev_write(struct file *file, const char __user *buf, 347 343 size_t count, loff_t *offp) ··· 545 549 break; 546 550 } 547 551 err = ubi_is_mapped(desc, lnum); 552 + break; 553 + } 554 + 555 + /* Set volume property command*/ 556 + case UBI_IOCSETPROP: 557 + { 558 + struct ubi_set_prop_req req; 559 + 560 + err = copy_from_user(&req, argp, 561 + sizeof(struct ubi_set_prop_req)); 562 + if (err) { 563 + err = -EFAULT; 564 + break; 565 + } 566 + switch (req.property) { 567 + case UBI_PROP_DIRECT_WRITE: 568 + mutex_lock(&ubi->volumes_mutex); 569 + desc->vol->direct_writes = !!req.value; 570 + mutex_unlock(&ubi->volumes_mutex); 571 + break; 572 + default: 573 + err = -EINVAL; 574 + break; 575 + } 548 576 break; 549 577 } 550 578
+4 -1
drivers/mtd/ubi/ubi.h
··· 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 ··· 254 253 unsigned int upd_marker:1; 255 254 unsigned int updating:1; 256 255 unsigned int changing_leb:1; 256 + unsigned int direct_writes:1; 257 257 258 258 #ifdef CONFIG_MTD_UBI_GLUEBI 259 259 /* ··· 306 304 * @vtbl_size: size of the volume table in bytes 307 305 * @vtbl: in-RAM volume table copy 308 306 * @volumes_mutex: protects on-flash volume table and serializes volume 309 - * changes, like creation, deletion, update, re-size and re-name 307 + * changes, like creation, deletion, update, re-size, 308 + * re-name and set property 310 309 * 311 310 * @max_ec: current highest erase counter value 312 311 * @mean_ec: current mean erase counter value
+34
include/mtd/ubi-user.h
··· 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 /* ··· 183 175 #define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, int32_t) 184 176 /* Check if LEB is mapped command */ 185 177 #define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, int32_t) 178 + /* Set an UBI volume property */ 179 + #define UBI_IOCSETPROP _IOW(UBI_VOL_IOC_MAGIC, 6, struct ubi_set_prop_req) 186 180 187 181 /* Maximum MTD device name length supported by UBI */ 188 182 #define MAX_UBI_MTD_NAME_LEN 127 ··· 218 208 enum { 219 209 UBI_DYNAMIC_VOLUME = 3, 220 210 UBI_STATIC_VOLUME = 4, 211 + }; 212 + 213 + /* 214 + * UBI set property ioctl constants 215 + * 216 + * @UBI_PROP_DIRECT_WRITE: allow / disallow user to directly write and 217 + * erase individual eraseblocks on dynamic volumes 218 + */ 219 + enum { 220 + UBI_PROP_DIRECT_WRITE = 1, 221 221 }; 222 222 223 223 /** ··· 392 372 int8_t dtype; 393 373 int8_t padding[3]; 394 374 } __attribute__ ((packed)); 375 + 376 + 377 + /** 378 + * struct ubi_set_prop_req - a data structure used to set an ubi volume 379 + * property. 380 + * @property: property to set (%UBI_PROP_DIRECT_WRITE) 381 + * @padding: reserved for future, not used, has to be zeroed 382 + * @value: value to set 383 + */ 384 + struct ubi_set_prop_req { 385 + uint8_t property; 386 + uint8_t padding[7]; 387 + uint64_t value; 388 + } __attribute__ ((packed)); 395 389 396 390 #endif /* __UBI_USER_H__ */