Merge tag 'upstream-4.8-rc1' of git://git.infradead.org/linux-ubifs
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Aug 2016 23:51:49 +0000 (19:51 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Aug 2016 23:51:49 +0000 (19:51 -0400)
Pull UBI/UBIFS updates from Richard Weinberger:
 "This contains mostly cleanups and minor improvements of UBI and UBIFS"

* tag 'upstream-4.8-rc1' of git://git.infradead.org/linux-ubifs:
  ubi: Use bitmaps in Fastmap self-check code
  ubi: Be more paranoid while seaching for the most recent Fastmap
  ubi: Check whether the Fastmap anchor matches the super block
  ubi: Rework Fastmap attach base code
  ubi: Fix whitespace issue in count_fastmap_pebs()
  ubi: Introduce vol_ignored()
  ubi: Fix scan_fast() comment
  ubifs: switch_gc_head: Remove redondant sync of wbuf
  ubi: Make volume resize power cut aware
  ubi: Fix early logging
  ubi: gluebi: Fix double refcounting
  ubifs: Silence early error messages if MS_SILENT is set
  ubi: Fix race condition between ubi device creation and udev
  ubifs: Update comment for ubifs_errc
  ubi: Only read necessary size when reading the VID header
  ubifs: Make xattr structures static
  ubifs: Silence error output if MS_SILENT is set

12 files changed:
drivers/mtd/ubi/attach.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/fastmap.c
drivers/mtd/ubi/gluebi.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/vmt.c
drivers/mtd/ubi/wl.c
fs/ubifs/gc.c
fs/ubifs/super.c
fs/ubifs/ubifs.h
fs/ubifs/xattr.c

index c1aaf0336cf2e389386b4a6f7c87a8609652b474..903becd3141051d23142baa75f52df1939a2bc94 100644 (file)
@@ -174,6 +174,40 @@ static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec)
        return 0;
 }
 
+/**
+ * add_fastmap - add a Fastmap related physical eraseblock.
+ * @ai: attaching information
+ * @pnum: physical eraseblock number the VID header came from
+ * @vid_hdr: the volume identifier header
+ * @ec: erase counter of the physical eraseblock
+ *
+ * This function allocates a 'struct ubi_ainf_peb' object for a Fastamp
+ * physical eraseblock @pnum and adds it to the 'fastmap' list.
+ * Such blocks can be Fastmap super and data blocks from both the most
+ * recent Fastmap we're attaching from or from old Fastmaps which will
+ * be erased.
+ */
+static int add_fastmap(struct ubi_attach_info *ai, int pnum,
+                      struct ubi_vid_hdr *vid_hdr, int ec)
+{
+       struct ubi_ainf_peb *aeb;
+
+       aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+       if (!aeb)
+               return -ENOMEM;
+
+       aeb->pnum = pnum;
+       aeb->vol_id = be32_to_cpu(vidh->vol_id);
+       aeb->sqnum = be64_to_cpu(vidh->sqnum);
+       aeb->ec = ec;
+       list_add(&aeb->u.list, &ai->fastmap);
+
+       dbg_bld("add to fastmap list: PEB %d, vol_id %d, sqnum: %llu", pnum,
+               aeb->vol_id, aeb->sqnum);
+
+       return 0;
+}
+
 /**
  * validate_vid_hdr - check volume identifier header.
  * @ubi: UBI device description object
@@ -803,13 +837,26 @@ out_unlock:
        return err;
 }
 
+static bool vol_ignored(int vol_id)
+{
+       switch (vol_id) {
+               case UBI_LAYOUT_VOLUME_ID:
+               return true;
+       }
+
+#ifdef CONFIG_MTD_UBI_FASTMAP
+       return ubi_is_fm_vol(vol_id);
+#else
+       return false;
+#endif
+}
+
 /**
  * scan_peb - scan and process UBI headers of a PEB.
  * @ubi: UBI device description object
  * @ai: attaching information
  * @pnum: the physical eraseblock number
- * @vid: The volume ID of the found volume will be stored in this pointer
- * @sqnum: The sqnum of the found volume will be stored in this pointer
+ * @fast: true if we're scanning for a Fastmap
  *
  * This function reads UBI headers of PEB @pnum, checks them, and adds
  * information about this PEB to the corresponding list or RB-tree in the
@@ -817,9 +864,9 @@ out_unlock:
  * successfully handled and a negative error code in case of failure.
  */
 static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
