}
 
        ubi = ubi_devices[ubi_devices_cnt] = kzalloc(sizeof(struct ubi_device),
-                                                     GFP_KERNEL);
+                                                    GFP_KERNEL);
        if (!ubi) {
                err = -ENOMEM;
                goto out_mtd;
        if (err)
                goto out_free;
 
+       mutex_init(&ubi->buf_mutex);
+       ubi->peb_buf1 = vmalloc(ubi->peb_size);
+       if (!ubi->peb_buf1)
+               goto out_free;
+
+       ubi->peb_buf2 = vmalloc(ubi->peb_size);
+       if (!ubi->peb_buf2)
+                goto out_free;
+
+#ifdef CONFIG_MTD_UBI_DEBUG
+       mutex_init(&ubi->dbg_buf_mutex);
+       ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
+       if (!ubi->dbg_peb_buf)
+                goto out_free;
+#endif
+
        err = attach_by_scanning(ubi);
        if (err) {
                dbg_err("failed to attach by scanning, error %d", err);
        ubi_wl_close(ubi);
        vfree(ubi->vtbl);
 out_free:
+       vfree(ubi->peb_buf1);
+       vfree(ubi->peb_buf2);
+#ifdef CONFIG_MTD_UBI_DEBUG
+       vfree(ubi->dbg_peb_buf);
+#endif
        kfree(ubi);
 out_mtd:
        put_mtd_device(mtd);
        ubi_wl_close(ubi);
        vfree(ubi->vtbl);
        put_mtd_device(ubi->mtd);
+       vfree(ubi->peb_buf1);
+       vfree(ubi->peb_buf2);
+#ifdef CONFIG_MTD_UBI_DEBUG
+       vfree(ubi->dbg_peb_buf);
+#endif
        kfree(ubi_devices[ubi_num]);
        ubi_devices[ubi_num] = NULL;
        ubi_devices_cnt -= 1;
 
        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;
-       unsigned char *new_buf;
 
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
        if (!vid_hdr) {
                return -ENOMEM;
        }
 
+       mutex_lock(&ubi->buf_mutex);
+
 retry:
        new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
        if (new_pnum < 0) {
+               mutex_unlock(&ubi->buf_mutex);
                ubi_free_vid_hdr(ubi, vid_hdr);
                return new_pnum;
        }
                goto write_error;
 
        data_size = offset + len;
-       new_buf = vmalloc(data_size);
-       if (!new_buf) {
-               err = -ENOMEM;
-               goto out_put;
-       }
-       memset(new_buf + offset, 0xFF, len);
+       memset(ubi->peb_buf1 + offset, 0xFF, len);
 
        /* Read everything before the area where the write failure happened */
        if (offset > 0) {
-               err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset);
-               if (err && err != UBI_IO_BITFLIPS) {
-                       vfree(new_buf);
+               err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
+               if (err && err != UBI_IO_BITFLIPS)
                        goto out_put;
-               }
        }
 
-       memcpy(new_buf + offset, buf, len);
+       memcpy(ubi->peb_buf1 + offset, buf, len);
 
-       err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size);
-       if (err) {
-               vfree(new_buf);
+       err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
+       if (err)
                goto write_error;
-       }
 
-       vfree(new_buf);
+       mutex_unlock(&ubi->buf_mutex);
        ubi_free_vid_hdr(ubi, vid_hdr);
 
        vol->eba_tbl[lnum] = new_pnum;
        return 0;
 
 out_put:
+       mutex_unlock(&ubi->buf_mutex);
        ubi_wl_put_peb(ubi, new_pnum, 1);
        ubi_free_vid_hdr(ubi, vid_hdr);
        return err;
        ubi_warn("failed to write to PEB %d", new_pnum);
        ubi_wl_put_peb(ubi, new_pnum, 1);
        if (++tries > UBI_IO_RETRIES) {
+               mutex_unlock(&ubi->buf_mutex);
                ubi_free_vid_hdr(ubi, vid_hdr);
                return err;
        }
        int err, vol_id, lnum, data_size, aldata_size, pnum, idx;
        struct ubi_volume *vol;
        uint32_t crc;
-       void *buf, *buf1 = NULL;
 
        vol_id = be32_to_cpu(vid_hdr->vol_id);
        lnum = be32_to_cpu(vid_hdr->lnum);
                data_size = aldata_size =
                            ubi->leb_size - be32_to_cpu(vid_hdr->data_pad);
 
