Merge branch 'stable-3.2' into pandora-3.2
authorGrazvydas Ignotas <notasas@gmail.com>
Wed, 6 Feb 2013 15:55:31 +0000 (17:55 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Wed, 6 Feb 2013 15:55:31 +0000 (17:55 +0200)
Conflicts:
drivers/mtd/ubi/attach.c

16 files changed:
1  2 
arch/arm/Kconfig
arch/arm/kernel/head.S
arch/arm/mm/dma-mapping.c
drivers/mmc/host/omap_hsmmc.c
drivers/mtd/nand/omap2.c
drivers/mtd/ubi/attach.c
drivers/mtd/ubi/build.c
drivers/usb/musb/musb_core.c
fs/exec.c
fs/ubifs/lprops.c
fs/ubifs/ubifs.h
kernel/exit.c
kernel/sched.c
mm/memory.c
mm/shmem.c
mm/truncate.c

diff --combined arch/arm/Kconfig
@@@ -542,6 -542,7 +542,7 @@@ config ARCH_KIRKWOO
        bool "Marvell Kirkwood"
        select CPU_FEROCEON
        select PCI
+       select PCI_QUIRKS
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select PLAT_ORION
@@@ -979,35 -980,6 +980,35 @@@ config ARCH_ZYN
          Support for Xilinx Zynq ARM Cortex A9 Platform
  endchoice
  
 +config SYS_SUPPORTS_HUGETLBFS
 +              def_bool n
 +
 +config ARM_HUGETLB_SUPPORT
 +      bool "Support HUGETLB for ARMv7 (EXPERIMENTAL)"
 +      depends on CPU_V7 && EXPERIMENTAL
 +      select SYS_SUPPORTS_HUGETLBFS
 +      select HUGETLBFS
 +      default y
 +
 +choice
 +      prompt "Huge Page Size"
 +      depends on ARM_HUGETLB_SUPPORT
 +      default HUGEPAGE_SIZE_2MB
 +
 +config HUGEPAGE_SIZE_2MB
 +      bool "2MB"
 +      depends on ARM_HUGETLB_SUPPORT
 +      help
 +       This option select huge page size in 2MB units
 +
 +config HUGEPAGE_SIZE_16MB
 +      bool "16MB"
 +      depends on ARM_HUGETLB_SUPPORT
 +      help
 +        This option select huge page size in 16MB units
 +
 +endchoice
 +
  #
  # This is sorted alphabetically by mach-* pathname.  However, plat-*
  # Kconfigs may be included either alphabetically (according to the
@@@ -1804,7 -1776,7 +1805,7 @@@ config LEDS_CP
          will overrule the CPU usage LED.
  
  config ALIGNMENT_TRAP
 -      bool
 +      bool "Enable alignment trap"
        depends on CPU_CP15_MMU
        default y if !ARCH_EBSA110
        select HAVE_PROC_CPU if PROC_FS
@@@ -1866,11 -1838,6 +1867,11 @@@ config DEPRECATED_PARAM_STRUC
          This was deprecated in 2001 and announced to live on for 5 years.
          Some old boot loaders still use this way.
  
 +config CPU_V7_SYSFS
 +      bool
 +      depends on CPU_V7 && SYSFS
 +      default y
 +
  endmenu
  
  menu "Boot options"
diff --combined arch/arm/kernel/head.S
@@@ -221,6 -221,7 +221,7 @@@ __create_page_tables
        /*
         * Then map boot params address in r2 or
         * the first 1MB of ram if boot params address is not specified.
+        * We map 2 sections in case the ATAGs/DTB crosses a section boundary.
         */
        mov     r0, r2, lsr #SECTION_SHIFT
        movs    r0, r0, lsl #SECTION_SHIFT
        add     r3, r3, #PAGE_OFFSET
        add     r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
        orr     r6, r7, r0
+       str     r6, [r3], #1 << PMD_ORDER
+       add     r6, r6, #1 << SECTION_SHIFT
        str     r6, [r3]
  
  #ifdef CONFIG_DEBUG_LL
@@@ -373,10 -376,6 +376,10 @@@ __enable_mmu
  #endif
  #ifdef CONFIG_CPU_ICACHE_DISABLE
        bic     r0, r0, #CR_I
 +#endif
 +#ifdef CONFIG_USER_L2_PLE
 +      mov     r5, #3
 +      mcr     p15, 0, r5, c11, c1, 0
  #endif
        mov     r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
                      domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
@@@ -152,6 -152,9 +152,6 @@@ static struct arm_vmregion_head consist
        .vm_end         = CONSISTENT_END,
  };
  
 -#ifdef CONFIG_HUGETLB_PAGE
 -#error ARM Coherent DMA allocator does not (yet) support huge TLB
 -#endif
  
  /*
   * Initialise the consistent memory allocation.
@@@ -497,25 -500,27 +497,27 @@@ static void dma_cache_maint_page(struc
        size_t size, enum dma_data_direction dir,
        void (*op)(const void *, size_t, int))
  {
+       unsigned long pfn;
+       size_t left = size;
+       pfn = page_to_pfn(page) + offset / PAGE_SIZE;
+       offset %= PAGE_SIZE;
        /*
         * A single sg entry may refer to multiple physically contiguous
         * pages.  But we still need to process highmem pages individually.
         * If highmem is not configured then the bulk of this loop gets
         * optimized out.
         */
-       size_t left = size;
        do {
                size_t len = left;
                void *vaddr;
  
+               page = pfn_to_page(pfn);
                if (PageHighMem(page)) {
-                       if (len + offset > PAGE_SIZE) {
-                               if (offset >= PAGE_SIZE) {
-                                       page += offset / PAGE_SIZE;
-                                       offset %= PAGE_SIZE;
-                               }
+                       if (len + offset > PAGE_SIZE)
                                len = PAGE_SIZE - offset;
-                       }
                        vaddr = kmap_high_get(page);
                        if (vaddr) {
                                vaddr += offset;
                        op(vaddr, len, dir);
                }
                offset = 0;
-               page++;
+               pfn++;
                left -= len;
        } while (left);
  }
@@@ -24,6 -24,7 +24,6 @@@
  #include <linux/delay.h>
  #include <linux/dma-mapping.h>
  #include <linux/platform_device.h>
 -#include <linux/workqueue.h>
  #include <linux/timer.h>
  #include <linux/clk.h>
  #include <linux/mmc/host.h>
@@@ -162,6 -163,7 +162,6 @@@ struct omap_hsmmc_host 
         */
        struct  regulator       *vcc;
        struct  regulator       *vcc_aux;
 -      struct  work_struct     mmc_carddetect_work;
        void    __iomem         *base;
        resource_size_t         mapbase;
        spinlock_t              irq_lock; /* Prevent races with irq handler */
@@@ -852,55 -854,6 +852,55 @@@ omap_hsmmc_show_slot_name(struct devic
  
  static DEVICE_ATTR(slot_name, S_IRUGO, omap_hsmmc_show_slot_name, NULL);
  
 +/* for hosts with 35xx erratum 2.1.1.128 */
 +static ssize_t
 +omap_hsmmc_show_unsafe_read(struct device *dev, struct device_attribute *attr,
 +                      char *buf)
 +{
 +      struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
 +      int val = 0;
 +
 +      if (!(mmc->caps2 & MMC_CAP2_NO_MULTI_READ)) {
 +              val = 1;
 +              if (mmc->f_max == OMAP_MMC_MAX_CLOCK)
 +                      val = 2;
 +      }
 +
 +      return sprintf(buf, "%d\n", val);
 +}
 +
 +static ssize_t
 +omap_hsmmc_set_unsafe_read(struct device *dev, struct device_attribute *attr,
 +              const char *buf, size_t count)
 +{
 +      struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
 +      unsigned long val;
 +      int ret;
 +
 +      ret = strict_strtoul(buf, 0, &val);
 +      if (ret)
 +              return -EINVAL;
 +
 +      switch (val) {
 +      case 0:
 +              mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
 +              mmc->f_max = OMAP_MMC_MAX_CLOCK;
 +              break;
 +      case 1:
 +              mmc->caps2 &= ~MMC_CAP2_NO_MULTI_READ;
 +              mmc->f_max = 32000000;
 +              break;
 +      case 2:
 +              mmc->caps2 &= ~MMC_CAP2_NO_MULTI_READ;
 +              mmc->f_max = OMAP_MMC_MAX_CLOCK;
 +              break;
 +      }
 +
 +      return count;
 +}
 +static DEVICE_ATTR(unsafe_read, S_IWUSR | S_IRUGO,
 +      omap_hsmmc_show_unsafe_read, omap_hsmmc_set_unsafe_read);
 +
  /*
   * Configure the response type and send the cmd.
   */
@@@ -1327,16 -1280,17 +1327,16 @@@ static void omap_hsmmc_protect_card(str
  }
  
  /*
 - * Work Item to notify the core about card insertion/removal
 + * irq handler to notify the core about card insertion/removal
   */
 -static void omap_hsmmc_detect(struct work_struct *work)
 +static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id)
  {
 -      struct omap_hsmmc_host *host =
 -              container_of(work, struct omap_hsmmc_host, mmc_carddetect_work);
 +      struct omap_hsmmc_host *host = dev_id;
        struct omap_mmc_slot_data *slot = &mmc_slot(host);
        int carddetect;
  
        if (host->suspended)
 -              return;
 +              return IRQ_HANDLED;
  
        sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
  
                mmc_detect_change(host->mmc, (HZ * 200) / 1000);
        else
                mmc_detect_change(host->mmc, (HZ * 50) / 1000);
 -}
 -
 -/*
 - * ISR for handling card insertion and removal
 - */
 -static irqreturn_t omap_hsmmc_cd_handler(int irq, void *dev_id)
 -{
 -      struct omap_hsmmc_host *host = (struct omap_hsmmc_host *)dev_id;
 -
 -      if (host->suspended)
 -              return IRQ_HANDLED;
 -      schedule_work(&host->mmc_carddetect_work);
 -
        return IRQ_HANDLED;
  }
  
@@@ -1531,8 -1498,11 +1531,8 @@@ static int omap_hsmmc_start_dma_transfe
        return 0;
  }
  
 -static void set_data_timeout(struct omap_hsmmc_host *host,
 -                           unsigned int timeout_ns,
 -                           unsigned int timeout_clks)
 +static void set_data_timeout(struct omap_hsmmc_host *host)
  {
 -      unsigned int timeout, cycle_ns;
        uint32_t reg, clkd, dto = 0;
  
        reg = OMAP_HSMMC_READ(host->base, SYSCTL);
        if (clkd == 0)
                clkd = 1;
  
 -      cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
 -      timeout = timeout_ns / cycle_ns;
 -      timeout += timeout_clks;
 -      if (timeout) {
 -              while ((timeout & 0x80000000) == 0) {
 -                      dto += 1;
 -                      timeout <<= 1;
 -              }
 -              dto = 31 - dto;
 -              timeout <<= 1;
 -              if (timeout && dto)
 -                      dto += 1;
 -              if (dto >= 13)
 -                      dto -= 13;
 -              else
 -                      dto = 0;
 -              if (dto > 14)
 -                      dto = 14;
 -      }
 +    /* Use the maximum timeout value allowed in the standard of 14 or 0xE */
 +      dto = 14;
  
        reg &= ~DTO_MASK;
        reg |= dto << DTO_SHIFT;
@@@ -1564,13 -1551,13 +1564,13 @@@ omap_hsmmc_prepare_data(struct omap_hsm
                 * busy signal.
                 */
                if (req->cmd->flags & MMC_RSP_BUSY)
 -                      set_data_timeout(host, 100000000U, 0);
 +                      set_data_timeout(host);
                return 0;
        }
  
        OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
                                        | (req->data->blocks << 16));
 -      set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks);
 +      set_data_timeout(host);
  
        if (host->use_dma) {
                ret = omap_hsmmc_start_dma_transfer(host, req);
@@@ -1932,6 -1919,7 +1932,6 @@@ static int __init omap_hsmmc_probe(stru
        host->next_data.cookie = 1;
  
        platform_set_drvdata(pdev, host);
 -      INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect);
  
        mmc->ops        = &omap_hsmmc_ops;
  
        omap_hsmmc_context_save(host);
  
        mmc->caps |= MMC_CAP_DISABLE;
 +
        if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
                dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
                mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
  
        /* Request IRQ for card detect */
        if ((mmc_slot(host).card_detect_irq)) {
 -              ret = request_irq(mmc_slot(host).card_detect_irq,
 -                                omap_hsmmc_cd_handler,
 -                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 -                                mmc_hostname(mmc), host);
 +              ret = request_threaded_irq(mmc_slot(host).card_detect_irq,
 +                                         NULL,
 +                                         omap_hsmmc_detect,
 +                                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 +                                         mmc_hostname(mmc), host);
                if (ret) {
                        dev_dbg(mmc_dev(host->mmc),
                                "Unable to grab MMC CD IRQ\n");
                        goto err_slot_name;
        }
  
 +      if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
 +              ret = device_create_file(&mmc->class_dev, &dev_attr_unsafe_read);
 +
 +              /* MMC_CAP2_NO_MULTI_READ makes it crawl, try a different workaround */
 +              mmc->caps2 &= ~MMC_CAP2_NO_MULTI_READ;
 +              mmc->max_segs = 1;
 +              mmc->f_max = 32000000;
 +      }
 +
        omap_hsmmc_debugfs(mmc);
        pm_runtime_mark_last_busy(host->dev);
        pm_runtime_put_autosuspend(host->dev);
@@@ -2152,6 -2129,7 +2152,6 @@@ static int omap_hsmmc_remove(struct pla
                free_irq(host->irq, host);
                if (mmc_slot(host).card_detect_irq)
                        free_irq(mmc_slot(host).card_detect_irq, host);
 -              flush_work_sync(&host->mmc_carddetect_work);
  
                pm_runtime_put_sync(host->dev);
                pm_runtime_disable(host->dev);
@@@ -2198,6 -2176,7 +2198,6 @@@ static int omap_hsmmc_suspend(struct de
                                return ret;
                        }
                }
 -              cancel_work_sync(&host->mmc_carddetect_work);
                ret = mmc_suspend_host(host->mmc);
  
                if (ret == 0) {
                } else {
                        host->suspended = 0;
                        if (host->pdata->resume) {
-                               ret = host->pdata->resume(&pdev->dev,
-                                                         host->slot_id);
-                               if (ret)
+                               if (host->pdata->resume(&pdev->dev, host->slot_id))
                                        dev_dbg(mmc_dev(host->mmc),
                                                "Unmask interrupt failed\n");
                        }
diff --combined drivers/mtd/nand/omap2.c
@@@ -24,7 -24,6 +24,7 @@@
  #include <plat/dma.h>
  #include <plat/gpmc.h>
  #include <plat/nand.h>
 +#include <asm/system.h>
  
  #define       DRIVER_NAME     "omap2-nand"
  #define       OMAP_NAND_TIMEOUT_MS    5000
@@@ -403,18 -402,14 +403,18 @@@ static inline int omap_nand_dma_transfe
                        PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
        if (ret)
                /* PFPW engine is busy, use cpu copy method */
 -              goto out_copy;
 +              goto out_copy_unmap;
  
 +      /* this will be short, avoid CPU wakeup latency */
 +      disable_hlt();
        init_completion(&info->comp);
  
        omap_start_dma(info->dma_ch);
  
        /* setup and start DMA using dma_addr */
        wait_for_completion(&info->comp);
 +      enable_hlt();
 +
        tim = 0;
        limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
        while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
        dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
        return 0;
  
 +out_copy_unmap:
 +      dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
  out_copy:
        if (info->nand.options & NAND_BUSWIDTH_16)
                is_write == 0 ? omap_read_buf16(mtd, (u_char *) addr, len)
@@@ -868,13 -861,68 +868,13 @@@ static void omap_enable_hwecc(struct mt
        gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
  }
  
 -/**
 - * omap_wait - wait until the command is done
 - * @mtd: MTD device structure
 - * @chip: NAND Chip structure
 - *
 - * Wait function is called during Program and erase operations and
 - * the way it is called from MTD layer, we should wait till the NAND
 - * chip is ready after the programming/erase operation has completed.
 - *
 - * Erase can take up to 400ms and program up to 20ms according to
 - * general NAND and SmartMedia specs
 - */
 -static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 -{
 -      struct nand_chip *this = mtd->priv;
 -      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 -                                                      mtd);
 -      unsigned long timeo = jiffies;
 -      int status = NAND_STATUS_FAIL, state = this->state;
 -
 -      if (state == FL_ERASING)
 -              timeo += (HZ * 400) / 1000;
 -      else
 -              timeo += (HZ * 20) / 1000;
 -
 -      gpmc_nand_write(info->gpmc_cs,
 -                      GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF));
 -      while (time_before(jiffies, timeo)) {
 -              status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
 -              if (status & NAND_STATUS_READY)
 -                      break;
 -              cond_resched();
 -      }
 -      return status;
 -}
 -
  /**
   * omap_dev_ready - calls the platform specific dev_ready function
   * @mtd: MTD device structure
   */
  static int omap_dev_ready(struct mtd_info *mtd)
  {
 -      unsigned int val = 0;
 -      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 -                                                      mtd);
 -
 -      val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
 -      if ((val & 0x100) == 0x100) {
 -              /* Clear IRQ Interrupt */
 -              val |= 0x100;
 -              val &= ~(0x0);
 -              gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, val);
 -      } else {
 -              unsigned int cnt = 0;
 -              while (cnt++ < 0x1FF) {
 -                      if  ((val & 0x100) == 0x100)
 -                              return 0;
 -                      val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
 -              }
 -      }
 -
 -      return 1;
 +      return !!gpmc_read_status(GPMC_STATUS_WAIT);
  }
  
  static int __devinit omap_nand_probe(struct platform_device *pdev)
                info->nand.dev_ready = omap_dev_ready;
                info->nand.chip_delay = 0;
        } else {
 -              info->nand.waitfunc = omap_wait;
                info->nand.chip_delay = 50;
        }
  
