.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) International Business Machines Corp., 2006 |
---|
3 | 4 | * Copyright (c) Nokia Corporation, 2007 |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License as published by |
---|
7 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
8 | | - * (at your option) any later version. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
---|
13 | | - * the GNU General Public License for more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License |
---|
16 | | - * along with this program; if not, write to the Free Software |
---|
17 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
18 | 5 | * |
---|
19 | 6 | * Author: Artem Bityutskiy (Битюцкий Артём), |
---|
20 | 7 | * Frank Haverkamp |
---|
.. | .. |
---|
363 | 350 | * we still can use 'ubi->ubi_num'. |
---|
364 | 351 | */ |
---|
365 | 352 | ubi = container_of(dev, struct ubi_device, dev); |
---|
366 | | - ubi = ubi_get_device(ubi->ubi_num); |
---|
367 | | - if (!ubi) |
---|
368 | | - return -ENODEV; |
---|
369 | 353 | |
---|
370 | 354 | if (attr == &dev_eraseblock_size) |
---|
371 | 355 | ret = sprintf(buf, "%d\n", ubi->leb_size); |
---|
.. | .. |
---|
394 | 378 | else |
---|
395 | 379 | ret = -EINVAL; |
---|
396 | 380 | |
---|
397 | | - ubi_put_device(ubi); |
---|
398 | 381 | return ret; |
---|
399 | 382 | } |
---|
400 | 383 | |
---|
.. | .. |
---|
484 | 467 | err = ubi_add_volume(ubi, ubi->volumes[i]); |
---|
485 | 468 | if (err) { |
---|
486 | 469 | ubi_err(ubi, "cannot add volume %d", i); |
---|
| 470 | + ubi->volumes[i] = NULL; |
---|
487 | 471 | goto out_volumes; |
---|
488 | 472 | } |
---|
489 | 473 | } |
---|
.. | .. |
---|
516 | 500 | } |
---|
517 | 501 | |
---|
518 | 502 | /** |
---|
| 503 | + * ubi_free_volumes_from - free volumes from specific index. |
---|
| 504 | + * @ubi: UBI device description object |
---|
| 505 | + * @from: the start index used for volume free. |
---|
| 506 | + */ |
---|
| 507 | +static void ubi_free_volumes_from(struct ubi_device *ubi, int from) |
---|
| 508 | +{ |
---|
| 509 | + int i; |
---|
| 510 | + |
---|
| 511 | + for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { |
---|
| 512 | + if (!ubi->volumes[i]) |
---|
| 513 | + continue; |
---|
| 514 | + ubi_eba_replace_table(ubi->volumes[i], NULL); |
---|
| 515 | + ubi_fastmap_destroy_checkmap(ubi->volumes[i]); |
---|
| 516 | + kfree(ubi->volumes[i]); |
---|
| 517 | + ubi->volumes[i] = NULL; |
---|
| 518 | + } |
---|
| 519 | +} |
---|
| 520 | + |
---|
| 521 | +/** |
---|
| 522 | + * ubi_free_all_volumes - free all volumes. |
---|
| 523 | + * @ubi: UBI device description object |
---|
| 524 | + */ |
---|
| 525 | +void ubi_free_all_volumes(struct ubi_device *ubi) |
---|
| 526 | +{ |
---|
| 527 | + ubi_free_volumes_from(ubi, 0); |
---|
| 528 | +} |
---|
| 529 | + |
---|
| 530 | +/** |
---|
519 | 531 | * ubi_free_internal_volumes - free internal volumes. |
---|
520 | 532 | * @ubi: UBI device description object |
---|
521 | 533 | */ |
---|
522 | 534 | void ubi_free_internal_volumes(struct ubi_device *ubi) |
---|
523 | 535 | { |
---|
524 | | - int i; |
---|
525 | | - |
---|
526 | | - for (i = ubi->vtbl_slots; |
---|
527 | | - i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { |
---|
528 | | - ubi_eba_replace_table(ubi->volumes[i], NULL); |
---|
529 | | - ubi_fastmap_destroy_checkmap(ubi->volumes[i]); |
---|
530 | | - kfree(ubi->volumes[i]); |
---|
531 | | - } |
---|
| 536 | + ubi_free_volumes_from(ubi, ubi->vtbl_slots); |
---|
532 | 537 | } |
---|
533 | 538 | |
---|
534 | 539 | static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024) |
---|
.. | .. |
---|
675 | 680 | ~(ubi->hdrs_min_io_size - 1); |
---|
676 | 681 | ubi->vid_hdr_shift = ubi->vid_hdr_offset - |
---|
677 | 682 | ubi->vid_hdr_aloffset; |
---|
| 683 | + } |
---|
| 684 | + |
---|
| 685 | + /* |
---|
| 686 | + * Memory allocation for VID header is ubi->vid_hdr_alsize |
---|
| 687 | + * which is described in comments in io.c. |
---|
| 688 | + * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds |
---|
| 689 | + * ubi->vid_hdr_alsize, so that all vid header operations |
---|
| 690 | + * won't access memory out of bounds. |
---|
| 691 | + */ |
---|
| 692 | + if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) { |
---|
| 693 | + ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)" |
---|
| 694 | + " + VID header size(%zu) > VID header aligned size(%d).", |
---|
| 695 | + ubi->vid_hdr_offset, ubi->vid_hdr_shift, |
---|
| 696 | + UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize); |
---|
| 697 | + return -EINVAL; |
---|
678 | 698 | } |
---|
679 | 699 | |
---|
680 | 700 | /* Similar for the data offset */ |
---|
.. | .. |
---|
859 | 879 | * Both UBI and UBIFS have been designed for SLC NAND and NOR flashes. |
---|
860 | 880 | * MLC NAND is different and needs special care, otherwise UBI or UBIFS |
---|
861 | 881 | * will die soon and you will lose all your data. |
---|
| 882 | + * Relax this rule if the partition we're attaching to operates in SLC |
---|
| 883 | + * mode. |
---|
862 | 884 | */ |
---|
863 | | - if (mtd->type == MTD_MLCNANDFLASH) { |
---|
| 885 | + if (mtd->type == MTD_MLCNANDFLASH && |
---|
| 886 | + !(mtd->flags & MTD_SLC_ON_MLC_EMULATION)) { |
---|
864 | 887 | pr_err("ubi: refuse attaching mtd%d - MLC NAND is not supported\n", |
---|
| 888 | + mtd->index); |
---|
| 889 | + return -EINVAL; |
---|
| 890 | + } |
---|
| 891 | + |
---|
| 892 | + /* UBI cannot work on flashes with zero erasesize. */ |
---|
| 893 | + if (!mtd->erasesize) { |
---|
| 894 | + pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n", |
---|
865 | 895 | mtd->index); |
---|
866 | 896 | return -EINVAL; |
---|
867 | 897 | } |
---|
.. | .. |
---|
969 | 999 | goto out_detach; |
---|
970 | 1000 | } |
---|
971 | 1001 | |
---|
972 | | - /* Make device "available" before it becomes accessible via sysfs */ |
---|
973 | | - ubi_devices[ubi_num] = ubi; |
---|
974 | | - |
---|
975 | 1002 | err = uif_init(ubi); |
---|
976 | 1003 | if (err) |
---|
977 | 1004 | goto out_detach; |
---|
.. | .. |
---|
1016 | 1043 | wake_up_process(ubi->bgt_thread); |
---|
1017 | 1044 | spin_unlock(&ubi->wl_lock); |
---|
1018 | 1045 | |
---|
| 1046 | + ubi_devices[ubi_num] = ubi; |
---|
1019 | 1047 | ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL); |
---|
1020 | 1048 | return ubi_num; |
---|
1021 | 1049 | |
---|
.. | .. |
---|
1024 | 1052 | out_uif: |
---|
1025 | 1053 | uif_close(ubi); |
---|
1026 | 1054 | out_detach: |
---|
1027 | | - ubi_devices[ubi_num] = NULL; |
---|
1028 | 1055 | ubi_wl_close(ubi); |
---|
1029 | | - ubi_free_internal_volumes(ubi); |
---|
| 1056 | + ubi_free_all_volumes(ubi); |
---|
1030 | 1057 | vfree(ubi->vtbl); |
---|
1031 | 1058 | out_free: |
---|
1032 | 1059 | vfree(ubi->peb_buf); |
---|
.. | .. |
---|
1172 | 1199 | * MTD device name. |
---|
1173 | 1200 | */ |
---|
1174 | 1201 | mtd = get_mtd_device_nm(mtd_dev); |
---|
1175 | | - if (IS_ERR(mtd) && PTR_ERR(mtd) == -ENODEV) |
---|
| 1202 | + if (PTR_ERR(mtd) == -ENODEV) |
---|
1176 | 1203 | /* Probably this is an MTD character device node path */ |
---|
1177 | 1204 | mtd = open_mtd_by_chdev(mtd_dev); |
---|
1178 | 1205 | } else |
---|
.. | .. |
---|
1334 | 1361 | switch (*endp) { |
---|
1335 | 1362 | case 'G': |
---|
1336 | 1363 | result *= 1024; |
---|
| 1364 | + fallthrough; |
---|
1337 | 1365 | case 'M': |
---|
1338 | 1366 | result *= 1024; |
---|
| 1367 | + fallthrough; |
---|
1339 | 1368 | case 'K': |
---|
1340 | 1369 | result *= 1024; |
---|
1341 | 1370 | if (endp[1] == 'i' && endp[2] == 'B') |
---|
.. | .. |
---|
1463 | 1492 | MODULE_DESCRIPTION("UBI - Unsorted Block Images"); |
---|
1464 | 1493 | MODULE_AUTHOR("Artem Bityutskiy"); |
---|
1465 | 1494 | MODULE_LICENSE("GPL"); |
---|
| 1495 | +MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); |
---|