-                   int pnum, int *vid, unsigned long long *sqnum)
+                   int pnum, bool fast)
 {
-       long long uninitialized_var(ec);
+       long long ec;
        int err, bitflips = 0, vol_id = -1, ec_err = 0;
 
        dbg_bld("scan PEB %d", pnum);
@@ -935,6 +982,20 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
                         */
                        ai->maybe_bad_peb_count += 1;
        case UBI_IO_BAD_HDR:
+                       /*
+                        * If we're facing a bad VID header we have to drop *all*
+                        * Fastmap data structures we find. The most recent Fastmap
+                        * could be bad and therefore there is a chance that we attach
+                        * from an old one. On a fine MTD stack a PEB must not render
+                        * bad all of a sudden, but the reality is different.
+                        * So, let's be paranoid and help finding the root cause by
+                        * falling back to scanning mode instead of attaching with a
+                        * bad EBA table and cause data corruption which is hard to
+                        * analyze.
+                        */
+                       if (fast)
+                               ai->force_full_scan = 1;
+
                if (ec_err)
                        /*
                         * Both headers are corrupted. There is a possibility
@@ -991,21 +1052,15 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
        }
 
        vol_id = be32_to_cpu(vidh->vol_id);
-       if (vid)
-               *vid = vol_id;
-       if (sqnum)
-               *sqnum = be64_to_cpu(vidh->sqnum);
-       if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) {
+       if (vol_id > UBI_MAX_VOLUMES && !vol_ignored(vol_id)) {
                int lnum = be32_to_cpu(vidh->lnum);
 
                /* Unsupported internal volume */
                switch (vidh->compat) {
                case UBI_COMPAT_DELETE:
-                       if (vol_id != UBI_FM_SB_VOLUME_ID
-                           && vol_id != UBI_FM_DATA_VOLUME_ID) {
-                               ubi_msg(ubi, "\"delete\" compatible internal volume %d:%d found, will remove it",
-                                       vol_id, lnum);
-                       }
+                       ubi_msg(ubi, "\"delete\" compatible internal volume %d:%d found, will remove it",
+                               vol_id, lnum);
+
                        err = add_to_list(ai, pnum, vol_id, lnum,
                                          ec, 1, &ai->erase);
                        if (err)
@@ -1037,7 +1092,12 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
        if (ec_err)
                ubi_warn(ubi, "valid VID header but corrupted EC header at PEB %d",
                         pnum);
-       err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
+
+       if (ubi_is_fm_vol(vol_id))
+               err = add_fastmap(ai, pnum, vidh, ec);
+       else
+               err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
+
        if (err)
                return err;
 
@@ -1186,6 +1246,10 @@ static void destroy_ai(struct ubi_attach_info *ai)
                list_del(&aeb->u.list);
                kmem_cache_free(ai->aeb_slab_cache, aeb);
        }
+       list_for_each_entry_safe(aeb, aeb_tmp, &ai->fastmap, u.list) {
+               list_del(&aeb->u.list);
+               kmem_cache_free(ai->aeb_slab_cache, aeb);
+       }
 
        /* Destroy the volume RB-tree */
        rb = ai->volumes.rb_node;
@@ -1245,7 +1309,7 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,
                cond_resched();
 
                dbg_gen("process PEB %d", pnum);
-               err = scan_peb(ubi, ai, pnum, NULL, NULL);
+               err = scan_peb(ubi, ai, pnum, false);
                if (err < 0)
                        goto out_vidh;
        }
@@ -1311,6 +1375,7 @@ static struct ubi_attach_info *alloc_ai(void)
        INIT_LIST_HEAD(&ai->free);
        INIT_LIST_HEAD(&ai->erase);
        INIT_LIST_HEAD(&ai->alien);