@@@ -1083,7 -1132,8 +1083,8 @@@ static int omap_nand_remove(struct plat
        /* Release NAND device, its internal structures and partitions */
        nand_release(&info->mtd);
        iounmap(info->nand.IO_ADDR_R);
-       kfree(&info->mtd);
+       release_mem_region(info->phys_base, NAND_IO_SIZE);
+       kfree(info);
        return 0;
  }
  
diff --combined drivers/mtd/ubi/attach.c
   */
  
  /*
 - * UBI scanning sub-system.
 + * UBI attaching sub-system.
   *
 - * This sub-system is responsible for scanning the flash media, checking UBI
 - * headers and providing complete information about the UBI flash image.
 + * This sub-system is responsible for attaching MTD devices and it also
 + * implements flash media scanning.
   *
 - * The scanning information is represented by a &struct ubi_scan_info' object.
 - * Information about found volumes is represented by &struct ubi_scan_volume
 + * The attaching information is represented by a &struct ubi_attach_info'
 + * object. Information about volumes is represented by &struct ubi_ainf_volume
   * objects which are kept in volume RB-tree with root at the @volumes field.
   * The RB-tree is indexed by the volume ID.
   *
 - * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
 - * These objects are kept in per-volume RB-trees with the root at the
 - * corresponding &struct ubi_scan_volume object. To put it differently, we keep
 - * an RB-tree of per-volume objects and each of these objects is the root of
 - * RB-tree of per-eraseblock objects.
 + * Logical eraseblocks are represented by &struct ubi_ainf_peb objects. These
 + * objects are kept in per-volume RB-trees with the root at the corresponding
 + * &struct ubi_ainf_volume object. To put it differently, we keep an RB-tree of
 + * per-volume objects and each of these objects is the root of RB-tree of
 + * per-LEB objects.
   *
   * Corrupted physical eraseblocks are put to the @corr list, free physical
   * eraseblocks are put to the @free list and the physical eraseblock to be
   *
   * 1. Corruptions caused by power cuts. These are expected corruptions and UBI
   * tries to handle them gracefully, without printing too many warnings and
 - * error messages. The idea is that we do not lose important data in these case
 - * - we may lose only the data which was being written to the media just before
 - * the power cut happened, and the upper layers (e.g., UBIFS) are supposed to
 - * handle such data losses (e.g., by using the FS journal).
 + * error messages. The idea is that we do not lose important data in these
 + * cases - we may lose only the data which were being written to the media just
 + * before the power cut happened, and the upper layers (e.g., UBIFS) are
 + * supposed to handle such data losses (e.g., by using the FS journal).
   *
   * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like
   * the reason is a power cut, UBI puts this PEB to the @erase list, and all
   * PEBs in the @erase list are scheduled for erasure later.
   *
   * 2. Unexpected corruptions which are not caused by power cuts. During
 - * scanning, such PEBs are put to the @corr list and UBI preserves them.
 + * attaching, such PEBs are put to the @corr list and UBI preserves them.
   * Obviously, this lessens the amount of available PEBs, and if at some  point
   * UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs
   * about such PEBs every time the MTD device is attached.
   *
   * However, it is difficult to reliably distinguish between these types of
 - * corruptions and UBI's strategy is as follows. UBI assumes corruption type 2
 - * if the VID header is corrupted and the data area does not contain all 0xFFs,
 - * and there were no bit-flips or integrity errors while reading the data area.
 - * Otherwise UBI assumes corruption type 1. So the decision criteria are as
 - * follows.
 - *   o If the data area contains only 0xFFs, there is no data, and it is safe
 + * corruptions and UBI's strategy is as follows (in case of attaching by
 + * scanning). UBI assumes corruption type 2 if the VID header is corrupted and
 + * the data area does not contain all 0xFFs, and there were no bit-flips or
 + * integrity errors (e.g., ECC errors in case of NAND) while reading the data
 + * area.  Otherwise UBI assumes corruption type 1. So the decision criteria
 + * are as follows.
 + *   o If the data area contains only 0xFFs, there are no data, and it is safe
   *     to just erase this PEB - this is corruption type 1.
   *   o If the data area has bit-flips or data integrity errors (ECC errors on
   *     NAND), it is probably a PEB which was being erased when power cut
  #include <linux/random.h>
  #include "ubi.h"
  
 -#ifdef CONFIG_MTD_UBI_DEBUG
 -static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
 -#else
 -#define paranoid_check_si(ubi, si) 0
 -#endif
 +static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
  
  /* Temporary variables used during scanning */
  static struct ubi_ec_hdr *ech;
