Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / drivers / mtd / ubi / eba.c
index 5b9834c..4dd0391 100644 (file)
@@ -426,8 +426,25 @@ retry:
                                                 pnum, vol_id, lnum);
                                        err = -EBADMSG;
                                } else {
-                                       err = -EINVAL;
-                                       ubi_ro_mode(ubi);
+                                       /*
+                                        * Ending up here in the non-Fastmap case
+                                        * is a clear bug as the VID header had to
+                                        * be present at scan time to have it referenced.
+                                        * With fastmap the story is more complicated.
+                                        * Fastmap has the mapping info without the need
+                                        * of a full scan. So the LEB could have been
+                                        * unmapped, Fastmap cannot know this and keeps
+                                        * the LEB referenced.
+                                        * This is valid and works as the layer above UBI
+                                        * has to do bookkeeping about used/referenced
+                                        * LEBs in any case.
+                                        */
+                                       if (ubi->fast_attach) {
+                                               err = -EBADMSG;
+                                       } else {
+                                               err = -EINVAL;
+                                               ubi_ro_mode(ubi);
+                                       }
                                }
                        }
                        goto out_free;
@@ -558,6 +575,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
        int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
        struct ubi_volume *vol = ubi->volumes[idx];
        struct ubi_vid_hdr *vid_hdr;
+       uint32_t crc;
 
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
        if (!vid_hdr)
@@ -582,14 +600,8 @@ retry:
                goto out_put;
        }
 
-       vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-       err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
-       if (err) {
-               up_read(&ubi->fm_eba_sem);
-               goto write_error;
-       }
+       ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC);
 
-       data_size = offset + len;
        mutex_lock(&ubi->buf_mutex);
        memset(ubi->peb_buf + offset, 0xFF, len);
 
@@ -604,6 +616,19 @@ retry:
 
        memcpy(ubi->peb_buf + offset, buf, len);
 
+       data_size = offset + len;
+       crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
+       vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+       vid_hdr->copy_flag = 1;
+       vid_hdr->data_size = cpu_to_be32(data_size);
+       vid_hdr->data_crc = cpu_to_be32(crc);
+       err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
+       if (err) {
+               mutex_unlock(&ubi->buf_mutex);
+               up_read(&ubi->fm_eba_sem);
+               goto write_error;
+       }
+
        err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
        if (err) {
                mutex_unlock(&ubi->buf_mutex);