+       INIT_LIST_HEAD(&ai->fastmap);
        ai->volumes = RB_ROOT;
        ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
                                               sizeof(struct ubi_ainf_peb),
@@ -1326,7 +1391,7 @@ static struct ubi_attach_info *alloc_ai(void)
 #ifdef CONFIG_MTD_UBI_FASTMAP
 
 /**
- * scan_fastmap - try to find a fastmap and attach from it.
+ * scan_fast - try to find a fastmap and attach from it.
  * @ubi: UBI device description object
  * @ai: attach info object
  *
@@ -1337,52 +1402,58 @@ static struct ubi_attach_info *alloc_ai(void)
  */
 static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
 {
-       int err, pnum, fm_anchor = -1;
-       unsigned long long max_sqnum = 0;
+       int err, pnum;
+       struct ubi_attach_info *scan_ai;
 
        err = -ENOMEM;
 
+       scan_ai = alloc_ai();
+       if (!scan_ai)
+               goto out;
+
        ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
        if (!ech)
-               goto out;
+               goto out_ai;
 
        vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
        if (!vidh)
                goto out_ech;
 
        for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) {
-               int vol_id = -1;
-               unsigned long long sqnum = -1;
                cond_resched();
 
                dbg_gen("process PEB %d", pnum);
-               err = scan_peb(ubi, *ai, pnum, &vol_id, &sqnum);
+               err = scan_peb(ubi, scan_ai, pnum, true);
                if (err < 0)
                        goto out_vidh;
-
-               if (vol_id == UBI_FM_SB_VOLUME_ID && sqnum > max_sqnum) {
-                       max_sqnum = sqnum;
-                       fm_anchor = pnum;
-               }
        }
 
        ubi_free_vid_hdr(ubi, vidh);
        kfree(ech);
 
-       if (fm_anchor < 0)
-               return UBI_NO_FASTMAP;
+       if (scan_ai->force_full_scan)
+               err = UBI_NO_FASTMAP;
+       else
+               err = ubi_scan_fastmap(ubi, *ai, scan_ai);
 
-       destroy_ai(*ai);
-       *ai = alloc_ai();
-       if (!*ai)
-               return -ENOMEM;
+       if (err) {
+               /*
+                * Didn't attach via fastmap, do a full scan but reuse what
+                * we've aready scanned.
+                */
+               destroy_ai(*ai);
+               *ai = scan_ai;
+       } else
+               destroy_ai(scan_ai);
 
-       return ubi_scan_fastmap(ubi, *ai, fm_anchor);
+       return err;
 
 out_vidh:
        ubi_free_vid_hdr(ubi, vidh);
 out_ech:
        kfree(ech);
+out_ai:
+       destroy_ai(scan_ai);
 out:
        return err;
 }