@@@ -97,18 -100,13 +97,18 @@@ static struct ubi_vid_hdr *vidh
  
  /**
   * add_to_list - add physical eraseblock to a list.
 - * @si: scanning information
 + * @ai: attaching information
   * @pnum: physical eraseblock number to add
 + * @vol_id: the last used volume id for the PEB
 + * @lnum: the last used LEB number for the PEB
   * @ec: erase counter of the physical eraseblock
   * @to_head: if not zero, add to the head of the list
   * @list: the list to add to
   *
 - * This function adds physical eraseblock @pnum to free, erase, or alien lists.
 + * This function allocates a 'struct ubi_ainf_peb' object for physical
 + * eraseblock @pnum and adds it to the "free", "erase", or "alien" lists.
 + * It stores the @lnum and @vol_id alongside, which can both be
 + * %UBI_UNKNOWN if they are not available, not readable, or not assigned.
   * If @to_head is not zero, PEB will be added to the head of the list, which
   * basically means it will be processed first later. E.g., we add corrupted
   * PEBs (corrupted due to power cuts) to the head of the erase list to make
   * returns zero in case of success and a negative error code in case of
   * failure.
   */
 -static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
 -                     struct list_head *list)
 +static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id,
 +                     int lnum, int ec, int to_head, struct list_head *list)
  {
 -      struct ubi_scan_leb *seb;
 +      struct ubi_ainf_peb *aeb;
  
 -      if (list == &si->free) {
 +      if (list == &ai->free) {
                dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
 -      } else if (list == &si->erase) {
 +      } else if (list == &ai->erase) {
                dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
 -      } else if (list == &si->alien) {
 +      } else if (list == &ai->alien) {
                dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
 -              si->alien_peb_count += 1;
 +              ai->alien_peb_count += 1;
        } else
                BUG();
  
 -      seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 -      if (!seb)
 +      aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
 +      if (!aeb)
                return -ENOMEM;
  
 -      seb->pnum = pnum;
 -      seb->ec = ec;
 +      aeb->pnum = pnum;
 +      aeb->vol_id = vol_id;
 +      aeb->lnum = lnum;
 +      aeb->ec = ec;
        if (to_head)
 -              list_add(&seb->u.list, list);
 +              list_add(&aeb->u.list, list);
        else
 -              list_add_tail(&seb->u.list, list);
 +              list_add_tail(&aeb->u.list, list);
        return 0;
  }
  
  /**
   * add_corrupted - add a corrupted physical eraseblock.
 - * @si: scanning information
 + * @ai: attaching information
   * @pnum: physical eraseblock number to add
   * @ec: erase counter of the physical eraseblock
   *
 - * This function adds corrupted physical eraseblock @pnum to the 'corr' list.
 - * The corruption was presumably not caused by a power cut. Returns zero in
 - * case of success and a negative error code in case of failure.
 + * This function allocates a 'struct ubi_ainf_peb' object for a corrupted
 + * physical eraseblock @pnum and adds it to the 'corr' list.  The corruption
 + * was presumably not caused by a power cut. Returns zero in case of success
 + * and a negative error code in case of failure.
   */
 -static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
 +static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec)
  {
 -      struct ubi_scan_leb *seb;
 +      struct ubi_ainf_peb *aeb;
  
        dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
  
 -      seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 -      if (!seb)
 +      aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
 +      if (!aeb)
                return -ENOMEM;
  
 -      si->corr_peb_count += 1;
 -      seb->pnum = pnum;
 -      seb->ec = ec;
 -      list_add(&seb->u.list, &si->corr);
 +      ai->corr_peb_count += 1;
 +      aeb->pnum = pnum;
 +      aeb->ec = ec;
 +      list_add(&aeb->u.list, &ai->corr);
        return 0;
  }
  
  /**
   * validate_vid_hdr - check volume identifier header.
   * @vid_hdr: the volume identifier header to check
 - * @sv: information about the volume this logical eraseblock belongs to
 + * @av: information about the volume this logical eraseblock belongs to
   * @pnum: physical eraseblock number the VID header came from
   *
   * This function checks that data stored in @vid_hdr is consistent. Returns
   * headers of the same volume.
   */
  static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
 -                          const struct ubi_scan_volume *sv, int pnum)
 +                          const struct ubi_ainf_volume *av, int pnum)
  {
        int vol_type = vid_hdr->vol_type;
        int vol_id = be32_to_cpu(vid_hdr->vol_id);
        int used_ebs = be32_to_cpu(vid_hdr->used_ebs);
        int data_pad = be32_to_cpu(vid_hdr->data_pad);
  
 -      if (sv->leb_count != 0) {
 -              int sv_vol_type;
 +      if (av->leb_count != 0) {
 +              int av_vol_type;
  
                /*
                 * This is not the first logical eraseblock belonging to this
                 * to the data in previous logical eraseblock headers.
                 */
  
 -              if (vol_id != sv->vol_id) {
 -                      dbg_err("inconsistent vol_id");
 +              if (vol_id != av->vol_id) {
 +                      ubi_err("inconsistent vol_id");
                        goto bad;
                }
  
 -              if (sv->vol_type == UBI_STATIC_VOLUME)
 -                      sv_vol_type = UBI_VID_STATIC;
 +              if (av->vol_type == UBI_STATIC_VOLUME)
 +                      av_vol_type = UBI_VID_STATIC;
                else
 -                      sv_vol_type = UBI_VID_DYNAMIC;
 +                      av_vol_type = UBI_VID_DYNAMIC;
  
 -              if (vol_type != sv_vol_type) {
 -                      dbg_err("inconsistent vol_type");
 +              if (vol_type != av_vol_type) {
 +                      ubi_err("inconsistent vol_type");
                        goto bad;
                }
  
 -              if (used_ebs != sv->used_ebs) {
 -                      dbg_err("inconsistent used_ebs");
 +              if (used_ebs != av->used_ebs) {
 +                      ubi_err("inconsistent used_ebs");
                        goto bad;
                }
  
 -              if (data_pad != sv->data_pad) {
 -                      dbg_err("inconsistent data_pad");
 +              if (data_pad != av->data_pad) {
 +                      ubi_err("inconsistent data_pad");
                        goto bad;
                }
        }
  
  bad:
        ubi_err("inconsistent VID header at PEB %d", pnum);
 -      ubi_dbg_dump_vid_hdr(vid_hdr);
 -      ubi_dbg_dump_sv(sv);
 +      ubi_dump_vid_hdr(vid_hdr);
 +      ubi_dump_av(av);
        return -EINVAL;
  }
  
  /**
 - * add_volume - add volume to the scanning information.
 - * @si: scanning information
 + * add_volume - add volume to the attaching information.
 + * @ai: attaching information
   * @vol_id: ID of the volume to add
   * @pnum: physical eraseblock number
   * @vid_hdr: volume identifier header
   *
   * If the volume corresponding to the @vid_hdr logical eraseblock is already
 - * present in the scanning information, this function does nothing. Otherwise
 - * it adds corresponding volume to the scanning information. Returns a pointer
 - * to the scanning volume object in case of success and a negative error code
 - * in case of failure.
 + * present in the attaching information, this function does nothing. Otherwise
 + * it adds corresponding volume to the attaching information. Returns a pointer
 + * to the allocated "av" object in case of success and a negative error code in
 + * case of failure.
   */
 -static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
 -                                        int pnum,
 +static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai,
 +                                        int vol_id, int pnum,
                                          const struct ubi_vid_hdr *vid_hdr)
  {
 -      struct ubi_scan_volume *sv;
 -      struct rb_node **p = &si->volumes.rb_node, *parent = NULL;
 +      struct ubi_ainf_volume *av;
 +      struct rb_node **p = &ai->volumes.rb_node, *parent = NULL;
  
        ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id));
  
        /* Walk the volume RB-tree to look if this volume is already present */
        while (*p) {
                parent = *p;
 -              sv = rb_entry(parent, struct ubi_scan_volume, rb);
 +              av = rb_entry(parent, struct ubi_ainf_volume, rb);
  
 -              if (vol_id == sv->vol_id)
 -                      return sv;
 +              if (vol_id == av->vol_id)
 +                      return av;
  
 -              if (vol_id > sv->vol_id)
 +              if (vol_id > av->vol_id)
                        p = &(*p)->rb_left;
                else
                        p = &(*p)->rb_right;
        }
  
        /* The volume is absent - add it */
 -      sv = kmalloc(sizeof(struct ubi_scan_volume), GFP_KERNEL);
 -      if (!sv)
 +      av = kmalloc(sizeof(struct ubi_ainf_volume), GFP_KERNEL);
 +      if (!av)
                return ERR_PTR(-ENOMEM);
  
 -      sv->highest_lnum = sv->leb_count = 0;
 -      sv->vol_id = vol_id;
 -      sv->root = RB_ROOT;
 -      sv->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
 -      sv->data_pad = be32_to_cpu(vid_hdr->data_pad);
 -      sv->compat = vid_hdr->compat;
 -      sv->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
 +      av->highest_lnum = av->leb_count = 0;
 +      av->vol_id = vol_id;
 +      av->root = RB_ROOT;
 +      av->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
 +      av->data_pad = be32_to_cpu(vid_hdr->data_pad);
 +      av->compat = vid_hdr->compat;
 +      av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
                                                            : UBI_STATIC_VOLUME;
 -      if (vol_id > si->highest_vol_id)
 -              si->highest_vol_id = vol_id;
 +      if (vol_id > ai->highest_vol_id)
 +              ai->highest_vol_id = vol_id;
  
 -      rb_link_node(&sv->rb, parent, p);
 -      rb_insert_color(&sv->rb, &si->volumes);
 -      si->vols_found += 1;
 +      rb_link_node(&av->rb, parent, p);
 +      rb_insert_color(&av->rb, &ai->volumes);
 +      ai->vols_found += 1;
        dbg_bld("added volume %d", vol_id);
 -      return sv;
 +      return av;
  }
  
  /**
   * compare_lebs - find out which logical eraseblock is newer.
   * @ubi: UBI device description object
 - * @seb: first logical eraseblock to compare
 + * @aeb: first logical eraseblock to compare
   * @pnum: physical eraseblock number of the second logical eraseblock to
   * compare
   * @vid_hdr: volume identifier header of the second logical eraseblock
   * case of success this function returns a positive value, in case of failure, a
   * negative error code is returned. The success return codes use the following
   * bits:
 - *     o bit 0 is cleared: the first PEB (described by @seb) is newer than the
 + *     o bit 0 is cleared: the first PEB (described by @aeb) is newer than the
   *       second PEB (described by @pnum and @vid_hdr);
   *     o bit 0 is set: the second PEB is newer;
   *     o bit 1 is cleared: no bit-flips were detected in the newer LEB;
   *     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(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
 +static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
                        int pnum, const struct ubi_vid_hdr *vid_hdr)
  {
        void *buf;
        struct ubi_vid_hdr *vh = NULL;
        unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
  
 -      if (sqnum2 == seb->sqnum) {
 +      if (sqnum2 == aeb->sqnum) {
                /*
                 * This must be a really ancient UBI image which has been
                 * created before sequence numbers support has been added. At
        }
  
        /* Obviously the LEB with lower sequence counter is older */
 -      second_is_newer = !!(sqnum2 > seb->sqnum);
 +      second_is_newer = (sqnum2 > aeb->sqnum);
  
        /*
         * Now we know which copy is newer. If the copy flag of the PEB with
                        return 1;
                }
        } else {
 -              if (!seb->copy_flag) {
 +              if (!aeb->copy_flag) {
                        /* It is not a copy, so it is newer */
                        dbg_bld("first PEB %d is newer, copy_flag is unset",
                                pnum);
                if (!vh)
                        return -ENOMEM;
  
 -              pnum = seb->pnum;
 +              pnum = aeb->pnum;
                err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
                if (err) {
                        if (err == UBI_IO_BITFLIPS)
                                bitflips = 1;
                        else {
 -                              dbg_err("VID of PEB %d header is bad, but it "
 +                              ubi_err("VID of PEB %d header is bad, but it "
                                        "was OK earlier, err %d", pnum, err);
                                if (err > 0)
                                        err = -EIO;
@@@ -434,9 -429,9 +434,9 @@@ out_free_vidh
  }
  
  /**
 - * ubi_scan_add_used - add physical eraseblock to the scanning information.
 + * ubi_add_to_av - add used physical eraseblock to the attaching information.
   * @ubi: UBI device description object
 - * @si: scanning information
 + * @ai: attaching information
   * @pnum: the physical eraseblock number
   * @ec: erase counter
   * @vid_hdr: the volume identifier header
   * 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(struct ubi_device *ubi, struct ubi_scan_info *si,
 -                    int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
 -                    int bitflips)
 +int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
 +                int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips)
  {
        int err, vol_id, lnum;
        unsigned long long sqnum;
 -      struct ubi_scan_volume *sv;
 -      struct ubi_scan_leb *seb;
 +      struct ubi_ainf_volume *av;
 +      struct ubi_ainf_peb *aeb;
        struct rb_node **p, *parent = NULL;
  
        vol_id = be32_to_cpu(vid_hdr->vol_id);
        dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d",
                pnum, vol_id, lnum, ec, sqnum, bitflips);
  
 -      sv = add_volume(si, vol_id, pnum, vid_hdr);
 -      if (IS_ERR(sv))
 -              return PTR_ERR(sv);
 +      av = add_volume(ai, vol_id, pnum, vid_hdr);
 +      if (IS_ERR(av))
 +              return PTR_ERR(av);
  
 -      if (si->max_sqnum < sqnum)
 -              si->max_sqnum = sqnum;
 +      if (ai->max_sqnum < sqnum)
 +              ai->max_sqnum = sqnum;
  
        /*
         * Walk the RB-tree of logical eraseblocks of volume @vol_id to look
         * if this is the first instance of this logical eraseblock or not.
         */
 -      p = &sv->root.rb_node;
 +      p = &av->root.rb_node;
        while (*p) {
                int cmp_res;
  
                parent = *p;
 -              seb = rb_entry(parent, struct ubi_scan_leb, u.rb);
 -              if (lnum != seb->lnum) {
 -                      if (lnum < seb->lnum)
 +              aeb = rb_entry(parent, struct ubi_ainf_peb, u.rb);
 +              if (lnum != aeb->lnum) {
 +                      if (lnum < aeb->lnum)
                                p = &(*p)->rb_left;
                        else
                                p = &(*p)->rb_right;
                 * logical eraseblock present.
                 */
  
 -              dbg_bld("this LEB already exists: PEB %d, sqnum %llu, "
 -                      "EC %d", seb->pnum, seb->sqnum, seb->ec);
 +              dbg_bld("this LEB already exists: PEB %d, sqnum %llu, EC %d",
 +                      aeb->pnum, aeb->sqnum, aeb->ec);
  
                /*
                 * Make sure that the logical eraseblocks have different
                 * images, but refuse attaching old images with duplicated
                 * logical eraseblocks because there was an unclean reboot.
                 */
 -              if (seb->sqnum == sqnum && sqnum != 0) {
 +              if (aeb->sqnum == sqnum && sqnum != 0) {
                        ubi_err("two LEBs with same sequence number %llu",
                                sqnum);
 -                      ubi_dbg_dump_seb(seb, 0);
 -                      ubi_dbg_dump_vid_hdr(vid_hdr);
 +                      ubi_dump_aeb(aeb, 0);
 +                      ubi_dump_vid_hdr(vid_hdr);
                        return -EINVAL;
                }
  
                 * Now we have to drop the older one and preserve the newer
                 * one.
                 */
 -              cmp_res = compare_lebs(ubi, seb, pnum, vid_hdr);
 +              cmp_res = compare_lebs(ubi, aeb, pnum, vid_hdr);
                if (cmp_res < 0)
                        return cmp_res;
  
                         * This logical eraseblock is newer than the one
                         * found earlier.
                         */
 -                      err = validate_vid_hdr(vid_hdr, sv, pnum);
 +                      err = validate_vid_hdr(vid_hdr, av, pnum);
                        if (err)
                                return err;
  
 -                      err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
 -                                        &si->erase);
 +                      err = add_to_list(ai, aeb->pnum, aeb->vol_id,
 +                                        aeb->lnum, aeb->ec, cmp_res & 4,
 +                                        &ai->erase);
                        if (err)
                                return err;
  
 -                      seb->ec = ec;
 -                      seb->pnum = pnum;
 -                      seb->scrub = ((cmp_res & 2) || bitflips);
 -                      seb->copy_flag = vid_hdr->copy_flag;
 -                      seb->sqnum = sqnum;
 +                      aeb->ec = ec;
 +                      aeb->pnum = pnum;
 +                      aeb->vol_id = vol_id;
 +                      aeb->lnum = lnum;
 +                      aeb->scrub = ((cmp_res & 2) || bitflips);
 +                      aeb->copy_flag = vid_hdr->copy_flag;
 +                      aeb->sqnum = sqnum;
  
 -                      if (sv->highest_lnum == lnum)
 -                              sv->last_data_size =
 +                      if (av->highest_lnum == lnum)
 +                              av->last_data_size =
                                        be32_to_cpu(vid_hdr->data_size);
  
                        return 0;
                         * This logical eraseblock is older than the one found
                         * previously.
                         */
 -                      return add_to_list(si, pnum, ec, cmp_res & 4,
 -                                         &si->erase);
 +                      return add_to_list(ai, pnum, vol_id, lnum, ec,
 +                                         cmp_res & 4, &ai->erase);
                }
        }
  
        /*
         * We've met this logical eraseblock for the first time, add it to the
 -       * scanning information.
 +       * attaching information.
         */
  
 -      err = validate_vid_hdr(vid_hdr, sv, pnum);
 +      err = validate_vid_hdr(vid_hdr, av, pnum);
        if (err)
                return err;
  
 -      seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 -      if (!seb)
 +      aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
 +      if (!aeb)
                return -ENOMEM;
  
 -      seb->ec = ec;
 -      seb->pnum = pnum;
 -      seb->lnum = lnum;
 -      seb->scrub = bitflips;
 -      seb->copy_flag = vid_hdr->copy_flag;
 -      seb->sqnum = sqnum;
 -
 -      if (sv->highest_lnum <= lnum) {
 -              sv->highest_lnum = lnum;
 -              sv->last_data_size = be32_to_cpu(vid_hdr->data_size);
 +      aeb->ec = ec;
 +      aeb->pnum = pnum;
 +      aeb->vol_id = vol_id;
 +      aeb->lnum = lnum;
 +      aeb->scrub = bitflips;
 +      aeb->copy_flag = vid_hdr->copy_flag;
 +      aeb->sqnum = sqnum;
 +
 +      if (av->highest_lnum <= lnum) {
 +              av->highest_lnum = lnum;
 +              av->last_data_size = be32_to_cpu(vid_hdr->data_size);
        }
  
 -      sv->leb_count += 1;
 -      rb_link_node(&seb->u.rb, parent, p);
 -      rb_insert_color(&seb->u.rb, &sv->root);
 +      av->leb_count += 1;
 +      rb_link_node(&aeb->u.rb, parent, p);
 +      rb_insert_color(&aeb->u.rb, &av->root);
        return 0;
  }
  
  /**
 - * ubi_scan_find_sv - find volume in the scanning information.
 - * @si: scanning information
 + * ubi_find_av - find volume in the attaching information.
 + * @ai: attaching information
   * @vol_id: the requested volume ID
   *
   * This function returns a pointer to the volume description or %NULL if there
 - * are no data about this volume in the scanning information.
 - */
 -struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
 -                                       int vol_id)
 -{
 -      struct ubi_scan_volume *sv;
 -      struct rb_node *p = si->volumes.rb_node;
 -
 -      while (p) {
 -              sv = rb_entry(p, struct ubi_scan_volume, rb);
 -
 -              if (vol_id == sv->vol_id)
 -                      return sv;
 -
 -              if (vol_id > sv->vol_id)
 -                      p = p->rb_left;
 -              else
 -                      p = p->rb_right;
 -      }
 -
 -      return NULL;
 -}
 -
 -/**
 - * ubi_scan_find_seb - find LEB in the volume scanning information.
 - * @sv: a pointer to the volume scanning information
 - * @lnum: the requested logical eraseblock
 - *
 - * This function returns a pointer to the scanning logical eraseblock or %NULL
 - * if there are no data about it in the scanning volume information.
 + * are no data about this volume in the attaching information.
   */
 -struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
 -                                     int lnum)
 +struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
 +                                  int vol_id)
  {
 -      struct ubi_scan_leb *seb;
 -      struct rb_node *p = sv->root.rb_node;
 +      struct ubi_ainf_volume *av;
 +      struct rb_node *p = ai->volumes.rb_node;
  
        while (p) {
 -              seb = rb_entry(p, struct ubi_scan_leb, u.rb);
 +              av = rb_entry(p, struct ubi_ainf_volume, rb);
  
 -              if (lnum == seb->lnum)
 -                      return seb;
 +              if (vol_id == av->vol_id)
 +                      return av;
  
 -              if (lnum > seb->lnum)
 +              if (vol_id > av->vol_id)
                        p = p->rb_left;
                else
                        p = p->rb_right;
  }
  
  /**
 - * ubi_scan_rm_volume - delete scanning information about a volume.
 - * @si: scanning information
 - * @sv: the volume scanning information to delete
 + * ubi_remove_av - delete attaching information about a volume.
 + * @ai: attaching information
 + * @av: the volume attaching information to delete
   */
 -void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
 +void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
  {
        struct rb_node *rb;
 -      struct ubi_scan_leb *seb;
 +      struct ubi_ainf_peb *aeb;
  
 -      dbg_bld("remove scanning information about volume %d", sv->vol_id);
 +      dbg_bld("remove attaching information about volume %d", av->vol_id);
  
 -      while ((rb = rb_first(&sv->root))) {
 -              seb = rb_entry(rb, struct ubi_scan_leb, u.rb);
 -              rb_erase(&seb->u.rb, &sv->root);
 -              list_add_tail(&seb->u.list, &si->erase);
 +      while ((rb = rb_first(&av->root))) {
 +              aeb = rb_entry(rb, struct ubi_ainf_peb, u.rb);
 +              rb_erase(&aeb->u.rb, &av->root);
 +              list_add_tail(&aeb->u.list, &ai->erase);
        }
  
 -      rb_erase(&sv->rb, &si->volumes);
 -      kfree(sv);
 -      si->vols_found -= 1;
 +      rb_erase(&av->rb, &ai->volumes);
 +      kfree(av);
 +      ai->vols_found -= 1;
  }
  
  /**
 - * ubi_scan_erase_peb - erase a physical eraseblock.
 + * early_erase_peb - erase a physical eraseblock.
   * @ubi: UBI device description object
 - * @si: scanning information
 + * @ai: attaching information
   * @pnum: physical eraseblock number to erase;
 - * @ec: erase counter value to write (%UBI_SCAN_UNKNOWN_EC if it is unknown)
 + * @ec: erase counter value to write (%UBI_UNKNOWN if it is unknown)
   *
   * This function erases physical eraseblock 'pnum', and writes the erase
   * counter header to it. This function should only be used on UBI device
   * This function returns zero in case of success and a negative error code in
   * case of failure.
   */
 -int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
 -                     int pnum, int ec)
 +static int early_erase_peb(struct ubi_device *ubi,
 +                         const struct ubi_attach_info *ai, int pnum, int ec)
  {
        int err;
        struct ubi_ec_hdr *ec_hdr;
@@@ -695,9 -716,9 +695,9 @@@ out_free
  }
  
  /**
 - * ubi_scan_get_free_peb - get a free physical eraseblock.
 + * ubi_early_get_peb - get a free physical eraseblock.
   * @ubi: UBI device description object
 - * @si: scanning information
 + * @ai: attaching information
   *
   * This function returns a free physical eraseblock. It is supposed to be
   * called on the UBI initialization stages when the wear-leveling sub-system is
   * the lists, writes the EC header if it is needed, and removes it from the
   * list.
   *
 - * This function returns scanning physical eraseblock information in case of
 - * success and an error code in case of failure.
 + * This function returns a pointer to the "aeb" of the found free PEB in case
 + * of success and an error code in case of failure.
   */
 -struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
 -                                         struct ubi_scan_info *si)
 +struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
 +                                     struct ubi_attach_info *ai)
  {
        int err = 0;
 -      struct ubi_scan_leb *seb, *tmp_seb;
 +      struct ubi_ainf_peb *aeb, *tmp_aeb;
  
 -      if (!list_empty(&si->free)) {
 -              seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
 -              list_del(&seb->u.list);
 -              dbg_bld("return free PEB %d, EC %d", seb->pnum, seb->ec);
 -              return seb;
 +      if (!list_empty(&ai->free)) {
 +              aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list);
 +              list_del(&aeb->u.list);
 +              dbg_bld("return free PEB %d, EC %d", aeb->pnum, aeb->ec);
 +              return aeb;
        }
  
        /*
         * so forth. We don't want to take care about bad eraseblocks here -
         * they'll be handled later.
         */
 -      list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
 -              if (seb->ec == UBI_SCAN_UNKNOWN_EC)
 -                      seb->ec = si->mean_ec;
 +      list_for_each_entry_safe(aeb, tmp_aeb, &ai->erase, u.list) {
 +              if (aeb->ec == UBI_UNKNOWN)
 +                      aeb->ec = ai->mean_ec;
  
 -              err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
 +              err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1);
                if (err)
                        continue;
  
 -              seb->ec += 1;
 -              list_del(&seb->u.list);
 -              dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
 -              return seb;
 +              aeb->ec += 1;
 +              list_del(&aeb->u.list);
 +              dbg_bld("return PEB %d, EC %d", aeb->pnum, aeb->ec);
 +              return aeb;
        }
  
        ubi_err("no free eraseblocks");
@@@ -768,9 -789,9 +768,9 @@@ static int check_corruption(struct ubi_
        int err;
  
        mutex_lock(&ubi->buf_mutex);
 -      memset(ubi->peb_buf1, 0x00, ubi->leb_size);
 +      memset(ubi->peb_buf, 0x00, ubi->leb_size);
  
 -      err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
 +      err = ubi_io_read(ubi, ubi->peb_buf, pnum, ubi->leb_start,
                          ubi->leb_size);
        if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
                /*
        if (err)
                goto out_unlock;
  
 -      if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size))
 +      if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size))
                goto out_unlock;
  
        ubi_err("PEB %d contains corrupted VID header, and the data does not "
                "contain all 0xFF, this may be a non-UBI PEB or a severe VID "
                "header corruption which requires manual inspection", pnum);
 -      ubi_dbg_dump_vid_hdr(vid_hdr);
 +      ubi_dump_vid_hdr(vid_hdr);
        dbg_msg("hexdump of PEB %d offset %d, length %d",
                pnum, ubi->leb_start, ubi->leb_size);
        ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
 -                             ubi->peb_buf1, ubi->leb_size, 1);
 +                             ubi->peb_buf, ubi->leb_size, 1);
        err = 1;
  
  out_unlock:
  }
  
  /**
 - * process_eb - read, check UBI headers, and add them to scanning information.
 + * scan_peb - scan and process UBI headers of a PEB.
   * @ubi: UBI device description object
 - * @si: scanning information
 + * @ai: attaching information
   * @pnum: the physical eraseblock number
   *
 - * This function returns a zero if the physical eraseblock was successfully
 - * handled and a negative error code in case of failure.
 + * 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
 + * "attaching info" structure. Returns zero if the physical eraseblock was
 + * successfully handled and a negative error code in case of failure.
   */
 -static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 -                    int pnum)
 +static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
 +                  int pnum)
  {
        long long uninitialized_var(ec);
        int err, bitflips = 0, vol_id, ec_err = 0;
        if (err < 0)
                return err;
        else if (err) {
 -              /*
 -               * FIXME: this is actually duty of the I/O sub-system to
 -               * initialize this, but MTD does not provide enough
 -               * information.
 -               */
 -              si->bad_peb_count += 1;
 +              ai->bad_peb_count += 1;
                return 0;
        }
  
                bitflips = 1;
                break;
        case UBI_IO_FF:
 -              si->empty_peb_count += 1;
 -              return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
 -                                 &si->erase);
 +              ai->empty_peb_count += 1;
 +              return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
 +                                 UBI_UNKNOWN, 0, &ai->erase);
        case UBI_IO_FF_BITFLIPS:
 -              si->empty_peb_count += 1;
 -              return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
 -                                 &si->erase);
 +              ai->empty_peb_count += 1;
 +              return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
 +                                 UBI_UNKNOWN, 1, &ai->erase);
        case UBI_IO_BAD_HDR_EBADMSG:
        case UBI_IO_BAD_HDR:
                /*
                 * moved and EC be re-created.
                 */
                ec_err = err;
 -              ec = UBI_SCAN_UNKNOWN_EC;
 +              ec = UBI_UNKNOWN;
                bitflips = 1;
                break;
        default:
                         */
                        ubi_err("erase counter overflow, max is %d",
                                UBI_MAX_ERASECOUNTER);
 -                      ubi_dbg_dump_ec_hdr(ech);
 +                      ubi_dump_ec_hdr(ech);
                        return -EINVAL;
                }
  
                    ubi->image_seq != image_seq) {
                        ubi_err("bad image sequence number %d in PEB %d, "
                                "expected %d", image_seq, pnum, ubi->image_seq);
 -                      ubi_dbg_dump_ec_hdr(ech);
 +                      ubi_dump_ec_hdr(ech);
                        return -EINVAL;
                }
        }
                         * PEB, bit it is not marked as bad yet. This may also
                         * be a result of power cut during erasure.
                         */
 -                      si->maybe_bad_peb_count += 1;
 +                      ai->maybe_bad_peb_count += 1;
        case UBI_IO_BAD_HDR:
                if (ec_err)
                        /*
                        return err;
                else if (!err)
                        /* This corruption is caused by a power cut */
 -                      err = add_to_list(si, pnum, ec, 1, &si->erase);
 +                      err = add_to_list(ai, pnum, UBI_UNKNOWN,
 +                                        UBI_UNKNOWN, ec, 1, &ai->erase);
                else
                        /* This is an unexpected corruption */
 -                      err = add_corrupted(si, pnum, ec);
 +                      err = add_corrupted(ai, pnum, ec);
                if (err)
                        return err;
                goto adjust_mean_ec;
        case UBI_IO_FF_BITFLIPS:
 -              err = add_to_list(si, pnum, ec, 1, &si->erase);
 +              err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
 +                                ec, 1, &ai->erase);
                if (err)
                        return err;
                goto adjust_mean_ec;
        case UBI_IO_FF:
