Merge git://git.infradead.org/mtd-2.6
[pandora-kernel.git] / drivers / mtd / ubi / cdev.c
1 /*
2  * Copyright (c) International Business Machines Corp., 2006
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12  * the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Artem Bityutskiy (Битюцкий Артём)
19  */
20
21 /*
22  * This file includes implementation of UBI character device operations.
23  *
24  * There are two kinds of character devices in UBI: UBI character devices and
25  * UBI volume character devices. UBI character devices allow users to
26  * manipulate whole volumes: create, remove, and re-size them. Volume character
27  * devices provide volume I/O capabilities.
28  *
29  * Major and minor numbers are assigned dynamically to both UBI and volume
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.
36  */
37
38 #include <linux/module.h>
39 #include <linux/stat.h>
40 #include <linux/ioctl.h>
41 #include <linux/capability.h>
42 #include <mtd/ubi-user.h>
43 #include <asm/uaccess.h>
44 #include <asm/div64.h>
45 #include "ubi.h"
46
47 /**
48  * get_exclusive - get exclusive access to an UBI volume.
49  * @desc: volume descriptor
50  *
51  * This function changes UBI volume open mode to "exclusive". Returns previous
52  * mode value (positive integer) in case of success and a negative error code
53  * in case of failure.
54  */
55 static int get_exclusive(struct ubi_volume_desc *desc)
56 {
57         int users, err;
58         struct ubi_volume *vol = desc->vol;
59
60         spin_lock(&vol->ubi->volumes_lock);
61         users = vol->readers + vol->writers + vol->exclusive;
62         ubi_assert(users > 0);
63         if (users > 1) {
64                 dbg_err("%d users for volume %d", users, vol->vol_id);
65                 err = -EBUSY;
66         } else {
67                 vol->readers = vol->writers = 0;
68                 vol->exclusive = 1;
69                 err = desc->mode;
70                 desc->mode = UBI_EXCLUSIVE;
71         }
72         spin_unlock(&vol->ubi->volumes_lock);
73
74         return err;
75 }
76
77 /**
78  * revoke_exclusive - revoke exclusive mode.
79  * @desc: volume descriptor
80  * @mode: new mode to switch to
81  */
82 static void revoke_exclusive(struct ubi_volume_desc *desc, int mode)
83 {
84         struct ubi_volume *vol = desc->vol;
85
86         spin_lock(&vol->ubi->volumes_lock);
87         ubi_assert(vol->readers == 0 && vol->writers == 0);
88         ubi_assert(vol->exclusive == 1 && desc->mode == UBI_EXCLUSIVE);
89         vol->exclusive = 0;
90         if (mode == UBI_READONLY)
91                 vol->readers = 1;
92         else if (mode == UBI_READWRITE)
93                 vol->writers = 1;
94         else
95                 vol->exclusive = 1;
96         spin_unlock(&vol->ubi->volumes_lock);
97
98         desc->mode = mode;
99 }
100
101 static int vol_cdev_open(struct inode *inode, struct file *file)
102 {
103         struct ubi_volume_desc *desc;
104         int vol_id = iminor(inode) - 1, mode, ubi_num;
105
106         ubi_num = ubi_major2num(imajor(inode));
107         if (ubi_num < 0)
108                 return ubi_num;
109
110         if (file->f_mode & FMODE_WRITE)
111                 mode = UBI_READWRITE;
112         else
113                 mode = UBI_READONLY;
114
115         dbg_msg("open volume %d, mode %d", vol_id, mode);
116
117         desc = ubi_open_volume(ubi_num, vol_id, mode);
118         if (IS_ERR(desc))
119                 return PTR_ERR(desc);
120
121         file->private_data = desc;
122         return 0;
123 }
124
125 static int vol_cdev_release(struct inode *inode, struct file *file)
126 {
127         struct ubi_volume_desc *desc = file->private_data;
128         struct ubi_volume *vol = desc->vol;
129
130         dbg_msg("release volume %d, mode %d", vol->vol_id, desc->mode);
131
132         if (vol->updating) {
133                 ubi_warn("update of volume %d not finished, volume is damaged",
134                          vol->vol_id);
135                 ubi_assert(!vol->changing_leb);
136                 vol->updating = 0;
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);
144         }
145
146         ubi_close_volume(desc);
147         return 0;
148 }
149
150 static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
151 {
152         struct ubi_volume_desc *desc = file->private_data;
153         struct ubi_volume *vol = desc->vol;
154         loff_t new_offset;
155
156         if (vol->updating) {
157                  /* Update is in progress, seeking is prohibited */
158                 dbg_err("updating");
159                 return -EBUSY;
160         }
161
162         switch (origin) {
163         case 0: /* SEEK_SET */
164                 new_offset = offset;
165                 break;
166         case 1: /* SEEK_CUR */
167                 new_offset = file->f_pos + offset;
168                 break;
169         case 2: /* SEEK_END */
170                 new_offset = vol->used_bytes + offset;
171                 break;
172         default:
173                 return -EINVAL;
174         }
175
176         if (new_offset < 0 || new_offset > vol->used_bytes) {
177                 dbg_err("bad seek %lld", new_offset);
178                 return -EINVAL;
179         }
180
181         dbg_msg("seek volume %d, offset %lld, origin %d, new offset %lld",
182                 vol->vol_id, offset, origin, new_offset);
183
184         file->f_pos = new_offset;
185         return new_offset;
186 }
187
188 static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
189                              loff_t *offp)
190 {
191         struct ubi_volume_desc *desc = file->private_data;
192         struct ubi_volume *vol = desc->vol;
193         struct ubi_device *ubi = vol->ubi;
194         int err, lnum, off, len,  tbuf_size;
195         size_t count_save = count;
196         void *tbuf;
197         uint64_t tmp;
198
199         dbg_msg("read %zd bytes from offset %lld of volume %d",
200                 count, *offp, vol->vol_id);
201
202         if (vol->updating) {
203                 dbg_err("updating");
204                 return -EBUSY;
205         }
206         if (vol->upd_marker) {
207                 dbg_err("damaged volume, update marker is set");
208                 return -EBADF;
209         }
210         if (*offp == vol->used_bytes || count == 0)
211                 return 0;
212
213         if (vol->corrupted)
214                 dbg_msg("read from corrupted volume %d", vol->vol_id);
215
216         if (*offp + count > vol->used_bytes)
217                 count_save = count = vol->used_bytes - *offp;
218
219         tbuf_size = vol->usable_leb_size;
220         if (count < tbuf_size)
221                 tbuf_size = ALIGN(count, ubi->min_io_size);
222         tbuf = vmalloc(tbuf_size);
223         if (!tbuf)
224                 return -ENOMEM;
225
226         len = count > tbuf_size ? tbuf_size : count;
227
228         tmp = *offp;
229         off = do_div(tmp, vol->usable_leb_size);
230         lnum = tmp;
231
232         do {
233                 cond_resched();
234
235                 if (off + len >= vol->usable_leb_size)
236                         len = vol->usable_leb_size - off;
237
238                 err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
239                 if (err)
240                         break;
241
242                 off += len;
243                 if (off == vol->usable_leb_size) {
244                         lnum += 1;
245                         off -= vol->usable_leb_size;
246                 }
247
248                 count -= len;
249                 *offp += len;
250
251                 err = copy_to_user(buf, tbuf, len);
252                 if (err) {
253                         err = -EFAULT;
254                         break;
255                 }
256
257                 buf += len;
258                 len = count > tbuf_size ? tbuf_size : count;
259         } while (count);
260
261         vfree(tbuf);
262         return err ? err : count_save - count;
263 }
264
265 #ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
266
267 /*
268  * This function allows to directly write to dynamic UBI volumes, without
269  * issuing the volume update operation. Available only as a debugging feature.
270  * Very useful for testing UBI.
271  */
272 static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
273                                      size_t count, loff_t *offp)
274 {
275         struct ubi_volume_desc *desc = file->private_data;
276         struct ubi_volume *vol = desc->vol;
277         struct ubi_device *ubi = vol->ubi;
278         int lnum, off, len, tbuf_size, err = 0;
279         size_t count_save = count;
280         char *tbuf;
281         uint64_t tmp;
282
283         dbg_msg("requested: write %zd bytes to offset %lld of volume %u",
284                 count, *offp, vol->vol_id);
285
286         if (vol->vol_type == UBI_STATIC_VOLUME)
287                 return -EROFS;
288
289         tmp = *offp;
290         off = do_div(tmp, vol->usable_leb_size);
291         lnum = tmp;
292
293         if (off % ubi->min_io_size) {
294                 dbg_err("unaligned position");
295                 return -EINVAL;
296         }
297
298         if (*offp + count > vol->used_bytes)
299                 count_save = count = vol->used_bytes - *offp;
300
301         /* We can write only in fractions of the minimum I/O unit */
302         if (count % ubi->min_io_size) {
303                 dbg_err("unaligned write length");
304                 return -EINVAL;
305         }
306
307         tbuf_size = vol->usable_leb_size;
308         if (count < tbuf_size)
309                 tbuf_size = ALIGN(count, ubi->min_io_size);
310         tbuf = vmalloc(tbuf_size);
311         if (!tbuf)
312                 return -ENOMEM;
313
314         len = count > tbuf_size ? tbuf_size : count;
315
316         while (count) {
317                 cond_resched();
318
319                 if (off + len >= vol->usable_leb_size)
320                         len = vol->usable_leb_size - off;
321
322                 err = copy_from_user(tbuf, buf, len);
323                 if (err) {
324                         err = -EFAULT;
325                         break;
326                 }
327
328                 err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len,
329                                         UBI_UNKNOWN);
330                 if (err)
331                         break;
332
333                 off += len;
334                 if (off == vol->usable_leb_size) {
335                         lnum += 1;
336                         off -= vol->usable_leb_size;
337                 }
338
339                 count -= len;
340                 *offp += len;
341                 buf += len;
342                 len = count > tbuf_size ? tbuf_size : count;
343         }
344
345         vfree(tbuf);
346         return err ? err : count_save - count;
347 }
348
349 #else
350 #define vol_cdev_direct_write(file, buf, count, offp) -EPERM
351 #endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */
352
353 static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
354                               size_t count, loff_t *offp)
355 {
356         int err = 0;
357         struct ubi_volume_desc *desc = file->private_data;
358         struct ubi_volume *vol = desc->vol;
359         struct ubi_device *ubi = vol->ubi;
360
361         if (!vol->updating && !vol->changing_leb)
362                 return vol_cdev_direct_write(file, buf, count, offp);
363
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
369         if (err < 0) {
370                 ubi_err("cannot accept more %zd bytes of data, error %d",
371                         count, err);
372                 return err;
373         }
374
375         if (err) {
376                 /*
377                  * The operation is finished, @err contains number of actually
378                  * written bytes.
379                  */
380                 count = err;
381
382                 if (vol->changing_leb) {
383                         revoke_exclusive(desc, UBI_READWRITE);
384                         return count;
385                 }
386
387                 err = ubi_check_volume(ubi, vol->vol_id);
388                 if (err < 0)
389                         return err;
390
391                 if (err) {
392                         ubi_warn("volume %d on UBI device %d is corrupted",
393                                  vol->vol_id, ubi->ubi_num);
394                         vol->corrupted = 1;
395                 }
396                 vol->checked = 1;
397                 ubi_gluebi_updated(vol);
398                 revoke_exclusive(desc, UBI_READWRITE);
399         }
400
401         return count;
402 }
403
404 static int vol_cdev_ioctl(struct inode *inode, struct file *file,
405                           unsigned int cmd, unsigned long arg)
406 {
407         int err = 0;
408         struct ubi_volume_desc *desc = file->private_data;
409         struct ubi_volume *vol = desc->vol;
410         struct ubi_device *ubi = vol->ubi;
411         void __user *argp = (void __user *)arg;
412
413         switch (cmd) {
414         /* Volume update command */
415         case UBI_IOCVOLUP:
416         {
417                 int64_t bytes, rsvd_bytes;
418
419                 if (!capable(CAP_SYS_RESOURCE)) {
420                         err = -EPERM;
421                         break;
422                 }
423
424                 err = copy_from_user(&bytes, argp, sizeof(int64_t));
425                 if (err) {
426                         err = -EFAULT;
427                         break;
428                 }
429
430                 if (desc->mode == UBI_READONLY) {
431                         err = -EROFS;
432                         break;
433                 }
434
435                 rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad);
436                 if (bytes < 0 || bytes > rsvd_bytes) {
437                         err = -EINVAL;
438                         break;
439                 }
440
441                 err = get_exclusive(desc);
442                 if (err < 0)
443                         break;
444
445                 err = ubi_start_update(ubi, vol, bytes);
446                 if (bytes == 0)
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;
481
482                 err = ubi_start_leb_change(ubi, vol, &req);
483                 if (req.bytes == 0)
484                         revoke_exclusive(desc, UBI_READWRITE);
485                 break;
486         }
487
488 #ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
489         /* Logical eraseblock erasure command */
490         case UBI_IOCEBER:
491         {
492                 int32_t lnum;
493
494                 err = get_user(lnum, (__user int32_t *)argp);
495                 if (err) {
496                         err = -EFAULT;
497                         break;
498                 }
499
500                 if (desc->mode == UBI_READONLY ||
501                     vol->vol_type == UBI_STATIC_VOLUME) {
502                         err = -EROFS;
503                         break;
504                 }
505
506                 if (lnum < 0 || lnum >= vol->reserved_pebs) {
507                         err = -EINVAL;
508                         break;
509                 }
510
511                 dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
512                 err = ubi_eba_unmap_leb(ubi, vol, lnum);
513                 if (err)
514                         break;
515
516                 err = ubi_wl_flush(ubi);
517                 break;
518         }
519 #endif
520
521         default:
522                 err = -ENOTTY;
523                 break;
524         }
525
526         return err;
527 }
528
529 /**
530  * verify_mkvol_req - verify volume creation request.
531  * @ubi: UBI device description object
532  * @req: the request to check
533  *
534  * This function zero if the request is correct, and %-EINVAL if not.
535  */
536 static int verify_mkvol_req(const struct ubi_device *ubi,
537                             const struct ubi_mkvol_req *req)
538 {
539         int n, err = -EINVAL;
540
541         if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 ||
542             req->name_len < 0)
543                 goto bad;
544
545         if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) &&
546             req->vol_id != UBI_VOL_NUM_AUTO)
547                 goto bad;
548
549         if (req->alignment == 0)
550                 goto bad;
551
552         if (req->bytes == 0)
553                 goto bad;
554
555         if (req->vol_type != UBI_DYNAMIC_VOLUME &&
556             req->vol_type != UBI_STATIC_VOLUME)
557                 goto bad;
558
559         if (req->alignment > ubi->leb_size)
560                 goto bad;
561
562         n = req->alignment % ubi->min_io_size;
563         if (req->alignment != 1 && n)
564                 goto bad;
565
566         if (req->name_len > UBI_VOL_NAME_MAX) {
567                 err = -ENAMETOOLONG;
568                 goto bad;
569         }
570
571         return 0;
572
573 bad:
574         dbg_err("bad volume creation request");
575         ubi_dbg_dump_mkvol_req(req);
576         return err;
577 }
578
579 /**
580  * verify_rsvol_req - verify volume re-size request.
581  * @ubi: UBI device description object
582  * @req: the request to check
583  *
584  * This function returns zero if the request is correct, and %-EINVAL if not.
585  */
586 static int verify_rsvol_req(const struct ubi_device *ubi,
587                             const struct ubi_rsvol_req *req)
588 {
589         if (req->bytes <= 0)
590                 return -EINVAL;
591
592         if (req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots)
593                 return -EINVAL;
594
595         return 0;
596 }
597
598 static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
599                           unsigned int cmd, unsigned long arg)
600 {
601         int err = 0;
602         struct ubi_device *ubi;
603         struct ubi_volume_desc *desc;
604         void __user *argp = (void __user *)arg;
605
606         if (!capable(CAP_SYS_RESOURCE))
607                 return -EPERM;
608
609         ubi = ubi_get_by_major(imajor(inode));
610         if (!ubi)
611                 return -ENODEV;
612
613         switch (cmd) {
614         /* Create volume command */
615         case UBI_IOCMKVOL:
616         {
617                 struct ubi_mkvol_req req;
618
619                 dbg_msg("create volume");
620                 err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req));
621                 if (err) {
622                         err = -EFAULT;
623                         break;
624                 }
625
626                 err = verify_mkvol_req(ubi, &req);
627                 if (err)
628                         break;
629
630                 req.name[req.name_len] = '\0';
631
632                 mutex_lock(&ubi->volumes_mutex);
633                 err = ubi_create_volume(ubi, &req);
634                 mutex_unlock(&ubi->volumes_mutex);
635                 if (err)
636                         break;
637
638                 err = put_user(req.vol_id, (__user int32_t *)argp);
639                 if (err)
640                         err = -EFAULT;
641
642                 break;
643         }
644
645         /* Remove volume command */
646         case UBI_IOCRMVOL:
647         {
648                 int vol_id;
649
650                 dbg_msg("remove volume");
651                 err = get_user(vol_id, (__user int32_t *)argp);
652                 if (err) {
653                         err = -EFAULT;
654                         break;
655                 }
656
657                 desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
658                 if (IS_ERR(desc)) {
659                         err = PTR_ERR(desc);
660                         break;
661                 }
662
663                 mutex_lock(&ubi->volumes_mutex);
664                 err = ubi_remove_volume(desc);
665                 mutex_unlock(&ubi->volumes_mutex);
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);
673                 break;
674         }
675
676         /* Re-size volume command */
677         case UBI_IOCRSVOL:
678         {
679                 int pebs;
680                 uint64_t tmp;
681                 struct ubi_rsvol_req req;
682
683                 dbg_msg("re-size volume");
684                 err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req));
685                 if (err) {
686                         err = -EFAULT;
687                         break;
688                 }
689
690                 err = verify_rsvol_req(ubi, &req);
691                 if (err)
692                         break;
693
694                 desc = ubi_open_volume(ubi->ubi_num, req.vol_id, UBI_EXCLUSIVE);
695                 if (IS_ERR(desc)) {
696                         err = PTR_ERR(desc);
697                         break;
698                 }
699
700                 tmp = req.bytes;
701                 pebs = !!do_div(tmp, desc->vol->usable_leb_size);
702                 pebs += tmp;
703
704                 mutex_lock(&ubi->volumes_mutex);
705                 err = ubi_resize_volume(desc, pebs);
706                 mutex_unlock(&ubi->volumes_mutex);
707                 ubi_close_volume(desc);
708                 break;
709         }
710
711         default:
712                 err = -ENOTTY;
713                 break;
714         }
715
716         ubi_put_device(ubi);
717         return err;
718 }
719
720 static 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 */
798 struct file_operations ubi_ctrl_cdev_operations = {
799         .ioctl = ctrl_cdev_ioctl,
800         .owner = THIS_MODULE,
801 };
802
803 /* UBI character device operations */
804 struct file_operations ubi_cdev_operations = {
805         .owner = THIS_MODULE,
806         .ioctl = ubi_cdev_ioctl,
807         .llseek = no_llseek,
808 };
809
810 /* UBI volume character device operations */
811 struct file_operations ubi_vol_cdev_operations = {
812         .owner   = THIS_MODULE,
813         .open    = vol_cdev_open,
814         .release = vol_cdev_release,
815         .llseek  = vol_cdev_llseek,
816         .read    = vol_cdev_read,
817         .write   = vol_cdev_write,
818         .ioctl   = vol_cdev_ioctl,
819 };