index ef3618299494f4973fd528ae72325490eb622b2c..0680516bb4728007871d0064b987d73141fa9aed 100644 (file)
@@ -874,7 +874,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
        for (i = 0; i < UBI_MAX_DEVICES; i++) {
                ubi = ubi_devices[i];
                if (ubi && mtd->index == ubi->mtd->index) {
-                       ubi_err(ubi, "mtd%d is already attached to ubi%d",
+                       pr_err("ubi: mtd%d is already attached to ubi%d",
                                mtd->index, i);
                        return -EEXIST;
                }
@@ -889,7 +889,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
         * no sense to attach emulated MTD devices, so we prohibit this.
         */
        if (mtd->type == MTD_UBIVOLUME) {
-               ubi_err(ubi, "refuse attaching mtd%d - it is already emulated on top of UBI",
+               pr_err("ubi: refuse attaching mtd%d - it is already emulated on top of UBI",
                        mtd->index);
                return -EINVAL;
        }
@@ -900,7 +900,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
                        if (!ubi_devices[ubi_num])
                                break;
                if (ubi_num == UBI_MAX_DEVICES) {
-                       ubi_err(ubi, "only %d UBI devices may be created",
+                       pr_err("ubi: only %d UBI devices may be created",
                                UBI_MAX_DEVICES);
                        return -ENFILE;
                }
@@ -910,7 +910,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
 
                /* Make sure ubi_num is not busy */
                if (ubi_devices[ubi_num]) {
-                       ubi_err(ubi, "already exists");
+                       pr_err("ubi: ubi%i already exists", ubi_num);
                        return -EEXIST;
                }
        }
@@ -992,6 +992,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
                        goto out_detach;
        }
 
+       /* Make device "available" before it becomes accessible via sysfs */
+       ubi_devices[ubi_num] = ubi;
+
        err = uif_init(ubi, &ref);
        if (err)
                goto out_detach;
@@ -1036,7 +1039,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
        wake_up_process(ubi->bgt_thread);
        spin_unlock(&ubi->wl_lock);
 
-       ubi_devices[ubi_num] = ubi;
        ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
        return ubi_num;
 
@@ -1047,6 +1049,7 @@ out_uif:
        ubi_assert(ref);
        uif_close(ubi);
 out_detach:
+       ubi_devices[ubi_num] = NULL;
        ubi_wl_close(ubi);
        ubi_free_internal_volumes(ubi);
        vfree(ubi->vtbl);
index 990898b9dc7289f881ecf357573bbc1d79bbf6ad..48eb55f344eb12b23e2f77c5736cffa816b3ded0 100644 (file)
  */
 
 #include <linux/crc32.h>
+#include <linux/bitmap.h>
 #include "ubi.h"
 
 /**
  * init_seen - allocate memory for used for debugging.
  * @ubi: UBI device description object
  */
-static inline int *init_seen(struct ubi_device *ubi)
+static inline unsigned long *init_seen(struct ubi_device *ubi)
 {
-       int *ret;
+       unsigned long *ret;
 
        if (!ubi_dbg_chk_fastmap(ubi))
                return NULL;
 
-       ret = kcalloc(ubi->peb_count, sizeof(int), GFP_KERNEL);
+       ret = kcalloc(BITS_TO_LONGS(ubi->peb_count), sizeof(unsigned long),
+                     GFP_KERNEL);
        if (!ret)
                return ERR_PTR(-ENOMEM);
 
@@ -39,7 +41,7 @@ static inline int *init_seen(struct ubi_device *ubi)
  * free_seen - free the seen logic integer array.
  * @seen: integer array of @ubi->peb_count size
  */
-static inline void free_seen(int *seen)
+static inline void free_seen(unsigned long *seen)
 {
        kfree(seen);
 }
@@ -50,12 +52,12 @@ static inline void free_seen(int *seen)
  * @pnum: The PEB to be makred as seen
  * @seen: integer array of @ubi->peb_count size
  */
-static inline void set_seen(struct ubi_device *ubi, int pnum, int *seen)
+static inline void set_seen(struct ubi_device *ubi, int pnum, unsigned long *seen)
 {
        if (!ubi_dbg_chk_fastmap(ubi) || !seen)
                return;
 
-       seen[pnum] = 1;
+       set_bit(pnum, seen);
 }
 
 /**
@@ -63,7 +65,7 @@ static inline void set_seen(struct ubi_device *ubi, int pnum, int *seen)
  * @ubi: UBI device description object
  * @seen: integer array of @ubi->peb_count size
  */
-static int self_check_seen(struct ubi_device *ubi, int *seen)
+static int self_check_seen(struct ubi_device *ubi, unsigned long *seen)
 {
        int pnum, ret = 0;
 
@@ -71,7 +73,7 @@ static int self_check_seen(struct ubi_device *ubi, int *seen)
                return 0;
 
        for (pnum = 0; pnum < ubi->peb_count; pnum++) {
-               if (!seen[pnum] && ubi->lookuptbl[pnum]) {
+               if (test_bit(pnum, seen) && ubi->lookuptbl[pnum]) {
                        ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum);
                        ret = -EINVAL;
                }
@@ -578,7 +580,7 @@ static int count_fastmap_pebs(struct ubi_attach_info *ai)
        list_for_each_entry(aeb, &ai->free, u.list)
                n++;
 
-        ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
+       ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
                ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
                        n++;
 
@@ -849,28 +851,58 @@ fail:
        return ret;
 }
 
+/**
+ * find_fm_anchor - find the most recent Fastmap superblock (anchor)
+ * @ai: UBI attach info to be filled
+ */
+static int find_fm_anchor(struct ubi_attach_info *ai)
+{
+       int ret = -1;
+       struct ubi_ainf_peb *aeb;
+       unsigned long long max_sqnum = 0;
+
+       list_for_each_entry(aeb, &ai->fastmap, u.list) {
+               if (aeb->vol_id == UBI_FM_SB_VOLUME_ID && aeb->sqnum > max_sqnum) {
+                       max_sqnum = aeb->sqnum;
+                       ret = aeb->pnum;
+               }
+       }
+
+       return ret;
+}
+
 /**
  * ubi_scan_fastmap - scan the fastmap.
  * @ubi: UBI device object
  * @ai: UBI attach info to be filled
- * @fm_anchor: The fastmap starts at this PEB
+ * @scan_ai: UBI attach info from the first 64 PEBs,
+ *           used to find the most recent Fastmap data structure
  *
  * Returns 0 on success, UBI_NO_FASTMAP if no fastmap was found,
  * UBI_BAD_FASTMAP if one was found but is not usable.
  * < 0 indicates an internal error.
  */
 int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
-                    int fm_anchor)
+                    struct ubi_attach_info *scan_ai)
 {
        struct ubi_fm_sb *fmsb, *fmsb2;
        struct ubi_vid_hdr *vh;
        struct ubi_ec_hdr *ech;
        struct ubi_fastmap_layout *fm;
-       int i, used_blocks, pnum, ret = 0;
+       struct ubi_ainf_peb *tmp_aeb, *aeb;
+       int i, used_blocks, pnum, fm_anchor, ret = 0;
        size_t fm_size;
        __be32 crc, tmp_crc;
        unsigned long long sqnum = 0;
 
+       fm_anchor = find_fm_anchor(scan_ai);
+       if (fm_anchor < 0)
+               return UBI_NO_FASTMAP;
+
+       /* Move all (possible) fastmap blocks into our new attach structure. */
+       list_for_each_entry_safe(aeb, tmp_aeb, &scan_ai->fastmap, u.list)
+               list_move_tail(&aeb->u.list, &ai->fastmap);
+
        down_write(&ubi->fm_protect);
        memset(ubi->fm_buf, 0, ubi->fm_size);
 
@@ -945,6 +977,13 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
                        goto free_hdr;
                }
 
+               if (i == 0 && pnum != fm_anchor) {
+                       ubi_err(ubi, "Fastmap anchor PEB mismatch: PEB: %i vs. %i",
+                               pnum, fm_anchor);
+                       ret = UBI_BAD_FASTMAP;
+                       goto free_hdr;
+               }
+
                ret = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
                if (ret && ret != UBI_IO_BITFLIPS) {
                        ubi_err(ubi, "unable to read fastmap block# %i EC (PEB: %i)",
@@ -1102,7 +1141,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
        struct rb_node *tmp_rb;
        int ret, i, j, free_peb_count, used_peb_count, vol_count;
        int scrub_peb_count, erase_peb_count;
-       int *seen_pebs = NULL;
+       unsigned long *seen_pebs = NULL;
 
        fm_raw = ubi->fm_buf;
        memset(ubi->fm_buf, 0, ubi->fm_size);
index cb7c075f2144969d5f416d440060455ee2904933..1cb287ec32adbb486c3289c23a89191e7be48221 100644 (file)
@@ -99,9 +99,6 @@ static int gluebi_get_device(struct mtd_info *mtd)
        struct gluebi_device *gluebi;
        int ubi_mode = UBI_READONLY;
 
-       if (!try_module_get(THIS_MODULE))
-               return -ENODEV;
-
        if (mtd->flags & MTD_WRITEABLE)
                ubi_mode = UBI_READWRITE;
 
@@ -129,7 +126,6 @@ static int gluebi_get_device(struct mtd_info *mtd)
                                       ubi_mode);
        if (IS_ERR(gluebi->desc)) {
                mutex_unlock(&devices_mutex);
-               module_put(THIS_MODULE);
                return PTR_ERR(gluebi->desc);
        }
        gluebi->refcnt += 1;
@@ -153,7 +149,6 @@ static void gluebi_put_device(struct mtd_info *mtd)
        gluebi->refcnt -= 1;
        if (gluebi->refcnt == 0)
                ubi_close_volume(gluebi->desc);
-       module_put(THIS_MODULE);
        mutex_unlock(&devices_mutex);
 }
 
index 10cf3b549959ce46f9c517b77fbcdd84e274a3d2..ff8cafe1e5cd1f1489ef41745f21f6c1110b61c5 100644 (file)
@@ -1019,7 +1019,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 
        p = (char *)vid_hdr - ubi->vid_hdr_shift;
        read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
-                         ubi->vid_hdr_alsize);
+                         ubi->vid_hdr_shift + UBI_VID_HDR_SIZE);
        if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
                return read_err;
 