-       buf = vmalloc(aldata_size);
-       if (!buf)
-               return -ENOMEM;
-
        /*
         * We do not want anybody to write to this logical eraseblock while we
         * are moving it, so we lock it.
         */
        err = leb_write_lock(ubi, vol_id, lnum);
-       if (err) {
-               vfree(buf);
+       if (err)
                return err;
-       }
+
+       mutex_lock(&ubi->buf_mutex);
 
        /*
         * But the logical eraseblock might have been put by this time.
        /* OK, now the LEB is locked and we can safely start moving it */
 
        dbg_eba("read %d bytes of data", aldata_size);
-       err = ubi_io_read_data(ubi, buf, from, 0, aldata_size);
+       err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size);
        if (err && err != UBI_IO_BITFLIPS) {
                ubi_warn("error %d while reading data from PEB %d",
                         err, from);
         */
        if (vid_hdr->vol_type == UBI_VID_DYNAMIC)
                aldata_size = data_size =
-                               ubi_calc_data_len(ubi, buf, data_size);
+                       ubi_calc_data_len(ubi, ubi->peb_buf1, data_size);
 
        cond_resched();
-       crc = crc32(UBI_CRC32_INIT, buf, data_size);
+       crc = crc32(UBI_CRC32_INIT, ubi->peb_buf1, data_size);
        cond_resched();
 
        /*
        }
 
        if (data_size > 0) {
-               err = ubi_io_write_data(ubi, buf, to, 0, aldata_size);
+               err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
                if (err)
                        goto out_unlock;
 
+               cond_resched();
+
                /*
                 * We've written the data and are going to read it back to make
                 * sure it was written correctly.
                 */
-               buf1 = vmalloc(aldata_size);
-               if (!buf1) {
-                       err = -ENOMEM;
-                       goto out_unlock;
-               }
 
-               cond_resched();
-
-               err = ubi_io_read_data(ubi, buf1, to, 0, aldata_size);
+               err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
                if (err) {
                        if (err != UBI_IO_BITFLIPS)
                                ubi_warn("cannot read data back from PEB %d",
 
                cond_resched();
 
-               if (memcmp(buf, buf1, aldata_size)) {
+               if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
                        ubi_warn("read data back from PEB %d - it is different",
                                 to);
                        goto out_unlock;
        ubi_assert(vol->eba_tbl[lnum] == from);
        vol->eba_tbl[lnum] = to;
 
-       leb_write_unlock(ubi, vol_id, lnum);
-       vfree(buf);
-       vfree(buf1);
-
-       return 0;
-
 out_unlock:
+       mutex_unlock(&ubi->buf_mutex);
        leb_write_unlock(ubi, vol_id, lnum);
-       vfree(buf);
-       vfree(buf1);
        return err;
 }
 
 
 static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
                                  const struct ubi_vid_hdr *vid_hdr);
-static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
-                                int offset, int len);
+static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
+                                int len);
 #else
 #define paranoid_check_not_bad(ubi, pnum) 0
 #define paranoid_check_peb_ec_hdr(ubi, pnum)  0
  * Note, in case of an error, it is possible that something was still written
  * to the flash media, but may be some garbage.
  */
