aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/cdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/cdev.c')
-rw-r--r--drivers/mtd/ubi/cdev.c244
1 files changed, 181 insertions, 63 deletions
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index fe4da1e96c52..9d6aae5449b6 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -28,6 +28,11 @@
28 * 28 *
29 * Major and minor numbers are assigned dynamically to both UBI and volume 29 * Major and minor numbers are assigned dynamically to both UBI and volume
30 * character devices. 30 * character devices.
31 *
32 * Well, there is the third kind of character devices - the UBI control
33 * character device, which allows to manipulate by UBI devices - create and
34 * delete them. In other words, it is used for attaching and detaching MTD
35 * devices.
31 */ 36 */
32 37
33#include <linux/module.h> 38#include <linux/module.h>
@@ -39,34 +44,6 @@
39#include <asm/div64.h> 44#include <asm/div64.h>
40#include "ubi.h" 45#include "ubi.h"
41 46
42/*
43 * Maximum sequence numbers of UBI and volume character device IOCTLs (direct
44 * logical eraseblock erase is a debug-only feature).
45 */
46#define UBI_CDEV_IOC_MAX_SEQ 2
47#ifndef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
48#define VOL_CDEV_IOC_MAX_SEQ 1
49#else
50#define VOL_CDEV_IOC_MAX_SEQ 2
51#endif
52
53/**
54 * major_to_device - get UBI device object by character device major number.
55 * @major: major number
56 *
57 * This function returns a pointer to the UBI device object.
58 */
59static struct ubi_device *major_to_device(int major)
60{
61 int i;
62
63 for (i = 0; i < ubi_devices_cnt; i++)
64 if (ubi_devices[i] && ubi_devices[i]->major == major)
65 return ubi_devices[i];
66 BUG();
67 return NULL;
68}
69
70/** 47/**
71 * get_exclusive - get exclusive access to an UBI volume. 48 * get_exclusive - get exclusive access to an UBI volume.
72 * @desc: volume descriptor 49 * @desc: volume descriptor
@@ -124,9 +101,11 @@ static void revoke_exclusive(struct ubi_volume_desc *desc, int mode)
124static int vol_cdev_open(struct inode *inode, struct file *file) 101static int vol_cdev_open(struct inode *inode, struct file *file)
125{ 102{
126 struct ubi_volume_desc *desc; 103 struct ubi_volume_desc *desc;
127 const struct ubi_device *ubi = major_to_device(imajor(inode)); 104 int vol_id = iminor(inode) - 1, mode, ubi_num;
128 int vol_id = iminor(inode) - 1; 105
129 int mode; 106 ubi_num = ubi_major2num(imajor(inode));
107 if (ubi_num < 0)
108 return ubi_num;
130 109
131 if (file->f_mode & FMODE_WRITE) 110 if (file->f_mode & FMODE_WRITE)
132 mode = UBI_READWRITE; 111 mode = UBI_READWRITE;
@@ -135,7 +114,7 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
135 114
136 dbg_msg("open volume %d, mode %d", vol_id, mode); 115 dbg_msg("open volume %d, mode %d", vol_id, mode);
137 116
138 desc = ubi_open_volume(ubi->ubi_num, vol_id, mode); 117 desc = ubi_open_volume(ubi_num, vol_id, mode);
139 if (IS_ERR(desc)) 118 if (IS_ERR(desc))
140 return PTR_ERR(desc); 119 return PTR_ERR(desc);
141 120
@@ -153,8 +132,15 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
153 if (vol->updating) { 132 if (vol->updating) {
154 ubi_warn("update of volume %d not finished, volume is damaged", 133 ubi_warn("update of volume %d not finished, volume is damaged",
155 vol->vol_id); 134 vol->vol_id);
135 ubi_assert(!vol->changing_leb);
156 vol->updating = 0; 136 vol->updating = 0;
157 vfree(vol->upd_buf); 137 vfree(vol->upd_buf);
138 } else if (vol->changing_leb) {
139 dbg_msg("only %lld of %lld bytes received for atomic LEB change"
140 " for volume %d:%d, cancel", vol->upd_received,
141 vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id);
142 vol->changing_leb = 0;
143 vfree(vol->upd_buf);
158 } 144 }
159 145
160 ubi_close_volume(desc); 146 ubi_close_volume(desc);
@@ -205,13 +191,13 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
205 struct ubi_volume_desc *desc = file->private_data; 191 struct ubi_volume_desc *desc = file->private_data;
206 struct ubi_volume *vol = desc->vol; 192 struct ubi_volume *vol = desc->vol;
207 struct ubi_device *ubi = vol->ubi; 193 struct ubi_device *ubi = vol->ubi;
208 int err, lnum, off, len, vol_id = desc->vol->vol_id, tbuf_size; 194 int err, lnum, off, len, tbuf_size;
209 size_t count_save = count; 195 size_t count_save = count;
210 void *tbuf; 196 void *tbuf;
211 uint64_t tmp; 197 uint64_t tmp;
212 198
213 dbg_msg("read %zd bytes from offset %lld of volume %d", 199 dbg_msg("read %zd bytes from offset %lld of volume %d",
214 count, *offp, vol_id); 200 count, *offp, vol->vol_id);
215 201
216 if (vol->updating) { 202 if (vol->updating) {
217 dbg_err("updating"); 203 dbg_err("updating");
@@ -225,7 +211,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
225 return 0; 211 return 0;
226 212
227 if (vol->corrupted) 213 if (vol->corrupted)
228 dbg_msg("read from corrupted volume %d", vol_id); 214 dbg_msg("read from corrupted volume %d", vol->vol_id);
229 215
230 if (*offp + count > vol->used_bytes) 216 if (*offp + count > vol->used_bytes)
231 count_save = count = vol->used_bytes - *offp; 217 count_save = count = vol->used_bytes - *offp;
@@ -249,7 +235,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
249 if (off + len >= vol->usable_leb_size) 235 if (off + len >= vol->usable_leb_size)
250 len = vol->usable_leb_size - off; 236 len = vol->usable_leb_size - off;
251 237
252 err = ubi_eba_read_leb(ubi, vol_id, lnum, tbuf, off, len, 0); 238 err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
253 if (err) 239 if (err)
254 break; 240 break;
255 241
@@ -289,13 +275,13 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
289 struct ubi_volume_desc *desc = file->private_data; 275 struct ubi_volume_desc *desc = file->private_data;
290 struct ubi_volume *vol = desc->vol; 276 struct ubi_volume *vol = desc->vol;
291 struct ubi_device *ubi = vol->ubi; 277 struct ubi_device *ubi = vol->ubi;
292 int lnum, off, len, tbuf_size, vol_id = vol->vol_id, err = 0; 278 int lnum, off, len, tbuf_size, err = 0;
293 size_t count_save = count; 279 size_t count_save = count;
294 char *tbuf; 280 char *tbuf;
295 uint64_t tmp; 281 uint64_t tmp;
296 282
297 dbg_msg("requested: write %zd bytes to offset %lld of volume %u", 283 dbg_msg("requested: write %zd bytes to offset %lld of volume %u",
298 count, *offp, desc->vol->vol_id); 284 count, *offp, vol->vol_id);
299 285
300 if (vol->vol_type == UBI_STATIC_VOLUME) 286 if (vol->vol_type == UBI_STATIC_VOLUME)
301 return -EROFS; 287 return -EROFS;
@@ -339,7 +325,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
339 break; 325 break;
340 } 326 }
341 327
342 err = ubi_eba_write_leb(ubi, vol_id, lnum, tbuf, off, len, 328 err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len,
343 UBI_UNKNOWN); 329 UBI_UNKNOWN);
344 if (err) 330 if (err)
345 break; 331 break;
@@ -372,22 +358,32 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
372 struct ubi_volume *vol = desc->vol; 358 struct ubi_volume *vol = desc->vol;
373 struct ubi_device *ubi = vol->ubi; 359 struct ubi_device *ubi = vol->ubi;
374 360
375 if (!vol->updating) 361 if (!vol->updating && !vol->changing_leb)
376 return vol_cdev_direct_write(file, buf, count, offp); 362 return vol_cdev_direct_write(file, buf, count, offp);
377 363
378 err = ubi_more_update_data(ubi, vol->vol_id, buf, count); 364 if (vol->updating)
365 err = ubi_more_update_data(ubi, vol, buf, count);
366 else
367 err = ubi_more_leb_change_data(ubi, vol, buf, count);
368
379 if (err < 0) { 369 if (err < 0) {
380 ubi_err("cannot write %zd bytes of update data", count); 370 ubi_err("cannot accept more %zd bytes of data, error %d",
371 count, err);
381 return err; 372 return err;
382 } 373 }
383 374
384 if (err) { 375 if (err) {
385 /* 376 /*
386 * Update is finished, @err contains number of actually written 377 * The operation is finished, @err contains number of actually
387 * bytes now. 378 * written bytes.
388 */ 379 */
389 count = err; 380 count = err;
390 381
382 if (vol->changing_leb) {
383 revoke_exclusive(desc, UBI_READWRITE);
384 return count;
385 }
386
391 err = ubi_check_volume(ubi, vol->vol_id); 387 err = ubi_check_volume(ubi, vol->vol_id);
392 if (err < 0) 388 if (err < 0)
393 return err; 389 return err;
@@ -402,7 +398,6 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
402 revoke_exclusive(desc, UBI_READWRITE); 398 revoke_exclusive(desc, UBI_READWRITE);
403 } 399 }
404 400
405 *offp += count;
406 return count; 401 return count;
407} 402}
408 403
@@ -447,11 +442,46 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
447 if (err < 0) 442 if (err < 0)
448 break; 443 break;
449 444
450 err = ubi_start_update(ubi, vol->vol_id, bytes); 445 err = ubi_start_update(ubi, vol, bytes);
451 if (bytes == 0) 446 if (bytes == 0)
452 revoke_exclusive(desc, UBI_READWRITE); 447 revoke_exclusive(desc, UBI_READWRITE);
448 break;
449 }
450
451 /* Atomic logical eraseblock change command */
452 case UBI_IOCEBCH:
453 {
454 struct ubi_leb_change_req req;
455
456 err = copy_from_user(&req, argp,
457 sizeof(struct ubi_leb_change_req));
458 if (err) {
459 err = -EFAULT;
460 break;
461 }
462
463 if (desc->mode == UBI_READONLY ||
464 vol->vol_type == UBI_STATIC_VOLUME) {
465 err = -EROFS;
466 break;
467 }
468
469 /* Validate the request */
470 err = -EINVAL;
471 if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
472 req.bytes < 0 || req.lnum >= vol->usable_leb_size)
473 break;
474 if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
475 req.dtype != UBI_UNKNOWN)
476 break;
477
478 err = get_exclusive(desc);
479 if (err < 0)
480 break;
453 481
454 file->f_pos = 0; 482 err = ubi_start_leb_change(ubi, vol, &req);
483 if (req.bytes == 0)
484 revoke_exclusive(desc, UBI_READWRITE);
455 break; 485 break;
456 } 486 }
457 487
@@ -467,7 +497,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
467 break; 497 break;
468 } 498 }
469 499
470 if (desc->mode == UBI_READONLY) { 500 if (desc->mode == UBI_READONLY ||
501 vol->vol_type == UBI_STATIC_VOLUME) {
471 err = -EROFS; 502 err = -EROFS;
472 break; 503 break;
473 } 504 }
@@ -477,13 +508,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
477 break; 508 break;
478 } 509 }
479 510
480 if (vol->vol_type != UBI_DYNAMIC_VOLUME) {
481 err = -EROFS;
482 break;
483 }
484
485 dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); 511 dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
486 err = ubi_eba_unmap_leb(ubi, vol->vol_id, lnum); 512 err = ubi_eba_unmap_leb(ubi, vol, lnum);
487 if (err) 513 if (err)
488 break; 514 break;
489 515
@@ -580,9 +606,9 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
580 if (!capable(CAP_SYS_RESOURCE)) 606 if (!capable(CAP_SYS_RESOURCE))
581 return -EPERM; 607 return -EPERM;
582 608
583 ubi = major_to_device(imajor(inode)); 609 ubi = ubi_get_by_major(imajor(inode));
584 if (IS_ERR(ubi)) 610 if (!ubi)
585 return PTR_ERR(ubi); 611 return -ENODEV;
586 612
587 switch (cmd) { 613 switch (cmd) {
588 /* Create volume command */ 614 /* Create volume command */
@@ -591,8 +617,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
591 struct ubi_mkvol_req req; 617 struct ubi_mkvol_req req;
592 618
593 dbg_msg("create volume"); 619 dbg_msg("create volume");
594 err = copy_from_user(&req, argp, 620 err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req));
595 sizeof(struct ubi_mkvol_req));
596 if (err) { 621 if (err) {
597 err = -EFAULT; 622 err = -EFAULT;
598 break; 623 break;
@@ -604,7 +629,9 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
604 629
605 req.name[req.name_len] = '\0'; 630 req.name[req.name_len] = '\0';
606 631
632 mutex_lock(&ubi->volumes_mutex);
607 err = ubi_create_volume(ubi, &req); 633 err = ubi_create_volume(ubi, &req);
634 mutex_unlock(&ubi->volumes_mutex);
608 if (err) 635 if (err)
609 break; 636 break;
610 637
@@ -633,10 +660,16 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
633 break; 660 break;
634 } 661 }
635 662
663 mutex_lock(&ubi->volumes_mutex);
636 err = ubi_remove_volume(desc); 664 err = ubi_remove_volume(desc);
637 if (err) 665 mutex_unlock(&ubi->volumes_mutex);
638 ubi_close_volume(desc);
639 666
667 /*
668 * The volume is deleted (unless an error occurred), and the
669 * 'struct ubi_volume' object will be freed when
670 * 'ubi_close_volume()' will call 'put_device()'.
671 */
672 ubi_close_volume(desc);
640 break; 673 break;
641 } 674 }
642 675
@@ -648,8 +681,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
648 struct ubi_rsvol_req req; 681 struct ubi_rsvol_req req;
649 682
650 dbg_msg("re-size volume"); 683 dbg_msg("re-size volume");
651 err = copy_from_user(&req, argp, 684 err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req));
652 sizeof(struct ubi_rsvol_req));
653 if (err) { 685 if (err) {
654 err = -EFAULT; 686 err = -EFAULT;
655 break; 687 break;
@@ -669,7 +701,9 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
669 pebs = !!do_div(tmp, desc->vol->usable_leb_size); 701 pebs = !!do_div(tmp, desc->vol->usable_leb_size);
670 pebs += tmp; 702 pebs += tmp;
671 703
704 mutex_lock(&ubi->volumes_mutex);
672 err = ubi_resize_volume(desc, pebs); 705 err = ubi_resize_volume(desc, pebs);
706 mutex_unlock(&ubi->volumes_mutex);
673 ubi_close_volume(desc); 707 ubi_close_volume(desc);
674 break; 708 break;
675 } 709 }
@@ -679,9 +713,93 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
679 break; 713 break;
680 } 714 }
681 715
716 ubi_put_device(ubi);
682 return err; 717 return err;
683} 718}
684 719
720static int ctrl_cdev_ioctl(struct inode *inode, struct file *file,
721 unsigned int cmd, unsigned long arg)
722{
723 int err = 0;
724 void __user *argp = (void __user *)arg;
725
726 if (!capable(CAP_SYS_RESOURCE))
727 return -EPERM;
728
729 switch (cmd) {
730 /* Attach an MTD device command */
731 case UBI_IOCATT:
732 {
733 struct ubi_attach_req req;
734 struct mtd_info *mtd;
735
736 dbg_msg("attach MTD device");
737 err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req));
738 if (err) {
739 err = -EFAULT;
740 break;
741 }
742
743 if (req.mtd_num < 0 ||
744 (req.ubi_num < 0 && req.ubi_num != UBI_DEV_NUM_AUTO)) {
745 err = -EINVAL;
746 break;
747 }
748
749 mtd = get_mtd_device(NULL, req.mtd_num);
750 if (IS_ERR(mtd)) {
751 err = PTR_ERR(mtd);
752 break;
753 }
754
755 /*
756 * Note, further request verification is done by
757 * 'ubi_attach_mtd_dev()'.
758 */
759 mutex_lock(&ubi_devices_mutex);
760 err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset);
761 mutex_unlock(&ubi_devices_mutex);
762 if (err < 0)
763 put_mtd_device(mtd);
764 else
765 /* @err contains UBI device number */
766 err = put_user(err, (__user int32_t *)argp);
767
768 break;
769 }
770
771 /* Detach an MTD device command */
772 case UBI_IOCDET:
773 {
774 int ubi_num;
775
776 dbg_msg("dettach MTD device");
777 err = get_user(ubi_num, (__user int32_t *)argp);
778 if (err) {
779 err = -EFAULT;
780 break;
781 }
782
783 mutex_lock(&ubi_devices_mutex);
784 err = ubi_detach_mtd_dev(ubi_num, 0);
785 mutex_unlock(&ubi_devices_mutex);
786 break;
787 }
788
789 default:
790 err = -ENOTTY;
791 break;
792 }
793
794 return err;
795}
796
797/* UBI control character device operations */
798struct file_operations ubi_ctrl_cdev_operations = {
799 .ioctl = ctrl_cdev_ioctl,
800 .owner = THIS_MODULE,
801};
802
685/* UBI character device operations */ 803/* UBI character device operations */
686struct file_operations ubi_cdev_operations = { 804struct file_operations ubi_cdev_operations = {
687 .owner = THIS_MODULE, 805 .owner = THIS_MODULE,