index 61d4e99755a4bef64aa7821727444911d2816d77..b616a115c9d38b9e8f2d5b3209629f1e98ab0501 100644 (file)
@@ -703,6 +703,8 @@ struct ubi_ainf_volume {
  * @erase: list of physical eraseblocks which have to be erased
  * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
  *         those belonging to "preserve"-compatible internal volumes)
+ * @fastmap: list of physical eraseblocks which relate to fastmap (e.g.,
+ *           eraseblocks of the current and not yet erased old fastmap blocks)
  * @corr_peb_count: count of PEBs in the @corr list
  * @empty_peb_count: count of PEBs which are presumably empty (contain only
  *                   0xFF bytes)
@@ -713,6 +715,8 @@ struct ubi_ainf_volume {
  * @vols_found: number of volumes found
  * @highest_vol_id: highest volume ID
  * @is_empty: flag indicating whether the MTD device is empty or not
+ * @force_full_scan: flag indicating whether we need to do a full scan and drop
+                    all existing Fastmap data structures
  * @min_ec: lowest erase counter value
  * @max_ec: highest erase counter value
  * @max_sqnum: highest sequence number value
@@ -731,6 +735,7 @@ struct ubi_attach_info {
        struct list_head free;
        struct list_head erase;
        struct list_head alien;
+       struct list_head fastmap;
        int corr_peb_count;
        int empty_peb_count;
        int alien_peb_count;
@@ -739,6 +744,7 @@ struct ubi_attach_info {
        int vols_found;
        int highest_vol_id;
        int is_empty;
+       int force_full_scan;
        int min_ec;
        int max_ec;
        unsigned long long max_sqnum;
@@ -911,7 +917,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
 size_t ubi_calc_fm_size(struct ubi_device *ubi);
 int ubi_update_fastmap(struct ubi_device *ubi);
 int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
-                    int fm_anchor);
+                    struct ubi_attach_info *scan_ai);
 #else
 static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; }
 #endif