-int ubi_io_write(const struct ubi_device *ubi, const void *buf, int pnum,
-                int offset, int len)
+int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
+                int len)
 {
        int err;
        size_t written;
  * zero in case of success and a negative error code in case of failure. If
  * %-EIO is returned, the physical eraseblock most probably went bad.
  */
-static int do_sync_erase(const struct ubi_device *ubi, int pnum)
+static int do_sync_erase(struct ubi_device *ubi, int pnum)
 {
        int err, retries = 0;
        struct erase_info ei;
  * test, a positive number of erase operations done if the test was
  * successfully passed, and other negative error codes in case of other errors.
  */
-static int torture_peb(const struct ubi_device *ubi, int pnum)
+static int torture_peb(struct ubi_device *ubi, int pnum)
 {
-       void *buf;
        int err, i, patt_count;
 
-       buf = vmalloc(ubi->peb_size);
-       if (!buf)
-               return -ENOMEM;
-
        patt_count = ARRAY_SIZE(patterns);
        ubi_assert(patt_count > 0);
 
+       mutex_lock(&ubi->buf_mutex);
        for (i = 0; i < patt_count; i++) {
                err = do_sync_erase(ubi, pnum);
                if (err)
                        goto out;
 
                /* Make sure the PEB contains only 0xFF bytes */
-               err = ubi_io_read(ubi, buf, pnum, 0, ubi->peb_size);
+               err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
                if (err)
                        goto out;
 
-               err = check_pattern(buf, 0xFF, ubi->peb_size);
+               err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
                if (err == 0) {
                        ubi_err("erased PEB %d, but a non-0xFF byte found",
                                pnum);
                }
 
                /* Write a pattern and check it */
-               memset(buf, patterns[i], ubi->peb_size);
-               err = ubi_io_write(ubi, buf, pnum, 0, ubi->peb_size);
+               memset(ubi->peb_buf1, patterns[i], ubi->peb_size);
+               err = ubi_io_write(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
                if (err)
                        goto out;
 
-               memset(buf, ~patterns[i], ubi->peb_size);
-               err = ubi_io_read(ubi, buf, pnum, 0, ubi->peb_size);
+               memset(ubi->peb_buf1, ~patterns[i], ubi->peb_size);
+               err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
                if (err)
                        goto out;
 
-               err = check_pattern(buf, patterns[i], ubi->peb_size);
+               err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size);
                if (err == 0) {
                        ubi_err("pattern %x checking failed for PEB %d",
                                patterns[i], pnum);
        err = patt_count;
 
 out:
+       mutex_unlock(&ubi->buf_mutex);
        if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
                /*
                 * If a bit-flip or data integrity error was detected, the test
                        pnum);
                err = -EIO;
        }
-       vfree(buf);
        return err;
 }
 
  * codes in case of other errors. Note, %-EIO means that the physical
  * eraseblock is bad.
  */
-int ubi_io_sync_erase(const struct ubi_device *ubi, int pnum, int torture)
+int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
 {
        int err, ret = 0;
 
  * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
  * o a negative error code in case of failure.
  */
-int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                       struct ubi_ec_hdr *ec_hdr, int verbose)
 {
        int err, read_err = 0;
  * case of failure. If %-EIO is returned, the physical eraseblock most probably
  * went bad.
  */
-int ubi_io_write_ec_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
                        struct ubi_ec_hdr *ec_hdr)
 {
        int err;
  *   header there);
  * o a negative error code in case of failure.
  */
-int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                        struct ubi_vid_hdr *vid_hdr, int verbose)
 {
        int err, read_err = 0;
  * case of failure. If %-EIO is returned, the physical eraseblock probably went
  * bad.
  */
-int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
                         struct ubi_vid_hdr *vid_hdr)
 {
        int err;
  * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
  * code if an error occurred.
  */
-static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
-                                int offset, int len)
+static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
+                                int len)
 {
        size_t read;
        int err;
-       void *buf;
        loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
 
-       buf = vmalloc(len);
-       if (!buf)
-               return -ENOMEM;
-       memset(buf, 0, len);
-
-       err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
+       mutex_lock(&ubi->dbg_buf_mutex);
+       err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf);
        if (err && err != -EUCLEAN) {
                ubi_err("error %d while reading %d bytes from PEB %d:%d, "
                        "read %zd bytes", err, len, pnum, offset, read);
                goto error;
        }
 
-       err = check_pattern(buf, 0xFF, len);
+       err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
        if (err == 0) {
                ubi_err("flash region at PEB %d:%d, length %d does not "
                        "contain all 0xFF bytes", pnum, offset, len);
                goto fail;
        }
+       mutex_unlock(&ubi->dbg_buf_mutex);
 
-       vfree(buf);
        return 0;
 
 fail:
        ubi_err("paranoid check failed for PEB %d", pnum);
        dbg_msg("hex dump of the %d-%d region", offset, offset + len);
-       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
+       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4,
+                      ubi->dbg_peb_buf, len, 1);
        err = 1;
 error:
        ubi_dbg_dump_stack();
-       vfree(buf);
+       mutex_unlock(&ubi->dbg_buf_mutex);
        return err;
 }
 
 
 #include "ubi.h"
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-static int paranoid_check_si(const struct ubi_device *ubi,
-                            struct ubi_scan_info *si);
+static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
 #else
 #define paranoid_check_si(ubi, si) 0
 #endif
  *     o bit 2 is cleared: the older LEB is not corrupted;
  *     o bit 2 is set: the older LEB is corrupted.
  */
-static int compare_lebs(const struct ubi_device *ubi,
-                       const struct ubi_scan_leb *seb, int pnum,
-                       const struct ubi_vid_hdr *vid_hdr)
+static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
+                       int pnum, const struct ubi_vid_hdr *vid_hdr)
 {
        void *buf;
        int len, err, second_is_newer, bitflips = 0, corrupted = 0;
  * to be picked, while the older one has to be dropped. This function returns
  * zero in case of success and a negative error code in case of failure.
  */
-int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
+int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                      int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
                      int bitflips)
 {
  * function returns zero in case of success and a negative error code in case
  * of failure.
  */
-int ubi_scan_erase_peb(const struct ubi_device *ubi,
-                      const struct ubi_scan_info *si, int pnum, int ec)
+int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
+                      int pnum, int ec)
 {
        int err;
        struct ubi_ec_hdr *ec_hdr;
  * This function returns scanning physical eraseblock information in case of
  * success and an error code in case of failure.
  */
-struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
+struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
                                           struct ubi_scan_info *si)
 {
        int err = 0, i;
  * This function returns zero if the scanning information is all right, %1 if
  * not and a negative error code if an error occurred.
  */
-static int paranoid_check_si(const struct ubi_device *ubi,
-                            struct ubi_scan_info *si)
+static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
 {
        int pnum, err, vols_found = 0;
        struct rb_node *rb1, *rb2;
 
                list_add_tail(&seb->u.list, list);
 }
 
-int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
+int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                      int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
                      int bitflips);
 struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
 struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
                                       int lnum);
 void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv);
-struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
+struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
                                           struct ubi_scan_info *si);
-int ubi_scan_erase_peb(const struct ubi_device *ubi,
-                      const struct ubi_scan_info *si, int pnum, int ec);
+int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
+                      int pnum, int ec);
 struct ubi_scan_info *ubi_scan(struct ubi_device *ubi);
 void ubi_scan_destroy_si(struct ubi_scan_info *si);
 
 
  * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
  * not
  * @mtd: MTD device descriptor
+ *
+ * @peb_buf1: a buffer of PEB size used for different purposes
+ * @peb_buf2: another buffer of PEB size used for different purposes
+ * @buf_mutex: proptects @peb_buf1 and @peb_buf2
+ * @dbg_peb_buf:  buffer of PEB size used for debugging
+ * @dbg_buf_mutex: proptects @dbg_peb_buf
  */
 struct ubi_device {
        struct cdev cdev;
        int vid_hdr_shift;
        int bad_allowed;
        struct mtd_info *mtd;
+
+       void *peb_buf1;
+       void *peb_buf2;
+       struct mutex buf_mutex;
+#ifdef CONFIG_MTD_UBI_DEBUG
+       void *dbg_peb_buf;
+       struct mutex dbg_buf_mutex;
+#endif
 };
 
 extern struct file_operations ubi_cdev_operations;
 /* io.c */
 int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
                int len);
-int ubi_io_write(const struct ubi_device *ubi, const void *buf, int pnum,
-                int offset, int len);
-int ubi_io_sync_erase(const struct ubi_device *ubi, int pnum, int torture);
+int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
+                int len);
+int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture);
 int ubi_io_is_bad(const struct ubi_device *ubi, int pnum);
 int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum);
-int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                       struct ubi_ec_hdr *ec_hdr, int verbose);
-int ubi_io_write_ec_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
                        struct ubi_ec_hdr *ec_hdr);
-int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                        struct ubi_vid_hdr *vid_hdr, int verbose);
-int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum,
+int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
                         struct ubi_vid_hdr *vid_hdr);
 
 /*
  * the beginning of the logical eraseblock, not to the beginning of the
  * physical eraseblock.
  */
-static inline int ubi_io_write_data(const struct ubi_device *ubi, const void *buf,
+static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
                                    int pnum, int offset, int len)
 {
        ubi_assert(offset >= 0);
 
  * This function returns zero in case of success and a negative error code in
  * case of failure.
  */
-static int create_vtbl(const struct ubi_device *ubi, struct ubi_scan_info *si,
+static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
                       int copy, void *vtbl)
 {
        int err, tries = 0;
  * not corrupted, and recovering from corruptions if needed. Returns volume
  * table in case of success and a negative error code in case of failure.
  */
-static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
+static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
                                            struct ubi_scan_info *si,
                                            struct ubi_scan_volume *sv)
 {
  * This function returns volume table contents in case of success and a
  * negative error code in case of failure.
  */
-static struct ubi_vtbl_record *create_empty_lvol(const struct ubi_device *ubi,
+static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
                                                 struct ubi_scan_info *si)
 {
        int i;
 
 };
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec);
+static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
                                     struct rb_root *root);
 #else
  * is equivalent to @ec, %1 if not, and a negative error code if an error
  * occurred.
  */
-static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec)
+static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
 {
        int err;
        long long read_ec;