-               if (ec_err)
+               if (ec_err || bitflips)
 -                      err = add_to_list(si, pnum, ec, 1, &si->erase);
 +                      err = add_to_list(ai, pnum, UBI_UNKNOWN,
 +                                        UBI_UNKNOWN, ec, 1, &ai->erase);
                else
 -                      err = add_to_list(si, pnum, ec, 0, &si->free);
 +                      err = add_to_list(ai, pnum, UBI_UNKNOWN,
 +                                        UBI_UNKNOWN, ec, 0, &ai->free);
                if (err)
                        return err;
                goto adjust_mean_ec;
                case UBI_COMPAT_DELETE:
                        ubi_msg("\"delete\" compatible internal volume %d:%d"
                                " found, will remove it", vol_id, lnum);
 -                      err = add_to_list(si, pnum, ec, 1, &si->erase);
 +                      err = add_to_list(ai, pnum, vol_id, lnum,
 +                                        ec, 1, &ai->erase);
                        if (err)
                                return err;
                        return 0;
                case UBI_COMPAT_PRESERVE:
                        ubi_msg("\"preserve\" compatible internal volume %d:%d"
                                " found", vol_id, lnum);
 -                      err = add_to_list(si, pnum, ec, 0, &si->alien);
 +                      err = add_to_list(ai, pnum, vol_id, lnum,
 +                                        ec, 0, &ai->alien);
                        if (err)
                                return err;
                        return 0;
        if (ec_err)
                ubi_warn("valid VID header but corrupted EC header at PEB %d",
                         pnum);
 -      err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
 +      err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
        if (err)
                return err;
  
  adjust_mean_ec:
        if (!ec_err) {
 -              si->ec_sum += ec;
 -              si->ec_count += 1;
 -              if (ec > si->max_ec)
 -                      si->max_ec = ec;
 -              if (ec < si->min_ec)
 -                      si->min_ec = ec;
 +              ai->ec_sum += ec;
 +              ai->ec_count += 1;
 +              if (ec > ai->max_ec)
 +                      ai->max_ec = ec;
 +              if (ec < ai->min_ec)
 +                      ai->min_ec = ec;
        }
  
        return 0;
  }
  
  /**
 - * check_what_we_have - check what PEB were found by scanning.
 + * late_analysis - analyze the overall situation with PEB.
   * @ubi: UBI device description object
 - * @si: scanning information
 + * @ai: attaching information
   *
 - * This is a helper function which takes a look what PEBs were found by
 - * scanning, and decides whether the flash is empty and should be formatted and
 - * whether there are too many corrupted PEBs and we should not attach this
 - * MTD device. Returns zero if we should proceed with attaching the MTD device,
 - * and %-EINVAL if we should not.
 + * This is a helper function which takes a look what PEBs we have after we
 + * gather information about all of them ("ai" is compete). It decides whether
 + * the flash is empty and should be formatted of whether there are too many
 + * corrupted PEBs and we should not attach this MTD device. Returns zero if we
 + * should proceed with attaching the MTD device, and %-EINVAL if we should not.
   */
 -static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
 +static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
  {
 -      struct ubi_scan_leb *seb;
 +      struct ubi_ainf_peb *aeb;
        int max_corr, peb_count;
  
 -      peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
 +      peb_count = ubi->peb_count - ai->bad_peb_count - ai->alien_peb_count;
        max_corr = peb_count / 20 ?: 8;
  
        /*
         * unclean reboots. However, many of them may indicate some problems
         * with the flash HW or driver.
         */
 -      if (si->corr_peb_count) {
 +      if (ai->corr_peb_count) {
                ubi_err("%d PEBs are corrupted and preserved",
 -                      si->corr_peb_count);
 +                      ai->corr_peb_count);
                printk(KERN_ERR "Corrupted PEBs are:");
 -              list_for_each_entry(seb, &si->corr, u.list)
 -                      printk(KERN_CONT " %d", seb->pnum);
 +              list_for_each_entry(aeb, &ai->corr, u.list)
 +                      printk(KERN_CONT " %d", aeb->pnum);
                printk(KERN_CONT "\n");
  
                /*
                 * If too many PEBs are corrupted, we refuse attaching,
                 * otherwise, only print a warning.
                 */
 -              if (si->corr_peb_count >= max_corr) {
 +              if (ai->corr_peb_count >= max_corr) {
                        ubi_err("too many corrupted PEBs, refusing");
                        return -EINVAL;
                }
        }
  
 -      if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
 +      if (ai->empty_peb_count + ai->maybe_bad_peb_count == peb_count) {
                /*
                 * All PEBs are empty, or almost all - a couple PEBs look like
                 * they may be bad PEBs which were not marked as bad yet.
                 * 2. Flash contains non-UBI data and we do not want to format
                 *    it and destroy possibly important information.
                 */
 -              if (si->maybe_bad_peb_count <= 2) {
 -                      si->is_empty = 1;
 +              if (ai->maybe_bad_peb_count <= 2) {
 +                      ai->is_empty = 1;
                        ubi_msg("empty MTD device detected");
                        get_random_bytes(&ubi->image_seq,
                                         sizeof(ubi->image_seq));
  }
  
  /**
 - * ubi_scan - scan an MTD device.
 + * scan_all - scan entire MTD device.
   * @ubi: UBI device description object
   *
   * This function does full scanning of an MTD device and returns complete
 - * information about it. In case of failure, an error code is returned.
 + * information about it in form of a "struct ubi_attach_info" object. In case
 + * of failure, an error code is returned.
   */
 -struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
 +static struct ubi_attach_info *scan_all(struct ubi_device *ubi)
  {
        int err, pnum;
        struct rb_node *rb1, *rb2;
 -      struct ubi_scan_volume *sv;
 -      struct ubi_scan_leb *seb;
 -      struct ubi_scan_info *si;
 +      struct ubi_ainf_volume *av;
 +      struct ubi_ainf_peb *aeb;
 +      struct ubi_attach_info *ai;
  
 -      si = kzalloc(sizeof(struct ubi_scan_info), GFP_KERNEL);
 -      if (!si)
 +      ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
 +      if (!ai)
                return ERR_PTR(-ENOMEM);
  
 -      INIT_LIST_HEAD(&si->corr);
 -      INIT_LIST_HEAD(&si->free);
 -      INIT_LIST_HEAD(&si->erase);
 -      INIT_LIST_HEAD(&si->alien);
 -      si->volumes = RB_ROOT;
 +      INIT_LIST_HEAD(&ai->corr);
 +      INIT_LIST_HEAD(&ai->free);
 +      INIT_LIST_HEAD(&ai->erase);
 +      INIT_LIST_HEAD(&ai->alien);
 +      ai->volumes = RB_ROOT;
  
        err = -ENOMEM;
 -      si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab",
 -                                            sizeof(struct ubi_scan_leb),
 -                                            0, 0, NULL);
 -      if (!si->scan_leb_slab)
 -              goto out_si;
 +      ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
 +                                             sizeof(struct ubi_ainf_peb),
 +                                             0, 0, NULL);
 +      if (!ai->aeb_slab_cache)
 +              goto out_ai;
  
        ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
        if (!ech)
 -              goto out_si;
 +              goto out_ai;
  
        vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
        if (!vidh)
                cond_resched();
  
                dbg_gen("process PEB %d", pnum);
 -              err = process_eb(ubi, si, pnum);
 +              err = scan_peb(ubi, ai, pnum);
                if (err < 0)
                        goto out_vidh;
        }
        dbg_msg("scanning is finished");
  
        /* Calculate mean erase counter */
 -      if (si->ec_count)
 -              si->mean_ec = div_u64(si->ec_sum, si->ec_count);
 +      if (ai->ec_count)
 +              ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
  
 -      err = check_what_we_have(ubi, si);
 +      err = late_analysis(ubi, ai);
        if (err)
                goto out_vidh;
  
         * In case of unknown erase counter we use the mean erase counter
         * value.
         */
 -      ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
 -              ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb)
 -                      if (seb->ec == UBI_SCAN_UNKNOWN_EC)
 -                              seb->ec = si->mean_ec;
 +      ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
 +              ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
 +                      if (aeb->ec == UBI_UNKNOWN)
 +                              aeb->ec = ai->mean_ec;
        }
  
 -      list_for_each_entry(seb, &si->free, u.list) {
 -              if (seb->ec == UBI_SCAN_UNKNOWN_EC)
 -                      seb->ec = si->mean_ec;
 +      list_for_each_entry(aeb, &ai->free, u.list) {
 +              if (aeb->ec == UBI_UNKNOWN)
 +                      aeb->ec = ai->mean_ec;
        }
  
 -      list_for_each_entry(seb, &si->corr, u.list)
 -              if (seb->ec == UBI_SCAN_UNKNOWN_EC)
 -                      seb->ec = si->mean_ec;
 +      list_for_each_entry(aeb, &ai->corr, u.list)
 +              if (aeb->ec == UBI_UNKNOWN)
 +                      aeb->ec = ai->mean_ec;
  
 -      list_for_each_entry(seb, &si->erase, u.list)
 -              if (seb->ec == UBI_SCAN_UNKNOWN_EC)
 -                      seb->ec = si->mean_ec;
 +      list_for_each_entry(aeb, &ai->erase, u.list)
 +              if (aeb->ec == UBI_UNKNOWN)
 +                      aeb->ec = ai->mean_ec;
  
 -      err = paranoid_check_si(ubi, si);
 +      err = self_check_ai(ubi, ai);
        if (err)
                goto out_vidh;
  
        ubi_free_vid_hdr(ubi, vidh);
        kfree(ech);
  
 -      return si;
 +      return ai;
  
  out_vidh:
        ubi_free_vid_hdr(ubi, vidh);
  out_ech:
        kfree(ech);
 -out_si:
 -      ubi_scan_destroy_si(si);
 +out_ai:
 +      ubi_destroy_ai(ai);
        return ERR_PTR(err);
  }
  
  /**
 - * destroy_sv - free the scanning volume information
 - * @sv: scanning volume information
 - * @si: scanning information
 + * ubi_attach - attach an MTD device.
 + * @ubi: UBI device descriptor
   *
 - * This function destroys the volume RB-tree (@sv->root) and the scanning
 - * volume information.
 + * This function returns zero in case of success and a negative error code in
 + * case of failure.
   */
 -static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
 +int ubi_attach(struct ubi_device *ubi)
  {
 -      struct ubi_scan_leb *seb;
 -      struct rb_node *this = sv->root.rb_node;
 +      int err;
 +      struct ubi_attach_info *ai;
 +
 +      ai = scan_all(ubi);
 +      if (IS_ERR(ai))
 +              return PTR_ERR(ai);
 +
 +      ubi->bad_peb_count = ai->bad_peb_count;
 +      ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
 +      ubi->corr_peb_count = ai->corr_peb_count;
 +      ubi->max_ec = ai->max_ec;
 +      ubi->mean_ec = ai->mean_ec;
 +      ubi_msg("max. sequence number:       %llu", ai->max_sqnum);
 +
 +      err = ubi_read_volume_table(ubi, ai);
 +      if (err)
 +              goto out_ai;
 +
 +      err = ubi_wl_init(ubi, ai);
 +      if (err)
 +              goto out_vtbl;
 +
 +      err = ubi_eba_init(ubi, ai);
 +      if (err)
 +              goto out_wl;
 +
 +      ubi_destroy_ai(ai);
 +      return 0;
 +
 +out_wl:
 +      ubi_wl_close(ubi);
 +out_vtbl:
 +      ubi_free_internal_volumes(ubi);
 +      vfree(ubi->vtbl);
 +out_ai:
 +      ubi_destroy_ai(ai);
 +      return err;
 +}
 +
 +/**
 + * destroy_av - free volume attaching information.
 + * @av: volume attaching information
 + * @ai: attaching information
 + *
 + * This function destroys the volume attaching information.
 + */
 +static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
 +{
 +      struct ubi_ainf_peb *aeb;
 +      struct rb_node *this = av->root.rb_node;
  
        while (this) {
                if (this->rb_left)
                else if (this->rb_right)
                        this = this->rb_right;
                else {
 -                      seb = rb_entry(this, struct ubi_scan_leb, u.rb);
 +                      aeb = rb_entry(this, struct ubi_ainf_peb, u.rb);
                        this = rb_parent(this);
                        if (this) {
 -                              if (this->rb_left == &seb->u.rb)
 +                              if (this->rb_left == &aeb->u.rb)
                                        this->rb_left = NULL;
                                else
                                        this->rb_right = NULL;
                        }
  
 -                      kmem_cache_free(si->scan_leb_slab, seb);
 +                      kmem_cache_free(ai->aeb_slab_cache, aeb);
                }
        }
 -      kfree(sv);
 +      kfree(av);
  }
  
  /**
 - * ubi_scan_destroy_si - destroy scanning information.
 - * @si: scanning information
 + * ubi_destroy_ai - destroy attaching information.
 + * @ai: attaching information
   */
 -void ubi_scan_destroy_si(struct ubi_scan_info *si)
 +void ubi_destroy_ai(struct ubi_attach_info *ai)
  {
 -      struct ubi_scan_leb *seb, *seb_tmp;
 -      struct ubi_scan_volume *sv;
 +      struct ubi_ainf_peb *aeb, *aeb_tmp;
 +      struct ubi_ainf_volume *av;
        struct rb_node *rb;
  
 -      list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) {
 -              list_del(&seb->u.list);
 -              kmem_cache_free(si->scan_leb_slab, seb);
 +      list_for_each_entry_safe(aeb, aeb_tmp, &ai->alien, u.list) {
 +              list_del(&aeb->u.list);
 +              kmem_cache_free(ai->aeb_slab_cache, aeb);
        }
 -      list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) {
 -              list_del(&seb->u.list);
 -              kmem_cache_free(si->scan_leb_slab, seb);
 +      list_for_each_entry_safe(aeb, aeb_tmp, &ai->erase, u.list) {
 +              list_del(&aeb->u.list);
 +              kmem_cache_free(ai->aeb_slab_cache, aeb);
        }
 -      list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) {
 -              list_del(&seb->u.list);
 -              kmem_cache_free(si->scan_leb_slab, seb);
 +      list_for_each_entry_safe(aeb, aeb_tmp, &ai->corr, u.list) {
 +              list_del(&aeb->u.list);
 +              kmem_cache_free(ai->aeb_slab_cache, aeb);
        }
 -      list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) {
 -              list_del(&seb->u.list);
 -              kmem_cache_free(si->scan_leb_slab, seb);
 +      list_for_each_entry_safe(aeb, aeb_tmp, &ai->free, u.list) {
 +              list_del(&aeb->u.list);
 +              kmem_cache_free(ai->aeb_slab_cache, aeb);
        }
  
        /* Destroy the volume RB-tree */
 -      rb = si->volumes.rb_node;
 +      rb = ai->volumes.rb_node;
        while (rb) {
                if (rb->rb_left)
                        rb = rb->rb_left;
                else if (rb->rb_right)
                        rb = rb->rb_right;
                else {
 -                      sv = rb_entry(rb, struct ubi_scan_volume, rb);
 +                      av = rb_entry(rb, struct ubi_ainf_volume, rb);
  
                        rb = rb_parent(rb);
                        if (rb) {
 -                              if (rb->rb_left == &sv->rb)
 +                              if (rb->rb_left == &av->rb)
                                        rb->rb_left = NULL;
                                else
                                        rb->rb_right = NULL;
                        }
  
 -                      destroy_sv(si, sv);
 +                      destroy_av(ai, av);
                }
        }
  
 -      if (si->scan_leb_slab)
 -              kmem_cache_destroy(si->scan_leb_slab);
 +      if (ai->aeb_slab_cache)
 +              kmem_cache_destroy(ai->aeb_slab_cache);
  
 -      kfree(si);
 +      kfree(ai);
  }
  
 -#ifdef CONFIG_MTD_UBI_DEBUG
 -
  /**
 - * paranoid_check_si - check the scanning information.
 + * self_check_ai - check the attaching information.
   * @ubi: UBI device description object
 - * @si: scanning information
 + * @ai: attaching information
   *
 - * This function returns zero if the scanning information is all right, and a
 + * This function returns zero if the attaching information is all right, and a
   * negative error code if not or if an error occurred.
   */
 -static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
 +static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
  {
        int pnum, err, vols_found = 0;
        struct rb_node *rb1, *rb2;
 -      struct ubi_scan_volume *sv;
 -      struct ubi_scan_leb *seb, *last_seb;
 +      struct ubi_ainf_volume *av;
 +      struct ubi_ainf_peb *aeb, *last_aeb;
        uint8_t *buf;
  
        if (!ubi->dbg->chk_gen)
                return 0;
  
        /*
 -       * At first, check that scanning information is OK.
 +       * At first, check that attaching information is OK.
         */
 -      ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
 +      ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
                int leb_count = 0;
  
                cond_resched();
  
                vols_found += 1;
  
 -              if (si->is_empty) {
 +              if (ai->is_empty) {
                        ubi_err("bad is_empty flag");
 -                      goto bad_sv;
 +                      goto bad_av;
                }
  
 -              if (sv->vol_id < 0 || sv->highest_lnum < 0 ||
 -                  sv->leb_count < 0 || sv->vol_type < 0 || sv->used_ebs < 0 ||
 -                  sv->data_pad < 0 || sv->last_data_size < 0) {
 +              if (av->vol_id < 0 || av->highest_lnum < 0 ||
 +                  av->leb_count < 0 || av->vol_type < 0 || av->used_ebs < 0 ||
 +                  av->data_pad < 0 || av->last_data_size < 0) {
                        ubi_err("negative values");
 -                      goto bad_sv;
 +                      goto bad_av;
                }
  
 -              if (sv->vol_id >= UBI_MAX_VOLUMES &&
 -                  sv->vol_id < UBI_INTERNAL_VOL_START) {
 +              if (av->vol_id >= UBI_MAX_VOLUMES &&
 +                  av->vol_id < UBI_INTERNAL_VOL_START) {
                        ubi_err("bad vol_id");
 -                      goto bad_sv;
 +                      goto bad_av;
                }
  
 -              if (sv->vol_id > si->highest_vol_id) {
 +              if (av->vol_id > ai->highest_vol_id) {
                        ubi_err("highest_vol_id is %d, but vol_id %d is there",
 -                              si->highest_vol_id, sv->vol_id);
 +                              ai->highest_vol_id, av->vol_id);
                        goto out;
                }
  
 -              if (sv->vol_type != UBI_DYNAMIC_VOLUME &&
 -                  sv->vol_type != UBI_STATIC_VOLUME) {
 +              if (av->vol_type != UBI_DYNAMIC_VOLUME &&
 +                  av->vol_type != UBI_STATIC_VOLUME) {
                        ubi_err("bad vol_type");
 -                      goto bad_sv;
 +                      goto bad_av;
                }
  
 -              if (sv->data_pad > ubi->leb_size / 2) {
 +              if (av->data_pad > ubi->leb_size / 2) {
                        ubi_err("bad data_pad");
 -                      goto bad_sv;
 +                      goto bad_av;
                }
  
 -              last_seb = NULL;
 -              ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
 +              last_aeb = NULL;
 +              ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
                        cond_resched();
  
 -                      last_seb = seb;
 +                      last_aeb = aeb;
                        leb_count += 1;
  
 -                      if (seb->pnum < 0 || seb->ec < 0) {
 +                      if (aeb->pnum < 0 || aeb->ec < 0) {
                                ubi_err("negative values");
 -                              goto bad_seb;
 +                              goto bad_aeb;
                        }
  
 -                      if (seb->ec < si->min_ec) {
 -                              ubi_err("bad si->min_ec (%d), %d found",
 -                                      si->min_ec, seb->ec);
 -                              goto bad_seb;
 +                      if (aeb->ec < ai->min_ec) {
 +                              ubi_err("bad ai->min_ec (%d), %d found",
 +                                      ai->min_ec, aeb->ec);
 +                              goto bad_aeb;
                        }
  
 -                      if (seb->ec > si->max_ec) {
 -                              ubi_err("bad si->max_ec (%d), %d found",
 -                                      si->max_ec, seb->ec);
 -                              goto bad_seb;
 +                      if (aeb->ec > ai->max_ec) {
 +                              ubi_err("bad ai->max_ec (%d), %d found",
 +                                      ai->max_ec, aeb->ec);
 +                              goto bad_aeb;
                        }
  
 -                      if (seb->pnum >= ubi->peb_count) {
 +                      if (aeb->pnum >= ubi->peb_count) {
                                ubi_err("too high PEB number %d, total PEBs %d",
 -                                      seb->pnum, ubi->peb_count);
 -                              goto bad_seb;
 +                                      aeb->pnum, ubi->peb_count);
 +                              goto bad_aeb;
                        }
  
 -                      if (sv->vol_type == UBI_STATIC_VOLUME) {
 -                              if (seb->lnum >= sv->used_ebs) {
 +                      if (av->vol_type == UBI_STATIC_VOLUME) {
 +                              if (aeb->lnum >= av->used_ebs) {
                                        ubi_err("bad lnum or used_ebs");
 -                                      goto bad_seb;
 +                                      goto bad_aeb;
                                }
                        } else {
 -                              if (sv->used_ebs != 0) {
 +                              if (av->used_ebs != 0) {
                                        ubi_err("non-zero used_ebs");
 -                                      goto bad_seb;
 +                                      goto bad_aeb;
                                }
                        }
  
 -                      if (seb->lnum > sv->highest_lnum) {
 +                      if (aeb->lnum > av->highest_lnum) {
                                ubi_err("incorrect highest_lnum or lnum");
 -                              goto bad_seb;
 +                              goto bad_aeb;
                        }
                }
  
 -              if (sv->leb_count != leb_count) {
 +              if (av->leb_count != leb_count) {
                        ubi_err("bad leb_count, %d objects in the tree",
                                leb_count);
 -                      goto bad_sv;
 +                      goto bad_av;
                }
  
 -              if (!last_seb)
 +              if (!last_aeb)
                        continue;
  
 -              seb = last_seb;
 +              aeb = last_aeb;
  
 -              if (seb->lnum != sv->highest_lnum) {
 +              if (aeb->lnum != av->highest_lnum) {
                        ubi_err("bad highest_lnum");
 -                      goto bad_seb;
 +                      goto bad_aeb;
                }
        }
  
 -      if (vols_found != si->vols_found) {
 -              ubi_err("bad si->vols_found %d, should be %d",
 -                      si->vols_found, vols_found);
 +      if (vols_found != ai->vols_found) {
 +              ubi_err("bad ai->vols_found %d, should be %d",
 +                      ai->vols_found, vols_found);
                goto out;
        }
  
 -      /* Check that scanning information is correct */
 -      ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
 -              last_seb = NULL;
 -              ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
 +      /* Check that attaching information is correct */
 +      ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
 +              last_aeb = NULL;
 +              ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
                        int vol_type;
  
                        cond_resched();
  
 -                      last_seb = seb;
 +                      last_aeb = aeb;
  
 -                      err = ubi_io_read_vid_hdr(ubi, seb->pnum, vidh, 1);
 +                      err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidh, 1);
                        if (err && err != UBI_IO_BITFLIPS) {
                                ubi_err("VID header is not OK (%d)", err);
                                if (err > 0)
  
                        vol_type = vidh->vol_type == UBI_VID_DYNAMIC ?
                                   UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
 -                      if (sv->vol_type != vol_type) {
 +                      if (av->vol_type != vol_type) {
                                ubi_err("bad vol_type");
                                goto bad_vid_hdr;
                        }
  
 -                      if (seb->sqnum != be64_to_cpu(vidh->sqnum)) {
 -                              ubi_err("bad sqnum %llu", seb->sqnum);
 +                      if (aeb->sqnum != be64_to_cpu(vidh->sqnum)) {
 +                              ubi_err("bad sqnum %llu", aeb->sqnum);
                                goto bad_vid_hdr;
                        }
  
 -                      if (sv->vol_id != be32_to_cpu(vidh->vol_id)) {
 -                              ubi_err("bad vol_id %d", sv->vol_id);
 +                      if (av->vol_id != be32_to_cpu(vidh->vol_id)) {
 +                              ubi_err("bad vol_id %d", av->vol_id);
                                goto bad_vid_hdr;
                        }
  
 -                      if (sv->compat != vidh->compat) {
 +                      if (av->compat != vidh->compat) {
                                ubi_err("bad compat %d", vidh->compat);
                                goto bad_vid_hdr;
                        }
  
 -                      if (seb->lnum != be32_to_cpu(vidh->lnum)) {
 -                              ubi_err("bad lnum %d", seb->lnum);
 +                      if (aeb->lnum != be32_to_cpu(vidh->lnum)) {
 +                              ubi_err("bad lnum %d", aeb->lnum);
                                goto bad_vid_hdr;
                        }
  
 -                      if (sv->used_ebs != be32_to_cpu(vidh->used_ebs)) {
 -                              ubi_err("bad used_ebs %d", sv->used_ebs);
 +                      if (av->used_ebs != be32_to_cpu(vidh->used_ebs)) {
 +                              ubi_err("bad used_ebs %d", av->used_ebs);
                                goto bad_vid_hdr;
                        }
  
 -                      if (sv->data_pad != be32_to_cpu(vidh->data_pad)) {
 -                              ubi_err("bad data_pad %d", sv->data_pad);
 +                      if (av->data_pad != be32_to_cpu(vidh->data_pad)) {
 +                              ubi_err("bad data_pad %d", av->data_pad);
                                goto bad_vid_hdr;
                        }
                }
  
 -              if (!last_seb)
 +              if (!last_aeb)
                        continue;
  
 -              if (sv->highest_lnum != be32_to_cpu(vidh->lnum)) {
 -                      ubi_err("bad highest_lnum %d", sv->highest_lnum);
 +              if (av->highest_lnum != be32_to_cpu(vidh->lnum)) {
 +                      ubi_err("bad highest_lnum %d", av->highest_lnum);
                        goto bad_vid_hdr;
                }
  
 -              if (sv->last_data_size != be32_to_cpu(vidh->data_size)) {
 -                      ubi_err("bad last_data_size %d", sv->last_data_size);
 +              if (av->last_data_size != be32_to_cpu(vidh->data_size)) {
 +                      ubi_err("bad last_data_size %d", av->last_data_size);
                        goto bad_vid_hdr;
                }
        }
                        buf[pnum] = 1;
        }
  
 -      ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb)
 -              ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb)
 -                      buf[seb->pnum] = 1;
 +      ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
 +              ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
 +                      buf[aeb->pnum] = 1;
  
 -      list_for_each_entry(seb, &si->free, u.list)
 -              buf[seb->pnum] = 1;
 +      list_for_each_entry(aeb, &ai->free, u.list)
 +              buf[aeb->pnum] = 1;
  
 -      list_for_each_entry(seb, &si->corr, u.list)
 -              buf[seb->pnum] = 1;
 +      list_for_each_entry(aeb, &ai->corr, u.list)
 +              buf[aeb->pnum] = 1;
  
 -      list_for_each_entry(seb, &si->erase, u.list)
 -              buf[seb->pnum] = 1;
 +      list_for_each_entry(aeb, &ai->erase, u.list)
 +              buf[aeb->pnum] = 1;
  
 -      list_for_each_entry(seb, &si->alien, u.list)
 -              buf[seb->pnum] = 1;
 +      list_for_each_entry(aeb, &ai->alien, u.list)
 +              buf[aeb->pnum] = 1;
  
        err = 0;
        for (pnum = 0; pnum < ubi->peb_count; pnum++)
                goto out;
        return 0;
  
 -bad_seb:
 -      ubi_err("bad scanning information about LEB %d", seb->lnum);
 -      ubi_dbg_dump_seb(seb, 0);
 -      ubi_dbg_dump_sv(sv);
 +bad_aeb:
 +      ubi_err("bad attaching information about LEB %d", aeb->lnum);
 +      ubi_dump_aeb(aeb, 0);
 +      ubi_dump_av(av);
        goto out;
  
 -bad_sv:
 -      ubi_err("bad scanning information about volume %d", sv->vol_id);
 -      ubi_dbg_dump_sv(sv);
 +bad_av:
 +      ubi_err("bad attaching information about volume %d", av->vol_id);
 +      ubi_dump_av(av);
        goto out;
  
  bad_vid_hdr:
 -      ubi_err("bad scanning information about volume %d", sv->vol_id);
 -      ubi_dbg_dump_sv(sv);
 -      ubi_dbg_dump_vid_hdr(vidh);
 +      ubi_err("bad attaching information about volume %d", av->vol_id);
 +      ubi_dump_av(av);
 +      ubi_dump_vid_hdr(vidh);
  
  out:
 -      ubi_dbg_dump_stack();
 +      dump_stack();
        return -EINVAL;
  }
 -
 -#endif /* CONFIG_MTD_UBI_DEBUG */
diff --combined drivers/mtd/ubi/build.c
   * module load parameters or the kernel boot parameters. If MTD devices were
   * specified, UBI does not attach any MTD device, but it is possible to do
   * later using the "UBI control device".
 - *
 - * At the moment we only attach UBI devices by scanning, which will become a
 - * bottleneck when flashes reach certain large size. Then one may improve UBI
 - * and add other methods, although it does not seem to be easy to do.
   */
  
  #include <linux/err.h>
@@@ -550,10 -554,10 +550,10 @@@ static void uif_close(struct ubi_devic
  }
  
  /**
 - * free_internal_volumes - free internal volumes.
 + * ubi_free_internal_volumes - free internal volumes.
   * @ubi: UBI device description object
   */
 -static void free_internal_volumes(struct ubi_device *ubi)
 +void ubi_free_internal_volumes(struct ubi_device *ubi)
  {
        int i;
  
        }
  }
  
 -/**
 - * attach_by_scanning - attach an MTD device using scanning method.
 - * @ubi: UBI device descriptor
 - *
 - * This function returns zero in case of success and a negative error code in
 - * case of failure.
 - *
 - * Note, currently this is the only method to attach UBI devices. Hopefully in
 - * the future we'll have more scalable attaching methods and avoid full media
 - * scanning. But even in this case scanning will be needed as a fall-back
 - * attaching method if there are some on-flash table corruptions.
 - */
 -static int attach_by_scanning(struct ubi_device *ubi)
 -{
 -      int err;
 -      struct ubi_scan_info *si;
 -
 -      si = ubi_scan(ubi);
 -      if (IS_ERR(si))
 -              return PTR_ERR(si);
 -
 -      ubi->bad_peb_count = si->bad_peb_count;
 -      ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
 -      ubi->corr_peb_count = si->corr_peb_count;
 -      ubi->max_ec = si->max_ec;
 -      ubi->mean_ec = si->mean_ec;
 -      ubi_msg("max. sequence number:       %llu", si->max_sqnum);
 -
 -      err = ubi_read_volume_table(ubi, si);
 -      if (err)
 -              goto out_si;
 -
 -      err = ubi_wl_init_scan(ubi, si);
 -      if (err)
 -              goto out_vtbl;
 -
 -      err = ubi_eba_init_scan(ubi, si);
 -      if (err)
 -              goto out_wl;
 -
 -      ubi_scan_destroy_si(si);
 -      return 0;
 -
 -out_wl:
 -      ubi_wl_close(ubi);
 -out_vtbl:
 -      free_internal_volumes(ubi);
 -      vfree(ubi->vtbl);
 -out_si:
 -      ubi_scan_destroy_si(si);
 -      return err;
 -}
 -
  /**
   * io_init - initialize I/O sub-system for a given UBI device.
   * @ubi: UBI device description object
@@@ -733,11 -790,11 +733,11 @@@ static int io_init(struct ubi_device *u
        ubi_msg("data offset:                %d", ubi->leb_start);
  
        /*
 -       * Note, ideally, we have to initialize ubi->bad_peb_count here. But
 +       * Note, ideally, we have to initialize @ubi->bad_peb_count here. But
         * unfortunately, MTD does not provide this information. We should loop
         * over all physical eraseblocks and invoke mtd->block_is_bad() for
 -       * each physical eraseblock. So, we skip ubi->bad_peb_count
 -       * uninitialized and initialize it after scanning.
 +       * each physical eraseblock. So, we leave @ubi->bad_peb_count
 +       * uninitialized so far.
         */
  
        return 0;
   * @ubi: UBI device description object
   * @vol_id: ID of the volume to re-size
   *
 - * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in
 + * This function re-sizes the volume marked by the %UBI_VTBL_AUTORESIZE_FLG in
   * the volume table to the largest possible size. See comments in ubi-header.h
   * for more description of the flag. Returns zero in case of success and a
   * negative error code in case of failure.
@@@ -759,6 -816,11 +759,11 @@@ static int autoresize(struct ubi_devic
        struct ubi_volume *vol = ubi->volumes[vol_id];
        int err, old_reserved_pebs = vol->reserved_pebs;
  
+       if (ubi->ro_mode) {
+               ubi_warn("skip auto-resize because of R/O mode");
+               return 0;
+       }
        /*
         * Clear the auto-resize flag in the volume in-memory copy of the
         * volume table, and 'ubi_resize_volume()' will propagate this change
@@@ -824,7 -886,7 +829,7 @@@ int ubi_attach_mtd_dev(struct mtd_info 
        for (i = 0; i < UBI_MAX_DEVICES; i++) {
                ubi = ubi_devices[i];
                if (ubi && mtd->index == ubi->mtd->index) {
 -                      dbg_err("mtd%d is already attached to ubi%d",
 +                      ubi_err("mtd%d is already attached to ubi%d",
                                mtd->index, i);
                        return -EEXIST;
                }
                        if (!ubi_devices[ubi_num])
                                break;
                if (ubi_num == UBI_MAX_DEVICES) {
 -                      dbg_err("only %d UBI devices may be created",
 +                      ubi_err("only %d UBI devices may be created",
                                UBI_MAX_DEVICES);
                        return -ENFILE;
                }
  
                /* Make sure ubi_num is not busy */
                if (ubi_devices[ubi_num]) {
 -                      dbg_err("ubi%d already exists", ubi_num);
 +                      ubi_err("ubi%d already exists", ubi_num);
                        return -EEXIST;
                }
        }
        spin_lock_init(&ubi->volumes_lock);
  
        ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
 -      dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
 +      dbg_msg("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
        dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
  
        err = io_init(ubi);
                goto out_free;
  
        err = -ENOMEM;
 -      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)
 +      ubi->peb_buf = vmalloc(ubi->peb_size);
 +      if (!ubi->peb_buf)
                goto out_free;
  
        err = ubi_debugging_init_dev(ubi);
        if (err)
                goto out_free;
  
 -      err = attach_by_scanning(ubi);
 +      err = ubi_attach(ubi);
        if (err) {
 -              dbg_err("failed to attach by scanning, error %d", err);
 +              ubi_err("failed to attach mtd%d, error %d", mtd->index, err);
                goto out_debugging;
        }
  
@@@ -963,12 -1029,13 +968,12 @@@ out_uif
        uif_close(ubi);
  out_detach:
        ubi_wl_close(ubi);
 -      free_internal_volumes(ubi);
 +      ubi_free_internal_volumes(ubi);
        vfree(ubi->vtbl);
  out_debugging:
        ubi_debugging_exit_dev(ubi);
  out_free:
 -      vfree(ubi->peb_buf1);
 -      vfree(ubi->peb_buf2);
 +      vfree(ubi->peb_buf);
        if (ref)
                put_device(&ubi->dev);
        else
@@@ -1035,11 -1102,12 +1040,11 @@@ int ubi_detach_mtd_dev(int ubi_num, in
        ubi_debugfs_exit_dev(ubi);
        uif_close(ubi);
        ubi_wl_close(ubi);
 -      free_internal_volumes(ubi);
 +      ubi_free_internal_volumes(ubi);
        vfree(ubi->vtbl);
        put_mtd_device(ubi->mtd);
        ubi_debugging_exit_dev(ubi);
 -      vfree(ubi->peb_buf1);
 -      vfree(ubi->peb_buf2);
 +      vfree(ubi->peb_buf);
        ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
        put_device(&ubi->dev);
        return 0;
@@@ -137,9 -137,6 +137,9 @@@ static int musb_ulpi_read(struct otg_tr
        int     i = 0;
        u8      r;
        u8      power;
 +      int     ret;
 +
 +      pm_runtime_get_sync(otg->io_dev);
  
        /* Make sure the transceiver is not in low power mode */
        power = musb_readb(addr, MUSB_POWER);
        while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
                                & MUSB_ULPI_REG_CMPLT)) {
                i++;
 -              if (i == 10000)
 -                      return -ETIMEDOUT;
 +              if (i == 10000) {
 +                      ret = -ETIMEDOUT;
 +                      goto out;
 +              }
  
        }
        r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
        r &= ~MUSB_ULPI_REG_CMPLT;
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
  
 -      return musb_readb(addr, MUSB_ULPI_REG_DATA);
 +      ret = musb_readb(addr, MUSB_ULPI_REG_DATA);
 +
 +out:
 +      pm_runtime_put(otg->io_dev);
 +
 +      return ret;
  }
  
  static int musb_ulpi_write(struct otg_transceiver *otg,
        int     i = 0;
        u8      r = 0;
        u8      power;
 +      int     ret = 0;
 +
 +      pm_runtime_get_sync(otg->io_dev);
  
        /* Make sure the transceiver is not in low power mode */
        power = musb_readb(addr, MUSB_POWER);
        while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
                                & MUSB_ULPI_REG_CMPLT)) {
                i++;
 -              if (i == 10000)
 -                      return -ETIMEDOUT;
 +              if (i == 10000) {
 +                      ret = -ETIMEDOUT;
 +                      goto out;
 +              }
        }
  
        r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
        r &= ~MUSB_ULPI_REG_CMPLT;
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
  
 -      return 0;
 +out:
 +      pm_runtime_put(otg->io_dev);
 +
 +      return ret;
  }
  #else
  #define musb_ulpi_read                NULL
@@@ -672,15 -654,6 +672,15 @@@ static irqreturn_t musb_stage0_irq(stru
                        musb->is_active = 0;
                        break;
                }
 +
 +              switch (musb->xceiv->state) {
 +              case OTG_STATE_B_IDLE:
 +              case OTG_STATE_B_PERIPHERAL:
 +                      cancel_delayed_work(&musb->vbus_workaround_work);
 +                      schedule_delayed_work(&musb->vbus_workaround_work, HZ / 2);
 +              default:
 +                      break;
 +              }
        }
  
        if (int_usb & MUSB_INTR_CONNECT) {
@@@ -1009,9 -982,6 +1009,9 @@@ static void musb_shutdown(struct platfo
        unsigned long   flags;
  
        pm_runtime_get_sync(musb->controller);
 +
 +      musb_gadget_cleanup(musb);
 +
        spin_lock_irqsave(&musb->lock, flags);
        musb_platform_disable(musb);
        musb_generic_disable(musb);
        musb_platform_exit(musb);
  
        pm_runtime_put(musb->controller);
 +
 +      cancel_delayed_work(&musb->vbus_workaround_work);
 +
        /* FIXME power down */
  }
  
@@@ -1803,41 -1770,6 +1803,41 @@@ static void musb_irq_work(struct work_s
        }
  }
  
 +#include <linux/usb/ulpi.h>
 +
 +static void musb_vbus_workaround_work(struct work_struct *work)
 +{
 +      struct musb *musb = container_of(work, struct musb, vbus_workaround_work.work);
 +      u8 devctl;
 +      int ret;
 +
 +      if (musb_ulpi_access.write == NULL)
 +              return;
 +
 +      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +
 +      /*
 +       * I don't really know why but VBUS sometimes gets stuck and
 +       * causes session to never end. It would look like some pullup
 +       * is enabled when it shouldn't be on certain PHY states.
 +       * Turning on pulldowns magically drains VBUS to zero and allows
 +       * session to end, so let's do that here.
 +       *
 +       * XXX: probably better check VBUS on TWL?
 +       * beagle sometimes has session bit set but no VBUS on twl?
 +       */
 +      if ((musb->xceiv->state == OTG_STATE_B_PERIPHERAL ||
 +           musb->xceiv->state == OTG_STATE_B_IDLE) &&
 +          (devctl & MUSB_DEVCTL_VBUS) != (3 << MUSB_DEVCTL_VBUS_SHIFT) &&
 +          (devctl & MUSB_DEVCTL_VBUS) != (0 << MUSB_DEVCTL_VBUS_SHIFT)) {
 +              dev_dbg(musb->controller, "VBUS workaround..\n");
 +              ret = musb_ulpi_access.write(musb->xceiv, ULPI_SET(ULPI_OTG_CTRL),
 +                      ULPI_OTG_CTRL_DM_PULLDOWN | ULPI_OTG_CTRL_DP_PULLDOWN);
 +              //if (ret)
 +              //      dev_err(musb->controller, "VBUS workaround error\n");
 +      }
 +}
 +
  /* --------------------------------------------------------------------------
   * Init support
   */
@@@ -1895,6 -1827,8 +1895,6 @@@ static void musb_free(struct musb *musb
        sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
  #endif
  
 -      musb_gadget_cleanup(musb);
 -
        if (musb->nIrq >= 0) {
                if (musb->irq_wake)
                        disable_irq_wake(musb->nIrq);
@@@ -1973,7 -1907,6 +1973,7 @@@ musb_init_controller(struct device *dev
        }
  
        if (!musb->xceiv->io_ops) {
 +              musb->xceiv->io_dev = musb->controller;
                musb->xceiv->io_priv = musb->mregs;
                musb->xceiv->io_ops = &musb_ulpi_access;
        }
        /* Init IRQ workqueue before request_irq */
        INIT_WORK(&musb->irq_work, musb_irq_work);
  
 +      INIT_DELAYED_WORK(&musb->vbus_workaround_work, musb_vbus_workaround_work);
 +
        /* attach to the IRQ */
        if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
                dev_err(dev, "request_irq %d failed!\n", nIrq);
        if (status < 0)
                goto fail3;
  
 +      pm_runtime_put(musb->controller);
 +
        status = musb_init_debugfs(musb);
        if (status < 0)
                goto fail4;
@@@ -2182,9 -2111,11 +2182,9 @@@ static int __exit musb_remove(struct pl
         *  - Peripheral mode: peripheral is deactivated (or never-activated)
         *  - OTG mode: both roles are deactivated (or never-activated)
         */
 -      pm_runtime_get_sync(musb->controller);
        musb_exit_debugfs(musb);
        musb_shutdown(pdev);
  
 -      pm_runtime_put(musb->controller);
        musb_free(musb);
        iounmap(ctrl_base);
        device_init_wakeup(&pdev->dev, 0);
@@@ -2225,7 -2156,6 +2225,7 @@@ static void musb_save_context(struct mu
                if (!epio)
                        continue;
  
 +              musb_writeb(musb_base, MUSB_INDEX, i);
                musb->context.index_regs[i].txmaxp =
                        musb_readw(epio, MUSB_TXMAXP);
                musb->context.index_regs[i].txcsr =
@@@ -2301,7 -2231,6 +2301,7 @@@ static void musb_restore_context(struc
                if (!epio)
                        continue;
  
 +              musb_writeb(musb_base, MUSB_INDEX, i);
                musb_writew(epio, MUSB_TXMAXP,
                        musb->context.index_regs[i].txmaxp);
                musb_writew(epio, MUSB_TXCSR,
@@@ -2357,7 -2286,6 +2357,7 @@@ static int musb_suspend(struct device *
  {
        struct musb     *musb = dev_to_musb(dev);
        unsigned long   flags;
 +      int             ret = 0;
  
        spin_lock_irqsave(&musb->lock, flags);
  
                /* FIXME force disconnect unless we know USB will wake
                 * the system up quickly enough to respond ...
                 */
 +              /*
 +               * FIXME: musb must be already runtime suspended at this point.
 +               * If it's not, framework will try to suspend it late when
 +               * i2c will be off, and twl4030 will want to access it for it's
 +               * stuff, causing data abort.
 +               */
 +              int pm_usage_count =
 +                      atomic_read(&musb->controller->power.usage_count);
 +              if (pm_usage_count > 1) {
 +                      dev_err(dev, "can't suspend while still active, "
 +                              "try removing gadget drivers (usage_count %d)\n",
 +                              pm_usage_count);
 +                      ret = -EBUSY;
 +              }
        } else if (is_host_active(musb)) {
                /* we know all the children are suspended; sometimes
                 * they will even be wakeup-enabled.
        }
  
        spin_unlock_irqrestore(&musb->lock, flags);
 -      return 0;
 +      return ret;
  }
  
  static int musb_resume_noirq(struct device *dev)
@@@ -2458,10 -2372,7 +2458,7 @@@ static int __init musb_init(void
        if (usb_disabled())
                return 0;
  
-       pr_info("%s: version " MUSB_VERSION ", "
-               "?dma?"
-               ", "
-               "otg (peripheral+host)",
+       pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
                musb_driver_name);
        return platform_driver_probe(&musb_driver, musb_probe);
  }
diff --combined fs/exec.c
+++ b/fs/exec.c
@@@ -1095,7 -1095,8 +1095,8 @@@ int flush_old_exec(struct linux_binprm 
        bprm->mm = NULL;                /* We're using it now */
  
        set_fs(USER_DS);
-       current->flags &= ~(PF_RANDOMIZE | PF_KTHREAD);
+       current->flags &=
+               ~(PF_RANDOMIZE | PF_KTHREAD | PF_NOFREEZE | PF_FREEZER_NOSIG);
        flush_thread();
        current->personality &= ~bprm->per_clear;
  
@@@ -1201,9 -1202,24 +1202,24 @@@ void free_bprm(struct linux_binprm *bpr
                mutex_unlock(&current->signal->cred_guard_mutex);
                abort_creds(bprm->cred);
        }
+       /* If a binfmt changed the interp, free it. */
+       if (bprm->interp != bprm->filename)
+               kfree(bprm->interp);
        kfree(bprm);
  }
  
+ int bprm_change_interp(char *interp, struct linux_binprm *bprm)
+ {
+       /* If a binfmt changed the interp, free it first. */
+       if (bprm->interp != bprm->filename)
+               kfree(bprm->interp);
+       bprm->interp = kstrdup(interp, GFP_KERNEL);
+       if (!bprm->interp)
+               return -ENOMEM;
+       return 0;
+ }
+ EXPORT_SYMBOL(bprm_change_interp);
  /*
   * install the new credentials for this executable
   */
@@@ -2076,8 -2092,8 +2092,8 @@@ static int umh_pipe_setup(struct subpro
        fd_install(0, rp);
        spin_lock(&cf->file_lock);
        fdt = files_fdtable(cf);
 -      FD_SET(0, fdt->open_fds);
 -      FD_CLR(0, fdt->close_on_exec);
 +      __set_open_fd(0, fdt);
 +      __clear_close_on_exec(0, fdt);
        spin_unlock(&cf->file_lock);
  
        /* and disallow core files too */
diff --combined fs/ubifs/lprops.c
@@@ -300,8 -300,11 +300,11 @@@ void ubifs_add_to_cat(struct ubifs_inf
        default:
                ubifs_assert(0);
        }
        lprops->flags &= ~LPROPS_CAT_MASK;
        lprops->flags |= cat;
+       c->in_a_category_cnt += 1;
+       ubifs_assert(c->in_a_category_cnt <= c->main_lebs);
  }
  
  /**
@@@ -334,6 -337,9 +337,9 @@@ static void ubifs_remove_from_cat(struc
        default:
                ubifs_assert(0);
        }
+       c->in_a_category_cnt -= 1;
+       ubifs_assert(c->in_a_category_cnt >= 0);
  }
  
  /**
@@@ -447,7 -453,7 +453,7 @@@ static void change_category(struct ubif
        int new_cat = ubifs_categorize_lprops(c, lprops);
  
        if (old_cat == new_cat) {
 -              struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1];
 +              struct ubifs_lpt_heap *heap;
  
                /* lprops on a heap now must be moved up or down */
                if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT)
@@@ -846,9 -852,7 +852,9 @@@ const struct ubifs_lprops *ubifs_fast_f
        return lprops;
  }
  
 -#ifdef CONFIG_UBIFS_FS_DEBUG
 +/*
 + * Everything below is related to debugging.
 + */
  
  /**
   * dbg_check_cats - check category heaps and lists.
@@@ -1003,8 -1007,8 +1009,8 @@@ void dbg_check_heap(struct ubifs_info *
  out:
        if (err) {
                dbg_msg("failed cat %d hpos %d err %d", cat, i, err);
 -              dbg_dump_stack();
 -              dbg_dump_heap(c, heap, cat);
 +              dump_stack();
 +              ubifs_dump_heap(c, heap, cat);
        }
  }
  
@@@ -1111,8 -1115,8 +1117,8 @@@ static int scan_check_cb(struct ubifs_i
        if (IS_ERR(sleb)) {
                ret = PTR_ERR(sleb);
                if (ret == -EUCLEAN) {
 -                      dbg_dump_lprops(c);
 -                      dbg_dump_budg(c, &c->bi);
 +                      ubifs_dump_lprops(c);
 +                      ubifs_dump_budg(c, &c->bi);
                }
                goto out;
        }
@@@ -1239,7 -1243,7 +1245,7 @@@ out_print
        ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, "
                  "should be free %d, dirty %d",
                  lnum, lp->free, lp->dirty, lp->flags, free, dirty);
 -      dbg_dump_leb(c, lnum);
 +      ubifs_dump_leb(c, lnum);
  out_destroy:
        ubifs_scan_destroy(sleb);
        ret = -EINVAL;
@@@ -1317,3 -1321,5 +1323,3 @@@ int dbg_check_lprops(struct ubifs_info 
  out:
        return err;
  }
 -
 -#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --combined fs/ubifs/ubifs.h
@@@ -84,6 -84,9 +84,6 @@@
  #define INUM_WARN_WATERMARK 0xFFF00000
  #define INUM_WATERMARK      0xFFFFFF00
  
 -/* Largest key size supported in this implementation */
 -#define CUR_MAX_KEY_LEN UBIFS_SK_LEN
 -
  /* Maximum number of entries in each LPT (LEB category) heap */
  #define LPT_HEAP_SZ 256
  
@@@ -274,10 -277,10 +274,10 @@@ struct ubifs_old_idx 
  
  /* The below union makes it easier to deal with keys */
  union ubifs_key {
 -      uint8_t u8[CUR_MAX_KEY_LEN];
 -      uint32_t u32[CUR_MAX_KEY_LEN/4];
 -      uint64_t u64[CUR_MAX_KEY_LEN/8];
 -      __le32 j32[CUR_MAX_KEY_LEN/4];
 +      uint8_t u8[UBIFS_SK_LEN];
 +      uint32_t u32[UBIFS_SK_LEN/4];
 +      uint64_t u64[UBIFS_SK_LEN/8];
 +      __le32 j32[UBIFS_SK_LEN/4];
  };
  
  /**
@@@ -650,6 -653,8 +650,6 @@@ typedef int (*ubifs_lpt_scan_callback)(
   * @avail: number of bytes available in the write-buffer
   * @used:  number of used bytes in the write-buffer
   * @size: write-buffer size (in [@c->min_io_size, @c->max_write_size] range)
 - * @dtype: type of data stored in this LEB (%UBI_LONGTERM, %UBI_SHORTTERM,
 - * %UBI_UNKNOWN)
   * @jhead: journal head the mutex belongs to (note, needed only to shut lockdep
   *         up by 'mutex_lock_nested()).
   * @sync_callback: write-buffer synchronization callback
@@@ -683,6 -688,7 +683,6 @@@ struct ubifs_wbuf 
        int avail;
        int used;
        int size;
 -      int dtype;
        int jhead;
        int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad);
        struct mutex io_mutex;
@@@ -759,9 -765,6 +759,9 @@@ struct ubifs_zbranch 
   * @offs: offset of the corresponding indexing node
   * @len: length  of the corresponding indexing node
   * @zbranch: array of znode branches (@c->fanout elements)
 + *
 + * Note! The @lnum, @offs, and @len fields are not really needed - we have them
 + * only for internal consistency check. They could be removed to save some RAM.
   */
  struct ubifs_znode {
        struct ubifs_znode *parent;
        int child_cnt;
        int iip;
        int alt;
 -#ifdef CONFIG_UBIFS_FS_DEBUG
 -      int lnum, offs, len;
 -#endif
 +      int lnum;
 +      int offs;
 +      int len;
        struct ubifs_zbranch zbranch[];
  };
  
@@@ -1184,6 -1187,8 +1184,8 @@@ struct ubifs_debug_info
   * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size)
   * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size)
   * @freeable_cnt: number of freeable LEBs in @freeable_list
+  * @in_a_category_cnt: count of lprops which are in a certain category, which
+  *                     basically meants that they were loaded from the flash
   *
   * @ltab_lnum: LEB number of LPT's own lprops table
   * @ltab_offs: offset of LPT's own lprops table
@@@ -1413,6 -1418,7 +1415,7 @@@ struct ubifs_info 
        struct list_head freeable_list;
        struct list_head frdi_idx_list;
        int freeable_cnt;
+       int in_a_category_cnt;
  
        int ltab_lnum;
        int ltab_offs;
        struct rb_root size_tree;
        struct ubifs_mount_opts mount_opts;
  
 -#ifdef CONFIG_UBIFS_FS_DEBUG
        struct ubifs_debug_info *dbg;
 -#endif
  };
  
  extern struct list_head ubifs_infos;
@@@ -1466,20 -1474,22 +1469,20 @@@ void ubifs_ro_mode(struct ubifs_info *c
  int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
                   int len, int even_ebadmsg);
  int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
 -                  int len, int dtype);
 -int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
 -                   int dtype);
 +                  int len);
 +int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
  int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
 -int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype);
 +int ubifs_leb_map(struct ubifs_info *c, int lnum);
  int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
  int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
 -int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
 -                         int dtype);
 +int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs);
  int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf);
  int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
                    int lnum, int offs);
  int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
                         int lnum, int offs);
  int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
 -                   int offs, int dtype);
 +                   int offs);
  int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
                     int offs, int quiet, int must_chk_crc);
  void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
diff --combined kernel/exit.c
@@@ -499,7 -499,6 +499,7 @@@ struct files_struct *get_files_struct(s
  
        return files;
  }
 +EXPORT_SYMBOL_GPL(get_files_struct);
  
  void put_files_struct(struct files_struct *files)
  {
                rcu_read_unlock();
        }
  }
 +EXPORT_SYMBOL_GPL(put_files_struct);
  
  void reset_files_struct(struct files_struct *files)
  {
@@@ -1021,6 -1019,22 +1021,22 @@@ NORET_TYPE void do_exit(long code
  
        preempt_disable();
        exit_rcu();
+       /*
+        * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+        * when the following two conditions become true.
+        *   - There is race condition of mmap_sem (It is acquired by
+        *     exit_mm()), and
+        *   - SMI occurs before setting TASK_RUNINNG.
+        *     (or hypervisor of virtual machine switches to other guest)
+        *  As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+        *
+        * To avoid it, we have to wait for releasing tsk->pi_lock which
+        * is held by try_to_wake_up()
+        */
+       smp_mb();
+       raw_spin_unlock_wait(&tsk->pi_lock);
        /* causes final put_task_struct in finish_task_switch(). */
        tsk->state = TASK_DEAD;
        schedule();
diff --combined kernel/sched.c
@@@ -5293,7 -5293,6 +5293,7 @@@ int can_nice(const struct task_struct *
        return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
                capable(CAP_SYS_NICE));
  }
 +EXPORT_SYMBOL_GPL(can_nice);
  
  #ifdef __ARCH_WANT_SYS_NICE
  
@@@ -8193,34 -8192,66 +8193,66 @@@ int __init sched_create_sysfs_power_sav
  }
  #endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */
  
+ static int num_cpus_frozen;   /* used to mark begin/end of suspend/resume */
  /*
   * Update cpusets according to cpu_active mask.  If cpusets are
   * disabled, cpuset_update_active_cpus() becomes a simple wrapper
   * around partition_sched_domains().
+  *
+  * If we come here as part of a suspend/resume, don't touch cpusets because we
+  * want to restore it back to its original state upon resume anyway.
   */
  static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
                             void *hcpu)
  {
-       switch (action & ~CPU_TASKS_FROZEN) {
+       switch (action) {
+       case CPU_ONLINE_FROZEN:
+       case CPU_DOWN_FAILED_FROZEN:
+               /*
+                * num_cpus_frozen tracks how many CPUs are involved in suspend
+                * resume sequence. As long as this is not the last online
+                * operation in the resume sequence, just build a single sched
+                * domain, ignoring cpusets.
+                */
+               num_cpus_frozen--;
+               if (likely(num_cpus_frozen)) {
+                       partition_sched_domains(1, NULL, NULL);
+                       break;
+               }
+               /*
+                * This is the last CPU online operation. So fall through and
+                * restore the original sched domains by considering the
+                * cpuset configurations.
+                */
        case CPU_ONLINE:
        case CPU_DOWN_FAILED:
                cpuset_update_active_cpus();
-               return NOTIFY_OK;
+               break;
        default:
                return NOTIFY_DONE;
        }
+       return NOTIFY_OK;
  }
  
  static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
                               void *hcpu)
  {
-       switch (action & ~CPU_TASKS_FROZEN) {
+       switch (action) {
        case CPU_DOWN_PREPARE:
                cpuset_update_active_cpus();
-               return NOTIFY_OK;
+               break;
+       case CPU_DOWN_PREPARE_FROZEN:
+               num_cpus_frozen++;
+               partition_sched_domains(1, NULL, NULL);
+               break;
        default:
                return NOTIFY_DONE;
        }
+       return NOTIFY_OK;
  }
  
  static int update_runtime(struct notifier_block *nfb,
diff --combined mm/memory.c
@@@ -205,10 -205,14 +205,14 @@@ static int tlb_next_batch(struct mmu_ga
                return 1;
        }
  
+       if (tlb->batch_count == MAX_GATHER_BATCH_COUNT)
+               return 0;
        batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
        if (!batch)
                return 0;
  
+       tlb->batch_count++;
        batch->next = NULL;
        batch->nr   = 0;
        batch->max  = MAX_GATHER_BATCH;
@@@ -235,6 -239,7 +239,7 @@@ void tlb_gather_mmu(struct mmu_gather *
        tlb->local.nr   = 0;
        tlb->local.max  = ARRAY_SIZE(tlb->__pages);
        tlb->active     = &tlb->local;
+       tlb->batch_count = 0;
  
  #ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb->batch = NULL;
@@@ -1396,7 -1401,6 +1401,7 @@@ unsigned long zap_page_range(struct vm_
        tlb_finish_mmu(&tlb, address, end);
        return end;
  }
 +EXPORT_SYMBOL_GPL(zap_page_range);
  
  /**
   * zap_vma_ptes - remove ptes mapping the vma
@@@ -3470,6 -3474,7 +3475,7 @@@ int handle_mm_fault(struct mm_struct *m
        if (unlikely(is_vm_hugetlb_page(vma)))
                return hugetlb_fault(mm, vma, address, flags);
  
+ retry:
        pgd = pgd_offset(mm, address);
        pud = pud_alloc(mm, pgd, address);
        if (!pud)
                                                          pmd, flags);
        } else {
                pmd_t orig_pmd = *pmd;
+               int ret;
                barrier();
                if (pmd_trans_huge(orig_pmd)) {
                        if (flags & FAULT_FLAG_WRITE &&
                            !pmd_write(orig_pmd) &&
-                           !pmd_trans_splitting(orig_pmd))
-                               return do_huge_pmd_wp_page(mm, vma, address,
-                                                          pmd, orig_pmd);
+                           !pmd_trans_splitting(orig_pmd)) {
+                               ret = do_huge_pmd_wp_page(mm, vma, address, pmd,
+                                                         orig_pmd);
+                               /*
+                                * If COW results in an oom, the huge pmd will
+                                * have been split, so retry the fault on the
+                                * pte for a smaller charge.
+                                */
+                               if (unlikely(ret & VM_FAULT_OOM))
+                                       goto retry;
+                               return ret;
+                       }
                        return 0;
                }
        }