@@ -1105,4 +1111,42 @@ static inline int idx2vol_id(const struct ubi_device *ubi, int idx)
                return idx;
 }
 
+/**
+ * ubi_is_fm_vol - check whether a volume ID is a Fastmap volume.
+ * @vol_id: volume ID
+ */
+static inline bool ubi_is_fm_vol(int vol_id)
+{
+       switch (vol_id) {
+               case UBI_FM_SB_VOLUME_ID:
+               case UBI_FM_DATA_VOLUME_ID:
+               return true;
+       }
+
+       return false;
+}
+
+/**
+ * ubi_find_fm_block - check whether a PEB is part of the current Fastmap.
+ * @ubi: UBI device description object
+ * @pnum: physical eraseblock to look for
+ *
+ * This function returns a wear leveling object if @pnum relates to the current
+ * fastmap, @NULL otherwise.
+ */
+static inline struct ubi_wl_entry *ubi_find_fm_block(const struct ubi_device *ubi,
+                                                    int pnum)
+{
+       int i;
+
+       if (ubi->fm) {
+               for (i = 0; i < ubi->fm->used_blocks; i++) {
+                       if (ubi->fm->e[i]->pnum == pnum)
+                               return ubi->fm->e[i];
+               }
+       }
+
+       return NULL;
+}
+
 #endif /* !__UBI_UBI_H__ */
