diff options
Diffstat (limited to 'drivers/mtd/ubi/vtbl.c')
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 25b3bd61c7ec..56fc3fbce838 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
@@ -86,8 +86,10 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, | |||
86 | { | 86 | { |
87 | int i, err; | 87 | int i, err; |
88 | uint32_t crc; | 88 | uint32_t crc; |
89 | struct ubi_volume *layout_vol; | ||
89 | 90 | ||
90 | ubi_assert(idx >= 0 && idx < ubi->vtbl_slots); | 91 | ubi_assert(idx >= 0 && idx < ubi->vtbl_slots); |
92 | layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)]; | ||
91 | 93 | ||
92 | if (!vtbl_rec) | 94 | if (!vtbl_rec) |
93 | vtbl_rec = &empty_vtbl_record; | 95 | vtbl_rec = &empty_vtbl_record; |
@@ -96,31 +98,25 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, | |||
96 | vtbl_rec->crc = cpu_to_be32(crc); | 98 | vtbl_rec->crc = cpu_to_be32(crc); |
97 | } | 99 | } |
98 | 100 | ||
99 | mutex_lock(&ubi->vtbl_mutex); | ||
100 | memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record)); | 101 | memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record)); |
101 | for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { | 102 | for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { |
102 | err = ubi_eba_unmap_leb(ubi, UBI_LAYOUT_VOL_ID, i); | 103 | err = ubi_eba_unmap_leb(ubi, layout_vol, i); |
103 | if (err) { | 104 | if (err) |
104 | mutex_unlock(&ubi->vtbl_mutex); | ||
105 | return err; | 105 | return err; |
106 | } | 106 | |
107 | err = ubi_eba_write_leb(ubi, UBI_LAYOUT_VOL_ID, i, ubi->vtbl, 0, | 107 | err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, |
108 | ubi->vtbl_size, UBI_LONGTERM); | 108 | ubi->vtbl_size, UBI_LONGTERM); |
109 | if (err) { | 109 | if (err) |
110 | mutex_unlock(&ubi->vtbl_mutex); | ||
111 | return err; | 110 | return err; |
112 | } | ||
113 | } | 111 | } |
114 | 112 | ||
115 | paranoid_vtbl_check(ubi); | 113 | paranoid_vtbl_check(ubi); |
116 | mutex_unlock(&ubi->vtbl_mutex); | 114 | return 0; |
117 | return ubi_wl_flush(ubi); | ||
118 | } | 115 | } |
119 | 116 | ||
120 | /** | 117 | /** |
121 | * vol_til_check - check if volume table is not corrupted and contains sensible | 118 | * vtbl_check - check if volume table is not corrupted and contains sensible |
122 | * data. | 119 | * data. |
123 | * | ||
124 | * @ubi: UBI device description object | 120 | * @ubi: UBI device description object |
125 | * @vtbl: volume table | 121 | * @vtbl: volume table |
126 | * | 122 | * |
@@ -273,7 +269,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
273 | * this volume table copy was found during scanning. It has to be wiped | 269 | * this volume table copy was found during scanning. It has to be wiped |
274 | * out. | 270 | * out. |
275 | */ | 271 | */ |
276 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOL_ID); | 272 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); |
277 | if (sv) | 273 | if (sv) |
278 | old_seb = ubi_scan_find_seb(sv, copy); | 274 | old_seb = ubi_scan_find_seb(sv, copy); |
279 | 275 | ||
@@ -285,7 +281,7 @@ retry: | |||
285 | } | 281 | } |
286 | 282 | ||
287 | vid_hdr->vol_type = UBI_VID_DYNAMIC; | 283 | vid_hdr->vol_type = UBI_VID_DYNAMIC; |
288 | vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOL_ID); | 284 | vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID); |
289 | vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT; | 285 | vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT; |
290 | vid_hdr->data_size = vid_hdr->used_ebs = | 286 | vid_hdr->data_size = vid_hdr->used_ebs = |
291 | vid_hdr->data_pad = cpu_to_be32(0); | 287 | vid_hdr->data_pad = cpu_to_be32(0); |
@@ -518,6 +514,17 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
518 | vol->name[vol->name_len] = '\0'; | 514 | vol->name[vol->name_len] = '\0'; |
519 | vol->vol_id = i; | 515 | vol->vol_id = i; |
520 | 516 | ||
517 | if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) { | ||
518 | /* Auto re-size flag may be set only for one volume */ | ||
519 | if (ubi->autoresize_vol_id != -1) { | ||
520 | ubi_err("more then one auto-resize volume (%d " | ||
521 | "and %d)", ubi->autoresize_vol_id, i); | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | ubi->autoresize_vol_id = i; | ||
526 | } | ||
527 | |||
521 | ubi_assert(!ubi->volumes[i]); | 528 | ubi_assert(!ubi->volumes[i]); |
522 | ubi->volumes[i] = vol; | 529 | ubi->volumes[i] = vol; |
523 | ubi->vol_count += 1; | 530 | ubi->vol_count += 1; |
@@ -568,6 +575,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
568 | vol->last_eb_bytes = sv->last_data_size; | 575 | vol->last_eb_bytes = sv->last_data_size; |
569 | } | 576 | } |
570 | 577 | ||
578 | /* And add the layout volume */ | ||
571 | vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); | 579 | vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); |
572 | if (!vol) | 580 | if (!vol) |
573 | return -ENOMEM; | 581 | return -ENOMEM; |
@@ -582,7 +590,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
582 | vol->last_eb_bytes = vol->reserved_pebs; | 590 | vol->last_eb_bytes = vol->reserved_pebs; |
583 | vol->used_bytes = | 591 | vol->used_bytes = |
584 | (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); | 592 | (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); |
585 | vol->vol_id = UBI_LAYOUT_VOL_ID; | 593 | vol->vol_id = UBI_LAYOUT_VOLUME_ID; |
594 | vol->ref_count = 1; | ||
586 | 595 | ||
587 | ubi_assert(!ubi->volumes[i]); | 596 | ubi_assert(!ubi->volumes[i]); |
588 | ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol; | 597 | ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol; |
@@ -734,7 +743,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
734 | ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE; | 743 | ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE; |
735 | ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); | 744 | ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); |
736 | 745 | ||
737 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOL_ID); | 746 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); |
738 | if (!sv) { | 747 | if (!sv) { |
739 | /* | 748 | /* |
740 | * No logical eraseblocks belonging to the layout volume were | 749 | * No logical eraseblocks belonging to the layout volume were |