diff --combined mm/shmem.c
@@@ -595,7 -595,7 +595,7 @@@ static void shmem_evict_inode(struct in
                kfree(xattr->name);
                kfree(xattr);
        }
-       BUG_ON(inode->i_blocks);
+       WARN_ON(inode->i_blocks);
        shmem_free_inode(inode->i_sb);
        end_writeback(inode);
  }
@@@ -798,24 -798,28 +798,28 @@@ static struct mempolicy *shmem_get_sbmp
  static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
                        struct shmem_inode_info *info, pgoff_t index)
  {
-       struct mempolicy mpol, *spol;
        struct vm_area_struct pvma;
-       spol = mpol_cond_copy(&mpol,
-                       mpol_shared_policy_lookup(&info->policy, index));
+       struct page *page;
  
        /* Create a pseudo vma that just contains the policy */
        pvma.vm_start = 0;
        pvma.vm_pgoff = index;
        pvma.vm_ops = NULL;
-       pvma.vm_policy = spol;
-       return swapin_readahead(swap, gfp, &pvma, 0);
+       pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
+       page = swapin_readahead(swap, gfp, &pvma, 0);
+       /* Drop reference taken by mpol_shared_policy_lookup() */
+       mpol_cond_put(pvma.vm_policy);
+       return page;
  }
  
  static struct page *shmem_alloc_page(gfp_t gfp,
                        struct shmem_inode_info *info, pgoff_t index)
  {
        struct vm_area_struct pvma;
+       struct page *page;
  
        /* Create a pseudo vma that just contains the policy */
        pvma.vm_start = 0;
        pvma.vm_ops = NULL;
        pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
  
-       /*
-        * alloc_page_vma() will drop the shared policy reference
-        */
-       return alloc_page_vma(gfp, &pvma, 0);
+       page = alloc_page_vma(gfp, &pvma, 0);
+       /* Drop reference taken by mpol_shared_policy_lookup() */
+       mpol_cond_put(pvma.vm_policy);
+       return page;
  }
  #else /* !CONFIG_NUMA */
  #ifdef CONFIG_TMPFS