index 10059dfdc1b6db3e570348bd03ad41f968329340..0138f526474a25d0fa14bc5f8d375e74235287af 100644 (file)
@@ -488,13 +488,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
                spin_unlock(&ubi->volumes_lock);
        }
 
-       /* Change volume table record */
-       vtbl_rec = ubi->vtbl[vol_id];
-       vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
-       err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
-       if (err)
-               goto out_acc;
-
        if (pebs < 0) {
                for (i = 0; i < -pebs; i++) {
                        err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i);
@@ -512,6 +505,24 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
                spin_unlock(&ubi->volumes_lock);
        }
 
+       /*
+        * When we shrink a volume we have to flush all pending (erase) work.
+        * Otherwise it can happen that upon next attach UBI finds a LEB with
+        * lnum > highest_lnum and refuses to attach.
+        */
+       if (pebs < 0) {
+               err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
+               if (err)
+                       goto out_acc;
+       }
+
+       /* Change volume table record */
+       vtbl_rec = ubi->vtbl[vol_id];
+       vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
+       err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
+       if (err)
+               goto out_acc;
+
        vol->reserved_pebs = reserved_pebs;
        if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
                vol->used_ebs = reserved_pebs;
index 959c7b12e0b1be4863960e43fa9dfbe67f2eb58a..f4533266d7b26cbac8ca44861d88277a5d0cbabc 100644 (file)
@@ -1598,19 +1598,44 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                }
        }
 
-       dbg_wl("found %i PEBs", found_pebs);
+       list_for_each_entry(aeb, &ai->fastmap, u.list) {
+               cond_resched();
+
+               e = ubi_find_fm_block(ubi, aeb->pnum);
 
-       if (ubi->fm) {
-               ubi_assert(ubi->good_peb_count ==
-                          found_pebs + ubi->fm->used_blocks);
+               if (e) {
+                       ubi_assert(!ubi->lookuptbl[e->pnum]);
+                       ubi->lookuptbl[e->pnum] = e;
+               } else {
+                       /*
+                        * Usually old Fastmap PEBs are scheduled for erasure
+                        * and we don't have to care about them but if we face
+                        * an power cut before scheduling them we need to
+                        * take care of them here.
+                        */
+                       if (ubi->lookuptbl[aeb->pnum])
+                               continue;
+
+                       e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
+                       if (!e)
+                               goto out_free;
 
-               for (i = 0; i < ubi->fm->used_blocks; i++) {
-                       e = ubi->fm->e[i];
+                       e->pnum = aeb->pnum;
+                       e->ec = aeb->ec;
+                       ubi_assert(!ubi->lookuptbl[e->pnum]);
                        ubi->lookuptbl[e->pnum] = e;
+                       if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
+                               wl_entry_destroy(ubi, e);
+                               goto out_free;
+                       }
                }
+
+               found_pebs++;
        }
-       else
-               ubi_assert(ubi->good_peb_count == found_pebs);
+
+       dbg_wl("found %i PEBs", found_pebs);
+
+       ubi_assert(ubi->good_peb_count == found_pebs);
 
        reserved_pebs = WL_RESERVED_PEBS;
        ubi_fastmap_init(ubi, &reserved_pebs);
index 9718da86ad01a804db1e3c7e2a2ca6923f6299a3..821b34816976a112df8d950555500ed9bbf64361 100644 (file)
@@ -100,10 +100,6 @@ static int switch_gc_head(struct ubifs_info *c)
        if (err)
                return err;
 
-       err = ubifs_wbuf_sync_nolock(wbuf);
-       if (err)
-               return err;
-
        err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0);
        if (err)
                return err;