@@@ -1962,12 -1968,14 +1968,14 @@@ static struct dentry *shmem_fh_to_dentr
  {
        struct inode *inode;
        struct dentry *dentry = NULL;
-       u64 inum = fid->raw[2];
-       inum = (inum << 32) | fid->raw[1];
+       u64 inum;
  
        if (fh_len < 3)
                return NULL;
  
+       inum = fid->raw[2];
+       inum = (inum << 32) | fid->raw[1];
        inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
                        shmem_match, fid->raw);
        if (inode) {
@@@ -2576,7 -2584,6 +2584,7 @@@ int shmem_zero_setup(struct vm_area_str
        vma->vm_flags |= VM_CAN_NONLINEAR;
        return 0;
  }
 +EXPORT_SYMBOL_GPL(shmem_zero_setup);
  
  /**
   * shmem_read_mapping_page_gfp - read into page cache, using specified page allocation flags.
diff --combined mm/truncate.c
@@@ -394,11 -394,12 +394,12 @@@ invalidate_complete_page2(struct addres
        if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL))
                return 0;
  
+       clear_page_mlock(page);
        spin_lock_irq(&mapping->tree_lock);
        if (PageDirty(page))
                goto failed;
  
-       clear_page_mlock(page);
        BUG_ON(page_has_private(page));
        __delete_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
@@@ -626,4 -627,3 +627,4 @@@ int vmtruncate_range(struct inode *inod
  
        return 0;
  }
 +EXPORT_SYMBOL_GPL(vmtruncate_range);