index 70349954e78b3118f23c031773caf3c038f84552..4ec051089186ea2aef6bb4f96e22fefa24a10777 100644 (file)
@@ -520,19 +520,19 @@ static int init_constants_early(struct ubifs_info *c)
        c->max_write_shift = fls(c->max_write_size) - 1;
 
        if (c->leb_size < UBIFS_MIN_LEB_SZ) {
-               ubifs_err(c, "too small LEBs (%d bytes), min. is %d bytes",
-                         c->leb_size, UBIFS_MIN_LEB_SZ);
+               ubifs_errc(c, "too small LEBs (%d bytes), min. is %d bytes",
+                          c->leb_size, UBIFS_MIN_LEB_SZ);
                return -EINVAL;
        }
 
        if (c->leb_cnt < UBIFS_MIN_LEB_CNT) {
-               ubifs_err(c, "too few LEBs (%d), min. is %d",
-                         c->leb_cnt, UBIFS_MIN_LEB_CNT);
+               ubifs_errc(c, "too few LEBs (%d), min. is %d",
+                          c->leb_cnt, UBIFS_MIN_LEB_CNT);
                return -EINVAL;
        }
 
        if (!is_power_of_2(c->min_io_size)) {
-               ubifs_err(c, "bad min. I/O size %d", c->min_io_size);
+               ubifs_errc(c, "bad min. I/O size %d", c->min_io_size);
                return -EINVAL;
        }
 
@@ -543,8 +543,8 @@ static int init_constants_early(struct ubifs_info *c)
        if (c->max_write_size < c->min_io_size ||
            c->max_write_size % c->min_io_size ||
            !is_power_of_2(c->max_write_size)) {
-               ubifs_err(c, "bad write buffer size %d for %d min. I/O unit",
-                         c->max_write_size, c->min_io_size);
+               ubifs_errc(c, "bad write buffer size %d for %d min. I/O unit",
+                          c->max_write_size, c->min_io_size);
                return -EINVAL;
        }
 
@@ -2108,8 +2108,9 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
         */
        ubi = open_ubi(name, UBI_READONLY);
        if (IS_ERR(ubi)) {
-               pr_err("UBIFS error (pid: %d): cannot open \"%s\", error %d",
-                      current->pid, name, (int)PTR_ERR(ubi));
+               if (!(flags & MS_SILENT))
+                       pr_err("UBIFS error (pid: %d): cannot open \"%s\", error %d",
+                              current->pid, name, (int)PTR_ERR(ubi));
                return ERR_CAST(ubi);
        }
 
index ddf9f6b9eee24400d676917a2c899c784ac5b86f..4617d459022a5df4cfa2645bea329c31fa3b7a00 100644 (file)
@@ -1783,8 +1783,8 @@ void ubifs_err(const struct ubifs_info *c, const char *fmt, ...);
 __printf(2, 3)
 void ubifs_warn(const struct ubifs_info *c, const char *fmt, ...);
 /*
- * A variant of 'ubifs_err()' which takes the UBIFS file-sytem description
- * object as an argument.
+ * A conditional variant of 'ubifs_err()' which doesn't output anything
+ * if probing (ie. MS_SILENT set).
  */
 #define ubifs_errc(c, fmt, ...)                                                \
 do {                                                                   \
index b5fc27969e9d31bc0a9e951cc50a83c66d9c1352..e237811f09ce5ce6139aab0951047a74dd715665 100644 (file)
@@ -592,19 +592,19 @@ static int ubifs_xattr_set(const struct xattr_handler *handler,
                return __ubifs_removexattr(inode, name);
 }
 
-const struct xattr_handler ubifs_user_xattr_handler = {
+static const struct xattr_handler ubifs_user_xattr_handler = {
        .prefix = XATTR_USER_PREFIX,
        .get = ubifs_xattr_get,
        .set = ubifs_xattr_set,
 };
 
-const struct xattr_handler ubifs_trusted_xattr_handler = {
+static const struct xattr_handler ubifs_trusted_xattr_handler = {
        .prefix = XATTR_TRUSTED_PREFIX,
        .get = ubifs_xattr_get,
        .set = ubifs_xattr_set,
 };
 
-const struct xattr_handler ubifs_security_xattr_handler = {
+static const struct xattr_handler ubifs_security_xattr_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .get = ubifs_xattr_get,
        .set = ubifs_xattr_set,
This page took 0.079435 seconds and 5 git commands to generate.