+ ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
+ EXTRA_CFLAGS += -DDEBUG
+diff --exclude=.git -urN linux-2.6.25.6/drivers/input/serio/at32psif.c avr32-2.6/drivers/input/serio/at32psif.c
+--- linux-2.6.25.6/drivers/input/serio/at32psif.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/input/serio/at32psif.c 2008-06-12 15:09:40.619816021 +0200
+@@ -0,0 +1,351 @@
++/*
++ * Copyright (C) 2007 Atmel Corporation
++ *
++ * Driver for the AT32AP700X PS/2 controller (PSIF).
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/serio.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++
++#include "at32psif.h"
++
++#define PSIF_BUF_SIZE 16
++
++#define ring_is_empty(_psif) (_psif->head == _psif->tail)
++#define ring_next_head(_psif) ((_psif->head + 1) & (PSIF_BUF_SIZE - 1))
++#define ring_next_tail(_psif) ((_psif->tail + 1) & (PSIF_BUF_SIZE - 1))
++
++struct psif {
++ struct platform_device *pdev;
++ struct clk *pclk;
++ struct serio *io;
++ struct timer_list tx_timer;
++ void __iomem *regs;
++ unsigned int irq;
++ unsigned int open;
++ /* Prevent concurrent writes to circular buffer. */
++ spinlock_t lock;
++ unsigned int head;
++ unsigned int tail;
++ unsigned char buffer[PSIF_BUF_SIZE];
++};
++
++static irqreturn_t psif_interrupt(int irq, void *_ptr)
++{
++ struct psif *psif = _ptr;
++ int retval = IRQ_NONE;
++ unsigned int io_flags = 0;
++ unsigned long status;
++
++ status = psif_readl(psif, SR);
++
++ if (status & PSIF_BIT(RXRDY)) {
++ unsigned char val = (unsigned char) psif_readl(psif, RHR);
++
++ if (status & PSIF_BIT(PARITY))
++ io_flags |= SERIO_PARITY;
++ if (status & PSIF_BIT(OVRUN))
++ dev_err(&psif->pdev->dev, "overrun read error\n");
++
++ serio_interrupt(psif->io, val, io_flags);
++
++ retval = IRQ_HANDLED;
++ }
++
++ spin_lock(&psif->lock);
++
++ if (status & PSIF_BIT(TXEMPTY)) {
++ if (status & PSIF_BIT(NACK))
++ dev_err(&psif->pdev->dev, "NACK error\n");
++
++ psif_writel(psif, IDR, PSIF_BIT(TXEMPTY));
++
++ if (!ring_is_empty(psif))
++ mod_timer(&psif->tx_timer,
++ jiffies + msecs_to_jiffies(1));
++
++ retval = IRQ_HANDLED;
++ }
++
++ spin_unlock(&psif->lock);
++
++ return retval;
++}
++
++static void psif_transmit_data(unsigned long data)
++{
++ struct psif *psif = (struct psif *)data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&psif->lock, flags);
++
++ psif_writel(psif, THR, psif->buffer[psif->tail]);
++ psif->tail = ring_next_tail(psif);
++
++ if (!ring_is_empty(psif))
++ psif_writel(psif, IER, PSIF_BIT(TXEMPTY));
++
++ spin_unlock_irqrestore(&psif->lock, flags);
++}
++
++static int psif_write(struct serio *io, unsigned char val)
++{
++ struct psif *psif = io->port_data;
++ unsigned long flags;
++ unsigned int head;
++
++ spin_lock_irqsave(&psif->lock, flags);
++
++ head = ring_next_head(psif);
++
++ if (head != psif->tail) {
++ psif->buffer[psif->head] = val;
++ psif->head = head;
++ } else {
++ dev_err(&psif->pdev->dev, "underrun write error\n");
++ }
++
++ spin_unlock_irqrestore(&psif->lock, flags);
++
++ /* Make sure TXEMPTY interrupt is enabled. */
++ psif_writel(psif, IER, PSIF_BIT(TXEMPTY));
++
++ return 0;
++}
++
++static int psif_open(struct serio *io)
++{
++ struct psif *psif = io->port_data;
++ int retval;
++
++ retval = clk_enable(psif->pclk);
++ if (retval)
++ goto out;
++
++ psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN));
++ psif_writel(psif, IER, PSIF_BIT(RXRDY));
++
++ psif->open = 1;
++out:
++ return retval;
++}
++
++static void psif_close(struct serio *io)
++{
++ struct psif *psif = io->port_data;
++
++ psif->open = 0;
++
++ psif_writel(psif, IDR, ~0UL);
++ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++ clk_disable(psif->pclk);
++}
++
++static void psif_set_prescaler(struct psif *psif)
++{
++ unsigned long prscv;
++ unsigned long rate = clk_get_rate(psif->pclk);
++
++ /* PRSCV = Pulse length (100 us) * PSIF module frequency. */
++ prscv = 100 * (rate / 1000000UL);
++
++ if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE) - 1)) {
++ prscv = (1<<PSIF_PSR_PRSCV_SIZE) - 1;
++ dev_dbg(&psif->pdev->dev, "pclk too fast, "
++ "prescaler set to max\n");
++ }
++
++ clk_enable(psif->pclk);
++ psif_writel(psif, PSR, prscv);
++ clk_disable(psif->pclk);
++}
++
++static int __init psif_probe(struct platform_device *pdev)
++{
++ struct resource *regs;
++ struct psif *psif;
++ struct serio *io;
++ struct clk *pclk;
++ int irq;
++ int ret;
++
++ psif = kzalloc(sizeof(struct psif), GFP_KERNEL);
++ if (!psif) {
++ dev_dbg(&pdev->dev, "out of memory\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++ psif->pdev = pdev;
++
++ io = kzalloc(sizeof(struct serio), GFP_KERNEL);
++ if (!io) {
++ dev_dbg(&pdev->dev, "out of memory\n");
++ ret = -ENOMEM;
++ goto out_free_psif;
++ }
++ psif->io = io;
++
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_dbg(&pdev->dev, "no mmio resources defined\n");
++ ret = -ENOMEM;
++ goto out_free_io;
++ }
++
++ psif->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!psif->regs) {
++ ret = -ENOMEM;
++ dev_dbg(&pdev->dev, "could not map I/O memory\n");
++ goto out_free_io;
++ }
++
++ pclk = clk_get(&pdev->dev, "pclk");
++ if (IS_ERR(pclk)) {
++ dev_dbg(&pdev->dev, "could not get peripheral clock\n");
++ ret = PTR_ERR(pclk);
++ goto out_iounmap;
++ }
++ psif->pclk = pclk;
++
++ /* Reset the PSIF to enter at a known state. */
++ ret = clk_enable(pclk);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not enable pclk\n");
++ goto out_put_clk;
++ }
++ psif_writel(psif, CR, PSIF_BIT(CR_SWRST));
++ clk_disable(pclk);
++
++ setup_timer(&psif->tx_timer, psif_transmit_data, (unsigned long)psif);
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_dbg(&pdev->dev, "could not get irq\n");
++ ret = -ENXIO;
++ goto out_put_clk;
++ }
++ ret = request_irq(irq, psif_interrupt, IRQF_SHARED, "at32psif", psif);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
++ goto out_put_clk;
++ }
++ psif->irq = irq;
++
++ io->id.type = SERIO_8042;
++ io->write = psif_write;
++ io->open = psif_open;
++ io->close = psif_close;
++ strlcpy(io->name, pdev->dev.bus_id, sizeof(io->name));
++ strlcpy(io->phys, pdev->dev.bus_id, sizeof(io->phys));
++ io->port_data = psif;
++ io->dev.parent = &pdev->dev;
++
++ psif_set_prescaler(psif);
++
++ spin_lock_init(&psif->lock);
++ serio_register_port(psif->io);
++ platform_set_drvdata(pdev, psif);
++
++ dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n",
++ (int)psif->regs, psif->irq);
++
++ return 0;
++
++out_put_clk:
++ clk_put(psif->pclk);
++out_iounmap:
++ iounmap(psif->regs);
++out_free_io:
++ kfree(io);
++out_free_psif:
++ kfree(psif);
++out:
++ return ret;
++}
++
++static int __exit psif_remove(struct platform_device *pdev)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ psif_writel(psif, IDR, ~0UL);
++ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++ serio_unregister_port(psif->io);
++ iounmap(psif->regs);
++ free_irq(psif->irq, psif);
++ clk_put(psif->pclk);
++ kfree(psif);
++
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int psif_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ if (psif->open) {
++ psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS));
++ clk_disable(psif->pclk);
++ }
++
++ return 0;
++}
++
++static int psif_resume(struct platform_device *pdev)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ if (psif->open) {
++ clk_enable(psif->pclk);
++ psif_set_prescaler(psif);
++ psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN));
++ }
++
++ return 0;
++}
++#else
++#define psif_suspend NULL
++#define psif_resume NULL
++#endif
++
++static struct platform_driver psif_driver = {
++ .remove = __exit_p(psif_remove),
++ .driver = {
++ .name = "atmel_psif",
++ },
++ .suspend = psif_suspend,
++ .resume = psif_resume,
++};
++
++static int __init psif_init(void)
++{
++ return platform_driver_probe(&psif_driver, psif_probe);
++}
++
++static void __exit psif_exit(void)
++{
++ platform_driver_unregister(&psif_driver);
++}
++
++module_init(psif_init);
++module_exit(psif_exit);
++
++MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
++MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
++MODULE_LICENSE("GPL");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/input/serio/at32psif.h avr32-2.6/drivers/input/serio/at32psif.h
+--- linux-2.6.25.6/drivers/input/serio/at32psif.h 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/input/serio/at32psif.h 2008-06-12 15:09:40.619816021 +0200
+@@ -0,0 +1,82 @@
++/*
++ * Copyright (C) 2007 Atmel Corporation
++ *
++ * Driver for the AT32AP700X PS/2 controller (PSIF).
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#ifndef _AT32PSIF_H
++#define _AT32PSIF_H
++
++/* PSIF register offsets */
++#define PSIF_CR 0x00
++#define PSIF_RHR 0x04
++#define PSIF_THR 0x08
++#define PSIF_SR 0x10
++#define PSIF_IER 0x14
++#define PSIF_IDR 0x18
++#define PSIF_IMR 0x1c
++#define PSIF_PSR 0x24
++
++/* Bitfields in control register. */
++#define PSIF_CR_RXDIS_OFFSET 1
++#define PSIF_CR_RXDIS_SIZE 1
++#define PSIF_CR_RXEN_OFFSET 0
++#define PSIF_CR_RXEN_SIZE 1
++#define PSIF_CR_SWRST_OFFSET 15
++#define PSIF_CR_SWRST_SIZE 1
++#define PSIF_CR_TXDIS_OFFSET 9
++#define PSIF_CR_TXDIS_SIZE 1
++#define PSIF_CR_TXEN_OFFSET 8
++#define PSIF_CR_TXEN_SIZE 1
++
++/* Bitfields in interrupt disable, enable, mask and status register. */
++#define PSIF_NACK_OFFSET 8
++#define PSIF_NACK_SIZE 1
++#define PSIF_OVRUN_OFFSET 5
++#define PSIF_OVRUN_SIZE 1
++#define PSIF_PARITY_OFFSET 9
++#define PSIF_PARITY_SIZE 1
++#define PSIF_RXRDY_OFFSET 4
++#define PSIF_RXRDY_SIZE 1
++#define PSIF_TXEMPTY_OFFSET 1
++#define PSIF_TXEMPTY_SIZE 1
++#define PSIF_TXRDY_OFFSET 0
++#define PSIF_TXRDY_SIZE 1
++
++/* Bitfields in prescale register. */
++#define PSIF_PSR_PRSCV_OFFSET 0
++#define PSIF_PSR_PRSCV_SIZE 12
++
++/* Bitfields in receive hold register. */
++#define PSIF_RHR_RXDATA_OFFSET 0
++#define PSIF_RHR_RXDATA_SIZE 8
++
++/* Bitfields in transmit hold register. */
++#define PSIF_THR_TXDATA_OFFSET 0
++#define PSIF_THR_TXDATA_SIZE 8
++
++/* Bit manipulation macros */
++#define PSIF_BIT(name) \
++ (1 << PSIF_##name##_OFFSET)
++#define PSIF_BF(name, value) \
++ (((value) & ((1 << PSIF_##name##_SIZE) - 1)) \
++ << PSIF_##name##_OFFSET)
++#define PSIF_BFEXT(name, value)\
++ (((value) >> PSIF_##name##_OFFSET) \
++ & ((1 << PSIF_##name##_SIZE) - 1))
++#define PSIF_BFINS(name, value, old) \
++ (((old) & ~(((1 << PSIF_##name##_SIZE) - 1) \
++ << PSIF_##name##_OFFSET)) \
++ | PSIF_BF(name, value))
++
++/* Register access macros */
++#define psif_readl(port, reg) \
++ __raw_readl((port)->regs + PSIF_##reg)
++#define psif_writel(port, reg, value) \
++ __raw_writel((value), (port)->regs + PSIF_##reg)
++
++#endif /* _AT32PSIF_H */
+diff --exclude=.git -urN linux-2.6.25.6/drivers/input/serio/Kconfig avr32-2.6/drivers/input/serio/Kconfig
+--- linux-2.6.25.6/drivers/input/serio/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/input/serio/Kconfig 2008-06-12 15:09:40.615815791 +0200
+@@ -88,6 +88,17 @@
+ To compile this driver as a module, choose M here: the
+ module will be called rpckbd.
+
++config SERIO_AT32PSIF
++ tristate "AVR32 PSIF PS/2 keyboard and mouse controller"
++ depends on AVR32
++ default n
++ help
++ Say Y here if you want to use the PSIF peripheral on AVR32 devices
++ and connect a PS/2 keyboard and/or mouse to it.
++
++ To compile this driver as a module, choose M here: the module will
++ be called at32psif.
++
+ config SERIO_AMBAKMI
+ tristate "AMBA KMI keyboard controller"
+ depends on ARM_AMBA
+diff --exclude=.git -urN linux-2.6.25.6/drivers/input/serio/Makefile avr32-2.6/drivers/input/serio/Makefile
+--- linux-2.6.25.6/drivers/input/serio/Makefile 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/input/serio/Makefile 2008-06-12 15:03:58.919815686 +0200
+@@ -12,6 +12,7 @@
+ obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o
+ obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
+ obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
++obj-$(CONFIG_SERIO_AT32PSIF) += at32psif.o
+ obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
+ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
+ obj-$(CONFIG_HP_SDC) += hp_sdc.o
+diff --exclude=.git -urN linux-2.6.25.6/drivers/misc/atmel_tclib.c avr32-2.6/drivers/misc/atmel_tclib.c
+--- linux-2.6.25.6/drivers/misc/atmel_tclib.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/misc/atmel_tclib.c 2008-06-12 15:03:59.515815344 +0200
+@@ -0,0 +1,161 @@
++#include <linux/atmel_tc.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++/* Number of bytes to reserve for the iomem resource */
++#define ATMEL_TC_IOMEM_SIZE 256
++
++
++/*
++ * This is a thin library to solve the problem of how to portably allocate
++ * one of the TC blocks. For simplicity, it doesn't currently expect to
++ * share individual timers between different drivers.
++ */
++
++#if defined(CONFIG_AVR32)
++/* AVR32 has these divide PBB */
++const u8 atmel_tc_divisors[5] = { 0, 4, 8, 16, 32, };
++EXPORT_SYMBOL(atmel_tc_divisors);
++
++#elif defined(CONFIG_ARCH_AT91)
++/* AT91 has these divide MCK */
++const u8 atmel_tc_divisors[5] = { 2, 8, 32, 128, 0, };
++EXPORT_SYMBOL(atmel_tc_divisors);
++
++#endif
++
++static DEFINE_SPINLOCK(tc_list_lock);
++static LIST_HEAD(tc_list);
++
++/**
++ * atmel_tc_alloc - allocate a specified TC block
++ * @block: which block to allocate
++ * @name: name to be associated with the iomem resource
++ *
++ * Caller allocates a block. If it is available, a pointer to a
++ * pre-initialized struct atmel_tc is returned. The caller can access
++ * the registers directly through the "regs" field.
++ */
++struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
++{
++ struct atmel_tc *tc;
++ struct platform_device *pdev = NULL;
++ struct resource *r;
++
++ spin_lock(&tc_list_lock);
++ list_for_each_entry(tc, &tc_list, node) {
++ if (tc->pdev->id == block) {
++ pdev = tc->pdev;
++ break;
++ }
++ }
++
++ if (!pdev || tc->iomem)
++ goto fail;
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ r = request_mem_region(r->start, ATMEL_TC_IOMEM_SIZE, name);
++ if (!r)
++ goto fail;
++
++ tc->regs = ioremap(r->start, ATMEL_TC_IOMEM_SIZE);
++ if (!tc->regs)
++ goto fail_ioremap;
++
++ tc->iomem = r;
++
++out:
++ spin_unlock(&tc_list_lock);
++ return tc;
++
++fail_ioremap:
++ release_resource(r);
++fail:
++ tc = NULL;
++ goto out;
++}
++EXPORT_SYMBOL_GPL(atmel_tc_alloc);
++
++/**
++ * atmel_tc_free - release a specified TC block
++ * @tc: Timer/counter block that was returned by atmel_tc_alloc()
++ *
++ * This reverses the effect of atmel_tc_alloc(), unmapping the I/O
++ * registers, invalidating the resource returned by that routine and
++ * making the TC available to other drivers.
++ */
++void atmel_tc_free(struct atmel_tc *tc)
++{
++ spin_lock(&tc_list_lock);
++ if (tc->regs) {
++ iounmap(tc->regs);
++ release_resource(tc->iomem);
++ tc->regs = NULL;
++ tc->iomem = NULL;
++ }
++ spin_unlock(&tc_list_lock);
++}
++EXPORT_SYMBOL_GPL(atmel_tc_free);
++
++static int __init tc_probe(struct platform_device *pdev)
++{
++ struct atmel_tc *tc;
++ struct clk *clk;
++ int irq;
++
++ if (!platform_get_resource(pdev, IORESOURCE_MEM, 0))
++ return -EINVAL;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return -EINVAL;
++
++ tc = kzalloc(sizeof(struct atmel_tc), GFP_KERNEL);
++ if (!tc)
++ return -ENOMEM;
++
++ tc->pdev = pdev;
++
++ clk = clk_get(&pdev->dev, "t0_clk");
++ if (IS_ERR(clk)) {
++ kfree(tc);
++ return -EINVAL;
++ }
++
++ tc->clk[0] = clk;
++ tc->clk[1] = clk_get(&pdev->dev, "t1_clk");
++ if (IS_ERR(tc->clk[1]))
++ tc->clk[1] = clk;
++ tc->clk[2] = clk_get(&pdev->dev, "t2_clk");
++ if (IS_ERR(tc->clk[2]))
++ tc->clk[2] = clk;
++
++ tc->irq[0] = irq;
++ tc->irq[1] = platform_get_irq(pdev, 1);
++ if (tc->irq[1] < 0)
++ tc->irq[1] = irq;
++ tc->irq[2] = platform_get_irq(pdev, 2);
++ if (tc->irq[2] < 0)
++ tc->irq[2] = irq;
++
++ spin_lock(&tc_list_lock);
++ list_add_tail(&tc->node, &tc_list);
++ spin_unlock(&tc_list_lock);
++
++ return 0;
++}
++
++static struct platform_driver tc_driver = {
++ .driver.name = "atmel_tcb",
++};
++
++static int __init tc_init(void)
++{
++ return platform_driver_probe(&tc_driver, tc_probe);
++}
++arch_initcall(tc_init);
+diff --exclude=.git -urN linux-2.6.25.6/drivers/misc/Kconfig avr32-2.6/drivers/misc/Kconfig
+--- linux-2.6.25.6/drivers/misc/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/misc/Kconfig 2008-06-12 15:09:41.067816939 +0200
+@@ -22,6 +22,39 @@
+ purposes including software controlled power-efficent backlights
+ on LCD displays, motor control, and waveform generation.
+
++config ATMEL_TCLIB
++ bool "Atmel AT32/AT91 Timer/Counter Library"
++ depends on (AVR32 || ARCH_AT91)
++ help
++ Select this if you want a library to allocate the Timer/Counter
++ blocks found on many Atmel processors. This facilitates using
++ these blocks by different drivers despite processor differences.
++
++config ATMEL_TCB_CLKSRC
++ bool "TC Block Clocksource"
++ depends on ATMEL_TCLIB && GENERIC_TIME
++ default y
++ help
++ Select this to get a high precision clocksource based on a
++ TC block with a 5+ MHz base clock rate. Two timer channels
++ are combined to make a single 32-bit timer.
++
++ When GENERIC_CLOCKEVENTS is defined, the third timer channel
++ may be used as a clock event device supporting oneshot mode
++ (delays of up to two seconds) based on the 32 KiHz clock.
++
++config ATMEL_TCB_CLKSRC_BLOCK
++ int
++ depends on ATMEL_TCB_CLKSRC
++ prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X
++ default 0
++ range 0 1
++ help
++ Some chips provide more than one TC block, so you have the
++ choice of which one to use for the clock framework. The other
++ TC can be used for other purposes, such as PWM generation and
++ interval timing.
++
+ config IBM_ASM
+ tristate "Device driver for IBM RSA service processor"
+ depends on X86 && PCI && INPUT && EXPERIMENTAL
+diff --exclude=.git -urN linux-2.6.25.6/drivers/misc/Makefile avr32-2.6/drivers/misc/Makefile
+--- linux-2.6.25.6/drivers/misc/Makefile 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/misc/Makefile 2008-06-12 15:09:41.067816939 +0200
+@@ -10,6 +10,7 @@
+ obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
+ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
+ obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
++obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
+ obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
+ obj-$(CONFIG_LKDTM) += lkdtm.o
+ obj-$(CONFIG_TIFM_CORE) += tifm_core.o
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mmc/host/atmel-mci.c avr32-2.6/drivers/mmc/host/atmel-mci.c
+--- linux-2.6.25.6/drivers/mmc/host/atmel-mci.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/mmc/host/atmel-mci.c 2008-06-12 15:09:41.083816184 +0200
+@@ -0,0 +1,1220 @@
++/*
++ * Atmel MultiMedia Card Interface driver
++ *
++ * Copyright (C) 2004-2006 Atmel Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/blkdev.h>
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <linux/mmc/host.h>
++
++#include <asm/dma-controller.h>
++#include <asm/io.h>
++#include <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++
++#include "atmel-mci.h"
++
++#define DRIVER_NAME "atmel_mci"
++
++#define MCI_DATA_ERROR_FLAGS (MCI_BIT(DCRCE) | MCI_BIT(DTOE) | \
++ MCI_BIT(OVRE) | MCI_BIT(UNRE))
++
++enum {
++ EVENT_CMD_COMPLETE = 0,
++ EVENT_DATA_COMPLETE,
++ EVENT_DATA_ERROR,
++ EVENT_STOP_SENT,
++ EVENT_STOP_COMPLETE,
++ EVENT_DMA_COMPLETE,
++ EVENT_DMA_ERROR,
++};
++
++struct atmel_mci_dma {
++ struct dma_request_sg req;
++ unsigned short rx_periph_id;
++ unsigned short tx_periph_id;
++};
++
++struct atmel_mci {
++ struct mmc_host *mmc;
++ void __iomem *regs;
++ struct atmel_mci_dma dma;
++
++ struct mmc_request *mrq;
++ struct mmc_command *cmd;
++ struct mmc_data *data;
++
++ u32 cmd_status;
++ u32 data_status;
++ u32 stop_status;
++ u32 stop_cmdr;
++
++ struct tasklet_struct tasklet;
++ unsigned long pending_events;
++ unsigned long completed_events;
++
++ int present;
++ int detect_pin;
++ int wp_pin;
++
++ /* For detect pin debouncing */
++ struct timer_list detect_timer;
++
++ unsigned long bus_hz;
++ unsigned long mapbase;
++ struct clk *mck;
++ struct platform_device *pdev;
++
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *debugfs_root;
++ struct dentry *debugfs_regs;
++ struct dentry *debugfs_req;
++ struct dentry *debugfs_pending_events;
++ struct dentry *debugfs_completed_events;
++#endif
++};
++
++/* Those printks take an awful lot of time... */
++#ifndef DEBUG
++static unsigned int fmax = 15000000U;
++#else
++static unsigned int fmax = 1000000U;
++#endif
++module_param(fmax, uint, 0444);
++MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
++
++/* Test bit macros for completed events */
++#define mci_cmd_is_complete(host) \
++ test_bit(EVENT_CMD_COMPLETE, &host->completed_events)
++#define mci_data_is_complete(host) \
++ test_bit(EVENT_DATA_COMPLETE, &host->completed_events)
++#define mci_data_error_is_complete(host) \
++ test_bit(EVENT_DATA_ERROR, &host->completed_events)
++#define mci_stop_sent_is_complete(host) \
++ test_bit(EVENT_STOP_SENT, &host->completed_events)
++#define mci_stop_is_complete(host) \
++ test_bit(EVENT_STOP_COMPLETE, &host->completed_events)
++#define mci_dma_is_complete(host) \
++ test_bit(EVENT_DMA_COMPLETE, &host->completed_events)
++#define mci_dma_error_is_complete(host) \
++ test_bit(EVENT_DMA_ERROR, &host->completed_events)
++
++/* Test and clear bit macros for pending events */
++#define mci_clear_cmd_is_pending(host) \
++ test_and_clear_bit(EVENT_CMD_COMPLETE, &host->pending_events)
++#define mci_clear_data_is_pending(host) \
++ test_and_clear_bit(EVENT_DATA_COMPLETE, &host->pending_events)
++#define mci_clear_data_error_is_pending(host) \
++ test_and_clear_bit(EVENT_DATA_ERROR, &host->pending_events)
++#define mci_clear_stop_sent_is_pending(host) \
++ test_and_clear_bit(EVENT_STOP_SENT, &host->pending_events)
++#define mci_clear_stop_is_pending(host) \
++ test_and_clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
++#define mci_clear_dma_error_is_pending(host) \
++ test_and_clear_bit(EVENT_DMA_ERROR, &host->pending_events)
++
++/* Test and set bit macros for completed events */
++#define mci_set_cmd_is_completed(host) \
++ test_and_set_bit(EVENT_CMD_COMPLETE, &host->completed_events)
++#define mci_set_data_is_completed(host) \
++ test_and_set_bit(EVENT_DATA_COMPLETE, &host->completed_events)
++#define mci_set_data_error_is_completed(host) \
++ test_and_set_bit(EVENT_DATA_ERROR, &host->completed_events)
++#define mci_set_stop_sent_is_completed(host) \
++ test_and_set_bit(EVENT_STOP_SENT, &host->completed_events)
++#define mci_set_stop_is_completed(host) \
++ test_and_set_bit(EVENT_STOP_COMPLETE, &host->completed_events)
++#define mci_set_dma_error_is_completed(host) \
++ test_and_set_bit(EVENT_DMA_ERROR, &host->completed_events)
++
++/* Set bit macros for completed events */
++#define mci_set_cmd_complete(host) \
++ set_bit(EVENT_CMD_COMPLETE, &host->completed_events)
++#define mci_set_data_complete(host) \
++ set_bit(EVENT_DATA_COMPLETE, &host->completed_events)
++#define mci_set_data_error_complete(host) \
++ set_bit(EVENT_DATA_ERROR, &host->completed_events)
++#define mci_set_stop_sent_complete(host) \
++ set_bit(EVENT_STOP_SENT, &host->completed_events)
++#define mci_set_stop_complete(host) \
++ set_bit(EVENT_STOP_COMPLETE, &host->completed_events)
++#define mci_set_dma_complete(host) \
++ set_bit(EVENT_DMA_COMPLETE, &host->completed_events)
++#define mci_set_dma_error_complete(host) \
++ set_bit(EVENT_DMA_ERROR, &host->completed_events)
++
++/* Set bit macros for pending events */
++#define mci_set_cmd_pending(host) \
++ set_bit(EVENT_CMD_COMPLETE, &host->pending_events)
++#define mci_set_data_pending(host) \
++ set_bit(EVENT_DATA_COMPLETE, &host->pending_events)
++#define mci_set_data_error_pending(host) \
++ set_bit(EVENT_DATA_ERROR, &host->pending_events)
++#define mci_set_stop_sent_pending(host) \
++ set_bit(EVENT_STOP_SENT, &host->pending_events)
++#define mci_set_stop_pending(host) \
++ set_bit(EVENT_STOP_COMPLETE, &host->pending_events)
++#define mci_set_dma_error_pending(host) \
++ set_bit(EVENT_DMA_ERROR, &host->pending_events)
++
++/* Clear bit macros for pending events */
++#define mci_clear_cmd_pending(host) \
++ clear_bit(EVENT_CMD_COMPLETE, &host->pending_events)
++#define mci_clear_data_pending(host) \
++ clear_bit(EVENT_DATA_COMPLETE, &host->pending_events)
++#define mci_clear_data_error_pending(host) \
++ clear_bit(EVENT_DATA_ERROR, &host->pending_events)
++#define mci_clear_stop_sent_pending(host) \
++ clear_bit(EVENT_STOP_SENT, &host->pending_events)
++#define mci_clear_stop_pending(host) \
++ clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
++#define mci_clear_dma_error_pending(host) \
++ clear_bit(EVENT_DMA_ERROR, &host->pending_events)
++
++
++#ifdef CONFIG_DEBUG_FS
++#include <linux/debugfs.h>
++
++#define DBG_REQ_BUF_SIZE (4096 - sizeof(unsigned int))
++
++struct req_dbg_data {
++ unsigned int nbytes;
++ char str[DBG_REQ_BUF_SIZE];
++};
++
++static int req_dbg_open(struct inode *inode, struct file *file)
++{
++ struct atmel_mci *host;
++ struct mmc_request *mrq;
++ struct mmc_command *cmd, *stop;
++ struct mmc_data *data;
++ struct req_dbg_data *priv;
++ char *str;
++ unsigned long n = 0;
++
++ priv = kzalloc(DBG_REQ_BUF_SIZE, GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++ str = priv->str;
++
++ mutex_lock(&inode->i_mutex);
++ host = inode->i_private;
++
++ spin_lock_irq(&host->mmc->lock);
++ mrq = host->mrq;
++ if (mrq) {
++ cmd = mrq->cmd;
++ data = mrq->data;
++ stop = mrq->stop;
++ n = snprintf(str, DBG_REQ_BUF_SIZE,
++ "CMD%u(0x%x) %x %x %x %x %x (err %u)\n",
++ cmd->opcode, cmd->arg, cmd->flags,
++ cmd->resp[0], cmd->resp[1], cmd->resp[2],
++ cmd->resp[3], cmd->error);
++ if (n < DBG_REQ_BUF_SIZE && data)
++ n += snprintf(str + n, DBG_REQ_BUF_SIZE - n,
++ "DATA %u * %u (%u) %x (err %u)\n",
++ data->blocks, data->blksz,
++ data->bytes_xfered, data->flags,
++ data->error);
++ if (n < DBG_REQ_BUF_SIZE && stop)
++ n += snprintf(str + n, DBG_REQ_BUF_SIZE - n,
++ "CMD%u(0x%x) %x %x %x %x %x (err %u)\n",
++ stop->opcode, stop->arg, stop->flags,
++ stop->resp[0], stop->resp[1],
++ stop->resp[2], stop->resp[3],
++ stop->error);
++ }
++ spin_unlock_irq(&host->mmc->lock);
++ mutex_unlock(&inode->i_mutex);
++
++ priv->nbytes = min(n, DBG_REQ_BUF_SIZE);
++ file->private_data = priv;
++
++ return 0;
++}
++
++static ssize_t req_dbg_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ struct req_dbg_data *priv = file->private_data;
++
++ return simple_read_from_buffer(buf, nbytes, ppos,
++ priv->str, priv->nbytes);
++}
++
++static int req_dbg_release(struct inode *inode, struct file *file)
++{
++ kfree(file->private_data);
++ return 0;
++}
++
++static const struct file_operations req_dbg_fops = {
++ .owner = THIS_MODULE,
++ .open = req_dbg_open,
++ .llseek = no_llseek,
++ .read = req_dbg_read,
++ .release = req_dbg_release,
++};
++
++static int regs_dbg_open(struct inode *inode, struct file *file)
++{
++ struct atmel_mci *host;
++ unsigned int i;
++ u32 *data;
++ int ret = -ENOMEM;
++
++ mutex_lock(&inode->i_mutex);
++ host = inode->i_private;
++ data = kmalloc(inode->i_size, GFP_KERNEL);
++ if (!data)
++ goto out;
++
++ spin_lock_irq(&host->mmc->lock);
++ for (i = 0; i < inode->i_size / 4; i++)
++ data[i] = __raw_readl(host->regs + i * 4);
++ spin_unlock_irq(&host->mmc->lock);
++
++ file->private_data = data;
++ ret = 0;
++
++out:
++ mutex_unlock(&inode->i_mutex);
++
++ return ret;
++}
++
++static ssize_t regs_dbg_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ struct inode *inode = file->f_dentry->d_inode;
++ int ret;
++
++ mutex_lock(&inode->i_mutex);
++ ret = simple_read_from_buffer(buf, nbytes, ppos,
++ file->private_data,
++ file->f_dentry->d_inode->i_size);
++ mutex_unlock(&inode->i_mutex);
++
++ return ret;
++}
++
++static int regs_dbg_release(struct inode *inode, struct file *file)
++{
++ kfree(file->private_data);
++ return 0;
++}
++
++static const struct file_operations regs_dbg_fops = {
++ .owner = THIS_MODULE,
++ .open = regs_dbg_open,
++ .llseek = generic_file_llseek,
++ .read = regs_dbg_read,
++ .release = regs_dbg_release,
++};
++
++static void atmci_init_debugfs(struct atmel_mci *host)
++{
++ struct mmc_host *mmc;
++ struct dentry *root, *regs;
++ struct resource *res;
++
++ mmc = host->mmc;
++ root = debugfs_create_dir(mmc_hostname(mmc), NULL);
++ if (IS_ERR(root) || !root)
++ goto err_root;
++ host->debugfs_root = root;
++
++ regs = debugfs_create_file("regs", 0400, root, host, ®s_dbg_fops);
++ if (!regs)
++ goto err_regs;
++
++ res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
++ regs->d_inode->i_size = res->end - res->start + 1;
++ host->debugfs_regs = regs;
++
++ host->debugfs_req = debugfs_create_file("req", 0400, root,
++ host, &req_dbg_fops);
++ if (!host->debugfs_req)
++ goto err_req;
++
++ host->debugfs_pending_events
++ = debugfs_create_u32("pending_events", 0400, root,
++ (u32 *)&host->pending_events);
++ if (!host->debugfs_pending_events)
++ goto err_pending_events;
++
++ host->debugfs_completed_events
++ = debugfs_create_u32("completed_events", 0400, root,
++ (u32 *)&host->completed_events);
++ if (!host->debugfs_completed_events)
++ goto err_completed_events;
++
++ return;
++
++err_completed_events:
++ debugfs_remove(host->debugfs_pending_events);
++err_pending_events:
++ debugfs_remove(host->debugfs_req);
++err_req:
++ debugfs_remove(host->debugfs_regs);
++err_regs:
++ debugfs_remove(host->debugfs_root);
++err_root:
++ host->debugfs_root = NULL;
++ dev_err(&host->pdev->dev,
++ "failed to initialize debugfs for %s\n",
++ mmc_hostname(mmc));
++}
++
++static void atmci_cleanup_debugfs(struct atmel_mci *host)
++{
++ if (host->debugfs_root) {
++ debugfs_remove(host->debugfs_completed_events);
++ debugfs_remove(host->debugfs_pending_events);
++ debugfs_remove(host->debugfs_req);
++ debugfs_remove(host->debugfs_regs);
++ debugfs_remove(host->debugfs_root);
++ host->debugfs_root = NULL;
++ }
++}
++#else
++static inline void atmci_init_debugfs(struct atmel_mci *host)
++{
++
++}
++
++static inline void atmci_cleanup_debugfs(struct atmel_mci *host)
++{
++
++}
++#endif /* CONFIG_DEBUG_FS */
++
++static inline unsigned int ns_to_clocks(struct atmel_mci *host,
++ unsigned int ns)
++{
++ return (ns * (host->bus_hz / 1000000) + 999) / 1000;
++}
++
++static void atmci_set_timeout(struct atmel_mci *host,
++ struct mmc_data *data)
++{
++ static unsigned dtomul_to_shift[] = {
++ 0, 4, 7, 8, 10, 12, 16, 20
++ };
++ unsigned timeout;
++ unsigned dtocyc, dtomul;
++
++ timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks;
++
++ for (dtomul = 0; dtomul < 8; dtomul++) {
++ unsigned shift = dtomul_to_shift[dtomul];
++ dtocyc = (timeout + (1 << shift) - 1) >> shift;
++ if (dtocyc < 15)
++ break;
++ }
++
++ if (dtomul >= 8) {
++ dtomul = 7;
++ dtocyc = 15;
++ }
++
++ dev_dbg(&host->mmc->class_dev, "setting timeout to %u cycles\n",
++ dtocyc << dtomul_to_shift[dtomul]);
++ mci_writel(host, DTOR, (MCI_BF(DTOMUL, dtomul)
++ | MCI_BF(DTOCYC, dtocyc)));
++}
++
++/*
++ * Return mask with command flags to be enabled for this command.
++ */
++static u32 atmci_prepare_command(struct mmc_host *mmc,
++ struct mmc_command *cmd)
++{
++ u32 cmdr;
++
++ cmd->error = 0;
++
++ cmdr = MCI_BF(CMDNB, cmd->opcode);
++
++ if (cmd->flags & MMC_RSP_PRESENT) {
++ if (cmd->flags & MMC_RSP_136)
++ cmdr |= MCI_BF(RSPTYP, MCI_RSPTYP_136_BIT);
++ else
++ cmdr |= MCI_BF(RSPTYP, MCI_RSPTYP_48_BIT);
++ }
++
++ /*
++ * This should really be MAXLAT_5 for CMD2 and ACMD41, but
++ * it's too difficult to determine whether this is an ACMD or
++ * not. Better make it 64.
++ */
++ cmdr |= MCI_BIT(MAXLAT);
++
++ if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN)
++ cmdr |= MCI_BIT(OPDCMD);
++
++ dev_dbg(&mmc->class_dev,
++ "cmd: op %02x arg %08x flags %08x, cmdflags %08lx\n",
++ cmd->opcode, cmd->arg, cmd->flags, (unsigned long)cmdr);
++
++ return cmdr;
++}
++
++static void atmci_start_command(struct atmel_mci *host,
++ struct mmc_command *cmd,
++ u32 cmd_flags)
++{
++ WARN_ON(host->cmd);
++ host->cmd = cmd;
++
++ mci_writel(host, ARGR, cmd->arg);
++ mci_writel(host, CMDR, cmd_flags);
++
++ if (cmd->data)
++ dma_start_request(host->dma.req.req.dmac,
++ host->dma.req.req.channel);
++}
++
++/*
++ * Returns a mask of flags to be set in the command register when the
++ * command to start the transfer is to be sent.
++ */
++static u32 atmci_prepare_data(struct mmc_host *mmc, struct mmc_data *data)
++{
++ struct atmel_mci *host = mmc_priv(mmc);
++ u32 cmd_flags;
++
++ WARN_ON(host->data);
++ host->data = data;
++
++ atmci_set_timeout(host, data);
++ mci_writel(host, BLKR, (MCI_BF(BCNT, data->blocks)
++ | MCI_BF(BLKLEN, data->blksz)));
++ host->dma.req.block_size = data->blksz;
++ host->dma.req.nr_blocks = data->blocks;
++
++ cmd_flags = MCI_BF(TRCMD, MCI_TRCMD_START_TRANS);
++ if (data->flags & MMC_DATA_STREAM)
++ cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_STREAM);
++ else if (data->blocks > 1)
++ cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_MULTI_BLOCK);
++ else
++ cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_BLOCK);
++
++ if (data->flags & MMC_DATA_READ) {
++ cmd_flags |= MCI_BIT(TRDIR);
++ host->dma.req.nr_sg
++ = dma_map_sg(&host->pdev->dev, data->sg,
++ data->sg_len, DMA_FROM_DEVICE);
++ host->dma.req.periph_id = host->dma.rx_periph_id;
++ host->dma.req.direction = DMA_DIR_PERIPH_TO_MEM;
++ host->dma.req.data_reg = host->mapbase + MCI_RDR;
++ } else {
++ host->dma.req.nr_sg
++ = dma_map_sg(&host->pdev->dev, data->sg,
++ data->sg_len, DMA_TO_DEVICE);
++ host->dma.req.periph_id = host->dma.tx_periph_id;
++ host->dma.req.direction = DMA_DIR_MEM_TO_PERIPH;
++ host->dma.req.data_reg = host->mapbase + MCI_TDR;
++ }
++ host->dma.req.sg = data->sg;
++
++ dma_prepare_request_sg(host->dma.req.req.dmac, &host->dma.req);
++
++ return cmd_flags;
++}
++
++static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct atmel_mci *host = mmc_priv(mmc);
++ struct mmc_data *data = mrq->data;
++ u32 iflags;
++ u32 cmdflags = 0;
++
++ iflags = mci_readl(host, IMR);
++ if (iflags)
++ dev_warn(&mmc->class_dev, "WARNING: IMR=0x%08x\n",
++ mci_readl(host, IMR));
++
++ WARN_ON(host->mrq != NULL);
++
++ /*
++ * We may "know" the card is gone even though there's still an
++ * electrical connection. If so, we really need to communicate
++ * this to the MMC core since there won't be any more
++ * interrupts as the card is completely removed. Otherwise,
++ * the MMC core might believe the card is still there even
++ * though the card was just removed very slowly.
++ */
++ if (!host->present) {
++ mrq->cmd->error = -ENOMEDIUM;
++ mmc_request_done(mmc, mrq);
++ return;
++ }
++
++ host->mrq = mrq;
++ host->pending_events = 0;
++ host->completed_events = 0;
++
++ iflags = MCI_BIT(CMDRDY);
++ cmdflags = atmci_prepare_command(mmc, mrq->cmd);
++
++ if (mrq->stop) {
++ WARN_ON(!data);
++
++ host->stop_cmdr = atmci_prepare_command(mmc, mrq->stop);
++ host->stop_cmdr |= MCI_BF(TRCMD, MCI_TRCMD_STOP_TRANS);
++ if (!(data->flags & MMC_DATA_WRITE))
++ host->stop_cmdr |= MCI_BIT(TRDIR);
++ if (data->flags & MMC_DATA_STREAM)
++ host->stop_cmdr |= MCI_BF(TRTYP, MCI_TRTYP_STREAM);
++ else
++ host->stop_cmdr |= MCI_BF(TRTYP, MCI_TRTYP_MULTI_BLOCK);
++ }
++ if (data) {
++ cmdflags |= atmci_prepare_data(mmc, data);
++ iflags |= MCI_DATA_ERROR_FLAGS;
++ }
++
++ atmci_start_command(host, mrq->cmd, cmdflags);
++ mci_writel(host, IER, iflags);
++}
++
++static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++ struct atmel_mci *host = mmc_priv(mmc);
++ u32 mr;
++
++ if (ios->clock) {
++ u32 clkdiv;
++
++ /* Set clock rate */
++ clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * ios->clock) - 1;
++ if (clkdiv > 255) {
++ dev_warn(&mmc->class_dev,
++ "clock %u too slow; using %lu\n",
++ ios->clock, host->bus_hz / (2 * 256));
++ clkdiv = 255;
++ }
++
++ mr = mci_readl(host, MR);
++ mr = MCI_BFINS(CLKDIV, clkdiv, mr)
++ | MCI_BIT(WRPROOF) | MCI_BIT(RDPROOF);
++ mci_writel(host, MR, mr);
++
++ /* Enable the MCI controller */
++ mci_writel(host, CR, MCI_BIT(MCIEN));
++ } else {
++ /* Disable the MCI controller */
++ mci_writel(host, CR, MCI_BIT(MCIDIS));
++ }
++
++ switch (ios->bus_width) {
++ case MMC_BUS_WIDTH_1:
++ mci_writel(host, SDCR, 0);
++ break;
++ case MMC_BUS_WIDTH_4:
++ mci_writel(host, SDCR, MCI_BIT(SDCBUS));
++ break;
++ }
++
++ switch (ios->power_mode) {
++ case MMC_POWER_ON:
++ /* Send init sequence (74 clock cycles) */
++ mci_writel(host, IDR, ~0UL);
++ mci_writel(host, CMDR, MCI_BF(SPCMD, MCI_SPCMD_INIT_CMD));
++ while (!(mci_readl(host, SR) & MCI_BIT(CMDRDY)))
++ cpu_relax();
++ break;
++ default:
++ /*
++ * TODO: None of the currently available AVR32-based
++ * boards allow MMC power to be turned off. Implement
++ * power control when this can be tested properly.
++ */
++ break;
++ }
++}
++
++static int atmci_get_ro(struct mmc_host *mmc)
++{
++ int read_only = 0;
++ struct atmel_mci *host = mmc_priv(mmc);
++
++ if (host->wp_pin >= 0) {
++ read_only = gpio_get_value(host->wp_pin);
++ dev_dbg(&mmc->class_dev, "card is %s\n",
++ read_only ? "read-only" : "read-write");
++ } else {
++ dev_dbg(&mmc->class_dev,
++ "no pin for checking read-only switch."
++ " Assuming write-enable.\n");
++ }
++
++ return read_only;
++}
++
++static struct mmc_host_ops atmci_ops = {
++ .request = atmci_request,
++ .set_ios = atmci_set_ios,
++ .get_ro = atmci_get_ro,
++};
++
++static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct atmel_mci *host = mmc_priv(mmc);
++
++ WARN_ON(host->cmd || host->data);
++ host->mrq = NULL;
++
++ mmc_request_done(mmc, mrq);
++}
++
++static void send_stop_cmd(struct mmc_host *mmc, struct mmc_data *data,
++ u32 flags)
++{
++ struct atmel_mci *host = mmc_priv(mmc);
++
++ atmci_start_command(host, data->stop, host->stop_cmdr | flags);
++ mci_writel(host, IER, MCI_BIT(CMDRDY));
++}
++
++static void atmci_data_complete(struct atmel_mci *host, struct mmc_data *data)
++{
++ host->data = NULL;
++ dma_unmap_sg(&host->pdev->dev, data->sg, host->dma.req.nr_sg,
++ ((data->flags & MMC_DATA_WRITE)
++ ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
++
++ /*
++ * Data might complete before command for very short transfers
++ * (like READ_SCR)
++ */
++ if (mci_cmd_is_complete(host)
++ && (!data->stop || mci_stop_is_complete(host)))
++ atmci_request_end(host->mmc, data->mrq);
++}
++
++static void atmci_command_complete(struct atmel_mci *host,
++ struct mmc_command *cmd, u32 status)
++{
++ if (status & MCI_BIT(RTOE))
++ cmd->error = -ETIMEDOUT;
++ else if ((cmd->flags & MMC_RSP_CRC)
++ && (status & MCI_BIT(RCRCE)))
++ cmd->error = -EILSEQ;
++ else if (status & (MCI_BIT(RINDE) | MCI_BIT(RDIRE) | MCI_BIT(RENDE)))
++ cmd->error = -EIO;
++
++ if (cmd->error) {
++ dev_dbg(&host->mmc->class_dev,
++ "command error: op=0x%x status=0x%08x\n",
++ cmd->opcode, status);
++
++ if (cmd->data) {
++ dma_stop_request(host->dma.req.req.dmac,
++ host->dma.req.req.channel);
++ mci_writel(host, IDR, MCI_BIT(NOTBUSY)
++ | MCI_DATA_ERROR_FLAGS);
++ host->data = NULL;
++ }
++ }
++}
++
++static void atmci_detect_change(unsigned long data)
++{
++ struct atmel_mci *host = (struct atmel_mci *)data;
++ struct mmc_request *mrq = host->mrq;
++ int present;
++
++ /*
++ * atmci_remove() sets detect_pin to -1 before freeing the
++ * interrupt. We must not re-enable the interrupt if it has
++ * been freed.
++ */
++ smp_rmb();
++ if (host->detect_pin < 0)
++ return;
++
++ enable_irq(gpio_to_irq(host->detect_pin));
++ present = !gpio_get_value(host->detect_pin);
++
++ dev_vdbg(&host->pdev->dev, "detect change: %d (was %d)\n",
++ present, host->present);
++
++ if (present != host->present) {
++ dev_dbg(&host->mmc->class_dev, "card %s\n",
++ present ? "inserted" : "removed");
++ host->present = present;
++
++ /* Reset controller if card is gone */
++ if (!present) {
++ mci_writel(host, CR, MCI_BIT(SWRST));
++ mci_writel(host, IDR, ~0UL);
++ mci_writel(host, CR, MCI_BIT(MCIEN));
++ }
++
++ /* Clean up queue if present */
++ if (mrq) {
++ if (!mci_cmd_is_complete(host))
++ mrq->cmd->error = -ENOMEDIUM;
++ if (mrq->data && !mci_data_is_complete(host)
++ && !mci_data_error_is_complete(host)) {
++ dma_stop_request(host->dma.req.req.dmac,
++ host->dma.req.req.channel);
++ host->data->error = -ENOMEDIUM;
++ atmci_data_complete(host, host->data);
++ }
++ if (mrq->stop && !mci_stop_is_complete(host))
++ mrq->stop->error = -ENOMEDIUM;
++
++ host->cmd = NULL;
++ atmci_request_end(host->mmc, mrq);
++ }
++
++ mmc_detect_change(host->mmc, 0);
++ }
++}
++
++static void atmci_tasklet_func(unsigned long priv)
++{
++ struct mmc_host *mmc = (struct mmc_host *)priv;
++ struct atmel_mci *host = mmc_priv(mmc);
++ struct mmc_request *mrq = host->mrq;
++ struct mmc_data *data = host->data;
++
++ dev_vdbg(&mmc->class_dev,
++ "tasklet: pending/completed/mask %lx/%lx/%x\n",
++ host->pending_events, host->completed_events,
++ mci_readl(host, IMR));
++
++ if (mci_clear_cmd_is_pending(host)) {
++ mci_set_cmd_complete(host);
++ atmci_command_complete(host, mrq->cmd, host->cmd_status);
++ if (!host->data || mci_data_is_complete(host)
++ || mci_data_error_is_complete(host))
++ atmci_request_end(mmc, mrq);
++ }
++ if (mci_clear_stop_is_pending(host)) {
++ mci_set_stop_complete(host);
++ atmci_command_complete(host, mrq->stop, host->stop_status);
++ if (mci_data_is_complete(host)
++ || mci_data_error_is_complete(host))
++ atmci_request_end(mmc, mrq);
++ }
++ if (mci_clear_dma_error_is_pending(host)) {
++ mci_set_dma_error_complete(host);
++ mci_clear_data_pending(host);
++
++ /* DMA controller got bus error => invalid address */
++ data->error = -EIO;
++
++ dev_dbg(&mmc->class_dev, "dma error after %u bytes xfered\n",
++ host->data->bytes_xfered);
++
++ if (data->stop
++ && !mci_set_stop_sent_is_completed(host))
++ /* TODO: Check if card is still present */
++ send_stop_cmd(host->mmc, data, 0);
++
++ atmci_data_complete(host, data);
++ }
++ if (mci_clear_data_error_is_pending(host)) {
++ u32 status = host->data_status;
++
++ mci_set_data_error_complete(host);
++ mci_clear_data_pending(host);
++
++ dma_stop_request(host->dma.req.req.dmac,
++ host->dma.req.req.channel);
++
++ if (status & MCI_BIT(DCRCE)) {
++ dev_dbg(&mmc->class_dev, "data CRC error\n");
++ data->error = -EILSEQ;
++ } else if (status & MCI_BIT(DTOE)) {
++ dev_dbg(&mmc->class_dev, "data timeout error\n");
++ data->error = -ETIMEDOUT;
++ } else {
++ dev_dbg(&mmc->class_dev, "data FIFO error\n");
++ data->error = -EIO;
++ }
++ dev_dbg(&mmc->class_dev, "bytes xfered: %u\n",
++ data->bytes_xfered);
++
++ if (data->stop
++ && !mci_set_stop_sent_is_completed(host))
++ /* TODO: Check if card is still present */
++ send_stop_cmd(host->mmc, data, 0);
++
++ atmci_data_complete(host, data);
++ }
++ if (mci_clear_data_is_pending(host)) {
++ mci_set_data_complete(host);
++ data->bytes_xfered = data->blocks * data->blksz;
++ atmci_data_complete(host, data);
++ }
++}
++
++static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status)
++{
++ struct atmel_mci *host = mmc_priv(mmc);
++ struct mmc_command *cmd = host->cmd;
++
++ /*
++ * Read the response now so that we're free to send a new
++ * command immediately.
++ */
++ cmd->resp[0] = mci_readl(host, RSPR);
++ cmd->resp[1] = mci_readl(host, RSPR);
++ cmd->resp[2] = mci_readl(host, RSPR);
++ cmd->resp[3] = mci_readl(host, RSPR);
++
++ mci_writel(host, IDR, MCI_BIT(CMDRDY));
++ host->cmd = NULL;
++
++ if (mci_stop_sent_is_complete(host)) {
++ host->stop_status = status;
++ mci_set_stop_pending(host);
++ } else {
++ struct mmc_request *mrq = host->mrq;
++
++ if (mrq->stop && mci_dma_is_complete(host)
++ && !mci_set_stop_sent_is_completed(host))
++ send_stop_cmd(host->mmc, mrq->data, 0);
++ host->cmd_status = status;
++ mci_set_cmd_pending(host);
++ }
++
++ tasklet_schedule(&host->tasklet);
++}
++
++static void atmci_xfer_complete(struct dma_request *_req)
++{
++ struct dma_request_sg *req = to_dma_request_sg(_req);
++ struct atmel_mci_dma *dma;
++ struct atmel_mci *host;
++ struct mmc_data *data;
++
++ dma = container_of(req, struct atmel_mci_dma, req);
++ host = container_of(dma, struct atmel_mci, dma);
++ data = host->data;
++
++ /*
++ * This callback may be called before we see the CMDRDY
++ * interrupt under heavy irq load (possibly caused by other
++ * drivers) or when interrupts are disabled for a long time.
++ */
++ mci_set_dma_complete(host);
++ if (data->stop && mci_cmd_is_complete(host)
++ && !mci_set_stop_sent_is_completed(host))
++ send_stop_cmd(host->mmc, data, 0);
++
++ /*
++ * Regardless of what the documentation says, we have to wait
++ * for NOTBUSY even after block read operations.
++ *
++ * When the DMA transfer is complete, the controller may still
++ * be reading the CRC from the card, i.e. the data transfer is
++ * still in progress and we haven't seen all the potential
++ * error bits yet.
++ */
++ mci_writel(host, IER, MCI_BIT(NOTBUSY));
++}
++
++static void atmci_dma_error(struct dma_request *_req)
++{
++ struct dma_request_sg *req = to_dma_request_sg(_req);
++ struct atmel_mci_dma *dma;
++ struct atmel_mci *host;
++
++ dma = container_of(req, struct atmel_mci_dma, req);
++ host = container_of(dma, struct atmel_mci, dma);
++
++ mci_writel(host, IDR, (MCI_BIT(NOTBUSY)
++ | MCI_DATA_ERROR_FLAGS));
++
++ mci_set_dma_error_pending(host);
++ tasklet_schedule(&host->tasklet);
++}
++
++static irqreturn_t atmci_interrupt(int irq, void *dev_id)
++{
++ struct mmc_host *mmc = dev_id;
++ struct atmel_mci *host = mmc_priv(mmc);
++ u32 status, mask, pending;
++
++ spin_lock(&mmc->lock);
++
++ status = mci_readl(host, SR);
++ mask = mci_readl(host, IMR);
++ pending = status & mask;
++
++ do {
++ if (pending & MCI_DATA_ERROR_FLAGS) {
++ mci_writel(host, IDR, (MCI_BIT(NOTBUSY)
++ | MCI_DATA_ERROR_FLAGS));
++ host->data_status = status;
++ mci_set_data_error_pending(host);
++ tasklet_schedule(&host->tasklet);
++ break;
++ }
++ if (pending & MCI_BIT(CMDRDY))
++ atmci_cmd_interrupt(mmc, status);
++ if (pending & MCI_BIT(NOTBUSY)) {
++ mci_writel(host, IDR, (MCI_BIT(NOTBUSY)
++ | MCI_DATA_ERROR_FLAGS));
++ mci_set_data_pending(host);
++ tasklet_schedule(&host->tasklet);
++ }
++
++ status = mci_readl(host, SR);
++ mask = mci_readl(host, IMR);
++ pending = status & mask;
++ } while (pending);
++
++ spin_unlock(&mmc->lock);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
++{
++ struct mmc_host *mmc = dev_id;
++ struct atmel_mci *host = mmc_priv(mmc);
++
++ /*
++ * Disable interrupts until the pin has stabilized and check
++ * the state then. Use mod_timer() since we may be in the
++ * middle of the timer routine when this interrupt triggers.
++ */
++ disable_irq_nosync(irq);
++ mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20));
++
++ return IRQ_HANDLED;
++}
++
++static int __devinit atmci_probe(struct platform_device *pdev)
++{
++ struct mci_platform_data *board;
++ struct atmel_mci *host;
++ struct mmc_host *mmc;
++ struct resource *regs;
++ int irq;
++ int ret;
++
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!regs)
++ return -ENXIO;
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return irq;
++
++ board = pdev->dev.platform_data;
++
++ mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev);
++ if (!mmc)
++ return -ENOMEM;
++
++ host = mmc_priv(mmc);
++ host->pdev = pdev;
++ host->mmc = mmc;
++ if (board) {
++ host->detect_pin = board->detect_pin;
++ host->wp_pin = board->wp_pin;
++ } else {
++ host->detect_pin = -1;
++ host->wp_pin = -1;
++ }
++
++ host->mck = clk_get(&pdev->dev, "mci_clk");
++ if (IS_ERR(host->mck)) {
++ ret = PTR_ERR(host->mck);
++ goto out_free_host;
++ }
++ clk_enable(host->mck);
++
++ ret = -ENOMEM;
++ host->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!host->regs)
++ goto out_disable_clk;
++
++ host->bus_hz = clk_get_rate(host->mck);
++ host->mapbase = regs->start;
++
++ mmc->ops = &atmci_ops;
++ mmc->f_min = (host->bus_hz + 511) / 512;
++ mmc->f_max = min((unsigned int)(host->bus_hz / 2), fmax);
++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++ mmc->caps |= MMC_CAP_4_BIT_DATA;
++
++ tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)mmc);
++
++ ret = request_irq(irq, atmci_interrupt, 0, "mmci", mmc);
++ if (ret)
++ goto out_unmap;
++
++ /* Assume card is present if we don't have a detect pin */
++ host->present = 1;
++ if (host->detect_pin >= 0) {
++ if (gpio_request(host->detect_pin, "mmc_detect")) {
++ dev_dbg(&mmc->class_dev, "no detect pin available\n");
++ host->detect_pin = -1;
++ } else {
++ host->present = !gpio_get_value(host->detect_pin);
++ }
++ }
++ if (host->wp_pin >= 0) {
++ if (gpio_request(host->wp_pin, "mmc_wp")) {
++ dev_dbg(&mmc->class_dev, "no WP pin available\n");
++ host->wp_pin = -1;
++ }
++ }
++
++ /* TODO: Get this information from platform data */
++ ret = -ENOMEM;
++ host->dma.req.req.dmac = find_dma_controller(0);
++ if (!host->dma.req.req.dmac) {
++ dev_dbg(&mmc->class_dev, "no DMA controller available\n");
++ goto out_free_irq;
++ }
++ ret = dma_alloc_channel(host->dma.req.req.dmac);
++ if (ret < 0) {
++ dev_dbg(&mmc->class_dev, "unable to allocate DMA channel\n");
++ goto out_free_irq;
++ }
++ host->dma.req.req.channel = ret;
++ host->dma.req.width = DMA_WIDTH_32BIT;
++ host->dma.req.req.xfer_complete = atmci_xfer_complete;
++ host->dma.req.req.block_complete = NULL; // atmci_block_complete;
++ host->dma.req.req.error = atmci_dma_error;
++ host->dma.rx_periph_id = 0;
++ host->dma.tx_periph_id = 1;
++
++ mci_writel(host, CR, MCI_BIT(SWRST));
++ mci_writel(host, IDR, ~0UL);
++
++ platform_set_drvdata(pdev, host);
++
++ mmc_add_host(mmc);
++
++ if (host->detect_pin >= 0) {
++ setup_timer(&host->detect_timer, atmci_detect_change,
++ (unsigned long)host);
++
++ ret = request_irq(gpio_to_irq(host->detect_pin),
++ atmci_detect_interrupt,
++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
++ DRIVER_NAME, mmc);
++ if (ret) {
++ dev_dbg(&mmc->class_dev,
++ "could not request IRQ %d for detect pin\n",
++ gpio_to_irq(host->detect_pin));
++ gpio_free(host->detect_pin);
++ host->detect_pin = -1;
++ }
++ }
++
++ dev_info(&mmc->class_dev, "Atmel MCI controller at 0x%08lx irq %d\n",
++ host->mapbase, irq);
++
++ atmci_init_debugfs(host);
++
++ return 0;
++
++out_free_irq:
++ if (host->detect_pin >= 0)
++ gpio_free(host->detect_pin);
++ if (host->wp_pin >= 0)
++ gpio_free(host->wp_pin);
++ free_irq(irq, mmc);
++out_unmap:
++ iounmap(host->regs);
++out_disable_clk:
++ clk_disable(host->mck);
++ clk_put(host->mck);
++out_free_host:
++ mmc_free_host(mmc);
++ return ret;
++}
++
++static int __devexit atmci_remove(struct platform_device *pdev)
++{
++ struct atmel_mci *host = platform_get_drvdata(pdev);
++
++ platform_set_drvdata(pdev, NULL);
++
++ if (host) {
++ atmci_cleanup_debugfs(host);
++
++ if (host->detect_pin >= 0) {
++ int pin = host->detect_pin;
++
++ /* Make sure our timer doesn't enable the interrupt */
++ host->detect_pin = -1;
++ smp_wmb();
++
++ free_irq(gpio_to_irq(pin), host->mmc);
++ del_timer_sync(&host->detect_timer);
++ cancel_delayed_work(&host->mmc->detect);
++ gpio_free(pin);
++ }
++
++ mmc_remove_host(host->mmc);
++
++ mci_writel(host, IDR, ~0UL);
++ mci_writel(host, CR, MCI_BIT(MCIDIS));
++ mci_readl(host, SR);
++
++ dma_release_channel(host->dma.req.req.dmac,
++ host->dma.req.req.channel);
++
++ if (host->wp_pin >= 0)
++ gpio_free(host->wp_pin);
++
++ free_irq(platform_get_irq(pdev, 0), host->mmc);
++ iounmap(host->regs);
++
++ clk_disable(host->mck);
++ clk_put(host->mck);
++
++ mmc_free_host(host->mmc);
++ }
++ return 0;
++}
++
++static struct platform_driver atmci_driver = {
++ .probe = atmci_probe,
++ .remove = __devexit_p(atmci_remove),
++ .driver = {
++ .name = DRIVER_NAME,
++ },
++};
++
++static int __init atmci_init(void)
++{
++ return platform_driver_register(&atmci_driver);
++}
++
++static void __exit atmci_exit(void)
++{
++ platform_driver_unregister(&atmci_driver);
++}
++
++module_init(atmci_init);
++module_exit(atmci_exit);
++
++MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");
++MODULE_LICENSE("GPL");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mmc/host/atmel-mci.h avr32-2.6/drivers/mmc/host/atmel-mci.h
+--- linux-2.6.25.6/drivers/mmc/host/atmel-mci.h 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/mmc/host/atmel-mci.h 2008-06-12 15:09:41.083816184 +0200
+@@ -0,0 +1,192 @@
++/*
++ * Atmel MultiMedia Card Interface driver
++ *
++ * Copyright (C) 2004-2006 Atmel Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __DRIVERS_MMC_ATMEL_MCI_H__
++#define __DRIVERS_MMC_ATMEL_MCI_H__
++
++/* MCI register offsets */
++#define MCI_CR 0x0000
++#define MCI_MR 0x0004
++#define MCI_DTOR 0x0008
++#define MCI_SDCR 0x000c
++#define MCI_ARGR 0x0010
++#define MCI_CMDR 0x0014
++#define MCI_BLKR 0x0018
++#define MCI_RSPR 0x0020
++#define MCI_RSPR1 0x0024
++#define MCI_RSPR2 0x0028
++#define MCI_RSPR3 0x002c
++#define MCI_RDR 0x0030
++#define MCI_TDR 0x0034
++#define MCI_SR 0x0040
++#define MCI_IER 0x0044
++#define MCI_IDR 0x0048
++#define MCI_IMR 0x004c
++
++/* Bitfields in CR */
++#define MCI_MCIEN_OFFSET 0
++#define MCI_MCIEN_SIZE 1
++#define MCI_MCIDIS_OFFSET 1
++#define MCI_MCIDIS_SIZE 1
++#define MCI_PWSEN_OFFSET 2
++#define MCI_PWSEN_SIZE 1
++#define MCI_PWSDIS_OFFSET 3
++#define MCI_PWSDIS_SIZE 1
++#define MCI_SWRST_OFFSET 7
++#define MCI_SWRST_SIZE 1
++
++/* Bitfields in MR */
++#define MCI_CLKDIV_OFFSET 0
++#define MCI_CLKDIV_SIZE 8
++#define MCI_PWSDIV_OFFSET 8
++#define MCI_PWSDIV_SIZE 3
++#define MCI_RDPROOF_OFFSET 11
++#define MCI_RDPROOF_SIZE 1
++#define MCI_WRPROOF_OFFSET 12
++#define MCI_WRPROOF_SIZE 1
++#define MCI_DMAPADV_OFFSET 14
++#define MCI_DMAPADV_SIZE 1
++#define MCI_BLKLEN_OFFSET 16
++#define MCI_BLKLEN_SIZE 16
++
++/* Bitfields in DTOR */
++#define MCI_DTOCYC_OFFSET 0
++#define MCI_DTOCYC_SIZE 4
++#define MCI_DTOMUL_OFFSET 4
++#define MCI_DTOMUL_SIZE 3
++
++/* Bitfields in SDCR */
++#define MCI_SDCSEL_OFFSET 0
++#define MCI_SDCSEL_SIZE 4
++#define MCI_SDCBUS_OFFSET 7
++#define MCI_SDCBUS_SIZE 1
++
++/* Bitfields in ARGR */
++#define MCI_ARG_OFFSET 0
++#define MCI_ARG_SIZE 32
++
++/* Bitfields in CMDR */
++#define MCI_CMDNB_OFFSET 0
++#define MCI_CMDNB_SIZE 6
++#define MCI_RSPTYP_OFFSET 6
++#define MCI_RSPTYP_SIZE 2
++#define MCI_SPCMD_OFFSET 8
++#define MCI_SPCMD_SIZE 3
++#define MCI_OPDCMD_OFFSET 11
++#define MCI_OPDCMD_SIZE 1
++#define MCI_MAXLAT_OFFSET 12
++#define MCI_MAXLAT_SIZE 1
++#define MCI_TRCMD_OFFSET 16
++#define MCI_TRCMD_SIZE 2
++#define MCI_TRDIR_OFFSET 18
++#define MCI_TRDIR_SIZE 1
++#define MCI_TRTYP_OFFSET 19
++#define MCI_TRTYP_SIZE 2
++
++/* Bitfields in BLKR */
++#define MCI_BCNT_OFFSET 0
++#define MCI_BCNT_SIZE 16
++
++/* Bitfields in RSPRn */
++#define MCI_RSP_OFFSET 0
++#define MCI_RSP_SIZE 32
++
++/* Bitfields in SR/IER/IDR/IMR */
++#define MCI_CMDRDY_OFFSET 0
++#define MCI_CMDRDY_SIZE 1
++#define MCI_RXRDY_OFFSET 1
++#define MCI_RXRDY_SIZE 1
++#define MCI_TXRDY_OFFSET 2
++#define MCI_TXRDY_SIZE 1
++#define MCI_BLKE_OFFSET 3
++#define MCI_BLKE_SIZE 1
++#define MCI_DTIP_OFFSET 4
++#define MCI_DTIP_SIZE 1
++#define MCI_NOTBUSY_OFFSET 5
++#define MCI_NOTBUSY_SIZE 1
++#define MCI_ENDRX_OFFSET 6
++#define MCI_ENDRX_SIZE 1
++#define MCI_ENDTX_OFFSET 7
++#define MCI_ENDTX_SIZE 1
++#define MCI_RXBUFF_OFFSET 14
++#define MCI_RXBUFF_SIZE 1
++#define MCI_TXBUFE_OFFSET 15
++#define MCI_TXBUFE_SIZE 1
++#define MCI_RINDE_OFFSET 16
++#define MCI_RINDE_SIZE 1
++#define MCI_RDIRE_OFFSET 17
++#define MCI_RDIRE_SIZE 1
++#define MCI_RCRCE_OFFSET 18
++#define MCI_RCRCE_SIZE 1
++#define MCI_RENDE_OFFSET 19
++#define MCI_RENDE_SIZE 1
++#define MCI_RTOE_OFFSET 20
++#define MCI_RTOE_SIZE 1
++#define MCI_DCRCE_OFFSET 21
++#define MCI_DCRCE_SIZE 1
++#define MCI_DTOE_OFFSET 22
++#define MCI_DTOE_SIZE 1
++#define MCI_OVRE_OFFSET 30
++#define MCI_OVRE_SIZE 1
++#define MCI_UNRE_OFFSET 31
++#define MCI_UNRE_SIZE 1
++
++/* Constants for DTOMUL */
++#define MCI_DTOMUL_1_CYCLE 0
++#define MCI_DTOMUL_16_CYCLES 1
++#define MCI_DTOMUL_128_CYCLES 2
++#define MCI_DTOMUL_256_CYCLES 3
++#define MCI_DTOMUL_1024_CYCLES 4
++#define MCI_DTOMUL_4096_CYCLES 5
++#define MCI_DTOMUL_65536_CYCLES 6
++#define MCI_DTOMUL_1048576_CYCLES 7
++
++/* Constants for RSPTYP */
++#define MCI_RSPTYP_NO_RESP 0
++#define MCI_RSPTYP_48_BIT 1
++#define MCI_RSPTYP_136_BIT 2
++
++/* Constants for SPCMD */
++#define MCI_SPCMD_NO_SPEC_CMD 0
++#define MCI_SPCMD_INIT_CMD 1
++#define MCI_SPCMD_SYNC_CMD 2
++#define MCI_SPCMD_INT_CMD 4
++#define MCI_SPCMD_INT_RESP 5
++
++/* Constants for TRCMD */
++#define MCI_TRCMD_NO_TRANS 0
++#define MCI_TRCMD_START_TRANS 1
++#define MCI_TRCMD_STOP_TRANS 2
++
++/* Constants for TRTYP */
++#define MCI_TRTYP_BLOCK 0
++#define MCI_TRTYP_MULTI_BLOCK 1
++#define MCI_TRTYP_STREAM 2
++
++/* Bit manipulation macros */
++#define MCI_BIT(name) \
++ (1 << MCI_##name##_OFFSET)
++#define MCI_BF(name,value) \
++ (((value) & ((1 << MCI_##name##_SIZE) - 1)) \
++ << MCI_##name##_OFFSET)
++#define MCI_BFEXT(name,value) \
++ (((value) >> MCI_##name##_OFFSET) \
++ & ((1 << MCI_##name##_SIZE) - 1))
++#define MCI_BFINS(name,value,old) \
++ (((old) & ~(((1 << MCI_##name##_SIZE) - 1) \
++ << MCI_##name##_OFFSET)) \
++ | MCI_BF(name,value))
++
++/* Register access macros */
++#define mci_readl(port,reg) \
++ __raw_readl((port)->regs + MCI_##reg)
++#define mci_writel(port,reg,value) \
++ __raw_writel((value), (port)->regs + MCI_##reg)
++
++#endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mmc/host/Kconfig avr32-2.6/drivers/mmc/host/Kconfig
+--- linux-2.6.25.6/drivers/mmc/host/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mmc/host/Kconfig 2008-06-12 15:09:41.083816184 +0200
+@@ -91,6 +91,16 @@
+
+ If unsure, say N.
+
++config MMC_ATMELMCI
++ tristate "Atmel Multimedia Card Interface support"
++ depends on AVR32 && MMC
++ help
++ This selects the Atmel Multimedia Card Interface. If you have
++ a AT91 (ARM) or AT32 (AVR32) platform with a Multimedia Card
++ slot, say Y or M here.
++
++ If unsure, say N.
++
+ config MMC_IMX
+ tristate "Motorola i.MX Multimedia Card Interface support"
+ depends on ARCH_IMX
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mmc/host/Makefile avr32-2.6/drivers/mmc/host/Makefile
+--- linux-2.6.25.6/drivers/mmc/host/Makefile 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mmc/host/Makefile 2008-06-12 15:09:41.083816184 +0200
+@@ -15,6 +15,7 @@
+ obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
+ obj-$(CONFIG_MMC_OMAP) += omap.o
+ obj-$(CONFIG_MMC_AT91) += at91_mci.o
++obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
+ obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
+ obj-$(CONFIG_MMC_SPI) += mmc_spi.o
+
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/at91_nand.c avr32-2.6/drivers/mtd/nand/at91_nand.c
+--- linux-2.6.25.6/drivers/mtd/nand/at91_nand.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/at91_nand.c 1970-01-01 01:00:00.000000000 +0100
+@@ -1,236 +0,0 @@
+-/*
+- * drivers/mtd/nand/at91_nand.c
+- *
+- * Copyright (C) 2003 Rick Bronson
+- *
+- * Derived from drivers/mtd/nand/autcpu12.c
+- * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
+- *
+- * Derived from drivers/mtd/spia.c
+- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- */
+-
+-#include <linux/slab.h>
+-#include <linux/module.h>
+-#include <linux/platform_device.h>
+-#include <linux/mtd/mtd.h>
+-#include <linux/mtd/nand.h>
+-#include <linux/mtd/partitions.h>
+-
+-#include <asm/io.h>
+-#include <asm/sizes.h>
+-
+-#include <asm/hardware.h>
+-#include <asm/arch/board.h>
+-#include <asm/arch/gpio.h>
+-
+-struct at91_nand_host {
+- struct nand_chip nand_chip;
+- struct mtd_info mtd;
+- void __iomem *io_base;
+- struct at91_nand_data *board;
+-};
+-
+-/*
+- * Hardware specific access to control-lines
+- */
+-static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+-{
+- struct nand_chip *nand_chip = mtd->priv;
+- struct at91_nand_host *host = nand_chip->priv;
+-
+- if (cmd == NAND_CMD_NONE)
+- return;
+-
+- if (ctrl & NAND_CLE)
+- writeb(cmd, host->io_base + (1 << host->board->cle));
+- else
+- writeb(cmd, host->io_base + (1 << host->board->ale));
+-}
+-
+-/*
+- * Read the Device Ready pin.
+- */
+-static int at91_nand_device_ready(struct mtd_info *mtd)
+-{
+- struct nand_chip *nand_chip = mtd->priv;
+- struct at91_nand_host *host = nand_chip->priv;
+-
+- return at91_get_gpio_value(host->board->rdy_pin);
+-}
+-
+-/*
+- * Enable NAND.
+- */
+-static void at91_nand_enable(struct at91_nand_host *host)
+-{
+- if (host->board->enable_pin)
+- at91_set_gpio_value(host->board->enable_pin, 0);
+-}
+-
+-/*
+- * Disable NAND.
+- */
+-static void at91_nand_disable(struct at91_nand_host *host)
+-{
+- if (host->board->enable_pin)
+- at91_set_gpio_value(host->board->enable_pin, 1);
+-}
+-
+-#ifdef CONFIG_MTD_PARTITIONS
+-const char *part_probes[] = { "cmdlinepart", NULL };
+-#endif
+-
+-/*
+- * Probe for the NAND device.
+- */
+-static int __init at91_nand_probe(struct platform_device *pdev)
+-{
+- struct at91_nand_host *host;
+- struct mtd_info *mtd;
+- struct nand_chip *nand_chip;
+- int res;
+-
+-#ifdef CONFIG_MTD_PARTITIONS
+- struct mtd_partition *partitions = NULL;
+- int num_partitions = 0;
+-#endif
+-
+- /* Allocate memory for the device structure (and zero it) */
+- host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
+- if (!host) {
+- printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
+- return -ENOMEM;
+- }
+-
+- host->io_base = ioremap(pdev->resource[0].start,
+- pdev->resource[0].end - pdev->resource[0].start + 1);
+- if (host->io_base == NULL) {
+- printk(KERN_ERR "at91_nand: ioremap failed\n");
+- kfree(host);
+- return -EIO;
+- }
+-
+- mtd = &host->mtd;
+- nand_chip = &host->nand_chip;
+- host->board = pdev->dev.platform_data;
+-
+- nand_chip->priv = host; /* link the private data structures */
+- mtd->priv = nand_chip;
+- mtd->owner = THIS_MODULE;
+-
+- /* Set address of NAND IO lines */
+- nand_chip->IO_ADDR_R = host->io_base;
+- nand_chip->IO_ADDR_W = host->io_base;
+- nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
+-
+- if (host->board->rdy_pin)
+- nand_chip->dev_ready = at91_nand_device_ready;
+-
+- nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */
+- nand_chip->chip_delay = 20; /* 20us command delay time */
+-
+- if (host->board->bus_width_16) /* 16-bit bus width */
+- nand_chip->options |= NAND_BUSWIDTH_16;
+-
+- platform_set_drvdata(pdev, host);
+- at91_nand_enable(host);
+-
+- if (host->board->det_pin) {
+- if (at91_get_gpio_value(host->board->det_pin)) {
+- printk ("No SmartMedia card inserted.\n");
+- res = ENXIO;
+- goto out;
+- }
+- }
+-
+- /* Scan to find existance of the device */
+- if (nand_scan(mtd, 1)) {
+- res = -ENXIO;
+- goto out;
+- }
+-
+-#ifdef CONFIG_MTD_PARTITIONS
+-#ifdef CONFIG_MTD_CMDLINE_PARTS
+- mtd->name = "at91_nand";
+- num_partitions = parse_mtd_partitions(mtd, part_probes,
+- &partitions, 0);
+-#endif
+- if (num_partitions <= 0 && host->board->partition_info)
+- partitions = host->board->partition_info(mtd->size,
+- &num_partitions);
+-
+- if ((!partitions) || (num_partitions == 0)) {
+- printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
+- res = ENXIO;
+- goto release;
+- }
+-
+- res = add_mtd_partitions(mtd, partitions, num_partitions);
+-#else
+- res = add_mtd_device(mtd);
+-#endif
+-
+- if (!res)
+- return res;
+-
+-release:
+- nand_release(mtd);
+-out:
+- at91_nand_disable(host);
+- platform_set_drvdata(pdev, NULL);
+- iounmap(host->io_base);
+- kfree(host);
+- return res;
+-}
+-
+-/*
+- * Remove a NAND device.
+- */
+-static int __devexit at91_nand_remove(struct platform_device *pdev)
+-{
+- struct at91_nand_host *host = platform_get_drvdata(pdev);
+- struct mtd_info *mtd = &host->mtd;
+-
+- nand_release(mtd);
+-
+- at91_nand_disable(host);
+-
+- iounmap(host->io_base);
+- kfree(host);
+-
+- return 0;
+-}
+-
+-static struct platform_driver at91_nand_driver = {
+- .probe = at91_nand_probe,
+- .remove = at91_nand_remove,
+- .driver = {
+- .name = "at91_nand",
+- .owner = THIS_MODULE,
+- },
+-};
+-
+-static int __init at91_nand_init(void)
+-{
+- return platform_driver_register(&at91_nand_driver);
+-}
+-
+-
+-static void __exit at91_nand_exit(void)
+-{
+- platform_driver_unregister(&at91_nand_driver);
+-}
+-
+-
+-module_init(at91_nand_init);
+-module_exit(at91_nand_exit);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Rick Bronson");
+-MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/atmel_nand.c avr32-2.6/drivers/mtd/nand/atmel_nand.c
+--- linux-2.6.25.6/drivers/mtd/nand/atmel_nand.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/mtd/nand/atmel_nand.c 2008-06-12 15:09:41.107815889 +0200
+@@ -0,0 +1,650 @@
++/*
++ * Copyright (C) 2003 Rick Bronson
++ *
++ * Derived from drivers/mtd/nand/autcpu12.c
++ * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
++ *
++ * Derived from drivers/mtd/spia.c
++ * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
++ *
++ *
++ * Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
++ * Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright (C) 2007
++ *
++ * Derived from Das U-Boot source code
++ * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
++ * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++
++#include <linux/gpio.h>
++#include <linux/io.h>
++
++#include <asm/arch/board.h>
++#include <asm/arch/cpu.h>
++
++#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
++#define hard_ecc 1
++#else
++#define hard_ecc 0
++#endif
++
++#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE
++#define no_ecc 1
++#else
++#define no_ecc 0
++#endif
++
++/* Register access macros */
++#define ecc_readl(add, reg) \
++ __raw_readl(add + ATMEL_ECC_##reg)
++#define ecc_writel(add, reg, value) \
++ __raw_writel((value), add + ATMEL_ECC_##reg)
++
++#include "atmel_nand_ecc.h" /* Hardware ECC registers */
++
++/* oob layout for large page size
++ * bad block info is on bytes 0 and 1
++ * the bytes have to be consecutives to avoid
++ * several NAND_CMD_RNDOUT during read
++ */
++static struct nand_ecclayout atmel_oobinfo_large = {
++ .eccbytes = 4,
++ .eccpos = {60, 61, 62, 63},
++ .oobfree = {
++ {2, 58}
++ },
++};
++
++/* oob layout for small page size
++ * bad block info is on bytes 4 and 5
++ * the bytes have to be consecutives to avoid
++ * several NAND_CMD_RNDOUT during read
++ */
++static struct nand_ecclayout atmel_oobinfo_small = {
++ .eccbytes = 4,
++ .eccpos = {0, 1, 2, 3},
++ .oobfree = {
++ {6, 10}
++ },
++};
++
++struct atmel_nand_host {
++ struct nand_chip nand_chip;
++ struct mtd_info mtd;
++ void __iomem *io_base;
++ struct atmel_nand_data *board;
++ struct device *dev;
++ void __iomem *ecc;
++};
++
++/*
++ * Enable NAND.
++ */
++static void atmel_nand_enable(struct atmel_nand_host *host)
++{
++ if (host->board->enable_pin)
++ gpio_set_value(host->board->enable_pin, 0);
++}
++
++/*
++ * Disable NAND.
++ */
++static void atmel_nand_disable(struct atmel_nand_host *host)
++{
++ if (host->board->enable_pin)
++ gpio_set_value(host->board->enable_pin, 1);
++}
++
++/*
++ * Hardware specific access to control-lines
++ */
++static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++ struct atmel_nand_host *host = nand_chip->priv;
++
++ if (ctrl & NAND_CTRL_CHANGE) {
++ if (ctrl & NAND_NCE)
++ atmel_nand_enable(host);
++ else
++ atmel_nand_disable(host);
++ }
++ if (cmd == NAND_CMD_NONE)
++ return;
++
++ if (ctrl & NAND_CLE)
++ writeb(cmd, host->io_base + (1 << host->board->cle));
++ else
++ writeb(cmd, host->io_base + (1 << host->board->ale));
++}
++
++/*
++ * Read the Device Ready pin.
++ */
++static int atmel_nand_device_ready(struct mtd_info *mtd)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++ struct atmel_nand_host *host = nand_chip->priv;
++
++ return gpio_get_value(host->board->rdy_pin);
++}
++
++/*
++ * Minimal-overhead PIO for data access.
++ */
++static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++
++ __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
++}
++
++static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++
++ __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
++}
++
++static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++
++ __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
++}
++
++static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++
++ __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
++}
++
++/*
++ * write oob for small pages
++ */
++static int atmel_nand_write_oob_512(struct mtd_info *mtd,
++ struct nand_chip *chip, int page)
++{
++ int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
++ int eccsize = chip->ecc.size, length = mtd->oobsize;
++ int len, pos, status = 0;
++ const uint8_t *bufpoi = chip->oob_poi;
++
++ pos = eccsize + chunk;
++
++ chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
++ len = min_t(int, length, chunk);
++ chip->write_buf(mtd, bufpoi, len);
++ bufpoi += len;
++ length -= len;
++ if (length > 0)
++ chip->write_buf(mtd, bufpoi, length);
++
++ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
++ status = chip->waitfunc(mtd, chip);
++
++ return status & NAND_STATUS_FAIL ? -EIO : 0;
++
++}
++
++/*
++ * read oob for small pages
++ */
++static int atmel_nand_read_oob_512(struct mtd_info *mtd,
++ struct nand_chip *chip, int page, int sndcmd)
++{
++ if (sndcmd) {
++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
++ sndcmd = 0;
++ }
++ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
++ return sndcmd;
++}
++
++/*
++ * Calculate HW ECC
++ *
++ * function called after a write
++ *
++ * mtd: MTD block structure
++ * dat: raw data (unused)
++ * ecc_code: buffer for ECC
++ */
++static int atmel_nand_calculate(struct mtd_info *mtd,
++ const u_char *dat, unsigned char *ecc_code)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++ struct atmel_nand_host *host = nand_chip->priv;
++ uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
++ unsigned int ecc_value;
++
++ /* get the first 2 ECC bytes */
++ ecc_value = ecc_readl(host->ecc, PR);
++
++ ecc_code[eccpos[0]] = ecc_value & 0xFF;
++ ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
++
++ /* get the last 2 ECC bytes */
++ ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY;
++
++ ecc_code[eccpos[2]] = ecc_value & 0xFF;
++ ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
++
++ return 0;
++}
++
++/*
++ * HW ECC read page function
++ *
++ * mtd: mtd info structure
++ * chip: nand chip info structure
++ * buf: buffer to store read data
++ */
++static int atmel_nand_read_page(struct mtd_info *mtd,
++ struct nand_chip *chip, uint8_t *buf)
++{
++ int eccsize = chip->ecc.size;
++ int eccbytes = chip->ecc.bytes;
++ uint32_t *eccpos = chip->ecc.layout->eccpos;
++ uint8_t *p = buf;
++ uint8_t *oob = chip->oob_poi;
++ uint8_t *ecc_pos;
++ int stat;
++
++ /*
++ * Errata: ALE is incorrectly wired up to the ECC controller
++ * on the AP7000, so it will include the address cycles in the
++ * ECC calculation.
++ *
++ * Workaround: Reset the parity registers before reading the
++ * actual data.
++ */
++ if (cpu_is_at32ap7000()) {
++ struct atmel_nand_host *host = chip->priv;
++ ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
++ }
++
++ /* read the page */
++ chip->read_buf(mtd, p, eccsize);
++
++ /* move to ECC position if needed */
++ if (eccpos[0] != 0) {
++ /* This only works on large pages
++ * because the ECC controller waits for
++ * NAND_CMD_RNDOUTSTART after the
++ * NAND_CMD_RNDOUT.
++ * anyway, for small pages, the eccpos[0] == 0
++ */
++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
++ mtd->writesize + eccpos[0], -1);
++ }
++
++ /* the ECC controller needs to read the ECC just after the data */
++ ecc_pos = oob + eccpos[0];
++ chip->read_buf(mtd, ecc_pos, eccbytes);
++
++ /* check if there's an error */
++ stat = chip->ecc.correct(mtd, p, oob, NULL);
++
++ if (stat < 0)
++ mtd->ecc_stats.failed++;
++ else
++ mtd->ecc_stats.corrected += stat;
++
++ /* get back to oob start (end of page) */
++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
++
++ /* read the oob */
++ chip->read_buf(mtd, oob, mtd->oobsize);
++
++ return 0;
++}
++
++/*
++ * HW ECC Correction
++ *
++ * function called after a read
++ *
++ * mtd: MTD block structure
++ * dat: raw data read from the chip
++ * read_ecc: ECC from the chip (unused)
++ * isnull: unused
++ *
++ * Detect and correct a 1 bit error for a page
++ */
++static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
++ u_char *read_ecc, u_char *isnull)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++ struct atmel_nand_host *host = nand_chip->priv;
++ unsigned int ecc_status;
++ unsigned int ecc_word, ecc_bit;
++
++ /* get the status from the Status Register */
++ ecc_status = ecc_readl(host->ecc, SR);
++
++ /* if there's no error */
++ if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
++ return 0;
++
++ /* get error bit offset (4 bits) */
++ ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR;
++ /* get word address (12 bits) */
++ ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR;
++ ecc_word >>= 4;
++
++ /* if there are multiple errors */
++ if (ecc_status & ATMEL_ECC_MULERR) {
++ /* check if it is a freshly erased block
++ * (filled with 0xff) */
++ if ((ecc_bit == ATMEL_ECC_BITADDR)
++ && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
++ /* the block has just been erased, return OK */
++ return 0;
++ }
++ /* it doesn't seems to be a freshly
++ * erased block.
++ * We can't correct so many errors */
++ dev_dbg(host->dev, "atmel_nand : multiple errors detected."
++ " Unable to correct.\n");
++ return -EIO;
++ }
++
++ /* if there's a single bit error : we can correct it */
++ if (ecc_status & ATMEL_ECC_ECCERR) {
++ /* there's nothing much to do here.
++ * the bit error is on the ECC itself.
++ */
++ dev_dbg(host->dev, "atmel_nand : one bit error on ECC code."
++ " Nothing to correct\n");
++ return 0;
++ }
++
++ dev_dbg(host->dev, "atmel_nand : one bit error on data."
++ " (word offset in the page :"
++ " 0x%x bit offset : 0x%x)\n",
++ ecc_word, ecc_bit);
++ /* correct the error */
++ if (nand_chip->options & NAND_BUSWIDTH_16) {
++ /* 16 bits words */
++ ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
++ } else {
++ /* 8 bits words */
++ dat[ecc_word] ^= (1 << ecc_bit);
++ }
++ dev_dbg(host->dev, "atmel_nand : error corrected\n");
++ return 1;
++}
++
++/*
++ * Enable HW ECC : unused on most chips
++ */
++static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
++{
++ if (cpu_is_at32ap7000()) {
++ struct nand_chip *nand_chip = mtd->priv;
++ struct atmel_nand_host *host = nand_chip->priv;
++ ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
++ }
++}
++
++#ifdef CONFIG_MTD_PARTITIONS
++static const char *part_probes[] = { "cmdlinepart", NULL };
++#endif
++
++/*
++ * Probe for the NAND device.
++ */
++static int __init atmel_nand_probe(struct platform_device *pdev)
++{
++ struct atmel_nand_host *host;
++ struct mtd_info *mtd;
++ struct nand_chip *nand_chip;
++ struct resource *regs;
++ struct resource *mem;
++ int res;
++
++#ifdef CONFIG_MTD_PARTITIONS
++ struct mtd_partition *partitions = NULL;
++ int num_partitions = 0;
++#endif
++
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!mem) {
++ printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
++ return -ENXIO;
++ }
++
++ /* Allocate memory for the device structure (and zero it) */
++ host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL);
++ if (!host) {
++ printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n");
++ return -ENOMEM;
++ }
++
++ host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
++ if (host->io_base == NULL) {
++ printk(KERN_ERR "atmel_nand: ioremap failed\n");
++ res = -EIO;
++ goto err_nand_ioremap;
++ }
++
++ mtd = &host->mtd;
++ nand_chip = &host->nand_chip;
++ host->board = pdev->dev.platform_data;
++ host->dev = &pdev->dev;
++
++ nand_chip->priv = host; /* link the private data structures */
++ mtd->priv = nand_chip;
++ mtd->owner = THIS_MODULE;
++
++ /* Set address of NAND IO lines */
++ nand_chip->IO_ADDR_R = host->io_base;
++ nand_chip->IO_ADDR_W = host->io_base;
++ nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
++
++ if (host->board->rdy_pin)
++ nand_chip->dev_ready = atmel_nand_device_ready;
++
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ if (!regs && hard_ecc) {
++ printk(KERN_ERR "atmel_nand: can't get I/O resource "
++ "regs\nFalling back on software ECC\n");
++ }
++
++ nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */
++ if (no_ecc)
++ nand_chip->ecc.mode = NAND_ECC_NONE;
++ if (hard_ecc && regs) {
++ host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
++ if (host->ecc == NULL) {
++ printk(KERN_ERR "atmel_nand: ioremap failed\n");
++ res = -EIO;
++ goto err_ecc_ioremap;
++ }
++ nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
++ nand_chip->ecc.calculate = atmel_nand_calculate;
++ nand_chip->ecc.correct = atmel_nand_correct;
++ nand_chip->ecc.hwctl = atmel_nand_hwctl;
++ nand_chip->ecc.read_page = atmel_nand_read_page;
++ nand_chip->ecc.bytes = 4;
++ nand_chip->ecc.prepad = 0;
++ nand_chip->ecc.postpad = 0;
++ }
++
++ nand_chip->chip_delay = 20; /* 20us command delay time */
++
++ if (host->board->bus_width_16) { /* 16-bit bus width */
++ nand_chip->options |= NAND_BUSWIDTH_16;
++ nand_chip->read_buf = atmel_read_buf16;
++ nand_chip->write_buf = atmel_write_buf16;
++ } else {
++ nand_chip->read_buf = atmel_read_buf;
++ nand_chip->write_buf = atmel_write_buf;
++ }
++
++ platform_set_drvdata(pdev, host);
++ atmel_nand_enable(host);
++
++ if (host->board->det_pin) {
++ if (gpio_get_value(host->board->det_pin)) {
++ printk("No SmartMedia card inserted.\n");
++ res = ENXIO;
++ goto err_no_card;
++ }
++ }
++
++ /* first scan to find the device and get the page size */
++ if (nand_scan_ident(mtd, 1)) {
++ res = -ENXIO;
++ goto err_scan_ident;
++ }
++
++ if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
++ /* ECC is calculated for the whole page (1 step) */
++ nand_chip->ecc.size = mtd->writesize;
++
++ /* set ECC page size and oob layout */
++ switch (mtd->writesize) {
++ case 512:
++ nand_chip->ecc.layout = &atmel_oobinfo_small;
++ nand_chip->ecc.read_oob = atmel_nand_read_oob_512;
++ nand_chip->ecc.write_oob = atmel_nand_write_oob_512;
++ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
++ break;
++ case 1024:
++ nand_chip->ecc.layout = &atmel_oobinfo_large;
++ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
++ break;
++ case 2048:
++ nand_chip->ecc.layout = &atmel_oobinfo_large;
++ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
++ break;
++ case 4096:
++ nand_chip->ecc.layout = &atmel_oobinfo_large;
++ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
++ break;
++ default:
++ /* page size not handled by HW ECC */
++ /* switching back to soft ECC */
++ nand_chip->ecc.mode = NAND_ECC_SOFT;
++ nand_chip->ecc.calculate = NULL;
++ nand_chip->ecc.correct = NULL;
++ nand_chip->ecc.hwctl = NULL;
++ nand_chip->ecc.read_page = NULL;
++ nand_chip->ecc.postpad = 0;
++ nand_chip->ecc.prepad = 0;
++ nand_chip->ecc.bytes = 0;
++ break;
++ }
++ }
++
++ /* second phase scan */
++ if (nand_scan_tail(mtd)) {
++ res = -ENXIO;
++ goto err_scan_tail;
++ }
++
++#ifdef CONFIG_MTD_PARTITIONS
++#ifdef CONFIG_MTD_CMDLINE_PARTS
++ mtd->name = "atmel_nand";
++ num_partitions = parse_mtd_partitions(mtd, part_probes,
++ &partitions, 0);
++#endif
++ if (num_partitions <= 0 && host->board->partition_info)
++ partitions = host->board->partition_info(mtd->size,
++ &num_partitions);
++
++ if ((!partitions) || (num_partitions == 0)) {
++ printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
++ res = ENXIO;
++ goto err_no_partitions;
++ }
++
++ res = add_mtd_partitions(mtd, partitions, num_partitions);
++#else
++ res = add_mtd_device(mtd);
++#endif
++
++ if (!res)
++ return res;
++
++#ifdef CONFIG_MTD_PARTITIONS
++err_no_partitions:
++#endif
++ nand_release(mtd);
++err_scan_tail:
++err_scan_ident:
++err_no_card:
++ atmel_nand_disable(host);
++ platform_set_drvdata(pdev, NULL);
++ if (host->ecc)
++ iounmap(host->ecc);
++err_ecc_ioremap:
++ iounmap(host->io_base);
++err_nand_ioremap:
++ kfree(host);
++ return res;
++}
++
++/*
++ * Remove a NAND device.
++ */
++static int __exit atmel_nand_remove(struct platform_device *pdev)
++{
++ struct atmel_nand_host *host = platform_get_drvdata(pdev);
++ struct mtd_info *mtd = &host->mtd;
++
++ nand_release(mtd);
++
++ atmel_nand_disable(host);
++
++ if (host->ecc)
++ iounmap(host->ecc);
++ iounmap(host->io_base);
++ kfree(host);
++
++ return 0;
++}
++
++static struct platform_driver atmel_nand_driver = {
++ .remove = __exit_p(atmel_nand_remove),
++ .driver = {
++ .name = "atmel_nand",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init atmel_nand_init(void)
++{
++ return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe);
++}
++
++
++static void __exit atmel_nand_exit(void)
++{
++ platform_driver_unregister(&atmel_nand_driver);
++}
++
++
++module_init(atmel_nand_init);
++module_exit(atmel_nand_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Rick Bronson");
++MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32");
++MODULE_ALIAS("platform:atmel_nand");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/atmel_nand_ecc.h avr32-2.6/drivers/mtd/nand/atmel_nand_ecc.h
+--- linux-2.6.25.6/drivers/mtd/nand/atmel_nand_ecc.h 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/mtd/nand/atmel_nand_ecc.h 2008-06-12 15:09:41.111815840 +0200
+@@ -0,0 +1,36 @@
++/*
++ * Error Corrected Code Controller (ECC) - System peripherals regsters.
++ * Based on AT91SAM9260 datasheet revision B.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#ifndef ATMEL_NAND_ECC_H
++#define ATMEL_NAND_ECC_H
++
++#define ATMEL_ECC_CR 0x00 /* Control register */
++#define ATMEL_ECC_RST (1 << 0) /* Reset parity */
++
++#define ATMEL_ECC_MR 0x04 /* Mode register */
++#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */
++#define ATMEL_ECC_PAGESIZE_528 (0)
++#define ATMEL_ECC_PAGESIZE_1056 (1)
++#define ATMEL_ECC_PAGESIZE_2112 (2)
++#define ATMEL_ECC_PAGESIZE_4224 (3)
++
++#define ATMEL_ECC_SR 0x08 /* Status register */
++#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */
++#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
++#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */
++
++#define ATMEL_ECC_PR 0x0c /* Parity register */
++#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */
++#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
++
++#define ATMEL_ECC_NPR 0x10 /* NParity register */
++#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */
++
++#endif
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/bf5xx_nand.c avr32-2.6/drivers/mtd/nand/bf5xx_nand.c
+--- linux-2.6.25.6/drivers/mtd/nand/bf5xx_nand.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/bf5xx_nand.c 2008-06-12 15:09:41.111815840 +0200
+@@ -803,3 +803,4 @@
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR(DRV_AUTHOR);
+ MODULE_DESCRIPTION(DRV_DESC);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/Kconfig avr32-2.6/drivers/mtd/nand/Kconfig
+--- linux-2.6.25.6/drivers/mtd/nand/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/Kconfig 2008-06-12 15:09:41.107815889 +0200
+@@ -272,12 +272,54 @@
+
+ If you say "m", the module will be called "cs553x_nand.ko".
+
+-config MTD_NAND_AT91
+- bool "Support for NAND Flash / SmartMedia on AT91"
+- depends on ARCH_AT91
++config MTD_NAND_ATMEL
++ bool "Support for NAND Flash / SmartMedia on AT91 and AVR32"
++ depends on ARCH_AT91 || AVR32
+ help
+ Enables support for NAND Flash / Smart Media Card interface
+- on Atmel AT91 processors.
++ on Atmel AT91 and AVR32 processors.
++choice
++ prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32"
++ depends on MTD_NAND_ATMEL
++
++config MTD_NAND_ATMEL_ECC_HW
++ bool "Hardware ECC"
++ depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32
++ help
++ Use hardware ECC instead of software ECC when the chip
++ supports it.
++
++ The hardware ECC controller is capable of single bit error
++ correction and 2-bit random detection per page.
++
++ NB : hardware and software ECC schemes are incompatible.
++ If you switch from one to another, you'll have to erase your
++ mtd partition.
++
++ If unsure, say Y
++
++config MTD_NAND_ATMEL_ECC_SOFT
++ bool "Software ECC"
++ help
++ Use software ECC.
++
++ NB : hardware and software ECC schemes are incompatible.
++ If you switch from one to another, you'll have to erase your
++ mtd partition.
++
++config MTD_NAND_ATMEL_ECC_NONE
++ bool "No ECC (testing only, DANGEROUS)"
++ depends on DEBUG_KERNEL
++ help
++ No ECC will be used.
++ It's not a good idea and it should be reserved for testing
++ purpose only.
++
++ If unsure, say N
++
++ endchoice
++
++endchoice
+
+ config MTD_NAND_CM_X270
+ tristate "Support for NAND Flash on CM-X270 modules"
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/Makefile avr32-2.6/drivers/mtd/nand/Makefile
+--- linux-2.6.25.6/drivers/mtd/nand/Makefile 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/Makefile 2008-06-12 15:09:41.107815889 +0200
+@@ -24,7 +24,7 @@
+ obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
+ obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
+ obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
+-obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
++obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o
+ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
+ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
+ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/ndfc.c avr32-2.6/drivers/mtd/nand/ndfc.c
+--- linux-2.6.25.6/drivers/mtd/nand/ndfc.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/ndfc.c 2008-06-12 15:03:59.579815954 +0200
+@@ -317,3 +317,5 @@
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
+ MODULE_DESCRIPTION("Platform driver for NDFC");
++MODULE_ALIAS("platform:ndfc-chip");
++MODULE_ALIAS("platform:ndfc-nand");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/orion_nand.c avr32-2.6/drivers/mtd/nand/orion_nand.c
+--- linux-2.6.25.6/drivers/mtd/nand/orion_nand.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/orion_nand.c 2008-06-12 15:09:41.115816070 +0200
+@@ -169,3 +169,4 @@
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Tzachi Perelstein");
+ MODULE_DESCRIPTION("NAND glue for Orion platforms");
++MODULE_ALIAS("platform:orion_nand");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/plat_nand.c avr32-2.6/drivers/mtd/nand/plat_nand.c
+--- linux-2.6.25.6/drivers/mtd/nand/plat_nand.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/plat_nand.c 2008-06-12 15:09:41.115816070 +0200
+@@ -150,3 +150,4 @@
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Vitaly Wool");
+ MODULE_DESCRIPTION("Simple generic NAND driver");
++MODULE_ALIAS("platform:gen_nand");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/nand/s3c2410.c avr32-2.6/drivers/mtd/nand/s3c2410.c
+--- linux-2.6.25.6/drivers/mtd/nand/s3c2410.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/nand/s3c2410.c 2008-06-12 15:09:41.115816070 +0200
+@@ -927,3 +927,6 @@
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+ MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
++MODULE_ALIAS("platform:s3c2410-nand");
++MODULE_ALIAS("platform:s3c2412-nand");
++MODULE_ALIAS("platform:s3c2440-nand");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/build.c avr32-2.6/drivers/mtd/ubi/build.c
+--- linux-2.6.25.6/drivers/mtd/ubi/build.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/build.c 2008-06-12 15:09:41.119815462 +0200
+@@ -355,15 +355,34 @@
+ }
+
+ /**
++ * free_user_volumes - free all user volumes.
++ * @ubi: UBI device description object
++ *
++ * Normally the volumes are freed at the release function of the volume device
++ * objects. However, on error paths the volumes have to be freed before the
++ * device objects have been initialized.
++ */
++static void free_user_volumes(struct ubi_device *ubi)
++{
++ int i;
++
++ for (i = 0; i < ubi->vtbl_slots; i++)
++ if (ubi->volumes[i]) {
++ kfree(ubi->volumes[i]->eba_tbl);
++ kfree(ubi->volumes[i]);
++ }
++}
++
++/**
+ * uif_init - initialize user interfaces for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function returns zero in case of success and a negative error code in
+- * case of failure.
++ * case of failure. Note, this function destroys all volumes if it failes.
+ */
+ static int uif_init(struct ubi_device *ubi)
+ {
+- int i, err;
++ int i, err, do_free = 0;
+ dev_t dev;
+
+ sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
+@@ -410,10 +429,13 @@
+
+ out_volumes:
+ kill_volumes(ubi);
++ do_free = 0;
+ out_sysfs:
+ ubi_sysfs_close(ubi);
+ cdev_del(&ubi->cdev);
+ out_unreg:
++ if (do_free)
++ free_user_volumes(ubi);
+ unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
+ ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err);
+ return err;
+@@ -422,6 +444,10 @@
+ /**
+ * uif_close - close user interfaces for an UBI device.
+ * @ubi: UBI device description object
++ *
++ * Note, since this function un-registers UBI volume device objects (@vol->dev),
++ * the memory allocated voe the volumes is freed as well (in the release
++ * function).
+ */
+ static void uif_close(struct ubi_device *ubi)
+ {
+@@ -432,6 +458,21 @@
+ }
+
+ /**
++ * free_internal_volumes - free internal volumes.
++ * @ubi: UBI device description object
++ */
++static void free_internal_volumes(struct ubi_device *ubi)
++{
++ int i;
++
++ for (i = ubi->vtbl_slots;
++ i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
++ kfree(ubi->volumes[i]->eba_tbl);
++ kfree(ubi->volumes[i]);
++ }
++}
++
++/**
+ * attach_by_scanning - attach an MTD device using scanning method.
+ * @ubi: UBI device descriptor
+ *
+@@ -475,6 +516,7 @@
+ out_wl:
+ ubi_wl_close(ubi);
+ out_vtbl:
++ free_internal_volumes(ubi);
+ vfree(ubi->vtbl);
+ out_si:
+ ubi_scan_destroy_si(si);
+@@ -530,7 +572,11 @@
+ ubi->min_io_size = ubi->mtd->writesize;
+ ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
+
+- /* Make sure minimal I/O unit is power of 2 */
++ /*
++ * Make sure minimal I/O unit is power of 2. Note, there is no
++ * fundamental reason for this assumption. It is just an optimization
++ * which allows us to avoid costly division operations.
++ */
+ if (!is_power_of_2(ubi->min_io_size)) {
+ ubi_err("min. I/O unit (%d) is not power of 2",
+ ubi->min_io_size);
+@@ -581,7 +627,7 @@
+ if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||
+ ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
+ ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
+- ubi->leb_start % ubi->min_io_size) {
++ ubi->leb_start & (ubi->min_io_size - 1)) {
+ ubi_err("bad VID header (%d) or data offsets (%d)",
+ ubi->vid_hdr_offset, ubi->leb_start);
+ return -EINVAL;
+@@ -606,8 +652,16 @@
+ ubi->ro_mode = 1;
+ }
+
+- dbg_msg("leb_size %d", ubi->leb_size);
+- dbg_msg("ro_mode %d", ubi->ro_mode);
++ ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
++ ubi->peb_size, ubi->peb_size >> 10);
++ ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
++ ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
++ if (ubi->hdrs_min_io_size != ubi->min_io_size)
++ ubi_msg("sub-page size: %d",
++ ubi->hdrs_min_io_size);
++ ubi_msg("VID header offset: %d (aligned %d)",
++ ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
++ ubi_msg("data offset: %d", ubi->leb_start);
+
+ /*
+ * Note, ideally, we have to initialize ubi->bad_peb_count here. But
+@@ -638,7 +692,7 @@
+
+ /*
+ * Clear the auto-resize flag in the volume in-memory copy of the
+- * volume table, and 'ubi_resize_volume()' will propogate this change
++ * volume table, and 'ubi_resize_volume()' will propagate this change
+ * to the flash.
+ */
+ ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG;
+@@ -647,7 +701,7 @@
+ struct ubi_vtbl_record vtbl_rec;
+
+ /*
+- * No avalilable PEBs to re-size the volume, clear the flag on
++ * No available PEBs to re-size the volume, clear the flag on
+ * flash and exit.
+ */
+ memcpy(&vtbl_rec, &ubi->vtbl[vol_id],
+@@ -680,7 +734,7 @@
+ *
+ * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
+ * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
+- * which case this function finds a vacant device nubert and assings it
++ * which case this function finds a vacant device number and assigns it
+ * automatically. Returns the new UBI device number in case of success and a
+ * negative error code in case of failure.
+ *
+@@ -690,7 +744,7 @@
+ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
+ {
+ struct ubi_device *ubi;
+- int i, err;
++ int i, err, do_free = 1;
+
+ /*
+ * Check if we already have the same MTD device attached.
+@@ -755,8 +809,7 @@
+ mutex_init(&ubi->volumes_mutex);
+ spin_lock_init(&ubi->volumes_lock);
+
+- dbg_msg("attaching mtd%d to ubi%d: VID header offset %d",
+- mtd->index, ubi_num, vid_hdr_offset);
++ ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
+
+ err = io_init(ubi);
+ if (err)
+@@ -791,7 +844,7 @@
+
+ err = uif_init(ubi);
+ if (err)
+- goto out_detach;
++ goto out_nofree;
+
+ ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
+ if (IS_ERR(ubi->bgt_thread)) {
+@@ -804,15 +857,8 @@
+ ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
+ ubi_msg("MTD device name: \"%s\"", mtd->name);
+ ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
+- ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
+- ubi->peb_size, ubi->peb_size >> 10);
+- ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
+ ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
+ ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
+- ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
+- ubi_msg("VID header offset: %d (aligned %d)",
+- ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
+- ubi_msg("data offset: %d", ubi->leb_start);
+ ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
+ ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
+ ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
+@@ -835,9 +881,13 @@
+
+ out_uif:
+ uif_close(ubi);
++out_nofree:
++ do_free = 0;
+ out_detach:
+- ubi_eba_close(ubi);
+ ubi_wl_close(ubi);
++ if (do_free)
++ free_user_volumes(ubi);
++ free_internal_volumes(ubi);
+ vfree(ubi->vtbl);
+ out_free:
+ vfree(ubi->peb_buf1);
+@@ -899,8 +949,8 @@
+ kthread_stop(ubi->bgt_thread);
+
+ uif_close(ubi);
+- ubi_eba_close(ubi);
+ ubi_wl_close(ubi);
++ free_internal_volumes(ubi);
+ vfree(ubi->vtbl);
+ put_mtd_device(ubi->mtd);
+ vfree(ubi->peb_buf1);
+@@ -950,8 +1000,7 @@
+ BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
+
+ if (mtd_devs > UBI_MAX_DEVICES) {
+- printk(KERN_ERR "UBI error: too many MTD devices, "
+- "maximum is %d\n", UBI_MAX_DEVICES);
++ ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES);
+ return -EINVAL;
+ }
+
+@@ -959,25 +1008,25 @@
+ ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
+ if (IS_ERR(ubi_class)) {
+ err = PTR_ERR(ubi_class);
+- printk(KERN_ERR "UBI error: cannot create UBI class\n");
++ ubi_err("cannot create UBI class");
+ goto out;
+ }
+
+ err = class_create_file(ubi_class, &ubi_version);
+ if (err) {
+- printk(KERN_ERR "UBI error: cannot create sysfs file\n");
++ ubi_err("cannot create sysfs file");
+ goto out_class;
+ }
+
+ err = misc_register(&ubi_ctrl_cdev);
+ if (err) {
+- printk(KERN_ERR "UBI error: cannot register device\n");
++ ubi_err("cannot register device");
+ goto out_version;
+ }
+
+ ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
+- sizeof(struct ubi_wl_entry),
+- 0, 0, NULL);
++ sizeof(struct ubi_wl_entry),
++ 0, 0, NULL);
+ if (!ubi_wl_entry_slab)
+ goto out_dev_unreg;
+
+@@ -1000,8 +1049,7 @@
+ mutex_unlock(&ubi_devices_mutex);
+ if (err < 0) {
+ put_mtd_device(mtd);
+- printk(KERN_ERR "UBI error: cannot attach mtd%d\n",
+- mtd->index);
++ ubi_err("cannot attach mtd%d", mtd->index);
+ goto out_detach;
+ }
+ }
+@@ -1023,7 +1071,7 @@
+ out_class:
+ class_destroy(ubi_class);
+ out:
+- printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err);
++ ubi_err("UBI error: cannot initialize UBI, error %d", err);
+ return err;
+ }
+ module_init(ubi_init);
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/cdev.c avr32-2.6/drivers/mtd/ubi/cdev.c
+--- linux-2.6.25.6/drivers/mtd/ubi/cdev.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/cdev.c 2008-06-12 15:09:41.119815462 +0200
+@@ -290,7 +290,7 @@
+ off = do_div(tmp, vol->usable_leb_size);
+ lnum = tmp;
+
+- if (off % ubi->min_io_size) {
++ if (off & (ubi->min_io_size - 1)) {
+ dbg_err("unaligned position");
+ return -EINVAL;
+ }
+@@ -299,7 +299,7 @@
+ count_save = count = vol->used_bytes - *offp;
+
+ /* We can write only in fractions of the minimum I/O unit */
+- if (count % ubi->min_io_size) {
++ if (count & (ubi->min_io_size - 1)) {
+ dbg_err("unaligned write length");
+ return -EINVAL;
+ }
+@@ -559,7 +559,7 @@
+ if (req->alignment > ubi->leb_size)
+ goto bad;
+
+- n = req->alignment % ubi->min_io_size;
++ n = req->alignment & (ubi->min_io_size - 1);
+ if (req->alignment != 1 && n)
+ goto bad;
+
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/debug.h avr32-2.6/drivers/mtd/ubi/debug.h
+--- linux-2.6.25.6/drivers/mtd/ubi/debug.h 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/debug.h 2008-06-12 15:09:41.123815692 +0200
+@@ -99,8 +99,10 @@
+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD
+ /* Initialization and build messages */
+ #define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
++#define UBI_IO_DEBUG 1
+ #else
+ #define dbg_bld(fmt, ...) ({})
++#define UBI_IO_DEBUG 0
+ #endif
+
+ #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/eba.c avr32-2.6/drivers/mtd/ubi/eba.c
+--- linux-2.6.25.6/drivers/mtd/ubi/eba.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/eba.c 2008-06-12 15:09:41.123815692 +0200
+@@ -752,7 +752,7 @@
+ /* If this is the last LEB @len may be unaligned */
+ len = ALIGN(data_size, ubi->min_io_size);
+ else
+- ubi_assert(len % ubi->min_io_size == 0);
++ ubi_assert(!(len & (ubi->min_io_size - 1)));
+
+ vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
+ if (!vid_hdr)
+@@ -1233,20 +1233,3 @@
+ }
+ return err;
+ }
+-
+-/**
+- * ubi_eba_close - close EBA unit.
+- * @ubi: UBI device description object
+- */
+-void ubi_eba_close(const struct ubi_device *ubi)
+-{
+- int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
+-
+- dbg_eba("close EBA unit");
+-
+- for (i = 0; i < num_volumes; i++) {
+- if (!ubi->volumes[i])
+- continue;
+- kfree(ubi->volumes[i]->eba_tbl);
+- }
+-}
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/gluebi.c avr32-2.6/drivers/mtd/ubi/gluebi.c
+--- linux-2.6.25.6/drivers/mtd/ubi/gluebi.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/gluebi.c 2008-06-12 15:03:59.587815297 +0200
+@@ -291,11 +291,12 @@
+ /*
+ * In case of dynamic volume, MTD device size is just volume size. In
+ * case of a static volume the size is equivalent to the amount of data
+- * bytes, which is zero at this moment and will be changed after volume
+- * update.
++ * bytes.
+ */
+ if (vol->vol_type == UBI_DYNAMIC_VOLUME)
+ mtd->size = vol->usable_leb_size * vol->reserved_pebs;
++ else
++ mtd->size = vol->used_bytes;
+
+ if (add_mtd_device(mtd)) {
+ ubi_err("cannot not add MTD device\n");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/io.c avr32-2.6/drivers/mtd/ubi/io.c
+--- linux-2.6.25.6/drivers/mtd/ubi/io.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/io.c 2008-06-12 15:03:59.587815297 +0200
+@@ -631,6 +631,8 @@
+
+ dbg_io("read EC header from PEB %d", pnum);
+ ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
++ if (UBI_IO_DEBUG)
++ verbose = 1;
+
+ err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
+ if (err) {
+@@ -904,6 +906,8 @@
+
+ dbg_io("read VID header from PEB %d", pnum);
+ ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
++ if (UBI_IO_DEBUG)
++ verbose = 1;
+
+ p = (char *)vid_hdr - ubi->vid_hdr_shift;
+ err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/kapi.c avr32-2.6/drivers/mtd/ubi/kapi.c
+--- linux-2.6.25.6/drivers/mtd/ubi/kapi.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/kapi.c 2008-06-12 15:09:41.123815692 +0200
+@@ -397,8 +397,8 @@
+ return -EROFS;
+
+ if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 ||
+- offset + len > vol->usable_leb_size || offset % ubi->min_io_size ||
+- len % ubi->min_io_size)
++ offset + len > vol->usable_leb_size ||
++ offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
+ return -EINVAL;
+
+ if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
+@@ -447,7 +447,7 @@
+ return -EROFS;
+
+ if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 ||
+- len > vol->usable_leb_size || len % ubi->min_io_size)
++ len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
+ return -EINVAL;
+
+ if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/Kconfig avr32-2.6/drivers/mtd/ubi/Kconfig
+--- linux-2.6.25.6/drivers/mtd/ubi/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/Kconfig 2008-06-12 15:03:59.583815905 +0200
+@@ -24,8 +24,13 @@
+ erase counter value and the lowest erase counter value of eraseblocks
+ of UBI devices. When this threshold is exceeded, UBI starts performing
+ wear leveling by means of moving data from eraseblock with low erase
+- counter to eraseblocks with high erase counter. Leave the default
+- value if unsure.
++ counter to eraseblocks with high erase counter.
++
++ The default value should be OK for SLC NAND flashes, NOR flashes and
++ other flashes which have eraseblock life-cycle 100000 or more.
++ However, in case of MLC NAND flashes which typically have eraseblock
++ life-cycle less then 10000, the threshold should be lessened (e.g.,
++ to 128 or 256, although it does not have to be power of 2).
+
+ config MTD_UBI_BEB_RESERVE
+ int "Percentage of reserved eraseblocks for bad eraseblocks handling"
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/misc.c avr32-2.6/drivers/mtd/ubi/misc.c
+--- linux-2.6.25.6/drivers/mtd/ubi/misc.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/misc.c 2008-06-12 15:09:41.123815692 +0200
+@@ -37,7 +37,7 @@
+ {
+ int i;
+
+- ubi_assert(length % ubi->min_io_size == 0);
++ ubi_assert(!(length & (ubi->min_io_size - 1)));
+
+ for (i = length - 1; i >= 0; i--)
+ if (((const uint8_t *)buf)[i] != 0xFF)
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/scan.c avr32-2.6/drivers/mtd/ubi/scan.c
+--- linux-2.6.25.6/drivers/mtd/ubi/scan.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/scan.c 2008-06-12 15:03:59.587815297 +0200
+@@ -42,6 +42,7 @@
+
+ #include <linux/err.h>
+ #include <linux/crc32.h>
++#include <asm/div64.h>
+ #include "ubi.h"
+
+ #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+@@ -92,27 +93,6 @@
+ }
+
+ /**
+- * commit_to_mean_value - commit intermediate results to the final mean erase
+- * counter value.
+- * @si: scanning information
+- *
+- * This is a helper function which calculates partial mean erase counter mean
+- * value and adds it to the resulting mean value. As we can work only in
+- * integer arithmetic and we want to calculate the mean value of erase counter
+- * accurately, we first sum erase counter values in @si->ec_sum variable and
+- * count these components in @si->ec_count. If this temporary @si->ec_sum is
+- * going to overflow, we calculate the partial mean value
+- * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec.
+- */
+-static void commit_to_mean_value(struct ubi_scan_info *si)
+-{
+- si->ec_sum /= si->ec_count;
+- if (si->ec_sum % si->ec_count >= si->ec_count / 2)
+- si->mean_ec += 1;
+- si->mean_ec += si->ec_sum;
+-}
+-
+-/**
+ * validate_vid_hdr - check that volume identifier header is correct and
+ * consistent.
+ * @vid_hdr: the volume identifier header to check
+@@ -901,15 +881,8 @@
+
+ adjust_mean_ec:
+ if (!ec_corr) {
+- if (si->ec_sum + ec < ec) {
+- commit_to_mean_value(si);
+- si->ec_sum = 0;
+- si->ec_count = 0;
+- } else {
+- si->ec_sum += ec;
+- si->ec_count += 1;
+- }
+-
++ si->ec_sum += ec;
++ si->ec_count += 1;
+ if (ec > si->max_ec)
+ si->max_ec = ec;
+ if (ec < si->min_ec)
+@@ -965,9 +938,11 @@
+
+ dbg_msg("scanning is finished");
+
+- /* Finish mean erase counter calculations */
+- if (si->ec_count)
+- commit_to_mean_value(si);
++ /* Calculate mean erase counter */
++ if (si->ec_count) {
++ do_div(si->ec_sum, si->ec_count);
++ si->mean_ec = si->ec_sum;
++ }
+
+ if (si->is_empty)
+ ubi_msg("empty MTD device detected");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/scan.h avr32-2.6/drivers/mtd/ubi/scan.h
+--- linux-2.6.25.6/drivers/mtd/ubi/scan.h 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/scan.h 2008-06-12 15:03:59.587815297 +0200
+@@ -124,7 +124,7 @@
+ int max_ec;
+ unsigned long long max_sqnum;
+ int mean_ec;
+- int ec_sum;
++ uint64_t ec_sum;
+ int ec_count;
+ };
+
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/ubi.h avr32-2.6/drivers/mtd/ubi/ubi.h
+--- linux-2.6.25.6/drivers/mtd/ubi/ubi.h 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/ubi.h 2008-06-12 15:09:41.123815692 +0200
+@@ -37,10 +37,9 @@
+ #include <linux/string.h>
+ #include <linux/vmalloc.h>
+ #include <linux/mtd/mtd.h>
+-
+-#include <mtd/ubi-header.h>
+ #include <linux/mtd/ubi.h>
+
++#include "ubi-media.h"
+ #include "scan.h"
+ #include "debug.h"
+
+@@ -478,7 +477,6 @@
+ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
+ struct ubi_vid_hdr *vid_hdr);
+ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
+-void ubi_eba_close(const struct ubi_device *ubi);
+
+ /* wl.c */
+ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/ubi-media.h avr32-2.6/drivers/mtd/ubi/ubi-media.h
+--- linux-2.6.25.6/drivers/mtd/ubi/ubi-media.h 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/mtd/ubi/ubi-media.h 2008-06-12 15:03:59.587815297 +0200
+@@ -0,0 +1,372 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Thomas Gleixner
++ * Frank Haverkamp
++ * Oliver Lohmann
++ * Andreas Arnez
++ */
++
++/*
++ * This file defines the layout of UBI headers and all the other UBI on-flash
++ * data structures.
++ */
++
++#ifndef __UBI_MEDIA_H__
++#define __UBI_MEDIA_H__
++
++#include <asm/byteorder.h>
++
++/* The version of UBI images supported by this implementation */
++#define UBI_VERSION 1
++
++/* The highest erase counter value supported by this implementation */
++#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
++
++/* The initial CRC32 value used when calculating CRC checksums */
++#define UBI_CRC32_INIT 0xFFFFFFFFU
++
++/* Erase counter header magic number (ASCII "UBI#") */
++#define UBI_EC_HDR_MAGIC 0x55424923
++/* Volume identifier header magic number (ASCII "UBI!") */
++#define UBI_VID_HDR_MAGIC 0x55424921
++
++/*
++ * Volume type constants used in the volume identifier header.
++ *
++ * @UBI_VID_DYNAMIC: dynamic volume
++ * @UBI_VID_STATIC: static volume
++ */
++enum {
++ UBI_VID_DYNAMIC = 1,
++ UBI_VID_STATIC = 2
++};
++
++/*
++ * Volume flags used in the volume table record.
++ *
++ * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
++ *
++ * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
++ * table. UBI automatically re-sizes the volume which has this flag and makes
++ * the volume to be of largest possible size. This means that if after the
++ * initialization UBI finds out that there are available physical eraseblocks
++ * present on the device, it automatically appends all of them to the volume
++ * (the physical eraseblocks reserved for bad eraseblocks handling and other
++ * reserved physical eraseblocks are not taken). So, if there is a volume with
++ * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
++ * eraseblocks will be zero after UBI is loaded, because all of them will be
++ * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
++ * after the volume had been initialized.
++ *
++ * The auto-resize feature is useful for device production purposes. For
++ * example, different NAND flash chips may have different amount of initial bad
++ * eraseblocks, depending of particular chip instance. Manufacturers of NAND
++ * chips usually guarantee that the amount of initial bad eraseblocks does not
++ * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
++ * flashed to the end devices in production, he does not know the exact amount
++ * of good physical eraseblocks the NAND chip on the device will have, but this
++ * number is required to calculate the volume sized and put them to the volume
++ * table of the UBI image. In this case, one of the volumes (e.g., the one
++ * which will store the root file system) is marked as "auto-resizable", and
++ * UBI will adjust its size on the first boot if needed.
++ *
++ * Note, first UBI reserves some amount of physical eraseblocks for bad
++ * eraseblock handling, and then re-sizes the volume, not vice-versa. This
++ * means that the pool of reserved physical eraseblocks will always be present.
++ */
++enum {
++ UBI_VTBL_AUTORESIZE_FLG = 0x01,
++};
++
++/*
++ * Compatibility constants used by internal volumes.
++ *
++ * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
++ * to the flash
++ * @UBI_COMPAT_RO: attach this device in read-only mode
++ * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
++ * physical eraseblocks, don't allow the wear-leveling unit to move them
++ * @UBI_COMPAT_REJECT: reject this UBI image
++ */
++enum {
++ UBI_COMPAT_DELETE = 1,
++ UBI_COMPAT_RO = 2,
++ UBI_COMPAT_PRESERVE = 4,
++ UBI_COMPAT_REJECT = 5
++};
++
++/* Sizes of UBI headers */
++#define UBI_EC_HDR_SIZE sizeof(struct ubi_ec_hdr)
++#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
++
++/* Sizes of UBI headers without the ending CRC */
++#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(__be32))
++#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
++
++/**
++ * struct ubi_ec_hdr - UBI erase counter header.
++ * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
++ * @version: version of UBI implementation which is supposed to accept this
++ * UBI image
++ * @padding1: reserved for future, zeroes
++ * @ec: the erase counter
++ * @vid_hdr_offset: where the VID header starts
++ * @data_offset: where the user data start
++ * @padding2: reserved for future, zeroes
++ * @hdr_crc: erase counter header CRC checksum
++ *
++ * The erase counter header takes 64 bytes and has a plenty of unused space for
++ * future usage. The unused fields are zeroed. The @version field is used to
++ * indicate the version of UBI implementation which is supposed to be able to
++ * work with this UBI image. If @version is greater then the current UBI
++ * version, the image is rejected. This may be useful in future if something
++ * is changed radically. This field is duplicated in the volume identifier
++ * header.
++ *
++ * The @vid_hdr_offset and @data_offset fields contain the offset of the the
++ * volume identifier header and user data, relative to the beginning of the
++ * physical eraseblock. These values have to be the same for all physical
++ * eraseblocks.
++ */
++struct ubi_ec_hdr {
++ __be32 magic;
++ __u8 version;
++ __u8 padding1[3];
++ __be64 ec; /* Warning: the current limit is 31-bit anyway! */
++ __be32 vid_hdr_offset;
++ __be32 data_offset;
++ __u8 padding2[36];
++ __be32 hdr_crc;
++} __attribute__ ((packed));
++
++/**
++ * struct ubi_vid_hdr - on-flash UBI volume identifier header.
++ * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
++ * @version: UBI implementation version which is supposed to accept this UBI
++ * image (%UBI_VERSION)
++ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
++ * @copy_flag: if this logical eraseblock was copied from another physical
++ * eraseblock (for wear-leveling reasons)
++ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
++ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
++ * @vol_id: ID of this volume
++ * @lnum: logical eraseblock number
++ * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
++ * removed, kept only for not breaking older UBI users)
++ * @data_size: how many bytes of data this logical eraseblock contains
++ * @used_ebs: total number of used logical eraseblocks in this volume
++ * @data_pad: how many bytes at the end of this physical eraseblock are not
++ * used
++ * @data_crc: CRC checksum of the data stored in this logical eraseblock
++ * @padding1: reserved for future, zeroes
++ * @sqnum: sequence number
++ * @padding2: reserved for future, zeroes
++ * @hdr_crc: volume identifier header CRC checksum
++ *
++ * The @sqnum is the value of the global sequence counter at the time when this
++ * VID header was created. The global sequence counter is incremented each time
++ * UBI writes a new VID header to the flash, i.e. when it maps a logical
++ * eraseblock to a new physical eraseblock. The global sequence counter is an
++ * unsigned 64-bit integer and we assume it never overflows. The @sqnum
++ * (sequence number) is used to distinguish between older and newer versions of
++ * logical eraseblocks.
++ *
++ * There are 2 situations when there may be more then one physical eraseblock
++ * corresponding to the same logical eraseblock, i.e., having the same @vol_id
++ * and @lnum values in the volume identifier header. Suppose we have a logical
++ * eraseblock L and it is mapped to the physical eraseblock P.
++ *
++ * 1. Because UBI may erase physical eraseblocks asynchronously, the following
++ * situation is possible: L is asynchronously erased, so P is scheduled for
++ * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
++ * so P1 is written to, then an unclean reboot happens. Result - there are 2
++ * physical eraseblocks P and P1 corresponding to the same logical eraseblock
++ * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
++ * flash.
++ *
++ * 2. From time to time UBI moves logical eraseblocks to other physical
++ * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
++ * to P1, and an unclean reboot happens before P is physically erased, there
++ * are two physical eraseblocks P and P1 corresponding to L and UBI has to
++ * select one of them when the flash is attached. The @sqnum field says which
++ * PEB is the original (obviously P will have lower @sqnum) and the copy. But
++ * it is not enough to select the physical eraseblock with the higher sequence
++ * number, because the unclean reboot could have happen in the middle of the
++ * copying process, so the data in P is corrupted. It is also not enough to
++ * just select the physical eraseblock with lower sequence number, because the
++ * data there may be old (consider a case if more data was added to P1 after
++ * the copying). Moreover, the unclean reboot may happen when the erasure of P
++ * was just started, so it result in unstable P, which is "mostly" OK, but
++ * still has unstable bits.
++ *
++ * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
++ * copy. UBI also calculates data CRC when the data is moved and stores it at
++ * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
++ * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
++ * examined. If it is cleared, the situation* is simple and the newer one is
++ * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
++ * checksum is correct, this physical eraseblock is selected (P1). Otherwise
++ * the older one (P) is selected.
++ *
++ * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
++ * in the past. But it is not used anymore and we keep it in order to be able
++ * to deal with old UBI images. It will be removed at some point.
++ *
++ * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
++ * Internal volumes are not seen from outside and are used for various internal
++ * UBI purposes. In this implementation there is only one internal volume - the
++ * layout volume. Internal volumes are the main mechanism of UBI extensions.
++ * For example, in future one may introduce a journal internal volume. Internal
++ * volumes have their own reserved range of IDs.
++ *
++ * The @compat field is only used for internal volumes and contains the "degree
++ * of their compatibility". It is always zero for user volumes. This field
++ * provides a mechanism to introduce UBI extensions and to be still compatible
++ * with older UBI binaries. For example, if someone introduced a journal in
++ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
++ * journal volume. And in this case, older UBI binaries, which know nothing
++ * about the journal volume, would just delete this volume and work perfectly
++ * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
++ * - it just ignores the Ext3fs journal.
++ *
++ * The @data_crc field contains the CRC checksum of the contents of the logical
++ * eraseblock if this is a static volume. In case of dynamic volumes, it does
++ * not contain the CRC checksum as a rule. The only exception is when the
++ * data of the physical eraseblock was moved by the wear-leveling unit, then
++ * the wear-leveling unit calculates the data CRC and stores it in the
++ * @data_crc field. And of course, the @copy_flag is %in this case.
++ *
++ * The @data_size field is used only for static volumes because UBI has to know
++ * how many bytes of data are stored in this eraseblock. For dynamic volumes,
++ * this field usually contains zero. The only exception is when the data of the
++ * physical eraseblock was moved to another physical eraseblock for
++ * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
++ * contents and uses both @data_crc and @data_size fields. In this case, the
++ * @data_size field contains data size.
++ *
++ * The @used_ebs field is used only for static volumes and indicates how many
++ * eraseblocks the data of the volume takes. For dynamic volumes this field is
++ * not used and always contains zero.
++ *
++ * The @data_pad is calculated when volumes are created using the alignment
++ * parameter. So, effectively, the @data_pad field reduces the size of logical
++ * eraseblocks of this volume. This is very handy when one uses block-oriented
++ * software (say, cramfs) on top of the UBI volume.
++ */
++struct ubi_vid_hdr {
++ __be32 magic;
++ __u8 version;
++ __u8 vol_type;
++ __u8 copy_flag;
++ __u8 compat;
++ __be32 vol_id;
++ __be32 lnum;
++ __be32 leb_ver; /* obsolete, to be removed, don't use */
++ __be32 data_size;
++ __be32 used_ebs;
++ __be32 data_pad;
++ __be32 data_crc;
++ __u8 padding1[4];
++ __be64 sqnum;
++ __u8 padding2[12];
++ __be32 hdr_crc;
++} __attribute__ ((packed));
++
++/* Internal UBI volumes count */
++#define UBI_INT_VOL_COUNT 1
++
++/*
++ * Starting ID of internal volumes. There is reserved room for 4096 internal
++ * volumes.
++ */
++#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
++
++/* The layout volume contains the volume table */
++
++#define UBI_LAYOUT_VOLUME_ID UBI_INTERNAL_VOL_START
++#define UBI_LAYOUT_VOLUME_TYPE UBI_VID_DYNAMIC
++#define UBI_LAYOUT_VOLUME_ALIGN 1
++#define UBI_LAYOUT_VOLUME_EBS 2
++#define UBI_LAYOUT_VOLUME_NAME "layout volume"
++#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
++
++/* The maximum number of volumes per one UBI device */
++#define UBI_MAX_VOLUMES 128
++
++/* The maximum volume name length */
++#define UBI_VOL_NAME_MAX 127
++
++/* Size of the volume table record */
++#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
++
++/* Size of the volume table record without the ending CRC */
++#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
++
++/**
++ * struct ubi_vtbl_record - a record in the volume table.
++ * @reserved_pebs: how many physical eraseblocks are reserved for this volume
++ * @alignment: volume alignment
++ * @data_pad: how many bytes are unused at the end of the each physical
++ * eraseblock to satisfy the requested alignment
++ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
++ * @upd_marker: if volume update was started but not finished
++ * @name_len: volume name length
++ * @name: the volume name
++ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
++ * @padding: reserved, zeroes
++ * @crc: a CRC32 checksum of the record
++ *
++ * The volume table records are stored in the volume table, which is stored in
++ * the layout volume. The layout volume consists of 2 logical eraseblock, each
++ * of which contains a copy of the volume table (i.e., the volume table is
++ * duplicated). The volume table is an array of &struct ubi_vtbl_record
++ * objects indexed by the volume ID.
++ *
++ * If the size of the logical eraseblock is large enough to fit
++ * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
++ * records. Otherwise, it contains as many records as it can fit (i.e., size of
++ * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
++ *
++ * The @upd_marker flag is used to implement volume update. It is set to %1
++ * before update and set to %0 after the update. So if the update operation was
++ * interrupted, UBI knows that the volume is corrupted.
++ *
++ * The @alignment field is specified when the volume is created and cannot be
++ * later changed. It may be useful, for example, when a block-oriented file
++ * system works on top of UBI. The @data_pad field is calculated using the
++ * logical eraseblock size and @alignment. The alignment must be multiple to the
++ * minimal flash I/O unit. If @alignment is 1, all the available space of
++ * the physical eraseblocks is used.
++ *
++ * Empty records contain all zeroes and the CRC checksum of those zeroes.
++ */
++struct ubi_vtbl_record {
++ __be32 reserved_pebs;
++ __be32 alignment;
++ __be32 data_pad;
++ __u8 vol_type;
++ __u8 upd_marker;
++ __be16 name_len;
++ __u8 name[UBI_VOL_NAME_MAX+1];
++ __u8 flags;
++ __u8 padding[23];
++ __be32 crc;
++} __attribute__ ((packed));
++
++#endif /* !__UBI_MEDIA_H__ */
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/upd.c avr32-2.6/drivers/mtd/ubi/upd.c
+--- linux-2.6.25.6/drivers/mtd/ubi/upd.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/upd.c 2008-06-12 15:09:41.123815692 +0200
+@@ -237,10 +237,10 @@
+ int err;
+
+ if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
+- len = ALIGN(len, ubi->min_io_size);
+- memset(buf + len, 0xFF, len - len);
++ int l = ALIGN(len, ubi->min_io_size);
+
+- len = ubi_calc_data_len(ubi, buf, len);
++ memset(buf + len, 0xFF, l - len);
++ len = ubi_calc_data_len(ubi, buf, l);
+ if (len == 0) {
+ dbg_msg("all %d bytes contain 0xFF - skip", len);
+ return 0;
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/vmt.c avr32-2.6/drivers/mtd/ubi/vmt.c
+--- linux-2.6.25.6/drivers/mtd/ubi/vmt.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/vmt.c 2008-06-12 15:09:41.123815692 +0200
+@@ -127,6 +127,7 @@
+ {
+ struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
+
++ kfree(vol->eba_tbl);
+ kfree(vol);
+ }
+
+@@ -201,7 +202,7 @@
+ */
+ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
+ {
+- int i, err, vol_id = req->vol_id, dont_free = 0;
++ int i, err, vol_id = req->vol_id, do_free = 1;
+ struct ubi_volume *vol;
+ struct ubi_vtbl_record vtbl_rec;
+ uint64_t bytes;
+@@ -365,14 +366,14 @@
+
+ out_sysfs:
+ /*
+- * We have registered our device, we should not free the volume*
++ * We have registered our device, we should not free the volume
+ * description object in this function in case of an error - it is
+ * freed by the release function.
+ *
+ * Get device reference to prevent the release function from being
+ * called just after sysfs has been closed.
+ */
+- dont_free = 1;
++ do_free = 0;
+ get_device(&vol->dev);
+ volume_sysfs_close(vol);
+ out_gluebi:
+@@ -382,17 +383,18 @@
+ out_cdev:
+ cdev_del(&vol->cdev);
+ out_mapping:
+- kfree(vol->eba_tbl);
++ if (do_free)
++ kfree(vol->eba_tbl);
+ out_acc:
+ spin_lock(&ubi->volumes_lock);
+ ubi->rsvd_pebs -= vol->reserved_pebs;
+ ubi->avail_pebs += vol->reserved_pebs;
+ out_unlock:
+ spin_unlock(&ubi->volumes_lock);
+- if (dont_free)
+- put_device(&vol->dev);
+- else
++ if (do_free)
+ kfree(vol);
++ else
++ put_device(&vol->dev);
+ ubi_err("cannot create volume %d, error %d", vol_id, err);
+ return err;
+ }
+@@ -445,8 +447,6 @@
+ goto out_err;
+ }
+
+- kfree(vol->eba_tbl);
+- vol->eba_tbl = NULL;
+ cdev_del(&vol->cdev);
+ volume_sysfs_close(vol);
+
+@@ -727,7 +727,7 @@
+ goto fail;
+ }
+
+- n = vol->alignment % ubi->min_io_size;
++ n = vol->alignment & (ubi->min_io_size - 1);
+ if (vol->alignment != 1 && n) {
+ ubi_err("alignment is not multiple of min I/O unit");
+ goto fail;
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/vtbl.c avr32-2.6/drivers/mtd/ubi/vtbl.c
+--- linux-2.6.25.6/drivers/mtd/ubi/vtbl.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/vtbl.c 2008-06-12 15:09:41.127815922 +0200
+@@ -127,7 +127,7 @@
+ const struct ubi_vtbl_record *vtbl)
+ {
+ int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len;
+- int upd_marker;
++ int upd_marker, err;
+ uint32_t crc;
+ const char *name;
+
+@@ -153,7 +153,7 @@
+ if (reserved_pebs == 0) {
+ if (memcmp(&vtbl[i], &empty_vtbl_record,
+ UBI_VTBL_RECORD_SIZE)) {
+- dbg_err("bad empty record");
++ err = 2;
+ goto bad;
+ }
+ continue;
+@@ -161,56 +161,57 @@
+
+ if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 ||
+ name_len < 0) {
+- dbg_err("negative values");
++ err = 3;
+ goto bad;
+ }
+
+ if (alignment > ubi->leb_size || alignment == 0) {
+- dbg_err("bad alignment");
++ err = 4;
+ goto bad;
+ }
+
+- n = alignment % ubi->min_io_size;
++ n = alignment & (ubi->min_io_size - 1);
+ if (alignment != 1 && n) {
+- dbg_err("alignment is not multiple of min I/O unit");
++ err = 5;
+ goto bad;
+ }
+
+ n = ubi->leb_size % alignment;
+ if (data_pad != n) {
+ dbg_err("bad data_pad, has to be %d", n);
++ err = 6;
+ goto bad;
+ }
+
+ if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
+- dbg_err("bad vol_type");
++ err = 7;
+ goto bad;
+ }
+
+ if (upd_marker != 0 && upd_marker != 1) {
+- dbg_err("bad upd_marker");
++ err = 8;
+ goto bad;
+ }
+
+ if (reserved_pebs > ubi->good_peb_count) {
+ dbg_err("too large reserved_pebs, good PEBs %d",
+ ubi->good_peb_count);
++ err = 9;
+ goto bad;
+ }
+
+ if (name_len > UBI_VOL_NAME_MAX) {
+- dbg_err("too long volume name, max %d",
+- UBI_VOL_NAME_MAX);
++ err = 10;
+ goto bad;
+ }
+
+ if (name[0] == '\0') {
+- dbg_err("NULL volume name");
++ err = 11;
+ goto bad;
+ }
+
+ if (name_len != strnlen(name, name_len + 1)) {
+- dbg_err("bad name_len");
++ err = 12;
+ goto bad;
+ }
+ }
+@@ -235,7 +236,7 @@
+ return 0;
+
+ bad:
+- ubi_err("volume table check failed, record %d", i);
++ ubi_err("volume table check failed: record %d, error %d", i, err);
+ ubi_dbg_dump_vtbl_record(&vtbl[i], i);
+ return -EINVAL;
+ }
+@@ -384,7 +385,16 @@
+ err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
+ ubi->vtbl_size);
+ if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
+- /* Scrub the PEB later */
++ /*
++ * Scrub the PEB later. Note, -EBADMSG indicates an
++ * uncorrectable ECC error, but we have our own CRC and
++ * the data will be checked later. If the data is OK,
++ * the PEB will be scrubbed (because we set
++ * seb->scrub). If the data is not OK, the contents of
++ * the PEB will be recovered from the second copy, and
++ * seb->scrub will be cleared in
++ * 'ubi_scan_add_used()'.
++ */
+ seb->scrub = 1;
+ else if (err)
+ goto out_free;
+@@ -620,30 +630,32 @@
+ static int check_sv(const struct ubi_volume *vol,
+ const struct ubi_scan_volume *sv)
+ {
++ int err;
++
+ if (sv->highest_lnum >= vol->reserved_pebs) {
+- dbg_err("bad highest_lnum");
++ err = 1;
+ goto bad;
+ }
+ if (sv->leb_count > vol->reserved_pebs) {
+- dbg_err("bad leb_count");
++ err = 2;
+ goto bad;
+ }
+ if (sv->vol_type != vol->vol_type) {
+- dbg_err("bad vol_type");
++ err = 3;
+ goto bad;
+ }
+ if (sv->used_ebs > vol->reserved_pebs) {
+- dbg_err("bad used_ebs");
++ err = 4;
+ goto bad;
+ }
+ if (sv->data_pad != vol->data_pad) {
+- dbg_err("bad data_pad");
++ err = 5;
+ goto bad;
+ }
+ return 0;
+
+ bad:
+- ubi_err("bad scanning information");
++ ubi_err("bad scanning information, error %d", err);
+ ubi_dbg_dump_sv(sv);
+ ubi_dbg_dump_vol_info(vol);
+ return -EINVAL;
+@@ -672,14 +684,13 @@
+ return -EINVAL;
+ }
+
+- if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT&&
++ if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
+ si->highest_vol_id < UBI_INTERNAL_VOL_START) {
+ ubi_err("too large volume ID %d found by scanning",
+ si->highest_vol_id);
+ return -EINVAL;
+ }
+
+-
+ for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+ cond_resched();
+
+diff --exclude=.git -urN linux-2.6.25.6/drivers/mtd/ubi/wl.c avr32-2.6/drivers/mtd/ubi/wl.c
+--- linux-2.6.25.6/drivers/mtd/ubi/wl.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/mtd/ubi/wl.c 2008-06-12 15:09:41.127815922 +0200
+@@ -1368,7 +1368,7 @@
+ int err;
+
+ if (kthread_should_stop())
+- goto out;
++ break;
+
+ if (try_to_freeze())
+ continue;
+@@ -1403,7 +1403,6 @@
+ cond_resched();
+ }
+
+-out:
+ dbg_wl("background thread \"%s\" is killed", ubi->bgt_name);
+ return 0;
+ }
+diff --exclude=.git -urN linux-2.6.25.6/drivers/net/macb.c avr32-2.6/drivers/net/macb.c
+--- linux-2.6.25.6/drivers/net/macb.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/net/macb.c 2008-06-12 15:09:41.343816061 +0200
+@@ -1277,8 +1277,45 @@
+ return 0;
+ }
+
++#ifdef CONFIG_PM
++static int macb_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct net_device *netdev = platform_get_drvdata(pdev);
++ struct macb *bp = netdev_priv(netdev);
++
++ netif_device_detach(netdev);
++
++#ifndef CONFIG_ARCH_AT91
++ clk_disable(bp->hclk);
++#endif
++ clk_disable(bp->pclk);
++
++ return 0;
++}
++
++static int macb_resume(struct platform_device *pdev)
++{
++ struct net_device *netdev = platform_get_drvdata(pdev);
++ struct macb *bp = netdev_priv(netdev);
++
++ clk_enable(bp->pclk);
++#ifndef CONFIG_ARCH_AT91
++ clk_enable(bp->hclk);
++#endif
++
++ netif_device_attach(netdev);
++
++ return 0;
++}
++#else
++#define macb_suspend NULL
++#define macb_resume NULL
++#endif
++
+ static struct platform_driver macb_driver = {
+ .remove = __exit_p(macb_remove),
++ .suspend = macb_suspend,
++ .resume = macb_resume,
+ .driver = {
+ .name = "macb",
+ },
+diff --exclude=.git -urN linux-2.6.25.6/drivers/parport/Kconfig avr32-2.6/drivers/parport/Kconfig
+--- linux-2.6.25.6/drivers/parport/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/parport/Kconfig 2008-06-12 15:04:01.310815768 +0200
+@@ -36,7 +36,7 @@
+ config PARPORT_PC
+ tristate "PC-style hardware"
+ depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \
+- (!M68K || ISA) && !MN10300
++ (!M68K || ISA) && !MN10300 && !AVR32
+ ---help---
+ You should say Y here if you have a PC-style parallel port. All
+ IBM PC compatible computers and some Alphas have PC-style
+diff --exclude=.git -urN linux-2.6.25.6/drivers/pcmcia/at32_cf.c avr32-2.6/drivers/pcmcia/at32_cf.c
+--- linux-2.6.25.6/drivers/pcmcia/at32_cf.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/drivers/pcmcia/at32_cf.c 2008-06-12 15:09:42.047816626 +0200
+@@ -0,0 +1,533 @@
++/*
++ * Driver for AVR32 Static Memory Controller: CompactFlash support
++ *
++ * Copyright (C) 2006 Atmel Norway
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * The full GNU General Public License is included in this
++ * distribution in the file called COPYING.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/dma-mapping.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/gpio.h>
++#include <asm/io.h>
++#include <asm/arch/board.h>
++
++#include <asm/arch/smc.h>
++
++struct at32_cf_socket {
++ struct pcmcia_socket socket;
++ int detect_pin;
++ int reset_pin;
++ int vcc_pin;
++ int ready_pin;
++ struct resource res_attr;
++ struct resource res_mem;
++ struct resource res_io;
++ struct smc_config smc;
++ unsigned int irq;
++ unsigned int cf_cs;
++ socket_state_t state;
++ unsigned present:1;
++};
++#define to_at32_cf(sock) container_of(sock, struct at32_cf_socket, socket)
++
++/*
++ * We have the following memory layout relative to the base address:
++ *
++ * Alt IDE Mode: 00e0 0000 -> 00ff ffff
++ * True IDE Mode: 00c0 0000 -> 00df ffff
++ * I/O memory: 0080 0000 -> 00bf ffff
++ * Common memory: 0040 0000 -> 007f ffff
++ * Attribute memory: 0000 0000 -> 003f ffff
++ */
++#define CF_ATTR_OFFSET 0x00000000
++#define CF_MEM_OFFSET 0x00400000
++#define CF_IO_OFFSET 0x00800000
++#define CF_RES_SIZE 4096
++
++#ifdef DEBUG
++
++static int pc_debug;
++module_param(pc_debug, int, 0644);
++
++static void at32_cf_debug(struct at32_cf_socket *cf, const char *func,
++ int level, const char *fmt, ...)
++{
++ va_list args;
++
++ if (pc_debug > level) {
++ printk(KERN_DEBUG "at32_cf/%u: %s: ", cf->cf_cs, func);
++ va_start(args, fmt);
++ vprintk(fmt, args);
++ va_end(args);
++ }
++}
++
++#define debug(cf, lvl, fmt, arg...) \
++ at32_cf_debug(cf, __func__, lvl, fmt, ##arg)
++
++#else
++#define debug(cf, lvl, fmt, arg...) do { } while (0)
++#endif
++
++static inline int at32_cf_present(struct at32_cf_socket *cf)
++{
++ int present = 1;
++
++ /* If we don't have a detect pin, assume the card is present */
++ if (cf->detect_pin >= 0)
++ present = !gpio_get_value(cf->detect_pin);
++
++ return present;
++}
++
++static irqreturn_t at32_cf_irq(int irq, void *dev_id)
++{
++ struct at32_cf_socket *cf = dev_id;
++ unsigned int present;
++
++ present = at32_cf_present(cf);
++ if (present != cf->present) {
++ cf->present = present;
++ debug(cf, 3, "card %s\n", present ? "present" : "gone");
++ pcmcia_parse_events(&cf->socket, SS_DETECT);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int at32_cf_get_status(struct pcmcia_socket *sock, u_int *value)
++{
++ struct at32_cf_socket *cf;
++ u_int status = 0;
++
++ cf = container_of(sock, struct at32_cf_socket, socket);
++
++ if (at32_cf_present(cf)) {
++ /* NOTE: gpio on AP7xxx is 3.3V */
++ status = SS_DETECT | SS_3VCARD;
++ if (cf->ready_pin < 0 || gpio_get_value(cf->ready_pin))
++ status |= SS_READY;
++ if (cf->vcc_pin < 0 || gpio_get_value(cf->vcc_pin))
++ status |= SS_POWERON;
++ }
++
++ *value = status;
++ return 0;
++}
++
++static int at32_cf_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
++{
++ struct at32_cf_socket *cf = container_of(sock, struct at32_cf_socket, socket);
++
++ debug(cf, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
++ (state->csc_mask==0)?"<NONE> ":"",
++ (state->csc_mask&SS_DETECT)?"DETECT ":"",
++ (state->csc_mask&SS_READY)?"READY ":"",
++ (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
++ (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
++ (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
++ (state->flags==0)?"<NONE> ":"",
++ (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
++ (state->flags&SS_IOCARD)?"IOCARD ":"",
++ (state->flags&SS_RESET)?"RESET ":"",
++ (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
++ (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
++ state->Vcc, state->Vpp, state->io_irq);
++
++ /*
++ * TODO: Allow boards to override this in case they have level
++ * converters.
++ */
++ switch (state->Vcc) {
++ case 0:
++ if (cf->vcc_pin >= 0)
++ gpio_set_value(cf->vcc_pin, 0);
++ break;
++ case 33:
++ if (cf->vcc_pin >= 0)
++ gpio_set_value(cf->vcc_pin, 1);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ if (cf->reset_pin >= 0)
++ gpio_set_value(cf->reset_pin, state->flags & SS_RESET);
++
++ cf->state = *state;
++
++ return 0;
++}
++
++static int at32_cf_socket_init(struct pcmcia_socket *sock)
++{
++ debug(to_at32_cf(sock), 2, "called\n");
++
++ return 0;
++}
++
++static int at32_cf_suspend(struct pcmcia_socket *sock)
++{
++ debug(to_at32_cf(sock), 2, "called\n");
++
++ at32_cf_set_socket(sock, &dead_socket);
++
++ return 0;
++}
++
++static int at32_cf_set_io_map(struct pcmcia_socket *sock,
++ struct pccard_io_map *map)
++{
++ struct at32_cf_socket *cf = container_of(sock, struct at32_cf_socket, socket);
++ int retval;
++
++ debug(cf, 2, "map %u speed %u start 0x%08x stop 0x%08x\n",
++ map->map, map->speed, map->start, map->stop);
++ debug(cf, 2, "flags: %s%s%s%s%s%s%s%s\n",
++ (map->flags == 0) ? "<NONE>":"",
++ (map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
++ (map->flags & MAP_16BIT) ? "16BIT " : "",
++ (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
++ (map->flags & MAP_0WS) ? "0WS " : "",
++ (map->flags & MAP_WRPROT) ? "WRPROT " : "",
++ (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "",
++ (map->flags & MAP_PREFETCH) ? "PREFETCH " : "");
++
++ map->flags &= MAP_ACTIVE | MAP_16BIT | MAP_USE_WAIT;
++
++ if (map->flags & MAP_16BIT)
++ cf->smc.bus_width = 2;
++ else
++ cf->smc.bus_width = 1;
++
++ if (map->flags & MAP_USE_WAIT)
++ cf->smc.nwait_mode = 3;
++ else
++ cf->smc.nwait_mode = 0;
++
++ retval = smc_set_configuration(cf->cf_cs, &cf->smc);
++ if (retval) {
++ printk(KERN_ERR "at32_cf: could not set up SMC for I/O\n");
++ return retval;
++ }
++
++ map->start = cf->socket.io_offset;
++ map->stop = map->start + CF_RES_SIZE - 1;
++
++ return 0;
++}
++
++static int
++at32_cf_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
++{
++ struct at32_cf_socket *cf;
++ struct resource *res;
++ int retval;
++
++ cf = container_of(sock, struct at32_cf_socket, socket);
++
++ debug(cf, 2, "map %u speed %u card_start %08x\n",
++ map->map, map->speed, map->card_start);
++ debug(cf, 2, "flags: %s%s%s%s%s%s%s%s\n",
++ (map->flags==0)?"<NONE>":"",
++ (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
++ (map->flags&MAP_16BIT)?"16BIT ":"",
++ (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
++ (map->flags&MAP_0WS)?"0WS ":"",
++ (map->flags&MAP_WRPROT)?"WRPROT ":"",
++ (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
++ (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
++
++ if (map->card_start)
++ return -EINVAL;
++
++ map->flags &= MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT | MAP_USE_WAIT;
++
++ if (map->flags & MAP_ATTRIB) {
++ res = &cf->res_attr;
++
++ /* Linksys WCF12 seems to use WAIT when reading CIS */
++ map->flags |= MAP_USE_WAIT;
++ } else {
++ res = &cf->res_mem;
++ }
++
++ if (map->flags & MAP_USE_WAIT)
++ cf->smc.nwait_mode = 3;
++ else
++ cf->smc.nwait_mode = 0;
++
++ retval = smc_set_configuration(cf->cf_cs, &cf->smc);
++ if (retval) {
++ printk(KERN_ERR "at32_cf: could not set up SMC for mem\n");
++ return retval;
++ }
++
++ map->static_start = res->start;
++
++ return 0;
++}
++
++static struct pccard_operations at32_cf_ops = {
++ .init = at32_cf_socket_init,
++ .suspend = at32_cf_suspend,
++ .get_status = at32_cf_get_status,
++ .set_socket = at32_cf_set_socket,
++ .set_io_map = at32_cf_set_io_map,
++ .set_mem_map = at32_cf_set_mem_map,
++};
++
++static int __init request_pin(struct platform_device *pdev,
++ unsigned int pin, const char *name)
++{
++ if (gpio_request(pin, name)) {
++ dev_warn(&pdev->dev, "failed to request %s pin\n", name);
++ return -1;
++ }
++
++ return pin;
++}
++
++static struct smc_timing at32_cf_timing __initdata = {
++ .ncs_read_setup = 30,
++ .nrd_setup = 100,
++ .ncs_write_setup = 30,
++ .nwe_setup = 100,
++
++ .ncs_read_pulse = 360,
++ .nrd_pulse = 290,
++ .ncs_write_pulse = 360,
++ .nwe_pulse = 290,
++
++ .read_cycle = 420,
++ .write_cycle = 420,
++};
++
++static int __init at32_cf_probe(struct platform_device *pdev)
++{
++ struct at32_cf_socket *cf;
++ struct cf_platform_data *board = pdev->dev.platform_data;
++ struct resource *res_skt;
++ int irq;
++ int ret;
++
++ dev_dbg(&pdev->dev, "probe");
++
++ if (!board)
++ return -ENXIO;
++
++ res_skt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res_skt)
++ return -ENXIO;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return irq;
++
++ cf = kzalloc(sizeof(struct at32_cf_socket), GFP_KERNEL);
++ if (!cf)
++ return -ENOMEM;
++
++ cf->detect_pin = -1;
++ cf->reset_pin = -1;
++ cf->vcc_pin = -1;
++ cf->ready_pin = -1;
++ cf->cf_cs = board->cs;
++
++ if (board->detect_pin != GPIO_PIN_NONE)
++ cf->detect_pin = request_pin(pdev, board->detect_pin,
++ "cf_detect");
++ if (board->reset_pin != GPIO_PIN_NONE)
++ cf->reset_pin = request_pin(pdev, board->reset_pin,
++ "cf_reset");
++ if (board->vcc_pin != GPIO_PIN_NONE)
++ cf->vcc_pin = request_pin(pdev, board->vcc_pin,
++ "cf_vcc");
++ if (board->ready_pin != GPIO_PIN_NONE)
++ /* READY is also used for irq through EIM */
++ cf->ready_pin = board->ready_pin;
++
++ debug(cf, 2, "pins: detect=%d reset=%d vcc=%d\n",
++ cf->detect_pin, cf->reset_pin, cf->vcc_pin);
++
++ cf->socket.pci_irq = irq;
++ cf->socket.ops = &at32_cf_ops;
++ cf->socket.resource_ops = &pccard_static_ops;
++ cf->socket.dev.parent = &pdev->dev;
++ cf->socket.owner = THIS_MODULE;
++ cf->socket.features =
++ SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
++ cf->socket.map_size = CF_RES_SIZE;
++
++ cf->res_attr.start = res_skt->start + CF_ATTR_OFFSET;
++ cf->res_attr.end = cf->res_attr.start + CF_RES_SIZE - 1;
++ cf->res_attr.name = "attribute";
++ cf->res_attr.flags = IORESOURCE_MEM;
++ ret = request_resource(res_skt, &cf->res_attr);
++ if (ret)
++ goto err_request_res_attr;
++
++ cf->res_mem.start = res_skt->start + CF_MEM_OFFSET;
++ cf->res_mem.end = cf->res_mem.start + CF_RES_SIZE - 1;
++ cf->res_mem.name = "memory";
++ cf->res_mem.flags = IORESOURCE_MEM;
++ ret = request_resource(res_skt, &cf->res_mem);
++ if (ret)
++ goto err_request_res_mem;
++
++ cf->res_io.start = res_skt->start + CF_IO_OFFSET;
++ cf->res_io.end = cf->res_io.start + CF_RES_SIZE - 1;
++ cf->res_io.name = "io";
++ cf->res_io.flags = IORESOURCE_MEM;
++ ret = request_resource(res_skt, &cf->res_io);
++ if (ret)
++ goto err_request_res_io;
++
++ cf->socket.io_offset = cf->res_io.start;
++
++ if (cf->detect_pin >= 0) {
++ ret = request_irq(gpio_to_irq(cf->detect_pin), at32_cf_irq,
++ IRQF_SHARED, "cf_detect", cf);
++ if (ret) {
++ debug(cf, 1,
++ "failed to request cf_detect interrupt\n");
++ goto err_detect_irq;
++ }
++ }
++
++ cf->present = at32_cf_present(cf);
++
++ /* Setup SMC timings */
++ smc_set_timing(&cf->smc, &at32_cf_timing);
++
++ cf->smc.bus_width = 2;
++ cf->smc.nrd_controlled = 1;
++ cf->smc.nwe_controlled = 1;
++ cf->smc.nwait_mode = 0;
++ cf->smc.byte_write = 0;
++ cf->smc.tdf_cycles = 8;
++ cf->smc.tdf_mode = 0;
++
++ ret = smc_set_configuration(cf->cf_cs, &cf->smc);
++ if (ret) {
++ debug(cf, 1, "failed to configure SMC\n", ret);
++ goto err_smc;
++ }
++
++ ret = pcmcia_register_socket(&cf->socket);
++ if (ret) {
++ debug(cf, 1, "failed to register socket: %d\n", ret);
++ goto err_register_socket;
++ }
++
++ if (cf->reset_pin >= 0)
++ gpio_direction_output(cf->reset_pin, 0);
++
++ platform_set_drvdata(pdev, cf);
++
++ dev_info(&pdev->dev, "Atmel SMC CF interface at 0x%08lx\n",
++ (unsigned long)res_skt->start);
++
++ return 0;
++
++err_register_socket:
++err_smc:
++ if (cf->detect_pin >= 0)
++ free_irq(gpio_to_irq(cf->detect_pin), cf);
++err_detect_irq:
++ release_resource(&cf->res_io);
++err_request_res_io:
++ release_resource(&cf->res_mem);
++err_request_res_mem:
++ release_resource(&cf->res_attr);
++err_request_res_attr:
++ if (cf->vcc_pin >= 0)
++ gpio_free(cf->vcc_pin);
++ if (cf->reset_pin >= 0)
++ gpio_free(cf->reset_pin);
++ if (cf->detect_pin >= 0)
++ gpio_free(cf->detect_pin);
++ kfree(cf);
++
++ return ret;
++}
++
++static int __exit at32_cf_remove(struct platform_device *pdev)
++{
++ struct at32_cf_socket *cf = platform_get_drvdata(pdev);
++
++ pcmcia_unregister_socket(&cf->socket);
++ if (cf->detect_pin >= 0) {
++ free_irq(gpio_to_irq(cf->detect_pin), cf);
++ gpio_free(cf->detect_pin);
++ }
++ if (cf->vcc_pin >= 0)
++ gpio_free(cf->vcc_pin);
++ if (cf->reset_pin >= 0)
++ gpio_free(cf->reset_pin);
++
++ release_resource(&cf->res_io);
++ release_resource(&cf->res_mem);
++ release_resource(&cf->res_attr);
++ kfree(cf);
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++static struct platform_driver at32_cf_driver = {
++ .remove = __exit_p(at32_cf_remove),
++ .driver = {
++ .name = "at32_cf",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init at32_cf_init(void)
++{
++ int ret;
++
++ ret = platform_driver_probe(&at32_cf_driver, at32_cf_probe);
++ if (ret)
++ printk(KERN_ERR "at32_cf: probe failed: %d\n", ret);
++ return ret;
++}
++
++static void __exit at32_cf_exit(void)
++{
++ platform_driver_unregister(&at32_cf_driver);
++}
++
++module_init(at32_cf_init);
++module_exit(at32_cf_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Driver for SMC PCMCIA interface");
++MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+diff --exclude=.git -urN linux-2.6.25.6/drivers/pcmcia/Kconfig avr32-2.6/drivers/pcmcia/Kconfig
+--- linux-2.6.25.6/drivers/pcmcia/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/pcmcia/Kconfig 2008-06-12 15:09:42.047816626 +0200
+@@ -277,6 +277,13 @@
+ Say Y here to support the CompactFlash controller on the
+ PA Semi Electra eval board.
+
++config AT32_CF
++ tristate "AT32AP CompactFlash Controller"
++ depends on PCMCIA && AVR32 && PLATFORM_AT32AP
++ help
++ Say Y here to support the CompactFlash controller on AT32 chips.
++ Or choose M to compile the driver as a module named "at32_cf".
++
+ config PCCARD_NONSTATIC
+ tristate
+
+diff --exclude=.git -urN linux-2.6.25.6/drivers/pcmcia/Makefile avr32-2.6/drivers/pcmcia/Makefile
+--- linux-2.6.25.6/drivers/pcmcia/Makefile 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/pcmcia/Makefile 2008-06-12 15:09:42.047816626 +0200
+@@ -38,6 +38,7 @@
+ obj-$(CONFIG_OMAP_CF) += omap_cf.o
+ obj-$(CONFIG_AT91_CF) += at91_cf.o
+ obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
++obj-$(CONFIG_AT32_CF) += at32_cf.o
+
+ sa11xx_core-y += soc_common.o sa11xx_base.o
+ pxa2xx_core-y += soc_common.o pxa2xx_base.o
+diff --exclude=.git -urN linux-2.6.25.6/drivers/serial/atmel_serial.c avr32-2.6/drivers/serial/atmel_serial.c
+--- linux-2.6.25.6/drivers/serial/atmel_serial.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/serial/atmel_serial.c 2008-06-12 15:09:42.514816054 +0200
+@@ -1440,6 +1440,15 @@
+ };
+
+ #ifdef CONFIG_PM
++static bool atmel_serial_clk_will_stop(void)
++{
++#ifdef CONFIG_ARCH_AT91
++ return at91_suspend_entering_slow_clock();
++#else
++ return false;
++#endif
++}
++
+ static int atmel_serial_suspend(struct platform_device *pdev,
+ pm_message_t state)
+ {
+@@ -1447,7 +1456,7 @@
+ struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+ if (device_may_wakeup(&pdev->dev)
+- && !at91_suspend_entering_slow_clock())
++ && !atmel_serial_clk_will_stop())
+ enable_irq_wake(port->irq);
+ else {
+ uart_suspend_port(&atmel_uart, port);
+diff --exclude=.git -urN linux-2.6.25.6/drivers/spi/atmel_spi.c avr32-2.6/drivers/spi/atmel_spi.c
+--- linux-2.6.25.6/drivers/spi/atmel_spi.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/spi/atmel_spi.c 2008-06-12 15:09:42.542815989 +0200
+@@ -51,9 +51,7 @@
+ u8 stopping;
+ struct list_head queue;
+ struct spi_transfer *current_transfer;
+- unsigned long current_remaining_bytes;
+- struct spi_transfer *next_transfer;
+- unsigned long next_remaining_bytes;
++ unsigned long remaining_bytes;
+
+ void *buffer;
+ dma_addr_t buffer_dma;
+@@ -133,48 +131,6 @@
+ gpio_set_value(gpio, !active);
+ }
+
+-static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
+- struct spi_transfer *xfer)
+-{
+- return msg->transfers.prev == &xfer->transfer_list;
+-}
+-
+-static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
+-{
+- return xfer->delay_usecs == 0 && !xfer->cs_change;
+-}
+-
+-static void atmel_spi_next_xfer_data(struct spi_master *master,
+- struct spi_transfer *xfer,
+- dma_addr_t *tx_dma,
+- dma_addr_t *rx_dma,
+- u32 *plen)
+-{
+- struct atmel_spi *as = spi_master_get_devdata(master);
+- u32 len = *plen;
+-
+- /* use scratch buffer only when rx or tx data is unspecified */
+- if (xfer->rx_buf)
+- *rx_dma = xfer->rx_dma + xfer->len - len;
+- else {
+- *rx_dma = as->buffer_dma;
+- if (len > BUFFER_SIZE)
+- len = BUFFER_SIZE;
+- }
+- if (xfer->tx_buf)
+- *tx_dma = xfer->tx_dma + xfer->len - len;
+- else {
+- *tx_dma = as->buffer_dma;
+- if (len > BUFFER_SIZE)
+- len = BUFFER_SIZE;
+- memset(as->buffer, 0, len);
+- dma_sync_single_for_device(&as->pdev->dev,
+- as->buffer_dma, len, DMA_TO_DEVICE);
+- }
+-
+- *plen = len;
+-}
+-
+ /*
+ * Submit next transfer for DMA.
+ * lock is held, spi irq is blocked
+@@ -184,78 +140,53 @@
+ {
+ struct atmel_spi *as = spi_master_get_devdata(master);
+ struct spi_transfer *xfer;
+- u32 len, remaining, total;
++ u32 len;
+ dma_addr_t tx_dma, rx_dma;
+
+- if (!as->current_transfer)
+- xfer = list_entry(msg->transfers.next,
+- struct spi_transfer, transfer_list);
+- else if (!as->next_transfer)
+- xfer = list_entry(as->current_transfer->transfer_list.next,
+- struct spi_transfer, transfer_list);
+- else
+- xfer = NULL;
+-
+- if (xfer) {
+- len = xfer->len;
+- atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+- remaining = xfer->len - len;
+-
+- spi_writel(as, RPR, rx_dma);
+- spi_writel(as, TPR, tx_dma);
+-
+- if (msg->spi->bits_per_word > 8)
+- len >>= 1;
+- spi_writel(as, RCR, len);
+- spi_writel(as, TCR, len);
+-
+- dev_dbg(&msg->spi->dev,
+- " start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+- xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+- xfer->rx_buf, xfer->rx_dma);
+- } else {
+- xfer = as->next_transfer;
+- remaining = as->next_remaining_bytes;
++ xfer = as->current_transfer;
++ if (!xfer || as->remaining_bytes == 0) {
++ if (xfer)
++ xfer = list_entry(xfer->transfer_list.next,
++ struct spi_transfer, transfer_list);
++ else
++ xfer = list_entry(msg->transfers.next,
++ struct spi_transfer, transfer_list);
++ as->remaining_bytes = xfer->len;
++ as->current_transfer = xfer;
+ }
+
+- as->current_transfer = xfer;
+- as->current_remaining_bytes = remaining;
+-
+- if (remaining > 0)
+- len = remaining;
+- else if (!atmel_spi_xfer_is_last(msg, xfer)
+- && atmel_spi_xfer_can_be_chained(xfer)) {
+- xfer = list_entry(xfer->transfer_list.next,
+- struct spi_transfer, transfer_list);
+- len = xfer->len;
+- } else
+- xfer = NULL;
++ len = as->remaining_bytes;
+
+- as->next_transfer = xfer;
++ tx_dma = xfer->tx_dma + xfer->len - len;
++ rx_dma = xfer->rx_dma + xfer->len - len;
+
+- if (xfer) {
+- total = len;
+- atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+- as->next_remaining_bytes = total - len;
+-
+- spi_writel(as, RNPR, rx_dma);
+- spi_writel(as, TNPR, tx_dma);
+-
+- if (msg->spi->bits_per_word > 8)
+- len >>= 1;
+- spi_writel(as, RNCR, len);
+- spi_writel(as, TNCR, len);
+-
+- dev_dbg(&msg->spi->dev,
+- " next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+- xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+- xfer->rx_buf, xfer->rx_dma);
+- } else {
+- spi_writel(as, RNCR, 0);
+- spi_writel(as, TNCR, 0);
++ /* use scratch buffer only when rx or tx data is unspecified */
++ if (!xfer->rx_buf) {
++ rx_dma = as->buffer_dma;
++ if (len > BUFFER_SIZE)
++ len = BUFFER_SIZE;
+ }
++ if (!xfer->tx_buf) {
++ tx_dma = as->buffer_dma;
++ if (len > BUFFER_SIZE)
++ len = BUFFER_SIZE;
++ memset(as->buffer, 0, len);
++ dma_sync_single_for_device(&as->pdev->dev,
++ as->buffer_dma, len, DMA_TO_DEVICE);
++ }
++
++ spi_writel(as, RPR, rx_dma);
++ spi_writel(as, TPR, tx_dma);
+
+- /* REVISIT: We're waiting for ENDRX before we start the next
++ as->remaining_bytes -= len;
++ if (msg->spi->bits_per_word > 8)
++ len >>= 1;
++
++ /* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
++ * mechanism might help avoid the IRQ latency between transfers
++ * (and improve the nCS0 errata handling on at91rm9200 chips)
++ *
++ * We're also waiting for ENDRX before we start the next
+ * transfer because we need to handle some difficult timing
+ * issues otherwise. If we wait for ENDTX in one transfer and
+ * then starts waiting for ENDRX in the next, it's difficult
+@@ -265,7 +196,17 @@
+ *
+ * It should be doable, though. Just not now...
+ */
++ spi_writel(as, TNCR, 0);
++ spi_writel(as, RNCR, 0);
+ spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
++
++ dev_dbg(&msg->spi->dev,
++ " start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n",
++ xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
++ xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR));
++
++ spi_writel(as, RCR, len);
++ spi_writel(as, TCR, len);
+ spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
+ }
+
+@@ -363,7 +304,6 @@
+ spin_lock(&as->lock);
+
+ as->current_transfer = NULL;
+- as->next_transfer = NULL;
+
+ /* continue if needed */
+ if (list_empty(&as->queue) || as->stopping)
+@@ -447,7 +387,7 @@
+
+ spi_writel(as, IDR, pending);
+
+- if (as->current_remaining_bytes == 0) {
++ if (as->remaining_bytes == 0) {
+ msg->actual_length += xfer->len;
+
+ if (!msg->is_dma_mapped)
+@@ -457,7 +397,7 @@
+ if (xfer->delay_usecs)
+ udelay(xfer->delay_usecs);
+
+- if (atmel_spi_xfer_is_last(msg, xfer)) {
++ if (msg->transfers.prev == &xfer->transfer_list) {
+ /* report completed message */
+ atmel_spi_msg_done(master, as, msg, 0,
+ xfer->cs_change);
+diff --exclude=.git -urN linux-2.6.25.6/drivers/usb/gadget/atmel_usba_udc.c avr32-2.6/drivers/usb/gadget/atmel_usba_udc.c
+--- linux-2.6.25.6/drivers/usb/gadget/atmel_usba_udc.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/usb/gadget/atmel_usba_udc.c 2008-06-12 15:09:42.586816287 +0200
+@@ -18,6 +18,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/usb/ch9.h>
+ #include <linux/usb/gadget.h>
++#include <linux/usb/atmel_usba_udc.h>
+ #include <linux/delay.h>
+
+ #include <asm/gpio.h>
+@@ -27,6 +28,7 @@
+
+
+ static struct usba_udc the_udc;
++static struct usba_ep *usba_ep;
+
+ #ifdef CONFIG_USB_GADGET_DEBUG_FS
+ #include <linux/debugfs.h>
+@@ -324,53 +326,28 @@
+ return 1;
+ }
+
+-static void copy_to_fifo(void __iomem *fifo, const void *buf, int len)
+-{
+- unsigned long tmp;
++#if defined(CONFIG_AVR32)
+
+- DBG(DBG_FIFO, "copy to FIFO (len %d):\n", len);
+- for (; len > 0; len -= 4, buf += 4, fifo += 4) {
+- tmp = *(unsigned long *)buf;
+- if (len >= 4) {
+- DBG(DBG_FIFO, " -> %08lx\n", tmp);
+- __raw_writel(tmp, fifo);
+- } else {
+- do {
+- DBG(DBG_FIFO, " -> %02lx\n", tmp >> 24);
+- __raw_writeb(tmp >> 24, fifo);
+- fifo++;
+- tmp <<= 8;
+- } while (--len);
+- break;
+- }
+- }
++static void toggle_bias(int is_on)
++{
+ }
+
+-static void copy_from_fifo(void *buf, void __iomem *fifo, int len)
++#elif defined(CONFIG_ARCH_AT91)
++
++#include <asm/arch/at91_pmc.h>
++
++static void toggle_bias(int is_on)
+ {
+- union {
+- unsigned long *w;
+- unsigned char *b;
+- } p;
+- unsigned long tmp;
+-
+- DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len);
+- for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) {
+- if (len >= 4) {
+- tmp = __raw_readl(fifo);
+- *p.w = tmp;
+- DBG(DBG_FIFO, " -> %08lx\n", tmp);
+- } else {
+- do {
+- tmp = __raw_readb(fifo);
+- *p.b = tmp;
+- DBG(DBG_FIFO, " -> %02lx\n", tmp);
+- fifo++, p.b++;
+- } while (--len);
+- }
+- }
++ unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
++
++ if (is_on)
++ at91_sys_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
++ else
++ at91_sys_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+ }
+
++#endif /* CONFIG_ARCH_AT91 */
++
+ static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+ {
+ unsigned int transaction_len;
+@@ -387,7 +364,7 @@
+ ep->ep.name, req, transaction_len,
+ req->last_transaction ? ", done" : "");
+
+- copy_to_fifo(ep->fifo, req->req.buf + req->req.actual, transaction_len);
++ memcpy_toio(ep->fifo, req->req.buf + req->req.actual, transaction_len);
+ usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+ req->req.actual += transaction_len;
+ }
+@@ -476,7 +453,7 @@
+ bytecount = req->req.length - req->req.actual;
+ }
+
+- copy_from_fifo(req->req.buf + req->req.actual,
++ memcpy_fromio(req->req.buf + req->req.actual,
+ ep->fifo, bytecount);
+ req->req.actual += bytecount;
+
+@@ -1029,33 +1006,6 @@
+ .set_selfpowered = usba_udc_set_selfpowered,
+ };
+
+-#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
+-{ \
+- .ep = { \
+- .ops = &usba_ep_ops, \
+- .name = nam, \
+- .maxpacket = maxpkt, \
+- }, \
+- .udc = &the_udc, \
+- .queue = LIST_HEAD_INIT(usba_ep[idx].queue), \
+- .fifo_size = maxpkt, \
+- .nr_banks = maxbk, \
+- .index = idx, \
+- .can_dma = dma, \
+- .can_isoc = isoc, \
+-}
+-
+-static struct usba_ep usba_ep[] = {
+- EP("ep0", 0, 64, 1, 0, 0),
+- EP("ep1in-bulk", 1, 512, 2, 1, 1),
+- EP("ep2out-bulk", 2, 512, 2, 1, 1),
+- EP("ep3in-int", 3, 64, 3, 1, 0),
+- EP("ep4out-int", 4, 64, 3, 1, 0),
+- EP("ep5in-iso", 5, 1024, 3, 1, 1),
+- EP("ep6out-iso", 6, 1024, 3, 1, 1),
+-};
+-#undef EP
+-
+ static struct usb_endpoint_descriptor usba_ep0_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+@@ -1074,7 +1024,6 @@
+ static struct usba_udc the_udc = {
+ .gadget = {
+ .ops = &usba_udc_ops,
+- .ep0 = &usba_ep[0].ep,
+ .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list),
+ .is_dualspeed = 1,
+ .name = "atmel_usba_udc",
+@@ -1231,7 +1180,7 @@
+ } else {
+ usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+ usba_writel(udc, TST, USBA_TST_PKT_MODE);
+- copy_to_fifo(ep->fifo, test_packet_buffer,
++ memcpy_toio(ep->fifo, test_packet_buffer,
+ sizeof(test_packet_buffer));
+ usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+ dev_info(dev, "Entering Test_Packet mode...\n");
+@@ -1530,13 +1479,13 @@
+ DBG(DBG_HW, "Packet length: %u\n", pkt_len);
+ if (pkt_len != sizeof(crq)) {
+ pr_warning("udc: Invalid packet length %u "
+- "(expected %lu)\n", pkt_len, sizeof(crq));
++ "(expected %zu)\n", pkt_len, sizeof(crq));
+ set_protocol_stall(udc, ep);
+ return;
+ }
+
+ DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
+- copy_from_fifo(crq.data, ep->fifo, sizeof(crq));
++ memcpy_fromio(crq.data, ep->fifo, sizeof(crq));
+
+ /* Free up one bank in the FIFO so that we can
+ * generate or receive a reply right away. */
+@@ -1688,6 +1637,7 @@
+ DBG(DBG_INT, "irq, status=%#08x\n", status);
+
+ if (status & USBA_DET_SUSPEND) {
++ toggle_bias(0);
+ usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
+ DBG(DBG_BUS, "Suspend detected\n");
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN
+@@ -1699,6 +1649,7 @@
+ }
+
+ if (status & USBA_WAKE_UP) {
++ toggle_bias(1);
+ usba_writel(udc, INT_CLR, USBA_WAKE_UP);
+ DBG(DBG_BUS, "Wake Up CPU detected\n");
+ }
+@@ -1792,12 +1743,14 @@
+ vbus = gpio_get_value(udc->vbus_pin);
+ if (vbus != udc->vbus_prev) {
+ if (vbus) {
+- usba_writel(udc, CTRL, USBA_EN_USBA);
++ toggle_bias(1);
++ usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+ usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+ } else {
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ reset_all_endpoints(udc);
+- usba_writel(udc, CTRL, 0);
++ toggle_bias(0);
++ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+ spin_unlock(&udc->lock);
+ udc->driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
+@@ -1850,7 +1803,8 @@
+ /* If Vbus is present, enable the controller and wait for reset */
+ spin_lock_irqsave(&udc->lock, flags);
+ if (vbus_is_present(udc) && udc->vbus_prev == 0) {
+- usba_writel(udc, CTRL, USBA_EN_USBA);
++ toggle_bias(1);
++ usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+ usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+ }
+ spin_unlock_irqrestore(&udc->lock, flags);
+@@ -1883,7 +1837,8 @@
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ /* This will also disable the DP pullup */
+- usba_writel(udc, CTRL, 0);
++ toggle_bias(0);
++ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+
+ driver->unbind(&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+@@ -1908,7 +1863,7 @@
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
+ fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
+- if (!regs || !fifo)
++ if (!regs || !fifo || !pdata)
+ return -ENXIO;
+
+ irq = platform_get_irq(pdev, 0);
+@@ -1953,19 +1908,48 @@
+
+ /* Make sure we start from a clean slate */
+ clk_enable(pclk);
+- usba_writel(udc, CTRL, 0);
++ toggle_bias(0);
++ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+ clk_disable(pclk);
+
++ usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep,
++ GFP_KERNEL);
++ if (!usba_ep)
++ goto err_alloc_ep;
++
++ the_udc.gadget.ep0 = &usba_ep[0].ep;
++
+ INIT_LIST_HEAD(&usba_ep[0].ep.ep_list);
+ usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0);
+ usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0);
+ usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0);
+- for (i = 1; i < ARRAY_SIZE(usba_ep); i++) {
++ usba_ep[0].ep.ops = &usba_ep_ops;
++ usba_ep[0].ep.name = pdata->ep[0].name;
++ usba_ep[0].ep.maxpacket = pdata->ep[0].fifo_size;
++ usba_ep[0].udc = &the_udc;
++ INIT_LIST_HEAD(&usba_ep[0].queue);
++ usba_ep[0].fifo_size = pdata->ep[0].fifo_size;
++ usba_ep[0].nr_banks = pdata->ep[0].nr_banks;
++ usba_ep[0].index = pdata->ep[0].index;
++ usba_ep[0].can_dma = pdata->ep[0].can_dma;
++ usba_ep[0].can_isoc = pdata->ep[0].can_isoc;
++
++ for (i = 1; i < pdata->num_ep; i++) {
+ struct usba_ep *ep = &usba_ep[i];
+
+ ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
+ ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
+ ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
++ ep->ep.ops = &usba_ep_ops;
++ ep->ep.name = pdata->ep[i].name;
++ ep->ep.maxpacket = pdata->ep[i].fifo_size;
++ ep->udc = &the_udc;
++ INIT_LIST_HEAD(&ep->queue);
++ ep->fifo_size = pdata->ep[i].fifo_size;
++ ep->nr_banks = pdata->ep[i].nr_banks;
++ ep->index = pdata->ep[i].index;
++ ep->can_dma = pdata->ep[i].can_dma;
++ ep->can_isoc = pdata->ep[i].can_isoc;
+
+ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+ }
+@@ -1984,7 +1968,7 @@
+ goto err_device_add;
+ }
+
+- if (pdata && pdata->vbus_pin != GPIO_PIN_NONE) {
++ if (pdata->vbus_pin >= 0) {
+ if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
+ udc->vbus_pin = pdata->vbus_pin;
+
+@@ -2004,7 +1988,7 @@
+ }
+
+ usba_init_debugfs(udc);
+- for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++ for (i = 1; i < pdata->num_ep; i++)
+ usba_ep_init_debugfs(udc, &usba_ep[i]);
+
+ return 0;
+@@ -2012,6 +1996,8 @@
+ err_device_add:
+ free_irq(irq, udc);
+ err_request_irq:
++ kfree(usba_ep);
++err_alloc_ep:
+ iounmap(udc->fifo);
+ err_map_fifo:
+ iounmap(udc->regs);
+@@ -2029,10 +2015,11 @@
+ {
+ struct usba_udc *udc;
+ int i;
++ struct usba_platform_data *pdata = pdev->dev.platform_data;
+
+ udc = platform_get_drvdata(pdev);
+
+- for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++ for (i = 1; i < pdata->num_ep; i++)
+ usba_ep_cleanup_debugfs(&usba_ep[i]);
+ usba_cleanup_debugfs(udc);
+
+@@ -2040,6 +2027,7 @@
+ gpio_free(udc->vbus_pin);
+
+ free_irq(udc->irq, udc);
++ kfree(usba_ep);
+ iounmap(udc->fifo);
+ iounmap(udc->regs);
+ clk_put(udc->hclk);
+diff --exclude=.git -urN linux-2.6.25.6/drivers/usb/gadget/atmel_usba_udc.h avr32-2.6/drivers/usb/gadget/atmel_usba_udc.h
+--- linux-2.6.25.6/drivers/usb/gadget/atmel_usba_udc.h 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/usb/gadget/atmel_usba_udc.h 2008-06-12 15:04:02.443815949 +0200
+@@ -41,6 +41,15 @@
+ #define USBA_EN_USBA (1 << 8)
+ #define USBA_DETACH (1 << 9)
+ #define USBA_REMOTE_WAKE_UP (1 << 10)
++#define USBA_PULLD_DIS (1 << 11)
++
++#if defined(CONFIG_AVR32)
++#define USBA_ENABLE_MASK USBA_EN_USBA
++#define USBA_DISABLE_MASK 0
++#elif defined(CONFIG_ARCH_AT91)
++#define USBA_ENABLE_MASK (USBA_EN_USBA | USBA_PULLD_DIS)
++#define USBA_DISABLE_MASK USBA_DETACH
++#endif /* CONFIG_ARCH_AT91 */
+
+ /* Bitfields in FNUM */
+ #define USBA_MICRO_FRAME_NUM_OFFSET 0
+diff --exclude=.git -urN linux-2.6.25.6/drivers/usb/gadget/Kconfig avr32-2.6/drivers/usb/gadget/Kconfig
+--- linux-2.6.25.6/drivers/usb/gadget/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/usb/gadget/Kconfig 2008-06-12 15:09:42.582816057 +0200
+@@ -118,10 +118,10 @@
+ config USB_GADGET_ATMEL_USBA
+ boolean "Atmel USBA"
+ select USB_GADGET_DUALSPEED
+- depends on AVR32
++ depends on AVR32 || ARCH_AT91CAP9
+ help
+ USBA is the integrated high-speed USB Device controller on
+- the AT32AP700x processors from Atmel.
++ the AT32AP700x and AT91CAP9 processors from Atmel.
+
+ config USB_ATMEL_USBA
+ tristate
+diff --exclude=.git -urN linux-2.6.25.6/drivers/video/atmel_lcdfb.c avr32-2.6/drivers/video/atmel_lcdfb.c
+--- linux-2.6.25.6/drivers/video/atmel_lcdfb.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/drivers/video/atmel_lcdfb.c 2008-06-12 15:09:43.343816340 +0200
+@@ -38,7 +38,9 @@
+ #endif
+
+ #if defined(CONFIG_ARCH_AT91)
+-#define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT
++#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
++ | FBINFO_PARTIAL_PAN_OK \
++ | FBINFO_HWACCEL_YPAN)
+
+ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+ struct fb_var_screeninfo *var)
+@@ -176,7 +178,7 @@
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 0,
+- .ypanstep = 0,
++ .ypanstep = 1,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+ };
+@@ -250,6 +252,8 @@
+ return -ENOMEM;
+ }
+
++ memset(info->screen_base, 0, info->fix.smem_len);
++
+ return 0;
+ }
+
+@@ -634,7 +638,6 @@
+ struct fb_info *info = sinfo->info;
+ int ret = 0;
+
+- memset_io(info->screen_base, 0, info->fix.smem_len);
+ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
+
+ dev_info(info->device,
+@@ -764,6 +767,11 @@
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base)
+ goto release_intmem;
++
++ /*
++ * Don't clear the framebuffer -- someone may have set
++ * up a splash image.
++ */
+ } else {
+ /* alocate memory buffer */
+ ret = atmel_lcdfb_alloc_video_memory(sinfo);
+diff --exclude=.git -urN linux-2.6.25.6/fs/fs-writeback.c avr32-2.6/fs/fs-writeback.c
+--- linux-2.6.25.6/fs/fs-writeback.c 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/fs/fs-writeback.c 2008-06-12 15:09:44.531816544 +0200
+@@ -385,8 +385,6 @@
+ * WB_SYNC_HOLD is a hack for sys_sync(): reattach the inode to sb->s_dirty so
+ * that it can be located for waiting on in __writeback_single_inode().
+ *
+- * Called under inode_lock.
+- *
+ * If `bdi' is non-zero then we're being asked to writeback a specific queue.
+ * This function assumes that the blockdev superblock's inodes are backed by
+ * a variety of queues, so all inodes are searched. For other superblocks,
+@@ -402,11 +400,12 @@
+ * on the writer throttling path, and we get decent balancing between many
+ * throttled threads: we don't want them all piling up on inode_sync_wait.
+ */
+-static void
+-sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
++void generic_sync_sb_inodes(struct super_block *sb,
++ struct writeback_control *wbc)
+ {
+ const unsigned long start = jiffies; /* livelock avoidance */
+
++ spin_lock(&inode_lock);
+ if (!wbc->for_kupdate || list_empty(&sb->s_io))
+ queue_io(sb, wbc->older_than_this);
+
+@@ -485,8 +484,16 @@
+ if (!list_empty(&sb->s_more_io))
+ wbc->more_io = 1;
+ }
++ spin_unlock(&inode_lock);
+ return; /* Leave any unwritten inodes on s_io */
+ }
++EXPORT_SYMBOL_GPL(generic_sync_sb_inodes);
++
++static void sync_sb_inodes(struct super_block *sb,
++ struct writeback_control *wbc)
++{
++ generic_sync_sb_inodes(sb, wbc);
++}
+
+ /*
+ * Start writeback of dirty pagecache data against all unlocked inodes.
+@@ -526,11 +533,8 @@
+ * be unmounted by the time it is released.
+ */
+ if (down_read_trylock(&sb->s_umount)) {
+- if (sb->s_root) {
+- spin_lock(&inode_lock);
++ if (sb->s_root)
+ sync_sb_inodes(sb, wbc);
+- spin_unlock(&inode_lock);
+- }
+ up_read(&sb->s_umount);
+ }
+ spin_lock(&sb_lock);
+@@ -568,9 +572,7 @@
+ (inodes_stat.nr_inodes - inodes_stat.nr_unused) +
+ nr_dirty + nr_unstable;
+ wbc.nr_to_write += wbc.nr_to_write / 2; /* Bit more for luck */
+- spin_lock(&inode_lock);
+ sync_sb_inodes(sb, &wbc);
+- spin_unlock(&inode_lock);
+ }
+
+ /*
+diff --exclude=.git -urN linux-2.6.25.6/fs/Kconfig avr32-2.6/fs/Kconfig
+--- linux-2.6.25.6/fs/Kconfig 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/fs/Kconfig 2008-06-12 15:09:43.915816293 +0200
+@@ -1347,6 +1347,9 @@
+
+ endchoice
+
++# UBIFS File system configuration
++source "fs/ubifs/Kconfig"
++
+ config CRAMFS
+ tristate "Compressed ROM file system support (cramfs)"
+ depends on BLOCK
+diff --exclude=.git -urN linux-2.6.25.6/fs/Makefile avr32-2.6/fs/Makefile
+--- linux-2.6.25.6/fs/Makefile 2008-06-09 20:27:19.000000000 +0200
++++ avr32-2.6/fs/Makefile 2008-06-12 15:09:43.915816293 +0200
+@@ -100,6 +100,7 @@
+ obj-$(CONFIG_UFS_FS) += ufs/
+ obj-$(CONFIG_EFS_FS) += efs/
+ obj-$(CONFIG_JFFS2_FS) += jffs2/
++obj-$(CONFIG_UBIFS_FS) += ubifs/
+ obj-$(CONFIG_AFFS_FS) += affs/
+ obj-$(CONFIG_ROMFS_FS) += romfs/
+ obj-$(CONFIG_QNX4FS_FS) += qnx4/
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/budget.c avr32-2.6/fs/ubifs/budget.c
+--- linux-2.6.25.6/fs/ubifs/budget.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/budget.c 2008-06-12 15:09:45.311815896 +0200
+@@ -0,0 +1,863 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ */
++
++/*
++ * This file implements the budgeting unit which is responsible for UBIFS space
++ * management.
++ *
++ * Factors such as compression, wasted space at the ends of LEBs, space in other
++ * journal heads, the effect of updates on the index, and so on, make it
++ * impossible to accurately predict the amount of space needed. Consequently
++ * approximations are used.
++ */
++
++#include "ubifs.h"
++#include <linux/writeback.h>
++#include <asm/div64.h>
++
++/*
++ * When pessimistic budget calculations say that there is no enough space,
++ * UBIFS starts writing back dirty inodes and pages, doing garbage collection,
++ * or committing. The below constants define maximum number of times UBIFS
++ * repeats the operations.
++ */
++#define MAX_SHRINK_RETRIES 8
++#define MAX_GC_RETRIES 4
++#define MAX_CMT_RETRIES 2
++#define MAX_NOSPC_RETRIES 1
++
++/*
++ * The below constant defines amount of dirty pages which should be written
++ * back at when trying to shrink the liability.
++ */
++#define NR_TO_WRITE 16
++
++/**
++ * struct retries_info - information about re-tries while making free space.
++ * @prev_liability: previous liability
++ * @shrink_cnt: how many times the liability was shrinked
++ * @shrink_retries: count of liability shrink re-tries (increased when
++ * liability does not shrink)
++ * @try_gc: GC should be tried first
++ * @gc_retries: how many times GC was run
++ * @cmt_retries: how many times commit has been done
++ * @nospc_retries: how many times GC returned %-ENOSPC
++ *
++ * Since we consider budgeting to be the fast-path, and this structure has to
++ * be allocated on stack and zeroed out, we make it smaller using bit-fields.
++ */
++struct retries_info {
++ long long prev_liability;
++ unsigned int shrink_cnt;
++ unsigned int shrink_retries:5;
++ unsigned int try_gc:1;
++ unsigned int gc_retries:4;
++ unsigned int cmt_retries:3;
++ unsigned int nospc_retries:1;
++};
++
++/**
++ * shrink_liability - write-back some dirty pages/inodes.
++ * @c: UBIFS file-system description object
++ * @nr_to_write: how many dirty pages to write-back
++ *
++ * This function shrinks UBIFS liability by means of writing back some amount
++ * of dirty inodes and their pages. Returns the amount of pages which were
++ * written back. The returned value does not include dirty inodes which were
++ * synchronized.
++ *
++ * Note, this function synchronizes even VFS inodes which are locked
++ * (@i_mutex) by the caller of the budgeting function, because write-back does
++ * not touch @i_mutex.
++ */
++static int shrink_liability(struct ubifs_info *c, int nr_to_write)
++{
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_NONE,
++ .range_end = LLONG_MAX,
++ .nr_to_write = nr_to_write,
++ };
++
++ generic_sync_sb_inodes(c->vfs_sb, &wbc);
++ dbg_budg("%ld pages were written back", nr_to_write - wbc.nr_to_write);
++ return nr_to_write - wbc.nr_to_write;
++}
++
++
++/**
++ * run_gc - run garbage collector.
++ * @c: UBIFS file-system description object
++ *
++ * This function runs garbage collector to make some more free space. Returns
++ * zero if a free LEB has been produced, %-EAGAIN if commit is required, and a
++ * negative error code in case of failure.
++ */
++static int run_gc(struct ubifs_info *c)
++{
++ int err, lnum;
++
++ /* Make some free space by garbage-collecting dirty space */
++ down_read(&c->commit_sem);
++ lnum = ubifs_garbage_collect(c, 1);
++ up_read(&c->commit_sem);
++ if (lnum < 0)
++ return lnum;
++
++ /* GC freed one LEB, return it to lprops */
++ dbg_budg("GC freed LEB %d", lnum);
++ err = ubifs_return_leb(c, lnum);
++ if (err)
++ return err;
++
++ return 0;
++}
++
++/**
++ * make_free_space - make more free space on the file-system.
++ * @c: UBIFS file-system description object
++ * @ri: information about previous invocations of this function
++ *
++ * This function is called when an operation cannot be budgeted because there
++ * is supposedly no free space. But in most cases there is some free space:
++ * o budgeting is pessimistic, so it always budgets more then it is actually
++ * needed, so shrinking the liability is one way to make free space - the
++ * cached data will take less space then it was budgeted for;
++ * o GC may turn some dark space into free space (budgeting treats dark space
++ * as not available);
++ * o commit may free some LEB, i.e., turn freeable LEBs into free LEBs.
++ *
++ * So this function tries to do the above. Returns %-EAGAIN if some free space
++ * was presumably made and the caller has to re-try budgeting the operation.
++ * Returns %-ENOSPC if it couldn't do more free space, and other negative error
++ * codes on failures.
++ */
++static int make_free_space(struct ubifs_info *c, struct retries_info *ri)
++{
++ int err;
++
++ /*
++ * If we have some dirty pages and inodes (liability), try to write
++ * them back unless this was tried too many times without effect
++ * already.
++ */
++ if (ri->shrink_retries < MAX_SHRINK_RETRIES && !ri->try_gc) {
++ long long liability;
++
++ spin_lock(&c->space_lock);
++ liability = c->budg_idx_growth + c->budg_data_growth +
++ c->budg_dd_growth;
++ spin_unlock(&c->space_lock);
++
++ if (ri->prev_liability >= liability) {
++ /* Liability does not shrink, next time try GC then */
++ ri->shrink_retries += 1;
++ if (ri->gc_retries < MAX_GC_RETRIES)
++ ri->try_gc = 1;
++ dbg_budg("liability did not shrink: retries %d of %d",
++ ri->shrink_retries, MAX_SHRINK_RETRIES);
++ }
++
++ dbg_budg("force write-back (count %d)", ri->shrink_cnt);
++ shrink_liability(c, NR_TO_WRITE + ri->shrink_cnt);
++
++ ri->prev_liability = liability;
++ ri->shrink_cnt += 1;
++ return -EAGAIN;
++ }
++
++ /*
++ * Try to run garbage collector unless it was already tried too many
++ * times.
++ */
++ if (ri->gc_retries < MAX_GC_RETRIES) {
++ ri->gc_retries += 1;
++ dbg_budg("run GC, retries %d of %d",
++ ri->gc_retries, MAX_GC_RETRIES);
++
++ ri->try_gc = 0;
++ err = run_gc(c);
++ if (!err)
++ return -EAGAIN;
++
++ if (err == -EAGAIN) {
++ dbg_budg("GC asked to commit");
++ err = ubifs_run_commit(c);
++ if (err)
++ return err;
++ return -EAGAIN;
++ }
++
++ if (err != -ENOSPC)
++ return err;
++
++ /*
++ * GC could not make any progress. If this is the first time,
++ * then it makes sense to try to commit, because it might make
++ * some dirty space.
++ */
++ dbg_budg("GC returned -ENOSPC, retries %d",
++ ri->nospc_retries);
++ if (ri->nospc_retries >= MAX_NOSPC_RETRIES)
++ return err;
++ ri->nospc_retries += 1;
++ }
++
++ /* Neither GC nor write-back helped, try to commit */
++ if (ri->cmt_retries < MAX_CMT_RETRIES) {
++ ri->cmt_retries += 1;
++ dbg_budg("run commit, retries %d of %d",
++ ri->cmt_retries, MAX_CMT_RETRIES);
++ err = ubifs_run_commit(c);
++ if (err)
++ return err;
++ return -EAGAIN;
++ }
++
++ return -ENOSPC;
++}
++
++/**
++ * ubifs_calc_min_idx_lebs - calculate amount of eraseblocks for the index.
++ * @c: UBIFS file-system description object
++ *
++ * This function calculates and returns the number of eraseblocks which should
++ * be kept for index usage.
++ */
++int ubifs_calc_min_idx_lebs(struct ubifs_info *c)
++{
++ int ret;
++ uint64_t idx_size;
++
++ idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx;
++
++ /* And make sure we have twice the index size of space reserved */
++ idx_size <<= 1;
++
++ /*
++ * We do not maintain 'old_idx_size' as 'old_idx_lebs'/'old_idx_bytes'
++ * pair, nor similarly the two variables for the new index size, so we
++ * have to do this costly 64-bit division on fast-path.
++ */
++ if (do_div(idx_size, c->leb_size - c->max_idx_node_sz))
++ ret = idx_size + 1;
++ else
++ ret = idx_size;
++ /*
++ * The index head is not available for the in-the-gaps method, so add an
++ * extra LEB to compensate.
++ */
++ ret += 1;
++ /*
++ * At present the index needs at least 2 LEBs: one for the index head
++ * and one for in-the-gaps method (which currently does not cater for
++ * the index head and so excludes it from consideration).
++ */
++ if (ret < 2)
++ ret = 2;
++ return ret;
++}
++
++/**
++ * ubifs_calc_available - calculate available FS space.
++ * @c: UBIFS file-system description object
++ *
++ * This function calculates and returns amount of FS space available for use.
++ */
++long long ubifs_calc_available(const struct ubifs_info *c)
++{
++ long long available, subtract_lebs;
++
++ /*
++ * Force the amount available to the total size reported if the used
++ * space is zero.
++ */
++ if (c->lst.total_used <= UBIFS_INO_NODE_SZ &&
++ c->budg_data_growth + c->budg_dd_growth == 0) {
++ /* Do the same calculation as for c->block_cnt */
++ available = c->main_lebs - 2;
++ available *= c->leb_size - c->dark_wm;
++ return available;
++ }
++
++ available = c->main_bytes - c->lst.total_used;
++
++ /*
++ * Now 'available' contains theoretically available flash space
++ * assuming there is no index, so we have to subtract the space which
++ * is reserved for the index.
++ */
++ subtract_lebs = c->min_idx_lebs;
++
++ /* Take into account that GC reserves one LEB for its own needs */
++ subtract_lebs += 1;
++
++ /*
++ * The GC journal head LEB is not really accessible. And since
++ * different write types go to different heads, we may count only on
++ * one head's space.
++ */
++ subtract_lebs += c->jhead_cnt - 1;
++
++ /* We also reserve one LEB for deletions, which bypass budgeting */
++ subtract_lebs += 1;
++
++ available -= subtract_lebs * c->leb_size;
++
++ /* Subtract the dead space which is not available for use */
++ available -= c->lst.total_dead;
++
++ /*
++ * Subtract dark space, which might or might not be usable - it depends
++ * on the data which we have on the media and which will be written. If
++ * this is a lot of uncompressed or not-compressible data, the dark
++ * space cannot be used.
++ */
++ available -= c->lst.total_dark;
++
++ /*
++ * However, there is more dark space. The index may be bigger than
++ * min_idx_lebs. Those extra LEBs are assumed to be available, but
++ * their dark space is not included in total_dark, so it is subtracted
++ * here.
++ */
++ if (c->lst.idx_lebs > c->min_idx_lebs) {
++ subtract_lebs = c->lst.idx_lebs - c->min_idx_lebs;
++ available -= subtract_lebs * c->dark_wm;
++ }
++
++ /* The calculations are rough and may end up with a negative number */
++ return available > 0 ? available : 0;
++}
++
++/**
++ * rp_can_write - check whether the user is allowed to write.
++ * @c: UBIFS file-system description object
++ * @avail: available space on FS
++ *
++ * UBIFS has so-called "reserved pool" which is flash space reserved
++ * for the superuser and for uses whose UID/GID is recorded in UBIFS superblock.
++ * This function checks whether current user is allowed to write
++ * to the file-system - it returns %1 if there is plenty of space or the user
++ * is eligible to use the reserved pool and %0 otherwise.
++ */
++static int rp_can_write(struct ubifs_info *c, long long avail)
++{
++ if (avail > c->rp_size || current->fsuid == c->rp_uid ||
++ capable(CAP_SYS_RESOURCE) ||
++ (c->rp_gid != 0 && in_group_p(c->rp_gid)))
++ return 1;
++
++ return 0;
++}
++
++/**
++ * do_budget_space - reserve flash space for index and data growth.
++ * @c: UBIFS file-system description object
++ *
++ * This function makes sure UBIFS has enough free eraseblocks for index growth
++ * and data.
++ *
++ * When budgeting index space, UBIFS reserves twice as more LEBs as the index
++ * would take if it was consolidated and written to the flash. This guarantees
++ * that the "in-the-gaps" commit method always succeeds and UBIFS will always
++ * be able to commit dirty index. So this function basically adds amount of
++ * budgeted index space to the size of the current index, multiplies this by 2,
++ * and makes sure this does not exceed the amount of free eraseblocks.
++ *
++ * Notes about @c->min_idx_lebs and @c->lst.idx_lebs variables:
++ * o @c->lst.idx_lebs is the number of LEBs the index currently uses. It might
++ * be large, because UBIFS does not do any index consolidation as long as
++ * there is free space. IOW, the index may take a lot of LEBs, but the LEBs
++ * will contain a lot of dirt.
++ * o @c->min_idx_lebs is the the index presumably takes. IOW, the index may be
++ * consolidated to take up to @c->min_idx_lebs LEBs.
++ *
++ * This function returns zero in case of success, and %-ENOSPC in case of
++ * failure.
++ */
++static int do_budget_space(struct ubifs_info *c)
++{
++ long long outstanding, available;
++ int lebs, rsvd_idx_lebs, min_idx_lebs;
++
++ /* First budget index space */
++ min_idx_lebs = ubifs_calc_min_idx_lebs(c);
++
++ /* Now 'min_idx_lebs' contains number of LEBs to reserve */
++ if (min_idx_lebs > c->lst.idx_lebs)
++ rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
++ else
++ rsvd_idx_lebs = 0;
++
++ /*
++ * The number of LEBs that are available to be used by the index is:
++ *
++ * @c->lst.empty_lebs + @c->freeable_cnt + @c->idx_gc_cnt -
++ * @c->lst.taken_empty_lebs
++ *
++ * @empty_lebs are available because they are empty. @freeable_cnt are
++ * available because they contain only free and dirty space and the
++ * index allocation always occurs after wbufs are synch'ed.
++ * @idx_gc_cnt are available because they are index LEBs that have been
++ * garbage collected (including trivial GC) and are awaiting the commit
++ * before they can be unmapped - note that the in-the-gaps method will
++ * grab these if it needs them. @taken_empty_lebs are empty_lebs that
++ * have already been allocated for some purpose (also includes those
++ * LEBs on the @idx_gc list).
++ *
++ * Note, @taken_empty_lebs may temporarily be higher by one because of
++ * the way we serialize LEB allocations and budgeting. See a comment in
++ * 'ubifs_find_free_space()'.
++ */
++ lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
++ c->lst.taken_empty_lebs;
++ if (unlikely(rsvd_idx_lebs > lebs)) {
++ dbg_budg("out of indexing space: min_idx_lebs %d (old %d), "
++ "rsvd_idx_lebs %d", min_idx_lebs, c->min_idx_lebs,
++ rsvd_idx_lebs);
++ return -ENOSPC;
++ }
++
++ available = ubifs_calc_available(c);
++ outstanding = c->budg_data_growth + c->budg_dd_growth;
++
++ if (unlikely(available < outstanding)) {
++ dbg_budg("out of data space: available %lld, outstanding %lld",
++ available, outstanding);
++ return -ENOSPC;
++ }
++
++ if (!rp_can_write(c, available - outstanding))
++ return -ENOSPC;
++
++ c->min_idx_lebs = min_idx_lebs;
++ return 0;
++}
++
++/**
++ * calc_idx_growth - calculate approximate index growth from budgeting request.
++ * @c: UBIFS file-system description object
++ * @req: budgeting request
++ *
++ * For now we assume each new node adds one znode. But this is rather poor
++ * approximation, though.
++ */
++static int calc_idx_growth(const struct ubifs_info *c,
++ const struct ubifs_budget_req *req)
++{
++ int znodes;
++
++ znodes = req->new_ino + (req->new_page << UBIFS_BLOCKS_PER_PAGE_SHIFT) +
++ req->new_dent;
++ return znodes * c->max_idx_node_sz;
++}
++
++/**
++ * calc_data_growth - calculate approximate amount of new data from budgeting
++ * request.
++ * @c: UBIFS file-system description object
++ * @req: budgeting request
++ */
++static int calc_data_growth(const struct ubifs_info *c,
++ const struct ubifs_budget_req *req)
++{
++ int data_growth;
++
++ data_growth = req->new_ino ? c->inode_budget : 0;
++ if (req->new_page)
++ data_growth += c->page_budget;
++ if (req->new_dent)
++ data_growth += c->dent_budget;
++ data_growth += req->new_ino_d;
++
++ return data_growth;
++}
++
++/**
++ * calc_dd_growth - calculate approximate amount of data which makes other data
++ * dirty from budgeting request.
++ * @c: UBIFS file-system description object
++ * @req: budgeting request
++ */
++static int calc_dd_growth(const struct ubifs_info *c,
++ const struct ubifs_budget_req *req)
++{
++ int dd_growth;
++
++ dd_growth = req->dirtied_page ? c->page_budget : 0;
++
++ if (req->dirtied_ino)
++ dd_growth += c->inode_budget << (req->dirtied_ino - 1);
++ if (req->mod_dent)
++ dd_growth += c->dent_budget;
++ dd_growth += req->dirtied_ino_d;
++
++ return dd_growth;
++}
++
++/**
++ * ubifs_budget_space - ensure there is enough space to complete an operation.
++ * @c: UBIFS file-system description object
++ * @req: budget request
++ *
++ * This function allocates budget for an operation. It uses pessimistic
++ * approximation of how much flash space the operation needs. The goal of this
++ * function is to make sure UBIFS always has flash space to flush all dirty
++ * pages, dirty inodes, and dirty znodes (liability). This function may force
++ * commit, garbage-collection or write-back. Returns zero in case of success,
++ * %-ENOSPC if there is no free space and other negative error codes in case of
++ * failures.
++ */
++int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
++{
++ int uninitialized_var(cmt_retries), uninitialized_var(wb_retries);
++ int err, idx_growth, data_growth, dd_growth;
++ struct retries_info ri;
++
++ data_growth = calc_data_growth(c, req);
++ dd_growth = calc_dd_growth(c, req);
++ if (!data_growth && !dd_growth)
++ return 0;
++ idx_growth = calc_idx_growth(c, req);
++ memset(&ri, 0, sizeof(struct retries_info));
++
++again:
++ spin_lock(&c->space_lock);
++ ubifs_assert(c->budg_idx_growth >= 0);
++ ubifs_assert(c->budg_data_growth >= 0);
++ ubifs_assert(c->budg_dd_growth >= 0);
++
++ c->budg_idx_growth += idx_growth;
++ c->budg_data_growth += data_growth;
++ c->budg_dd_growth += dd_growth;
++
++ err = do_budget_space(c);
++ if (unlikely(err)) {
++ /* Restore the old values */
++ c->budg_idx_growth -= idx_growth;
++ c->budg_data_growth -= data_growth;
++ c->budg_dd_growth -= dd_growth;
++ spin_unlock(&c->space_lock);
++
++ goto make_space;
++ }
++
++ req->idx_growth = idx_growth;
++ req->data_growth = data_growth;
++ req->dd_growth = dd_growth;
++ spin_unlock(&c->space_lock);
++
++ return 0;
++
++make_space:
++ err = make_free_space(c, &ri);
++ if (err == -EAGAIN) {
++ dbg_budg("try again");
++ cond_resched();
++ goto again;
++ } else if (err == -ENOSPC)
++ dbg_budg("FS is full, -ENOSPC");
++ else
++ ubifs_err("cannot budget space, error %d", err);
++
++ return err;
++}
++
++/**
++ * ubifs_release_budget - release budgeted free space.
++ * @c: UBIFS file-system description object
++ * @req: budget request
++ *
++ * This function releases the space budgeted by 'ubifs_budget_space()'. Note,
++ * since the index changes (which were budgeted for in @req->idx_growth) will
++ * only be written to the media on commit, this function moves the index budget
++ * from @c->budg_idx_growth to @c->budg_uncommitted_idx. The latter will be
++ * zeroed by the commit operation.
++ */
++void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req)
++{
++ if (!req->data_growth && !req->dd_growth)
++ return;
++
++ if (req->idx_growth == -1)
++ req->idx_growth = calc_idx_growth(c, req);
++
++ spin_lock(&c->space_lock);
++ c->budg_idx_growth -= req->idx_growth;
++ c->budg_uncommitted_idx += req->idx_growth;
++ c->budg_data_growth -= req->data_growth;
++ c->budg_dd_growth -= req->dd_growth;
++ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
++
++ ubifs_assert(c->budg_idx_growth >= 0);
++ ubifs_assert(c->budg_data_growth >= 0);
++ ubifs_assert(c->min_idx_lebs < c->main_lebs);
++ spin_unlock(&c->space_lock);
++}
++
++/**
++ * ubifs_convert_page_budget - convert budget of a new page.
++ * @c: UBIFS file-system description object
++ *
++ * This function converts budget which was allocated for a new page of data to
++ * the budget of changing an existing page of data. The latter is not larger
++ * then the former, so this function only does simple re-calculation and does
++ * not involve any write-back.
++ */
++void ubifs_convert_page_budget(struct ubifs_info *c)
++{
++ spin_lock(&c->space_lock);
++ /* Release the index growth reservation */
++ c->budg_idx_growth -= c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT;
++ /* Release the data growth reservation */
++ c->budg_data_growth -= c->page_budget;
++ /* Increase the dirty data growth reservation instead */
++ c->budg_dd_growth += c->page_budget;
++ /* And re-calculate the indexing space reservation */
++ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
++ spin_unlock(&c->space_lock);
++}
++
++/**
++ * ubifs_budget_inode_op - budget an operation on inode.
++ * @c: UBIFS file-system description object
++ * @inode: VFS inode which will be made dirty by the operation
++ * @req: budget request of the operation
++ *
++ * This function is called to get budget for an operation which changes an
++ * inode. The inode may be in dirty or clean state. The former means there is
++ * no need to allocate the budget as it has already been allocated before. The
++ * latter means that the inode change budget has to be allocated.
++ *
++ * The caller has to pass the inode which is going to be changed. This function
++ * acquires budget the for as described in @req plus the budget for changing
++ * the inode dirty, if needed. Returns zero in case of success, %-ENOSPC if
++ * there is no more flash space, and other negative error codes in case of
++ * failure.
++ *
++ * Note, upon exit, this function leaves the inode locked, and the
++ * 'ubifs_release_ino_dirty()' or 'ubifs_release_ino_clean()' function has to
++ * be called to unlock it.
++ */
++int ubifs_budget_inode_op(struct ubifs_info *c, struct inode *inode,
++ struct ubifs_budget_req *req)
++{
++ struct ubifs_inode *ui = ubifs_inode(inode);
++ int err, old = req->dirtied_ino;
++
++ ubifs_assert(req->dirtied_ino <= 3);
++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 3);
++
++again:
++ /*
++ * If the inode is clean, it will be dirtied by this operation and we
++ * have to budget for this.
++ */
++ req->dirtied_ino += !ui->dirty;
++ if (req->dirtied_ino > old)
++ req->dirtied_ino_d += ui->data_len;
++
++ /*
++ * Note, if the budget request does not actually request anything
++ * (i.e., @req contains only zeroes), 'ubifs_budget_space()' will
++ * return almost straight away.
++ */
++ err = ubifs_budget_space(c, req);
++ if (unlikely(err))
++ return err;
++
++ mutex_lock(&ui->budg_mutex);
++
++ if (req->dirtied_ino != old + !ui->dirty) {
++ /* The inode has probably been written back meanwhile */
++ ubifs_release_budget(c, req);
++ mutex_unlock(&ui->budg_mutex);
++ req->dirtied_ino = old;
++ req->dirtied_ino_d -= ui->data_len;
++ goto again;
++ }
++
++ UBIFS_DBG(ui->budgeted = 1);
++ return 0;
++}
++
++/**
++ * ubifs_release_ino_dirty - release budget of a "dirtying" operation.
++ * @c: UBIFS file-system description object
++ * @inode: VFS inode the operation worked on
++ * @req: budget to release
++ *
++ * This function has to be called at the end of VFS operations which acquired
++ * budget via 'ubifs_budget_inode_op()'. It assumes that the inode has been
++ * marked as dirty and will be synchronized later by write-back, so it does not
++ * release the budget of the inode.
++ *
++ * Note, this function also avoids releasing page budgets which are released
++ * separately.
++ */
++void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
++ struct ubifs_budget_req *req)
++{
++ ubifs_assert(req->dirtied_ino <= 4);
++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
++ ubifs_assert(req->idx_growth >= 0);
++ ubifs_assert(req->data_growth >= 0);
++ ubifs_assert(req->dd_growth >= 0);
++
++ if (req->dirtied_ino) {
++ req->dd_growth -= c->inode_budget;
++ req->dd_growth -= req->dirtied_ino_d;
++ }
++
++ if (req->dirtied_page) {
++ req->dd_growth -= c->page_budget;
++ ubifs_assert(req->new_page == 0);
++ } else if (req->new_page) {
++ req->idx_growth -=
++ c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT;
++ req->data_growth -= c->page_budget;
++ ubifs_assert(req->dirtied_page == 0);
++ }
++
++ ubifs_assert(req->dd_growth >= 0);
++ ubifs_release_budget(c, req);
++ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
++}
++
++/**
++ * ubifs_cancel_ino_op - cancel budget of an operation on inode.
++ * @c: UBIFS file-system description object
++ * @inode: VFS inode the operation worked on
++ * @req: budget to release
++ *
++ * This function has to be called if the operation failed and whole budget has
++ * to be released, including the budget for inode which would had been
++ * dirtied. It is important not to mark the inode dirty before calling this
++ * function.
++ */
++void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
++ struct ubifs_budget_req *req)
++{
++ ubifs_assert(req->dirtied_ino <= 4);
++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
++ ubifs_assert(req->idx_growth >= 0);
++ ubifs_assert(req->data_growth >= 0);
++ ubifs_assert(req->dd_growth >= 0);
++
++ ubifs_release_budget(c, req);
++ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
++}
++
++/**
++ * ubifs_release_ino_clean - release budget of a "cleaning" operation.
++ * @c: UBIFS file-system description object
++ * @inode: VFS inode the operation worked on
++ * @req: budget to release
++ *
++ * This function has to be called at the end of VFS operations which acquired
++ * budget via 'ubifs_budget_inode_op()'. It assumed the operation synchronized
++ * the inode, so it marks the inode clean, unlocks it and releases whole budget.
++ *
++ * Note, this function also avoids releasing page budgets which are released
++ * separately.
++ */
++void ubifs_release_ino_clean(struct ubifs_info *c, struct inode *inode,
++ struct ubifs_budget_req *req)
++{
++ struct ubifs_inode *ui = ubifs_inode(inode);
++
++ ubifs_assert(req->dirtied_ino <= 4);
++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
++ ubifs_assert(req->idx_growth >= 0);
++ ubifs_assert(req->data_growth >= 0);
++ ubifs_assert(req->dd_growth >= 0);
++ ubifs_assert(!req->dirtied_page);
++ ubifs_assert(!req->new_page);
++ UBIFS_DBG(ui->budgeted = 0);
++
++ ubifs_release_budget(c, req);
++ if (ui->dirty) {
++ ui->dirty = 0;
++ /*
++ * Note, VFS still treats the inode as dirty and
++ * 'ubifs_write_inode()' will be called, but it'll do nothing
++ * because @ui->dirty is %0.
++ */
++ atomic_long_dec(&c->dirty_ino_cnt);
++ }
++ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
++}
++
++/**
++ * ubifs_release_new_page_budget - release budget of a new page.
++ * @c: UBIFS file-system description object
++ *
++ * This is a helper function which releases budget corresponding to the budget
++ * of one new page of data.
++ */
++void ubifs_release_new_page_budget(struct ubifs_info *c)
++{
++ struct ubifs_budget_req req = { .new_page = 1,
++ .idx_growth = -1,
++ .data_growth = c->page_budget };
++
++ ubifs_release_budget(c, &req);
++}
++
++/**
++ * ubifs_budg_get_free_space - return amount of free space.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns amount of free space on the file-system.
++ */
++long long ubifs_budg_get_free_space(struct ubifs_info *c)
++{
++ int min_idx_lebs, rsvd_idx_lebs;
++ long long available, outstanding, free;
++
++ /* Do exactly the same calculations as in 'do_budget_space()' */
++ spin_lock(&c->space_lock);
++ min_idx_lebs = ubifs_calc_min_idx_lebs(c);
++
++ if (min_idx_lebs > c->lst.idx_lebs)
++ rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
++ else
++ rsvd_idx_lebs = 0;
++
++ if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt
++ - c->lst.taken_empty_lebs) {
++ spin_unlock(&c->space_lock);
++ return 0;
++ }
++
++ c->min_idx_lebs = min_idx_lebs;
++ available = ubifs_calc_available(c);
++ outstanding = c->budg_data_growth + c->budg_dd_growth;
++ spin_unlock(&c->space_lock);
++
++ if (available > outstanding)
++ free = ubifs_reported_space(c, available - outstanding);
++ else
++ free = 0;
++
++ return free;
++}
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/commit.c avr32-2.6/fs/ubifs/commit.c
+--- linux-2.6.25.6/fs/ubifs/commit.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/commit.c 2008-06-12 15:09:45.311815896 +0200
+@@ -0,0 +1,677 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ */
++
++/*
++ * This file implements functions that manage the running of the commit process.
++ * Each affected module has its own functions to accomplish their part in the
++ * commit and those functions are called here.
++ *
++ * The commit is the process whereby all updates to the index and LEB properties
++ * are written out together and the journal becomes empty. This keeps the
++ * file system consistent - at all times the state can be recreated by reading
++ * the index and LEB properties and then replaying the journal.
++ *
++ * The commit is split into two parts named "commit start" and "commit end".
++ * During commit start, the commit process has exclusive access to the journal
++ * by holding the commit semaphore down for writing. As few I/O operations as
++ * possible are performed during commit start, instead the nodes that are to be
++ * written are merely identified. During commit end, the commit semaphore is no
++ * longer held and the journal is again in operation, allowing users to continue
++ * to use the file system while the bulk of the commit I/O is performed. The
++ * purpose of this two-step approach is to prevent the commit from causing any
++ * latency blips. Note that in any case, the commit does not prevent lookups
++ * (as permitted by the TNC mutex), or access to VFS data structures e.g. page
++ * cache.
++ */
++
++#include <linux/freezer.h>
++#include <linux/kthread.h>
++#include "ubifs.h"
++
++/**
++ * do_commit - commit the journal.
++ * @c: UBIFS file-system description object
++ *
++ * This function implements UBIFS commit. It has to be called with commit lock
++ * locked. Returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++static int do_commit(struct ubifs_info *c)
++{
++ int err, new_ltail_lnum, old_ltail_lnum, i;
++ struct ubifs_zbranch zroot;
++ struct ubifs_lp_stats lst;
++
++ dbg_cmt("start");
++ if (c->ro_media) {
++ err = -EROFS;
++ goto out_up;
++ }
++
++ /* Sync all write buffers (necessary for recovery) */
++ for (i = 0; i < c->jhead_cnt; i++) {
++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
++ if (err)
++ goto out_up;
++ }
++
++ err = ubifs_gc_start_commit(c);
++ if (err)
++ goto out_up;
++ err = dbg_check_lprops(c);
++ if (err)
++ goto out_up;
++ err = ubifs_log_start_commit(c, &new_ltail_lnum);
++ if (err)
++ goto out_up;
++ err = ubifs_tnc_start_commit(c, &zroot);
++ if (err)
++ goto out_up;
++ err = ubifs_lpt_start_commit(c);
++ if (err)
++ goto out_up;
++ err = ubifs_orphan_start_commit(c);
++ if (err)
++ goto out_up;
++
++ ubifs_get_lp_stats(c, &lst);
++
++ up_write(&c->commit_sem);
++
++ err = ubifs_tnc_end_commit(c);
++ if (err)
++ goto out;
++ err = ubifs_lpt_end_commit(c);
++ if (err)
++ goto out;
++ err = ubifs_orphan_end_commit(c);
++ if (err)
++ goto out;
++ old_ltail_lnum = c->ltail_lnum;
++ err = ubifs_log_end_commit(c, new_ltail_lnum);
++ if (err)
++ goto out;
++ err = dbg_check_old_index(c, &zroot);
++ if (err)
++ goto out;
++
++ mutex_lock(&c->mst_mutex);
++ c->mst_node->cmt_no = cpu_to_le64(++c->cmt_no);
++ c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum);
++ c->mst_node->root_lnum = cpu_to_le32(zroot.lnum);
++ c->mst_node->root_offs = cpu_to_le32(zroot.offs);
++ c->mst_node->root_len = cpu_to_le32(zroot.len);
++ c->mst_node->ihead_lnum = cpu_to_le32(c->ihead_lnum);
++ c->mst_node->ihead_offs = cpu_to_le32(c->ihead_offs);
++ c->mst_node->index_size = cpu_to_le64(c->old_idx_sz);
++ c->mst_node->lpt_lnum = cpu_to_le32(c->lpt_lnum);
++ c->mst_node->lpt_offs = cpu_to_le32(c->lpt_offs);
++ c->mst_node->nhead_lnum = cpu_to_le32(c->nhead_lnum);
++ c->mst_node->nhead_offs = cpu_to_le32(c->nhead_offs);
++ c->mst_node->ltab_lnum = cpu_to_le32(c->ltab_lnum);
++ c->mst_node->ltab_offs = cpu_to_le32(c->ltab_offs);
++ c->mst_node->lsave_lnum = cpu_to_le32(c->lsave_lnum);
++ c->mst_node->lsave_offs = cpu_to_le32(c->lsave_offs);
++ c->mst_node->lscan_lnum = cpu_to_le32(c->lscan_lnum);
++ c->mst_node->empty_lebs = cpu_to_le32(lst.empty_lebs);
++ c->mst_node->idx_lebs = cpu_to_le32(lst.idx_lebs);
++ c->mst_node->total_free = cpu_to_le64(lst.total_free);
++ c->mst_node->total_dirty = cpu_to_le64(lst.total_dirty);
++ c->mst_node->total_used = cpu_to_le64(lst.total_used);
++ c->mst_node->total_dead = cpu_to_le64(lst.total_dead);
++ c->mst_node->total_dark = cpu_to_le64(lst.total_dark);
++ if (c->no_orphs)
++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
++ else
++ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS);
++ err = ubifs_write_master(c);
++ mutex_unlock(&c->mst_mutex);
++ if (err)
++ goto out;
++
++ err = ubifs_log_post_commit(c, old_ltail_lnum);
++ if (err)
++ goto out;
++ err = ubifs_gc_end_commit(c);
++ if (err)
++ goto out;
++ err = ubifs_lpt_post_commit(c);
++ if (err)
++ goto out;
++
++ spin_lock(&c->cs_lock);
++ c->cmt_state = COMMIT_RESTING;
++ wake_up(&c->cmt_wq);
++ dbg_cmt("commit end");
++ spin_unlock(&c->cs_lock);
++
++ return 0;
++
++out_up:
++ up_write(&c->commit_sem);
++out:
++ ubifs_err("commit failed, error %d", err);
++ spin_lock(&c->cs_lock);
++ c->cmt_state = COMMIT_BROKEN;
++ wake_up(&c->cmt_wq);
++ spin_unlock(&c->cs_lock);
++ ubifs_ro_mode(c, err);
++ return err;
++}
++
++/**
++ * run_bg_commit - run background commit if it is needed.
++ * @c: UBIFS file-system description object
++ *
++ * This function runs background commit if it is needed. Returns zero in case
++ * of success and a negative error code in case of failure.
++ */
++static int run_bg_commit(struct ubifs_info *c)
++{
++ spin_lock(&c->cs_lock);
++ /*
++ * Run background commit only if background commit was requested or if
++ * commit is required.
++ */
++ if (c->cmt_state != COMMIT_BACKGROUND &&
++ c->cmt_state != COMMIT_REQUIRED)
++ goto out;
++ spin_unlock(&c->cs_lock);
++
++ down_write(&c->commit_sem);
++ spin_lock(&c->cs_lock);
++ if (c->cmt_state == COMMIT_REQUIRED)
++ c->cmt_state = COMMIT_RUNNING_REQUIRED;
++ else if (c->cmt_state == COMMIT_BACKGROUND)
++ c->cmt_state = COMMIT_RUNNING_BACKGROUND;
++ else
++ goto out_cmt_unlock;
++ spin_unlock(&c->cs_lock);
++
++ return do_commit(c);
++
++out_cmt_unlock:
++ up_write(&c->commit_sem);
++out:
++ spin_unlock(&c->cs_lock);
++ return 0;
++}
++
++/**
++ * ubifs_bg_thread - UBIFS background thread function.
++ * @info: points to the file-system description object
++ *
++ * This function implements various file-system background activities:
++ * o when a write-buffer timer expires it synchronizes the appropriate
++ * write-buffer;
++ * o when the journal is about to be full, it starts in-advance commit.
++ *
++ * Note, other stuff like background garbage collection may be added here in
++ * future.
++ */
++int ubifs_bg_thread(void *info)
++{
++ int err;
++ struct ubifs_info *c = info;
++
++ ubifs_msg("background thread \"%s\" started, PID %d",
++ c->bgt_name, current->pid);
++ set_freezable();
++
++ while (1) {
++ if (kthread_should_stop())
++ break;
++
++ if (try_to_freeze())
++ continue;
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ /* Check if there is something to do */
++ if (!c->need_bgt) {
++ /*
++ * Nothing prevents us from going sleep now and
++ * be never woken up and block the task which
++ * could wait in 'kthread_stop()' forever.
++ */
++ if (kthread_should_stop())
++ break;
++ schedule();
++ continue;
++ } else
++ __set_current_state(TASK_RUNNING);
++
++ c->need_bgt = 0;
++ err = ubifs_bg_wbufs_sync(c);
++ if (err)
++ ubifs_ro_mode(c, err);
++
++ run_bg_commit(c);
++ cond_resched();
++ }
++
++ dbg_msg("background thread \"%s\" stops", c->bgt_name);
++ return 0;
++}
++
++/**
++ * ubifs_commit_required - set commit state to "required".
++ * @c: UBIFS file-system description object
++ *
++ * This function is called if a commit is required but cannot be done from the
++ * calling function, so it is just flagged instead.
++ */
++void ubifs_commit_required(struct ubifs_info *c)
++{
++ spin_lock(&c->cs_lock);
++ switch (c->cmt_state) {
++ case COMMIT_RESTING:
++ case COMMIT_BACKGROUND:
++ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
++ dbg_cstate(COMMIT_REQUIRED));
++ c->cmt_state = COMMIT_REQUIRED;
++ break;
++ case COMMIT_RUNNING_BACKGROUND:
++ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
++ dbg_cstate(COMMIT_RUNNING_REQUIRED));
++ c->cmt_state = COMMIT_RUNNING_REQUIRED;
++ break;
++ case COMMIT_REQUIRED:
++ case COMMIT_RUNNING_REQUIRED:
++ case COMMIT_BROKEN:
++ break;
++ }
++ spin_unlock(&c->cs_lock);
++}
++
++/**
++ * ubifs_request_bg_commit - notify the background thread to do a commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function is called if the journal is full enough to make a commit
++ * worthwhile, so background thread is kicked to start it.
++ */
++void ubifs_request_bg_commit(struct ubifs_info *c)
++{
++ spin_lock(&c->cs_lock);
++ if (c->cmt_state == COMMIT_RESTING) {
++ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
++ dbg_cstate(COMMIT_BACKGROUND));
++ c->cmt_state = COMMIT_BACKGROUND;
++ spin_unlock(&c->cs_lock);
++ ubifs_wake_up_bgt(c);
++ } else
++ spin_unlock(&c->cs_lock);
++}
++
++/**
++ * wait_for_commit - wait for commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function sleeps until the commit operation is no longer running.
++ */
++static int wait_for_commit(struct ubifs_info *c)
++{
++ dbg_cmt("pid %d goes sleep", current->pid);
++
++ /*
++ * The following sleeps if the condition is false, and will be woken
++ * when the commit ends. It is possible, although very unlikely, that we
++ * will wake up and see the subsequent commit running, rather than the
++ * one we were waiting for, and go back to sleep. However, we will be
++ * woken again, so there is no danger of sleeping forever.
++ */
++ wait_event(c->cmt_wq, c->cmt_state != COMMIT_RUNNING_BACKGROUND &&
++ c->cmt_state != COMMIT_RUNNING_REQUIRED);
++ dbg_cmt("commit finished, pid %d woke up", current->pid);
++ return 0;
++}
++
++/**
++ * ubifs_run_commit - run or wait for commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function runs commit and returns zero in case of success and a negative
++ * error code in case of failure.
++ */
++int ubifs_run_commit(struct ubifs_info *c)
++{
++ int err = 0;
++
++ spin_lock(&c->cs_lock);
++ if (c->cmt_state == COMMIT_BROKEN) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ if (c->cmt_state == COMMIT_RUNNING_BACKGROUND)
++ /*
++ * We set the commit state to 'running required' to indicate
++ * that we want it to complete as quickly as possible.
++ */
++ c->cmt_state = COMMIT_RUNNING_REQUIRED;
++
++ if (c->cmt_state == COMMIT_RUNNING_REQUIRED) {
++ spin_unlock(&c->cs_lock);
++ return wait_for_commit(c);
++ }
++ spin_unlock(&c->cs_lock);
++
++ /* Ok, the commit is indeed needed */
++
++ down_write(&c->commit_sem);
++ spin_lock(&c->cs_lock);
++ /*
++ * Since we unlocked 'c->cs_lock', the state may have changed, so
++ * re-check it.
++ */
++ if (c->cmt_state == COMMIT_BROKEN) {
++ err = -EINVAL;
++ goto out_cmt_unlock;
++ }
++
++ if (c->cmt_state == COMMIT_RUNNING_BACKGROUND)
++ c->cmt_state = COMMIT_RUNNING_REQUIRED;
++
++ if (c->cmt_state == COMMIT_RUNNING_REQUIRED) {
++ up_write(&c->commit_sem);
++ spin_unlock(&c->cs_lock);
++ return wait_for_commit(c);
++ }
++ c->cmt_state = COMMIT_RUNNING_REQUIRED;
++ spin_unlock(&c->cs_lock);
++
++ err = do_commit(c);
++ return err;
++
++out_cmt_unlock:
++ up_write(&c->commit_sem);
++out:
++ spin_unlock(&c->cs_lock);
++ return err;
++}
++
++/**
++ * ubifs_gc_should_commit - determine if it is time for GC to run commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function is called by garbage collection to determine if commit should
++ * be run. If commit state is @COMMIT_BACKGROUND, which means that the journal
++ * is full enough to start commit, this function returns true. It is not
++ * absolutely necessary to commit yet, but it feels like this should be better
++ * then to keep doing GC. This function returns %1 if GC has to initiate commit
++ * and %0 if not.
++ */
++int ubifs_gc_should_commit(struct ubifs_info *c)
++{
++ int ret = 0;
++
++ spin_lock(&c->cs_lock);
++ if (c->cmt_state == COMMIT_BACKGROUND) {
++ dbg_cmt("commit required now");
++ c->cmt_state = COMMIT_REQUIRED;
++ } else
++ dbg_cmt("commit not requested");
++ if (c->cmt_state == COMMIT_REQUIRED)
++ ret = 1;
++ spin_unlock(&c->cs_lock);
++ return ret;
++}
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++/**
++ * struct idx_node - hold index nodes during index tree traversal.
++ * @list: list
++ * @iip: index in parent (slot number of this indexing node in the parent
++ * indexing node)
++ * @upper_key: all keys in this indexing node have to be less or equivalent to
++ * this key
++ * @idx: index node (8-byte aligned because all node structures must be 8-byte
++ * aligned)
++ */
++struct idx_node {
++ struct list_head list;
++ int iip;
++ union ubifs_key upper_key;
++ struct ubifs_idx_node idx __attribute__((aligned(8)));
++};
++
++/**
++ * dbg_old_index_check_init - get information for the next old index check.
++ * @c: UBIFS file-system description object
++ * @zroot: root of the index
++ *
++ * This function records information about the index that will be needed for the
++ * next old index check i.e. 'dbg_check_old_index()'.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
++{
++ struct ubifs_idx_node *idx;
++ int lnum, offs, len, err = 0;
++
++ c->old_zroot = *zroot;
++
++ lnum = c->old_zroot.lnum;
++ offs = c->old_zroot.offs;
++ len = c->old_zroot.len;
++
++ idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
++ if (!idx)
++ return -ENOMEM;
++
++ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
++ if (err)
++ goto out;
++
++ c->old_zroot_level = le16_to_cpu(idx->level);
++ c->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum);
++out:
++ kfree(idx);
++ return err;
++}
++
++/**
++ * dbg_check_old_index - check the old copy of the index.
++ * @c: UBIFS file-system description object
++ * @zroot: root of the new index
++ *
++ * In order to be able to recover from an unclean unmount, a complete copy of
++ * the index must exist on flash. This is the "old" index. The commit process
++ * must write the "new" index to flash without overwriting or destroying any
++ * part of the old index. This function is run at commit end in order to check
++ * that the old index does indeed exist completely intact.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
++{
++ int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt;
++ int first = 1, iip;
++ union ubifs_key lower_key, upper_key, l_key, u_key;
++ unsigned long long uninitialized_var(last_sqnum);
++ struct ubifs_idx_node *idx;
++ struct list_head list;
++ struct idx_node *i;
++ size_t sz;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
++ goto out;
++
++ INIT_LIST_HEAD(&list);
++
++ sz = sizeof(struct idx_node) + ubifs_idx_node_sz(c, c->fanout) -
++ UBIFS_IDX_NODE_SZ;
++
++ /* Start at the old zroot */
++ lnum = c->old_zroot.lnum;
++ offs = c->old_zroot.offs;
++ len = c->old_zroot.len;
++ iip = 0;
++
++ /*
++ * Traverse the index tree preorder depth-first i.e. do a node and then
++ * its subtrees from left to right.
++ */
++ while (1) {
++ struct ubifs_branch *br;
++
++ /* Get the next index node */
++ i = kmalloc(sz, GFP_NOFS);
++ if (!i) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ i->iip = iip;
++ /* Keep the index nodes on our path in a linked list */
++ list_add_tail(&i->list, &list);
++ /* Read the index node */
++ idx = &i->idx;
++ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
++ if (err)
++ goto out_free;
++ /* Validate index node */
++ child_cnt = le16_to_cpu(idx->child_cnt);
++ if (child_cnt < 1 || child_cnt > c->fanout) {
++ err = 1;
++ goto out_dump;
++ }
++ if (first) {
++ first = 0;
++ /* Check root level and sqnum */
++ if (le16_to_cpu(idx->level) != c->old_zroot_level) {
++ err = 2;
++ goto out_dump;
++ }
++ if (le64_to_cpu(idx->ch.sqnum) != c->old_zroot_sqnum) {
++ err = 3;
++ goto out_dump;
++ }
++ /* Set last values as though root had a parent */
++ last_level = le16_to_cpu(idx->level) + 1;
++ last_sqnum = le64_to_cpu(idx->ch.sqnum) + 1;
++ key_read(c, ubifs_idx_key(c, idx), &lower_key);
++ highest_ino_key(c, &upper_key, INUM_WATERMARK);
++ }
++ key_copy(c, &upper_key, &i->upper_key);
++ if (le16_to_cpu(idx->level) != last_level - 1) {
++ err = 3;
++ goto out_dump;
++ }
++ /*
++ * The index is always written bottom up hence a child's sqnum
++ * is always less than the parents.
++ */
++ if (le64_to_cpu(idx->ch.sqnum) >= last_sqnum) {
++ err = 4;
++ goto out_dump;
++ }
++ /* Check key range */
++ key_read(c, ubifs_idx_key(c, idx), &l_key);
++ br = ubifs_idx_branch(c, idx, child_cnt - 1);
++ key_read(c, &br->key, &u_key);
++ if (keys_cmp(c, &lower_key, &l_key) > 0) {
++ err = 5;
++ goto out_dump;
++ }
++ if (keys_cmp(c, &upper_key, &u_key) < 0) {
++ err = 6;
++ goto out_dump;
++ }
++ if (keys_cmp(c, &upper_key, &u_key) == 0)
++ if (!is_hash_key(c, &u_key)) {
++ err = 7;
++ goto out_dump;
++ }
++ /* Go to next index node */
++ if (le16_to_cpu(idx->level) == 0) {
++ /* At the bottom, so go up until can go right */
++ while (1) {
++ /* Drop the bottom of the list */
++ list_del(&i->list);
++ kfree(i);
++ /* No more list means we are done */
++ if (list_empty(&list))
++ goto out;
++ /* Look at the new bottom */
++ i = list_entry(list.prev, struct idx_node,
++ list);
++ idx = &i->idx;
++ /* Can we go right */
++ if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
++ iip = iip + 1;
++ break;
++ } else
++ /* Nope, so go up again */
++ iip = i->iip;
++ }
++ } else
++ /* Go down left */
++ iip = 0;
++ /*
++ * We have the parent in 'idx' and now we set up for reading the
++ * child pointed to by slot 'iip'.
++ */
++ last_level = le16_to_cpu(idx->level);
++ last_sqnum = le64_to_cpu(idx->ch.sqnum);
++ br = ubifs_idx_branch(c, idx, iip);
++ lnum = le32_to_cpu(br->lnum);
++ offs = le32_to_cpu(br->offs);
++ len = le32_to_cpu(br->len);
++ key_read(c, &br->key, &lower_key);
++ if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
++ br = ubifs_idx_branch(c, idx, iip + 1);
++ key_read(c, &br->key, &upper_key);
++ } else
++ key_copy(c, &i->upper_key, &upper_key);
++ }
++out:
++ err = dbg_old_index_check_init(c, zroot);
++ if (err)
++ goto out_free;
++
++ return 0;
++
++out_dump:
++ dbg_err("dumping index node (iip=%d)", i->iip);
++ dbg_dump_node(c, idx);
++ list_del(&i->list);
++ kfree(i);
++ if (!list_empty(&list)) {
++ i = list_entry(list.prev, struct idx_node, list);
++ dbg_err("dumping parent index node");
++ dbg_dump_node(c, &i->idx);
++ }
++out_free:
++ while (!list_empty(&list)) {
++ i = list_entry(list.next, struct idx_node, list);
++ list_del(&i->list);
++ kfree(i);
++ }
++ ubifs_err("failed, error %d", err);
++ if (err > 0)
++ err = -EINVAL;
++ return err;
++}
++
++#endif /* CONFIG_UBIFS_FS_DEBUG */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/compress.c avr32-2.6/fs/ubifs/compress.c
+--- linux-2.6.25.6/fs/ubifs/compress.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/compress.c 2008-06-12 15:09:45.315815846 +0200
+@@ -0,0 +1,253 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ * Copyright (C) 2006, 2007 University of Szeged, Hungary
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ * Zoltan Sogor
++ */
++
++/*
++ * This file provides a single place to access to compression and
++ * decompression.
++ */
++
++#include <linux/crypto.h>
++#include "ubifs.h"
++
++/* Fake description object for the "none" compressor */
++static struct ubifs_compressor none_compr = {
++ .compr_type = UBIFS_COMPR_NONE,
++ .name = "no compression",
++ .capi_name = "",
++};
++
++#ifdef CONFIG_UBIFS_FS_LZO
++static DEFINE_MUTEX(lzo_mutex);
++
++static struct ubifs_compressor lzo_compr = {
++ .compr_type = UBIFS_COMPR_LZO,
++ .comp_mutex = &lzo_mutex,
++ .name = "LZO",
++ .capi_name = "lzo",
++};
++#else
++static struct ubifs_compressor lzo_compr = {
++ .compr_type = UBIFS_COMPR_LZO,
++ .name = "LZO",
++};
++#endif
++
++#ifdef CONFIG_UBIFS_FS_ZLIB
++static DEFINE_MUTEX(deflate_mutex);
++static DEFINE_MUTEX(inflate_mutex);
++
++static struct ubifs_compressor zlib_compr = {
++ .compr_type = UBIFS_COMPR_ZLIB,
++ .comp_mutex = &deflate_mutex,
++ .decomp_mutex = &inflate_mutex,
++ .name = "zlib",
++ .capi_name = "deflate",
++};
++#else
++static struct ubifs_compressor zlib_compr = {
++ .compr_type = UBIFS_COMPR_ZLIB,
++ .name = "zlib",
++};
++#endif
++
++/* All UBIFS compressors */
++struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
++
++/**
++ * ubifs_compress - compress data.
++ * @in_buf: data to compress
++ * @in_len: length of the data to compress
++ * @out_buf: output buffer where compressed data should be stored
++ * @out_len: output buffer length is returned here
++ * @compr_type: type of compression to use on enter, actually used compression
++ * type on exit
++ *
++ * This function compresses input buffer @in_buf of length @in_len and stores
++ * the result in the output buffer @out_buf and the resulting length in
++ * @out_len. If the input buffer does not compress, it is just copied to the
++ * @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if
++ * compression error occurred.
++ *
++ * Note, if the input buffer was not compressed, it is copied to the output
++ * buffer and %UBIFS_COMPR_NONE is returned in @compr_type.
++ *
++ * This functions returns %0 on success or a negative error code on failure.
++ */
++void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
++ int *compr_type)
++{
++ int err;
++ struct ubifs_compressor *compr = ubifs_compressors[*compr_type];
++
++ if (*compr_type == UBIFS_COMPR_NONE)
++ goto no_compr;
++
++ /* If the input data is small, do not even try to compress it */
++ if (in_len < UBIFS_MIN_COMPR_LEN)
++ goto no_compr;
++
++ if (compr->comp_mutex)
++ mutex_lock(compr->comp_mutex);
++ err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf,
++ out_len);
++ if (compr->comp_mutex)
++ mutex_unlock(compr->comp_mutex);
++ if (unlikely(err)) {
++ ubifs_warn("cannot compress %d bytes, compressor %s, "
++ "error %d, leave data uncompressed",
++ in_len, compr->name, err);
++ goto no_compr;
++ }
++
++ /*
++ * Presently, we just require that compression results in less data,
++ * rather than any defined minimum compression ratio or amount.
++ */
++ if (ALIGN(*out_len, 8) >= ALIGN(in_len, 8))
++ goto no_compr;
++
++ return;
++
++no_compr:
++ memcpy(out_buf, in_buf, in_len);
++ *out_len = in_len;
++ *compr_type = UBIFS_COMPR_NONE;
++}
++
++/**
++ * ubifs_decompress - decompress data.
++ * @in_buf: data to decompress
++ * @in_len: length of the data to decompress
++ * @out_buf: output buffer where decompressed data should
++ * @out_len: output length is returned here
++ * @compr_type: type of compression
++ *
++ * This function decompresses data from buffer @in_buf into buffer @out_buf.
++ * The length of the uncompressed data is returned in @out_len. This functions
++ * returns %0 on success or a negative error code on failure.
++ */
++int ubifs_decompress(const void *in_buf, int in_len, void *out_buf,
++ int *out_len, int compr_type)
++{
++ int err;
++ struct ubifs_compressor *compr;
++
++ if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
++ ubifs_err("invalid compression type %d", compr_type);
++ return -EINVAL;
++ }
++
++ compr = ubifs_compressors[compr_type];
++
++ if (unlikely(!compr->capi_name)) {
++ ubifs_err("%s compression is not compiled in", compr->name);
++ return -EINVAL;
++ }
++
++ if (compr_type == UBIFS_COMPR_NONE) {
++ memcpy(out_buf, in_buf, in_len);
++ *out_len = in_len;
++ return 0;
++ }
++
++ if (compr->decomp_mutex)
++ mutex_lock(compr->decomp_mutex);
++ err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf,
++ out_len);
++ if (compr->decomp_mutex)
++ mutex_unlock(compr->decomp_mutex);
++ if (err)
++ ubifs_err("cannot decompress %d bytes, compressor %s, "
++ "error %d", in_len, compr->name, err);
++
++ return err;
++}
++
++/**
++ * compr_init - initialize a compressor.
++ * @compr: compressor description object
++ *
++ * This function initializes the requested compressor and returns zero in case
++ * of success or a negative error code in case of failure.
++ */
++static int __init compr_init(struct ubifs_compressor *compr)
++{
++ if (compr->capi_name) {
++ compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
++ if (IS_ERR(compr->cc)) {
++ ubifs_err("cannot initialize compressor %s, error %ld",
++ compr->name, PTR_ERR(compr->cc));
++ return PTR_ERR(compr->cc);
++ }
++ }
++
++ ubifs_compressors[compr->compr_type] = compr;
++ return 0;
++}
++
++/**
++ * compr_exit - de-initialize a compressor.
++ * @compr: compressor description object
++ */
++static void compr_exit(struct ubifs_compressor *compr)
++{
++ if (compr->capi_name)
++ crypto_free_comp(compr->cc);
++ return;
++}
++
++/**
++ * ubifs_compressors_init - initialize UBIFS compressors.
++ *
++ * This function initializes the compressor which were compiled in. Returns
++ * zero in case of success and a negative error code in case of failure.
++ */
++int __init ubifs_compressors_init(void)
++{
++ int err;
++
++ err = compr_init(&lzo_compr);
++ if (err)
++ return err;
++
++ err = compr_init(&zlib_compr);
++ if (err)
++ goto out_lzo;
++
++ ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
++ return 0;
++
++out_lzo:
++ compr_exit(&lzo_compr);
++ return err;
++}
++
++/**
++ * ubifs_compressors_exit - de-initialize UBIFS compressors.
++ */
++void __exit ubifs_compressors_exit(void)
++{
++ compr_exit(&lzo_compr);
++ compr_exit(&zlib_compr);
++}
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/debug.c avr32-2.6/fs/ubifs/debug.c
+--- linux-2.6.25.6/fs/ubifs/debug.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/debug.c 2008-06-12 15:09:45.315815846 +0200
+@@ -0,0 +1,2210 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/*
++ * This file implements most of the debugging stuff which is compiled in only
++ * when it is enabled. But some debugging check functions are implemented in
++ * corresponding subsystem, just because they are closely related and utilize
++ * various local functions of those subsystems.
++ */
++
++#define UBIFS_DBG_PRESERVE_UBI
++
++#include "ubifs.h"
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++DEFINE_SPINLOCK(dbg_lock);
++
++static char dbg_key_buf0[128];
++static char dbg_key_buf1[128];
++
++unsigned int ubifs_msg_flags = UBIFS_MSG_FLAGS_DEFAULT;
++unsigned int ubifs_chk_flags = UBIFS_CHK_FLAGS_DEFAULT;
++unsigned int ubifs_tst_flags;
++
++module_param_named(debug_msgs, ubifs_msg_flags, uint, S_IRUGO | S_IWUSR);
++module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR);
++module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR);
++
++MODULE_PARM_DESC(debug_msgs, "Debug message type flags");
++MODULE_PARM_DESC(debug_chks, "Debug check flags");
++MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
++
++static const char *get_key_fmt(int fmt)
++{
++ switch (fmt) {
++ case UBIFS_SIMPLE_KEY_FMT:
++ return "simple";
++ default:
++ return "unknown/invalid format";
++ }
++}
++
++static const char *get_key_hash(int hash)
++{
++ switch (hash) {
++ case UBIFS_KEY_HASH_R5:
++ return "R5";
++ case UBIFS_KEY_HASH_TEST:
++ return "test";
++ default:
++ return "unknown/invalid name hash";
++ }
++}
++
++static const char *get_key_type(int type)
++{
++ switch (type) {
++ case UBIFS_INO_KEY:
++ return "inode";
++ case UBIFS_DENT_KEY:
++ return "direntry";
++ case UBIFS_XENT_KEY:
++ return "xentry";
++ case UBIFS_DATA_KEY:
++ return "data";
++ case UBIFS_TRUN_KEY:
++ return "truncate";
++ default:
++ return "unknown/invalid key";
++ }
++}
++
++static void sprintf_key(const struct ubifs_info *c, const union ubifs_key *key,
++ char *buffer)
++{
++ char *p = buffer;
++ int type = key_type(c, key);
++
++ if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) {
++ switch (type) {
++ case UBIFS_INO_KEY:
++ sprintf(p, "(%lu, %s)", key_inum(c, key),
++ get_key_type(type));
++ break;
++ case UBIFS_DENT_KEY:
++ case UBIFS_XENT_KEY:
++ sprintf(p, "(%lu, %s, %#08x)", key_inum(c, key),
++ get_key_type(type), key_hash(c, key));
++ break;
++ case UBIFS_DATA_KEY:
++ sprintf(p, "(%lu, %s, %u)", key_inum(c, key),
++ get_key_type(type), key_block(c, key));
++ break;
++ case UBIFS_TRUN_KEY:
++ sprintf(p, "(%lu, %s)",
++ key_inum(c, key), get_key_type(type));
++ break;
++ default:
++ sprintf(p, "(bad key type: %#08x, %#08x)",
++ key->u32[0], key->u32[1]);
++ }
++ } else
++ sprintf(p, "bad key format %d", c->key_fmt);
++}
++
++const char *dbg_key_str0(const struct ubifs_info *c, const union ubifs_key *key)
++{
++ /* dbg_lock must be held */
++ sprintf_key(c, key, dbg_key_buf0);
++ return dbg_key_buf0;
++}
++
++const char *dbg_key_str1(const struct ubifs_info *c, const union ubifs_key *key)
++{
++ /* dbg_lock must be held */
++ sprintf_key(c, key, dbg_key_buf1);
++ return dbg_key_buf1;
++}
++
++const char *dbg_ntype(int type)
++{
++ switch (type) {
++ case UBIFS_PAD_NODE:
++ return "padding node";
++ case UBIFS_SB_NODE:
++ return "superblock node";
++ case UBIFS_MST_NODE:
++ return "master node";
++ case UBIFS_REF_NODE:
++ return "reference node";
++ case UBIFS_INO_NODE:
++ return "inode node";
++ case UBIFS_DENT_NODE:
++ return "direntry node";
++ case UBIFS_XENT_NODE:
++ return "xentry node";
++ case UBIFS_DATA_NODE:
++ return "data node";
++ case UBIFS_TRUN_NODE:
++ return "truncate node";
++ case UBIFS_IDX_NODE:
++ return "indexing node";
++ case UBIFS_CS_NODE:
++ return "commit start node";
++ case UBIFS_ORPH_NODE:
++ return "orphan node";
++ default:
++ return "unknown node";
++ }
++}
++
++static const char *dbg_gtype(int type)
++{
++ switch (type) {
++ case UBIFS_NO_NODE_GROUP:
++ return "no node group";
++ case UBIFS_IN_NODE_GROUP:
++ return "in node group";
++ case UBIFS_LAST_OF_NODE_GROUP:
++ return "last of node group";
++ default:
++ return "unknown";
++ }
++}
++
++const char *dbg_cstate(int cmt_state)
++{
++ switch (cmt_state) {
++ case COMMIT_RESTING:
++ return "commit resting";
++ case COMMIT_BACKGROUND:
++ return "background commit requested";
++ case COMMIT_REQUIRED:
++ return "commit required";
++ case COMMIT_RUNNING_BACKGROUND:
++ return "BACKGROUND commit running";
++ case COMMIT_RUNNING_REQUIRED:
++ return "commit running and required";
++ case COMMIT_BROKEN:
++ return "broken commit";
++ default:
++ return "unknown commit state";
++ }
++}
++
++static void dump_ch(const struct ubifs_ch *ch)
++{
++ printk(KERN_DEBUG "\tmagic %#x\n", le32_to_cpu(ch->magic));
++ printk(KERN_DEBUG "\tcrc %#x\n", le32_to_cpu(ch->crc));
++ printk(KERN_DEBUG "\tnode_type %d (%s)\n", ch->node_type,
++ dbg_ntype(ch->node_type));
++ printk(KERN_DEBUG "\tgroup_type %d (%s)\n", ch->group_type,
++ dbg_gtype(ch->group_type));
++ printk(KERN_DEBUG "\tsqnum %llu\n",
++ (unsigned long long)le64_to_cpu(ch->sqnum));
++ printk(KERN_DEBUG "\tlen %u\n", le32_to_cpu(ch->len));
++}
++
++void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
++{
++ const struct ubifs_inode *ui = ubifs_inode(inode);
++
++ printk(KERN_DEBUG "inode %lu\n", inode->i_ino);
++ printk(KERN_DEBUG "size %llu\n",
++ (unsigned long long)i_size_read(inode));
++ printk(KERN_DEBUG "nlink %u\n", inode->i_nlink);
++ printk(KERN_DEBUG "uid %u\n", (unsigned int)inode->i_uid);
++ printk(KERN_DEBUG "gid %u\n", (unsigned int)inode->i_gid);
++ printk(KERN_DEBUG "atime %u.%u\n",
++ (unsigned int)inode->i_atime.tv_sec,
++ (unsigned int)inode->i_atime.tv_nsec);
++ printk(KERN_DEBUG "mtime %u.%u\n",
++ (unsigned int)inode->i_mtime.tv_sec,
++ (unsigned int)inode->i_mtime.tv_nsec);
++ printk(KERN_DEBUG "ctime %u.%u\n",
++ (unsigned int)inode->i_ctime.tv_sec,
++ (unsigned int)inode->i_ctime.tv_nsec);
++ printk(KERN_DEBUG "creat_sqnum %llu\n", ui->creat_sqnum);
++ printk(KERN_DEBUG "xattr_size %lld\n", ui->xattr_size);
++ printk(KERN_DEBUG "xattr_cnt %d\n", ui->xattr_cnt);
++ printk(KERN_DEBUG "xattr_names %d\n", ui->xattr_names);
++ printk(KERN_DEBUG "dirty %u\n", ui->dirty);
++ printk(KERN_DEBUG "xattr %u\n", ui->xattr);
++ printk(KERN_DEBUG "flags %d\n", ui->flags);
++ printk(KERN_DEBUG "compr_type %d\n", ui->compr_type);
++ printk(KERN_DEBUG "data_len %d\n", ui->data_len);
++}
++
++void dbg_dump_node(const struct ubifs_info *c, const void *node)
++{
++ int i, n;
++ union ubifs_key key;
++ const struct ubifs_ch *ch = node;
++
++ if (dbg_failure_mode)
++ return;
++
++ /* If the magic is incorrect, just hexdump the first bytes */
++ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) {
++ printk(KERN_DEBUG "Not a node, first %zu bytes:", UBIFS_CH_SZ);
++ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
++ (void *)node, UBIFS_CH_SZ, 1);
++ return;
++ }
++
++ spin_lock(&dbg_lock);
++ dump_ch(node);
++
++ switch (ch->node_type) {
++ case UBIFS_PAD_NODE:
++ {
++ const struct ubifs_pad_node *pad = node;
++
++ printk(KERN_DEBUG "\tpad_len %u\n",
++ le32_to_cpu(pad->pad_len));
++ break;
++ }
++ case UBIFS_SB_NODE:
++ {
++ const struct ubifs_sb_node *sup = node;
++ unsigned int sup_flags = le32_to_cpu(sup->flags);
++
++ printk(KERN_DEBUG "\tkey_hash %d (%s)\n",
++ (int)sup->key_hash, get_key_hash(sup->key_hash));
++ printk(KERN_DEBUG "\tkey_fmt %d (%s)\n",
++ (int)sup->key_fmt, get_key_fmt(sup->key_fmt));
++ printk(KERN_DEBUG "\tflags %#x\n", sup_flags);
++ printk(KERN_DEBUG "\t big_lpt %u\n",
++ !!(sup_flags & UBIFS_FLG_BIGLPT));
++ printk(KERN_DEBUG "\tmin_io_size %u\n",
++ le32_to_cpu(sup->min_io_size));
++ printk(KERN_DEBUG "\tleb_size %u\n",
++ le32_to_cpu(sup->leb_size));
++ printk(KERN_DEBUG "\tleb_cnt %u\n",
++ le32_to_cpu(sup->leb_cnt));
++ printk(KERN_DEBUG "\tmax_leb_cnt %u\n",
++ le32_to_cpu(sup->max_leb_cnt));
++ printk(KERN_DEBUG "\tmax_bud_bytes %llu\n",
++ (unsigned long long)le64_to_cpu(sup->max_bud_bytes));
++ printk(KERN_DEBUG "\tlog_lebs %u\n",
++ le32_to_cpu(sup->log_lebs));
++ printk(KERN_DEBUG "\tlpt_lebs %u\n",
++ le32_to_cpu(sup->lpt_lebs));
++ printk(KERN_DEBUG "\torph_lebs %u\n",
++ le32_to_cpu(sup->orph_lebs));
++ printk(KERN_DEBUG "\tjhead_cnt %u\n",
++ le32_to_cpu(sup->jhead_cnt));
++ printk(KERN_DEBUG "\tfanout %u\n",
++ le32_to_cpu(sup->fanout));
++ printk(KERN_DEBUG "\tlsave_cnt %u\n",
++ le32_to_cpu(sup->lsave_cnt));
++ printk(KERN_DEBUG "\tdefault_compr %u\n",
++ (int)le16_to_cpu(sup->default_compr));
++ printk(KERN_DEBUG "\trp_size %llu\n",
++ (unsigned long long)le64_to_cpu(sup->rp_size));
++ printk(KERN_DEBUG "\trp_uid %u\n",
++ le32_to_cpu(sup->rp_uid));
++ printk(KERN_DEBUG "\trp_gid %u\n",
++ le32_to_cpu(sup->rp_gid));
++ printk(KERN_DEBUG "\tfmt_version %u\n",
++ le32_to_cpu(sup->fmt_version));
++ printk(KERN_DEBUG "\ttime_gran %u\n",
++ le32_to_cpu(sup->time_gran));
++ printk(KERN_DEBUG "\tUUID %02X%02X%02X%02X-%02X%02X"
++ "-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
++ sup->uuid[0], sup->uuid[1], sup->uuid[2], sup->uuid[3],
++ sup->uuid[4], sup->uuid[5], sup->uuid[6], sup->uuid[7],
++ sup->uuid[8], sup->uuid[9], sup->uuid[10], sup->uuid[11],
++ sup->uuid[12], sup->uuid[13], sup->uuid[14],
++ sup->uuid[15]);
++ break;
++ }
++ case UBIFS_MST_NODE:
++ {
++ const struct ubifs_mst_node *mst = node;
++
++ printk(KERN_DEBUG "\thighest_inum %llu\n",
++ (unsigned long long)le64_to_cpu(mst->highest_inum));
++ printk(KERN_DEBUG "\tcommit number %llu\n",
++ (unsigned long long)le64_to_cpu(mst->cmt_no));
++ printk(KERN_DEBUG "\tflags %#x\n",
++ le32_to_cpu(mst->flags));
++ printk(KERN_DEBUG "\tlog_lnum %u\n",
++ le32_to_cpu(mst->log_lnum));
++ printk(KERN_DEBUG "\troot_lnum %u\n",
++ le32_to_cpu(mst->root_lnum));
++ printk(KERN_DEBUG "\troot_offs %u\n",
++ le32_to_cpu(mst->root_offs));
++ printk(KERN_DEBUG "\troot_len %u\n",
++ le32_to_cpu(mst->root_len));
++ printk(KERN_DEBUG "\tgc_lnum %u\n",
++ le32_to_cpu(mst->gc_lnum));
++ printk(KERN_DEBUG "\tihead_lnum %u\n",
++ le32_to_cpu(mst->ihead_lnum));
++ printk(KERN_DEBUG "\tihead_offs %u\n",
++ le32_to_cpu(mst->ihead_offs));
++ printk(KERN_DEBUG "\tindex_size %u\n",
++ le32_to_cpu(mst->index_size));
++ printk(KERN_DEBUG "\tlpt_lnum %u\n",
++ le32_to_cpu(mst->lpt_lnum));
++ printk(KERN_DEBUG "\tlpt_offs %u\n",
++ le32_to_cpu(mst->lpt_offs));
++ printk(KERN_DEBUG "\tnhead_lnum %u\n",
++ le32_to_cpu(mst->nhead_lnum));
++ printk(KERN_DEBUG "\tnhead_offs %u\n",
++ le32_to_cpu(mst->nhead_offs));
++ printk(KERN_DEBUG "\tltab_lnum %u\n",
++ le32_to_cpu(mst->ltab_lnum));
++ printk(KERN_DEBUG "\tltab_offs %u\n",
++ le32_to_cpu(mst->ltab_offs));
++ printk(KERN_DEBUG "\tlsave_lnum %u\n",
++ le32_to_cpu(mst->lsave_lnum));
++ printk(KERN_DEBUG "\tlsave_offs %u\n",
++ le32_to_cpu(mst->lsave_offs));
++ printk(KERN_DEBUG "\tlscan_lnum %u\n",
++ le32_to_cpu(mst->lscan_lnum));
++ printk(KERN_DEBUG "\tleb_cnt %u\n",
++ le32_to_cpu(mst->leb_cnt));
++ printk(KERN_DEBUG "\tempty_lebs %u\n",
++ le32_to_cpu(mst->empty_lebs));
++ printk(KERN_DEBUG "\tidx_lebs %u\n",
++ le32_to_cpu(mst->idx_lebs));
++ printk(KERN_DEBUG "\ttotal_free %llu\n",
++ (unsigned long long)le64_to_cpu(mst->total_free));
++ printk(KERN_DEBUG "\ttotal_dirty %llu\n",
++ (unsigned long long)le64_to_cpu(mst->total_dirty));
++ printk(KERN_DEBUG "\ttotal_used %llu\n",
++ (unsigned long long)le64_to_cpu(mst->total_used));
++ printk(KERN_DEBUG "\ttotal_dead %llu\n",
++ (unsigned long long)le64_to_cpu(mst->total_dead));
++ printk(KERN_DEBUG "\ttotal_dark %llu\n",
++ (unsigned long long)le64_to_cpu(mst->total_dark));
++ break;
++ }
++ case UBIFS_REF_NODE:
++ {
++ const struct ubifs_ref_node *ref = node;
++
++ printk(KERN_DEBUG "\tlnum %u\n",
++ le32_to_cpu(ref->lnum));
++ printk(KERN_DEBUG "\toffs %u\n",
++ le32_to_cpu(ref->offs));
++ printk(KERN_DEBUG "\tjhead %u\n",
++ le32_to_cpu(ref->jhead));
++ break;
++ }
++ case UBIFS_INO_NODE:
++ {
++ const struct ubifs_ino_node *ino = node;
++
++ key_read(c, &ino->key, &key);
++ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
++ printk(KERN_DEBUG "\tcreat_sqnum %llu\n",
++ (unsigned long long)le64_to_cpu(ino->creat_sqnum));
++ printk(KERN_DEBUG "\tsize %llu\n",
++ (unsigned long long)le64_to_cpu(ino->size));
++ printk(KERN_DEBUG "\tnlink %u\n",
++ le32_to_cpu(ino->nlink));
++ printk(KERN_DEBUG "\tatime %lld.%u\n",
++ (long long)le64_to_cpu(ino->atime_sec),
++ le32_to_cpu(ino->atime_nsec));
++ printk(KERN_DEBUG "\tmtime %lld.%u\n",
++ (long long)le64_to_cpu(ino->mtime_sec),
++ le32_to_cpu(ino->mtime_nsec));
++ printk(KERN_DEBUG "\tctime %lld.%u\n",
++ (long long)le64_to_cpu(ino->ctime_sec),
++ le32_to_cpu(ino->ctime_nsec));
++ printk(KERN_DEBUG "\tuid %u\n",
++ le32_to_cpu(ino->uid));
++ printk(KERN_DEBUG "\tgid %u\n",
++ le32_to_cpu(ino->gid));
++ printk(KERN_DEBUG "\tmode %u\n",
++ le32_to_cpu(ino->mode));
++ printk(KERN_DEBUG "\tflags %#x\n",
++ le32_to_cpu(ino->flags));
++ printk(KERN_DEBUG "\txattr_cnt %u\n",
++ le32_to_cpu(ino->xattr_cnt));
++ printk(KERN_DEBUG "\txattr_size %llu\n",
++ (unsigned long long)le64_to_cpu(ino->xattr_size));
++ printk(KERN_DEBUG "\txattr_names %u\n",
++ le32_to_cpu(ino->xattr_names));
++ printk(KERN_DEBUG "\tcompr_type %#x\n",
++ (int)le16_to_cpu(ino->compr_type));
++ printk(KERN_DEBUG "\tdata len %u\n",
++ le32_to_cpu(ino->data_len));
++ break;
++ }
++ case UBIFS_DENT_NODE:
++ case UBIFS_XENT_NODE:
++ {
++ const struct ubifs_dent_node *dent = node;
++ int nlen = le16_to_cpu(dent->nlen);
++
++ key_read(c, &dent->key, &key);
++ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
++ printk(KERN_DEBUG "\tinum %llu\n",
++ (unsigned long long)le64_to_cpu(dent->inum));
++ printk(KERN_DEBUG "\ttype %d\n", (int)dent->type);
++ printk(KERN_DEBUG "\tnlen %d\n", nlen);
++ printk(KERN_DEBUG "\tname ");
++
++ if (nlen > UBIFS_MAX_NLEN)
++ printk(KERN_DEBUG "(bad name length, not printing, "
++ "bad or corrupted node)");
++ else {
++ for (i = 0; i < nlen && dent->name[i]; i++)
++ printk("%c", dent->name[i]);
++ }
++ printk("\n");
++
++ break;
++ }
++ case UBIFS_DATA_NODE:
++ {
++ const struct ubifs_data_node *dn = node;
++ int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
++
++ key_read(c, &dn->key, &key);
++ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
++ printk(KERN_DEBUG "\tsize %u\n",
++ le32_to_cpu(dn->size));
++ printk(KERN_DEBUG "\tcompr_typ %d\n",
++ (int)le16_to_cpu(dn->compr_type));
++ printk(KERN_DEBUG "\tdata size %d\n",
++ dlen);
++ printk(KERN_DEBUG "\tdata:\n");
++ print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 1,
++ (void *)&dn->data, dlen, 0);
++ break;
++ }
++ case UBIFS_TRUN_NODE:
++ {
++ const struct ubifs_trun_node *trun = node;
++
++ printk(KERN_DEBUG "\tinum %u\n",
++ le32_to_cpu(trun->inum));
++ printk(KERN_DEBUG "\told_size %llu\n",
++ (unsigned long long)le64_to_cpu(trun->old_size));
++ printk(KERN_DEBUG "\tnew_size %llu\n",
++ (unsigned long long)le64_to_cpu(trun->new_size));
++ break;
++ }
++ case UBIFS_IDX_NODE:
++ {
++ const struct ubifs_idx_node *idx = node;
++
++ n = le16_to_cpu(idx->child_cnt);
++ printk(KERN_DEBUG "\tchild_cnt %d\n", n);
++ printk(KERN_DEBUG "\tlevel %d\n",
++ (int)le16_to_cpu(idx->level));
++ printk(KERN_DEBUG "\tBranches:\n");
++
++ for (i = 0; i < n && i < c->fanout - 1; i++) {
++ const struct ubifs_branch *br;
++
++ br = ubifs_idx_branch(c, idx, i);
++ key_read(c, &br->key, &key);
++ printk(KERN_DEBUG "\t%d: LEB %d:%d len %d key %s\n",
++ i, le32_to_cpu(br->lnum), le32_to_cpu(br->offs),
++ le32_to_cpu(br->len), DBGKEY(&key));
++ }
++ break;
++ }
++ case UBIFS_CS_NODE:
++ break;
++ case UBIFS_ORPH_NODE:
++ {
++ const struct ubifs_orph_node *orph = node;
++
++ printk(KERN_DEBUG "\tcommit number %llu\n",
++ (unsigned long long)
++ le64_to_cpu(orph->cmt_no) & LLONG_MAX);
++ printk(KERN_DEBUG "\tlast node flag %llu\n",
++ (unsigned long long)(le64_to_cpu(orph->cmt_no)) >> 63);
++ n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3;
++ printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n);
++ for (i = 0; i < n; i++)
++ printk(KERN_DEBUG "\t ino %llu\n",
++ le64_to_cpu(orph->inos[i]));
++ break;
++ }
++ default:
++ printk(KERN_DEBUG "node type %d was not recognized\n",
++ (int)ch->node_type);
++ }
++ spin_unlock(&dbg_lock);
++}
++
++void dbg_dump_budget_req(const struct ubifs_budget_req *req)
++{
++ spin_lock(&dbg_lock);
++ printk(KERN_DEBUG "Budgeting request: new_ino %d, dirtied_ino %d\n",
++ req->new_ino, req->dirtied_ino);
++ printk(KERN_DEBUG "\tnew_ino_d %d, dirtied_ino_d %d\n",
++ req->new_ino_d, req->dirtied_ino_d);
++ printk(KERN_DEBUG "\tnew_page %d, dirtied_page %d\n",
++ req->new_page, req->dirtied_page);
++ printk(KERN_DEBUG "\tnew_dent %d, mod_dent %d\n",
++ req->new_dent, req->mod_dent);
++ printk(KERN_DEBUG "\tidx_growth %d\n", req->idx_growth);
++ printk(KERN_DEBUG "\tdata_growth %d dd_growth %d\n",
++ req->data_growth, req->dd_growth);
++ spin_unlock(&dbg_lock);
++}
++
++void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
++{
++ spin_lock(&dbg_lock);
++ printk(KERN_DEBUG "Lprops statistics: empty_lebs %d, idx_lebs %d\n",
++ lst->empty_lebs, lst->idx_lebs);
++ printk(KERN_DEBUG "\ttaken_empty_lebs %d, total_free %lld, "
++ "total_dirty %lld\n", lst->taken_empty_lebs, lst->total_free,
++ lst->total_dirty);
++ printk(KERN_DEBUG "\ttotal_used %lld, total_dark %lld, "
++ "total_dead %lld\n", lst->total_used, lst->total_dark,
++ lst->total_dead);
++ spin_unlock(&dbg_lock);
++}
++
++void dbg_dump_budg(struct ubifs_info *c)
++{
++ int i;
++ struct rb_node *rb;
++ struct ubifs_bud *bud;
++ struct ubifs_gced_idx_leb *idx_gc;
++
++ spin_lock(&dbg_lock);
++ printk(KERN_DEBUG "Budgeting info: budg_data_growth %lld, "
++ "budg_dd_growth %lld, budg_idx_growth %lld\n",
++ c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth);
++ printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, "
++ "freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth,
++ c->budg_data_growth + c->budg_dd_growth + c->budg_idx_growth,
++ c->freeable_cnt);
++ printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %lld, "
++ "calc_idx_sz %lld, idx_gc_cnt %d\n", c->min_idx_lebs,
++ c->old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt);
++ printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_ino_cnt %ld, "
++ "dirty_zn_cnt %ld, clean_zn_cnt %ld\n",
++ atomic_long_read(&c->dirty_pg_cnt),
++ atomic_long_read(&c->dirty_ino_cnt),
++ atomic_long_read(&c->dirty_zn_cnt),
++ atomic_long_read(&c->clean_zn_cnt));
++ printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n",
++ c->dark_wm, c->dead_wm, c->max_idx_node_sz);
++ printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n",
++ c->gc_lnum, c->ihead_lnum);
++ for (i = 0; i < c->jhead_cnt; i++)
++ printk(KERN_DEBUG "\tjhead %d\t LEB %d\n",
++ c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum);
++ for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) {
++ bud = rb_entry(rb, struct ubifs_bud, rb);
++ printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum);
++ }
++ list_for_each_entry(bud, &c->old_buds, list)
++ printk(KERN_DEBUG "\told bud LEB %d\n", bud->lnum);
++ list_for_each_entry(idx_gc, &c->idx_gc, list)
++ printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n",
++ idx_gc->lnum, idx_gc->unmap);
++ printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state);
++ spin_unlock(&dbg_lock);
++}
++
++void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
++{
++ printk(KERN_DEBUG "LEB %d lprops: free %d, dirty %d (used %d), "
++ "flags %#x\n", lp->lnum, lp->free, lp->dirty,
++ c->leb_size - lp->free - lp->dirty, lp->flags);
++}
++
++void dbg_dump_lprops(struct ubifs_info *c)
++{
++ int lnum, err;
++ struct ubifs_lprops lp;
++ struct ubifs_lp_stats lst;
++
++ printk(KERN_DEBUG "Dumping LEB properties\n");
++ ubifs_get_lp_stats(c, &lst);
++ dbg_dump_lstats(&lst);
++
++ for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
++ err = ubifs_read_one_lp(c, lnum, &lp);
++ if (err)
++ ubifs_err("cannot read lprops for LEB %d", lnum);
++
++ dbg_dump_lprop(c, &lp);
++ }
++}
++
++void dbg_dump_leb(const struct ubifs_info *c, int lnum)
++{
++ struct ubifs_scan_leb *sleb;
++ struct ubifs_scan_node *snod;
++
++ if (dbg_failure_mode)
++ return;
++
++ printk(KERN_DEBUG "Dumping LEB %d\n", lnum);
++
++ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
++ if (IS_ERR(sleb)) {
++ ubifs_err("scan error %d", (int)PTR_ERR(sleb));
++ return;
++ }
++
++ printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum,
++ sleb->nodes_cnt, sleb->endpt);
++
++ list_for_each_entry(snod, &sleb->nodes, list) {
++ cond_resched();
++ printk(KERN_DEBUG "Dumping node at LEB %d:%d len %d\n", lnum,
++ snod->offs, snod->len);
++ dbg_dump_node(c, snod->node);
++ }
++
++ ubifs_scan_destroy(sleb);
++ return;
++}
++
++void dbg_dump_znode(const struct ubifs_info *c,
++ const struct ubifs_znode *znode)
++{
++ int n;
++ const struct ubifs_zbranch *zbr;
++
++ spin_lock(&dbg_lock);
++ if (znode->parent)
++ zbr = &znode->parent->zbranch[znode->iip];
++ else
++ zbr = &c->zroot;
++
++ printk(KERN_DEBUG "znode %p, LEB %d:%d len %d parent %p iip %d level %d"
++ " child_cnt %d flags %lx\n", znode, zbr->lnum, zbr->offs,
++ zbr->len, znode->parent, znode->iip, znode->level,
++ znode->child_cnt, znode->flags);
++
++ if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) {
++ spin_unlock(&dbg_lock);
++ return;
++ }
++
++ printk(KERN_DEBUG "zbranches:\n");
++ for (n = 0; n < znode->child_cnt; n++) {
++ zbr = &znode->zbranch[n];
++ if (znode->level > 0)
++ printk(KERN_DEBUG "\t%d: znode %p LEB %d:%d len %d key "
++ "%s\n", n, zbr->znode, zbr->lnum,
++ zbr->offs, zbr->len,
++ DBGKEY(&zbr->key));
++ else
++ printk(KERN_DEBUG "\t%d: LNC %p LEB %d:%d len %d key "
++ "%s\n", n, zbr->znode, zbr->lnum,
++ zbr->offs, zbr->len,
++ DBGKEY(&zbr->key));
++ }
++ spin_unlock(&dbg_lock);
++}
++
++void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
++{
++ int i;
++
++ printk(KERN_DEBUG "Dumping heap cat %d (%d elements)\n",
++ cat, heap->cnt);
++ for (i = 0; i < heap->cnt; i++) {
++ struct ubifs_lprops *lprops = heap->arr[i];
++
++ printk(KERN_DEBUG "\t%d. LEB %d hpos %d free %d dirty %d "
++ "flags %d\n", i, lprops->lnum, lprops->hpos,
++ lprops->free, lprops->dirty, lprops->flags);
++ }
++}
++
++void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
++ struct ubifs_nnode *parent, int iip)
++{
++ int i;
++
++ printk(KERN_DEBUG "Dumping pnode:\n");
++ printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n",
++ (size_t)pnode, (size_t)parent, (size_t)pnode->cnext);
++ printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n",
++ pnode->flags, iip, pnode->level, pnode->num);
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ struct ubifs_lprops *lp = &pnode->lprops[i];
++
++ printk(KERN_DEBUG "\t%d: free %d dirty %d flags %d lnum %d\n",
++ i, lp->free, lp->dirty, lp->flags, lp->lnum);
++ }
++}
++
++void dbg_dump_tnc(struct ubifs_info *c)
++{
++ struct ubifs_znode *znode;
++ int level;
++
++ printk(KERN_DEBUG "\n");
++ printk(KERN_DEBUG "Dumping the TNC tree\n");
++ znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
++ level = znode->level;
++ printk(KERN_DEBUG "== Level %d ==\n", level);
++ while (znode) {
++ if (level != znode->level) {
++ level = znode->level;
++ printk(KERN_DEBUG "== Level %d ==\n", level);
++ }
++ dbg_dump_znode(c, znode);
++ znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
++ }
++
++ printk(KERN_DEBUG "\n");
++}
++
++static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode,
++ void *priv)
++{
++ dbg_dump_znode(c, znode);
++ return 0;
++}
++
++/**
++ * dbg_dump_index - dump the on-flash index.
++ * @c: UBIFS file-system description object
++ *
++ * This function dumps whole UBIFS indexing B-tree, unlike 'dbg_dump_tnc()'
++ * which dumps only in-memory znodes and does not read znodes which from flash.
++ */
++void dbg_dump_index(struct ubifs_info *c)
++{
++ dbg_walk_index(c, NULL, dump_znode, NULL);
++}
++
++/*
++ * dbg_check_dir - check directory inode size and link count.
++ * @c: UBIFS file-system description object
++ * @dir: the directory to calculate size for
++ * @size: the result is returned here
++ *
++ * This function makes sure that directory size and link count are correct.
++ * Returns zero in case of success and a negative error code in case of
++ * failure.
++ *
++ * Note, it is good idea to make sure the @dir->i_mutex is locked before
++ * calling this function.
++ */
++int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
++{
++ unsigned int nlink = 2;
++ union ubifs_key key;
++ struct ubifs_dent_node *dent, *pdent = NULL;
++ struct qstr nm = { .name = NULL };
++ loff_t size = UBIFS_INO_NODE_SZ;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
++ return 0;
++
++ if (!S_ISDIR(dir->i_mode))
++ return 0;
++
++ lowest_dent_key(c, &key, dir->i_ino);
++ while (1) {
++ int err;
++
++ dent = ubifs_tnc_next_ent(c, &key, &nm);
++ if (IS_ERR(dent)) {
++ err = PTR_ERR(dent);
++ if (err == -ENOENT)
++ break;
++ return err;
++ }
++
++ nm.name = dent->name;
++ nm.len = le16_to_cpu(dent->nlen);
++ size += CALC_DENT_SIZE(nm.len);
++ if (dent->type == UBIFS_ITYPE_DIR)
++ nlink += 1;
++ kfree(pdent);
++ pdent = dent;
++ key_read(c, &dent->key, &key);
++ }
++ kfree(pdent);
++
++ if (i_size_read(dir) != size) {
++ ubifs_err("directory inode %lu has size %llu, "
++ "but calculated size is %llu", dir->i_ino,
++ (unsigned long long)i_size_read(dir),
++ (unsigned long long)size);
++ dump_stack();
++ return -EINVAL;
++ }
++ if (dir->i_nlink != nlink) {
++ ubifs_err("directory inode %lu has nlink %u, but calculated "
++ "nlink is %u", dir->i_ino, dir->i_nlink, nlink);
++ dump_stack();
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/**
++ * dbg_check_key_order - make sure that colliding keys are properly ordered.
++ * @c: UBIFS file-system description object
++ * @zbr1: first zbranch
++ * @zbr1: following zbranch
++ *
++ * In UBIFS indexing B-tree colliding keys has to be sorted in binary order of
++ * names of the direntries/xentries which are referred by the keys. This
++ * function reads direntries/xentries referred by @zbr1 and @zbr2 and makes
++ * sure the name of direntry/xentry referred by @zbr1 is less than
++ * direntry/xentry referred by @zbr2. Returns zero if this is true, %1 if not,
++ * and a negative error code in case of failure.
++ */
++static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
++ struct ubifs_zbranch *zbr2)
++{
++ int err, nlen1, nlen2, cmp;
++ struct ubifs_dent_node *dent1, *dent2;
++ union ubifs_key key;
++
++ ubifs_assert(!keys_cmp(c, &zbr1->key, &zbr2->key));
++ dent1 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
++ if (!dent1)
++ return -ENOMEM;
++ dent2 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
++ if (!dent2) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++
++ err = ubifs_tnc_read_node(c, zbr1, dent1);
++ if (err)
++ goto out_free;
++ err = ubifs_validate_entry(c, dent1);
++ if (err)
++ goto out_free;
++
++ err = ubifs_tnc_read_node(c, zbr2, dent2);
++ if (err)
++ goto out_free;
++ err = ubifs_validate_entry(c, dent2);
++ if (err)
++ goto out_free;
++
++ /* Make sure node keys are the same as in zbranch */
++ err = 1;
++ key_read(c, &dent1->key, &key);
++ if (keys_cmp(c, &zbr1->key, &key)) {
++ dbg_err("1st entry at %d:%d has key %s", zbr1->lnum,
++ zbr1->offs, DBGKEY(&key));
++ dbg_err("but it should have key %s according to tnc",
++ DBGKEY(&zbr1->key));
++ dbg_dump_node(c, dent1);
++ goto out_free;
++ }
++
++ key_read(c, &dent2->key, &key);
++ if (keys_cmp(c, &zbr2->key, &key)) {
++ dbg_err("2nd entry at %d:%d has key %s", zbr1->lnum,
++ zbr1->offs, DBGKEY(&key));
++ dbg_err("but it should have key %s according to tnc",
++ DBGKEY(&zbr2->key));
++ dbg_dump_node(c, dent2);
++ goto out_free;
++ }
++
++ nlen1 = le16_to_cpu(dent1->nlen);
++ nlen2 = le16_to_cpu(dent2->nlen);
++
++ cmp = memcmp(dent1->name, dent2->name, min_t(int, nlen1, nlen2));
++ if (cmp < 0 || (cmp == 0 && nlen1 < nlen2)) {
++ err = 0;
++ goto out_free;
++ }
++ if (cmp == 0 && nlen1 == nlen2)
++ dbg_err("2 xent/dent nodes with the same name");
++ else
++ dbg_err("bad order of colliding key %s",
++ DBGKEY(&key));
++
++ dbg_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
++ dbg_dump_node(c, dent1);
++ dbg_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
++ dbg_dump_node(c, dent2);
++
++out_free:
++ kfree(dent2);
++ kfree(dent1);
++ return err;
++}
++
++/**
++ * dbg_check_znode - check if znode is all right.
++ * @c: UBIFS file-system description object
++ * @zbr: zbranch which points to this znode
++ *
++ * This function makes sure that znode referred to by @zbr is all right.
++ * Returns zero if it is, and %-EINVAL if it is not.
++ */
++static int dbg_check_znode(struct ubifs_info *c, struct ubifs_zbranch *zbr)
++{
++ struct ubifs_znode *znode = zbr->znode;
++ struct ubifs_znode *zp = znode->parent;
++ int n, err, cmp;
++
++ if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) {
++ err = 1;
++ goto out;
++ }
++ if (znode->level < 0) {
++ err = 2;
++ goto out;
++ }
++ if (znode->iip < 0 || znode->iip >= c->fanout) {
++ err = 3;
++ goto out;
++ }
++
++ if (zbr->len == 0)
++ /* Only dirty zbranch may have no on-flash nodes */
++ if (!ubifs_zn_dirty(znode)) {
++ err = 4;
++ goto out;
++ }
++
++ if (ubifs_zn_dirty(znode)) {
++ /*
++ * If znode is dirty, its parent has to be dirty as well. The
++ * order of the operation is important, so we have to have
++ * memory barriers.
++ */
++ smp_mb();
++ if (zp && !ubifs_zn_dirty(zp)) {
++ /*
++ * The dirty flag is atomic and is cleared outside the
++ * TNC mutex, so znode's dirty flag may now have
++ * been cleared. The child is always cleared before the
++ * parent, so we just need to check again.
++ */
++ smp_mb();
++ if (ubifs_zn_dirty(znode)) {
++ err = 5;
++ goto out;
++ }
++ }
++ }
++
++ if (zp) {
++ const union ubifs_key *min, *max;
++
++ if (znode->level != zp->level - 1) {
++ err = 6;
++ goto out;
++ }
++
++ /* Make sure the 'parent' pointer in our znode is correct */
++ err = ubifs_search_zbranch(c, zp, &zbr->key, &n);
++ if (!err) {
++ /* This zbranch does not exist in the parent */
++ err = 7;
++ goto out;
++ }
++
++ if (znode->iip >= zp->child_cnt) {
++ err = 8;
++ goto out;
++ }
++
++ if (znode->iip != n) {
++ /* This may happen only in case of collisions */
++ if (keys_cmp(c, &zp->zbranch[n].key,
++ &zp->zbranch[znode->iip].key)) {
++ err = 9;
++ goto out;
++ }
++ n = znode->iip;
++ }
++
++ /*
++ * Make sure that the first key in our znode is greater than or
++ * equal to the key in the pointing zbranch.
++ */
++ min = &zbr->key;
++ cmp = keys_cmp(c, min, &znode->zbranch[0].key);
++ if (cmp == 1) {
++ err = 10;
++ goto out;
++ }
++
++ if (n + 1 < zp->child_cnt) {
++ max = &zp->zbranch[n + 1].key;
++
++ /*
++ * Make sure the last key in our znode is less or
++ * equivalent than the the key in zbranch which goes
++ * after our pointing zbranch.
++ */
++ cmp = keys_cmp(c, max,
++ &znode->zbranch[znode->child_cnt - 1].key);
++ if (cmp == -1) {
++ err = 11;
++ goto out;
++ }
++ }
++ } else {
++ /* This may only be root znode */
++ if (zbr != &c->zroot) {
++ err = 12;
++ goto out;
++ }
++ }
++
++ /*
++ * Make sure that next key is greater or equivalent then the previous
++ * one.
++ */
++ for (n = 1; n < znode->child_cnt; n++) {
++ cmp = keys_cmp(c, &znode->zbranch[n - 1].key,
++ &znode->zbranch[n].key);
++ if (cmp > 0) {
++ err = 13;
++ goto out;
++ }
++ if (cmp == 0) {
++ /* This can only be keys with colliding hash */
++ if (!is_hash_key(c, &znode->zbranch[n].key)) {
++ err = 14;
++ goto out;
++ }
++
++ if (znode->level != 0 || c->replaying)
++ continue;
++
++ /*
++ * Colliding keys should follow binary order of
++ * corresponding xentry/dentry names.
++ */
++ err = dbg_check_key_order(c, &znode->zbranch[n - 1],
++ &znode->zbranch[n]);
++ if (err < 0)
++ return err;
++ if (err) {
++ err = 15;
++ goto out;
++ }
++ }
++ }
++
++ for (n = 0; n < znode->child_cnt; n++) {
++ if (!znode->zbranch[n].znode &&
++ (znode->zbranch[n].lnum == 0 ||
++ znode->zbranch[n].len == 0)) {
++ err = 16;
++ goto out;
++ }
++
++ if (znode->zbranch[n].lnum != 0 &&
++ znode->zbranch[n].len == 0) {
++ err = 17;
++ goto out;
++ }
++
++ if (znode->zbranch[n].lnum == 0 &&
++ znode->zbranch[n].len != 0) {
++ err = 18;
++ goto out;
++ }
++
++ if (znode->zbranch[n].lnum == 0 &&
++ znode->zbranch[n].offs != 0) {
++ err = 19;
++ goto out;
++ }
++
++ if (znode->level != 0 && znode->zbranch[n].znode)
++ if (znode->zbranch[n].znode->parent != znode) {
++ err = 20;
++ goto out;
++ }
++ }
++
++ return 0;
++
++out:
++ ubifs_err("failed, error %d", err);
++ ubifs_msg("dump of the znode");
++ dbg_dump_znode(c, znode);
++ if (zp) {
++ ubifs_msg("dump of the parent znode");
++ dbg_dump_znode(c, zp);
++ }
++ dump_stack();
++ return -EINVAL;
++}
++
++/**
++ * dbg_check_tnc - check TNC tree.
++ * @c: UBIFS file-system description object
++ * @extra: do extra checks that are possible at start commit
++ *
++ * This function traverses whole TNC tree and checks every znode. Returns zero
++ * if everything is all right and %-EINVAL if something is wrong with TNC.
++ */
++int dbg_check_tnc(struct ubifs_info *c, int extra)
++{
++ struct ubifs_znode *znode;
++ long clean_cnt = 0, dirty_cnt = 0;
++ int err, last;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_TNC))
++ return 0;
++
++ ubifs_assert(mutex_is_locked(&c->tnc_mutex));
++ if (!c->zroot.znode)
++ return 0;
++
++ znode = ubifs_tnc_postorder_first(c->zroot.znode);
++ while (1) {
++ struct ubifs_znode *prev;
++ struct ubifs_zbranch *zbr;
++
++ if (!znode->parent)
++ zbr = &c->zroot;
++ else
++ zbr = &znode->parent->zbranch[znode->iip];
++
++ err = dbg_check_znode(c, zbr);
++ if (err)
++ return err;
++
++ if (extra) {
++ if (ubifs_zn_dirty(znode))
++ dirty_cnt += 1;
++ else
++ clean_cnt += 1;
++ }
++
++ prev = znode;
++ znode = ubifs_tnc_postorder_next(znode);
++ if (!znode)
++ break;
++
++ /*
++ * If the last key of this znode is equivalent to the first key
++ * of the next znode (collision), then check order of the keys.
++ */
++ last = prev->child_cnt - 1;
++ if (prev->level == 0 && znode->level == 0 && !c->replaying &&
++ !keys_cmp(c, &prev->zbranch[last].key,
++ &znode->zbranch[0].key)) {
++ err = dbg_check_key_order(c, &prev->zbranch[last],
++ &znode->zbranch[0]);
++ if (err < 0)
++ return err;
++ if (err) {
++ ubifs_msg("first znode");
++ dbg_dump_znode(c, prev);
++ ubifs_msg("second znode");
++ dbg_dump_znode(c, znode);
++ return -EINVAL;
++ }
++ }
++ }
++
++ if (extra) {
++ if (clean_cnt != atomic_long_read(&c->clean_zn_cnt)) {
++ ubifs_err("incorrect clean_zn_cnt %ld, calculated %ld",
++ atomic_long_read(&c->clean_zn_cnt),
++ clean_cnt);
++ return -EINVAL;
++ }
++ if (dirty_cnt != atomic_long_read(&c->dirty_zn_cnt)) {
++ ubifs_err("incorrect dirty_zn_cnt %ld, calculated %ld",
++ atomic_long_read(&c->dirty_zn_cnt),
++ dirty_cnt);
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * dbg_walk_index - walk the on-flash index.
++ * @c: UBIFS file-system description object
++ * @leaf_cb: called for each leaf node
++ * @znode_cb: called for each indexing node
++ * @priv: private date which is passed to callbacks
++ *
++ * This function walks the UBIFS index and calls the @leaf_cb for each leaf
++ * node and @znode_cb for each indexing node. Returns zero in case of success
++ * and a negative error code in case of failure.
++ *
++ * It would be better if this function removed every znode it pulled to into
++ * the TNC, so that the behavior more closely matched the non-debugging
++ * behavior.
++ */
++int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
++ dbg_znode_callback znode_cb, void *priv)
++{
++ int err;
++ struct ubifs_zbranch *zbr;
++ struct ubifs_znode *znode, *child;
++
++ mutex_lock(&c->tnc_mutex);
++ /* If the root indexing node is not in TNC - pull it */
++ if (!c->zroot.znode) {
++ c->zroot.znode = ubifs_load_znode(c, &c->zroot, NULL, 0);
++ if (IS_ERR(c->zroot.znode)) {
++ err = PTR_ERR(c->zroot.znode);
++ c->zroot.znode = NULL;
++ goto out_unlock;
++ }
++ }
++
++ /*
++ * We are going to traverse the indexing tree in the postorder manner.
++ * Go down and find the leftmost indexing node where we are going to
++ * start from.
++ */
++ znode = c->zroot.znode;
++ while (znode->level > 0) {
++ zbr = &znode->zbranch[0];
++ child = zbr->znode;
++ if (!child) {
++ child = ubifs_load_znode(c, zbr, znode, 0);
++ if (IS_ERR(child)) {
++ err = PTR_ERR(child);
++ goto out_unlock;
++ }
++ zbr->znode = child;
++ }
++
++ znode = child;
++ }
++
++ /* Iterate over all indexing nodes */
++ while (1) {
++ int idx;
++
++ cond_resched();
++
++ if (znode_cb) {
++ err = znode_cb(c, znode, priv);
++ if (err) {
++ ubifs_err("znode checking function returned "
++ "error %d", err);
++ dbg_dump_znode(c, znode);
++ goto out_dump;
++ }
++ }
++ if (leaf_cb && znode->level == 0) {
++ for (idx = 0; idx < znode->child_cnt; idx++) {
++ zbr = &znode->zbranch[idx];
++ err = leaf_cb(c, zbr, priv);
++ if (err) {
++ ubifs_err("leaf checking function "
++ "returned error %d, for leaf "
++ "at LEB %d:%d",
++ err, zbr->lnum, zbr->offs);
++ goto out_dump;
++ }
++ }
++ }
++
++ if (!znode->parent)
++ break;
++
++ idx = znode->iip + 1;
++ znode = znode->parent;
++ if (idx < znode->child_cnt) {
++ /* Switch to the next index in the parent */
++ zbr = &znode->zbranch[idx];
++ child = zbr->znode;
++ if (!child) {
++ child = ubifs_load_znode(c, zbr, znode, idx);
++ if (IS_ERR(child)) {
++ err = PTR_ERR(child);
++ goto out_unlock;
++ }
++ zbr->znode = child;
++ }
++ znode = child;
++ } else
++ /*
++ * This is the last child, switch to the parent and
++ * continue.
++ */
++ continue;
++
++ /* Go to the lowest leftmost znode in the new sub-tree */
++ while (znode->level > 0) {
++ zbr = &znode->zbranch[0];
++ child = zbr->znode;
++ if (!child) {
++ child = ubifs_load_znode(c, zbr, znode, 0);
++ if (IS_ERR(child)) {
++ err = PTR_ERR(child);
++ goto out_unlock;
++ }
++ zbr->znode = child;
++ }
++ znode = child;
++ }
++ }
++
++ mutex_unlock(&c->tnc_mutex);
++ return 0;
++
++out_dump:
++ if (znode->parent)
++ zbr = &znode->parent->zbranch[znode->iip];
++ else
++ zbr = &c->zroot;
++ ubifs_msg("dump of znode at LEB %d:%d", zbr->lnum, zbr->offs);
++ dbg_dump_znode(c, znode);
++out_unlock:
++ mutex_unlock(&c->tnc_mutex);
++ return err;
++}
++
++/**
++ * add_size - add znode size to partially calculated index size.
++ * @c: UBIFS file-system description object
++ * @znode: znode to add size for
++ * @priv: partially calculated index size
++ *
++ * This is a helper function for 'dbg_check_idx_size()' which is called for
++ * every indexing node and adds its size to the 'long long' variable pointed to
++ * by @priv.
++ */
++static int add_size(struct ubifs_info *c, struct ubifs_znode *znode, void *priv)
++{
++ long long *idx_size = priv;
++ int add;
++
++ add = ubifs_idx_node_sz(c, znode->child_cnt);
++ add = ALIGN(add, 8);
++ *idx_size += add;
++ return 0;
++}
++
++/**
++ * dbg_check_idx_size - check index size.
++ * @c: UBIFS file-system description object
++ * @idx_size: size to check
++ *
++ * This function walks the UBIFS index, calculates its size and checks that the
++ * size is equivalent to @idx_size. Returns zero in case of success and a
++ * negative error code in case of failure.
++ */
++int dbg_check_idx_size(struct ubifs_info *c, long long idx_size)
++{
++ int err;
++ long long calc = 0;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ))
++ return 0;
++
++ err = dbg_walk_index(c, NULL, add_size, &calc);
++ if (err) {
++ ubifs_err("error %d while walking the index", err);
++ return err;
++ }
++
++ if (calc != idx_size) {
++ ubifs_err("index size check failed: calculated size is %lld, "
++ "should be %lld", calc, idx_size);
++ dump_stack();
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/**
++ * fsck_inode - information about an inode used when checking the file-system.
++ * @rb: link in the RB-tree of inodes
++ * @inum: inode number
++ * @mode: inode type, permissions, etc
++ * @nlink: inode link count
++ * @xatt_cnt: count of extended attributes
++ * @references: how many directory/xattr entries refer this inode (calculated
++ * while walking the index)
++ * @calc_cnt: for directory inode count of child directories, for regular files
++ * count of extended attributes
++ * @size: inode size (read from on-flash inode)
++ * @xattr_sz: summary size of all extended attributes (read from on-flash
++ * inode)
++ * @calc_sz: for directories calculated directory size, for regular files
++ * calculated summary size of all extended attributes
++ */
++struct fsck_inode {
++ struct rb_node rb;
++ ino_t inum;
++ umode_t mode;
++ int nlink;
++ int xattr_cnt;
++ int references;
++ int calc_cnt;
++ long long size;
++ long long xattr_sz;
++ long long calc_sz;
++};
++
++/**
++ * fsck_data - private FS checking information.
++ * @inodes: RB-tree of all inodes (contains @struct fsck_inode objects)
++ */
++struct fsck_data {
++ struct rb_root inodes;
++};
++
++/**
++ * add_inode - add inode information to RB-tree of inodes.
++ * @c: UBIFS file-system description object
++ * @fsckd: FS checking information
++ * @ino: raw UBIFS inode to add
++ *
++ * This is a helper function for 'check_leaf()' which adds information about
++ * inode @ino to the RB-tree of inodes. Returns inode information pointer in
++ * case of success and a negative error code in case of failure.
++ */
++static struct fsck_inode *add_inode(struct ubifs_info *c,
++ struct fsck_data *fsckd,
++ struct ubifs_ino_node *ino)
++{
++ struct rb_node **p, *parent = NULL;
++ struct fsck_inode *fscki;
++ ino_t inum = key_inum_flash(c, &ino->key);
++
++ p = &fsckd->inodes.rb_node;
++ while (*p) {
++ parent = *p;
++ fscki = rb_entry(parent, struct fsck_inode, rb);
++ if (inum < fscki->inum)
++ p = &(*p)->rb_left;
++ else if (inum > fscki->inum)
++ p = &(*p)->rb_right;
++ else
++ return fscki;
++ }
++
++ fscki = kzalloc(sizeof(struct fsck_inode), GFP_NOFS);
++ if (!fscki)
++ return ERR_PTR(-ENOMEM);
++
++ fscki->inum = inum;
++ fscki->nlink = le32_to_cpu(ino->nlink);
++ fscki->size = le64_to_cpu(ino->size);
++ fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt);
++ fscki->xattr_sz = le64_to_cpu(ino->xattr_size);
++ fscki->mode = le32_to_cpu(ino->mode);
++ if (S_ISDIR(fscki->mode)) {
++ fscki->calc_sz = UBIFS_INO_NODE_SZ;
++ fscki->calc_cnt = 2;
++ }
++ rb_link_node(&fscki->rb, parent, p);
++ rb_insert_color(&fscki->rb, &fsckd->inodes);
++ return fscki;
++}
++
++/**
++ * search_inode - search inode in the RB-tree of inodes.
++ * @fsckd: FS checking information
++ * @inum: inode number to search
++ *
++ * This is a helper function for 'check_leaf()' which searches inode @inum in
++ * the RB-tree of inodes and returns an inode information pointer or %NULL if
++ * the inode was not found.
++ */
++static struct fsck_inode *search_inode(struct fsck_data *fsckd, ino_t inum)
++{
++ struct rb_node *p;
++ struct fsck_inode *fscki;
++
++ p = fsckd->inodes.rb_node;
++ while (p) {
++ fscki = rb_entry(p, struct fsck_inode, rb);
++ if (inum < fscki->inum)
++ p = p->rb_left;
++ else if (inum > fscki->inum)
++ p = p->rb_right;
++ else
++ return fscki;
++ }
++ return NULL;
++}
++
++/**
++ * read_add_inode - read inode node and add it to RB-tree of inodes.
++ * @c: UBIFS file-system description object
++ * @fsckd: FS checking information
++ * @inum: inode number to read
++ *
++ * This is a helper function for 'check_leaf()' which finds inode node @inum in
++ * the index, reads it, and adds it to the RB-tree of inodes. Returns inode
++ * information pointer in case of success and a negative error code in case of
++ * failure.
++ */
++static struct fsck_inode *read_add_inode(struct ubifs_info *c,
++ struct fsck_data *fsckd, ino_t inum)
++{
++ int n, err;
++ union ubifs_key key;
++ struct ubifs_znode *znode;
++ struct ubifs_zbranch *zbr;
++ struct ubifs_ino_node *ino;
++ struct fsck_inode *fscki;
++
++ fscki = search_inode(fsckd, inum);
++ if (fscki)
++ return fscki;
++
++ ino_key_init(c, &key, inum);
++ err = ubifs_lookup_level0(c, &key, &znode, &n);
++ if (!err) {
++ ubifs_err("inode %lu not found in index", inum);
++ return ERR_PTR(-ENOENT);
++ } else if (err < 0) {
++ ubifs_err("error %d while looking up inode %lu", err, inum);
++ return ERR_PTR(err);
++ }
++
++ zbr = &znode->zbranch[n];
++ if (zbr->len < UBIFS_INO_NODE_SZ) {
++ ubifs_err("bad node %lu node length %d", inum, zbr->len);
++ return ERR_PTR(-EINVAL);
++ }
++
++ ino = kmalloc(zbr->len, GFP_NOFS);
++ if (!ino)
++ return ERR_PTR(-ENOMEM);
++
++ err = ubifs_tnc_read_node(c, zbr, ino);
++ if (err) {
++ ubifs_err("cannot read inode node at LEB %d:%d, error %d",
++ zbr->lnum, zbr->offs, err);
++ kfree(ino);
++ return ERR_PTR(err);
++ }
++
++ fscki = add_inode(c, fsckd, ino);
++ kfree(ino);
++ if (IS_ERR(fscki)) {
++ ubifs_err("error %ld while adding inode %lu node",
++ PTR_ERR(fscki), inum);
++ return fscki;
++ }
++
++ return fscki;
++}
++
++/**
++ * check_leaf - check leaf node.
++ * @c: UBIFS file-system description object
++ * @zbr: zbranch of the leaf node to check
++ * @priv: FS checking information
++ *
++ * This is a helper function for 'dbg_check_filesystem()' which is called for
++ * every single leaf node while walking the indexing tree. It checks that the
++ * leaf node referred from the indexing tree exists, has correct CRC, and does
++ * some other basic validation. This function is also responsible for building
++ * an RB-tree of inodes - it adds all inodes into the RB-tree. It also
++ * calculates reference count, size, etc for each inode in order to later
++ * compare them to the information stored inside the inodes and detect possible
++ * inconsistencies. Returns zero in case of success and a negative error code
++ * in case of failure.
++ */
++static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
++ void *priv)
++{
++ ino_t inum;
++ void *node;
++ int err, type = key_type(c, &zbr->key);
++ struct fsck_inode *fscki;
++
++ if (zbr->len < UBIFS_CH_SZ) {
++ ubifs_err("bad leaf length %d (LEB %d:%d)",
++ zbr->len, zbr->lnum, zbr->offs);
++ return -EINVAL;
++ }
++
++ node = kmalloc(zbr->len, GFP_NOFS);
++ if (!node)
++ return -ENOMEM;
++
++ err = ubifs_tnc_read_node(c, zbr, node);
++ if (err) {
++ ubifs_err("cannot read leaf node at LEB %d:%d, error %d",
++ zbr->lnum, zbr->offs, err);
++ goto out_free;
++ }
++
++ /* If this is an inode node, add it to RB-tree of inodes */
++ if (type == UBIFS_INO_KEY) {
++ fscki = add_inode(c, priv, node);
++ if (IS_ERR(fscki)) {
++ err = PTR_ERR(fscki);
++ ubifs_err("error %d while adding inode node", err);
++ goto out_dump;
++ }
++ goto out;
++ }
++
++ if (type != UBIFS_DENT_KEY && type != UBIFS_XENT_KEY &&
++ type != UBIFS_DATA_KEY) {
++ ubifs_err("unexpected node type %d at LEB %d:%d",
++ type, zbr->lnum, zbr->offs);
++ err = -EINVAL;
++ goto out_free;
++ }
++
++ if (type == UBIFS_DATA_KEY) {
++ long long blk_offs;
++ struct ubifs_data_node *dn = node;
++
++ /*
++ * Search the inode node this data node belongs to and insert
++ * it to the RB-tree of inodes.
++ */
++ inum = key_inum_flash(c, &dn->key);
++ fscki = read_add_inode(c, priv, inum);
++ if (IS_ERR(fscki)) {
++ err = PTR_ERR(fscki);
++ ubifs_err("error %d while processing data node and "
++ "trying to find inode node %lu", err, inum);
++ goto out_dump;
++ }
++
++ /* Make sure the data node is within inode size */
++ blk_offs = (key_block_flash(c, &dn->key) << UBIFS_BLOCK_SHIFT);
++ blk_offs += le32_to_cpu(dn->size);
++ if (blk_offs > fscki->size) {
++ ubifs_err("data node at LEB %d:%d is not within inode "
++ "size %lld", zbr->lnum, zbr->offs, fscki->size);
++ err = -EINVAL;
++ goto out_dump;
++ }
++ } else {
++ int nlen;
++ struct ubifs_dent_node *dent = node;
++ struct fsck_inode *fscki1;
++
++ err = ubifs_validate_entry(c, dent);
++ if (err)
++ goto out_dump;
++
++ /*
++ * Search the inode node this entry refers to and the parent
++ * inode node and insert them to the RB-tree of inodes.
++ */
++ inum = le64_to_cpu(dent->inum);
++ fscki = read_add_inode(c, priv, inum);
++ if (IS_ERR(fscki)) {
++ err = PTR_ERR(fscki);
++ ubifs_err("error %d while processing entry node and "
++ "trying to find inode node %lu", err, inum);
++ goto out_dump;
++ }
++
++ /* Count how many direntries or xentries refers this inode */
++ fscki->references += 1;
++
++ inum = key_inum_flash(c, &dent->key);
++ fscki1 = read_add_inode(c, priv, inum);
++ if (IS_ERR(fscki1)) {
++ err = PTR_ERR(fscki);
++ ubifs_err("error %d while processing entry node and "
++ "trying to find parent inode node %lu",
++ err, inum);
++ goto out_dump;
++ }
++
++ nlen = le16_to_cpu(dent->nlen);
++ if (type == UBIFS_XENT_KEY) {
++ fscki1->calc_cnt += 1;
++ fscki1->calc_sz += CALC_DENT_SIZE(nlen);
++ fscki1->calc_sz += CALC_XATTR_BYTES(fscki->size);
++ } else {
++ fscki1->calc_sz += CALC_DENT_SIZE(nlen);
++ if (dent->type == UBIFS_ITYPE_DIR)
++ fscki1->calc_cnt += 1;
++ }
++ }
++
++out:
++ kfree(node);
++ return 0;
++
++out_dump:
++ ubifs_msg("dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
++ dbg_dump_node(c, node);
++out_free:
++ kfree(node);
++ return err;
++}
++
++/**
++ * free_inodes - free RB-tree of inodes.
++ * @fsckd: FS checking information
++ */
++static void free_inodes(struct fsck_data *fsckd)
++{
++ struct rb_node *this = fsckd->inodes.rb_node;
++ struct fsck_inode *fscki;
++
++ while (this) {
++ if (this->rb_left)
++ this = this->rb_left;
++ else if (this->rb_right)
++ this = this->rb_right;
++ else {
++ fscki = rb_entry(this, struct fsck_inode, rb);
++ this = rb_parent(this);
++ if (this) {
++ if (this->rb_left == &fscki->rb)
++ this->rb_left = NULL;
++ else
++ this->rb_right = NULL;
++ }
++ kfree(fscki);
++ }
++ }
++}
++
++/**
++ * check_inodes - checks all inodes.
++ * @c: UBIFS file-system description object
++ * @fsckd: FS checking information
++ *
++ * This is a helper function for 'dbg_check_filesystem()' which walks the
++ * RB-tree of inodes after the index scan has been finished, and checks that
++ * inode nlink, size, etc are correct. Returns zero if inodes are fine,
++ * %-EINVAL if not, and a negative error code in case of failure.
++ */
++static int check_inodes(struct ubifs_info *c, struct fsck_data *fsckd)
++{
++ int n, err;
++ union ubifs_key key;
++ struct ubifs_znode *znode;
++ struct ubifs_zbranch *zbr;
++ struct ubifs_ino_node *ino;
++ struct fsck_inode *fscki;
++ struct rb_node *this = rb_first(&fsckd->inodes);
++
++ while (this) {
++ fscki = rb_entry(this, struct fsck_inode, rb);
++ this = rb_next(this);
++
++ if (S_ISDIR(fscki->mode)) {
++ /*
++ * Directories have to have exactly one reference (they
++ * cannot have hardlinks), although root inode is an
++ * exception.
++ */
++ if (fscki->inum != UBIFS_ROOT_INO &&
++ fscki->references != 1) {
++ ubifs_err("directory inode %lu has %d "
++ "direntries which refer it, but "
++ "should be 1", fscki->inum,
++ fscki->references);
++ goto out_dump;
++ }
++ if (fscki->inum == UBIFS_ROOT_INO &&
++ fscki->references != 0) {
++ ubifs_err("root inode %lu has non-zero (%d) "
++ "direntries which refer it",
++ fscki->inum, fscki->references);
++ goto out_dump;
++ }
++ if (fscki->calc_sz != fscki->size) {
++ ubifs_err("directory inode %lu size is %lld, "
++ "but calculated size is %lld",
++ fscki->inum, fscki->size,
++ fscki->calc_sz);
++ goto out_dump;
++ }
++ if (fscki->calc_cnt != fscki->nlink) {
++ ubifs_err("directory inode %lu nlink is %d, "
++ "but calculated nlink is %d",
++ fscki->inum, fscki->nlink,
++ fscki->calc_cnt);
++ goto out_dump;
++ }
++ } else {
++ if (fscki->references != fscki->nlink) {
++ ubifs_err("inode %lu nlink is %d, but "
++ "calculated nlink is %d", fscki->inum,
++ fscki->nlink, fscki->references);
++ goto out_dump;
++ }
++ if (fscki->xattr_sz != fscki->calc_sz) {
++ ubifs_err("inode %lu has xattr size %lld, but "
++ "calculated size is %lld",
++ fscki->inum, fscki->xattr_sz,
++ fscki->calc_sz);
++ goto out_dump;
++ }
++ if (fscki->xattr_cnt != fscki->calc_cnt) {
++ ubifs_err("inode %lu has %d xattrs, but "
++ "calculated count is %d", fscki->inum,
++ fscki->xattr_cnt, fscki->calc_cnt);
++ goto out_dump;
++ }
++ }
++ }
++
++ return 0;
++
++out_dump:
++ /* Read the bad inode and dump it */
++ ino_key_init(c, &key, fscki->inum);
++ err = ubifs_lookup_level0(c, &key, &znode, &n);
++ if (!err) {
++ ubifs_err("inode %lu not found in index", fscki->inum);
++ return -ENOENT;
++ } else if (err < 0) {
++ ubifs_err("error %d while looking up inode %lu",
++ err, fscki->inum);
++ return err;
++ }
++
++ zbr = &znode->zbranch[n];
++ ino = kmalloc(zbr->len, GFP_NOFS);
++ if (!ino)
++ return -ENOMEM;
++
++ err = ubifs_tnc_read_node(c, zbr, ino);
++ if (err) {
++ ubifs_err("cannot read inode node at LEB %d:%d, error %d",
++ zbr->lnum, zbr->offs, err);
++ kfree(ino);
++ return err;
++ }
++
++ ubifs_msg("dump of the inode %lu sitting in LEB %d:%d",
++ fscki->inum, zbr->lnum, zbr->offs);
++ dbg_dump_node(c, ino);
++ kfree(ino);
++ return -EINVAL;
++}
++
++/**
++ * dbg_check_filesystem - check the file-system.
++ * @c: UBIFS file-system description object
++ *
++ * This function checks the file system, namely:
++ * o makes sure that all leaf nodes exist and their CRCs are correct;
++ * o makes sure inode nlink, size, xattr size/count are correct (for all
++ * inodes).
++ *
++ * The function reads whole indexing tree and all nodes, so it is pretty
++ * heavy-weight. Returns zero if the file-system is consistent, %-EINVAL if
++ * not, and a negative error code in case of failure.
++ */
++int dbg_check_filesystem(struct ubifs_info *c)
++{
++ int err;
++ struct fsck_data fsckd;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_FS))
++ return 0;
++
++ fsckd.inodes = RB_ROOT;
++ err = dbg_walk_index(c, check_leaf, NULL, &fsckd);
++ if (err)
++ goto out_free;
++
++ err = check_inodes(c, &fsckd);
++ if (err)
++ goto out_free;
++
++ free_inodes(&fsckd);
++ return 0;
++
++out_free:
++ ubifs_err("file-system check failed with error %d", err);
++ dump_stack();
++ free_inodes(&fsckd);
++ return err;
++}
++
++static int invocation_cnt;
++
++int dbg_force_in_the_gaps(void)
++{
++ if (!dbg_force_in_the_gaps_enabled)
++ return 0;
++ /* Force in-the-gaps every 8th commit */
++ return !((invocation_cnt++) & 0x7);
++}
++
++/* Failure mode for recovery testing */
++
++#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
++
++struct failure_mode_info {
++ struct list_head list;
++ struct ubifs_info *c;
++};
++
++static LIST_HEAD(fmi_list);
++static DEFINE_SPINLOCK(fmi_lock);
++
++static unsigned int next;
++
++static int simple_rand(void)
++{
++ if (next == 0)
++ next = current->pid;
++ next = next * 1103515245 + 12345;
++ return (next >> 16) & 32767;
++}
++
++void dbg_failure_mode_registration(struct ubifs_info *c)
++{
++ struct failure_mode_info *fmi;
++
++ fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
++ if (!fmi) {
++ dbg_err("Failed to register failure mode - no memory");
++ return;
++ }
++ fmi->c = c;
++ spin_lock(&fmi_lock);
++ list_add_tail(&fmi->list, &fmi_list);
++ spin_unlock(&fmi_lock);
++}
++
++void dbg_failure_mode_deregistration(struct ubifs_info *c)
++{
++ struct failure_mode_info *fmi, *tmp;
++
++ spin_lock(&fmi_lock);
++ list_for_each_entry_safe(fmi, tmp, &fmi_list, list)
++ if (fmi->c == c) {
++ list_del(&fmi->list);
++ kfree(fmi);
++ }
++ spin_unlock(&fmi_lock);
++}
++
++static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc)
++{
++ struct failure_mode_info *fmi;
++
++ spin_lock(&fmi_lock);
++ list_for_each_entry(fmi, &fmi_list, list)
++ if (fmi->c->ubi == desc) {
++ struct ubifs_info *c = fmi->c;
++
++ spin_unlock(&fmi_lock);
++ return c;
++ }
++ spin_unlock(&fmi_lock);
++ return NULL;
++}
++
++static int in_failure_mode(struct ubi_volume_desc *desc)
++{
++ struct ubifs_info *c = dbg_find_info(desc);
++
++ if (c)
++ return c->failure_mode;
++ return 0;
++}
++
++static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
++{
++ struct ubifs_info *c = dbg_find_info(desc);
++
++ if (!c || !dbg_failure_mode)
++ return 0;
++ if (c->failure_mode)
++ return 1;
++ if (!c->fail_cnt) {
++ /* First call - decide delay to failure */
++ if (chance(1, 2)) {
++ unsigned int delay = 1 << (simple_rand() >> 11);
++
++ if (chance(1, 2)) {
++ c->fail_delay = 1;
++ c->fail_timeout = jiffies +
++ msecs_to_jiffies(delay);
++ dbg_rcvry("failing after %ums", delay);
++ } else {
++ c->fail_delay = 2;
++ c->fail_cnt_max = delay;
++ dbg_rcvry("failing after %u calls", delay);
++ }
++ }
++ c->fail_cnt += 1;
++ }
++ /* Determine if failure delay has expired */
++ if (c->fail_delay == 1) {
++ if (time_before(jiffies, c->fail_timeout))
++ return 0;
++ } else if (c->fail_delay == 2)
++ if (c->fail_cnt++ < c->fail_cnt_max)
++ return 0;
++ if (lnum == UBIFS_SB_LNUM) {
++ if (write) {
++ if (chance(1, 2))
++ return 0;
++ } else if (chance(19, 20))
++ return 0;
++ dbg_rcvry("failing in super block LEB %d", lnum);
++ } else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) {
++ if (chance(19, 20))
++ return 0;
++ dbg_rcvry("failing in master LEB %d", lnum);
++ } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) {
++ if (write) {
++ if (chance(99, 100))
++ return 0;
++ } else if (chance(399, 400))
++ return 0;
++ dbg_rcvry("failing in log LEB %d", lnum);
++ } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) {
++ if (write) {
++ if (chance(7, 8))
++ return 0;
++ } else if (chance(19, 20))
++ return 0;
++ dbg_rcvry("failing in LPT LEB %d", lnum);
++ } else if (lnum >= c->orph_first && lnum <= c->orph_last) {
++ if (write) {
++ if (chance(1, 2))
++ return 0;
++ } else if (chance(9, 10))
++ return 0;
++ dbg_rcvry("failing in orphan LEB %d", lnum);
++ } else if (lnum == c->ihead_lnum) {
++ if (chance(99, 100))
++ return 0;
++ dbg_rcvry("failing in index head LEB %d", lnum);
++ } else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) {
++ if (chance(9, 10))
++ return 0;
++ dbg_rcvry("failing in GC head LEB %d", lnum);
++ } else if (write && !RB_EMPTY_ROOT(&c->buds) &&
++ !ubifs_search_bud(c, lnum)) {
++ if (chance(19, 20))
++ return 0;
++ dbg_rcvry("failing in non-bud LEB %d", lnum);
++ } else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
++ c->cmt_state == COMMIT_RUNNING_REQUIRED) {
++ if (chance(999, 1000))
++ return 0;
++ dbg_rcvry("failing in bud LEB %d commit running", lnum);
++ } else {
++ if (chance(9999, 10000))
++ return 0;
++ dbg_rcvry("failing in bud LEB %d commit not running", lnum);
++ }
++ ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum);
++ c->failure_mode = 1;
++ dump_stack();
++ return 1;
++}
++
++static void cut_data(const void *buf, int len)
++{
++ int flen, i;
++ unsigned char *p = (void *)buf;
++
++ flen = (len * (long long)simple_rand()) >> 15;
++ for (i = flen; i < len; i++)
++ p[i] = 0xff;
++}
++
++int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
++ int len, int check)
++{
++ if (in_failure_mode(desc))
++ return -EIO;
++ return ubi_leb_read(desc, lnum, buf, offset, len, check);
++}
++
++int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
++ int offset, int len, int dtype)
++{
++ int err;
++
++ if (in_failure_mode(desc))
++ return -EIO;
++ if (do_fail(desc, lnum, 1))
++ cut_data(buf, len);
++ err = ubi_leb_write(desc, lnum, buf, offset, len, dtype);
++ if (err)
++ return err;
++ if (in_failure_mode(desc))
++ return -EIO;
++ return 0;
++}
++
++int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
++ int len, int dtype)
++{
++ int err;
++
++ if (do_fail(desc, lnum, 1))
++ return -EIO;
++ err = ubi_leb_change(desc, lnum, buf, len, dtype);
++ if (err)
++ return err;
++ if (do_fail(desc, lnum, 1))
++ return -EIO;
++ return 0;
++}
++
++int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum)
++{
++ int err;
++
++ if (do_fail(desc, lnum, 0))
++ return -EIO;
++ err = ubi_leb_erase(desc, lnum);
++ if (err)
++ return err;
++ if (do_fail(desc, lnum, 0))
++ return -EIO;
++ return 0;
++}
++
++int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
++{
++ int err;
++
++ if (do_fail(desc, lnum, 0))
++ return -EIO;
++ err = ubi_leb_unmap(desc, lnum);
++ if (err)
++ return err;
++ if (do_fail(desc, lnum, 0))
++ return -EIO;
++ return 0;
++}
++
++int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum)
++{
++ if (in_failure_mode(desc))
++ return -EIO;
++ return ubi_is_mapped(desc, lnum);
++}
++
++#endif /* CONFIG_UBIFS_FS_DEBUG */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/debug.h avr32-2.6/fs/ubifs/debug.h
+--- linux-2.6.25.6/fs/ubifs/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/debug.h 2008-06-12 15:09:45.315815846 +0200
+@@ -0,0 +1,396 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++#ifndef __UBIFS_DEBUG_H__
++#define __UBIFS_DEBUG_H__
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++#define UBIFS_DBG(op) op
++
++#define ubifs_assert(expr) do { \
++ if (unlikely(!(expr))) { \
++ printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
++ __func__, __LINE__, current->pid); \
++ dbg_dump_stack(); \
++ } \
++} while (0)
++
++#define ubifs_assert_cmt_locked(c) do { \
++ if (unlikely(down_write_trylock(&(c)->commit_sem))) { \
++ up_write(&(c)->commit_sem); \
++ printk(KERN_CRIT "commit lock is not locked!\n"); \
++ ubifs_assert(0); \
++ } \
++} while (0)
++
++#define dbg_dump_stack() do { \
++ if (!dbg_failure_mode) \
++ dump_stack(); \
++} while (0)
++
++/* Generic debugging messages */
++#define dbg_msg(fmt, ...) do { \
++ spin_lock(&dbg_lock); \
++ printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \
++ __func__, ##__VA_ARGS__); \
++ spin_unlock(&dbg_lock); \
++} while (0)
++
++#define dbg_do_msg(typ, fmt, ...) do { \
++ if (ubifs_msg_flags & typ) \
++ dbg_msg(fmt, ##__VA_ARGS__); \
++} while (0)
++
++#define dbg_err(fmt, ...) do { \
++ spin_lock(&dbg_lock); \
++ ubifs_err(fmt, ##__VA_ARGS__); \
++ spin_unlock(&dbg_lock); \
++} while (0)
++
++const char *dbg_key_str0(const struct ubifs_info *c,
++ const union ubifs_key *key);
++const char *dbg_key_str1(const struct ubifs_info *c,
++ const union ubifs_key *key);
++
++/*
++ * DBGKEY macros require dbg_lock to be held, which it is in the dbg message
++ * macros.
++ */
++#define DBGKEY(key) dbg_key_str0(c, (key))
++#define DBGKEY1(key) dbg_key_str1(c, (key))
++
++/* General messages */
++#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__)
++
++/* Additional journal messages */
++#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__)
++
++/* Additional TNC messages */
++#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__)
++
++/* Additional lprops messages */
++#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__)
++
++/* Additional LEB find messages */
++#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__)
++
++/* Additional mount messages */
++#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__)
++
++/* Additional I/O messages */
++#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__)
++
++/* Additional commit messages */
++#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__)
++
++/* Additional budgeting messages */
++#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__)
++
++/* Additional log messages */
++#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__)
++
++/* Additional gc messages */
++#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__)
++
++/* Additional scan messages */
++#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__)
++
++/* Additional recovery messages */
++#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__)
++
++/*
++ * Debugging message type flags (must match msg_type_names in debug.c).
++ *
++ * UBIFS_MSG_GEN: general messages
++ * UBIFS_MSG_JNL: journal messages
++ * UBIFS_MSG_MNT: mount messages
++ * UBIFS_MSG_CMT: commit messages
++ * UBIFS_MSG_FIND: LEB find messages
++ * UBIFS_MSG_BUDG: budgeting messages
++ * UBIFS_MSG_GC: garbage collection messages
++ * UBIFS_MSG_TNC: TNC messages
++ * UBIFS_MSG_LP: lprops messages
++ * UBIFS_MSG_IO: I/O messages
++ * UBIFS_MSG_LOG: log messages
++ * UBIFS_MSG_SCAN: scan messages
++ * UBIFS_MSG_RCVRY: recovery messages
++ */
++enum {
++ UBIFS_MSG_GEN = 0x1,
++ UBIFS_MSG_JNL = 0x2,
++ UBIFS_MSG_MNT = 0x4,
++ UBIFS_MSG_CMT = 0x8,
++ UBIFS_MSG_FIND = 0x10,
++ UBIFS_MSG_BUDG = 0x20,
++ UBIFS_MSG_GC = 0x40,
++ UBIFS_MSG_TNC = 0x80,
++ UBIFS_MSG_LP = 0x100,
++ UBIFS_MSG_IO = 0x200,
++ UBIFS_MSG_LOG = 0x400,
++ UBIFS_MSG_SCAN = 0x800,
++ UBIFS_MSG_RCVRY = 0x1000,
++};
++
++/* Debugging message type flags for each default debug message level */
++#define UBIFS_MSG_LVL_0 0
++#define UBIFS_MSG_LVL_1 0x1
++#define UBIFS_MSG_LVL_2 0x7f
++#define UBIFS_MSG_LVL_3 0xffff
++
++/*
++ * Debugging check flags (must match chk_names in debug.c).
++ *
++ * UBIFS_CHK_GEN: general checks
++ * UBIFS_CHK_TNC: check TNC
++ * UBIFS_CHK_IDX_SZ: check index size
++ * UBIFS_CHK_ORPH: check orphans
++ * UBIFS_CHK_OLD_IDX: check the old index
++ * UBIFS_CHK_LPROPS: check lprops
++ * UBIFS_CHK_FS: check the file-system
++ */
++enum {
++ UBIFS_CHK_GEN = 0x1,
++ UBIFS_CHK_TNC = 0x2,
++ UBIFS_CHK_IDX_SZ = 0x4,
++ UBIFS_CHK_ORPH = 0x8,
++ UBIFS_CHK_OLD_IDX = 0x10,
++ UBIFS_CHK_LPROPS = 0x20,
++ UBIFS_CHK_FS = 0x40,
++};
++
++/*
++ * Special testing flags (must match tst_names in debug.c).
++ *
++ * UBIFS_TST_FORCE_IN_THE_GAPS: force the use of in-the-gaps method
++ * UBIFS_TST_RCVRY: failure mode for recovery testing
++ */
++enum {
++ UBIFS_TST_FORCE_IN_THE_GAPS = 0x2,
++ UBIFS_TST_RCVRY = 0x4,
++};
++
++#if CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 1
++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_1
++#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 2
++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_2
++#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 3
++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_3
++#else
++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_0
++#endif
++
++#ifdef CONFIG_UBIFS_FS_DEBUG_CHKS
++#define UBIFS_CHK_FLAGS_DEFAULT 0xffffffff
++#else
++#define UBIFS_CHK_FLAGS_DEFAULT 0
++#endif
++
++extern spinlock_t dbg_lock;
++
++extern unsigned int ubifs_msg_flags;
++extern unsigned int ubifs_chk_flags;
++extern unsigned int ubifs_tst_flags;
++
++/* Dump functions */
++
++const char *dbg_ntype(int type);
++const char *dbg_cstate(int cmt_state);
++const char *dbg_get_key_dump(const struct ubifs_info *c,
++ const union ubifs_key *key);
++void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode);
++void dbg_dump_node(const struct ubifs_info *c, const void *node);
++void dbg_dump_budget_req(const struct ubifs_budget_req *req);
++void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
++void dbg_dump_budg(struct ubifs_info *c);
++void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
++void dbg_dump_lprops(struct ubifs_info *c);
++void dbg_dump_leb(const struct ubifs_info *c, int lnum);
++void dbg_dump_znode(const struct ubifs_info *c,
++ const struct ubifs_znode *znode);
++void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat);
++void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
++ struct ubifs_nnode *parent, int iip);
++void dbg_dump_tnc(struct ubifs_info *c);
++void dbg_dump_index(struct ubifs_info *c);
++
++/* Checking helper functions */
++
++typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
++ struct ubifs_zbranch *zbr, void *priv);
++typedef int (*dbg_znode_callback)(struct ubifs_info *c,
++ struct ubifs_znode *znode, void *priv);
++
++int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
++ dbg_znode_callback znode_cb, void *priv);
++
++/* Checking functions */
++
++int dbg_check_lprops(struct ubifs_info *c);
++
++int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot);
++int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot);
++
++int dbg_check_cats(struct ubifs_info *c);
++
++int dbg_check_ltab(struct ubifs_info *c);
++
++int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
++
++int dbg_check_tnc(struct ubifs_info *c, int extra);
++
++int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
++
++int dbg_check_filesystem(struct ubifs_info *c);
++
++void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
++ int add_pos);
++
++int dbg_check_lprops(struct ubifs_info *c);
++int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
++ int row, int col);
++
++/* Force the use of in-the-gaps method for testing */
++
++#define dbg_force_in_the_gaps_enabled \
++ (ubifs_tst_flags & UBIFS_TST_FORCE_IN_THE_GAPS)
++
++int dbg_force_in_the_gaps(void);
++
++/* Failure mode for recovery testing */
++
++#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)
++
++void dbg_failure_mode_registration(struct ubifs_info *c);
++void dbg_failure_mode_deregistration(struct ubifs_info *c);
++
++#ifndef UBIFS_DBG_PRESERVE_UBI
++
++#define ubi_leb_read dbg_leb_read
++#define ubi_leb_write dbg_leb_write
++#define ubi_leb_change dbg_leb_change
++#define ubi_leb_erase dbg_leb_erase
++#define ubi_leb_unmap dbg_leb_unmap
++#define ubi_is_mapped dbg_is_mapped
++
++#endif
++
++int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
++ int len, int check);
++int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
++ int offset, int len, int dtype);
++int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
++ int len, int dtype);
++int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum);
++int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum);
++int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum);
++
++static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf,
++ int offset, int len)
++{
++ return dbg_leb_read(desc, lnum, buf, offset, len, 0);
++}
++
++static inline int dbg_write(struct ubi_volume_desc *desc, int lnum,
++ const void *buf, int offset, int len)
++{
++ return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
++}
++
++static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
++ const void *buf, int len)
++{
++ return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
++}
++
++#else /* !CONFIG_UBIFS_FS_DEBUG */
++
++#define UBIFS_DBG(op)
++#define ubifs_assert(expr) ({})
++#define ubifs_assert_cmt_locked(c)
++#define dbg_dump_stack()
++#define dbg_err(fmt, ...) ({})
++#define dbg_msg(fmt, ...) ({})
++#define dbg_key(c, key, fmt, ...) ({})
++
++#define dbg_gen(fmt, ...) ({})
++#define dbg_jnl(fmt, ...) ({})
++#define dbg_tnc(fmt, ...) ({})
++#define dbg_lp(fmt, ...) ({})
++#define dbg_find(fmt, ...) ({})
++#define dbg_mnt(fmt, ...) ({})
++#define dbg_io(fmt, ...) ({})
++#define dbg_cmt(fmt, ...) ({})
++#define dbg_budg(fmt, ...) ({})
++#define dbg_log(fmt, ...) ({})
++#define dbg_gc(fmt, ...) ({})
++#define dbg_scan(fmt, ...) ({})
++#define dbg_rcvry(fmt, ...) ({})
++
++#define dbg_ntype(type) ""
++#define dbg_cstate(cmt_state) ""
++#define dbg_get_key_dump(c, key) ({})
++#define dbg_dump_inode(c, inode) ({})
++#define dbg_dump_node(c, node) ({})
++#define dbg_dump_budget_req(req) ({})
++#define dbg_dump_lstats(lst) ({})
++#define dbg_dump_budg(c) ({})
++#define dbg_dump_lprop(c, lp) ({})
++#define dbg_dump_lprops(c) ({})
++#define dbg_dump_leb(c, lnum) ({})
++#define dbg_dump_znode(c, znode) ({})
++#define dbg_dump_heap(c, heap, cat) ({})
++#define dbg_dump_pnode(c, pnode, parent, iip) ({})
++#define dbg_dump_tnc(c) ({})
++#define dbg_dump_index(c) ({})
++
++#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
++
++#define dbg_old_index_check_init(c, zroot) 0
++#define dbg_check_old_index(c, zroot) 0
++
++#define dbg_check_cats(c) 0
++
++#define dbg_check_ltab(c) 0
++
++#define dbg_check_dir_size(c, dir) 0
++
++#define dbg_check_tnc(c, x) 0
++
++#define dbg_check_idx_size(c, idx_size) 0
++#define dbg_check_filesystem(c) 0
++
++#define dbg_check_heap(c, heap, cat, add_pos) ({})
++
++#define dbg_check_lprops(c) 0
++#define dbg_check_lpt_nodes(c, cnode, row, col) 0
++
++#define dbg_force_in_the_gaps_enabled 0
++#define dbg_force_in_the_gaps() 0
++
++#define dbg_failure_mode 0
++#define dbg_failure_mode_registration(c) ({})
++#define dbg_failure_mode_deregistration(c) ({})
++
++#endif /* !CONFIG_UBIFS_FS_DEBUG */
++
++#endif /* !__UBIFS_DEBUG_H__ */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/dir.c avr32-2.6/fs/ubifs/dir.c
+--- linux-2.6.25.6/fs/ubifs/dir.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/dir.c 2008-06-12 15:09:45.364399968 +0200
+@@ -0,0 +1,1017 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ * Copyright (C) 2006, 2007 University of Szeged, Hungary
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ * Zoltan Sogor
++ */
++
++/*
++ * This file implements directory operations.
++ *
++ * All FS operations in this file allocate budget before writing anything to the
++ * media. If they fail to allocate it, the error is returned. The only
++ * exceptions are 'ubifs_unlink()' and 'ubifs_rmdir()' which keep working even
++ * if they unable to allocate the budget, because deletion %-ENOSPC failure is
++ * not what users are usually ready to get. UBIFS budgeting subsystem has some
++ * space reserved for these purposes.
++ *
++ * All operations in this file change the parent inode, e.g., 'ubifs_link()'
++ * changes ctime and nlink of the parent inode. The parent inode is written to
++ * the media straight away - it is not marked as dirty and there is no
++ * write-back for it. This was done to simplify file-system recovery which
++ * would otherwise be very difficult to do. So instead of marking the parent
++ * inode dirty, the operations mark it clean.
++ */
++
++#include "ubifs.h"
++
++/*
++ * Provide backing_dev_info in order to disable readahead. For UBIFS, I/O is
++ * not deferred, it is done immediately in readpage, which means the user would
++ * have to wait not just for their own I/O but the readahead I/O as well i.e.
++ * completely pointless.
++ */
++struct backing_dev_info ubifs_backing_dev_info = {
++ .ra_pages = 0, /* Set to zero to disable readahead */
++ .state = 0,
++ .capabilities = BDI_CAP_MAP_COPY,
++ .unplug_io_fn = default_unplug_io_fn,
++};
++
++/**
++ * inherit_flags - inherit flags of the parent inode.
++ * @dir: parent inode
++ * @mode: new inode mode flags
++ *
++ * This is a helper function for 'ubifs_new_inode()' which inherits flag of the
++ * parent directory inode @dir. UBIFS inodes inherit the following flags:
++ * o %UBIFS_COMPR_FL, which is useful to switch compression on/of on
++ * sub-directory basis;
++ * o %UBIFS_SYNC_FL - useful for the same reasons;
++ * o %UBIFS_DIRSYNC_FL - similar, but relevant only to directories.
++ *
++ * This function returns the inherited flags.
++ */
++static int inherit_flags(const struct inode *dir, int mode)
++{
++ int flags;
++ const struct ubifs_inode *ui = ubifs_inode(dir);
++
++ if (!S_ISDIR(dir->i_mode))
++ /*
++ * The parent is not a directory, which means that an extended
++ * attribute inode is being created. No flags.
++ */
++ return 0;
++
++ flags = ui->flags & (UBIFS_COMPR_FL | UBIFS_SYNC_FL | UBIFS_DIRSYNC_FL);
++ if (!S_ISDIR(mode))
++ /* The "DIRSYNC" flag only applies to directories */
++ flags &= ~UBIFS_DIRSYNC_FL;
++
++ return flags;
++}
++
++/**
++ * ubifs_new_inode - allocate new UBIFS inode object.
++ * @c: UBIFS file-system description object
++ * @dir: parent directory inode
++ * @mode: inode mode flags
++ *
++ * This function finds an unused inode number, allocates new inode and
++ * initializes it. Returns new inode in case of success and an error code in
++ * case of failure.
++ */
++struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
++ int mode)
++{
++ struct inode *inode;
++ struct ubifs_inode *ui;
++
++ inode = new_inode(c->vfs_sb);
++ if (!inode)
++ return ERR_PTR(-ENOMEM);
++
++ /*
++ * Set 'S_NOCMTIME' to prevent VFS form updating [mc]time of inodes and
++ * marking them dirty in file write path (see 'file_update_time()').
++ * UBIFS has to fully control "clean <-> dirty" transitions of inodes
++ * to make budgeting work.
++ */
++ inode->i_flags |= (S_NOCMTIME);
++
++ inode->i_uid = current->fsuid;
++ if (dir->i_mode & S_ISGID) {
++ inode->i_gid = dir->i_gid;
++ if (S_ISDIR(mode))
++ mode |= S_ISGID;
++ } else
++ inode->i_gid = current->fsgid;
++ inode->i_mode = mode;
++ inode->i_mtime = inode->i_atime = inode->i_ctime =
++ ubifs_current_time(inode);
++ inode->i_mapping->nrpages = 0;
++ /* Disable readahead */
++ inode->i_mapping->backing_dev_info = &ubifs_backing_dev_info;
++
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ inode->i_mapping->a_ops = &ubifs_file_address_operations;
++ inode->i_op = &ubifs_file_inode_operations;
++ inode->i_fop = &ubifs_file_operations;
++ break;
++ case S_IFDIR:
++ inode->i_op = &ubifs_dir_inode_operations;
++ inode->i_fop = &ubifs_dir_operations;
++ inode->i_size = UBIFS_INO_NODE_SZ;
++ break;
++ case S_IFLNK:
++ inode->i_op = &ubifs_symlink_inode_operations;
++ break;
++ case S_IFSOCK:
++ case S_IFIFO:
++ case S_IFBLK:
++ case S_IFCHR:
++ inode->i_op = &ubifs_file_inode_operations;
++ break;
++ default:
++ BUG();
++ }
++
++ ui = ubifs_inode(inode);
++ ui->flags = inherit_flags(dir, mode);
++ ubifs_set_inode_flags(inode);
++
++ if (S_ISREG(mode))
++ ui->compr_type = c->default_compr;
++ else
++ ui->compr_type = UBIFS_COMPR_NONE;
++
++ spin_lock(&c->cnt_lock);
++ /* Inode number overflow is currently not supported */
++ if (c->highest_inum >= INUM_WARN_WATERMARK) {
++ if (c->highest_inum >= INUM_WATERMARK) {
++ spin_unlock(&c->cnt_lock);
++ ubifs_err("out of inode numbers");
++ make_bad_inode(inode);
++ iput(inode);
++ return ERR_PTR(-EINVAL);
++ }
++ ubifs_warn("running out of inode numbers (current %lu, max %d)",
++ c->highest_inum, INUM_WATERMARK);
++ }
++
++ inode->i_ino = ++c->highest_inum;
++ inode->i_generation = ++c->vfs_gen;
++ /*
++ * The creation sequence number remains with this inode for its
++ * lifetime. All nodes for this inode have a greater sequence number,
++ * and so it is possible to distinguish obsolete nodes belonging to a
++ * previous incarnation of the same inode number - for example, for the
++ * purpose of rebuilding the index.
++ */
++ ui->creat_sqnum = ++c->max_sqnum;
++ spin_unlock(&c->cnt_lock);
++
++ return inode;
++}
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
++{
++ if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
++ return 0;
++ if (le16_to_cpu(dent->nlen) != nm->len)
++ return -EINVAL;
++ if (memcmp(dent->name, nm->name, nm->len))
++ return -EINVAL;
++ return 0;
++}
++
++#else
++
++#define dbg_check_name(dent, nm) 0
++
++#endif
++
++static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ int err;
++ union ubifs_key key;
++ struct inode *inode = NULL;
++ struct ubifs_dent_node *dent;
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++
++ dbg_gen("'%.*s' in dir ino %lu",
++ dentry->d_name.len, dentry->d_name.name, dir->i_ino);
++
++ if (dentry->d_name.len > UBIFS_MAX_NLEN)
++ return ERR_PTR(-ENAMETOOLONG);
++
++ dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
++ if (!dent)
++ return ERR_PTR(-ENOMEM);
++
++ dent_key_init(c, &key, dir->i_ino, &dentry->d_name);
++
++ err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
++ if (err) {
++ if (err == -ENOENT) {
++ dbg_gen("not found");
++ goto done;
++ }
++ goto out;
++ }
++
++ if (dbg_check_name(dent, &dentry->d_name)) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
++ if (IS_ERR(inode)) {
++ /*
++ * This should not happen. Probably the file-system needs
++ * checking.
++ */
++ err = PTR_ERR(inode);
++ ubifs_err("dead directory entry '%.*s', error %d",
++ dentry->d_name.len, dentry->d_name.name, err);
++ ubifs_ro_mode(c, err);
++ goto out;
++ }
++
++done:
++ kfree(dent);
++ /*
++ * Note, d_splice_alias() would be required instead if we supported
++ * NFS.
++ */
++ d_add(dentry, inode);
++ return NULL;
++
++out:
++ kfree(dent);
++ return ERR_PTR(err);
++}
++
++static int ubifs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ struct inode *inode;
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
++ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
++
++ dbg_gen("dent '%.*s', mode %#x in dir ino %lu",
++ dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);
++
++ inode = ubifs_new_inode(c, dir, mode);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++
++ err = ubifs_budget_inode_op(c, dir, &req);
++ if (err)
++ goto out;
++
++ dir->i_size += sz_change;
++
++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
++ IS_DIRSYNC(dir), 0);
++ if (err)
++ goto out_budg;
++
++ insert_inode_hash(inode);
++ d_instantiate(dentry, inode);
++ ubifs_release_ino_clean(c, dir, &req);
++ return 0;
++
++out_budg:
++ dir->i_size -= sz_change;
++ ubifs_cancel_ino_op(c, dir, &req);
++ ubifs_err("cannot create regular file, error %d", err);
++out:
++ make_bad_inode(inode);
++ iput(inode);
++ return err;
++}
++
++/**
++ * vfs_dent_type - get VFS directory entry type.
++ * @type: UBIFS directory entry type
++ *
++ * This function converts UBIFS directory entry type into VFS directory entry
++ * type.
++ */
++static unsigned int vfs_dent_type(uint8_t type)
++{
++ switch (type) {
++ case UBIFS_ITYPE_REG:
++ return DT_REG;
++ case UBIFS_ITYPE_DIR:
++ return DT_DIR;
++ case UBIFS_ITYPE_LNK:
++ return DT_LNK;
++ case UBIFS_ITYPE_BLK:
++ return DT_BLK;
++ case UBIFS_ITYPE_CHR:
++ return DT_CHR;
++ case UBIFS_ITYPE_FIFO:
++ return DT_FIFO;
++ case UBIFS_ITYPE_SOCK:
++ return DT_SOCK;
++ default:
++ BUG();
++ }
++ return 0;
++}
++
++/*
++ * The classical Unix view for directory is that it is a linear array of
++ * (name, inode number) entries. Linux/VFS assumes this model as well.
++ * Particularly, 'readdir()' call wants us to return a directory entry offset
++ * which later may be used to continue 'readdir()'ing the directory or to
++ * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this
++ * model because directory entries are identified by keys, which may collide.
++ *
++ * UBIFS uses directory entry hash value for directory offsets, so
++ * 'seekdir()'/'telldir()' may not always work because of possible key
++ * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work
++ * properly by means of saving full directory entry name in the private field
++ * of the file description object.
++ *
++ * This means that UBIFS cannot support NFS which requires full
++ * 'seekdir()'/'telldir()' support.
++ */
++static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err, over = 0;
++ struct qstr nm;
++ union ubifs_key key;
++ struct ubifs_dent_node *dent;
++ struct inode *dir = file->f_path.dentry->d_inode;
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++
++ dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
++
++ if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
++ /*
++ * The directory was seek'ed to a senseless position or there
++ * are no more entries.
++ */
++ return 0;
++
++ /* File positions 0 and 1 correspond to "." and ".." */
++ if (file->f_pos == 0) {
++ ubifs_assert(!file->private_data);
++ over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR);
++ if (over)
++ return 0;
++ file->f_pos = 1;
++ }
++
++ if (file->f_pos == 1) {
++ ubifs_assert(!file->private_data);
++ over = filldir(dirent, "..", 2, 1,
++ parent_ino(file->f_path.dentry), DT_DIR);
++ if (over)
++ return 0;
++
++ /* Find the first entry in TNC and save it */
++ lowest_dent_key(c, &key, dir->i_ino);
++ nm.name = NULL;
++ dent = ubifs_tnc_next_ent(c, &key, &nm);
++ if (IS_ERR(dent)) {
++ err = PTR_ERR(dent);
++ goto out;
++ }
++
++ file->f_pos = key_hash_flash(c, &dent->key);
++ file->private_data = dent;
++ }
++
++ dent = file->private_data;
++ if (!dent) {
++ /*
++ * The directory was seek'ed to and is now readdir'ed.
++ * Find the entry corresponding to @file->f_pos or the
++ * closest one.
++ */
++ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
++ nm.name = NULL;
++ dent = ubifs_tnc_next_ent(c, &key, &nm);
++ if (IS_ERR(dent)) {
++ err = PTR_ERR(dent);
++ goto out;
++ }
++ file->f_pos = key_hash_flash(c, &dent->key);
++ file->private_data = dent;
++ }
++
++ while (1) {
++ dbg_gen("feed '%s', ino %llu, new f_pos %#x",
++ dent->name, le64_to_cpu(dent->inum),
++ key_hash_flash(c, &dent->key));
++ ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum);
++
++ nm.len = le16_to_cpu(dent->nlen);
++ over = filldir(dirent, dent->name, nm.len, file->f_pos,
++ le64_to_cpu(dent->inum),
++ vfs_dent_type(dent->type));
++ if (over)
++ return 0;
++
++ /* Switch to the next entry */
++ key_read(c, &dent->key, &key);
++ nm.name = dent->name;
++ dent = ubifs_tnc_next_ent(c, &key, &nm);
++ if (IS_ERR(dent)) {
++ err = PTR_ERR(dent);
++ goto out;
++ }
++
++ kfree(file->private_data);
++ file->f_pos = key_hash_flash(c, &dent->key);
++ file->private_data = dent;
++ cond_resched();
++ }
++
++out:
++ if (err != -ENOENT) {
++ ubifs_err("cannot find next direntry, error %d", err);
++ return err;
++ }
++
++ kfree(file->private_data);
++ file->private_data = NULL;
++ file->f_pos = 2;
++ return 0;
++}
++
++/* If a directory is seeked, we have to free saved readdir() state */
++loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin)
++{
++ kfree(file->private_data);
++ file->private_data = NULL;
++ return generic_file_llseek(file, offset, origin);
++}
++
++/* Free saved readdir() state when the directory is closed */
++static int ubifs_dir_release(struct inode *dir, struct file *file)
++{
++ kfree(file->private_data);
++ file->private_data = NULL;
++ return 0;
++}
++
++static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ struct inode *inode = old_dentry->d_inode;
++ struct ubifs_inode *ui = ubifs_inode(inode);
++ struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 1,
++ .dirtied_ino_d = ui->data_len };
++ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
++
++ dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",
++ dentry->d_name.len, dentry->d_name.name, inode->i_ino,
++ inode->i_nlink, dir->i_ino);
++
++ err = ubifs_budget_inode_op(c, dir, &req);
++ if (err)
++ return err;
++
++ inc_nlink(inode);
++ dir->i_size += sz_change;
++ inode->i_ctime = dir->i_mtime = dir->i_ctime =
++ ubifs_current_time(inode);
++
++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
++ IS_DIRSYNC(dir), 0);
++ if (err)
++ goto out_budg;
++
++ atomic_inc(&inode->i_count);
++ d_instantiate(dentry, inode);
++ ubifs_release_ino_clean(c, dir, &req);
++ return 0;
++
++out_budg:
++ dir->i_size -= sz_change;
++ ubifs_cancel_ino_op(c, dir, &req);
++ drop_nlink(inode);
++ iput(inode);
++ return err;
++}
++
++static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ struct inode *inode = dentry->d_inode;
++ struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 1 };
++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
++ int err, budgeted = 1;
++
++ dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",
++ dentry->d_name.len, dentry->d_name.name, inode->i_ino,
++ inode->i_nlink, dir->i_ino);
++
++ err = ubifs_budget_inode_op(c, dir, &req);
++ if (err) {
++ if (err != -ENOSPC)
++ return err;
++ err = 0;
++ budgeted = 0;
++ }
++
++ dir->i_size -= sz_change;
++ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir);
++
++ inode->i_ctime = dir->i_ctime;
++ drop_nlink(inode);
++
++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1,
++ IS_DIRSYNC(dir), 0);
++ if (err)
++ goto out_budg;
++
++ if (budgeted)
++ ubifs_release_ino_clean(c, dir, &req);
++
++ return 0;
++
++out_budg:
++ dir->i_size += sz_change;
++ inc_nlink(inode);
++ if (budgeted)
++ ubifs_cancel_ino_op(c, dir, &req);
++ return err;
++}
++
++/**
++ * check_dir_empty - check if a directory is empty or not.
++ * @c: UBIFS file-system description object
++ * @dir: VFS inode object of the directory to check
++ *
++ * This function checks if directory @dir is empty. Returns zero if the
++ * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes
++ * in case of of errors.
++ */
++static int check_dir_empty(struct ubifs_info *c, struct inode *dir)
++{
++ struct qstr nm = { .name = NULL };
++ struct ubifs_dent_node *dent;
++ union ubifs_key key;
++ int err;
++
++ lowest_dent_key(c, &key, dir->i_ino);
++ dent = ubifs_tnc_next_ent(c, &key, &nm);
++ if (IS_ERR(dent)) {
++ err = PTR_ERR(dent);
++ if (err == -ENOENT)
++ err = 0;
++ } else {
++ kfree(dent);
++ err = -ENOTEMPTY;
++ }
++
++ return err;
++}
++
++static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ struct inode *inode = dentry->d_inode;
++ struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 1 };
++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
++ int err, budgeted = 0;
++
++ dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,
++ dentry->d_name.name, inode->i_ino, dir->i_ino);
++
++ err = check_dir_empty(c, dentry->d_inode);
++ if (err)
++ return err;
++
++ budgeted = 1;
++ err = ubifs_budget_inode_op(c, dir, &req);
++ if (err) {
++ if (err != -ENOSPC)
++ return err;
++ budgeted = 0;
++ }
++
++ dir->i_size -= sz_change;
++ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir);
++ drop_nlink(dir);
++
++ inode->i_size = 0;
++ inode->i_ctime = dir->i_ctime;
++ clear_nlink(inode);
++
++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1,
++ IS_DIRSYNC(dir), 0);
++ if (err)
++ goto out_budg;
++
++ if (budgeted)
++ ubifs_release_ino_clean(c, dir, &req);
++
++ return 0;
++
++out_budg:
++ dir->i_size += sz_change;
++ inc_nlink(dir);
++ inc_nlink(inode);
++ inc_nlink(inode);
++ if (budgeted)
++ ubifs_cancel_ino_op(c, dir, &req);
++ return err;
++}
++
++static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ struct inode *inode;
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
++ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
++
++ dbg_gen("dent '%.*s', mode %#x in dir ino %lu",
++ dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);
++
++ err = ubifs_budget_inode_op(c, dir, &req);
++ if (err)
++ return err;
++
++ inode = ubifs_new_inode(c, dir, S_IFDIR | mode);
++ if (IS_ERR(inode)) {
++ err = PTR_ERR(inode);
++ goto out_budg;
++ }
++
++ insert_inode_hash(inode);
++ inc_nlink(inode);
++
++ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir);
++ dir->i_size += sz_change;
++ inc_nlink(dir);
++
++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
++ IS_DIRSYNC(dir), 0);
++ if (err) {
++ ubifs_err("cannot create directory, error %d", err);
++ goto out_inode;
++ }
++
++ d_instantiate(dentry, inode);
++ ubifs_release_ino_clean(c, dir, &req);
++ return 0;
++
++out_inode:
++ dir->i_size -= sz_change;
++ drop_nlink(dir);
++ make_bad_inode(inode);
++ iput(inode);
++out_budg:
++ ubifs_cancel_ino_op(c, dir, &req);
++ return err;
++}
++
++static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
++ int mode, dev_t rdev)
++{
++ struct inode *inode;
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
++ union ubifs_dev_desc *dev = NULL;
++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
++ int err, devlen = 0;
++
++ dbg_gen("dent '%.*s' in dir ino %lu",
++ dentry->d_name.len, dentry->d_name.name, dir->i_ino);
++
++ if (!new_valid_dev(rdev))
++ return -EINVAL;
++
++ if (S_ISBLK(mode) || S_ISCHR(mode)) {
++ dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
++ if (!dev)
++ return -ENOMEM;
++ devlen = ubifs_encode_dev(dev, rdev);
++ }
++
++ err = ubifs_budget_inode_op(c, dir, &req);
++ if (err) {
++ kfree(dev);
++ return err;
++ }
++
++ inode = ubifs_new_inode(c, dir, mode);
++ if (IS_ERR(inode)) {
++ kfree(dev);
++ err = PTR_ERR(inode);
++ goto out_budg;
++ }
++
++ init_special_inode(inode, inode->i_mode, rdev);
++
++ inode->i_size = devlen;
++ ubifs_inode(inode)->data = dev;
++ ubifs_inode(inode)->data_len = devlen;
++
++ dir->i_size += sz_change;
++
++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
++ IS_DIRSYNC(dir), 0);
++ if (err)
++ goto out_inode;
++
++ insert_inode_hash(inode);
++ d_instantiate(dentry, inode);
++ ubifs_release_ino_clean(c, dir, &req);
++ return 0;
++
++out_inode:
++ dir->i_size -= sz_change;
++ make_bad_inode(inode);
++ iput(inode);
++out_budg:
++ ubifs_cancel_ino_op(c, dir, &req);
++ return err;
++}
++
++static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
++ const char *symname)
++{
++ struct inode *inode;
++ struct ubifs_inode *ui;
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ int err, len = strlen(symname);
++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
++ .new_ino_d = len };
++
++ dbg_gen("dent '%.*s', target '%s' in dir ino %lu", dentry->d_name.len,
++ dentry->d_name.name, symname, dir->i_ino);
++
++ if (len > UBIFS_MAX_INO_DATA)
++ return -ENAMETOOLONG;
++
++ err = ubifs_budget_inode_op(c, dir, &req);
++ if (err)
++ return err;
++
++ inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO);
++ if (IS_ERR(inode)) {
++ err = PTR_ERR(inode);
++ goto out_budg;
++ }
++
++ ui = ubifs_inode(inode);
++ ui->data = kmalloc(len + 1, GFP_NOFS);
++ if (!ui->data) {
++ err = -ENOMEM;
++ goto out_inode;
++ }
++
++ memcpy(ui->data, symname, len);
++ ((char *)ui->data)[len] = '\0';
++ /*
++ * The terminating zero byte is not written to the flash media and it
++ * is put just to make later in-memory string processing simpler. Thus,
++ * data length is @len, not @len + %1.
++ */
++ ui->data_len = len;
++ inode->i_size = len;
++
++ dir->i_size += sz_change;
++
++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
++ IS_DIRSYNC(dir), 0);
++ if (err)
++ goto out_dir;
++
++ insert_inode_hash(inode);
++ d_instantiate(dentry, inode);
++ ubifs_release_ino_clean(c, dir, &req);
++ return 0;
++
++out_dir:
++ dir->i_size -= sz_change;
++out_inode:
++ make_bad_inode(inode);
++ iput(inode);
++out_budg:
++ ubifs_cancel_ino_op(c, dir, &req);
++ return err;
++}
++
++static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry)
++{
++ struct ubifs_info *c = old_dir->i_sb->s_fs_info;
++ struct inode *old_inode = old_dentry->d_inode;
++ struct inode *new_inode = new_dentry->d_inode;
++ int err, move = (new_dir != old_dir);
++ int is_dir = S_ISDIR(old_inode->i_mode);
++ int unlink = !!new_inode;
++ int dirsync = (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir));
++ int new_sz = CALC_DENT_SIZE(new_dentry->d_name.len);
++ int old_sz = CALC_DENT_SIZE(old_dentry->d_name.len);
++ struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1 };
++ struct timespec time = ubifs_current_time(old_dir);
++
++ dbg_gen("dent '%.*s' ino %lu in dir ino %lu to dent '%.*s' in "
++ "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name,
++ old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,
++ new_dentry->d_name.name, new_dir->i_ino);
++
++ if (unlink && is_dir) {
++ err = check_dir_empty(c, new_inode);
++ if (err)
++ return err;
++ }
++
++ if (move) {
++ req.dirtied_ino = 1;
++ if (unlink) {
++ req.dirtied_ino += 2;
++ req.dirtied_ino_d = ubifs_inode(new_inode)->data_len;
++ }
++ }
++
++ /*
++ * Note, rename may write @new_dir inode if the directory entry is
++ * moved there. And if the @new_dir is dirty, we do not bother to make
++ * it clean. It could be done, but requires extra coding which does not
++ * seem to be really worth it.
++ */
++ err = ubifs_budget_inode_op(c, old_dir, &req);
++ if (err)
++ return err;
++
++ /*
++ * Like most other Unix systems, set the ctime for inodes on a
++ * rename.
++ */
++ old_inode->i_ctime = time;
++
++ /*
++ * If we moved a directory to another parent directory, decrement
++ * 'i_nlink' of the old parent. Also, update 'i_size' of the old parent
++ * as well as its [mc]time.
++ */
++ if (is_dir && move)
++ drop_nlink(old_dir);
++ old_dir->i_size -= old_sz;
++ old_dir->i_mtime = old_dir->i_ctime = time;
++ new_dir->i_mtime = new_dir->i_ctime = time;
++
++ /*
++ * If we moved a directory object to new directory, parent's 'i_nlink'
++ * should be adjusted.
++ */
++ if (move && is_dir)
++ inc_nlink(new_dir);
++
++ /*
++ * And finally, if we unlinked a direntry which happened to have the
++ * same name as the moved direntry, we have to decrement 'i_nlink' of
++ * the unlinked inode and change its ctime.
++ */
++ if (unlink) {
++ /*
++ * Directories cannot have hard-links, so if this is a
++ * directory, decrement its 'i_nlink' twice because an empty
++ * directory has 'i_nlink' 2.
++ */
++ if (is_dir)
++ drop_nlink(new_inode);
++ new_inode->i_ctime = time;
++ drop_nlink(new_inode);
++ } else
++ new_dir->i_size += new_sz;
++
++ err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry,
++ dirsync);
++ if (err)
++ goto out_inode;
++
++ ubifs_release_ino_clean(c, old_dir, &req);
++ return 0;
++
++out_inode:
++ if (unlink) {
++ if (is_dir)
++ inc_nlink(new_inode);
++ inc_nlink(new_inode);
++ } else
++ new_dir->i_size -= new_sz;
++ old_dir->i_size += old_sz;
++ if (is_dir && move) {
++ drop_nlink(new_dir);
++ inc_nlink(old_dir);
++ }
++ ubifs_cancel_ino_op(c, old_dir, &req);
++ return err;
++}
++
++int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
++ struct kstat *stat)
++{
++ struct inode *inode = dentry->d_inode;
++ loff_t size;
++
++ stat->dev = inode->i_sb->s_dev;
++ stat->ino = inode->i_ino;
++ stat->mode = inode->i_mode;
++ stat->nlink = inode->i_nlink;
++ stat->uid = inode->i_uid;
++ stat->gid = inode->i_gid;
++ stat->rdev = inode->i_rdev;
++ stat->atime = inode->i_atime;
++ stat->mtime = inode->i_mtime;
++ stat->ctime = inode->i_ctime;
++ stat->blksize = UBIFS_BLOCK_SIZE;
++ stat->size = i_size_read(inode);
++
++ spin_lock(&inode->i_lock);
++ size = ubifs_inode(inode)->xattr_size;
++ spin_unlock(&inode->i_lock);
++
++ /*
++ * Unfortunately, the 'stat()' system call was designed for block
++ * device based file systems, and it is not appropriate for UBIFS,
++ * because UBIFS does not have notion of "block". For example, it is
++ * difficult to tell how many block a directory takes - it actually
++ * takes less than 300 bytes, but we have to round it to block size,
++ * which introduces large mistake. This makes utilities like 'du' to
++ * report completely senseless numbers. This is the reason why UBIFS
++ * goes the same way as JFFS2 - it reports zero blocks for everything
++ * but regular files, which makes more sense than reporting completely
++ * wrong sizes.
++ */
++ if (S_ISREG(inode->i_mode))
++ size += stat->size;
++
++ size = ALIGN(size, UBIFS_BLOCK_SIZE);
++ /*
++ * Note, user-space expects 512-byte blocks count irrespectively of what
++ * was reported in @stat->size.
++ */
++ stat->blocks = size >> 9;
++
++ return 0;
++}
++
++struct inode_operations ubifs_dir_inode_operations = {
++ .lookup = ubifs_lookup,
++ .create = ubifs_create,
++ .link = ubifs_link,
++ .symlink = ubifs_symlink,
++ .unlink = ubifs_unlink,
++ .mkdir = ubifs_mkdir,
++ .rmdir = ubifs_rmdir,
++ .mknod = ubifs_mknod,
++ .rename = ubifs_rename,
++ .setattr = ubifs_setattr,
++ .getattr = ubifs_getattr,
++#ifdef CONFIG_UBIFS_FS_XATTR
++ .setxattr = ubifs_setxattr,
++ .getxattr = ubifs_getxattr,
++ .listxattr = ubifs_listxattr,
++ .removexattr = ubifs_removexattr,
++#endif
++};
++
++struct file_operations ubifs_dir_operations = {
++ .llseek = ubifs_dir_llseek,
++ .release = ubifs_dir_release,
++ .read = generic_read_dir,
++ .readdir = ubifs_readdir,
++ .fsync = ubifs_fsync,
++ .unlocked_ioctl = ubifs_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = ubifs_compat_ioctl,
++#endif
++};
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/file.c avr32-2.6/fs/ubifs/file.c
+--- linux-2.6.25.6/fs/ubifs/file.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/file.c 2008-06-12 15:09:45.364399968 +0200
+@@ -0,0 +1,960 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/*
++ * This file implements VFS file and inode operations of regular files, device
++ * nodes and symlinks as well as address space operations.
++ *
++ * UBIFS uses 2 page flags: PG_private and PG_checked. PG_private is set if the
++ * page is dirty and is used for budgeting purposes - dirty pages should not be
++ * budgeted. The PG_checked flag is set if full budgeting is required for the
++ * page e.g., when it corresponds to a file hole or it is just beyond the file
++ * size. The budgeting is done in 'ubifs_write_begin()', because it is OK to
++ * fail in this function, and the budget is released in 'ubifs_write_end()'. So
++ * the PG_private and PG_checked flags carry the information about how the page
++ * was budgeted, to make it possible to release the budget properly.
++ *
++ * A thing to keep in mind: inode's 'i_mutex' is locked in most VFS operations
++ * we implement. However, this is not true for '->writepage()', which might be
++ * called with 'i_mutex' unlocked. For example, when pdflush is performing
++ * write-back, it calls 'writepage()' with unlocked 'i_mutex', although the
++ * inode has 'I_LOCK' flag in this case. At "normal" work-paths 'i_mutex' is
++ * locked in '->writepage', e.g. in "sys_write -> alloc_pages -> direct reclaim
++ * path'. So, in '->writepage()' we are only guaranteed that the page is
++ * locked.
++ *
++ * Similarly, 'i_mutex' does not have to be locked in readpage(), e.g.,
++ * readahead path does not have it locked ("sys_read -> generic_file_aio_read
++ * -> ondemand_readahead -> readpage"). In case of readahead, 'I_LOCK' flag is
++ * not set as well.
++ *
++ * This, for example means that there might be 2 concurrent '->writepage()'
++ * calls for the same inode, but different inode dirty pages.
++ */
++
++#include "ubifs.h"
++#include <linux/mount.h>
++
++static int read_block(struct inode *inode, void *addr, unsigned int block,
++ struct ubifs_data_node *dn)
++{
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ int err, len, out_len;
++ union ubifs_key key;
++ unsigned int dlen;
++
++ data_key_init(c, &key, inode->i_ino, block);
++ err = ubifs_tnc_lookup(c, &key, dn);
++ if (err) {
++ if (err == -ENOENT)
++ /* Not found, so it must be a hole */
++ memset(addr, 0, UBIFS_BLOCK_SIZE);
++ return err;
++ }
++
++ ubifs_assert(dn->ch.sqnum > ubifs_inode(inode)->creat_sqnum);
++
++ len = le32_to_cpu(dn->size);
++ if (len <= 0 || len > UBIFS_BLOCK_SIZE)
++ goto dump;
++
++ dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
++ out_len = UBIFS_BLOCK_SIZE;
++ err = ubifs_decompress(&dn->data, dlen, addr, &out_len,
++ le16_to_cpu(dn->compr_type));
++ if (err || len != out_len)
++ goto dump;
++
++ /*
++ * Data length can be less than a full block, even for blocks that are
++ * not the last in the file (e.g., as a result of making a hole and
++ * appending data). Ensure that the remainder is zeroed out.
++ */
++ if (len < UBIFS_BLOCK_SIZE)
++ memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
++
++ return 0;
++
++dump:
++ ubifs_err("bad data node (block %u, inode %lu)",
++ block, inode->i_ino);
++ dbg_dump_node(c, dn);
++ return -EINVAL;
++}
++
++static int do_readpage(struct page *page)
++{
++ void *addr;
++ int err = 0, i;
++ unsigned int block, beyond;
++ struct ubifs_data_node *dn;
++ struct inode *inode = page->mapping->host;
++ loff_t i_size = i_size_read(inode);
++
++ dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
++ inode->i_ino, page->index, i_size, page->flags);
++ ubifs_assert(!PageChecked(page));
++ ubifs_assert(!PagePrivate(page));
++
++ addr = kmap(page);
++
++ block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
++ beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
++ if (block >= beyond) {
++ /* Reading beyond inode */
++ SetPageChecked(page);
++ memset(addr, 0, PAGE_CACHE_SIZE);
++ goto out;
++ }
++
++ dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
++ if (!dn) {
++ err = -ENOMEM;
++ goto error;
++ }
++
++ i = 0;
++ while (1) {
++ int ret;
++
++ if (block >= beyond) {
++ /* Reading beyond inode */
++ err = -ENOENT;
++ memset(addr, 0, UBIFS_BLOCK_SIZE);
++ } else {
++ ret = read_block(inode, addr, block, dn);
++ if (ret) {
++ err = ret;
++ if (err != -ENOENT)
++ break;
++ }
++ }
++ if (++i >= UBIFS_BLOCKS_PER_PAGE)
++ break;
++ block += 1;
++ addr += UBIFS_BLOCK_SIZE;
++ }
++ if (err) {
++ if (err == -ENOENT) {
++ /* Not found, so it must be a hole */
++ SetPageChecked(page);
++ dbg_gen("hole");
++ goto out_free;
++ }
++ ubifs_err("cannot read page %lu of inode %lu, error %d",
++ page->index, inode->i_ino, err);
++ goto error;
++ }
++
++out_free:
++ kfree(dn);
++out:
++ SetPageUptodate(page);
++ ClearPageError(page);
++ flush_dcache_page(page);
++ kunmap(page);
++ return 0;
++
++error:
++ kfree(dn);
++ ClearPageUptodate(page);
++ SetPageError(page);
++ flush_dcache_page(page);
++ kunmap(page);
++ return err;
++}
++
++static int ubifs_write_begin(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned flags,
++ struct page **pagep, void **fsdata)
++{
++ struct inode *inode = mapping->host;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
++ struct ubifs_budget_req req = { .new_page = 1 };
++ loff_t i_size = i_size_read(inode);
++ int uninitialized_var(err);
++ struct page *page;
++
++ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
++
++ if (unlikely(c->ro_media))
++ return -EROFS;
++
++ /*
++ * We are about to have a page of data written and we have to budget for
++ * this. The very important point here is that we have to budget before
++ * locking the page, because budgeting may force write-back, which
++ * would wait on locked pages and deadlock if we had the page locked.
++ *
++ * At this point we do not know anything about the page of data we are
++ * going to change, so assume the biggest budget (i.e., assume that
++ * this is a new page of data and it does not override an older page of
++ * data in the inode). Later the budget will be amended if this is not
++ * true.
++ */
++ if (pos + len > i_size)
++ /*
++ * We are writing beyond the file which means we are going to
++ * change inode size and make the inode dirty. And in turn,
++ * this means we have to budget for making the inode dirty.
++ *
++ * Note, if the inode is already dirty,
++ * 'ubifs_budget_inode_op()' will not allocate any budget,
++ * but will just lock the @budg_mutex of the inode to prevent
++ * it from becoming clean before we have changed its size,
++ * which is going to happen in 'ubifs_write_end()'.
++ */
++ err = ubifs_budget_inode_op(c, inode, &req);
++ else
++ /*
++ * The inode is not going to be marked as dirty by this write
++ * operation, do not budget for this.
++ */
++ err = ubifs_budget_space(c, &req);
++ if (unlikely(err))
++ return err;
++
++ page = __grab_cache_page(mapping, index);
++ if (unlikely(!page)) {
++ err = -ENOMEM;
++ goto out_release;
++ }
++
++ if (!PageUptodate(page)) {
++ /*
++ * The page is not loaded from the flash and has to be loaded
++ * unless we are writing all of it.
++ */
++ if (!(pos & PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
++ /*
++ * Set the PG_checked flag to make the further code
++ * assume the page is new.
++ */
++ SetPageChecked(page);
++ else {
++ err = do_readpage(page);
++ if (err)
++ goto out_unlock;
++ }
++
++ SetPageUptodate(page);
++ ClearPageError(page);
++ }
++
++ if (PagePrivate(page))
++ /*
++ * The page is dirty, which means it was budgeted twice:
++ * o first time the budget was allocated by the task which
++ * made the page dirty and set the PG_private flag;
++ * o and then we budgeted for it for the second time at the
++ * very beginning of this function.
++ *
++ * So what we have to do is to release the page budget we
++ * allocated.
++ *
++ * Note, the page write operation may change the inode length,
++ * which makes it dirty and means the budget should be
++ * allocated. This was done above in the "pos + len > i_size"
++ * case. If this was done, we do not free the the inode budget,
++ * because we cannot as we are really going to mark it dirty in
++ * the 'ubifs_write_end()' function.
++ */
++ ubifs_release_new_page_budget(c);
++ else if (!PageChecked(page))
++ /*
++ * The page is not new, which means we are changing the page
++ * which already exists on the media. This means that changing
++ * the page does not make the amount of indexing information
++ * larger, and this part of the budget which we have already
++ * acquired may be released.
++ */
++ ubifs_convert_page_budget(c);
++
++ *pagep = page;
++ return 0;
++
++out_unlock:
++ unlock_page(page);
++ page_cache_release(page);
++out_release:
++ if (pos + len > i_size)
++ ubifs_cancel_ino_op(c, inode, &req);
++ else
++ ubifs_release_budget(c, &req);
++ return err;
++}
++
++static int ubifs_write_end(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned copied,
++ struct page *page, void *fsdata)
++{
++ struct inode *inode = mapping->host;
++ struct ubifs_inode *ui = ubifs_inode(inode);
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ loff_t i_size = i_size_read(inode);
++
++ dbg_gen("ino %lu, pos %llu, pg %lu, len %u, copied %d, i_size %lld",
++ inode->i_ino, pos, page->index, len, copied, i_size);
++
++ if (unlikely(copied < len && len == PAGE_CACHE_SIZE)) {
++ /*
++ * VFS copied less data to the page that it intended and
++ * declared in its '->write_begin()' call via the @len
++ * argument. If the page was not up-to-date, and @len was
++ * @PAGE_CACHE_SIZE, the 'ubifs_write_begin()' function did
++ * not load it from the media (for optimization reasons). This
++ * means that part of the page contains garbage. So read the
++ * page now.
++ */
++ dbg_gen("copied %d instead of %d, read page and repeat",
++ copied, len);
++
++ if (pos + len > i_size)
++ /* See a comment below about this hacky unlock */
++ mutex_unlock(&ui->budg_mutex);
++
++ copied = do_readpage(page);
++
++ /*
++ * Return 0 to force VFS to repeat the whole operation, or the
++ * error code if 'do_readpage()' failed.
++ */
++ goto out;
++ }
++
++ if (!PagePrivate(page)) {
++ SetPagePrivate(page);
++ atomic_long_inc(&c->dirty_pg_cnt);
++ __set_page_dirty_nobuffers(page);
++ }
++
++ if (pos + len > i_size) {
++ i_size_write(inode, pos + len);
++
++ /*
++ * Note, we do not set @I_DIRTY_PAGES (which means that the
++ * inode has dirty pages), this has been done in
++ * '__set_page_dirty_nobuffers()'.
++ */
++ mark_inode_dirty_sync(inode);
++
++ /*
++ * The inode has been marked dirty, unlock it. This is a bit
++ * hacky because normally we would have to call
++ * 'ubifs_release_ino_dirty()'. But we know there is nothing
++ * to release because page's budget will be released in
++ * 'ubifs_write_page()' and inode's budget will be released in
++ * 'ubifs_write_inode()', so just unlock the inode here for
++ * optimization.
++ */
++ mutex_unlock(&ui->budg_mutex);
++ }
++
++out:
++ unlock_page(page);
++ page_cache_release(page);
++ return copied;
++}
++
++static int ubifs_readpage(struct file *file, struct page *page)
++{
++ do_readpage(page);
++ unlock_page(page);
++ return 0;
++}
++
++/**
++ * release_existing_page_budget - release budget of an existing page.
++ * @c: UBIFS file-system description object
++ *
++ * This is a helper function which releases budget corresponding to the budget
++ * of changing one one page of data which already exists on the flash media.
++ *
++ * This function was not moved to "budget.c" because there is only one user.
++ */
++static void release_existing_page_budget(struct ubifs_info *c)
++{
++ struct ubifs_budget_req req = { .dd_growth = c->page_budget};
++
++ ubifs_release_budget(c, &req);
++}
++
++static int do_writepage(struct page *page, int len)
++{
++ int err = 0, i, blen;
++ unsigned int block;
++ void *addr;
++ union ubifs_key key;
++ struct inode *inode = page->mapping->host;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++
++ /* Update radix tree tags */
++ set_page_writeback(page);
++
++ addr = kmap(page);
++
++ block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
++ i = 0;
++ while (len) {
++ blen = min_t(int, len, UBIFS_BLOCK_SIZE);
++ data_key_init(c, &key, inode->i_ino, block);
++ err = ubifs_jnl_write_data(c, inode, &key, addr, blen);
++ if (err)
++ break;
++ if (++i >= UBIFS_BLOCKS_PER_PAGE)
++ break;
++ block += 1;
++ addr += blen;
++ len -= blen;
++ }
++ if (err) {
++ SetPageError(page);
++ ubifs_err("cannot write page %lu of inode %lu, error %d",
++ page->index, inode->i_ino, err);
++ ubifs_ro_mode(c, err);
++ }
++
++ ubifs_assert(PagePrivate(page));
++ if (PageChecked(page))
++ ubifs_release_new_page_budget(c);
++ else
++ release_existing_page_budget(c);
++
++ atomic_long_dec(&c->dirty_pg_cnt);
++ ClearPagePrivate(page);
++ ClearPageChecked(page);
++
++ kunmap(page);
++ unlock_page(page);
++ end_page_writeback(page);
++
++ return err;
++}
++
++static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
++{
++ struct inode *inode = page->mapping->host;
++ loff_t i_size = i_size_read(inode);
++ pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
++ int len;
++ void *kaddr;
++
++ dbg_gen("ino %lu, pg %lu, pg flags %#lx",
++ inode->i_ino, page->index, page->flags);
++ ubifs_assert(PagePrivate(page));
++
++ /* Is the page fully inside i_size? */
++ if (page->index < end_index)
++ return do_writepage(page, PAGE_CACHE_SIZE);
++
++ /* Is the page fully outside i_size? (truncate in progress) */
++ len = i_size & (PAGE_CACHE_SIZE - 1);
++ if (page->index >= end_index + 1 || !len) {
++ unlock_page(page);
++ return 0;
++ }
++
++ /*
++ * The page straddles i_size. It must be zeroed out on each and every
++ * writepage invocation because it may be mmapped. "A file is mapped
++ * in multiples of the page size. For a file that is not a multiple of
++ * the page size, the remaining memory is zeroed when mapped, and
++ * writes to that region are not written out to the file."
++ */
++ kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + len, 0, PAGE_CACHE_SIZE - len);
++ flush_dcache_page(page);
++ kunmap_atomic(kaddr, KM_USER0);
++
++ return do_writepage(page, len);
++}
++
++static int ubifs_trunc(struct inode *inode, loff_t new_size)
++{
++ loff_t old_size;
++ int err;
++
++ dbg_gen("ino %lu, size %lld -> %lld",
++ inode->i_ino, inode->i_size, new_size);
++ old_size = inode->i_size;
++
++ err = vmtruncate(inode, new_size);
++ if (err)
++ return err;
++
++ if (new_size < old_size) {
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ int offset = new_size & (UBIFS_BLOCK_SIZE - 1);
++
++ if (offset) {
++ pgoff_t index = new_size >> PAGE_CACHE_SHIFT;
++ struct page *page;
++
++ page = find_lock_page(inode->i_mapping, index);
++ if (page) {
++ if (PageDirty(page)) {
++ ubifs_assert(PagePrivate(page));
++
++ clear_page_dirty_for_io(page);
++ if (UBIFS_BLOCKS_PER_PAGE_SHIFT)
++ offset = new_size &
++ (PAGE_CACHE_SIZE - 1);
++ err = do_writepage(page, offset);
++ page_cache_release(page);
++ if (err)
++ return err;
++ /*
++ * We could now tell ubifs_jnl_truncate
++ * not to read the last block.
++ */
++ } else {
++ /*
++ * We could 'kmap()' the page and
++ * pass the data to ubifs_jnl_truncate
++ * to save it from having to read it.
++ */
++ unlock_page(page);
++ page_cache_release(page);
++ }
++ }
++ }
++ err = ubifs_jnl_truncate(c, inode->i_ino, old_size, new_size);
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++
++int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
++{
++ unsigned int ia_valid = attr->ia_valid;
++ struct inode *inode = dentry->d_inode;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ struct ubifs_budget_req req;
++ int truncation, err = 0;
++
++ dbg_gen("ino %lu, ia_valid %#x", inode->i_ino, ia_valid);
++ err = inode_change_ok(inode, attr);
++ if (err)
++ return err;
++
++ memset(&req, 0, sizeof(struct ubifs_budget_req));
++
++ /*
++ * If this is truncation, and we do not truncate on a block boundary,
++ * budget for changing one data block, because the last block will be
++ * re-written.
++ */
++ truncation = (ia_valid & ATTR_SIZE) && attr->ia_size != inode->i_size;
++ if (truncation && attr->ia_size < inode->i_size &&
++ (attr->ia_size & (UBIFS_BLOCK_SIZE - 1)))
++ req.dirtied_page = 1;
++
++ err = ubifs_budget_inode_op(c, inode, &req);
++ if (err)
++ return err;
++
++ if (truncation) {
++ err = ubifs_trunc(inode, attr->ia_size);
++ if (err) {
++ ubifs_cancel_ino_op(c, inode, &req);
++ return err;
++ }
++
++ inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
++ }
++
++ if (ia_valid & ATTR_UID)
++ inode->i_uid = attr->ia_uid;
++ if (ia_valid & ATTR_GID)
++ inode->i_gid = attr->ia_gid;
++ if (ia_valid & ATTR_ATIME)
++ inode->i_atime = timespec_trunc(attr->ia_atime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_MTIME)
++ inode->i_mtime = timespec_trunc(attr->ia_mtime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_CTIME)
++ inode->i_ctime = timespec_trunc(attr->ia_ctime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_MODE) {
++ umode_t mode = attr->ia_mode;
++
++ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
++ mode &= ~S_ISGID;
++ inode->i_mode = mode;
++ }
++
++ mark_inode_dirty_sync(inode);
++ ubifs_release_ino_dirty(c, inode, &req);
++
++ if (req.dirtied_page) {
++ /*
++ * Truncation code does not make the reenacted page dirty, it
++ * just changes it on journal level, so we have to release page
++ * change budget.
++ */
++ memset(&req, 0, sizeof(struct ubifs_budget_req));
++ req.dd_growth = c->page_budget;
++ ubifs_release_budget(c, &req);
++ }
++
++ if (IS_SYNC(inode))
++ err = write_inode_now(inode, 1);
++
++ return err;
++}
++
++static void ubifs_invalidatepage(struct page *page, unsigned long offset)
++{
++ struct inode *inode = page->mapping->host;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ struct ubifs_budget_req req;
++
++ ubifs_assert(PagePrivate(page));
++ if (offset)
++ /* Partial page remains dirty */
++ return;
++
++ memset(&req, 0, sizeof(struct ubifs_budget_req));
++ if (PageChecked(page)) {
++ req.new_page = 1;
++ req.idx_growth = -1;
++ req.data_growth = c->page_budget;
++ } else
++ req.dd_growth = c->page_budget;
++ ubifs_release_budget(c, &req);
++
++ atomic_long_dec(&c->dirty_pg_cnt);
++ ClearPagePrivate(page);
++ ClearPageChecked(page);
++}
++
++static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ struct ubifs_inode *ui = ubifs_inode(dentry->d_inode);
++
++ nd_set_link(nd, ui->data);
++ return NULL;
++}
++
++int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync)
++{
++ struct inode *inode = dentry->d_inode;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ int err;
++
++ dbg_gen("syncing inode %lu", inode->i_ino);
++
++ /* Synchronize the inode and dirty pages */
++ err = write_inode_now(inode, 1);
++ if (err)
++ return err;
++
++ /*
++ * Some data related to this inode may still sit in a write-buffer.
++ * Flush them.
++ */
++ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1);
++ if (err)
++ return err;
++
++ return 0;
++}
++
++/**
++ * mctime_update_needed - check if mtime or ctime update is needed.
++ * @inode: the inode to do the check for
++ * @now: current time
++ *
++ * This helper function checks if the inode mtime/ctime should be updated or
++ * not. If current values of the time-stamps are within the UBIFS inode time
++ * granularity, they are not updated. This is an optimization.
++ */
++static inline int mctime_update_needed(const struct inode *inode,
++ const struct timespec *now)
++{
++ if (!timespec_equal(&inode->i_mtime, now) ||
++ !timespec_equal(&inode->i_ctime, now))
++ return 1;
++ return 0;
++}
++
++/**
++ * update_ctime - update mtime and ctime of an inode.
++ * @c: UBIFS file-system description object
++ * @inode: inode to update
++ *
++ * This function updates mtime and ctime of the inode if it is not equivalent to
++ * current time. Returns zero in case of success and a negative error code in
++ * case of failure.
++ */
++static int update_mctime(struct ubifs_info *c, struct inode *inode)
++{
++ struct timespec now = ubifs_current_time(inode);
++
++ if (mctime_update_needed(inode, &now)) {
++ struct ubifs_budget_req req;
++ int err;
++
++ memset(&req, 0, sizeof(struct ubifs_budget_req));
++ err = ubifs_budget_inode_op(c, inode, &req);
++ if (err)
++ return err;
++
++ inode->i_mtime = inode->i_ctime = now;
++ mark_inode_dirty_sync(inode);
++ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
++ }
++
++ return 0;
++}
++
++static ssize_t ubifs_write(struct file *file, const char __user *buf,
++ size_t len, loff_t *ppos)
++{
++ int err;
++ ssize_t ret;
++ struct inode *inode = file->f_mapping->host;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++
++ err = update_mctime(c, inode);
++ if (err)
++ return err;
++
++ ret = do_sync_write(file, buf, len, ppos);
++ if (ret < 0)
++ return ret;
++
++ if (ret > 0 && IS_SYNC(inode)) {
++ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1);
++ if (err)
++ return err;
++ }
++
++ return ret;
++}
++
++static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov,
++ unsigned long nr_segs, loff_t pos)
++{
++ int err;
++ ssize_t ret;
++ struct inode *inode = iocb->ki_filp->f_mapping->host;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++
++ err = update_mctime(c, inode);
++ if (err)
++ return err;
++
++ ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
++ if (ret < 0)
++ return ret;
++
++ if (ret > 0 && IS_SYNC(inode)) {
++ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1);
++ if (err)
++ return err;
++ }
++
++ return ret;
++}
++
++static int ubifs_set_page_dirty(struct page *page)
++{
++ int ret;
++
++ ret = __set_page_dirty_nobuffers(page);
++ /*
++ * An attempt to dirty a page without budgeting for it - should not
++ * happen.
++ */
++ ubifs_assert(ret == 0);
++ return ret;
++}
++
++static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
++{
++ /*
++ * An attempt to release a dirty page without budgeting for it - should
++ * not happen.
++ */
++ if (PageWriteback(page))
++ return 0;
++ ubifs_assert(PagePrivate(page));
++ ubifs_assert(0);
++ ClearPagePrivate(page);
++ ClearPageChecked(page);
++ return 1;
++}
++
++/*
++ * mmap()d file has taken write protection fault and is being made
++ * writable. UBIFS must ensure page is budgeted for.
++ */
++static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)
++{
++ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ struct timespec now = ubifs_current_time(inode);
++ struct ubifs_budget_req req = { .new_page = 1 };
++ int err, update_time;
++
++ dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index,
++ i_size_read(inode));
++ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
++
++ if (unlikely(c->ro_media))
++ return -EROFS;
++
++ /*
++ * We have not locked @page so far so we may budget for changing the
++ * page. Note, we cannot do this after we locked the page, because
++ * budgeting may cause write-back which would cause deadlock.
++ *
++ * At the moment we do not know whether the page is dirty or not, so we
++ * assume that it is not and budget for a new page. We could look at
++ * the @PG_private flag and figure this out, but we may race with write
++ * back and the page state may change by the time we lock it, so this
++ * would need additional care. We do not bother with this at the
++ * moment, although it might be good idea to do. Instead, we allocate
++ * budget for a new page and amend it later on if the page was in fact
++ * dirty.
++ *
++ * The budgeting-related logic of this function is similar to what we
++ * do in 'ubifs_write_begin()' and 'ubifs_write_end()'. Glance there
++ * for more comments.
++ */
++ if (mctime_update_needed(inode, &now)) {
++ /*
++ * We have to change inode time stamp which requires extra
++ * budgeting.
++ */
++ update_time = 1;
++ err = ubifs_budget_inode_op(c, inode, &req);
++ } else {
++ update_time = 0;
++ err = ubifs_budget_space(c, &req);
++ }
++ if (unlikely(err)) {
++ if (err == -ENOSPC)
++ ubifs_warn("out of space for mmapped file "
++ "(inode number %lu)", inode->i_ino);
++ return err;
++ }
++
++ lock_page(page);
++ if (unlikely(page->mapping != inode->i_mapping ||
++ page_offset(page) > i_size_read(inode))) {
++ /* Page got truncated out from underneath us */
++ err = -EINVAL;
++ goto out_unlock;
++ }
++
++ if (PagePrivate(page))
++ ubifs_release_new_page_budget(c);
++ else {
++ if (!PageChecked(page))
++ ubifs_convert_page_budget(c);
++ SetPagePrivate(page);
++ atomic_long_inc(&c->dirty_pg_cnt);
++ __set_page_dirty_nobuffers(page);
++ }
++
++ if (update_time) {
++ inode->i_mtime = inode->i_ctime = now;
++ mark_inode_dirty_sync(inode);
++ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
++ }
++
++ unlock_page(page);
++ return 0;
++
++out_unlock:
++ unlock_page(page);
++ if (update_time)
++ ubifs_cancel_ino_op(c, inode, &req);
++ else
++ ubifs_release_budget(c, &req);
++ return err;
++}
++
++struct vm_operations_struct ubifs_file_vm_ops = {
++ .fault = filemap_fault,
++ .page_mkwrite = ubifs_vm_page_mkwrite,
++};
++
++static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int err;
++
++ /* 'generic_file_mmap()' takes care of NOMMU case */
++ err = generic_file_mmap(file, vma);
++ if (err)
++ return err;
++ vma->vm_ops = &ubifs_file_vm_ops;
++ return 0;
++}
++
++struct address_space_operations ubifs_file_address_operations = {
++ .readpage = ubifs_readpage,
++ .writepage = ubifs_writepage,
++ .write_begin = ubifs_write_begin,
++ .write_end = ubifs_write_end,
++ .invalidatepage = ubifs_invalidatepage,
++ .set_page_dirty = ubifs_set_page_dirty,
++ .releasepage = ubifs_releasepage,
++};
++
++struct inode_operations ubifs_file_inode_operations = {
++ .setattr = ubifs_setattr,
++ .getattr = ubifs_getattr,
++#ifdef CONFIG_UBIFS_FS_XATTR
++ .setxattr = ubifs_setxattr,
++ .getxattr = ubifs_getxattr,
++ .listxattr = ubifs_listxattr,
++ .removexattr = ubifs_removexattr,
++#endif
++};
++
++struct inode_operations ubifs_symlink_inode_operations = {
++ .readlink = generic_readlink,
++ .follow_link = ubifs_follow_link,
++ .setattr = ubifs_setattr,
++ .getattr = ubifs_getattr,
++};
++
++struct file_operations ubifs_file_operations = {
++ .llseek = generic_file_llseek,
++ .read = do_sync_read,
++ .write = ubifs_write,
++ .aio_read = generic_file_aio_read,
++ .aio_write = ubifs_aio_write,
++ .mmap = ubifs_file_mmap,
++ .fsync = ubifs_fsync,
++ .unlocked_ioctl = ubifs_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = ubifs_compat_ioctl,
++#endif
++};
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/find.c avr32-2.6/fs/ubifs/find.c
+--- linux-2.6.25.6/fs/ubifs/find.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/find.c 2008-06-12 15:09:45.364399968 +0200
+@@ -0,0 +1,977 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/*
++ * This file contains functions for finding LEBs for various purposes e.g.
++ * garbage collection. In general, lprops category heaps and lists are used
++ * for fast access, falling back on scanning the LPT as a last resort.
++ */
++
++#include <linux/sort.h>
++#include "ubifs.h"
++
++/**
++ * struct scan_data - data provided to scan callback functions
++ * @min_space: minimum number of bytes for which to scan
++ * @pick_free: whether it is OK to scan for empty LEBs
++ * @lnum: LEB number found is returned here
++ * @exclude_index: whether to exclude index LEBs
++ */
++struct scan_data {
++ int min_space;
++ int pick_free;
++ int lnum;
++ int exclude_index;
++};
++
++/**
++ * valuable - determine whether LEB properties are valuable.
++ * @c: the UBIFS file-system description object
++ * @lprops: LEB properties
++ *
++ * This function return %1 if the LEB properties should be added to the LEB
++ * properties tree in memory. Otherwise %0 is returned.
++ */
++static int valuable(struct ubifs_info *c, const struct ubifs_lprops *lprops)
++{
++ int n, cat = lprops->flags & LPROPS_CAT_MASK;
++ struct ubifs_lpt_heap *heap;
++
++ switch (cat) {
++ case LPROPS_DIRTY:
++ case LPROPS_DIRTY_IDX:
++ case LPROPS_FREE:
++ heap = &c->lpt_heap[cat - 1];
++ if (heap->cnt < heap->max_cnt)
++ return 1;
++ if (lprops->free + lprops->dirty >= c->dark_wm)
++ return 1;
++ return 0;
++ case LPROPS_EMPTY:
++ n = c->lst.empty_lebs + c->freeable_cnt -
++ c->lst.taken_empty_lebs;
++ if (n < c->lsave_cnt)
++ return 1;
++ return 0;
++ case LPROPS_FREEABLE:
++ return 1;
++ case LPROPS_FRDI_IDX:
++ return 1;
++ }
++ return 0;
++}
++
++/**
++ * scan_for_dirty_cb - dirty space scan callback.
++ * @c: the UBIFS file-system description object
++ * @lprops: LEB properties to scan
++ * @in_tree: whether the LEB properties are in main memory
++ * @data: information passed to and from the caller of the scan
++ *
++ * This function returns a code that indicates whether the scan should continue
++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
++ * (%LPT_SCAN_STOP).
++ */
++static int scan_for_dirty_cb(struct ubifs_info *c,
++ const struct ubifs_lprops *lprops, int in_tree,
++ struct scan_data *data)
++{
++ int ret = LPT_SCAN_CONTINUE;
++
++ /* Exclude LEBs that are currently in use */
++ if (lprops->flags & LPROPS_TAKEN)
++ return LPT_SCAN_CONTINUE;
++ /* Determine whether to add these LEB properties to the tree */
++ if (!in_tree && valuable(c, lprops))
++ ret |= LPT_SCAN_ADD;
++ /* Exclude LEBs with too little space */
++ if (lprops->free + lprops->dirty < data->min_space)
++ return ret;
++ /* If specified, exclude index LEBs */
++ if (data->exclude_index && lprops->flags & LPROPS_INDEX)
++ return ret;
++ /* If specified, exclude empty or freeable LEBs */
++ if (lprops->free + lprops->dirty == c->leb_size) {
++ if (!data->pick_free)
++ return ret;
++ /* Exclude LEBs with too little dirty space (unless it is empty) */
++ } else if (lprops->dirty < c->dead_wm)
++ return ret;
++ /* Finally we found space */
++ data->lnum = lprops->lnum;
++ return LPT_SCAN_ADD | LPT_SCAN_STOP;
++}
++
++/**
++ * scan_for_dirty - find a data LEB with free space.
++ * @c: the UBIFS file-system description object
++ * @min_space: minimum amount free plus dirty space the returned LEB has to
++ * have
++ * @pick_free: if it is OK to return a free or freeable LEB
++ * @exclude_index: whether to exclude index LEBs
++ *
++ * This function returns a pointer to the LEB properties found or a negative
++ * error code.
++ */
++static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
++ int min_space, int pick_free,
++ int exclude_index)
++{
++ const struct ubifs_lprops *lprops;
++ struct ubifs_lpt_heap *heap;
++ struct scan_data data;
++ int err, i;
++
++ /* There may be an LEB with enough dirty space on the free heap */
++ heap = &c->lpt_heap[LPROPS_FREE - 1];
++ for (i = 0; i < heap->cnt; i++) {
++ lprops = heap->arr[i];
++ if (lprops->free + lprops->dirty < min_space)
++ continue;
++ if (lprops->dirty < c->dead_wm)
++ continue;
++ return lprops;
++ }
++ /*
++ * A LEB may have fallen off of the bottom of the dirty heap, and ended
++ * up as uncategorized even though it has enough dirty space for us now,
++ * so check the uncategorized list. N.B. neither empty nor freeable LEBs
++ * can end up as uncategorized because they are kept on lists not
++ * finite-sized heaps.
++ */
++ list_for_each_entry(lprops, &c->uncat_list, list) {
++ if (lprops->flags & LPROPS_TAKEN)
++ continue;
++ if (lprops->free + lprops->dirty < min_space)
++ continue;
++ if (exclude_index && (lprops->flags & LPROPS_INDEX))
++ continue;
++ if (lprops->dirty < c->dead_wm)
++ continue;
++ return lprops;
++ }
++ /* We have looked everywhere in main memory, now scan the flash */
++ if (c->pnodes_have >= c->pnode_cnt)
++ /* All pnodes are in memory, so skip scan */
++ return ERR_PTR(-ENOSPC);
++ data.min_space = min_space;
++ data.pick_free = pick_free;
++ data.lnum = -1;
++ data.exclude_index = exclude_index;
++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
++ (ubifs_lpt_scan_callback)scan_for_dirty_cb,
++ &data);
++ if (err)
++ return ERR_PTR(err);
++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
++ c->lscan_lnum = data.lnum;
++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
++ if (IS_ERR(lprops))
++ return lprops;
++ ubifs_assert(lprops->lnum == data.lnum);
++ ubifs_assert(lprops->free + lprops->dirty >= min_space);
++ ubifs_assert(lprops->dirty >= c->dead_wm ||
++ (pick_free &&
++ lprops->free + lprops->dirty == c->leb_size));
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
++ return lprops;
++}
++
++/**
++ * ubifs_find_dirty_leb - find a dirty LEB for the Garbage Collector.
++ * @c: the UBIFS file-system description object
++ * @ret_lp: LEB properties are returned here on exit
++ * @min_space: minimum amount free plus dirty space the returned LEB has to
++ * have
++ * @pick_free: controls whether it is OK to pick empty or index LEBs
++ *
++ * This function tries to find a dirty logical eraseblock which has at least
++ * @min_space free and dirty space. It prefers to take an LEB from the dirty or
++ * dirty index heap, and it falls-back to LPT scanning if the heaps are empty
++ * or do not have an LEB which satisfies the @min_space criteria.
++ *
++ * Note:
++ * o LEBs which have less than dead watermark of dirty space are never picked
++ * by this function;
++ *
++ * Returns zero and the LEB properties of
++ * found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a
++ * negative error code in case of other failures. The returned LEB is marked as
++ * "taken".
++ *
++ * The additional @pick_free argument controls if this function has to return a
++ * free or freeable LEB if one is present. For example, GC must to set it to %1,
++ * when called from the journal space reservation function, because the
++ * appearance of free space may coincide with the loss of enough dirty space
++ * for GC to succeed anyway.
++ *
++ * In contrast, if the Garbage Collector is called from budgeting, it should
++ * just make free space, not return LEBs which are already free or freeable.
++ *
++ * In addition @pick_free is set to %2 by the recovery process in order to
++ * recover gc_lnum in which case an index LEB must not be returned.
++ */
++int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
++ int min_space, int pick_free)
++{
++ int err = 0, sum, exclude_index = pick_free == 2 ? 1 : 0;
++ const struct ubifs_lprops *lp = NULL, *idx_lp = NULL;
++ struct ubifs_lpt_heap *heap, *idx_heap;
++
++ ubifs_get_lprops(c);
++
++ if (pick_free) {
++ int lebs, rsvd_idx_lebs = 0;
++
++ spin_lock(&c->space_lock);
++ lebs = c->lst.empty_lebs;
++ lebs += c->freeable_cnt - c->lst.taken_empty_lebs;
++
++ /*
++ * Note, the index may consume more LEBs than have been reserved
++ * for it. It is OK because it might be consolidated by GC.
++ * But if the index takes fewer LEBs than it is reserved for it,
++ * this function must avoid picking those reserved LEBs.
++ */
++ if (c->min_idx_lebs >= c->lst.idx_lebs) {
++ rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs;
++ exclude_index = 1;
++ }
++ spin_unlock(&c->space_lock);
++
++ /* Check if there are enough free LEBs for the index */
++ if (rsvd_idx_lebs < lebs) {
++ /* OK, try to find an empty LEB */
++ lp = ubifs_fast_find_empty(c);
++ if (lp)
++ goto found;
++
++ /* Or a freeable LEB */
++ lp = ubifs_fast_find_freeable(c);
++ if (lp)
++ goto found;
++ } else
++ /*
++ * We cannot pick free/freeable LEBs in the below code.
++ */
++ pick_free = 0;
++ } else {
++ spin_lock(&c->space_lock);
++ exclude_index = (c->min_idx_lebs >= c->lst.idx_lebs);
++ spin_unlock(&c->space_lock);
++ }
++
++ /* Look on the dirty and dirty index heaps */
++ heap = &c->lpt_heap[LPROPS_DIRTY - 1];
++ idx_heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
++
++ if (idx_heap->cnt && !exclude_index) {
++ idx_lp = idx_heap->arr[0];
++ sum = idx_lp->free + idx_lp->dirty;
++ /*
++ * Since we reserve twice as more space for the index than it
++ * actually takes, it does not make sense to pick indexing LEBs
++ * with less than half LEB of dirty space.
++ */
++ if (sum < min_space || sum < c->half_leb_size)
++ idx_lp = NULL;
++ }
++
++ if (heap->cnt) {
++ lp = heap->arr[0];
++ if (lp->dirty + lp->free < min_space)
++ lp = NULL;
++ }
++
++ /* Pick the LEB with most space */
++ if (idx_lp && lp) {
++ if (idx_lp->free + idx_lp->dirty >= lp->free + lp->dirty)
++ lp = idx_lp;
++ } else if (idx_lp && !lp)
++ lp = idx_lp;
++
++ if (lp) {
++ ubifs_assert(lp->dirty >= c->dead_wm);
++ goto found;
++ }
++
++ /* Did not find a dirty LEB on the dirty heaps, have to scan */
++ dbg_find("scanning LPT for a dirty LEB");
++ lp = scan_for_dirty(c, min_space, pick_free, exclude_index);
++ if (IS_ERR(lp)) {
++ err = PTR_ERR(lp);
++ goto out;
++ }
++ ubifs_assert(lp->dirty >= c->dead_wm ||
++ (pick_free && lp->free + lp->dirty == c->leb_size));
++
++found:
++ dbg_find("found LEB %d, free %d, dirty %d, flags %#x",
++ lp->lnum, lp->free, lp->dirty, lp->flags);
++
++ lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
++ lp->flags | LPROPS_TAKEN, 0);
++ if (IS_ERR(lp)) {
++ err = PTR_ERR(lp);
++ goto out;
++ }
++
++ memcpy(ret_lp, lp, sizeof(struct ubifs_lprops));
++
++out:
++ ubifs_release_lprops(c);
++ return err;
++}
++
++/**
++ * scan_for_free_cb - free space scan callback.
++ * @c: the UBIFS file-system description object
++ * @lprops: LEB properties to scan
++ * @in_tree: whether the LEB properties are in main memory
++ * @data: information passed to and from the caller of the scan
++ *
++ * This function returns a code that indicates whether the scan should continue
++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
++ * (%LPT_SCAN_STOP).
++ */
++static int scan_for_free_cb(struct ubifs_info *c,
++ const struct ubifs_lprops *lprops, int in_tree,
++ struct scan_data *data)
++{
++ int ret = LPT_SCAN_CONTINUE;
++
++ /* Exclude LEBs that are currently in use */
++ if (lprops->flags & LPROPS_TAKEN)
++ return LPT_SCAN_CONTINUE;
++ /* Determine whether to add these LEB properties to the tree */
++ if (!in_tree && valuable(c, lprops))
++ ret |= LPT_SCAN_ADD;
++ /* Exclude index LEBs */
++ if (lprops->flags & LPROPS_INDEX)
++ return ret;
++ /* Exclude LEBs with too little space */
++ if (lprops->free < data->min_space)
++ return ret;
++ /* If specified, exclude empty LEBs */
++ if (!data->pick_free && lprops->free == c->leb_size)
++ return ret;
++ /*
++ * LEBs that have only free and dirty space must not be allocated
++ * because they may have been unmapped already or they may have data
++ * that is obsolete only because of nodes that are still sitting in a
++ * wbuf.
++ */
++ if (lprops->free + lprops->dirty == c->leb_size && lprops->dirty > 0)
++ return ret;
++ /* Finally we found space */
++ data->lnum = lprops->lnum;
++ return LPT_SCAN_ADD | LPT_SCAN_STOP;
++}
++
++/**
++ * do_find_free_space - find a data LEB with free space.
++ * @c: the UBIFS file-system description object
++ * @min_space: minimum amount of free space required
++ * @pick_free: whether it is OK to scan for empty LEBs
++ * @squeeze: whether to try to find space in a non-empty LEB first
++ *
++ * This function returns a pointer to the LEB properties found or a negative
++ * error code.
++ */
++static
++const struct ubifs_lprops *do_find_free_space(struct ubifs_info *c,
++ int min_space, int pick_free,
++ int squeeze)
++{
++ const struct ubifs_lprops *lprops;
++ struct ubifs_lpt_heap *heap;
++ struct scan_data data;
++ int err, i;
++
++ if (squeeze) {
++ lprops = ubifs_fast_find_free(c);
++ if (lprops && lprops->free >= min_space)
++ return lprops;
++ }
++ if (pick_free) {
++ lprops = ubifs_fast_find_empty(c);
++ if (lprops)
++ return lprops;
++ }
++ if (!squeeze) {
++ lprops = ubifs_fast_find_free(c);
++ if (lprops && lprops->free >= min_space)
++ return lprops;
++ }
++ /* There may be an LEB with enough free space on the dirty heap */
++ heap = &c->lpt_heap[LPROPS_DIRTY - 1];
++ for (i = 0; i < heap->cnt; i++) {
++ lprops = heap->arr[i];
++ if (lprops->free >= min_space)
++ return lprops;
++ }
++ /*
++ * A LEB may have fallen off of the bottom of the free heap, and ended
++ * up as uncategorized even though it has enough free space for us now,
++ * so check the uncategorized list. N.B. neither empty nor freeable LEBs
++ * can end up as uncategorized because they are kept on lists not
++ * finite-sized heaps.
++ */
++ list_for_each_entry(lprops, &c->uncat_list, list) {
++ if (lprops->flags & LPROPS_TAKEN)
++ continue;
++ if (lprops->flags & LPROPS_INDEX)
++ continue;
++ if (lprops->free >= min_space)
++ return lprops;
++ }
++ /* We have looked everywhere in main memory, now scan the flash */
++ if (c->pnodes_have >= c->pnode_cnt)
++ /* All pnodes are in memory, so skip scan */
++ return ERR_PTR(-ENOSPC);
++ data.min_space = min_space;
++ data.pick_free = pick_free;
++ data.lnum = -1;
++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
++ (ubifs_lpt_scan_callback)scan_for_free_cb,
++ &data);
++ if (err)
++ return ERR_PTR(err);
++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
++ c->lscan_lnum = data.lnum;
++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
++ if (IS_ERR(lprops))
++ return lprops;
++ ubifs_assert(lprops->lnum == data.lnum);
++ ubifs_assert(lprops->free >= min_space);
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
++ return lprops;
++}
++
++/**
++ * ubifs_find_free_space - find a data LEB with free space.
++ * @c: the UBIFS file-system description object
++ * @min_space: minimum amount of required free space
++ * @free: contains amount of free space in the LEB on exit
++ * @squeeze: whether to try to find space in a non-empty LEB first
++ *
++ * This function looks for an LEB with at least @min_space bytes of free space.
++ * It tries to find an empty LEB if possible. If no empty LEBs are available,
++ * this function searches for a non-empty data LEB. The returned LEB is marked
++ * as "taken".
++ *
++ * This function returns found LEB number in case of success, %-ENOSPC if it
++ * failed to find a LEB with @min_space bytes of free space and other a negative
++ * error codes in case of failure.
++ */
++int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free,
++ int squeeze)
++{
++ const struct ubifs_lprops *lprops;
++ int lebs, rsvd_idx_lebs, pick_free = 0, err, lnum, flags;
++
++ dbg_find("min_space %d", min_space);
++ ubifs_assert(min_space > 0 && min_space <= c->dark_wm);
++
++ ubifs_get_lprops(c);
++
++ /* Check if there are enough empty LEBs for commit */
++ spin_lock(&c->space_lock);
++ if (c->min_idx_lebs > c->lst.idx_lebs)
++ rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs;
++ else
++ rsvd_idx_lebs = 0;
++ lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
++ c->lst.taken_empty_lebs;
++ ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs);
++ if (rsvd_idx_lebs < lebs)
++ /*
++ * OK to allocate an empty LEB, but we still don't want to go
++ * looking for one if there aren't any.
++ */
++ if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
++ pick_free = 1;
++ /*
++ * Because we release the space lock, we must account
++ * for this allocation here. After the LEB properties
++ * flags have been updated, we subtract one. Note, the
++ * result of this is that lprops also decreases
++ * @taken_empty_lebs in 'ubifs_change_lp()', so it is
++ * off by one for a short period of time which may
++ * introduce a small disturbance to budgeting
++ * calculations, but this is harmless because at the
++ * worst case this would make the budgeting subsystem
++ * be more pessimistic than needed.
++ *
++ * Fundamentally, this is about serialization of the
++ * budgeting and lprops subsystems. We could make the
++ * @space_lock a mutex and avoid dropping it before
++ * calling 'ubifs_change_lp()', but mutex is more
++ * heavy-weight, and we want budgeting to be as fast as
++ * possible.
++ */
++ c->lst.taken_empty_lebs += 1;
++ }
++ spin_unlock(&c->space_lock);
++
++ lprops = do_find_free_space(c, min_space, pick_free, squeeze);
++ if (IS_ERR(lprops)) {
++ err = PTR_ERR(lprops);
++ goto out;
++ }
++
++ lnum = lprops->lnum;
++ flags = lprops->flags | LPROPS_TAKEN;
++
++ lprops = ubifs_change_lp(c, lprops, LPROPS_NC, LPROPS_NC, flags, 0);
++ if (IS_ERR(lprops)) {
++ err = PTR_ERR(lprops);
++ goto out;
++ }
++
++ if (pick_free) {
++ spin_lock(&c->space_lock);
++ c->lst.taken_empty_lebs -= 1;
++ spin_unlock(&c->space_lock);
++ }
++
++ *free = lprops->free;
++ ubifs_release_lprops(c);
++
++ if (*free == c->leb_size) {
++ /*
++ * Ensure that empty LEBs have been unmapped. They may not have
++ * been, for example, because of an unclean unmount. Also
++ * LEBs that were freeable LEBs (free + dirty == leb_size) will
++ * not have been unmapped.
++ */
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ }
++
++ dbg_find("found LEB %d, free %d", lnum, *free);
++ ubifs_assert(*free >= min_space);
++ return lnum;
++
++out:
++ if (pick_free) {
++ spin_lock(&c->space_lock);
++ c->lst.taken_empty_lebs -= 1;
++ spin_unlock(&c->space_lock);
++ }
++ ubifs_release_lprops(c);
++ return err;
++}
++
++/**
++ * scan_for_idx_cb - callback used by the scan for a free LEB for the index.
++ * @c: the UBIFS file-system description object
++ * @lprops: LEB properties to scan
++ * @in_tree: whether the LEB properties are in main memory
++ * @data: information passed to and from the caller of the scan
++ *
++ * This function returns a code that indicates whether the scan should continue
++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
++ * (%LPT_SCAN_STOP).
++ */
++static int scan_for_idx_cb(struct ubifs_info *c,
++ const struct ubifs_lprops *lprops, int in_tree,
++ struct scan_data *data)
++{
++ int ret = LPT_SCAN_CONTINUE;
++
++ /* Exclude LEBs that are currently in use */
++ if (lprops->flags & LPROPS_TAKEN)
++ return LPT_SCAN_CONTINUE;
++ /* Determine whether to add these LEB properties to the tree */
++ if (!in_tree && valuable(c, lprops))
++ ret |= LPT_SCAN_ADD;
++ /* Exclude index LEBS */
++ if (lprops->flags & LPROPS_INDEX)
++ return ret;
++ /* Exclude LEBs that cannot be made empty */
++ if (lprops->free + lprops->dirty != c->leb_size)
++ return ret;
++ /*
++ * We are allocating for the index so it is safe to allocate LEBs with
++ * only free and dirty space, because write buffers are sync'd at commit
++ * start.
++ */
++ data->lnum = lprops->lnum;
++ return LPT_SCAN_ADD | LPT_SCAN_STOP;
++}
++
++/**
++ * scan_for_leb_for_idx - scan for a free LEB for the index.
++ * @c: the UBIFS file-system description object
++ */
++static const struct ubifs_lprops *scan_for_leb_for_idx(struct ubifs_info *c)
++{
++ struct ubifs_lprops *lprops;
++ struct scan_data data;
++ int err;
++
++ data.lnum = -1;
++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
++ (ubifs_lpt_scan_callback)scan_for_idx_cb,
++ &data);
++ if (err)
++ return ERR_PTR(err);
++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
++ c->lscan_lnum = data.lnum;
++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
++ if (IS_ERR(lprops))
++ return lprops;
++ ubifs_assert(lprops->lnum == data.lnum);
++ ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
++ return lprops;
++}
++
++/**
++ * ubifs_find_free_leb_for_idx - find a free LEB for the index.
++ * @c: the UBIFS file-system description object
++ *
++ * This function looks for a free LEB and returns that LEB number. The returned
++ * LEB is marked as "taken", "index".
++ *
++ * Only empty LEBs are allocated. This is for two reasons. First, the commit
++ * calculates the number of LEBs to allocate based on the assumption that they
++ * will be empty. Secondly, free space at the end of an index LEB is not
++ * guaranteed to be empty because it may have been used by the in-the-gaps
++ * method prior to an unclean unmount.
++ *
++ * If no LEB is found %-ENOSPC is returned. For other failures another negative
++ * error code is returned.
++ */
++int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
++{
++ const struct ubifs_lprops *lprops;
++ int lnum = -1, err, flags;
++
++ ubifs_get_lprops(c);
++
++ lprops = ubifs_fast_find_empty(c);
++ if (!lprops) {
++ lprops = ubifs_fast_find_freeable(c);
++ if (!lprops) {
++ ubifs_assert(c->freeable_cnt == 0);
++ if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
++ lprops = scan_for_leb_for_idx(c);
++ if (IS_ERR(lprops)) {
++ err = PTR_ERR(lprops);
++ goto out;
++ }
++ }
++ }
++ }
++
++ if (!lprops) {
++ err = -ENOSPC;
++ goto out;
++ }
++
++ lnum = lprops->lnum;
++
++ dbg_find("found LEB %d, free %d, dirty %d, flags %#x",
++ lnum, lprops->free, lprops->dirty, lprops->flags);
++
++ flags = lprops->flags | LPROPS_TAKEN | LPROPS_INDEX;
++ lprops = ubifs_change_lp(c, lprops, c->leb_size, 0, flags, 0);
++ if (IS_ERR(lprops)) {
++ err = PTR_ERR(lprops);
++ goto out;
++ }
++
++ ubifs_release_lprops(c);
++
++ /*
++ * Ensure that empty LEBs have been unmapped. They may not have been,
++ * for example, because of an unclean unmount. Also LEBs that were
++ * freeable LEBs (free + dirty == leb_size) will not have been unmapped.
++ */
++ err = ubifs_leb_unmap(c, lnum);
++ if (err) {
++ ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
++ LPROPS_TAKEN | LPROPS_INDEX, 0);
++ return err;
++ }
++
++ return lnum;
++
++out:
++ ubifs_release_lprops(c);
++ return err;
++}
++
++static int cmp_dirty_idx(const struct ubifs_lprops **a,
++ const struct ubifs_lprops **b)
++{
++ const struct ubifs_lprops *lpa = *a;
++ const struct ubifs_lprops *lpb = *b;
++
++ return lpa->dirty + lpa->free - lpb->dirty - lpb->free;
++}
++
++static void swap_dirty_idx(struct ubifs_lprops **a, struct ubifs_lprops **b,
++ int size)
++{
++ struct ubifs_lprops *t = *a;
++
++ *a = *b;
++ *b = t;
++}
++
++/**
++ * ubifs_save_dirty_idx_lnums - save an array of the most dirty index LEB nos.
++ * @c: the UBIFS file-system description object
++ *
++ * This function is called each commit to create an array of LEB numbers of
++ * dirty index LEBs sorted in order of dirty and free space. This is used by
++ * the in-the-gaps method of TNC commit.
++ */
++int ubifs_save_dirty_idx_lnums(struct ubifs_info *c)
++{
++ int i;
++
++ ubifs_get_lprops(c);
++ /* Copy the LPROPS_DIRTY_IDX heap */
++ c->dirty_idx.cnt = c->lpt_heap[LPROPS_DIRTY_IDX - 1].cnt;
++ memcpy(c->dirty_idx.arr, c->lpt_heap[LPROPS_DIRTY_IDX - 1].arr,
++ sizeof(void *) * c->dirty_idx.cnt);
++ /* Sort it so that the dirtiest is now at the end */
++ sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
++ (int (*)(const void *, const void *))cmp_dirty_idx,
++ (void (*)(void *, void *, int))swap_dirty_idx);
++ dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt);
++ if (c->dirty_idx.cnt)
++ dbg_find("dirtiest index LEB is %d with dirty %d and free %d",
++ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->lnum,
++ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->dirty,
++ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->free);
++ /* Replace the lprops pointers with LEB numbers */
++ for (i = 0; i < c->dirty_idx.cnt; i++)
++ c->dirty_idx.arr[i] = (void *)(size_t)c->dirty_idx.arr[i]->lnum;
++ ubifs_release_lprops(c);
++ return 0;
++}
++
++/**
++ * scan_dirty_idx_cb - callback used by the scan for a dirty index LEB.
++ * @c: the UBIFS file-system description object
++ * @lprops: LEB properties to scan
++ * @in_tree: whether the LEB properties are in main memory
++ * @data: information passed to and from the caller of the scan
++ *
++ * This function returns a code that indicates whether the scan should continue
++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
++ * (%LPT_SCAN_STOP).
++ */
++static int scan_dirty_idx_cb(struct ubifs_info *c,
++ const struct ubifs_lprops *lprops, int in_tree,
++ struct scan_data *data)
++{
++ int ret = LPT_SCAN_CONTINUE;
++
++ /* Exclude LEBs that are currently in use */
++ if (lprops->flags & LPROPS_TAKEN)
++ return LPT_SCAN_CONTINUE;
++ /* Determine whether to add these LEB properties to the tree */
++ if (!in_tree && valuable(c, lprops))
++ ret |= LPT_SCAN_ADD;
++ /* Exclude non-index LEBs */
++ if (!(lprops->flags & LPROPS_INDEX))
++ return ret;
++ /* Exclude LEBs with too little space */
++ if (lprops->free + lprops->dirty < c->min_idx_node_sz)
++ return ret;
++ /* Finally we found space */
++ data->lnum = lprops->lnum;
++ return LPT_SCAN_ADD | LPT_SCAN_STOP;
++}
++
++/**
++ * find_dirty_idx_leb - find a dirty index LEB.
++ * @c: the UBIFS file-system description object
++ *
++ * This function returns LEB number upon success and a negative error code upon
++ * failure. In particular, -ENOSPC is returned if a dirty index LEB is not
++ * found.
++ *
++ * Note that this function scans the entire LPT but it is called very rarely.
++ */
++static int find_dirty_idx_leb(struct ubifs_info *c)
++{
++ const struct ubifs_lprops *lprops;
++ struct ubifs_lpt_heap *heap;
++ struct scan_data data;
++ int err, i, ret;
++
++ /* Check all structures in memory first */
++ data.lnum = -1;
++ heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
++ for (i = 0; i < heap->cnt; i++) {
++ lprops = heap->arr[i];
++ ret = scan_dirty_idx_cb(c, lprops, 1, &data);
++ if (ret & LPT_SCAN_STOP)
++ goto found;
++ }
++ list_for_each_entry(lprops, &c->frdi_idx_list, list) {
++ ret = scan_dirty_idx_cb(c, lprops, 1, &data);
++ if (ret & LPT_SCAN_STOP)
++ goto found;
++ }
++ list_for_each_entry(lprops, &c->uncat_list, list) {
++ ret = scan_dirty_idx_cb(c, lprops, 1, &data);
++ if (ret & LPT_SCAN_STOP)
++ goto found;
++ }
++ if (c->pnodes_have >= c->pnode_cnt)
++ /* All pnodes are in memory, so skip scan */
++ return -ENOSPC;
++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
++ (ubifs_lpt_scan_callback)scan_dirty_idx_cb,
++ &data);
++ if (err)
++ return err;
++found:
++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
++ c->lscan_lnum = data.lnum;
++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
++ if (IS_ERR(lprops))
++ return PTR_ERR(lprops);
++ ubifs_assert(lprops->lnum == data.lnum);
++ ubifs_assert(lprops->free + lprops->dirty >= c->min_idx_node_sz);
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert((lprops->flags & LPROPS_INDEX));
++
++ dbg_find("found dirty LEB %d, free %d, dirty %d, flags %#x",
++ lprops->lnum, lprops->free, lprops->dirty, lprops->flags);
++
++ lprops = ubifs_change_lp(c, lprops, LPROPS_NC, LPROPS_NC,
++ lprops->flags | LPROPS_TAKEN, 0);
++ if (IS_ERR(lprops))
++ return PTR_ERR(lprops);
++
++ return lprops->lnum;
++}
++
++/**
++ * get_idx_gc_leb - try to get a LEB number from trivial GC.
++ * @c: the UBIFS file-system description object
++ */
++static int get_idx_gc_leb(struct ubifs_info *c)
++{
++ const struct ubifs_lprops *lp;
++ int err, lnum;
++
++ err = ubifs_get_idx_gc_leb(c);
++ if (err < 0)
++ return err;
++ lnum = err;
++ /*
++ * The LEB was due to be unmapped after the commit but
++ * it is needed now for this commit.
++ */
++ lp = ubifs_lpt_lookup_dirty(c, lnum);
++ if (unlikely(IS_ERR(lp)))
++ return PTR_ERR(lp);
++ lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
++ lp->flags | LPROPS_INDEX, -1);
++ if (unlikely(IS_ERR(lp)))
++ return PTR_ERR(lp);
++ dbg_find("LEB %d, dirty %d and free %d flags %#x",
++ lp->lnum, lp->dirty, lp->free, lp->flags);
++ return lnum;
++}
++
++/**
++ * find_dirtiest_idx_leb - find dirtiest index LEB from dirtiest array.
++ * @c: the UBIFS file-system description object
++ */
++static int find_dirtiest_idx_leb(struct ubifs_info *c)
++{
++ const struct ubifs_lprops *lp;
++ int lnum;
++
++ while (1) {
++ if (!c->dirty_idx.cnt)
++ return -ENOSPC;
++ /* The lprops pointers were replaced by LEB numbers */
++ lnum = (size_t)c->dirty_idx.arr[--c->dirty_idx.cnt];
++ lp = ubifs_lpt_lookup(c, lnum);
++ if (IS_ERR(lp))
++ return PTR_ERR(lp);
++ if ((lp->flags & LPROPS_TAKEN) || !(lp->flags & LPROPS_INDEX))
++ continue;
++ lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
++ lp->flags | LPROPS_TAKEN, 0);
++ if (IS_ERR(lp))
++ return PTR_ERR(lp);
++ break;
++ }
++ dbg_find("LEB %d, dirty %d and free %d flags %#x", lp->lnum, lp->dirty,
++ lp->free, lp->flags);
++ ubifs_assert(lp->flags | LPROPS_TAKEN);
++ ubifs_assert(lp->flags | LPROPS_INDEX);
++ return lnum;
++}
++
++/**
++ * ubifs_find_dirty_idx_leb - try to find dirtiest index LEB as at last commit.
++ * @c: the UBIFS file-system description object
++ *
++ * This function attempts to find an untaken index LEB with the most free and
++ * dirty space that can be used without overwriting index nodes that were in the
++ * last index committed.
++ */
++int ubifs_find_dirty_idx_leb(struct ubifs_info *c)
++{
++ int err;
++
++ ubifs_get_lprops(c);
++
++ /*
++ * We made an array of the dirtiest index LEB numbers as at the start of
++ * last commit. Try that array first.
++ */
++ err = find_dirtiest_idx_leb(c);
++
++ /* Next try scanning the entire LPT */
++ if (err == -ENOSPC)
++ err = find_dirty_idx_leb(c);
++
++ /* Finally take any index LEBs awaiting trivial GC */
++ if (err == -ENOSPC)
++ err = get_idx_gc_leb(c);
++
++ ubifs_release_lprops(c);
++ return err;
++}
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/gc.c avr32-2.6/fs/ubifs/gc.c
+--- linux-2.6.25.6/fs/ubifs/gc.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/gc.c 2008-06-12 15:09:45.367815766 +0200
+@@ -0,0 +1,762 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ */
++
++/*
++ * This file implements garbage collection. The procedure for garbage collection
++ * is different depending on whether a LEB as an index LEB (contains index
++ * nodes) or not. For non-index LEBs, garbage collection finds a LEB which
++ * contains a lot of dirty space (obsolete nodes), and copies the non-obsolete
++ * nodes to the journal, at which point the garbage-collected LEB is free to be
++ * reused. For index LEBs, garbage collection marks the non-obsolete index nodes
++ * dirty in the TNC, and after the next commit, the garbage-collected LEB is
++ * to be reused. Garbage collection will cause the number of dirty index nodes
++ * to grow, however sufficient space is reserved for the index to ensure the
++ * commit will never run out of space.
++ */
++
++#include <linux/pagemap.h>
++#include "ubifs.h"
++
++/*
++ * GC tries to optimize the way it fit nodes to available space, and it sorts
++ * nodes a little. The below constants are watermarks which define "large",
++ * "medium", and "small" nodes.
++ */
++#define MEDIUM_NODE_WM (UBIFS_BLOCK_SIZE / 4)
++#define SMALL_NODE_WM UBIFS_MAX_DENT_NODE_SZ
++
++/*
++ * GC may need to move more then one LEB to make progress. The below constants
++ * define "soft" and "hard" limits on the number of LEBs the garbage collector
++ * may move.
++ */
++#define SOFT_LEBS_LIMIT 4
++#define HARD_LEBS_LIMIT 32
++
++/**
++ * switch_gc_head - switch the garbage collection journal head.
++ * @c: UBIFS file-system description object
++ * @buf: buffer to write
++ * @len: length of the buffer to write
++ * @lnum: LEB number written is returned here
++ * @offs: offset written is returned here
++ *
++ * This function switch the GC head to the next LEB which is reserved in
++ * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required,
++ * and other negative error code in case of failures.
++ */
++static int switch_gc_head(struct ubifs_info *c)
++{
++ int err, gc_lnum = c->gc_lnum;
++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
++
++ ubifs_assert(gc_lnum != -1);
++ dbg_gc("switch GC head from LEB %d:%d to LEB %d (waste %d bytes)",
++ wbuf->lnum, wbuf->offs + wbuf->used, gc_lnum,
++ c->leb_size - wbuf->offs - wbuf->used);
++
++ err = ubifs_wbuf_sync_nolock(wbuf);
++ if (err)
++ return err;
++
++ /*
++ * The GC write-buffer was synchronized, we may safely unmap
++ * 'c->gc_lnum'.
++ */
++ err = ubifs_leb_unmap(c, gc_lnum);
++ if (err)
++ return err;
++
++ err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0);
++ if (err)
++ return err;
++
++ c->gc_lnum = -1;
++ err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0, UBI_LONGTERM);
++ return err;
++}
++
++/**
++ * move_nodes - move nodes.
++ * @c: UBIFS file-system description object
++ * @sleb: describes nodes to move
++ *
++ * This function moves valid nodes from data LEB described by @sleb to the GC
++ * journal head. The obsolete nodes are dropped.
++ *
++ * When moving nodes we have to deal with classical bin-packing problem: the
++ * space in the current GC journal head LEB and in @c->gc_lnum are the "bins",
++ * where the nodes in the @sleb->nodes list are the elements which should be
++ * fit optimally to the bins. This function uses the "first fit decreasing"
++ * strategy, although it does not really sort the nodes but just split them on
++ * 3 classes - large, medium, and small, so they are roughly sorted.
++ *
++ * This function returns zero in case of success, %-EAGAIN if commit is
++ * required, and other negative error codes in case of other failures.
++ */
++static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
++{
++ struct ubifs_scan_node *snod, *tmp;
++ struct list_head large, medium, small;
++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
++ int avail, err, min = INT_MAX;
++
++ INIT_LIST_HEAD(&large);
++ INIT_LIST_HEAD(&medium);
++ INIT_LIST_HEAD(&small);
++
++ list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
++ struct list_head *lst;
++
++ ubifs_assert(snod->type != UBIFS_IDX_NODE);
++ ubifs_assert(snod->type != UBIFS_REF_NODE);
++ ubifs_assert(snod->type != UBIFS_CS_NODE);
++
++ err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum,
++ snod->offs, 0);
++ if (err < 0)
++ goto out;
++
++ lst = &snod->list;
++ list_del(lst);
++ if (!err) {
++ /* The node is obsolete, remove it from the list */
++ kfree(snod);
++ continue;
++ }
++
++ /*
++ * Sort the list of nodes so that large nodes go first, and
++ * small nodes go last.
++ */
++ if (snod->len > MEDIUM_NODE_WM)
++ list_add(lst, &large);
++ else if (snod->len > SMALL_NODE_WM)
++ list_add(lst, &medium);
++ else
++ list_add(lst, &small);
++
++ /* And find the smallest node */
++ if (snod->len < min)
++ min = snod->len;
++ }
++
++ /*
++ * Join the tree lists so that we'd have one roughly sorted list
++ * ('large' will be the head of the joined list).
++ */
++ list_splice(&medium, large.prev);
++ list_splice(&small, large.prev);
++
++ if (wbuf->lnum == -1) {
++ /*
++ * The GC journal head is not set, because it is the first GC
++ * invocation since mount.
++ */
++ err = switch_gc_head(c);
++ if (err)
++ goto out;
++ }
++
++ /* Write nodes to their new location. Use the first-fit strategy */
++ while (1) {
++ avail = c->leb_size - wbuf->offs - wbuf->used;
++ list_for_each_entry_safe(snod, tmp, &large, list) {
++ int new_lnum, new_offs;
++
++ if (avail < min)
++ break;
++
++ if (snod->len > avail)
++ /* This node does not fit */
++ continue;
++
++ cond_resched();
++
++ new_lnum = wbuf->lnum;
++ new_offs = wbuf->offs + wbuf->used;
++ err = ubifs_wbuf_write_nolock(wbuf, snod->node,
++ snod->len);
++
++ err = ubifs_tnc_replace(c, &snod->key, sleb->lnum,
++ snod->offs, new_lnum, new_offs,
++ snod->len);
++ if (err)
++ goto out;
++
++ avail = c->leb_size - wbuf->offs - wbuf->used;
++ list_del(&snod->list);
++ kfree(snod);
++ }
++
++ if (list_empty(&large))
++ break;
++
++ /*
++ * Waste the rest of the space in the LEB and switch to the
++ * next LEB.
++ */
++ err = switch_gc_head(c);
++ if (err)
++ goto out;
++ }
++
++ return 0;
++
++out:
++ list_for_each_entry_safe(snod, tmp, &large, list) {
++ list_del(&snod->list);
++ kfree(snod);
++ }
++ return err;
++}
++
++/**
++ * gc_sync_wbufs - sync write-buffers for GC.
++ * @c: UBIFS file-system description object
++ *
++ * We must guarantee that obsoleting nodes are on flash. Unfortunately they may
++ * be in a write-buffer instead. That is, a node could be written to a
++ * write-buffer, obsoleting another node in a LEB that is GC'd. If that LEB is
++ * erased before the write-buffer is sync'd and then there is an unclean
++ * unmount, then an existing node is lost. To avoid this, we sync all
++ * write-buffers.
++ *
++ * This function returns %0 on success or a negative error code on failure.
++ */
++static int gc_sync_wbufs(struct ubifs_info *c)
++{
++ int err, i;
++
++ for (i = 0; i < c->jhead_cnt; i++) {
++ if (i == GCHD)
++ continue;
++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
++/**
++ * ubifs_garbage_collect_leb - garbage-collect a logical eraseblock.
++ * @c: UBIFS file-system description object
++ * @lp: describes the LEB to garbage collect
++ *
++ * This function garbage-collects an LEB and returns one of the @LEB_FREED,
++ * @LEB_RETAINED, etc positive codes in case of success, %-EAGAIN if commit is
++ * required, and other negative error codes in case of failures.
++ */
++int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
++{
++ struct ubifs_scan_leb *sleb;
++ struct ubifs_scan_node *snod;
++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
++ int err = 0, lnum = lp->lnum;
++
++ ubifs_assert(c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 ||
++ c->need_recovery);
++ ubifs_assert(c->gc_lnum != lnum);
++ ubifs_assert(wbuf->lnum != lnum);
++
++ /*
++ * We scan the entire LEB even though we only really need to scan up to
++ * (c->leb_size - lp->free).
++ */
++ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
++ if (IS_ERR(sleb))
++ return PTR_ERR(sleb);
++
++ ubifs_assert(!list_empty(&sleb->nodes));
++ snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
++
++ if (snod->type == UBIFS_IDX_NODE) {
++ struct ubifs_gced_idx_leb *idx_gc;
++
++ dbg_gc("indexing LEB %d (free %d, dirty %d)",
++ lnum, lp->free, lp->dirty);
++ list_for_each_entry(snod, &sleb->nodes, list) {
++ struct ubifs_idx_node *idx = snod->node;
++ int level = le16_to_cpu(idx->level);
++
++ ubifs_assert(snod->type == UBIFS_IDX_NODE);
++ key_read(c, ubifs_idx_key(c, idx), &snod->key);
++ err = ubifs_dirty_idx_node(c, &snod->key, level, lnum,
++ snod->offs);
++ if (err)
++ goto out;
++ }
++
++ idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS);
++ if (!idx_gc) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ idx_gc->lnum = lnum;
++ idx_gc->unmap = 0;
++ list_add(&idx_gc->list, &c->idx_gc);
++
++ /*
++ * Don't release the LEB until after the next commit, because
++ * it may contain date which is needed for recovery. So
++ * although we freed this LEB, it will become usable only after
++ * the commit.
++ */
++ err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0,
++ LPROPS_INDEX, 1);
++ if (err)
++ goto out;
++ err = LEB_FREED_IDX;
++ } else {
++ dbg_gc("data LEB %d (free %d, dirty %d)",
++ lnum, lp->free, lp->dirty);
++
++ err = move_nodes(c, sleb);
++ if (err)
++ goto out;
++
++ err = gc_sync_wbufs(c);
++ if (err)
++ goto out;
++
++ err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0);
++ if (err)
++ goto out;
++
++ if (c->gc_lnum == -1) {
++ c->gc_lnum = lnum;
++ err = LEB_RETAINED;
++ } else {
++ err = ubifs_wbuf_sync_nolock(wbuf);
++ if (err)
++ goto out;
++
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ goto out;
++
++ err = LEB_FREED;
++ }
++ }
++
++out:
++ ubifs_scan_destroy(sleb);
++ return err;
++}
++
++/**
++ * ubifs_garbage_collect - UBIFS garbage collector.
++ * @c: UBIFS file-system description object
++ * @anyway: do GC even if there are free LEBs
++ *
++ * This function does out-of-place garbage collection. The return codes are:
++ * o positive LEB number if the LEB has been freed and may be used;
++ * o %-EAGAIN if the caller has to run commit;
++ * o %-ENOSPC if GC failed to make any progress;
++ * o other negative error codes in case of other errors.
++ *
++ * Garbage collector writes data to the journal when GC'ing data LEBs, and just
++ * marking indexing nodes dirty when GC'ing indexing LEBs. Thus, at some point
++ * commit may be required. But commit cannot be run from inside GC, because the
++ * caller might be holding the commit lock, so %-EAGAIN is returned instead;
++ * And this error code means that the caller has to run commit, and re-run GC
++ * if there is still no free space.
++ *
++ * There are many reasons why this function may return %-EAGAIN:
++ * o the log is full and there is no space to write an LEB reference for
++ * @c->gc_lnum;
++ * o the journal is too large and exceeds size limitations;
++ * o GC moved indexing LEBs, but they can be used only after the commit;
++ * o the shrinker fails to find clean znodes to free and requests the commit;
++ * o etc.
++ *
++ * Note, if the file-system is close to be full, this function may return
++ * %-EAGAIN infinitely, so the caller has to limit amount of re-invocations of
++ * the function. E.g., this happens if the limits on the journal size are too
++ * tough and GC writes too much to the journal before an LEB is freed. This
++ * might also mean that the journal is too large, and the TNC becomes to big,
++ * so that the shrinker is constantly called, finds not clean znodes to free,
++ * and requests commit. Well, this may also happen if the journal is all right,
++ * but another kernel process consumes too much memory. Anyway, infinite
++ * %-EAGAIN may happen, but in some extreme/misconfiguration cases.
++ */
++int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
++{
++ int i, err, ret, min_space = c->dead_wm;
++ struct ubifs_lprops lp;
++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
++
++ ubifs_assert_cmt_locked(c);
++
++ if (ubifs_gc_should_commit(c))
++ return -EAGAIN;
++
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ /* We expect the write-buffer to be empty on entry */
++ ubifs_assert(!wbuf->used);
++
++ for (i = 0; ; i++) {
++ int space_before = c->leb_size - wbuf->offs - wbuf->used;
++ int space_after;
++
++ cond_resched();
++
++ /* Give the commit an opportunity to run */
++ if (ubifs_gc_should_commit(c)) {
++ ret = -EAGAIN;
++ break;
++ }
++
++ if (i > SOFT_LEBS_LIMIT && !list_empty(&c->idx_gc)) {
++ /*
++ * We've done enough iterations. Indexing LEBs were
++ * moved and will be available after the commit.
++ */
++ dbg_gc("soft limit, some index LEBs GC'ed, -EAGAIN");
++ ubifs_commit_required(c);
++ ret = -EAGAIN;
++ break;
++ }
++
++ if (i > HARD_LEBS_LIMIT) {
++ /*
++ * We've moved too many LEBs and have not made
++ * progress, give up.
++ */
++ dbg_gc("hard limit, -ENOSPC");
++ ret = -ENOSPC;
++ break;
++ }
++
++ /*
++ * Empty and freeable LEBs can turn up while we waited for
++ * the wbuf lock, or while we have been running GC. In that
++ * case, we should just return one of those instead of
++ * continuing to GC dirty LEBs. Hence we request
++ * 'ubifs_find_dirty_leb()' to return an empty LEB if it can.
++ */
++ ret = ubifs_find_dirty_leb(c, &lp, min_space, anyway ? 0 : 1);
++ if (ret) {
++ if (ret == -ENOSPC)
++ dbg_gc("no more dirty LEBs");
++ break;
++ }
++
++ dbg_gc("found LEB %d: free %d, dirty %d, sum %d "
++ "(min. space %d)", lp.lnum, lp.free, lp.dirty,
++ lp.free + lp.dirty, min_space);
++
++ if (lp.free + lp.dirty == c->leb_size) {
++ /* An empty LEB was returned */
++ dbg_gc("LEB %d is free, return it", lp.lnum);
++ /*
++ * ubifs_find_dirty_leb() doesn't return freeable index
++ * LEBs.
++ */
++ ubifs_assert(!(lp.flags & LPROPS_INDEX));
++ if (lp.free != c->leb_size) {
++ /*
++ * Write buffers must be sync'd before
++ * unmapping freeable LEBs, because one of them
++ * may contain data which obsoletes something
++ * in 'lp.pnum'.
++ */
++ ret = gc_sync_wbufs(c);
++ if (ret)
++ goto out;
++ ret = ubifs_change_one_lp(c, lp.lnum,
++ c->leb_size, 0, 0, 0,
++ 0);
++ if (ret)
++ goto out;
++ }
++ ret = ubifs_leb_unmap(c, lp.lnum);
++ if (ret)
++ goto out;
++ ret = lp.lnum;
++ break;
++ }
++
++ space_before = c->leb_size - wbuf->offs - wbuf->used;
++ if (wbuf->lnum == -1)
++ space_before = 0;
++
++ ret = ubifs_garbage_collect_leb(c, &lp);
++ if (ret < 0) {
++ if (ret == -EAGAIN || ret == -ENOSPC) {
++ /*
++ * These codes are not errors, so we have to
++ * return the LEB to lprops. But if the
++ * 'ubifs_return_leb()' function fails, its
++ * failure code is propagated to the caller
++ * instead of the original '-EAGAIN' or
++ * '-ENOSPC'.
++ */
++ err = ubifs_return_leb(c, lp.lnum);
++ if (err)
++ ret = err;
++ break;
++ }
++ goto out;
++ }
++
++ if (ret == LEB_FREED) {
++ /* An LEB has been freed and is ready for use */
++ dbg_gc("LEB %d freed, return", lp.lnum);
++ ret = lp.lnum;
++ break;
++ }
++
++ if (ret == LEB_FREED_IDX) {
++ /*
++ * This was an indexing LEB and it cannot be
++ * immediately used. And instead of requesting the
++ * commit straight away, we try to garbage collect some
++ * more.
++ */
++ dbg_gc("indexing LEB %d freed, continue", lp.lnum);
++ continue;
++ }
++
++ ubifs_assert(ret == LEB_RETAINED);
++ space_after = c->leb_size - wbuf->offs - wbuf->used;
++ dbg_gc("LEB %d retained, freed %d bytes", lp.lnum,
++ space_after - space_before);
++
++ if (space_after > space_before) {
++ /* GC makes progress, keep working */
++ min_space >>= 1;
++ if (min_space < c->dead_wm)
++ min_space = c->dead_wm;
++ continue;
++ }
++
++ dbg_gc("did not make progress");
++
++ /*
++ * GC moved an LEB bud have not done any progress. This means
++ * that the previous GC head LEB contained too few free space
++ * and the LEB which was GC'ed contained only large nodes which
++ * did not fit that space.
++ *
++ * We can do 2 things:
++ * 1. pick another LEB in a hope it'll contain a small node
++ * which will fit the space we have at the end of current GC
++ * head LEB, but there is no guarantee, so we try this out
++ * unless we have already been working for too long;
++ * 2. request an LEB with more dirty space, which will force
++ * 'ubifs_find_dirty_leb()' to start scanning the lprops
++ * table, instead of just picking one from the heap
++ * (previously it already picked the dirtiest LEB).
++ */
++ if (i < SOFT_LEBS_LIMIT) {
++ dbg_gc("try again");
++ continue;
++ }
++
++ min_space <<= 1;
++ if (min_space > c->dark_wm)
++ min_space = c->dark_wm;
++ dbg_gc("set min. space to %d", min_space);
++ }
++
++ if (ret == -ENOSPC && !list_empty(&c->idx_gc)) {
++ dbg_gc("no space, some index LEBs GC'ed, -EAGAIN");
++ ubifs_commit_required(c);
++ ret = -EAGAIN;
++ }
++
++ err = ubifs_wbuf_sync_nolock(wbuf);
++ if (!err)
++ err = ubifs_leb_unmap(c, c->gc_lnum);
++ if (err)
++ ret = err;
++ mutex_unlock(&wbuf->io_mutex);
++ return ret;
++
++out:
++ ubifs_assert(ret < 0);
++ ubifs_assert(ret != -ENOSPC && ret != -EAGAIN);
++ ubifs_wbuf_sync_nolock(wbuf);
++ mutex_unlock(&wbuf->io_mutex);
++ ubifs_return_leb(c, lp.lnum);
++ return ret;
++}
++
++/**
++ * ubifs_gc_start_commit - garbage collection at start of commit.
++ * @c: UBIFS file-system description object
++ *
++ * If a LEB has only dirty and free space, then we may safely unmap it and make
++ * it free. Note, we cannot do this with indexing LEBs because dirty space may
++ * correspond index nodes that are required for recovery. In that case, the
++ * LEB cannot be unmapped until after the next commit.
++ *
++ * This function returns %0 upon success and a negative error code upon failure.
++ */
++int ubifs_gc_start_commit(struct ubifs_info *c)
++{
++ struct ubifs_gced_idx_leb *idx_gc;
++ const struct ubifs_lprops *lp;
++ int err = 0, flags;
++
++ ubifs_get_lprops(c);
++
++ /*
++ * Unmap (non-index) freeable LEBs. Note that recovery requires that all
++ * wbufs are sync'd before this, which is done in 'do_commit()'.
++ */
++ while (1) {
++ lp = ubifs_fast_find_freeable(c);
++ if (unlikely(IS_ERR(lp))) {
++ err = PTR_ERR(lp);
++ goto out;
++ }
++ if (!lp)
++ break;
++ ubifs_assert(!(lp->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lp->flags & LPROPS_INDEX));
++ err = ubifs_leb_unmap(c, lp->lnum);
++ if (err)
++ goto out;
++ lp = ubifs_change_lp(c, lp, c->leb_size, 0, lp->flags, 0);
++ if (unlikely(IS_ERR(lp))) {
++ err = PTR_ERR(lp);
++ goto out;
++ }
++ ubifs_assert(!(lp->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lp->flags & LPROPS_INDEX));
++ }
++
++ /* Mark GC'd index LEBs OK to unmap after this commit finishes */
++ list_for_each_entry(idx_gc, &c->idx_gc, list)
++ idx_gc->unmap = 1;
++
++ /* Record index freeable LEBs for unmapping after commit */
++ while (1) {
++ lp = ubifs_fast_find_frdi_idx(c);
++ if (unlikely(IS_ERR(lp))) {
++ err = PTR_ERR(lp);
++ goto out;
++ }
++ if (!lp)
++ break;
++ idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS);
++ if (!idx_gc) {
++ err = -ENOMEM;
++ goto out;
++ }
++ ubifs_assert(!(lp->flags & LPROPS_TAKEN));
++ ubifs_assert(lp->flags & LPROPS_INDEX);
++ /* Don't release the LEB until after the next commit */
++ flags = (lp->flags | LPROPS_TAKEN) ^ LPROPS_INDEX;
++ lp = ubifs_change_lp(c, lp, c->leb_size, 0, flags, 1);
++ if (unlikely(IS_ERR(lp))) {
++ err = PTR_ERR(lp);
++ kfree(idx_gc);
++ goto out;
++ }
++ ubifs_assert(lp->flags & LPROPS_TAKEN);
++ ubifs_assert(!(lp->flags & LPROPS_INDEX));
++ idx_gc->lnum = lp->lnum;
++ idx_gc->unmap = 1;
++ list_add(&idx_gc->list, &c->idx_gc);
++ }
++out:
++ ubifs_release_lprops(c);
++ return err;
++}
++
++/**
++ * ubifs_gc_end_commit - garbage collection at end of commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function completes out-of-place garbage collection of index LEBs.
++ */
++int ubifs_gc_end_commit(struct ubifs_info *c)
++{
++ struct ubifs_gced_idx_leb *idx_gc, *tmp;
++ struct ubifs_wbuf *wbuf;
++ int err = 0;
++
++ wbuf = &c->jheads[GCHD].wbuf;
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ list_for_each_entry_safe(idx_gc, tmp, &c->idx_gc, list)
++ if (idx_gc->unmap) {
++ dbg_gc("LEB %d", idx_gc->lnum);
++ err = ubifs_leb_unmap(c, idx_gc->lnum);
++ if (err)
++ goto out;
++ err = ubifs_change_one_lp(c, idx_gc->lnum, LPROPS_NC,
++ LPROPS_NC, 0, LPROPS_TAKEN, -1);
++ if (err)
++ goto out;
++ list_del(&idx_gc->list);
++ kfree(idx_gc);
++ }
++out:
++ mutex_unlock(&wbuf->io_mutex);
++ return err;
++}
++
++/**
++ * ubifs_destroy_idx_gc - destroy idx_gc list.
++ * @c: UBIFS file-system description object
++ *
++ * This function destroys the idx_gc list. It is called when unmounting or
++ * remounting read-only so locks are not needed.
++ */
++void ubifs_destroy_idx_gc(struct ubifs_info *c)
++{
++ while (!list_empty(&c->idx_gc)) {
++ struct ubifs_gced_idx_leb *idx_gc;
++
++ idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb,
++ list);
++ c->idx_gc_cnt -= 1;
++ list_del(&idx_gc->list);
++ kfree(idx_gc);
++ }
++
++}
++
++/**
++ * ubifs_get_idx_gc_leb - get a LEB from GC'd index LEB list.
++ * @c: UBIFS file-system description object
++ *
++ * Called during start commit so locks are not needed.
++ */
++int ubifs_get_idx_gc_leb(struct ubifs_info *c)
++{
++ struct ubifs_gced_idx_leb *idx_gc;
++ int lnum;
++
++ if (list_empty(&c->idx_gc))
++ return -ENOSPC;
++ idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, list);
++ lnum = idx_gc->lnum;
++ /* c->idx_gc_cnt is updated by the caller when lprops are updated */
++ list_del(&idx_gc->list);
++ kfree(idx_gc);
++ return lnum;
++}
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/io.c avr32-2.6/fs/ubifs/io.c
+--- linux-2.6.25.6/fs/ubifs/io.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/io.c 2008-06-12 15:09:45.367815766 +0200
+@@ -0,0 +1,921 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ * Copyright (C) 2006, 2007 University of Szeged, Hungary
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ * Zoltan Sogor
++ */
++
++/*
++ * This file implements UBIFS I/O subsystem which provides various I/O-related
++ * helper functions (reading/writing/checking/validating nodes) and implements
++ * write-buffering support. Write buffers help to save space which otherwise
++ * would have been wasted for padding to the nearest minimal I/O unit boundary.
++ * Instead, data first goes to the write-buffer and is flushed when the
++ * buffer is full or when it is not used for some time (by timer). This is
++ * similarto the mechanism is used by JFFS2.
++ *
++ * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by
++ * mutexes defined inside these objects. Since sometimes upper-level code
++ * has to lock the write-buffer (e.g. journal space reservation code), many
++ * functions related to write-buffers have "nolock" suffix which means that the
++ * caller has to lock the write-buffer before calling this function.
++ *
++ * UBIFS stores nodes at 64 bit-aligned addresses. If the node length is not
++ * aligned, UBIFS starts the next node from the aligned address, and the padded
++ * bytes may contain any rubbish. In other words, UBIFS does not put padding
++ * bytes in those small gaps. Common headers of nodes store real node lengths,
++ * not aligned lengths. Indexing nodes also store real lengths in branches.
++ *
++ * UBIFS uses padding when it pads to the next min. I/O unit. In this case it
++ * uses padding nodes or padding bytes, if the padding node does not fit.
++ *
++ * All UBIFS nodes are protected by CRC checksums and UBIFS checks all nodes
++ * every time they are read from the flash media.
++ */
++
++#include <linux/crc32.h>
++#include "ubifs.h"
++
++/**
++ * ubifs_check_node - check node.
++ * @c: UBIFS file-system description object
++ * @buf: node to check
++ * @lnum: logical eraseblock number
++ * @offs: offset within the logical eraseblock
++ * @quiet: print no messages
++ *
++ * This function checks node magic number and CRC checksum. This function also
++ * validates node length to prevent UBIFS from becoming crazy when an attacker
++ * feeds it a file-system image with incorrect nodes. For example, too large
++ * node length in the common header could cause UBIFS to read memory outside of
++ * allocated buffer when checking the CRC checksum.
++ *
++ * This function returns zero in case of success %-EUCLEAN in case of bad CRC
++ * or magic.
++ */
++int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
++ int offs, int quiet)
++{
++ int err = -EINVAL, type, node_len;
++ uint32_t crc, node_crc, magic;
++ const struct ubifs_ch *ch = buf;
++
++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
++ ubifs_assert(!(offs & 7) && offs < c->leb_size);
++
++ magic = le32_to_cpu(ch->magic);
++ if (magic != UBIFS_NODE_MAGIC) {
++ if (!quiet)
++ ubifs_err("bad magic %#08x, expected %#08x",
++ magic, UBIFS_NODE_MAGIC);
++ err = -EUCLEAN;
++ goto out;
++ }
++
++ type = ch->node_type;
++ if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
++ if (!quiet)
++ ubifs_err("bad node type %d", type);
++ goto out;
++ }
++
++ node_len = le32_to_cpu(ch->len);
++ if (node_len + offs > c->leb_size)
++ goto out_len;
++
++ if (c->ranges[type].max_len == 0) {
++ if (node_len != c->ranges[type].len)
++ goto out_len;
++ } else if (node_len < c->ranges[type].min_len ||
++ node_len > c->ranges[type].max_len)
++ goto out_len;
++
++ crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
++ node_crc = le32_to_cpu(ch->crc);
++ if (crc != node_crc) {
++ if (!quiet)
++ ubifs_err("bad CRC: calculated %#08x, read %#08x",
++ crc, node_crc);
++ err = -EUCLEAN;
++ goto out;
++ }
++
++ return 0;
++
++out_len:
++ if (!quiet)
++ ubifs_err("bad node length %d", node_len);
++out:
++ if (!quiet) {
++ ubifs_err("bad node at LEB %d:%d", lnum, offs);
++ dbg_dump_node(c, buf);
++ dbg_dump_stack();
++ }
++ return err;
++}
++
++/**
++ * ubifs_pad - pad flash space.
++ * @c: UBIFS file-system description object
++ * @buf: buffer to put padding to
++ * @pad: how many bytes to pad
++ *
++ * The flash media obliges us to write only in chunks of %c->min_io_size and
++ * when we have to write less data we add padding node to the write-buffer and
++ * pad it to the next minimal I/O unit's boundary. Padding nodes help when the
++ * media is being scanned. If the amount of wasted space is not enough to fit a
++ * padding node which takes %UBIFS_PAD_NODE_SZ bytes, we write padding bytes
++ * pattern (%UBIFS_PADDING_BYTE).
++ *
++ * Padding nodes are also used to fill gaps when the "commit-in-gaps" method is
++ * used.
++ */
++void ubifs_pad(const struct ubifs_info *c, void *buf, int pad)
++{
++ uint32_t crc;
++
++ ubifs_assert(pad >= 0 && !(pad & 7));
++
++ if (pad >= UBIFS_PAD_NODE_SZ) {
++ struct ubifs_ch *ch = buf;
++ struct ubifs_pad_node *pad_node = buf;
++
++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
++ ch->node_type = UBIFS_PAD_NODE;
++ ch->group_type = UBIFS_NO_NODE_GROUP;
++ ch->padding[0] = ch->padding[1] = 0;
++ ch->sqnum = 0;
++ ch->len = cpu_to_le32(UBIFS_PAD_NODE_SZ);
++ pad -= UBIFS_PAD_NODE_SZ;
++ pad_node->pad_len = cpu_to_le32(pad);
++ crc = crc32(UBIFS_CRC32_INIT, buf + 8, UBIFS_PAD_NODE_SZ - 8);
++ ch->crc = cpu_to_le32(crc);
++ memset(buf + UBIFS_PAD_NODE_SZ, 0, pad);
++ } else if (pad > 0)
++ /* Too little space, padding node won't fit */
++ memset(buf, UBIFS_PADDING_BYTE, pad);
++}
++
++/**
++ * next_sqnum - get next sequence number.
++ * @c: UBIFS file-system description object
++ */
++static unsigned long long next_sqnum(struct ubifs_info *c)
++{
++ unsigned long long sqnum;
++
++ spin_lock(&c->cnt_lock);
++ sqnum = ++c->max_sqnum;
++ spin_unlock(&c->cnt_lock);
++
++ if (unlikely(sqnum >= SQNUM_WARN_WATERMARK)) {
++ if (sqnum >= SQNUM_WATERMARK) {
++ ubifs_err("sequence number overflow %llu, end of life",
++ sqnum);
++ ubifs_ro_mode(c, -EINVAL);
++ }
++ ubifs_warn("running out of sequence numbers, end of life soon");
++ }
++
++ return sqnum;
++}
++
++/**
++ * ubifs_prepare_node - prepare node to be written to flash.
++ * @c: UBIFS file-system description object
++ * @node: the node to pad
++ * @len: node length
++ * @pad: if the buffer has to be padded
++ *
++ * This function prepares node at @node to be written to the media - it
++ * calculates node CRC, fills the common header, and adds proper padding up to
++ * the next minimum I/O unit if @pad is not zero.
++ */
++void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad)
++{
++ uint32_t crc;
++ struct ubifs_ch *ch = node;
++ unsigned long long sqnum = next_sqnum(c);
++
++ ubifs_assert(len >= UBIFS_CH_SZ);
++
++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
++ ch->len = cpu_to_le32(len);
++ ch->group_type = UBIFS_NO_NODE_GROUP;
++ ch->sqnum = cpu_to_le64(sqnum);
++ ch->padding[0] = ch->padding[1] = 0;
++ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);
++ ch->crc = cpu_to_le32(crc);
++
++ if (pad) {
++ len = ALIGN(len, 8);
++ pad = ALIGN(len, c->min_io_size) - len;
++ ubifs_pad(c, node + len, pad);
++ }
++}
++
++/**
++ * ubifs_prep_grp_node - prepare node of a group to be written to flash.
++ * @c: UBIFS file-system description object
++ * @node: the node to pad
++ * @len: node length
++ * @last: indicates the last node of the group
++ *
++ * This function prepares node at @node to be written to the media - it
++ * calculates node CRC and fills the common header.
++ */
++void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last)
++{
++ uint32_t crc;
++ struct ubifs_ch *ch = node;
++ unsigned long long sqnum = next_sqnum(c);
++
++ ubifs_assert(len >= UBIFS_CH_SZ);
++
++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
++ ch->len = cpu_to_le32(len);
++ if (last)
++ ch->group_type = UBIFS_LAST_OF_NODE_GROUP;
++ else
++ ch->group_type = UBIFS_IN_NODE_GROUP;
++ ch->sqnum = cpu_to_le64(sqnum);
++ ch->padding[0] = ch->padding[1] = 0;
++ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);
++ ch->crc = cpu_to_le32(crc);
++}
++
++/**
++ * wbuf_timer_callback - write-buffer timer callback function.
++ * @data: timer data (write-buffer descriptor)
++ *
++ * This function is called when the write-buffer timer expires.
++ */
++static void wbuf_timer_callback_nolock(unsigned long data)
++{
++ struct ubifs_wbuf *wbuf = (struct ubifs_wbuf *)data;
++
++ wbuf->need_sync = 1;
++ wbuf->c->need_wbuf_sync = 1;
++ ubifs_wake_up_bgt(wbuf->c);
++}
++
++/**
++ * new_wbuf_timer - start new write-buffer timer.
++ * @wbuf: write-buffer descriptor
++ */
++static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
++{
++ ubifs_assert(!timer_pending(&wbuf->timer));
++
++ if (!wbuf->timeout)
++ return;
++
++ wbuf->timer.expires = jiffies + wbuf->timeout;
++ add_timer(&wbuf->timer);
++}
++
++/**
++ * cancel_wbuf_timer - cancel write-buffer timer.
++ * @wbuf: write-buffer descriptor
++ */
++static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
++{
++ /*
++ * If the syncer is waiting for the lock (from the background thread's
++ * context) and another task is changing write-buffer then the syncing
++ * should be canceled.
++ */
++ wbuf->need_sync = 0;
++ del_timer(&wbuf->timer);
++}
++
++/**
++ * ubifs_wbuf_sync_nolock - synchronize write-buffer.
++ * @wbuf: write-buffer to synchronize
++ *
++ * This function synchronizes write-buffer @buf and returns zero in case of
++ * success or a negative error code in case of failure.
++ */
++int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
++{
++ struct ubifs_info *c = wbuf->c;
++ int err, dirt;
++
++ cancel_wbuf_timer_nolock(wbuf);
++ if (!wbuf->used || wbuf->lnum == -1)
++ /* Write-buffer is empty or not seeked */
++ return 0;
++
++ dbg_io("LEB %d:%d, %d bytes",
++ wbuf->lnum, wbuf->offs, wbuf->used);
++ ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
++ ubifs_assert(!(wbuf->avail & 7));
++ ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
++
++ if (c->ro_media)
++ return -EROFS;
++
++ ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
++ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
++ c->min_io_size, wbuf->dtype);
++ if (err) {
++ ubifs_err("cannot write %d bytes to LEB %d:%d",
++ c->min_io_size, wbuf->lnum, wbuf->offs);
++ dbg_dump_stack();
++ return err;
++ }
++
++ dirt = wbuf->avail;
++
++ spin_lock(&wbuf->lock);
++ wbuf->offs += c->min_io_size;
++ wbuf->avail = c->min_io_size;
++ wbuf->used = 0;
++ wbuf->next_ino = 0;
++ spin_unlock(&wbuf->lock);
++
++ if (wbuf->sync_callback)
++ err = wbuf->sync_callback(c, wbuf->lnum,
++ c->leb_size - wbuf->offs, dirt);
++ return err;
++}
++
++/**
++ * ubifs_wbuf_seek_nolock - seek write-buffer.
++ * @wbuf: write-buffer
++ * @lnum: logical eraseblock number to seek to
++ * @offs: logical eraseblock offset to seek to
++ * @dtype: data type
++ *
++ * This function targets the write buffer to logical eraseblock @lnum:@offs.
++ * The write-buffer is synchronized if it is not empty. Returns zero in case of
++ * success and a negative error code in case of failure.
++ */
++int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
++ int dtype)
++{
++ const struct ubifs_info *c = wbuf->c;
++
++ dbg_io("LEB %d:%d", lnum, offs);
++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
++ ubifs_assert(offs >= 0 && offs <= c->leb_size);
++ ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
++ ubifs_assert(lnum != wbuf->lnum);
++
++ if (wbuf->used > 0) {
++ int err = ubifs_wbuf_sync_nolock(wbuf);
++
++ if (err)
++ return err;
++ }
++
++ spin_lock(&wbuf->lock);
++ wbuf->lnum = lnum;
++ wbuf->offs = offs;
++ wbuf->avail = c->min_io_size;
++ wbuf->used = 0;
++ spin_unlock(&wbuf->lock);
++ wbuf->dtype = dtype;
++
++ return 0;
++}
++
++/**
++ * ubifs_bg_wbufs_sync - synchronize write-buffers.
++ * @c: UBIFS file-system description object
++ *
++ * This function is called by background thread to synchronize write-buffers.
++ * Returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++int ubifs_bg_wbufs_sync(struct ubifs_info *c)
++{
++ int err, i;
++
++ if (!c->need_wbuf_sync)
++ return 0;
++ c->need_wbuf_sync = 0;
++
++ if (c->ro_media) {
++ err = -EROFS;
++ goto out_timers;
++ }
++
++ dbg_io("synchronize");
++ for (i = 0; i < c->jhead_cnt; i++) {
++ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
++
++ cond_resched();
++
++ /*
++ * If the mutex is locked then wbuf is being changed, so
++ * synchronization is not necessary.
++ */
++ if (mutex_is_locked(&wbuf->io_mutex))
++ continue;
++
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ if (!wbuf->need_sync) {
++ mutex_unlock(&wbuf->io_mutex);
++ continue;
++ }
++
++ err = ubifs_wbuf_sync_nolock(wbuf);
++ mutex_unlock(&wbuf->io_mutex);
++ if (err) {
++ ubifs_err("cannot sync write-buffer, error %d", err);
++ ubifs_ro_mode(c, err);
++ goto out_timers;
++ }
++ }
++
++ return 0;
++
++out_timers:
++ /* Cancel all timers to prevent repeated errors */
++ for (i = 0; i < c->jhead_cnt; i++) {
++ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
++
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ cancel_wbuf_timer_nolock(wbuf);
++ mutex_unlock(&wbuf->io_mutex);
++ }
++ return err;
++}
++
++/**
++ * ubifs_wbuf_write_nolock - write data to flash via write-buffer.
++ * @wbuf: write-buffer
++ * @buf: node to write
++ * @len: node length
++ *
++ * This function writes data to flash via write-buffer @wbuf. This means that
++ * the last piece of the node won't reach the flash media immediately if it
++ * does not take whole minimal I/O unit. Instead, the node will sit in RAM
++ * until the write-buffer is synchronized (e.g., by timer).
++ *
++ * This function returns zero in case of success and a negative error code in
++ * case of failure. If the node cannot be written because there is no more
++ * space in this logical eraseblock, %-ENOSPC is returned.
++ */
++int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
++{
++ struct ubifs_info *c = wbuf->c;
++ int err, written, n, aligned_len = ALIGN(len, 8), offs;
++
++ dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len,
++ dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum,
++ wbuf->offs + wbuf->used);
++ ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
++ ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
++ ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
++ ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
++ ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
++
++ if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
++ err = -ENOSPC;
++ goto out;
++ }
++
++ cancel_wbuf_timer_nolock(wbuf);
++
++ if (c->ro_media)
++ return -EROFS;
++
++ if (aligned_len <= wbuf->avail) {
++ /*
++ * The node is not very large and fits entirely within
++ * write-buffer.
++ */
++ memcpy(wbuf->buf + wbuf->used, buf, len);
++
++ if (aligned_len == wbuf->avail) {
++ dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum,
++ wbuf->offs);
++ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
++ wbuf->offs, c->min_io_size,
++ wbuf->dtype);
++ if (err)
++ goto out;
++
++ spin_lock(&wbuf->lock);
++ wbuf->offs += c->min_io_size;
++ wbuf->avail = c->min_io_size;
++ wbuf->used = 0;
++ wbuf->next_ino = 0;
++ spin_unlock(&wbuf->lock);
++ } else {
++ spin_lock(&wbuf->lock);
++ wbuf->avail -= aligned_len;
++ wbuf->used += aligned_len;
++ spin_unlock(&wbuf->lock);
++ }
++
++ goto exit;
++ }
++
++ /*
++ * The node is large enough and does not fit entirely within current
++ * minimal I/O unit. We have to fill and flush write-buffer and switch
++ * to the next min. I/O unit.
++ */
++ dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs);
++ memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
++ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
++ c->min_io_size, wbuf->dtype);
++ if (err)
++ goto out;
++
++ offs = wbuf->offs + c->min_io_size;
++ len -= wbuf->avail;
++ aligned_len -= wbuf->avail;
++ written = wbuf->avail;
++
++ /*
++ * The remaining data may take more whole min. I/O units, so write the
++ * remains multiple to min. I/O unit size directly to the flash media.
++ * We align node length to 8-byte boundary because we anyway flash wbuf
++ * if the remaining space is less than 8 bytes.
++ */
++ n = aligned_len >> c->min_io_shift;
++ if (n) {
++ n <<= c->min_io_shift;
++ dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, offs);
++ err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written, offs, n,
++ wbuf->dtype);
++ if (err)
++ goto out;
++ offs += n;
++ aligned_len -= n;
++ len -= n;
++ written += n;
++ }
++
++ spin_lock(&wbuf->lock);
++ if (aligned_len)
++ /*
++ * And now we have what's left and what does not take whole
++ * min. I/O unit, so write it to the write-buffer and we are
++ * done.
++ */
++ memcpy(wbuf->buf, buf + written, len);
++
++ wbuf->offs = offs;
++ wbuf->used = aligned_len;
++ wbuf->avail = c->min_io_size - aligned_len;
++ wbuf->next_ino = 0;
++ spin_unlock(&wbuf->lock);
++
++exit:
++ if (wbuf->sync_callback) {
++ int free = c->leb_size - wbuf->offs - wbuf->used;
++
++ err = wbuf->sync_callback(c, wbuf->lnum, free, 0);
++ if (err)
++ goto out;
++ }
++
++ if (wbuf->used)
++ new_wbuf_timer_nolock(wbuf);
++
++ return 0;
++
++out:
++ ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
++ len, wbuf->lnum, wbuf->offs, err);
++ dbg_dump_node(c, buf);
++ dbg_dump_stack();
++ dbg_dump_leb(c, wbuf->lnum);
++ return err;
++}
++
++/**
++ * ubifs_write_node - write node to the media.
++ * @c: UBIFS file-system description object
++ * @buf: the node to write
++ * @len: node length
++ * @lnum: logical eraseblock number
++ * @offs: offset within the logical eraseblock
++ * @dtype: node life-time hint (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
++ *
++ * This function automatically fills node magic number, assigns sequence
++ * number, and calculates node CRC checksum. The length of the @buf buffer has
++ * to be aligned to the minimal I/O unit size. This function automatically
++ * appends padding node and padding bytes if needed. Returns zero in case of
++ * success and a negative error code in case of failure.
++ */
++int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
++ int offs, int dtype)
++{
++ int err, buf_len = ALIGN(len, c->min_io_size);
++
++ dbg_io("LEB %d:%d, %s, length %d (aligned %d)",
++ lnum, offs, dbg_ntype(((struct ubifs_ch *)buf)->node_type), len,
++ buf_len);
++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
++ ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
++
++ if (c->ro_media)
++ return -EROFS;
++
++ ubifs_prepare_node(c, buf, len, 1);
++ err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype);
++ if (err) {
++ ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
++ buf_len, lnum, offs, err);
++ dbg_dump_node(c, buf);
++ dbg_dump_stack();
++ }
++
++ return err;
++}
++
++/**
++ * ubifs_read_node_wbuf - read node from the media or write-buffer.
++ * @wbuf: wbuf to check for un-written data
++ * @buf: buffer to read to
++ * @type: node type
++ * @len: node length
++ * @lnum: logical eraseblock number
++ * @offs: offset within the logical eraseblock
++ *
++ * This function reads a node of known type and length, checks it and stores
++ * in @buf. If the node partially or fully sits in the write-buffer, this
++ * function takes data from the buffer, otherwise it reads the flash media.
++ * Returns zero in case of success, %-EUCLEAN if CRC mismatched and a negative
++ * error code in case of failure.
++ */
++int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
++ int lnum, int offs)
++{
++ const struct ubifs_info *c = wbuf->c;
++ int err, rlen, overlap;
++ struct ubifs_ch *ch = buf;
++
++ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
++ ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
++ ubifs_assert(!(offs & 7) && offs < c->leb_size);
++ ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
++
++ spin_lock(&wbuf->lock);
++ overlap = (lnum == wbuf->lnum && offs + len > wbuf->offs);
++ if (!overlap) {
++ /* We may safely unlock the write-buffer and read the data */
++ spin_unlock(&wbuf->lock);
++ return ubifs_read_node(c, buf, type, len, lnum, offs);
++ }
++
++ /* Don't read under wbuf */
++ rlen = wbuf->offs - offs;
++ if (rlen < 0)
++ rlen = 0;
++
++ /* Copy the rest from the write-buffer */
++ memcpy(buf + rlen, wbuf->buf + offs + rlen - wbuf->offs, len - rlen);
++ spin_unlock(&wbuf->lock);
++
++ if (rlen > 0) {
++ /* Read everything that goes before write-buffer */
++ err = ubi_read(c->ubi, lnum, buf, offs, rlen);
++ if (err && err != -EBADMSG) {
++ ubifs_err("failed to read node %d from LEB %d:%d, "
++ "error %d", type, lnum, offs, err);
++ dbg_dump_stack();
++ return err;
++ }
++ }
++
++ err = ubifs_check_node(c, buf, lnum, offs, 0);
++ if (err) {
++ ubifs_err("expected node type %d", type);
++ return err;
++ }
++
++ if (type != ch->node_type) {
++ ubifs_err("bad node type (%d but expected %d)",
++ ch->node_type, type);
++ goto out;
++ }
++
++ rlen = le32_to_cpu(ch->len);
++ if (rlen != len) {
++ ubifs_err("bad node length %d, expected %d", rlen, len);
++ goto out;
++ }
++
++ return 0;
++
++out:
++ ubifs_err("bad node at LEB %d:%d", lnum, offs);
++ dbg_dump_node(c, buf);
++ dbg_dump_stack();
++ return -EINVAL;
++}
++
++/**
++ * ubifs_read_node - read node.
++ * @c: UBIFS file-system description object
++ * @buf: buffer to read to
++ * @type: node type
++ * @len: node length (not aligned)
++ * @lnum: logical eraseblock number
++ * @offs: offset within the logical eraseblock
++ *
++ * This function reads a node of known type and and length, checks it and
++ * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched
++ * and a negative error code in case of failure.
++ */
++int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
++ int lnum, int offs)
++{
++ int err, l;
++ struct ubifs_ch *ch = buf;
++
++ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
++ ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
++ ubifs_assert(!(offs & 7) && offs < c->leb_size);
++ ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
++
++ err = ubi_read(c->ubi, lnum, buf, offs, len);
++ if (err && err != -EBADMSG) {
++ ubifs_err("cannot read node %d from LEB %d:%d, error %d",
++ type, lnum, offs, err);
++ return err;
++ }
++
++ err = ubifs_check_node(c, buf, lnum, offs, 0);
++ if (err) {
++ ubifs_err("expected node type %d", type);
++ return err;
++ }
++
++ if (type != ch->node_type) {
++ ubifs_err("bad node type (%d but expected %d)",
++ ch->node_type, type);
++ goto out;
++ }
++
++ l = le32_to_cpu(ch->len);
++ if (l != len) {
++ ubifs_err("bad node length %d, expected %d", l, len);
++ goto out;
++ }
++
++ return 0;
++
++out:
++ ubifs_err("bad node at LEB %d:%d", lnum, offs);
++ dbg_dump_node(c, buf);
++ dbg_dump_stack();
++ return -EINVAL;
++}
++
++/**
++ * ubifs_wbuf_init - initialize write-buffer.
++ * @c: UBIFS file-system description object
++ * @wbuf: write-buffer to initialize
++ *
++ * This function initializes write buffer. Returns zero in case of success
++ * %-ENOMEM in case of failure.
++ */
++int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
++{
++ size_t size;
++
++ wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL);
++ if (!wbuf->buf)
++ return -ENOMEM;
++
++ size = (c->min_io_size / UBIFS_CH_SZ + 1) * sizeof(ino_t);
++ wbuf->inodes = kmalloc(size, GFP_KERNEL);
++ if (!wbuf->inodes) {
++ kfree(wbuf->buf);
++ wbuf->buf = NULL;
++ return -ENOMEM;
++ }
++
++ wbuf->used = 0;
++ wbuf->lnum = wbuf->offs = -1;
++ wbuf->avail = c->min_io_size;
++ wbuf->dtype = UBI_UNKNOWN;
++ wbuf->sync_callback = NULL;
++ mutex_init(&wbuf->io_mutex);
++ spin_lock_init(&wbuf->lock);
++
++ wbuf->c = c;
++ init_timer(&wbuf->timer);
++ wbuf->timer.function = wbuf_timer_callback_nolock;
++ wbuf->timer.data = (unsigned long)wbuf;
++ wbuf->timeout = DEFAULT_WBUF_TIMEOUT;
++ wbuf->next_ino = 0;
++
++ return 0;
++}
++
++/**
++ * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array.
++ * @wbuf: the write-buffer whereto add
++ * @inum: the inode number
++ *
++ * This function adds an inode number to the inode array of the write-buffer.
++ */
++void ubifs_wbuf_add_ino_nolock(struct ubifs_wbuf *wbuf, ino_t inum)
++{
++ if (!wbuf->buf)
++ /* NOR flash or something similar */
++ return;
++
++ spin_lock(&wbuf->lock);
++ if (wbuf->used)
++ wbuf->inodes[wbuf->next_ino++] = inum;
++ spin_unlock(&wbuf->lock);
++}
++
++/**
++ * wbuf_has_ino - returns if the wbuf contains data from the inode.
++ * @wbuf: the write-buffer
++ * @inum: the inode number
++ *
++ * This function returns with %1 if the write-buffer contains some data from the
++ * given inode otherwise it returns with %0.
++ */
++static int wbuf_has_ino(struct ubifs_wbuf *wbuf, ino_t inum)
++{
++ int i, ret = 0;
++
++ spin_lock(&wbuf->lock);
++ for (i = 0; i < wbuf->next_ino; i++)
++ if (inum == wbuf->inodes[i]) {
++ ret = 1;
++ break;
++ }
++ spin_unlock(&wbuf->lock);
++
++ return ret;
++}
++
++/**
++ * ubifs_sync_wbufs_by_inodes - synchronize write-buffers which have data.
++ * belonging to specified inodes.
++ * @c: UBIFS file-system description object
++ * @inodes: array of inodes
++ * @count: number of elements in @inodes
++ *
++ * This function synchronizes write-buffers which contain nodes belonging to
++ * any inode specified in @inodes array. Returns zero in case of success and a
++ * negative error code in case of failure.
++ */
++int ubifs_sync_wbufs_by_inodes(struct ubifs_info *c,
++ struct inode * const *inodes, int count)
++{
++ int i, j, err = 0;
++
++ ubifs_assert(count);
++
++ for (i = 0; i < c->jhead_cnt; i++) {
++ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
++
++ if (i == GCHD)
++ /*
++ * GC head is special, do not look at it. Even if the
++ * head contains something related to this inode, it is
++ * a _copy_ of corresponding on-flash node which sits
++ * somewhere else.
++ */
++ continue;
++
++ for (j = 0; j < count && !err; j++)
++ if (wbuf_has_ino(wbuf, inodes[j]->i_ino)) {
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ if (wbuf_has_ino(wbuf, inodes[j]->i_ino))
++ err = ubifs_wbuf_sync_nolock(wbuf);
++ mutex_unlock(&wbuf->io_mutex);
++ break;
++ }
++
++ if (err) {
++ ubifs_ro_mode(c, err);
++ break;
++ }
++ }
++
++ return err;
++}
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/ioctl.c avr32-2.6/fs/ubifs/ioctl.c
+--- linux-2.6.25.6/fs/ubifs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/ioctl.c 2008-06-12 15:09:45.367815766 +0200
+@@ -0,0 +1,204 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ * Copyright (C) 2006, 2007 University of Szeged, Hungary
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Zoltan Sogor
++ * Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/* This file implements EXT2-compatible extended attribute ioctl() calls */
++
++#include <linux/compat.h>
++#include <linux/smp_lock.h>
++#include "ubifs.h"
++
++/**
++ * ubifs_set_inode_flags - set VFS inode flags.
++ * @inode: VFS inode to set flags for
++ *
++ * This function propagates flags from UBIFS inode object to VFS inode object.
++ */
++void ubifs_set_inode_flags(struct inode *inode)
++{
++ unsigned int flags = ubifs_inode(inode)->flags;
++
++ inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC);
++ if (flags & UBIFS_SYNC_FL)
++ inode->i_flags |= S_SYNC;
++ if (flags & UBIFS_APPEND_FL)
++ inode->i_flags |= S_APPEND;
++ if (flags & UBIFS_IMMUTABLE_FL)
++ inode->i_flags |= S_IMMUTABLE;
++ if (flags & UBIFS_DIRSYNC_FL)
++ inode->i_flags |= S_DIRSYNC;
++}
++
++/*
++ * ioctl2ubifs - convert ioctl inode flags to UBIFS inode flags.
++ * @ioctl_flags: flags to convert
++ *
++ * This function convert ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags
++ * (@UBIFS_COMPR_FL, etc).
++ */
++static int ioctl2ubifs(int ioctl_flags)
++{
++ int ubifs_flags = 0;
++
++ if (ioctl_flags & FS_COMPR_FL)
++ ubifs_flags |= UBIFS_COMPR_FL;
++ if (ioctl_flags & FS_SYNC_FL)
++ ubifs_flags |= UBIFS_SYNC_FL;
++ if (ioctl_flags & FS_APPEND_FL)
++ ubifs_flags |= UBIFS_APPEND_FL;
++ if (ioctl_flags & FS_IMMUTABLE_FL)
++ ubifs_flags |= UBIFS_IMMUTABLE_FL;
++ if (ioctl_flags & FS_DIRSYNC_FL)
++ ubifs_flags |= UBIFS_DIRSYNC_FL;
++
++ return ubifs_flags;
++}
++
++/*
++ * ubifs2ioctl - convert UBIFS inode flags to ioctl inode flags.
++ * @ubifs_flags: flags to convert
++ *
++ * This function convert UBIFS (@UBIFS_COMPR_FL, etc) to ioctl flags
++ * (@FS_COMPR_FL, etc).
++ */
++static int ubifs2ioctl(int ubifs_flags)
++{
++ int ioctl_flags = 0;
++
++ if (ubifs_flags & UBIFS_COMPR_FL)
++ ioctl_flags |= FS_COMPR_FL;
++ if (ubifs_flags & UBIFS_SYNC_FL)
++ ioctl_flags |= FS_SYNC_FL;
++ if (ubifs_flags & UBIFS_APPEND_FL)
++ ioctl_flags |= FS_APPEND_FL;
++ if (ubifs_flags & UBIFS_IMMUTABLE_FL)
++ ioctl_flags |= FS_IMMUTABLE_FL;
++ if (ubifs_flags & UBIFS_DIRSYNC_FL)
++ ioctl_flags |= FS_DIRSYNC_FL;
++
++ return ioctl_flags;
++}
++
++static int setflags(struct inode *inode, int flags)
++{
++ struct ubifs_inode *ui = ubifs_inode(inode);
++ struct ubifs_info *c = inode->i_sb->s_fs_info;
++ struct ubifs_budget_req req;
++ int oldflags, err;
++
++ mutex_lock(&inode->i_mutex);
++
++ memset(&req, 0 , sizeof(struct ubifs_budget_req));
++ err = ubifs_budget_inode_op(c, inode, &req);
++ if (err)
++ goto out;
++
++ /*
++ * The IMMUTABLE and APPEND_ONLY flags can only be changed by
++ * the relevant capability.
++ */
++ oldflags = ubifs2ioctl(ui->flags);
++ if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
++ if (!capable(CAP_LINUX_IMMUTABLE)) {
++ err = -EPERM;
++ goto out_budg;
++ }
++ }
++
++ ui->flags = ioctl2ubifs(flags);
++ ubifs_set_inode_flags(inode);
++
++ inode->i_ctime = ubifs_current_time(inode);
++ mark_inode_dirty_sync(inode);
++
++ ubifs_release_ino_dirty(c, inode, &req);
++
++ if (IS_SYNC(inode))
++ err = write_inode_now(inode, 1);
++
++ mutex_unlock(&inode->i_mutex);
++ return err;
++
++out_budg:
++ ubifs_cancel_ino_op(c, inode, &req);
++out:
++ ubifs_err("can't modify inode %lu attributes", inode->i_ino);
++ mutex_unlock(&inode->i_mutex);
++ return err;
++}
++
++long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ int flags;
++ struct inode *inode = file->f_path.dentry->d_inode;
++
++ switch (cmd) {
++ case FS_IOC_GETFLAGS:
++ flags = ubifs2ioctl(ubifs_inode(inode)->flags);
++
++ return put_user(flags, (int __user *) arg);
++
++ case FS_IOC_SETFLAGS: {
++ if (IS_RDONLY(inode))
++ return -EROFS;
++
++ if (!is_owner_or_cap(inode))
++ return -EACCES;
++
++ if (get_user(flags, (int __user *) arg))
++ return -EFAULT;
++
++ if (!S_ISDIR(inode->i_mode))
++ flags &= ~FS_DIRSYNC_FL;
++
++ return setflags(inode, flags);
++ }
++
++ default:
++ return -ENOTTY;
++ }
++}
++
++#ifdef CONFIG_COMPAT
++long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ int err;
++
++ switch (cmd) {
++ case FS_IOC32_GETFLAGS:
++ cmd = FS_IOC_GETFLAGS;
++ break;
++ case FS_IOC32_SETFLAGS:
++ cmd = FS_IOC_SETFLAGS;
++ break;
++ default:
++ return -ENOIOCTLCMD;
++ }
++
++ lock_kernel();
++ err = ubifs_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
++ unlock_kernel();
++
++ return err;
++}
++#endif
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/journal.c avr32-2.6/fs/ubifs/journal.c
+--- linux-2.6.25.6/fs/ubifs/journal.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/journal.c 2008-06-12 15:09:45.367815766 +0200
+@@ -0,0 +1,1286 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/*
++ * This file implements UBIFS journal.
++ *
++ * The journal consists of 2 parts - the log and bud LEBs. The log has fixed
++ * length and position, while a bud logical eraseblock is any LEB in the main
++ * area. Buds contain file system data - data nodes, inode nodes, etc. The log
++ * contains only references to buds and some other stuff like commit
++ * start node. The idea is that when we commit the journal, we do
++ * not copy the data, the buds just become indexed. Since after the commit the
++ * nodes in bud eraseblocks become leaf nodes of the file system index tree, we
++ * use term "bud". Analogy is obvious, bud eraseblocks contain nodes which will
++ * become leafs in the future.
++ *
++ * The journal is multi-headed because we want to write data to the journal as
++ * optimally as possible. It is nice to have nodes belonging to the same inode
++ * in one LEB, so we may write data owned by different inodes to different
++ * journal heads, although at present only one data head is used.
++ *
++ * For recovery reasons, the base head contains all inode nodes, all directory
++ * entry nodes and all truncate nodes. This means that the other heads contain
++ * only data nodes.
++ *
++ * Bud LEBs may be half-indexed. For example, if the bud was not full at the
++ * time of commit, the bud is retained to continue to be used in the journal,
++ * even though the "front" of the LEB is now indexed. In that case, the log
++ * reference contains the offset where the bud starts for the purposes of the
++ * journal.
++ *
++ * The journal size has to be limited, because the larger is the journal, the
++ * longer it takes to mount UBIFS (scanning the journal) and the more memory it
++ * takes (indexing in the TNC).
++ *
++ * Note, all the journal write operations like 'ubifs_jnl_update()' here, which
++ * write multiple UBIFS nodes to the journal at one go, are atomic with respect
++ * to unclean reboots. Should the unclean reboot happen, the recovery code drops
++ * all the nodes.
++ */
++
++#include "ubifs.h"
++
++/**
++ * zero_ino_node_unused - zero out unused fields of an on-flash inode node.
++ * @ino: the inode to zero out
++ */
++static inline void zero_ino_node_unused(struct ubifs_ino_node *ino)
++{
++ memset(ino->padding, 0, 26);
++}
++
++/**
++ * zero_dent_node_unused - zero out unused fields of an on-flash directory
++ * entry node.
++ * @ino: the directory entry to zero out
++ */
++static inline void zero_dent_node_unused(struct ubifs_dent_node *dent)
++{
++ dent->padding1 = 0;
++ memset(dent->padding2, 0, 4);
++}
++
++/**
++ * zero_data_node_unused - zero out unused fields of an on-flash data node.
++ * @ino: the data node to zero out
++ */
++static inline void zero_data_node_unused(struct ubifs_data_node *data)
++{
++ memset(data->padding, 0, 2);
++}
++
++/**
++ * zero_trun_node_unused - zero out unused fields of an on-flash truncation
++ * node.
++ * @ino: the truncation node to zero out
++ */
++static inline void zero_trun_node_unused(struct ubifs_trun_node *trun)
++{
++ memset(trun->padding, 0, 12);
++}
++
++/**
++ * reserve_space - reserve space in the journal.
++ * @c: UBIFS file-system description object
++ * @jhead: journal head number
++ * @len: node length
++ *
++ * This function reserves space in journal head @head. If the reservation
++ * succeeded, the journal head stays locked and later has to be unlocked using
++ * 'release_head()'. 'write_node()' and 'write_head()' functions also unlock
++ * it. Returns zero in case of success, %-EAGAIN if commit has to be done, and
++ * other negative error codes in case of other failures.
++ */
++static int reserve_space(struct ubifs_info *c, int jhead, int len)
++{
++ int err = 0, err1, retries = 0, avail, lnum, offs, free, squeeze;
++ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
++
++ /*
++ * Typically, the base head has smaller nodes written to it, so it is
++ * better to try to allocate space at the ends of eraseblocks. This is
++ * what the squeeze parameter does.
++ */
++ squeeze = (jhead == BASEHD);
++again:
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ avail = c->leb_size - wbuf->offs - wbuf->used;
++
++ if (wbuf->lnum != -1 && avail >= len)
++ return 0;
++
++ /*
++ * Write buffer wasn't seek'ed or there is no enough space - look for an
++ * LEB with some empty space.
++ */
++ lnum = ubifs_find_free_space(c, len, &free, squeeze);
++ if (lnum >= 0) {
++ /* Found an LEB, add it to the journal head */
++ offs = c->leb_size - free;
++ err = ubifs_add_bud_to_log(c, jhead, lnum, offs);
++ if (err)
++ goto out_return;
++ /* A new bud was successfully allocated and added to the log */
++ goto out;
++ }
++
++ err = lnum;
++ if (err != -ENOSPC)
++ goto out_unlock;
++
++ /*
++ * No free space, we have to run garbage collector to make
++ * some. But the write-buffer mutex has to be unlocked because
++ * GC have to sync write buffers, which may lead a deadlock.
++ */
++ dbg_jnl("no free space jhead %d, run GC", jhead);
++ mutex_unlock(&wbuf->io_mutex);
++
++ lnum = ubifs_garbage_collect(c, 0);
++ if (lnum < 0) {
++ err = lnum;
++ if (err != -ENOSPC)
++ return err;
++
++ /*
++ * GC could not make a free LEB. But someone else may
++ * have allocated new bud for this journal head,
++ * because we dropped the 'io_mutex', so try once
++ * again.
++ */
++ dbg_jnl("GC couldn't make a free LEB for jhead %d", jhead);
++ if (retries++ < 2) {
++ dbg_jnl("retry (%d)", retries);
++ goto again;
++ }
++
++ dbg_jnl("return -ENOSPC");
++ return err;
++ }
++
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ dbg_jnl("got LEB %d for jhead %d", lnum, jhead);
++ avail = c->leb_size - wbuf->offs - wbuf->used;
++
++ if (wbuf->lnum != -1 && avail >= len) {
++ /*
++ * Someone else has switched the journal head and we have
++ * enough space now. This happens when more then one process is
++ * trying to write to the same journal head at the same time.
++ */
++ dbg_jnl("return LEB %d back, already have LEB %d:%d",
++ lnum, wbuf->lnum, wbuf->offs + wbuf->used);
++ err = ubifs_return_leb(c, lnum);
++ if (err)
++ goto out_unlock;
++ return 0;
++ }
++
++ err = ubifs_add_bud_to_log(c, jhead, lnum, 0);
++ if (err)
++ goto out_return;
++ offs = 0;
++
++out:
++ err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, UBI_SHORTTERM);
++ if (err)
++ goto out_unlock;
++
++ return 0;
++
++out_unlock:
++ mutex_unlock(&wbuf->io_mutex);
++ return err;
++
++out_return:
++ /* An error occurred and the LEB has to be returned to lprops */
++ ubifs_assert(err < 0);
++ err1 = ubifs_return_leb(c, lnum);
++ if (err1 && err == -EAGAIN)
++ /*
++ * Return original error code 'err' only if it is not
++ * '-EAGAIN', which is not really an error. Otherwise, return
++ * the error code of 'ubifs_return_leb()'.
++ */
++ err = err1;
++ mutex_unlock(&wbuf->io_mutex);
++ return err;
++}
++
++/**
++ * write_node - write node to a journal head.
++ * @c: UBIFS file-system description object
++ * @jhead: journal head
++ * @node: node to write
++ * @len: node length
++ * @lnum: LEB number written is returned here
++ * @offs: offset written is returned here
++ *
++ * This function writes a node to reserved space of journal head @jhead.
++ * Returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++static int write_node(struct ubifs_info *c, int jhead, void *node, int len,
++ int *lnum, int *offs)
++{
++ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
++
++ ubifs_assert(jhead != GCHD);
++
++ *lnum = c->jheads[jhead].wbuf.lnum;
++ *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used;
++
++ dbg_jnl("jhead %d, LEB %d:%d, len %d", jhead, *lnum, *offs, len);
++ ubifs_prepare_node(c, node, len, 0);
++
++ return ubifs_wbuf_write_nolock(wbuf, node, len);
++}
++
++/**
++ * write_head - write data to a journal head.
++ * @c: UBIFS file-system description object
++ * @jhead: journal head
++ * @buf: buffer to write
++ * @len: length to write
++ * @lnum: LEB number written is returned here
++ * @offs: offset written is returned here
++ * @sync: non-zero if the write-buffer has to by synchronized
++ *
++ * This function is the same as 'write_node()' but it does not assume the
++ * buffer it is writing is a node, so it does not prepare it (which means
++ * initializing common header and calculating CRC).
++ */
++static int write_head(struct ubifs_info *c, int jhead, void *buf, int len,
++ int *lnum, int *offs, int sync)
++{
++ int err;
++ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
++
++ ubifs_assert(jhead != GCHD);
++
++ *lnum = c->jheads[jhead].wbuf.lnum;
++ *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used;
++ dbg_jnl("jhead %d, LEB %d:%d, len %d", jhead, *lnum, *offs, len);
++
++ err = ubifs_wbuf_write_nolock(wbuf, buf, len);
++ if (err)
++ return err;
++ if (sync)
++ err = ubifs_wbuf_sync_nolock(wbuf);
++ return err;
++}
++
++/**
++ * make_reservation - reserve journal space.
++ * @c: UBIFS file-system description object
++ * @jhead: journal head
++ * @len: how many bytes to reserve
++ *
++ * This function makes space reservation in journal head @jhead. The function
++ * takes the commit lock and locks the journal head, and the caller has to
++ * unlock the head and finish the reservation with 'finish_reservation()'.
++ * Returns zero in case of success and a negative error code in case of
++ * failure.
++ *
++ * Note, the journal head may be unlocked as soon as the data is written, while
++ * the commit lock has to be released after the data has been added to the
++ * TNC.
++ */
++static int make_reservation(struct ubifs_info *c, int jhead, int len)
++{
++ int err, cmt_retries = 0, nospc_retries = 0;
++
++ ubifs_assert(len <= c->dark_wm);
++
++again:
++ down_read(&c->commit_sem);
++ err = reserve_space(c, jhead, len);
++ if (!err)
++ return 0;
++ up_read(&c->commit_sem);
++
++ if (err == -ENOSPC) {
++ /*
++ * GC could not make any progress. We should try to commit
++ * once because it could make some dirty space and GC would
++ * make progress, so make the error -EAGAIN so that the below
++ * will commit and re-try.
++ */
++ if (nospc_retries++ < 2) {
++ dbg_jnl("no space, retry");
++ err = -EAGAIN;
++ }
++
++ /*
++ * This means that the budgeting is incorrect. We always have
++ * to be able to write to the media, because all operations are
++ * budgeted. Deletions are not budgeted, though, but we reserve
++ * an extra LEB for them.
++ */
++ }
++
++ if (err != -EAGAIN)
++ goto out;
++
++ /*
++ * -EAGAIN means that the journal is full or too large, or the above
++ * code wants to do one commit. Do this and re-try.
++ */
++ if (cmt_retries > 128) {
++ /*
++ * This should not happen unless the journal size limitations
++ * are too tough.
++ */
++ ubifs_err("stuck in space allocation");
++ err = -ENOSPC;
++ goto out;
++ } else if (cmt_retries > 32)
++ ubifs_warn("too many space allocation re-tries (%d)",
++ cmt_retries);
++
++ dbg_jnl("-EAGAIN, commit and retry (retried %d times)",
++ cmt_retries);
++ cmt_retries += 1;
++
++ err = ubifs_run_commit(c);
++ if (err)
++ return err;
++ goto again;
++
++out:
++ ubifs_err("cannot reserve %d bytes in jhead %d, error %d",
++ len, jhead, err);
++ if (err == -ENOSPC) {
++ /* This are some budgeting problems, print useful information */
++ down_write(&c->commit_sem);
++ spin_lock(&c->space_lock);
++ dbg_dump_stack();
++ dbg_dump_budg(c);
++ spin_unlock(&c->space_lock);
++ dbg_dump_lprops(c);
++ cmt_retries = dbg_check_lprops(c);
++ up_write(&c->commit_sem);
++ }
++
++ return err;
++}
++
++/**
++ * release_head - release a journal head.
++ * @c: UBIFS file-system description object
++ * @jhead: journal head
++ *
++ * This function releases journal head @jhead which was locked by
++ * the 'make_reservation()' function. It has to be called after each successful
++ * 'make_reservation()' invocation.
++ */
++static inline void release_head(struct ubifs_info *c, int jhead)
++{
++ mutex_unlock(&c->jheads[jhead].wbuf.io_mutex);
++}
++
++/**
++ * finish_reservation - finish a reservation.
++ * @c: UBIFS file-system description object
++ *
++ * This function finishes journal space reservation. It must be called after
++ * 'make_reservation()'.
++ */
++static void finish_reservation(struct ubifs_info *c)
++{
++ up_read(&c->commit_sem);
++}
++
++/**
++ * get_dent_type - translate VFS inode mode to UBIFS directory entry type.
++ * @mode: inode mode
++ */
++static int get_dent_type(int mode)
++{
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ return UBIFS_ITYPE_REG;
++ case S_IFDIR:
++ return UBIFS_ITYPE_DIR;
++ case S_IFLNK:
++ return UBIFS_ITYPE_LNK;
++ case S_IFBLK:
++ return UBIFS_ITYPE_BLK;
++ case S_IFCHR:
++ return UBIFS_ITYPE_CHR;
++ case S_IFIFO:
++ return UBIFS_ITYPE_FIFO;
++ case S_IFSOCK:
++ return UBIFS_ITYPE_SOCK;
++ default:
++ BUG();
++ }
++ return 0;
++}
++
++/**
++ * pack_inode - pack an inode node.
++ * @c: UBIFS file-system description object
++ * @ino: buffer in which to pack inode node
++ * @inode: inode to pack
++ * @last: indicates the last node of the group
++ * @last_reference: non-zero if this is a deletion inode
++ */
++static void pack_inode(struct ubifs_info *c, struct ubifs_ino_node *ino,
++ const struct inode *inode, int last, int last_reference)
++{
++ int data_len = 0;
++ struct ubifs_inode *ui = ubifs_inode(inode);
++
++ ino->ch.node_type = UBIFS_INO_NODE;
++ ino_key_init_flash(c, &ino->key, inode->i_ino);
++ ino->creat_sqnum = cpu_to_le64(ui->creat_sqnum);
++ ino->size = cpu_to_le64(i_size_read(inode));
++ ino->nlink = cpu_to_le32(inode->i_nlink);
++ ino->atime_sec = cpu_to_le64(inode->i_atime.tv_sec);
++ ino->atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
++ ino->ctime_sec = cpu_to_le64(inode->i_ctime.tv_sec);
++ ino->ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
++ ino->mtime_sec = cpu_to_le64(inode->i_mtime.tv_sec);
++ ino->mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
++ ino->uid = cpu_to_le32(inode->i_uid);
++ ino->gid = cpu_to_le32(inode->i_gid);
++ ino->mode = cpu_to_le32(inode->i_mode);
++ ino->flags = cpu_to_le32(ui->flags);
++ ino->compr_type = cpu_to_le16(ui->compr_type);
++ ino->xattr_cnt = cpu_to_le32(ui->xattr_cnt);
++ ino->xattr_size = cpu_to_le64(ui->xattr_size);
++ ino->xattr_names = cpu_to_le32(ui->xattr_names);
++ ino->data_len = cpu_to_le32(ui->data_len);
++ zero_ino_node_unused(ino);
++
++ /*
++ * Drop the attached data if this is a deletion inode, the data is not
++ * needed anymore.
++ */
++ if (!last_reference) {
++ memcpy(ino->data, ui->data, ui->data_len);
++ data_len = ui->data_len;
++ }
++
++ ubifs_prep_grp_node(c, ino, UBIFS_INO_NODE_SZ + data_len, last);
++}
++
++/**
++ * ubifs_jnl_update - update inode.
++ * @c: UBIFS file-system description object
++ * @dir: parent inode or host inode in case of extended attributes
++ * @nm: directory entry name
++ * @inode: inode
++ * @deletion: indicates a directory entry deletion i.e unlink or rmdir
++ * @sync: non-zero if the write-buffer has to be synchronized
++ * @xent: non-zero if the directory entry is an extended attribute entry
++ *
++ * This function updates an inode by writing a directory entry (or extended
++ * attribute entry), the inode itself, and the parent directory inode (or the
++ * host inode) to the journal.
++ *
++ * The function writes the host inode @dir last, which is important in case of
++ * extended attributes. Indeed, then we guarantee that if the host inode gets
++ * synchronized, and the write-buffer it sits in gets flushed, the extended
++ * attribute inode gets flushed too. And this is exactly what the user expects -
++ * synchronizing the host inode synchronizes its extended attributes.
++ * Similarly, this guarantees that if @dir is synchronized, its directory entry
++ * corresponding to @nm gets synchronized too.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
++ const struct qstr *nm, const struct inode *inode,
++ int deletion, int sync, int xent)
++{
++ int err, dlen, ilen, len, lnum, ino_offs, dent_offs;
++ int aligned_dlen, aligned_ilen;
++ int last_reference = !!(deletion && inode->i_nlink == 0);
++ struct ubifs_dent_node *dent;
++ struct ubifs_ino_node *ino;
++ union ubifs_key dent_key, ino_key;
++
++ dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
++ inode->i_ino, nm->len, nm->name, ubifs_inode(inode)->data_len,
++ dir->i_ino);
++ ubifs_assert(ubifs_inode(dir)->data_len == 0);
++
++ dlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
++ ilen = UBIFS_INO_NODE_SZ;
++
++ /*
++ * If the last reference to the inode is being deleted, then there is no
++ * need to attach and write inode data, it is being deleted anyway.
++ */
++ if (!last_reference)
++ ilen += ubifs_inode(inode)->data_len;
++
++ aligned_dlen = ALIGN(dlen, 8);
++ aligned_ilen = ALIGN(ilen, 8);
++
++ len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ;
++
++ dent = kmalloc(len, GFP_NOFS);
++ if (!dent)
++ return -ENOMEM;
++
++ /* Make reservation before allocating sequence numbers */
++ err = make_reservation(c, BASEHD, len);
++ if (err)
++ goto out_free;
++
++ if (!xent) {
++ dent->ch.node_type = UBIFS_DENT_NODE;
++ dent_key_init(c, &dent_key, dir->i_ino, nm);
++ } else {
++ dent->ch.node_type = UBIFS_XENT_NODE;
++ xent_key_init(c, &dent_key, dir->i_ino, nm);
++ }
++
++ key_write(c, &dent_key, dent->key);
++ dent->inum = deletion ? 0 : cpu_to_le64(inode->i_ino);
++ dent->type = get_dent_type(inode->i_mode);
++ dent->nlen = cpu_to_le16(nm->len);
++ memcpy(dent->name, nm->name, nm->len);
++ dent->name[nm->len] = '\0';
++ zero_dent_node_unused(dent);
++ ubifs_prep_grp_node(c, dent, dlen, 0);
++
++ ino = (void *)dent + aligned_dlen;
++ pack_inode(c, ino, inode, 0, last_reference);
++
++ ino = (void *)ino + aligned_ilen;
++ pack_inode(c, ino, dir, 1, 0);
++
++ if (last_reference) {
++ err = ubifs_add_orphan(c, inode->i_ino);
++ if (err) {
++ release_head(c, BASEHD);
++ goto out_finish;
++ }
++ }
++
++ err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync);
++ if (!sync && !err) {
++ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
++
++ ubifs_wbuf_add_ino_nolock(wbuf, inode->i_ino);
++ ubifs_wbuf_add_ino_nolock(wbuf, dir->i_ino);
++ }
++ release_head(c, BASEHD);
++ kfree(dent);
++ if (err)
++ goto out_ro;
++
++ if (deletion) {
++ err = ubifs_tnc_remove_nm(c, &dent_key, nm);
++ if (err)
++ goto out_ro;
++ err = ubifs_add_dirt(c, lnum, dlen);
++ } else
++ err = ubifs_tnc_add_nm(c, &dent_key, lnum, dent_offs, dlen, nm);
++ if (err)
++ goto out_ro;
++
++ /*
++ * Note, we do not remove the inode from TNC even if the last reference
++ * to it has just been deleted, because the inode may still be opened.
++ * Instead, the inode has been added to orphan lists and the orphan
++ * subsystem will take further care about it.
++ */
++ ino_key_init(c, &ino_key, inode->i_ino);
++ ino_offs = dent_offs + aligned_dlen;
++ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, ilen);
++ if (err)
++ goto out_ro;
++
++ ino_key_init(c, &ino_key, dir->i_ino);
++ ino_offs += aligned_ilen;
++ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ);
++ if (err)
++ goto out_ro;
++
++ finish_reservation(c);
++ return 0;
++
++out_finish:
++ finish_reservation(c);
++out_free:
++ kfree(dent);
++ return err;
++
++out_ro:
++ ubifs_ro_mode(c, err);
++ if (last_reference)
++ ubifs_delete_orphan(c, inode->i_ino);
++ finish_reservation(c);
++ return err;
++}
++
++/**
++ * ubifs_jnl_write_data - write a data node to the journal.
++ * @c: UBIFS file-system description object
++ * @inode: inode the data node belongs to
++ * @key: node key
++ * @buf: buffer to write
++ * @len: data length (must not exceed %UBIFS_BLOCK_SIZE)
++ *
++ * This function writes a data node to the journal. Returns %0 if the data node
++ * was successfully written, and a negative error code in case of failure.
++ */
++int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
++ const union ubifs_key *key, const void *buf, int len)
++{
++ int err, lnum, offs, compr_type, out_len;
++ int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR;
++ const struct ubifs_inode *ui = ubifs_inode(inode);
++ struct ubifs_data_node *data;
++
++ dbg_jnl("ino %lu, blk %u, len %d, key %s", key_inum(c, key),
++ key_block(c, key), len, DBGKEY(key));
++ ubifs_assert(len <= UBIFS_BLOCK_SIZE);
++
++ data = kmalloc(dlen, GFP_NOFS);
++ if (!data)
++ return -ENOMEM;
++
++ data->ch.node_type = UBIFS_DATA_NODE;
++ key_write(c, key, &data->key);
++ data->size = cpu_to_le32(len);
++ zero_data_node_unused(data);
++
++ if (!(ui->flags && UBIFS_COMPR_FL))
++ /* Compression is disabled for this inode */
++ compr_type = UBIFS_COMPR_NONE;
++ else
++ compr_type = ui->compr_type;
++
++ out_len = dlen - UBIFS_DATA_NODE_SZ;
++ ubifs_compress(buf, len, &data->data, &out_len, &compr_type);
++ ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
++
++ dlen = UBIFS_DATA_NODE_SZ + out_len;
++ data->compr_type = cpu_to_le16(compr_type);
++
++ /* Make reservation before allocating sequence numbers */
++ err = make_reservation(c, DATAHD, dlen);
++ if (err)
++ goto out_free;
++
++ err = write_node(c, DATAHD, data, dlen, &lnum, &offs);
++ if (!err)
++ ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf,
++ key_inum(c, key));
++ release_head(c, DATAHD);
++ if (err)
++ goto out_ro;
++
++ err = ubifs_tnc_add(c, key, lnum, offs, dlen);
++ if (err)
++ goto out_ro;
++
++ finish_reservation(c);
++ kfree(data);
++ return 0;
++
++out_ro:
++ ubifs_ro_mode(c, err);
++ finish_reservation(c);
++out_free:
++ kfree(data);
++ return err;
++}
++
++/**
++ * ubifs_jnl_write_inode - flush inode to the journal.
++ * @c: UBIFS file-system description object
++ * @inode: inode to flush
++ * @last_reference: inode has been deleted
++ * @sync: non-zero if the write-buffer has to be synchronized
++ *
++ * This function writes inode @inode to the journal (to the base head). Returns
++ * zero in case of success and a negative error code in case of failure.
++ */
++int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode,
++ int last_reference, int sync)
++{
++ int err, len, lnum, offs;
++ struct ubifs_ino_node *ino;
++ struct ubifs_inode *ui = ubifs_inode(inode);
++
++ dbg_jnl("ino %lu%s", inode->i_ino,
++ last_reference ? " (last reference)" : "");
++ if (last_reference)
++ ubifs_assert(inode->i_nlink == 0);
++
++ /* If the inode is deleted, do not write the attached data */
++ len = UBIFS_INO_NODE_SZ;
++ if (!last_reference)
++ len += ui->data_len;
++ ino = kmalloc(len, GFP_NOFS);
++ if (!ino)
++ return -ENOMEM;
++
++ /* Make reservation before allocating sequence numbers */
++ err = make_reservation(c, BASEHD, len);
++ if (err)
++ goto out_free;
++
++ pack_inode(c, ino, inode, 1, last_reference);
++
++ err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync);
++ if (!sync && !err)
++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
++ inode->i_ino);
++ release_head(c, BASEHD);
++ if (err)
++ goto out_ro;
++
++ if (last_reference) {
++ err = ubifs_tnc_remove_ino(c, inode->i_ino);
++ if (err)
++ goto out_ro;
++ ubifs_delete_orphan(c, inode->i_ino);
++ err = ubifs_add_dirt(c, lnum, len);
++ } else {
++ union ubifs_key key;
++
++ ino_key_init(c, &key, inode->i_ino);
++ err = ubifs_tnc_add(c, &key, lnum, offs, len);
++ }
++ if (err)
++ goto out_ro;
++
++ finish_reservation(c);
++ kfree(ino);
++ return 0;
++
++out_ro:
++ ubifs_ro_mode(c, err);
++ finish_reservation(c);
++out_free:
++ kfree(ino);
++ return err;
++}
++
++/**
++ * ubifs_jnl_rename - rename a directory entry.
++ * @c: UBIFS file-system description object
++ * @old_dir: parent inode of directory entry to rename
++ * @old_dentry: directory entry to rename
++ * @new_dir: parent inode of directory entry to rename
++ * @new_dentry: new directory entry (or directory entry to replace)
++ * @sync: non-zero if the write-buffer has to be synchronized
++ *
++ * Returns zero in case of success and a negative error code in case of failure.
++ */
++int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
++ const struct dentry *old_dentry,
++ const struct inode *new_dir,
++ const struct dentry *new_dentry, int sync)
++{
++ const struct inode *old_inode = old_dentry->d_inode;
++ const struct inode *new_inode = new_dentry->d_inode;
++ int err, dlen1, dlen2, ilen, lnum, offs, len;
++ int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ;
++ int last_reference = !!(new_inode && new_inode->i_nlink == 0);
++ struct ubifs_dent_node *dent, *dent2;
++ void *p;
++ union ubifs_key key;
++
++ dbg_jnl("dent '%.*s' in dir ino %lu to dent '%.*s' in dir ino %lu",
++ old_dentry->d_name.len, old_dentry->d_name.name,
++ old_dir->i_ino, new_dentry->d_name.len,
++ new_dentry->d_name.name, new_dir->i_ino);
++
++ ubifs_assert(ubifs_inode(old_dir)->data_len == 0);
++ ubifs_assert(ubifs_inode(new_dir)->data_len == 0);
++
++ dlen1 = UBIFS_DENT_NODE_SZ + new_dentry->d_name.len + 1;
++ dlen2 = UBIFS_DENT_NODE_SZ + old_dentry->d_name.len + 1;
++ if (new_inode) {
++ ilen = UBIFS_INO_NODE_SZ;
++ if (!last_reference)
++ ilen += ubifs_inode(new_inode)->data_len;
++ } else
++ ilen = 0;
++
++ aligned_dlen1 = ALIGN(dlen1, 8);
++ aligned_dlen2 = ALIGN(dlen2, 8);
++
++ len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
++ if (old_dir != new_dir)
++ len += plen;
++
++ dent = kmalloc(len, GFP_NOFS);
++ if (!dent)
++ return -ENOMEM;
++
++ /* Make reservation before allocating sequence numbers */
++ err = make_reservation(c, BASEHD, len);
++ if (err)
++ goto out_free;
++
++ /* Make new dent */
++ dent->ch.node_type = UBIFS_DENT_NODE;
++ dent_key_init_flash(c, &dent->key, new_dir->i_ino, &new_dentry->d_name);
++ dent->inum = cpu_to_le64(old_inode->i_ino);
++ dent->type = get_dent_type(old_inode->i_mode);
++ dent->nlen = cpu_to_le16(new_dentry->d_name.len);
++ memcpy(dent->name, new_dentry->d_name.name, new_dentry->d_name.len);
++ dent->name[new_dentry->d_name.len] = '\0';
++ zero_dent_node_unused(dent);
++ ubifs_prep_grp_node(c, dent, dlen1, 0);
++
++ dent2 = (void *)dent + aligned_dlen1;
++
++ /* Make deletion dent */
++ dent2->ch.node_type = UBIFS_DENT_NODE;
++ dent_key_init_flash(c, &dent2->key, old_dir->i_ino,
++ &old_dentry->d_name);
++ dent2->inum = 0;
++ dent2->type = DT_UNKNOWN;
++ dent2->nlen = cpu_to_le16(old_dentry->d_name.len);
++ memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len);
++ dent2->name[old_dentry->d_name.len] = '\0';
++ zero_dent_node_unused(dent2);
++ ubifs_prep_grp_node(c, dent2, dlen2, 0);
++
++ p = (void *)dent2 + aligned_dlen2;
++ if (new_inode) {
++ pack_inode(c, p, new_inode, 0, last_reference);
++ p += ALIGN(ilen, 8);
++ }
++
++ if (old_dir == new_dir)
++ pack_inode(c, p, old_dir, 1, 0);
++ else {
++ pack_inode(c, p, old_dir, 0, 0);
++ p += ALIGN(plen, 8);
++ pack_inode(c, p, new_dir, 1, 0);
++ }
++
++ if (last_reference) {
++ err = ubifs_add_orphan(c, new_inode->i_ino);
++ if (err) {
++ release_head(c, BASEHD);
++ goto out_finish;
++ }
++ }
++
++ err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync);
++ if (!sync && !err) {
++ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
++
++ ubifs_wbuf_add_ino_nolock(wbuf, new_dir->i_ino);
++ ubifs_wbuf_add_ino_nolock(wbuf, old_dir->i_ino);
++ if (new_inode)
++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
++ new_inode->i_ino);
++ }
++ release_head(c, BASEHD);
++ if (err)
++ goto out_ro;
++
++ dent_key_init(c, &key, new_dir->i_ino, &new_dentry->d_name);
++ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, &new_dentry->d_name);
++ if (err)
++ goto out_ro;
++
++ err = ubifs_add_dirt(c, lnum, dlen2);
++ if (err)
++ goto out_ro;
++
++ dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
++ err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
++ if (err)
++ goto out_ro;
++
++ offs += aligned_dlen1 + aligned_dlen2;
++ if (new_inode) {
++ ino_key_init(c, &key, new_inode->i_ino);
++ err = ubifs_tnc_add(c, &key, lnum, offs, ilen);
++ if (err)
++ goto out_ro;
++ offs += ALIGN(ilen, 8);
++ }
++
++ ino_key_init(c, &key, old_dir->i_ino);
++ err = ubifs_tnc_add(c, &key, lnum, offs, plen);
++ if (err)
++ goto out_ro;
++
++ if (old_dir != new_dir) {
++ offs += ALIGN(plen, 8);
++ ino_key_init(c, &key, new_dir->i_ino);
++ err = ubifs_tnc_add(c, &key, lnum, offs, plen);
++ if (err)
++ goto out_ro;
++ }
++
++ finish_reservation(c);
++ kfree(dent);
++ return 0;
++
++out_ro:
++ ubifs_ro_mode(c, err);
++ if (last_reference)
++ ubifs_delete_orphan(c, new_inode->i_ino);
++out_finish:
++ finish_reservation(c);
++out_free:
++ kfree(dent);
++ return err;
++}
++
++/**
++ * recomp_data_node - re-compress a truncated data node.
++ * @dn: data node to re-compress
++ * @new_len: new length
++ *
++ * This function is used when an inode is truncated and the last data node of
++ * the inode has to be re-compressed and re-written.
++ */
++static int recomp_data_node(struct ubifs_data_node *dn, int *new_len)
++{
++ void *buf;
++ int err, len, compr_type, out_len;
++
++ out_len = le32_to_cpu(dn->size);
++ buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS);
++ if (!buf)
++ return -ENOMEM;
++
++ len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
++ compr_type = le16_to_cpu(dn->compr_type);
++ err = ubifs_decompress(&dn->data, len, buf, &out_len, compr_type);
++ if (err)
++ goto out;
++
++ ubifs_compress(buf, *new_len, &dn->data, &out_len, &compr_type);
++ ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
++ dn->compr_type = cpu_to_le16(compr_type);
++ dn->size = cpu_to_le32(*new_len);
++ *new_len = UBIFS_DATA_NODE_SZ + out_len;
++out:
++ kfree(buf);
++ return err;
++}
++
++/**
++ * ubifs_jnl_truncate - update the journal for a truncation.
++ * @c: UBIFS file-system description object
++ * @inum: inode number of inode being truncated
++ * @old_size: old size
++ * @new_size: new size
++ *
++ * When the size of a file decreases due to truncation, a truncation node is
++ * written, the journal tree is updated, and the last data block is re-written
++ * if it has been affected.
++ *
++ * This function returns %0 in the case of success, and a negative error code in
++ * case of failure.
++ */
++int ubifs_jnl_truncate(struct ubifs_info *c, ino_t inum,
++ loff_t old_size, loff_t new_size)
++{
++ union ubifs_key key, to_key;
++ struct ubifs_trun_node *trun;
++ struct ubifs_data_node *uninitialized_var(dn);
++ int err, dlen, len, lnum, offs, bit, sz;
++ unsigned int blk;
++
++ dbg_jnl("ino %lu, size %lld -> %lld", inum, old_size, new_size);
++
++ sz = UBIFS_TRUN_NODE_SZ + UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR;
++ trun = kmalloc(sz, GFP_NOFS);
++ if (!trun)
++ return -ENOMEM;
++
++ trun->ch.node_type = UBIFS_TRUN_NODE;
++ trun->inum = cpu_to_le32(inum);
++ trun->old_size = cpu_to_le64(old_size);
++ trun->new_size = cpu_to_le64(new_size);
++ zero_trun_node_unused(trun);
++
++ dlen = new_size & (UBIFS_BLOCK_SIZE - 1);
++
++ if (dlen) {
++ /* Get last data block so it can be truncated */
++ dn = (void *)trun + ALIGN(UBIFS_TRUN_NODE_SZ, 8);
++ blk = new_size / UBIFS_BLOCK_SIZE;
++ data_key_init(c, &key, inum, blk);
++ dbg_jnl("last block key %s", DBGKEY(&key));
++ err = ubifs_tnc_lookup(c, &key, dn);
++ if (err == -ENOENT)
++ dlen = 0; /* Not found (so it is a hole) */
++ else if (err)
++ goto out_free;
++ else {
++ if (le32_to_cpu(dn->size) <= dlen)
++ dlen = 0; /* Nothing to do */
++ else {
++ int compr_type = le16_to_cpu(dn->compr_type);
++
++ if (compr_type != UBIFS_COMPR_NONE) {
++ err = recomp_data_node(dn, &dlen);
++ if (err)
++ goto out_free;
++ } else {
++ dn->size = cpu_to_le32(dlen);
++ dlen += UBIFS_DATA_NODE_SZ;
++ }
++ zero_data_node_unused(dn);
++ }
++ }
++ }
++
++ if (dlen)
++ len = ALIGN(UBIFS_TRUN_NODE_SZ, 8) + dlen;
++ else
++ len = UBIFS_TRUN_NODE_SZ;
++
++ /* Must make reservation before allocating sequence numbers */
++ err = make_reservation(c, BASEHD, len);
++ if (err)
++ goto out_free;
++
++ ubifs_prepare_node(c, trun, UBIFS_TRUN_NODE_SZ, 0);
++ if (dlen)
++ ubifs_prepare_node(c, dn, dlen, 0);
++
++ err = write_head(c, BASEHD, trun, len, &lnum, &offs, 0);
++ if (!err)
++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, inum);
++ release_head(c, BASEHD);
++ if (err)
++ goto out_ro;
++
++ if (dlen) {
++ offs += ALIGN(UBIFS_TRUN_NODE_SZ, 8);
++ err = ubifs_tnc_add(c, &key, lnum, offs, dlen);
++ if (err)
++ goto out_ro;
++ }
++
++ err = ubifs_add_dirt(c, lnum, UBIFS_TRUN_NODE_SZ);
++ if (err)
++ goto out_ro;
++
++ bit = new_size & (UBIFS_BLOCK_SIZE - 1);
++
++ blk = new_size / UBIFS_BLOCK_SIZE + (bit ? 1 : 0);
++ data_key_init(c, &key, inum, blk);
++
++ bit = old_size & (UBIFS_BLOCK_SIZE - 1);
++
++ blk = old_size / UBIFS_BLOCK_SIZE - (bit ? 0: 1);
++ data_key_init(c, &to_key, inum, blk);
++
++ err = ubifs_tnc_remove_range(c, &key, &to_key);
++ if (err)
++ goto out_ro;
++
++ finish_reservation(c);
++ kfree(trun);
++ return 0;
++
++out_ro:
++ ubifs_ro_mode(c, err);
++ finish_reservation(c);
++out_free:
++ kfree(trun);
++ return err;
++}
++
++#ifdef CONFIG_UBIFS_FS_XATTR
++
++int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
++ const struct inode *inode, const struct qstr *nm,
++ int sync)
++{
++ int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen;
++ struct ubifs_dent_node *xent;
++ struct ubifs_ino_node *ino;
++ union ubifs_key xent_key, key1, key2;
++
++ dbg_jnl("host %lu, xattr ino %lu, name '%s', data len %d",
++ host->i_ino, inode->i_ino, nm->name,
++ ubifs_inode(inode)->data_len);
++ ubifs_assert(inode->i_nlink == 0);
++
++ /*
++ * Since we are deleting the inode, we do not bother to attach any data
++ * to it and assume its length is %UBIFS_INO_NODE_SZ.
++ */
++ xlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
++ aligned_xlen = ALIGN(xlen, 8);
++ hlen = ubifs_inode(host)->data_len + UBIFS_INO_NODE_SZ;
++ len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8);
++
++ xent = kmalloc(len, GFP_NOFS);
++ if (!xent)
++ return -ENOMEM;
++
++ /* Make reservation before allocating sequence numbers */
++ err = make_reservation(c, BASEHD, len);
++ if (err) {
++ kfree(xent);
++ return err;
++ }
++
++ xent->ch.node_type = UBIFS_XENT_NODE;
++ xent_key_init(c, &xent_key, host->i_ino, nm);
++ key_write(c, &xent_key, xent->key);
++ xent->inum = 0;
++ xent->type = get_dent_type(inode->i_mode);
++ xent->nlen = cpu_to_le16(nm->len);
++ memcpy(xent->name, nm->name, nm->len);
++ xent->name[nm->len] = '\0';
++ zero_dent_node_unused(xent);
++ ubifs_prep_grp_node(c, xent, xlen, 0);
++
++ ino = (void *)xent + aligned_xlen;
++ pack_inode(c, ino, inode, 0, 1);
++
++ ino = (void *)ino + UBIFS_INO_NODE_SZ;
++ pack_inode(c, ino, host, 1, 0);
++
++ err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync);
++ if (!sync && !err)
++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino);
++ release_head(c, BASEHD);
++ kfree(xent);
++ if (err)
++ goto out_ro;
++
++ /* Remove the extended attribute entry from TNC */
++ err = ubifs_tnc_remove_nm(c, &xent_key, nm);
++ if (err)
++ goto out_ro;
++ err = ubifs_add_dirt(c, lnum, xlen);
++ if (err)
++ goto out_ro;
++
++ /*
++ * Remove all nodes belonging to the extended attribute inode from TNC.
++ * Well, there actually must be only one node - the inode itself.
++ */
++ lowest_ino_key(c, &key1, inode->i_ino);
++ highest_ino_key(c, &key2, inode->i_ino);
++ err = ubifs_tnc_remove_range(c, &key1, &key2);
++ if (err)
++ goto out_ro;
++ err = ubifs_add_dirt(c, lnum, UBIFS_INO_NODE_SZ);
++ if (err)
++ goto out_ro;
++
++ /* And update TNC with the new host inode position */
++ ino_key_init(c, &key1, host->i_ino);
++ err = ubifs_tnc_add(c, &key1, lnum, xent_offs + len - hlen, hlen);
++ if (err)
++ goto out_ro;
++
++ finish_reservation(c);
++ return 0;
++
++out_ro:
++ ubifs_ro_mode(c, err);
++ finish_reservation(c);
++ return err;
++}
++
++/**
++ * ubifs_jnl_write_2_inodes - write 2 inodes to the journal.
++ * @c: UBIFS file-system description object
++ * @inode1: first inode to write
++ * @inode2: second inode to write
++ * @sync: non-zero if the write-buffer has to be synchronized
++ *
++ * This function writes 2 inodes @inode1 and @inode2 to the journal (to the
++ * base head - first @inode1, then @inode2). Returns zero in case of success
++ * and a negative error code in case of failure.
++ */
++int ubifs_jnl_write_2_inodes(struct ubifs_info *c, const struct inode *inode1,
++ const struct inode *inode2, int sync)
++{
++ int err, len1, len2, aligned_len, aligned_len1, lnum, offs;
++ struct ubifs_ino_node *ino;
++ union ubifs_key key;
++
++ dbg_jnl("ino %lu, ino %lu", inode1->i_ino, inode2->i_ino);
++ ubifs_assert(inode1->i_nlink > 0);
++ ubifs_assert(inode2->i_nlink > 0);
++
++ len1 = UBIFS_INO_NODE_SZ + ubifs_inode(inode1)->data_len;
++ len2 = UBIFS_INO_NODE_SZ + ubifs_inode(inode2)->data_len;
++ aligned_len1 = ALIGN(len1, 8);
++ aligned_len = aligned_len1 + ALIGN(len2, 8);
++
++ ino = kmalloc(aligned_len, GFP_NOFS);
++ if (!ino)
++ return -ENOMEM;
++
++ /* Make reservation before allocating sequence numbers */
++ err = make_reservation(c, BASEHD, aligned_len);
++ if (err)
++ goto out_free;
++
++ pack_inode(c, ino, inode1, 0, 0);
++ pack_inode(c, (void *)ino + aligned_len1, inode2, 1, 0);
++
++ err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0);
++ if (!sync && !err) {
++ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
++
++ ubifs_wbuf_add_ino_nolock(wbuf, inode1->i_ino);
++ ubifs_wbuf_add_ino_nolock(wbuf, inode2->i_ino);
++ }
++ release_head(c, BASEHD);
++ if (err)
++ goto out_ro;
++
++ ino_key_init(c, &key, inode1->i_ino);
++ err = ubifs_tnc_add(c, &key, lnum, offs, len1);
++ if (err)
++ goto out_ro;
++
++ ino_key_init(c, &key, inode2->i_ino);
++ err = ubifs_tnc_add(c, &key, lnum, offs + aligned_len1, len2);
++ if (err)
++ goto out_ro;
++
++ finish_reservation(c);
++ kfree(ino);
++ return 0;
++
++out_ro:
++ ubifs_ro_mode(c, err);
++ finish_reservation(c);
++out_free:
++ kfree(ino);
++ return err;
++}
++
++#endif /* CONFIG_UBIFS_FS_XATTR */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/Kconfig avr32-2.6/fs/ubifs/Kconfig
+--- linux-2.6.25.6/fs/ubifs/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/Kconfig 2008-06-12 15:09:45.311815896 +0200
+@@ -0,0 +1,72 @@
++config UBIFS_FS
++ tristate "UBIFS file system support"
++ select CRC16
++ select CRC32
++ select CRYPTO if UBIFS_FS_ADVANCED_COMPR
++ select CRYPTO if UBIFS_FS_LZO
++ select CRYPTO if UBIFS_FS_ZLIB
++ select CRYPTO_LZO if UBIFS_FS_LZO
++ select CRYPTO_DEFLATE if UBIFS_FS_ZLIB
++ depends on MTD_UBI
++ help
++ UBIFS is a file system for flash devices which works on top of UBI.
++
++config UBIFS_FS_XATTR
++ bool "Extended attributes support"
++ depends on UBIFS_FS
++ help
++ This option enables support of extended attributes.
++
++config UBIFS_FS_ADVANCED_COMPR
++ bool "Advanced compression options"
++ depends on UBIFS_FS
++ help
++ This option allows to explicitly choose which compressions, if any,
++ are enabled in UBIFS. Removing compressors means inbility to read
++ existing file systems.
++
++ If unsure, say 'N'.
++
++config UBIFS_FS_LZO
++ bool "LZO compression support" if UBIFS_FS_ADVANCED_COMPR
++ depends on UBIFS_FS
++ default y
++ help
++ LZO compressor is generally faster then zlib but compresses worse.
++ Say 'Y' if unsure.
++
++config UBIFS_FS_ZLIB
++ bool "ZLIB compression support" if UBIFS_FS_ADVANCED_COMPR
++ depends on UBIFS_FS
++ default y
++ help
++ Zlib copresses better then LZO but it is slower. Say 'Y' if unsure.
++
++# Debugging-related stuff
++config UBIFS_FS_DEBUG
++ bool "Enable debugging"
++ depends on UBIFS_FS
++ select DEBUG_FS
++ select KALLSYMS_ALL
++ help
++ This option enables UBIFS debugging.
++
++config UBIFS_FS_DEBUG_MSG_LVL
++ int "Default message level (0 = no extra messages, 3 = lots)"
++ depends on UBIFS_FS_DEBUG
++ default "0"
++ help
++ This controls the amount of debugging messages produced by UBIFS.
++ If reporting bugs, please try to have available a full dump of the
++ messages at level 1 while the misbehaviour was occurring. Level 2
++ may become necessary if level 1 messages were not enough to find the
++ bug. Generally Level 3 should be avoided.
++
++config UBIFS_FS_DEBUG_CHKS
++ bool "Enable extra checks"
++ depends on UBIFS_FS_DEBUG
++ help
++ If extra checks are enabled UBIFS will check the consistency of its
++ internal data structures during operation. However, UBIFS performance
++ is dramatically slower when this option is selected especially if the
++ file system is large.
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/key.h avr32-2.6/fs/ubifs/key.h
+--- linux-2.6.25.6/fs/ubifs/key.h 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/key.h 2008-06-12 15:09:45.367815766 +0200
+@@ -0,0 +1,533 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/*
++ * This header contains various key-related definitions and helper function.
++ * UBIFS allows several key schemes, so we access key fields only via these
++ * helpers. At the moment only one key scheme is supported.
++ *
++ * Simple key scheme
++ * ~~~~~~~~~~~~~~~~~
++ *
++ * Keys are 64-bits long. First 32-bits are inode number (parent inode number
++ * in case of direntry key). Next 3 bits are node type. The last 29 bits are
++ * 4KiB offset in case of inode node, and direntry hash in case of a direntry
++ * node. We use "r5" hash borrowed from reiserfs.
++ */
++
++#ifndef __UBIFS_KEY_H__
++#define __UBIFS_KEY_H__
++
++/**
++ * key_r5_hash - R5 hash function (borrowed from reiserfs).
++ * @s: direntry name
++ * @len: name length
++ */
++static inline uint32_t key_r5_hash(const char *s, int len)
++{
++ uint32_t a = 0;
++ const signed char *str = (const signed char *)s;
++
++ while (*str) {
++ a += *str << 4;
++ a += *str >> 4;
++ a *= 11;
++ str++;
++ }
++
++ a &= UBIFS_S_KEY_HASH_MASK;
++
++ /*
++ * We use hash values as offset in directories, so values %0 and %1 are
++ * reserved for "." and "..". %2 is reserved for "end of readdir"
++ * marker.
++ */
++ if (unlikely(a >= 0 && a <= 2))
++ a += 3;
++ return a;
++}
++
++/**
++ * key_test_hash - testing hash function.
++ * @str: direntry name
++ * @len: name length
++ */
++static inline uint32_t key_test_hash(const char *str, int len)
++{
++ uint32_t a = 0;
++
++ len = min_t(uint32_t, len, 4);
++ memcpy(&a, str, len);
++ a &= UBIFS_S_KEY_HASH_MASK;
++ if (unlikely(a >= 0 && a <= 2))
++ a += 3;
++ return a;
++}
++
++/**
++ * ino_key_init - initialize inode key.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: inode number
++ */
++static inline void ino_key_init(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum)
++{
++ key->u32[0] = inum;
++ key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS;
++}
++
++/**
++ * ino_key_init_flash - initialize on-flash inode key.
++ * @c: UBIFS file-system description object
++ * @k: key to initialize
++ * @inum: inode number
++ */
++static inline void ino_key_init_flash(const struct ubifs_info *c, void *k,
++ ino_t inum)
++{
++ union ubifs_key *key = k;
++
++ key->j32[0] = cpu_to_le32(inum);
++ key->j32[1] = cpu_to_le32(UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS);
++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
++}
++
++/**
++ * lowest_ino_key - get the lowest possible inode key.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: inode number
++ */
++static inline void lowest_ino_key(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum)
++{
++ key->u32[0] = inum;
++ key->u32[1] = 0;
++}
++
++/**
++ * highest_ino_key - get the highest possible inode key.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: inode number
++ */
++static inline void highest_ino_key(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum)
++{
++ key->u32[0] = inum;
++ key->u32[1] = 0xffffffff;
++}
++
++/**
++ * dent_key_init - initialize directory entry key.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: parent inode number
++ * @nm: direntry name and length
++ */
++static inline void dent_key_init(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum,
++ const struct qstr *nm)
++{
++ uint32_t hash = c->key_hash(nm->name, nm->len);
++
++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
++ key->u32[0] = inum;
++ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
++}
++
++/**
++ * dent_key_init_hash - initialize directory entry key without re-calculating
++ * hash function.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: parent inode number
++ * @hash: direntry name hash
++ */
++static inline void dent_key_init_hash(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum,
++ uint32_t hash)
++{
++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
++ key->u32[0] = inum;
++ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
++}
++
++/**
++ * dent_key_init_flash - initialize on-flash directory entry key.
++ * @c: UBIFS file-system description object
++ * @k: key to initialize
++ * @inum: parent inode number
++ * @nm: direntry name and length
++ */
++static inline void dent_key_init_flash(const struct ubifs_info *c, void *k,
++ ino_t inum, const struct qstr *nm)
++{
++ union ubifs_key *key = k;
++ uint32_t hash = c->key_hash(nm->name, nm->len);
++
++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
++ key->j32[0] = cpu_to_le32(inum);
++ key->j32[1] = cpu_to_le32(hash |
++ (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS));
++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
++}
++
++/**
++ * lowest_dent_key - get the lowest possible directory entry key.
++ * @c: UBIFS file-system description object
++ * @key: where to store the lowest key
++ * @inum: parent inode number
++ */
++static inline void lowest_dent_key(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum)
++{
++ key->u32[0] = inum;
++ key->u32[1] = UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS;
++}
++
++/**
++ * xent_key_init - initialize extended attribute entry key.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: host inode number
++ * @nm: extended attribute entry name and length
++ */
++static inline void xent_key_init(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum,
++ const struct qstr *nm)
++{
++ uint32_t hash = c->key_hash(nm->name, nm->len);
++
++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
++ key->u32[0] = inum;
++ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
++}
++
++/**
++ * xent_key_init_hash - initialize extended attribute entry key without
++ * re-calculating hash function.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: host inode number
++ * @hash: extended attribute entry name hash
++ */
++static inline void xent_key_init_hash(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum,
++ uint32_t hash)
++{
++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
++ key->u32[0] = inum;
++ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
++}
++
++/**
++ * xent_key_init_flash - initialize on-flash extended attribute entry key.
++ * @c: UBIFS file-system description object
++ * @k: key to initialize
++ * @inum: host inode number
++ * @nm: extended attribute entry name and length
++ */
++static inline void xent_key_init_flash(const struct ubifs_info *c, void *k,
++ ino_t inum, const struct qstr *nm)
++{
++ union ubifs_key *key = k;
++ uint32_t hash = c->key_hash(nm->name, nm->len);
++
++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
++ key->j32[0] = cpu_to_le32(inum);
++ key->j32[1] = cpu_to_le32(hash |
++ (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS));
++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
++}
++
++/**
++ * lowest_xent_key - get the lowest possible extended attribute entry key.
++ * @c: UBIFS file-system description object
++ * @key: where to store the lowest key
++ * @inum: host inode number
++ */
++static inline void lowest_xent_key(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum)
++{
++ key->u32[0] = inum;
++ key->u32[1] = UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS;
++}
++
++/**
++ * data_key_init - initialize data key.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: inode number
++ * @block: block number
++ */
++static inline void data_key_init(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum,
++ unsigned int block)
++{
++ ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK));
++ key->u32[0] = inum;
++ key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS);
++}
++
++/**
++ * data_key_init_flash - initialize on-flash data key.
++ * @c: UBIFS file-system description object
++ * @k: key to initialize
++ * @inum: inode number
++ * @block: block number
++ */
++static inline void data_key_init_flash(const struct ubifs_info *c, void *k,
++ ino_t inum, unsigned int block)
++{
++ union ubifs_key *key = k;
++
++ ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK));
++ key->j32[0] = cpu_to_le32(inum);
++ key->j32[1] = cpu_to_le32(block |
++ (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS));
++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
++}
++
++/**
++ * trun_key_init - initialize truncation node key.
++ * @c: UBIFS file-system description object
++ * @key: key to initialize
++ * @inum: inode number
++ *
++ * Note, UBIFS does not have truncation keys on the media and this function is
++ * only used for purposes of replay.
++ */
++static inline void trun_key_init(const struct ubifs_info *c,
++ union ubifs_key *key, ino_t inum)
++{
++ key->u32[0] = inum;
++ key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS;
++}
++
++/**
++ * key_type - get key type.
++ * @c: UBIFS file-system description object
++ * @key: key to get type of
++ */
++static inline int key_type(const struct ubifs_info *c,
++ const union ubifs_key *key)
++{
++ return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS;
++}
++
++/**
++ * key_type_flash - get type of a on-flash formatted key.
++ * @c: UBIFS file-system description object
++ * @k: key to get type of
++ */
++static inline int key_type_flash(const struct ubifs_info *c, const void *k)
++{
++ const union ubifs_key *key = k;
++
++ return le32_to_cpu(key->u32[1]) >> UBIFS_S_KEY_BLOCK_BITS;
++}
++
++/**
++ * key_inum - fetch inode number from key.
++ * @c: UBIFS file-system description object
++ * @k: key to fetch inode number from
++ */
++static inline ino_t key_inum(const struct ubifs_info *c, const void *k)
++{
++ const union ubifs_key *key = k;
++
++ return key->u32[0];
++}
++
++/**
++ * key_inum_flash - fetch inode number from an on-flash formatted key.
++ * @c: UBIFS file-system description object
++ * @k: key to fetch inode number from
++ */
++static inline ino_t key_inum_flash(const struct ubifs_info *c, const void *k)
++{
++ const union ubifs_key *key = k;
++
++ return le32_to_cpu(key->j32[0]);
++}
++
++/**
++ * key_hash - get directory entry hash.
++ * @c: UBIFS file-system description object
++ * @key: the key to get hash from
++ */
++static inline int key_hash(const struct ubifs_info *c,
++ const union ubifs_key *key)
++{
++ return key->u32[1] & UBIFS_S_KEY_HASH_MASK;
++}
++
++/**
++ * key_hash_flash - get directory entry hash from an on-flash formatted key.
++ * @c: UBIFS file-system description object
++ * @k: the key to get hash from
++ */
++static inline int key_hash_flash(const struct ubifs_info *c, const void *k)
++{
++ const union ubifs_key *key = k;
++
++ return le32_to_cpu(key->j32[1]) & UBIFS_S_KEY_HASH_MASK;
++}
++
++/**
++ * key_block - get data block number.
++ * @c: UBIFS file-system description object
++ * @key: the key to get the block number from
++ */
++static inline unsigned int key_block(const struct ubifs_info *c,
++ const union ubifs_key *key)
++{
++ return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK;
++}
++
++/**
++ * key_block_flash - get data block number from an on-flash formatted key.
++ * @c: UBIFS file-system description object
++ * @k: the key to get the block number from
++ */
++static inline unsigned int key_block_flash(const struct ubifs_info *c,
++ const void *k)
++{
++ const union ubifs_key *key = k;
++
++ return le32_to_cpu(key->u32[1]) & UBIFS_S_KEY_BLOCK_MASK;
++}
++
++/**
++ * key_read - transform a key to in-memory format.
++ * @c: UBIFS file-system description object
++ * @from: the key to transform
++ * @to: the key to store the result
++ */
++static inline void key_read(const struct ubifs_info *c, const void *from,
++ union ubifs_key *to)
++{
++ const union ubifs_key *f = from;
++
++ to->u32[0] = le32_to_cpu(f->j32[0]);
++ to->u32[1] = le32_to_cpu(f->j32[1]);
++}
++
++/**
++ * key_write - transform a key from in-memory format.
++ * @c: UBIFS file-system description object
++ * @from: the key to transform
++ * @to: the key to store the result
++ */
++static inline void key_write(const struct ubifs_info *c,
++ const union ubifs_key *from, void *to)
++{
++ union ubifs_key *t = to;
++
++ t->j32[0] = cpu_to_le32(from->u32[0]);
++ t->j32[1] = cpu_to_le32(from->u32[1]);
++ memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
++}
++
++/**
++ * key_write_idx - transform a key from in-memory format for the index.
++ * @c: UBIFS file-system description object
++ * @from: the key to transform
++ * @to: the key to store the result
++ */
++static inline void key_write_idx(const struct ubifs_info *c,
++ const union ubifs_key *from, void *to)
++{
++ union ubifs_key *t = to;
++
++ t->j32[0] = cpu_to_le32(from->u32[0]);
++ t->j32[1] = cpu_to_le32(from->u32[1]);
++}
++
++/**
++ * key_copy - copy a key.
++ * @c: UBIFS file-system description object
++ * @from: the key to copy from
++ * @to: the key to copy to
++ */
++static inline void key_copy(const struct ubifs_info *c,
++ const union ubifs_key *from, union ubifs_key *to)
++{
++ to->u64[0] = from->u64[0];
++}
++
++/**
++ * keys_cmp - compare keys.
++ * @c: UBIFS file-system description object
++ * @key1: the first key to compare
++ * @key2: the second key to compare
++ *
++ * This function compares 2 keys and returns %-1 if @key1 is less than
++ * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2.
++ */
++static inline int keys_cmp(const struct ubifs_info *c,
++ const union ubifs_key *key1,
++ const union ubifs_key *key2)
++{
++ if (key1->u32[0] < key2->u32[0])
++ return -1;
++ if (key1->u32[0] > key2->u32[0])
++ return 1;
++ if (key1->u32[1] < key2->u32[1])
++ return -1;
++ if (key1->u32[1] > key2->u32[1])
++ return 1;
++
++ return 0;
++}
++
++/**
++ * is_hash_key - is a key vulnerable to hash collisions.
++ * @c: UBIFS file-system description object
++ * @key: key
++ *
++ * This function returns %1 if @key is a hashed key or %0 otherwise.
++ */
++static inline int is_hash_key(const struct ubifs_info *c,
++ const union ubifs_key *key)
++{
++ int type = key_type(c, key);
++
++ return type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY;
++}
++
++/**
++ * key_max_inode_size - get maximum file size allowed by current key format.
++ * @c: UBIFS file-system description object
++ */
++static inline unsigned long long key_max_inode_size(const struct ubifs_info *c)
++{
++ switch (c->key_fmt) {
++ case UBIFS_SIMPLE_KEY_FMT:
++ return (1ULL << UBIFS_S_KEY_BLOCK_BITS) * UBIFS_BLOCK_SIZE;
++ default:
++ return 0;
++ }
++}
++#endif /* !__UBIFS_KEY_H__ */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/log.c avr32-2.6/fs/ubifs/log.c
+--- linux-2.6.25.6/fs/ubifs/log.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/log.c 2008-06-12 15:09:45.367815766 +0200
+@@ -0,0 +1,799 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/*
++ * This file is a part of UBIFS journal implementation and contains various
++ * functions which manipulate the log. The log is a fixed area on the flash
++ * which does not contain any data but refers to buds. The log is a part of the
++ * journal.
++ */
++
++#include "ubifs.h"
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++static int dbg_check_bud_bytes(struct ubifs_info *c);
++#else
++#define dbg_check_bud_bytes(c) 0
++#endif
++
++/**
++ * ubifs_search_bud - search bud LEB.
++ * @c: UBIFS file-system description object
++ * @lnum: logical eraseblock number to search
++ *
++ * This function searches bud LEB @lnum. Returns bud description object in case
++ * of success and %NULL if there is no bud with this LEB number.
++ */
++struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum)
++{
++ struct rb_node *p;
++ struct ubifs_bud *bud;
++
++ spin_lock(&c->buds_lock);
++ p = c->buds.rb_node;
++ while (p) {
++ bud = rb_entry(p, struct ubifs_bud, rb);
++ if (lnum < bud->lnum)
++ p = p->rb_left;
++ else if (lnum > bud->lnum)
++ p = p->rb_right;
++ else {
++ spin_unlock(&c->buds_lock);
++ return bud;
++ }
++ }
++ spin_unlock(&c->buds_lock);
++ return NULL;
++}
++
++/**
++ * ubifs_get_wbuf - get the wbuf associated with a LEB, if there is one.
++ * @c: UBIFS file-system description object
++ * @lnum: logical eraseblock number to search
++ *
++ * This functions returns the wbuf for @lnum or %NULL if there is not one.
++ */
++struct ubifs_wbuf *ubifs_get_wbuf(struct ubifs_info *c, int lnum)
++{
++ struct rb_node *p;
++ struct ubifs_bud *bud;
++ int jhead;
++
++ if (!c->jheads)
++ return NULL;
++
++ spin_lock(&c->buds_lock);
++ p = c->buds.rb_node;
++ while (p) {
++ bud = rb_entry(p, struct ubifs_bud, rb);
++ if (lnum < bud->lnum)
++ p = p->rb_left;
++ else if (lnum > bud->lnum)
++ p = p->rb_right;
++ else {
++ jhead = bud->jhead;
++ spin_unlock(&c->buds_lock);
++ return &c->jheads[jhead].wbuf;
++ }
++ }
++ spin_unlock(&c->buds_lock);
++ return NULL;
++}
++
++/**
++ * next_log_lnum - switch to the next log LEB.
++ * @c: UBIFS file-system description object
++ * @lnum: current log LEB
++ */
++static inline int next_log_lnum(const struct ubifs_info *c, int lnum)
++{
++ lnum += 1;
++ if (lnum > c->log_last)
++ lnum = UBIFS_LOG_LNUM;
++
++ return lnum;
++}
++
++/**
++ * empty_log_bytes - calculate amount of empty space in the log.
++ * @c: UBIFS file-system description object
++ */
++static inline long long empty_log_bytes(const struct ubifs_info *c)
++{
++ long long h, t;
++
++ h = c->lhead_lnum * c->leb_size + c->lhead_offs;
++ t = c->ltail_lnum * c->leb_size;
++
++ if (h >= t)
++ return c->log_bytes - h + t;
++ else
++ return t - h;
++}
++
++/**
++ * ubifs_add_bud - add bud LEB to the tree of buds and its journal head list.
++ * @c: UBIFS file-system description object
++ * @bud: the bud to add
++ */
++void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
++{
++ struct rb_node **p, *parent = NULL;
++ struct ubifs_bud *b;
++ struct ubifs_jhead *jhead;
++
++ spin_lock(&c->buds_lock);
++ p = &c->buds.rb_node;
++ while (*p) {
++ parent = *p;
++ b = rb_entry(parent, struct ubifs_bud, rb);
++ ubifs_assert(bud->lnum != b->lnum);
++ if (bud->lnum < b->lnum)
++ p = &(*p)->rb_left;
++ else
++ p = &(*p)->rb_right;
++ }
++
++ rb_link_node(&bud->rb, parent, p);
++ rb_insert_color(&bud->rb, &c->buds);
++ if (c->jheads) {
++ jhead = &c->jheads[bud->jhead];
++ list_add_tail(&bud->list, &jhead->buds_list);
++ } else
++ ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY));
++
++ /*
++ * Note, although this is a new bud, we anyway account this space now,
++ * before any data has been written to it, because this is about to
++ * guarantee fixed mount time, and this bud will anyway be read and
++ * scanned.
++ */
++ c->bud_bytes += c->leb_size - bud->start;
++
++ dbg_log("LEB %d:%d, jhead %d, bud_bytes %lld", bud->lnum,
++ bud->start, bud->jhead, c->bud_bytes);
++ spin_unlock(&c->buds_lock);
++}
++
++/**
++ * ubifs_create_buds_lists - create journal head buds lists for remount rw.
++ * @c: UBIFS file-system description object
++ */
++void ubifs_create_buds_lists(struct ubifs_info *c)
++{
++ struct rb_node *p;
++
++ spin_lock(&c->buds_lock);
++ p = rb_first(&c->buds);
++ while (p) {
++ struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb);
++ struct ubifs_jhead *jhead = &c->jheads[bud->jhead];
++
++ list_add_tail(&bud->list, &jhead->buds_list);
++ p = rb_next(p);
++ }
++ spin_unlock(&c->buds_lock);
++}
++
++/**
++ * ubifs_add_bud_to_log - add a new bud to the log.
++ * @c: UBIFS file-system description object
++ * @jhead: journal head the bud belongs to
++ * @lnum: LEB number of the bud
++ * @offs: starting offset of the bud
++ *
++ * This function writes reference node for the new bud LEB @lnum it to the log,
++ * and adds it to the buds tress. It also makes sure that log size does not
++ * exceed the 'c->max_bud_bytes' limit. Returns zero in case of success,
++ * %-EAGAIN if commit is required, and a negative error codes in case of
++ * failure.
++ */
++int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
++{
++ int err;
++ struct ubifs_bud *bud;
++ struct ubifs_ref_node *ref;
++
++ bud = kmalloc(sizeof(struct ubifs_bud), GFP_NOFS);
++ if (!bud)
++ return -ENOMEM;
++ ref = kzalloc(c->ref_node_alsz, GFP_NOFS);
++ if (!ref) {
++ kfree(bud);
++ return -ENOMEM;
++ }
++
++ mutex_lock(&c->log_mutex);
++ /* Make sure we have enough space in the log */
++ if (empty_log_bytes(c) - c->ref_node_alsz < c->min_log_bytes) {
++ dbg_log("not enough log space - %lld, required %d",
++ empty_log_bytes(c), c->min_log_bytes);
++ ubifs_commit_required(c);
++ err = -EAGAIN;
++ goto out_unlock;
++ }
++
++ /*
++ * Make sure the the amount of space in buds will not exceed
++ * 'c->max_bud_bytes' limit, because we want to guarantee mount time
++ * limits.
++ *
++ * It is not necessary to hold @c->buds_lock when reading @c->bud_bytes
++ * because we are holding @c->log_mutex. All @c->bud_bytes take place
++ * when both @c->log_mutex and @c->bud_bytes are locked.
++ */
++ if (c->bud_bytes + c->leb_size - offs > c->max_bud_bytes) {
++ dbg_log("bud bytes %lld (%lld max), require commit",
++ c->bud_bytes, c->max_bud_bytes);
++ ubifs_commit_required(c);
++ err = -EAGAIN;
++ goto out_unlock;
++ }
++
++ /*
++ * If the journal is full enough - start background commit. Note, it is
++ * OK to read 'c->cmt_state' without spinlock because integer reads
++ * are atomic in the kernel.
++ */
++ if (c->bud_bytes >= c->bg_bud_bytes &&
++ c->cmt_state == COMMIT_RESTING) {
++ dbg_log("bud bytes %lld (%lld max), initiate BG commit",
++ c->bud_bytes, c->max_bud_bytes);
++ ubifs_request_bg_commit(c);
++ }
++
++ bud->lnum = lnum;
++ bud->start = offs;
++ bud->jhead = jhead;
++
++ ref->ch.node_type = UBIFS_REF_NODE;
++ ref->lnum = cpu_to_le32(bud->lnum);
++ ref->offs = cpu_to_le32(bud->start);
++ ref->jhead = cpu_to_le32(jhead);
++
++ if (c->lhead_offs > c->leb_size - c->ref_node_alsz) {
++ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum);
++ c->lhead_offs = 0;
++ }
++
++ if (c->lhead_offs == 0) {
++ /* Must ensure next log LEB has been unmapped */
++ err = ubifs_leb_unmap(c, c->lhead_lnum);
++ if (err)
++ goto out_unlock;
++ }
++
++ if (bud->start == 0) {
++ /*
++ * Before writing the LEB reference which refers an empty LEB
++ * to the log, we have to make sure it is mapped, because
++ * otherwise we'd risk to refer an LEB with garbage in case of
++ * an unclean reboot, because the target LEB might have been
++ * unmapped, but not yet physically erased.
++ */
++ err = ubi_leb_map(c->ubi, bud->lnum, UBI_SHORTTERM);
++ if (err)
++ goto out_unlock;
++ }
++
++ dbg_log("write ref LEB %d:%d",
++ c->lhead_lnum, c->lhead_offs);
++ err = ubifs_write_node(c, ref, UBIFS_REF_NODE_SZ, c->lhead_lnum,
++ c->lhead_offs, UBI_SHORTTERM);
++ c->lhead_offs += c->ref_node_alsz;
++ if (err)
++ goto out_unlock;
++
++ ubifs_add_bud(c, bud);
++
++ mutex_unlock(&c->log_mutex);
++ kfree(ref);
++ return 0;
++
++out_unlock:
++ mutex_unlock(&c->log_mutex);
++ kfree(ref);
++ kfree(bud);
++ return err;
++}
++
++/**
++ * remove_buds - remove used buds.
++ * @c: UBIFS file-system description object
++ *
++ * This function removes use buds from the buds tree. It does not remove the
++ * buds which are pointed to by journal heads.
++ */
++static void remove_buds(struct ubifs_info *c)
++{
++ struct rb_node *p;
++
++ ubifs_assert(list_empty(&c->old_buds));
++ c->cmt_bud_bytes = 0;
++ spin_lock(&c->buds_lock);
++ p = rb_first(&c->buds);
++ while (p) {
++ struct rb_node *p1 = p;
++ struct ubifs_bud *bud;
++ struct ubifs_wbuf *wbuf;
++
++ p = rb_next(p);
++ bud = rb_entry(p1, struct ubifs_bud, rb);
++ wbuf = &c->jheads[bud->jhead].wbuf;
++
++ if (wbuf->lnum == bud->lnum) {
++ /*
++ * Do not remove buds which are pointed to by journal
++ * heads (non-closed buds).
++ */
++ c->cmt_bud_bytes += wbuf->offs - bud->start;
++ dbg_log("preserve %d:%d, jhead %d, bud bytes %d, "
++ "cmt_bud_bytes %lld", bud->lnum, bud->start,
++ bud->jhead, wbuf->offs - bud->start,
++ c->cmt_bud_bytes);
++ bud->start = wbuf->offs;
++ } else {
++ c->cmt_bud_bytes += c->leb_size - bud->start;
++ dbg_log("remove %d:%d, jhead %d, bud bytes %d, "
++ "cmt_bud_bytes %lld", bud->lnum, bud->start,
++ bud->jhead, c->leb_size - bud->start,
++ c->cmt_bud_bytes);
++ rb_erase(p1, &c->buds);
++ list_del(&bud->list);
++ /*
++ * If the commit does not finish, the recovery will need
++ * to replay the journal, in which case the old buds
++ * must be unchanged. Do not release them until post
++ * commit i.e. do not allow them to be garbage
++ * collected.
++ */
++ list_add(&bud->list, &c->old_buds);
++ }
++ }
++ spin_unlock(&c->buds_lock);
++}
++
++/**
++ * ubifs_log_start_commit - start commit.
++ * @c: UBIFS file-system description object
++ * @ltail_lnum: return new log tail LEB number
++ *
++ * The commit operation starts with writing "commit start" node to the log and
++ * reference nodes for all journal heads which will define new journal after
++ * the commit has been finished. The commit start and reference nodes are
++ * written in one go to the nearest empty log LEB (hence, when commit is
++ * finished UBIFS may safely unmap all the previous log LEBs). This function
++ * returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
++{
++ void *buf;
++ struct ubifs_cs_node *cs;
++ struct ubifs_ref_node *ref;
++ int err, i, max_len, len;
++
++ err = dbg_check_bud_bytes(c);
++ if (err)
++ return err;
++
++ max_len = UBIFS_CS_NODE_SZ + c->jhead_cnt * UBIFS_REF_NODE_SZ;
++ max_len = ALIGN(max_len, c->min_io_size);
++ buf = cs = kmalloc(max_len, GFP_NOFS);
++ if (!buf)
++ return -ENOMEM;
++
++ cs->ch.node_type = UBIFS_CS_NODE;
++ cs->cmt_no = cpu_to_le64(c->cmt_no + 1);
++ ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0);
++
++ /*
++ * Note, we do not lock 'c->log_mutex' because this is the commit start
++ * phase and we are exclusively using the log. And we do not lock
++ * write-buffer because nobody can write to the file-system at this
++ * phase.
++ */
++
++ len = UBIFS_CS_NODE_SZ;
++ for (i = 0; i < c->jhead_cnt; i++) {
++ int lnum = c->jheads[i].wbuf.lnum;
++ int offs = c->jheads[i].wbuf.offs;
++
++ if (lnum == -1 || offs == c->leb_size)
++ continue;
++
++ dbg_log("add ref to LEB %d:%d for jhead %d", lnum, offs, i);
++ ref = buf + len;
++ ref->ch.node_type = UBIFS_REF_NODE;
++ ref->lnum = cpu_to_le32(lnum);
++ ref->offs = cpu_to_le32(offs);
++ ref->jhead = cpu_to_le32(i);
++
++ ubifs_prepare_node(c, ref, UBIFS_REF_NODE_SZ, 0);
++ len += UBIFS_REF_NODE_SZ;
++ }
++
++ ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len);
++
++ /* Switch to the next log LEB */
++ if (c->lhead_offs) {
++ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum);
++ c->lhead_offs = 0;
++ }
++
++ if (c->lhead_offs == 0) {
++ /* Must ensure next LEB has been unmapped */
++ err = ubifs_leb_unmap(c, c->lhead_lnum);
++ if (err)
++ goto out;
++ }
++
++ len = ALIGN(len, c->min_io_size);
++ dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len);
++ err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len, UBI_SHORTTERM);
++ if (err)
++ goto out;
++
++ *ltail_lnum = c->lhead_lnum;
++
++ c->lhead_offs += len;
++ if (c->lhead_offs == c->leb_size) {
++ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum);
++ c->lhead_offs = 0;
++ }
++
++ remove_buds(c);
++
++ /*
++ * We have started the commit and now users may use the rest of the log
++ * for new writes.
++ */
++ c->min_log_bytes = 0;
++
++out:
++ kfree(buf);
++ return err;
++}
++
++/**
++ * ubifs_log_end_commit - end commit.
++ * @c: UBIFS file-system description object
++ * @ltail_lnum: new log tail LEB number
++ *
++ * This function is called on when the commit operation was finished. It
++ * moves log tail to new position and unmaps LEBs which contain obsolete data.
++ * Returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum)
++{
++ int err;
++
++ /*
++ * At this phase we have to lock 'c->log_mutex' because UBIFS allows FS
++ * writes during commit. Its only short "commit" start phase when
++ * writers are blocked.
++ */
++ mutex_lock(&c->log_mutex);
++
++ dbg_log("old tail was LEB %d:0, new tail is LEB %d:0",
++ c->ltail_lnum, ltail_lnum);
++
++ c->ltail_lnum = ltail_lnum;
++ /*
++ * The commit is finished and from now on it must be guaranteed that
++ * there is always enough space for the next commit.
++ */
++ c->min_log_bytes = c->leb_size;
++
++ spin_lock(&c->buds_lock);
++ c->bud_bytes -= c->cmt_bud_bytes;
++ spin_unlock(&c->buds_lock);
++
++ err = dbg_check_bud_bytes(c);
++
++ mutex_unlock(&c->log_mutex);
++ return err;
++}
++
++/**
++ * ubifs_log_post_commit - things to do after commit is completed.
++ * @c: UBIFS file-system description object
++ * @old_ltail_lnum: old log tail LEB number
++ *
++ * Release buds only after commit is completed, because they must be unchanged
++ * if recovery is needed.
++ *
++ * Unmap log LEBs only after commit is completed, because they may be needed for
++ * recovery.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum)
++{
++ int lnum, err = 0;
++
++ while (!list_empty(&c->old_buds)) {
++ struct ubifs_bud *bud;
++
++ bud = list_entry(c->old_buds.next, struct ubifs_bud, list);
++ err = ubifs_return_leb(c, bud->lnum);
++ if (err)
++ return err;
++ list_del(&bud->list);
++ kfree(bud);
++ }
++ mutex_lock(&c->log_mutex);
++ for (lnum = old_ltail_lnum; lnum != c->ltail_lnum;
++ lnum = next_log_lnum(c, lnum)) {
++ dbg_log("unmap log LEB %d", lnum);
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ goto out;
++ }
++out:
++ mutex_unlock(&c->log_mutex);
++ return err;
++}
++
++/**
++ * struct done_ref - references that have been done.
++ * @rb: rb-tree node
++ * @lnum: LEB number
++ */
++struct done_ref {
++ struct rb_node rb;
++ int lnum;
++};
++
++/**
++ * done_already - determine if a reference has been done already.
++ * @done_tree: rb-tree to store references that have been done
++ * @lnum: LEB number of reference
++ *
++ * This function returns %1 if the reference has been done, %0 if not, otherwise
++ * a negative error code is returned.
++ */
++static int done_already(struct rb_root *done_tree, int lnum)
++{
++ struct rb_node **p = &done_tree->rb_node, *parent = NULL;
++ struct done_ref *dr;
++
++ while (*p) {
++ parent = *p;
++ dr = rb_entry(parent, struct done_ref, rb);
++ if (lnum < dr->lnum)
++ p = &(*p)->rb_left;
++ else if (lnum > dr->lnum)
++ p = &(*p)->rb_right;
++ else
++ return 1;
++ }
++
++ dr = kzalloc(sizeof(struct done_ref), GFP_NOFS);
++ if (!dr)
++ return -ENOMEM;
++
++ dr->lnum = lnum;
++
++ rb_link_node(&dr->rb, parent, p);
++ rb_insert_color(&dr->rb, done_tree);
++
++ return 0;
++}
++
++/**
++ * destroy_done_tree - destroy the done tree.
++ * @done_tree: done tree to destroy
++ */
++static void destroy_done_tree(struct rb_root *done_tree)
++{
++ struct rb_node *this = done_tree->rb_node;
++ struct done_ref *dr;
++
++ while (this) {
++ if (this->rb_left) {
++ this = this->rb_left;
++ continue;
++ } else if (this->rb_right) {
++ this = this->rb_right;
++ continue;
++ }
++ dr = rb_entry(this, struct done_ref, rb);
++ this = rb_parent(this);
++ if (this) {
++ if (this->rb_left == &dr->rb)
++ this->rb_left = NULL;
++ else
++ this->rb_right = NULL;
++ }
++ kfree(dr);
++ }
++}
++
++/**
++ * add_node - add a node to the consolidated log.
++ * @c: UBIFS file-system description object
++ * @buf: buffer to which to add
++ * @lnum: LEB number to which to write is passed and returned here
++ * @offs: offset to where to write is passed and returned here
++ * @node: node to add
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int add_node(struct ubifs_info *c, void *buf, int *lnum, int *offs,
++ void *node)
++{
++ struct ubifs_ch *ch = node;
++ int len = le32_to_cpu(ch->len), remains = c->leb_size - *offs;
++
++ if (len > remains) {
++ int sz = ALIGN(*offs, c->min_io_size), err;
++
++ ubifs_pad(c, buf + *offs, sz - *offs);
++ err = ubi_leb_change(c->ubi, *lnum, buf, sz, UBI_SHORTTERM);
++ if (err)
++ return err;
++ *lnum = next_log_lnum(c, *lnum);
++ *offs = 0;
++ }
++ memcpy(buf + *offs, node, len);
++ *offs += ALIGN(len, 8);
++ return 0;
++}
++
++/**
++ * ubifs_consolidate_log - consolidate the log.
++ * @c: UBIFS file-system description object
++ *
++ * Repeated failed commits could cause the log to be full, but at least 1 LEB is
++ * needed for commit. This function rewrites the reference nodes in the log
++ * omitting duplicates, and failed CS nodes, and leaving no gaps.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_consolidate_log(struct ubifs_info *c)
++{
++ struct ubifs_scan_leb *sleb;
++ struct ubifs_scan_node *snod;
++ struct rb_root done_tree = RB_ROOT;
++ int lnum, err, first = 1, write_lnum, offs = 0;
++ void *buf;
++
++ dbg_rcvry("log tail LEB %d, log head LEB %d", c->ltail_lnum,
++ c->lhead_lnum);
++ buf = vmalloc(c->leb_size);
++ if (!buf)
++ return -ENOMEM;
++ lnum = c->ltail_lnum;
++ write_lnum = lnum;
++ while (1) {
++ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
++ if (IS_ERR(sleb)) {
++ err = PTR_ERR(sleb);
++ goto out_free;
++ }
++ list_for_each_entry(snod, &sleb->nodes, list) {
++ switch (snod->type) {
++ case UBIFS_REF_NODE: {
++ struct ubifs_ref_node *ref = snod->node;
++ int ref_lnum = le32_to_cpu(ref->lnum);
++
++ err = done_already(&done_tree, ref_lnum);
++ if (err < 0)
++ goto out_scan;
++ if (err != 1) {
++ err = add_node(c, buf, &write_lnum,
++ &offs, snod->node);
++ if (err)
++ goto out_scan;
++ }
++ break;
++ }
++ case UBIFS_CS_NODE:
++ if (!first)
++ break;
++ err = add_node(c, buf, &write_lnum, &offs,
++ snod->node);
++ if (err)
++ goto out_scan;
++ first = 0;
++ break;
++ }
++ }
++ ubifs_scan_destroy(sleb);
++ if (lnum == c->lhead_lnum)
++ break;
++ lnum = next_log_lnum(c, lnum);
++ }
++ if (offs) {
++ int sz = ALIGN(offs, c->min_io_size);
++
++ ubifs_pad(c, buf + offs, sz - offs);
++ err = ubi_leb_change(c->ubi, write_lnum, buf, sz,
++ UBI_SHORTTERM);
++ if (err)
++ goto out_free;
++ offs = ALIGN(offs, c->min_io_size);
++ }
++ destroy_done_tree(&done_tree);
++ vfree(buf);
++ if (write_lnum == c->lhead_lnum) {
++ ubifs_err("log is too full");
++ return -EINVAL;
++ }
++ /* Unmap remaining LEBs */
++ lnum = write_lnum;
++ do {
++ lnum = next_log_lnum(c, lnum);
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ } while (lnum != c->lhead_lnum);
++ c->lhead_lnum = write_lnum;
++ c->lhead_offs = offs;
++ dbg_rcvry("new log head at %d:%d", c->lhead_lnum, c->lhead_offs);
++ return 0;
++
++out_scan:
++ ubifs_scan_destroy(sleb);
++out_free:
++ destroy_done_tree(&done_tree);
++ vfree(buf);
++ return err;
++}
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++/**
++ * dbg_check_bud_bytes - make sure bud bytes calculation are all right.
++ * @c: UBIFS file-system description object
++ *
++ * This function makes sure the amount of flash space used by closed buds
++ * ('c->bud_bytes' is correct). Returns zero in case of success and %-EINVAL in
++ * case of failure.
++ */
++static int dbg_check_bud_bytes(struct ubifs_info *c)
++{
++ int i, err = 0;
++ struct ubifs_bud *bud;
++ long long bud_bytes = 0;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
++ return 0;
++
++ spin_lock(&c->buds_lock);
++ for (i = 0; i < c->jhead_cnt; i++)
++ list_for_each_entry(bud, &c->jheads[i].buds_list, list)
++ bud_bytes += c->leb_size - bud->start;
++
++ if (c->bud_bytes != bud_bytes) {
++ ubifs_err("bad bud_bytes %lld, calculated %lld",
++ c->bud_bytes, bud_bytes);
++ err = -EINVAL;
++ }
++ spin_unlock(&c->buds_lock);
++
++ return err;
++}
++
++#endif /* CONFIG_UBIFS_FS_DEBUG */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/lprops.c avr32-2.6/fs/ubifs/lprops.c
+--- linux-2.6.25.6/fs/ubifs/lprops.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/lprops.c 2008-06-12 15:09:45.371816276 +0200
+@@ -0,0 +1,1355 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ */
++
++/*
++ * This file implements the functions that access LEB properties and their
++ * categories. LEBs are categorized based on the needs of UBIFS, and the
++ * categories are stored as either heaps or lists to provide a fast way of
++ * finding a LEB in a particular category. For example, UBIFS may need to find
++ * an empty LEB for the journal, or a very dirty LEB for garbage collection.
++ */
++
++#include "ubifs.h"
++
++/**
++ * get_heap_comp_val - get the LEB properties value for heap comparisons.
++ * @lprops: LEB properties
++ * @cat: LEB category
++ */
++static int get_heap_comp_val(struct ubifs_lprops *lprops, int cat)
++{
++ switch (cat) {
++ case LPROPS_FREE:
++ return lprops->free;
++ case LPROPS_DIRTY_IDX:
++ return lprops->free + lprops->dirty;
++ default:
++ return lprops->dirty;
++ }
++}
++
++/**
++ * move_up_lpt_heap - move a new heap entry up as far as possible.
++ * @c: UBIFS file-system description object
++ * @heap: LEB category heap
++ * @lprops: LEB properties to move
++ * @cat: LEB category
++ *
++ * New entries to a heap are added at the bottom and then moved up until the
++ * parent's value is greater. In the case of LPT's category heaps, the value
++ * is either the amount of free space or the amount of dirty space, depending
++ * on the category.
++ */
++static void move_up_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
++ struct ubifs_lprops *lprops, int cat)
++{
++ int val1, val2, hpos;
++
++ hpos = lprops->hpos;
++ if (!hpos)
++ return; /* Already top of the heap */
++ val1 = get_heap_comp_val(lprops, cat);
++ /* Compare to parent and, if greater, move up the heap */
++ do {
++ int ppos = (hpos - 1) / 2;
++
++ val2 = get_heap_comp_val(heap->arr[ppos], cat);
++ if (val2 >= val1)
++ return;
++ /* Greater than parent so move up */
++ heap->arr[ppos]->hpos = hpos;
++ heap->arr[hpos] = heap->arr[ppos];
++ heap->arr[ppos] = lprops;
++ lprops->hpos = ppos;
++ hpos = ppos;
++ } while (hpos);
++}
++
++/**
++ * adjust_lpt_heap - move a changed heap entry up or down the heap.
++ * @c: UBIFS file-system description object
++ * @heap: LEB category heap
++ * @lprops: LEB properties to move
++ * @hpos: heap position of @lprops
++ * @cat: LEB category
++ *
++ * Changed entries in a heap are moved up or down until the parent's value is
++ * greater. In the case of LPT's category heaps, the value is either the amount
++ * of free space or the amount of dirty space, depending on the category.
++ */
++static void adjust_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
++ struct ubifs_lprops *lprops, int hpos, int cat)
++{
++ int val1, val2, val3, cpos;
++
++ val1 = get_heap_comp_val(lprops, cat);
++ /* Compare to parent and, if greater than parent, move up the heap */
++ if (hpos) {
++ int ppos = (hpos - 1) / 2;
++
++ val2 = get_heap_comp_val(heap->arr[ppos], cat);
++ if (val1 > val2) {
++ /* Greater than parent so move up */
++ while (1) {
++ heap->arr[ppos]->hpos = hpos;
++ heap->arr[hpos] = heap->arr[ppos];
++ heap->arr[ppos] = lprops;
++ lprops->hpos = ppos;
++ hpos = ppos;
++ if (!hpos)
++ return;
++ ppos = (hpos - 1) / 2;
++ val2 = get_heap_comp_val(heap->arr[ppos], cat);
++ if (val1 <= val2)
++ return;
++ /* Still greater than parent so keep going */
++ }
++ }
++ }
++ /* Not greater than parent, so compare to children */
++ while (1) {
++ /* Compare to left child */
++ cpos = hpos * 2 + 1;
++ if (cpos >= heap->cnt)
++ return;
++ val2 = get_heap_comp_val(heap->arr[cpos], cat);
++ if (val1 < val2) {
++ /* Less than left child, so promote biggest child */
++ if (cpos + 1 < heap->cnt) {
++ val3 = get_heap_comp_val(heap->arr[cpos + 1],
++ cat);
++ if (val3 > val2)
++ cpos += 1; /* Right child is bigger */
++ }
++ heap->arr[cpos]->hpos = hpos;
++ heap->arr[hpos] = heap->arr[cpos];
++ heap->arr[cpos] = lprops;
++ lprops->hpos = cpos;
++ hpos = cpos;
++ continue;
++ }
++ /* Compare to right child */
++ cpos += 1;
++ if (cpos >= heap->cnt)
++ return;
++ val3 = get_heap_comp_val(heap->arr[cpos], cat);
++ if (val1 < val3) {
++ /* Less than right child, so promote right child */
++ heap->arr[cpos]->hpos = hpos;
++ heap->arr[hpos] = heap->arr[cpos];
++ heap->arr[cpos] = lprops;
++ lprops->hpos = cpos;
++ hpos = cpos;
++ continue;
++ }
++ return;
++ }
++}
++
++/**
++ * add_to_lpt_heap - add LEB properties to a LEB category heap.
++ * @c: UBIFS file-system description object
++ * @lprops: LEB properties to add
++ * @cat: LEB category
++ *
++ * This function returns %1 if @lprops is added to the heap for LEB category
++ * @cat, otherwise %0 is returned because the heap is full.
++ */
++static int add_to_lpt_heap(struct ubifs_info *c, struct ubifs_lprops *lprops,
++ int cat)
++{
++ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1];
++
++ if (heap->cnt >= heap->max_cnt) {
++ const int b = LPT_HEAP_SZ / 2 - 1;
++ int cpos, val1, val2;
++
++ /* Compare to some other LEB on the bottom of heap */
++ /* Pick a position kind of randomly */
++ cpos = (((size_t)lprops >> 4) & b) + b;
++ ubifs_assert(cpos >= b);
++ ubifs_assert(cpos < LPT_HEAP_SZ);
++ ubifs_assert(cpos < heap->cnt);
++
++ val1 = get_heap_comp_val(lprops, cat);
++ val2 = get_heap_comp_val(heap->arr[cpos], cat);
++ if (val1 > val2) {
++ struct ubifs_lprops *lp;
++
++ lp = heap->arr[cpos];
++ lp->flags &= ~LPROPS_CAT_MASK;
++ lp->flags |= LPROPS_UNCAT;
++ list_add(&lp->list, &c->uncat_list);
++ lprops->hpos = cpos;
++ heap->arr[cpos] = lprops;
++ move_up_lpt_heap(c, heap, lprops, cat);
++ dbg_check_heap(c, heap, cat, lprops->hpos);
++ return 1; /* Added to heap */
++ }
++ dbg_check_heap(c, heap, cat, -1);
++ return 0; /* Not added to heap */
++ } else {
++ lprops->hpos = heap->cnt++;
++ heap->arr[lprops->hpos] = lprops;
++ move_up_lpt_heap(c, heap, lprops, cat);
++ dbg_check_heap(c, heap, cat, lprops->hpos);
++ return 1; /* Added to heap */
++ }
++}
++
++/**
++ * remove_from_lpt_heap - remove LEB properties from a LEB category heap.
++ * @c: UBIFS file-system description object
++ * @lprops: LEB properties to remove
++ * @cat: LEB category
++ */
++static void remove_from_lpt_heap(struct ubifs_info *c,
++ struct ubifs_lprops *lprops, int cat)
++{
++ struct ubifs_lpt_heap *heap;
++ int hpos = lprops->hpos;
++
++ heap = &c->lpt_heap[cat - 1];
++ ubifs_assert(hpos >= 0 && hpos < heap->cnt);
++ ubifs_assert(heap->arr[hpos] == lprops);
++ heap->cnt -= 1;
++ if (hpos < heap->cnt) {
++ heap->arr[hpos] = heap->arr[heap->cnt];
++ heap->arr[hpos]->hpos = hpos;
++ adjust_lpt_heap(c, heap, heap->arr[hpos], hpos, cat);
++ }
++ dbg_check_heap(c, heap, cat, -1);
++}
++
++/**
++ * lpt_heap_replace - replace lprops in a category heap.
++ * @c: UBIFS file-system description object
++ * @old_lprops: LEB properties to replace
++ * @new_lprops: LEB properties with which to replace
++ * @cat: LEB category
++ *
++ * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode)
++ * and the lprops that the pnode contains. When that happens, references in
++ * the category heaps to those lprops must be updated to point to the new
++ * lprops. This function does that.
++ */
++static void lpt_heap_replace(struct ubifs_info *c,
++ struct ubifs_lprops *old_lprops,
++ struct ubifs_lprops *new_lprops, int cat)
++{
++ struct ubifs_lpt_heap *heap;
++ int hpos = new_lprops->hpos;
++
++ heap = &c->lpt_heap[cat - 1];
++ heap->arr[hpos] = new_lprops;
++}
++
++/**
++ * ubifs_add_to_cat - add LEB properties to a category list or heap.
++ * @c: UBIFS file-system description object
++ * @lprops: LEB properties to add
++ * @cat: LEB category to which to add
++ *
++ * LEB properties are categorized to enable fast find operations.
++ */
++void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
++ int cat)
++{
++ switch (cat) {
++ case LPROPS_DIRTY:
++ case LPROPS_DIRTY_IDX:
++ case LPROPS_FREE:
++ if (add_to_lpt_heap(c, lprops, cat))
++ break;
++ /* No more room on heap so make it uncategorized */
++ cat = LPROPS_UNCAT;
++ /* Fall through */
++ case LPROPS_UNCAT:
++ list_add(&lprops->list, &c->uncat_list);
++ break;
++ case LPROPS_EMPTY:
++ list_add(&lprops->list, &c->empty_list);
++ break;
++ case LPROPS_FREEABLE:
++ list_add(&lprops->list, &c->freeable_list);
++ c->freeable_cnt += 1;
++ break;
++ case LPROPS_FRDI_IDX:
++ list_add(&lprops->list, &c->frdi_idx_list);
++ break;
++ default:
++ ubifs_assert(0);
++ }
++ lprops->flags &= ~LPROPS_CAT_MASK;
++ lprops->flags |= cat;
++}
++
++/**
++ * ubifs_remove_from_cat - remove LEB properties from a category list or heap.
++ * @c: UBIFS file-system description object
++ * @lprops: LEB properties to remove
++ * @cat: LEB category from which to remove
++ *
++ * LEB properties are categorized to enable fast find operations.
++ */
++static void ubifs_remove_from_cat(struct ubifs_info *c,
++ struct ubifs_lprops *lprops, int cat)
++{
++ switch (cat) {
++ case LPROPS_DIRTY:
++ case LPROPS_DIRTY_IDX:
++ case LPROPS_FREE:
++ remove_from_lpt_heap(c, lprops, cat);
++ break;
++ case LPROPS_FREEABLE:
++ c->freeable_cnt -= 1;
++ ubifs_assert(c->freeable_cnt >= 0);
++ /* Fall through */
++ case LPROPS_UNCAT:
++ case LPROPS_EMPTY:
++ case LPROPS_FRDI_IDX:
++ ubifs_assert(!list_empty(&lprops->list));
++ list_del(&lprops->list);
++ break;
++ default:
++ ubifs_assert(0);
++ }
++}
++
++/**
++ * ubifs_replace_cat - replace lprops in a category list or heap.
++ * @c: UBIFS file-system description object
++ * @old_lprops: LEB properties to replace
++ * @new_lprops: LEB properties with which to replace
++ *
++ * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode)
++ * and the lprops that the pnode contains. When that happens, references in
++ * category lists and heaps must be replaced. This function does that.
++ */
++void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops,
++ struct ubifs_lprops *new_lprops)
++{
++ int cat;
++
++ cat = new_lprops->flags & LPROPS_CAT_MASK;
++ switch (cat) {
++ case LPROPS_DIRTY:
++ case LPROPS_DIRTY_IDX:
++ case LPROPS_FREE:
++ lpt_heap_replace(c, old_lprops, new_lprops, cat);
++ break;
++ case LPROPS_UNCAT:
++ case LPROPS_EMPTY:
++ case LPROPS_FREEABLE:
++ case LPROPS_FRDI_IDX:
++ list_replace(&old_lprops->list, &new_lprops->list);
++ break;
++ default:
++ ubifs_assert(0);
++ }
++}
++
++/**
++ * ubifs_ensure_cat - ensure LEB properties are categorized.
++ * @c: UBIFS file-system description object
++ * @lprops: LEB properties
++ *
++ * A LEB may have fallen off of the bottom of a heap, and ended up as
++ * uncategorized even though it has enough space for us now. If that is the case
++ * this function will put the LEB back onto a heap.
++ */
++void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops)
++{
++ int cat = lprops->flags & LPROPS_CAT_MASK;
++
++ if (cat != LPROPS_UNCAT)
++ return;
++ cat = ubifs_categorize_lprops(c, lprops);
++ if (cat == LPROPS_UNCAT)
++ return;
++ ubifs_remove_from_cat(c, lprops, LPROPS_UNCAT);
++ ubifs_add_to_cat(c, lprops, cat);
++}
++
++/**
++ * ubifs_categorize_lprops - categorize LEB properties.
++ * @c: UBIFS file-system description object
++ * @lprops: LEB properties to categorize
++ *
++ * LEB properties are categorized to enable fast find operations. This function
++ * returns the LEB category to which the LEB properties belong. Note however
++ * that if the LEB category is stored as a heap and the heap is full, the
++ * LEB properties may have their category changed to %LPROPS_UNCAT.
++ */
++int ubifs_categorize_lprops(const struct ubifs_info *c,
++ const struct ubifs_lprops *lprops)
++{
++ if (lprops->flags & LPROPS_TAKEN)
++ return LPROPS_UNCAT;
++
++ if (lprops->free == c->leb_size) {
++ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
++ return LPROPS_EMPTY;
++ }
++
++ if (lprops->free + lprops->dirty == c->leb_size) {
++ if (lprops->flags & LPROPS_INDEX)
++ return LPROPS_FRDI_IDX;
++ else
++ return LPROPS_FREEABLE;
++ }
++
++ if (lprops->flags & LPROPS_INDEX) {
++ if (lprops->dirty + lprops->free >= c->min_idx_node_sz)
++ return LPROPS_DIRTY_IDX;
++ } else {
++ if (lprops->dirty >= c->dead_wm &&
++ lprops->dirty > lprops->free)
++ return LPROPS_DIRTY;
++ if (lprops->free > 0)
++ return LPROPS_FREE;
++ }
++
++ return LPROPS_UNCAT;
++}
++
++/**
++ * change_category - change LEB properties category.
++ * @c: UBIFS file-system description object
++ * @lprops: LEB properties to recategorize
++ *
++ * LEB properties are categorized to enable fast find operations. When the LEB
++ * properties change they must be recategorized.
++ */
++static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops)
++{
++ int old_cat = lprops->flags & LPROPS_CAT_MASK;
++ int new_cat = ubifs_categorize_lprops(c, lprops);
++
++ if (old_cat == new_cat) {
++ struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1];
++
++ /* lprops on a heap now must be moved up or down */
++ if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT)
++ return; /* Not on a heap */
++ heap = &c->lpt_heap[new_cat - 1];
++ adjust_lpt_heap(c, heap, lprops, lprops->hpos, new_cat);
++ } else {
++ ubifs_remove_from_cat(c, lprops, old_cat);
++ ubifs_add_to_cat(c, lprops, new_cat);
++ }
++}
++
++/**
++ * ubifs_get_lprops - get reference to LEB properties.
++ * @c: the UBIFS file-system description object
++ *
++ * This function locks lprops. Lprops have to be unlocked by
++ * 'ubifs_release_lprops()'.
++ */
++void ubifs_get_lprops(struct ubifs_info *c)
++{
++ mutex_lock(&c->lp_mutex);
++}
++
++/**
++ * calc_dark - calculate LEB dark space size.
++ * @c: the UBIFS file-system description object
++ * @spc: amount of free and dirty space in the LEB
++ *
++ * This function calculates amount of dark space in an LEB which has @spc bytes
++ * of free and dirty space. Returns the calculations result.
++ *
++ * Dark space is the space which is not always usable - it depends on which
++ * nodes are written in which order. E.g., if an LEB has only 512 free bytes,
++ * it is dark space, because it cannot fit a large data node. So UBIFS cannot
++ * count on this LEB and treat these 512 bytes as usable because it is not true
++ * if, for example, only big chunks of uncompressible data will be written to
++ * the FS.
++ */
++static int calc_dark(struct ubifs_info *c, int spc)
++{
++ ubifs_assert(!(spc & 7));
++
++ if (spc < c->dark_wm)
++ return spc;
++
++ /*
++ * If we have slightly more space then the dark space watermark, we can
++ * anyway safely assume it we'll be able to write a node of the
++ * smallest size there.
++ */
++ if (spc - c->dark_wm < MIN_WRITE_SZ)
++ return spc - MIN_WRITE_SZ;
++
++ return c->dark_wm;
++}
++
++/**
++ * is_lprops_dirty - determine if LEB properties are dirty.
++ * @c: the UBIFS file-system description object
++ * @lprops: LEB properties to test
++ */
++static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops)
++{
++ struct ubifs_pnode *pnode;
++ int pos;
++
++ pos = (lprops->lnum - c->main_first) & (UBIFS_LPT_FANOUT - 1);
++ pnode = (struct ubifs_pnode *)container_of(lprops - pos,
++ struct ubifs_pnode,
++ lprops[0]);
++ return !test_bit(COW_ZNODE, &pnode->flags) &&
++ test_bit(DIRTY_CNODE, &pnode->flags);
++}
++
++/**
++ * ubifs_change_lp - change LEB properties.
++ * @c: the UBIFS file-system description object
++ * @lp: LEB properties to change
++ * @free: new free space amount
++ * @dirty: new dirty space amount
++ * @flags: new flags
++ * @idx_gc_cnt: change to the count of idx_gc list
++ *
++ * This function changes LEB properties. This function does not change a LEB
++ * property (@free, @dirty or @flag) if the value passed is %LPROPS_NC.
++ *
++ * This function returns a pointer to the updated LEB properties on success
++ * and a negative error code on failure. N.B. the LEB properties may have had to
++ * be copied (due to COW) and consequently the pointer returned may not be the
++ * same as the pointer passed.
++ */
++const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
++ const struct ubifs_lprops *lp,
++ int free, int dirty, int flags,
++ int idx_gc_cnt)
++{
++ /*
++ * This is the only function that is allowed to change lprops, so we
++ * discard the const qualifier.
++ */
++ struct ubifs_lprops *lprops = (struct ubifs_lprops *)lp;
++
++ dbg_lp("LEB %d, free %d, dirty %d, flags %d",
++ lprops->lnum, free, dirty, flags);
++
++ ubifs_assert(mutex_is_locked(&c->lp_mutex));
++ ubifs_assert(c->lst.empty_lebs >= 0 &&
++ c->lst.empty_lebs <= c->main_lebs);
++ ubifs_assert(c->freeable_cnt >= 0);
++ ubifs_assert(c->freeable_cnt <= c->main_lebs);
++ ubifs_assert(c->lst.taken_empty_lebs >= 0);
++ ubifs_assert(c->lst.taken_empty_lebs <= c->lst.empty_lebs);
++ ubifs_assert(!(c->lst.total_free & 7) && !(c->lst.total_dirty & 7));
++ ubifs_assert(!(c->lst.total_dead & 7) && !(c->lst.total_dark & 7));
++ ubifs_assert(!(c->lst.total_used & 7));
++ ubifs_assert(free == LPROPS_NC || free >= 0);
++ ubifs_assert(dirty == LPROPS_NC || dirty >= 0);
++
++ if (!is_lprops_dirty(c, lprops)) {
++ lprops = ubifs_lpt_lookup_dirty(c, lprops->lnum);
++ if (IS_ERR(lprops))
++ return lprops;
++ } else
++ ubifs_assert(lprops == ubifs_lpt_lookup_dirty(c, lprops->lnum));
++
++ ubifs_assert(!(lprops->free & 7) && !(lprops->dirty & 7));
++
++ spin_lock(&c->space_lock);
++
++ if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size)
++ c->lst.taken_empty_lebs -= 1;
++
++ if (!(lprops->flags & LPROPS_INDEX)) {
++ int old_spc;
++
++ old_spc = lprops->free + lprops->dirty;
++ if (old_spc < c->dead_wm)
++ c->lst.total_dead -= old_spc;
++ else
++ c->lst.total_dark -= calc_dark(c, old_spc);
++
++ c->lst.total_used -= c->leb_size - old_spc;
++ }
++
++ if (free != LPROPS_NC) {
++ free = ALIGN(free, 8);
++ c->lst.total_free += free - lprops->free;
++
++ /* Increase or decrease empty LEBs counter if needed */
++ if (free == c->leb_size) {
++ if (lprops->free != c->leb_size)
++ c->lst.empty_lebs += 1;
++ } else if (lprops->free == c->leb_size)
++ c->lst.empty_lebs -= 1;
++ lprops->free = free;
++ }
++
++ if (dirty != LPROPS_NC) {
++ dirty = ALIGN(dirty, 8);
++ c->lst.total_dirty += dirty - lprops->dirty;
++ lprops->dirty = dirty;
++ }
++
++ if (flags != LPROPS_NC) {
++ /* Take care about indexing LEBs counter if needed */
++ if ((lprops->flags & LPROPS_INDEX)) {
++ if (!(flags & LPROPS_INDEX))
++ c->lst.idx_lebs -= 1;
++ } else if (flags & LPROPS_INDEX)
++ c->lst.idx_lebs += 1;
++ lprops->flags = flags;
++ }
++
++ if (!(lprops->flags & LPROPS_INDEX)) {
++ int new_spc;
++
++ new_spc = lprops->free + lprops->dirty;
++ if (new_spc < c->dead_wm)
++ c->lst.total_dead += new_spc;
++ else
++ c->lst.total_dark += calc_dark(c, new_spc);
++
++ c->lst.total_used += c->leb_size - new_spc;
++ }
++
++ if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size)
++ c->lst.taken_empty_lebs += 1;
++
++ change_category(c, lprops);
++
++ c->idx_gc_cnt += idx_gc_cnt;
++
++ spin_unlock(&c->space_lock);
++
++ return lprops;
++}
++
++/**
++ * ubifs_release_lprops - release lprops lock.
++ * @c: the UBIFS file-system description object
++ *
++ * This function has to be called after each 'ubifs_get_lprops()' call to
++ * unlock lprops.
++ */
++void ubifs_release_lprops(struct ubifs_info *c)
++{
++ ubifs_assert(mutex_is_locked(&c->lp_mutex));
++ ubifs_assert(c->lst.empty_lebs >= 0 &&
++ c->lst.empty_lebs <= c->main_lebs);
++
++ mutex_unlock(&c->lp_mutex);
++}
++
++/**
++ * ubifs_get_lp_stats - get lprops statistics.
++ * @c: UBIFS file-system description object
++ * @st: return statistics
++ */
++void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *st)
++{
++ spin_lock(&c->space_lock);
++ memcpy(st, &c->lst, sizeof(struct ubifs_lp_stats));
++ spin_unlock(&c->space_lock);
++}
++
++/**
++ * ubifs_change_one_lp - change LEB properties.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB to change properties for
++ * @free: amount of free space
++ * @dirty: amount of dirty space
++ * @flags_set: flags to set
++ * @flags_clean: flags to clean
++ * @idx_gc_cnt: change to the count of idx_gc list
++ *
++ * This function changes properties of LEB @lnum. It is a helper wrapper over
++ * 'ubifs_change_lp()' which hides lprops get/release. The arguments are the
++ * same as in case of 'ubifs_change_lp()'. Returns zero in case of success and
++ * a negative error code in case of failure.
++ */
++int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
++ int flags_set, int flags_clean, int idx_gc_cnt)
++{
++ int err = 0, flags;
++ const struct ubifs_lprops *lp;
++
++ ubifs_get_lprops(c);
++
++ lp = ubifs_lpt_lookup_dirty(c, lnum);
++ if (IS_ERR(lp)) {
++ err = PTR_ERR(lp);
++ goto out;
++ }
++
++ flags = (lp->flags | flags_set) & ~flags_clean;
++ lp = ubifs_change_lp(c, lp, free, dirty, flags, idx_gc_cnt);
++ if (IS_ERR(lp))
++ err = PTR_ERR(lp);
++
++out:
++ ubifs_release_lprops(c);
++ return err;
++}
++
++/**
++ * ubifs_update_one_lp - update LEB properties.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB to change properties for
++ * @free: amount of free space
++ * @dirty: amount of dirty space to add
++ * @flags_set: flags to set
++ * @flags_clean: flags to clean
++ *
++ * This function is the same as 'ubifs_change_one_lp()' but @dirty is added to
++ * current dirty space, not substitutes it.
++ */
++int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
++ int flags_set, int flags_clean)
++{
++ int err = 0, flags;
++ const struct ubifs_lprops *lp;
++
++ ubifs_get_lprops(c);
++
++ lp = ubifs_lpt_lookup_dirty(c, lnum);
++ if (IS_ERR(lp)) {
++ err = PTR_ERR(lp);
++ goto out;
++ }
++
++ flags = (lp->flags | flags_set) & ~flags_clean;
++ lp = ubifs_change_lp(c, lp, free, lp->dirty + dirty, flags, 0);
++ if (IS_ERR(lp))
++ err = PTR_ERR(lp);
++
++out:
++ ubifs_release_lprops(c);
++ return err;
++}
++
++/**
++ * ubifs_read_one_lp - read LEB properties.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB to read properties for
++ * @lp: where to store read properties
++ *
++ * This helper function reads properties of a LEB @lnum and stores them in @lp.
++ * Returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp)
++{
++ int err = 0;
++ const struct ubifs_lprops *lpp;
++
++ ubifs_get_lprops(c);
++
++ lpp = ubifs_lpt_lookup(c, lnum);
++ if (IS_ERR(lpp)) {
++ err = PTR_ERR(lpp);
++ goto out;
++ }
++
++ memcpy(lp, lpp, sizeof(struct ubifs_lprops));
++
++out:
++ ubifs_release_lprops(c);
++ return err;
++}
++
++/**
++ * ubifs_fast_find_free - try to find a LEB with free space quickly.
++ * @c: the UBIFS file-system description object
++ *
++ * This function returns LEB properties for a LEB with free space or %NULL if
++ * the function is unable to find a LEB quickly.
++ */
++const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c)
++{
++ struct ubifs_lprops *lprops;
++ struct ubifs_lpt_heap *heap;
++
++ ubifs_assert(mutex_is_locked(&c->lp_mutex));
++
++ heap = &c->lpt_heap[LPROPS_FREE - 1];
++ if (heap->cnt == 0)
++ return NULL;
++
++ lprops = heap->arr[0];
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
++ return lprops;
++}
++
++/**
++ * ubifs_fast_find_empty - try to find an empty LEB quickly.
++ * @c: the UBIFS file-system description object
++ *
++ * This function returns LEB properties for an empty LEB or %NULL if the
++ * function is unable to find an empty LEB quickly.
++ */
++const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c)
++{
++ struct ubifs_lprops *lprops;
++
++ ubifs_assert(mutex_is_locked(&c->lp_mutex));
++
++ if (list_empty(&c->empty_list))
++ return NULL;
++
++ lprops = list_entry(c->empty_list.next, struct ubifs_lprops, list);
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
++ ubifs_assert(lprops->free == c->leb_size);
++ return lprops;
++}
++
++/**
++ * ubifs_fast_find_freeable - try to find a freeable LEB quickly.
++ * @c: the UBIFS file-system description object
++ *
++ * This function returns LEB properties for a freeable LEB or %NULL if the
++ * function is unable to find a freeable LEB quickly.
++ */
++const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c)
++{
++ struct ubifs_lprops *lprops;
++
++ ubifs_assert(mutex_is_locked(&c->lp_mutex));
++
++ if (list_empty(&c->freeable_list))
++ return NULL;
++
++ lprops = list_entry(c->freeable_list.next, struct ubifs_lprops, list);
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
++ ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
++ ubifs_assert(c->freeable_cnt > 0);
++ return lprops;
++}
++
++/**
++ * ubifs_fast_find_frdi_idx - try to find a freeable index LEB quickly.
++ * @c: the UBIFS file-system description object
++ *
++ * This function returns LEB properties for a freeable index LEB or %NULL if the
++ * function is unable to find a freeable index LEB quickly.
++ */
++const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c)
++{
++ struct ubifs_lprops *lprops;
++
++ ubifs_assert(mutex_is_locked(&c->lp_mutex));
++
++ if (list_empty(&c->frdi_idx_list))
++ return NULL;
++
++ lprops = list_entry(c->frdi_idx_list.next, struct ubifs_lprops, list);
++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
++ ubifs_assert((lprops->flags & LPROPS_INDEX));
++ ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
++ return lprops;
++}
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++/**
++ * dbg_check_cats - check category heaps and lists.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int dbg_check_cats(struct ubifs_info *c)
++{
++ struct ubifs_lprops *lprops;
++ struct list_head *pos;
++ int i, cat;
++
++ if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
++ return 0;
++
++ list_for_each_entry(lprops, &c->empty_list, list) {
++ if (lprops->free != c->leb_size) {
++ ubifs_err("non-empty LEB %d on empty list "
++ "(free %d dirty %d flags %d)", lprops->lnum,
++ lprops->free, lprops->dirty, lprops->flags);
++ return -EINVAL;
++ }
++ if (lprops->flags & LPROPS_TAKEN) {
++ ubifs_err("taken LEB %d on empty list "
++ "(free %d dirty %d flags %d)", lprops->lnum,
++ lprops->free, lprops->dirty, lprops->flags);
++ return -EINVAL;
++ }
++ }
++
++ i = 0;
++ list_for_each_entry(lprops, &c->freeable_list, list) {
++ if (lprops->free + lprops->dirty != c->leb_size) {
++ ubifs_err("non-freeable LEB %d on freeable list "
++ "(free %d dirty %d flags %d)", lprops->lnum,
++ lprops->free, lprops->dirty, lprops->flags);
++ return -EINVAL;
++ }
++ if (lprops->flags & LPROPS_TAKEN) {
++ ubifs_err("taken LEB %d on freeable list "
++ "(free %d dirty %d flags %d)", lprops->lnum,
++ lprops->free, lprops->dirty, lprops->flags);
++ return -EINVAL;
++ }
++ i += 1;
++ }
++ if (i != c->freeable_cnt) {
++ ubifs_err("freeable list count %d expected %d", i,
++ c->freeable_cnt);
++ return -EINVAL;
++ }
++
++ i = 0;
++ list_for_each(pos, &c->idx_gc)
++ i += 1;
++ if (i != c->idx_gc_cnt) {
++ ubifs_err("idx_gc list count %d expected %d", i,
++ c->idx_gc_cnt);
++ return -EINVAL;
++ }
++
++ list_for_each_entry(lprops, &c->frdi_idx_list, list) {
++ if (lprops->free + lprops->dirty != c->leb_size) {
++ ubifs_err("non-freeable LEB %d on frdi_idx list "
++ "(free %d dirty %d flags %d)", lprops->lnum,
++ lprops->free, lprops->dirty, lprops->flags);
++ return -EINVAL;
++ }
++ if (lprops->flags & LPROPS_TAKEN) {
++ ubifs_err("taken LEB %d on frdi_idx list "
++ "(free %d dirty %d flags %d)", lprops->lnum,
++ lprops->free, lprops->dirty, lprops->flags);
++ return -EINVAL;
++ }
++ if (!(lprops->flags & LPROPS_INDEX)) {
++ ubifs_err("non-index LEB %d on frdi_idx list "
++ "(free %d dirty %d flags %d)", lprops->lnum,
++ lprops->free, lprops->dirty, lprops->flags);
++ return -EINVAL;
++ }
++ }
++
++ for (cat = 1; cat <= LPROPS_HEAP_CNT; cat++) {
++ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1];
++
++ for (i = 0; i < heap->cnt; i++) {
++ lprops = heap->arr[i];
++ if (!lprops) {
++ ubifs_err("null ptr in LPT heap cat %d", cat);
++ return -EINVAL;
++ }
++ if (lprops->hpos != i) {
++ ubifs_err("bad ptr in LPT heap cat %d", cat);
++ return -EINVAL;
++ }
++ if (lprops->flags & LPROPS_TAKEN) {
++ ubifs_err("taken LEB in LPT heap cat %d", cat);
++ return -EINVAL;
++ }
++ }
++ }
++
++ return 0;
++}
++
++void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
++ int add_pos)
++{
++ int i = 0, j, err = 0;
++
++ if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
++ return;
++
++ for (i = 0; i < heap->cnt; i++) {
++ struct ubifs_lprops *lprops = heap->arr[i];
++ struct ubifs_lprops *lp;
++
++ if (i != add_pos)
++ if ((lprops->flags & LPROPS_CAT_MASK) != cat) {
++ err = 1;
++ goto out;
++ }
++ if (lprops->hpos != i) {
++ err = 2;
++ goto out;
++ }
++ lp = ubifs_lpt_lookup(c, lprops->lnum);
++ if (IS_ERR(lp)) {
++ err = 3;
++ goto out;
++ }
++ if (lprops != lp) {
++ dbg_msg("lprops %zx lp %zx lprops->lnum %d lp->lnum %d",
++ (size_t)lprops, (size_t)lp, lprops->lnum,
++ lp->lnum);
++ err = 4;
++ goto out;
++ }
++ for (j = 0; j < i; j++) {
++ lp = heap->arr[j];
++ if (lp == lprops) {
++ err = 5;
++ goto out;
++ }
++ if (lp->lnum == lprops->lnum) {
++ err = 6;
++ goto out;
++ }
++ }
++ }
++out:
++ if (err) {
++ dbg_msg("failed cat %d hpos %d err %d", cat, i, err);
++ dbg_dump_stack();
++ dbg_dump_heap(c, heap, cat);
++ }
++}
++
++/**
++ * struct scan_check_data - data provided to scan callback function.
++ * @lst: LEB properties statistics
++ * @err: error code
++ */
++struct scan_check_data {
++ struct ubifs_lp_stats lst;
++ int err;
++};
++
++/**
++ * scan_check_cb - scan callback.
++ * @c: the UBIFS file-system description object
++ * @lp: LEB properties to scan
++ * @in_tree: whether the LEB properties are in main memory
++ * @data: information passed to and from the caller of the scan
++ *
++ * This function returns a code that indicates whether the scan should continue
++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
++ * (%LPT_SCAN_STOP).
++ */
++static int scan_check_cb(struct ubifs_info *c,
++ const struct ubifs_lprops *lp, int in_tree,
++ struct scan_check_data *data)
++{
++ struct ubifs_scan_leb *sleb;
++ struct ubifs_scan_node *snod;
++ struct ubifs_lp_stats *lst = &data->lst;
++ int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty;
++
++ cat = lp->flags & LPROPS_CAT_MASK;
++ if (cat != LPROPS_UNCAT) {
++ cat = ubifs_categorize_lprops(c, lp);
++ if (cat != (lp->flags & LPROPS_CAT_MASK)) {
++ ubifs_err("bad LEB category %d expected %d",
++ (lp->flags & LPROPS_CAT_MASK), cat);
++ goto out;
++ }
++ }
++
++ /* Check lp is on its category list (if it has one) */
++ if (in_tree) {
++ struct list_head *list = NULL;
++
++ switch (cat) {
++ case LPROPS_EMPTY:
++ list = &c->empty_list;
++ break;
++ case LPROPS_FREEABLE:
++ list = &c->freeable_list;
++ break;
++ case LPROPS_FRDI_IDX:
++ list = &c->frdi_idx_list;
++ break;
++ case LPROPS_UNCAT:
++ list = &c->uncat_list;
++ break;
++ }
++ if (list) {
++ struct ubifs_lprops *lprops;
++ int found = 0;
++
++ list_for_each_entry(lprops, list, list) {
++ if (lprops == lp) {
++ found = 1;
++ break;
++ }
++ }
++ if (!found) {
++ ubifs_err("bad LPT list (category %d)", cat);
++ goto out;
++ }
++ }
++ }
++
++ /* Check lp is on its category heap (if it has one) */
++ if (in_tree && cat > 0 && cat <= LPROPS_HEAP_CNT) {
++ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1];
++
++ if ((lp->hpos != -1 && heap->arr[lp->hpos]->lnum != lnum) ||
++ lp != heap->arr[lp->hpos]) {
++ ubifs_err("bad LPT heap (category %d)", cat);
++ goto out;
++ }
++ }
++
++ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
++ if (IS_ERR(sleb)) {
++ /*
++ * After an unclean unmount, empty and freeable LEBs
++ * may contain garbage.
++ */
++ if (lp->free == c->leb_size) {
++ ubifs_err("scan errors were in empty LEB "
++ "- continuing checking");
++ lst->empty_lebs += 1;
++ lst->total_free += c->leb_size;
++ lst->total_dark += calc_dark(c, c->leb_size);
++ return LPT_SCAN_CONTINUE;
++ }
++
++ if (lp->free + lp->dirty == c->leb_size &&
++ !(lp->flags & LPROPS_INDEX)) {
++ ubifs_err("scan errors were in freeable LEB "
++ "- continuing checking");
++ lst->total_free += lp->free;
++ lst->total_dirty += lp->dirty;
++ lst->total_dark += calc_dark(c, c->leb_size);
++ return LPT_SCAN_CONTINUE;
++ }
++ data->err = PTR_ERR(sleb);
++ return LPT_SCAN_STOP;
++ }
++
++ is_idx = -1;
++ list_for_each_entry(snod, &sleb->nodes, list) {
++ int found, level = 0;
++
++ cond_resched();
++
++ if (is_idx == -1)
++ is_idx = (snod->type == UBIFS_IDX_NODE) ? 1 : 0;
++
++ if (is_idx && snod->type != UBIFS_IDX_NODE) {
++ ubifs_err("indexing node in data LEB %d:%d",
++ lnum, snod->offs);
++ goto out_destroy;
++ }
++
++ if (snod->type == UBIFS_IDX_NODE) {
++ struct ubifs_idx_node *idx = snod->node;
++
++ key_read(c, ubifs_idx_key(c, idx), &snod->key);
++ level = le16_to_cpu(idx->level);
++ }
++
++ found = ubifs_tnc_has_node(c, &snod->key, level, lnum,
++ snod->offs, is_idx);
++ if (found) {
++ if (found < 0)
++ goto out_destroy;
++ used += ALIGN(snod->len, 8);
++ }
++ }
++
++ free = c->leb_size - sleb->endpt;
++ dirty = sleb->endpt - used;
++
++ if (free > c->leb_size || free < 0 || dirty > c->leb_size ||
++ dirty < 0) {
++ ubifs_err("bad calculated accounting for LEB %d: "
++ "free %d, dirty %d", lnum, free, dirty);
++ goto out_destroy;
++ }
++
++ if (lp->free + lp->dirty == c->leb_size &&
++ free + dirty == c->leb_size)
++ if ((is_idx && !(lp->flags & LPROPS_INDEX)) ||
++ (!is_idx && free == c->leb_size)) {
++ /*
++ * Empty or freeable LEBs could contain index
++ * nodes from an uncompleted commit due to an
++ * unclean unmount. Or they could be empty for
++ * the same reason.
++ */
++ free = lp->free;
++ dirty = lp->dirty;
++ is_idx = 0;
++ }
++
++ if (is_idx && lp->free + lp->dirty == free + dirty &&
++ lnum != c->ihead_lnum) {
++ /*
++ * After an unclean unmount, an index LEB could have a different
++ * amount of free space than the value recorded by lprops. That
++ * is because the in-the-gaps method may use free space or
++ * create free space (as a side-effect of using ubi_leb_change
++ * and not writing the whole LEB). The incorrect free space
++ * value is not a problem because the index is only ever
++ * allocated empty LEBs, so there will never be an attempt to
++ * write to the free space at the end of an index LEB - except
++ * by the in-the-gaps method for which it is not a problem.
++ */
++ free = lp->free;
++ dirty = lp->dirty;
++ }
++
++ if (lp->free != free || lp->dirty != dirty)
++ goto out_print;
++
++ if (is_idx && !(lp->flags & LPROPS_INDEX)) {
++ if (free == c->leb_size)
++ /* Free but not unmapped LEB, it's fine */
++ is_idx = 0;
++ else {
++ ubifs_err("indexing node without indexing "
++ "flag");
++ goto out_print;
++ }
++ }
++
++ if (!is_idx && (lp->flags & LPROPS_INDEX)) {
++ ubifs_err("data node with indexing flag");
++ goto out_print;
++ }
++
++ if (free == c->leb_size)
++ lst->empty_lebs += 1;
++
++ if (is_idx)
++ lst->idx_lebs += 1;
++
++ if (!(lp->flags & LPROPS_INDEX))
++ lst->total_used += c->leb_size - free - dirty;
++ lst->total_free += free;
++ lst->total_dirty += dirty;
++
++ if (!(lp->flags & LPROPS_INDEX)) {
++ int spc = free + dirty;
++
++ if (spc < c->dead_wm)
++ lst->total_dead += spc;
++ else
++ lst->total_dark += calc_dark(c, spc);
++ }
++
++ ubifs_scan_destroy(sleb);
++
++ return LPT_SCAN_CONTINUE;
++
++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);
++out_destroy:
++ ubifs_scan_destroy(sleb);
++out:
++ data->err = -EINVAL;
++ return LPT_SCAN_STOP;
++}
++
++/**
++ * dbg_check_lprops - check all LEB properties.
++ * @c: UBIFS file-system description object
++ *
++ * This function checks all LEB properties and makes sure they are all correct.
++ * It returns zero if everything is fine, %-EINVAL if there is an inconsistency
++ * and other negative error codes in case of other errors. This function is
++ * called while the file system is locked (because of commit start), so no
++ * additional locking is required. Note that locking the LPT mutex would cause
++ * a circular lock dependency with the TNC mutex.
++ */
++int dbg_check_lprops(struct ubifs_info *c)
++{
++ int i, err;
++ struct scan_check_data data;
++ struct ubifs_lp_stats *lst = &data.lst;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
++ return 0;
++
++ /*
++ * As we are going to scan the media, the write buffers have to be
++ * synchronized.
++ */
++ for (i = 0; i < c->jhead_cnt; i++) {
++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
++ if (err)
++ return err;
++ }
++
++ memset(lst, 0, sizeof(struct ubifs_lp_stats));
++
++ data.err = 0;
++ err = ubifs_lpt_scan_nolock(c, c->main_first, c->leb_cnt - 1,
++ (ubifs_lpt_scan_callback)scan_check_cb,
++ &data);
++ if (err && err != -ENOSPC)
++ goto out;
++ if (data.err) {
++ err = data.err;
++ goto out;
++ }
++
++ if (lst->empty_lebs != c->lst.empty_lebs ||
++ lst->idx_lebs != c->lst.idx_lebs ||
++ lst->total_free != c->lst.total_free ||
++ lst->total_dirty != c->lst.total_dirty ||
++ lst->total_used != c->lst.total_used) {
++ ubifs_err("bad overall accounting");
++ ubifs_err("calculated: empty_lebs %d, idx_lebs %d, "
++ "total_free %lld, total_dirty %lld, total_used %lld",
++ lst->empty_lebs, lst->idx_lebs, lst->total_free,
++ lst->total_dirty, lst->total_used);
++ ubifs_err("read from lprops: empty_lebs %d, idx_lebs %d, "
++ "total_free %lld, total_dirty %lld, total_used %lld",
++ c->lst.empty_lebs, c->lst.idx_lebs, c->lst.total_free,
++ c->lst.total_dirty, c->lst.total_used);
++ err = -EINVAL;
++ goto out;
++ }
++
++ if (lst->total_dead != c->lst.total_dead ||
++ lst->total_dark != c->lst.total_dark) {
++ ubifs_err("bad dead/dark space accounting");
++ ubifs_err("calculated: total_dead %lld, total_dark %lld",
++ lst->total_dead, lst->total_dark);
++ ubifs_err("read from lprops: total_dead %lld, total_dark %lld",
++ c->lst.total_dead, c->lst.total_dark);
++ err = -EINVAL;
++ goto out;
++ }
++
++ err = dbg_check_cats(c);
++out:
++ return err;
++}
++
++#endif /* CONFIG_UBIFS_FS_DEBUG */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/lpt.c avr32-2.6/fs/ubifs/lpt.c
+--- linux-2.6.25.6/fs/ubifs/lpt.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/lpt.c 2008-06-12 15:09:45.475816115 +0200
+@@ -0,0 +1,2241 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ */
++
++/*
++ * This file implements the LEB properties tree (LPT) area. The LPT area
++ * contains the LEB properties tree, a table of LPT area eraseblocks (ltab), and
++ * (for the "big" model) a table of saved LEB numbers (lsave). The LPT area sits
++ * between the log and the orphan area.
++ *
++ * The LPT area is like a miniature self-contained file system. It is required
++ * that it never runs out of space, is fast to access and update, and scales
++ * logarithmically. The LEB properties tree is implemented as a wandering tree
++ * much like the TNC, and the LPT area has its own garbage collection.
++ *
++ * The LPT has two slightly different forms called the "small model" and the
++ * "big model". The small model is used when the entire LEB properties table
++ * can be written into a single eraseblock. In that case, garbage collection
++ * consists of just writing the whole table, which therefore makes all other
++ * eraseblocks reusable. In the case of the big model, dirty eraseblocks are
++ * selected for garbage collection, which consists are marking the nodes in
++ * that LEB as dirty, and then only the dirty nodes are written out. Also, in
++ * the case of the big model, a table of LEB numbers is saved so that the entire
++ * LPT does not to be scanned looking for empty eraseblocks when UBIFS is first
++ * mounted.
++ */
++
++#include <linux/crc16.h>
++#include "ubifs.h"
++
++/**
++ * do_calc_lpt_geom - calculate sizes for the LPT area.
++ * @c: the UBIFS file-system description object
++ *
++ * Calculate the sizes of LPT bit fields, nodes, and tree, based on the
++ * properties of the flash and whether LPT is "big" (c->big_lpt).
++ */
++static void do_calc_lpt_geom(struct ubifs_info *c)
++{
++ int i, n, bits, per_leb_wastage, max_pnode_cnt;
++ long long sz, tot_wastage;
++
++ n = c->main_lebs + c->max_leb_cnt - c->leb_cnt;
++ max_pnode_cnt = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT);
++
++ c->lpt_hght = 1;
++ n = UBIFS_LPT_FANOUT;
++ while (n < max_pnode_cnt) {
++ c->lpt_hght += 1;
++ n <<= UBIFS_LPT_FANOUT_SHIFT;
++ }
++
++ c->pnode_cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
++
++ n = DIV_ROUND_UP(c->pnode_cnt, UBIFS_LPT_FANOUT);
++ c->nnode_cnt = n;
++ for (i = 1; i < c->lpt_hght; i++) {
++ n = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT);
++ c->nnode_cnt += n;
++ }
++
++ c->space_bits = fls(c->leb_size) - 3;
++ c->lpt_lnum_bits = fls(c->lpt_lebs);
++ c->lpt_offs_bits = fls(c->leb_size - 1);
++ c->lpt_spc_bits = fls(c->leb_size);
++
++ n = DIV_ROUND_UP(c->max_leb_cnt, UBIFS_LPT_FANOUT);
++ c->pcnt_bits = fls(n - 1);
++
++ c->lnum_bits = fls(c->max_leb_cnt - 1);
++
++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
++ (c->big_lpt ? c->pcnt_bits : 0) +
++ (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT;
++ c->pnode_sz = (bits + 7) / 8;
++
++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
++ (c->big_lpt ? c->pcnt_bits : 0) +
++ (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT;
++ c->nnode_sz = (bits + 7) / 8;
++
++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
++ c->lpt_lebs * c->lpt_spc_bits * 2;
++ c->ltab_sz = (bits + 7) / 8;
++
++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
++ c->lnum_bits * c->lsave_cnt;
++ c->lsave_sz = (bits + 7) / 8;
++
++ /* Calculate the minimum LPT size */
++ c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
++ c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
++ c->lpt_sz += c->ltab_sz;
++ c->lpt_sz += c->lsave_sz;
++
++ /* Add wastage */
++ sz = c->lpt_sz;
++ per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz);
++ sz += per_leb_wastage;
++ tot_wastage = per_leb_wastage;
++ while (sz > c->leb_size) {
++ sz += per_leb_wastage;
++ sz -= c->leb_size;
++ tot_wastage += per_leb_wastage;
++ }
++ tot_wastage += ALIGN(sz, c->min_io_size) - sz;
++ c->lpt_sz += tot_wastage;
++}
++
++/**
++ * ubifs_calc_lpt_geom - calculate and check sizes for the LPT area.
++ * @c: the UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_calc_lpt_geom(struct ubifs_info *c)
++{
++ int lebs_needed;
++ uint64_t sz;
++
++ do_calc_lpt_geom(c);
++
++ /* Verify that lpt_lebs is big enough */
++ sz = c->lpt_sz * 2; /* Must have at least 2 times the size */
++ sz += c->leb_size - 1;
++ do_div(sz, c->leb_size);
++ lebs_needed = sz;
++ if (lebs_needed > c->lpt_lebs) {
++ ubifs_err("too few LPT LEBs");
++ return -EINVAL;
++ }
++
++ /* Verify that ltab fits in a single LEB (since ltab is a single node */
++ if (c->ltab_sz > c->leb_size) {
++ ubifs_err("LPT ltab too big");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/**
++ * calc_dflt_lpt_geom - calculate default LPT geometry.
++ * @c: the UBIFS file-system description object
++ * @main_lebs: number of main area LEBs is passed and returned here
++ * @big_lpt: whether the LPT area is "big" is returned here
++ *
++ * The size of the LPT area depends on parameters that themselves are dependent
++ * on the size of the LPT area. This function, successively recalculates the LPT
++ * area geometry until the parameters and resultant geometry are consistent.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs,
++ int *big_lpt)
++{
++ int i, lebs_needed;
++ uint64_t sz;
++
++ /* Start by assuming the minimum number of LPT LEBs */
++ c->lpt_lebs = UBIFS_MIN_LPT_LEBS;
++ c->main_lebs = *main_lebs - c->lpt_lebs;
++ if (c->main_lebs <= 0)
++ return -EINVAL;
++
++ /* And assume we will use the small LPT model */
++ c->big_lpt = 0;
++
++ /*
++ * Calculate the geometry based on assumptions above and then see if it
++ * makes sense
++ */
++ do_calc_lpt_geom(c);
++
++ /* Small LPT model must have lpt_sz < leb_size */
++ if (c->lpt_sz > c->leb_size) {
++ /* Nope, so try again using big LPT model */
++ c->big_lpt = 1;
++ do_calc_lpt_geom(c);
++ }
++
++ /* Now check there are enough LPT LEBs */
++ for (i = 0; i < 64 ; i++) {
++ sz = c->lpt_sz * 4; /* Allow 4 times the size */
++ sz += c->leb_size - 1;
++ do_div(sz, c->leb_size);
++ lebs_needed = sz;
++ if (lebs_needed > c->lpt_lebs) {
++ /* Not enough LPT LEBs so try again with more */
++ c->lpt_lebs = lebs_needed;
++ c->main_lebs = *main_lebs - c->lpt_lebs;
++ if (c->main_lebs <= 0)
++ return -EINVAL;
++ do_calc_lpt_geom(c);
++ continue;
++ }
++ if (c->ltab_sz > c->leb_size) {
++ ubifs_err("LPT ltab too big");
++ return -EINVAL;
++ }
++ *main_lebs = c->main_lebs;
++ *big_lpt = c->big_lpt;
++ return 0;
++ }
++ return -EINVAL;
++}
++
++/**
++ * pack_bits - pack bit fields end-to-end.
++ * @addr: address at which to pack (passed and next address returned)
++ * @pos: bit position at which to pack (passed and next position returned)
++ * @val: value to pack
++ * @nrbits: number of bits of value to pack (1-32)
++ */
++static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits)
++{
++ uint8_t *p = *addr;
++ int b = *pos;
++
++ ubifs_assert(nrbits > 0);
++ ubifs_assert(nrbits <= 32);
++ ubifs_assert(*pos >= 0);
++ ubifs_assert(*pos < 8);
++ ubifs_assert((val >> nrbits) == 0 || nrbits == 32);
++ if (b) {
++ *p |= ((uint8_t)val) << b;
++ nrbits += b;
++ if (nrbits > 8) {
++ *++p = (uint8_t)(val >>= (8 - b));
++ if (nrbits > 16) {
++ *++p = (uint8_t)(val >>= 8);
++ if (nrbits > 24) {
++ *++p = (uint8_t)(val >>= 8);
++ if (nrbits > 32)
++ *++p = (uint8_t)(val >>= 8);
++ }
++ }
++ }
++ } else {
++ *p = (uint8_t)val;
++ if (nrbits > 8) {
++ *++p = (uint8_t)(val >>= 8);
++ if (nrbits > 16) {
++ *++p = (uint8_t)(val >>= 8);
++ if (nrbits > 24)
++ *++p = (uint8_t)(val >>= 8);
++ }
++ }
++ }
++ b = nrbits & 7;
++ if (b == 0)
++ p++;
++ *addr = p;
++ *pos = b;
++}
++
++/**
++ * ubifs_unpack_bits - unpack bit fields.
++ * @addr: address at which to unpack (passed and next address returned)
++ * @pos: bit position at which to unpack (passed and next position returned)
++ * @nrbits: number of bits of value to unpack (1-32)
++ *
++ * This functions returns the value unpacked.
++ */
++uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits)
++{
++ const int k = 32 - nrbits;
++ uint8_t *p = *addr;
++ int b = *pos;
++ uint32_t val;
++
++ ubifs_assert(nrbits > 0);
++ ubifs_assert(nrbits <= 32);
++ ubifs_assert(*pos >= 0);
++ ubifs_assert(*pos < 8);
++ if (b) {
++ val = p[1] | ((uint32_t)p[2] << 8) | ((uint32_t)p[3] << 16) |
++ ((uint32_t)p[4] << 24);
++ val <<= (8 - b);
++ val |= *p >> b;
++ nrbits += b;
++ } else
++ val = p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) |
++ ((uint32_t)p[3] << 24);
++ val <<= k;
++ val >>= k;
++ b = nrbits & 7;
++ p += nrbits / 8;
++ *addr = p;
++ *pos = b;
++ ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32);
++ return val;
++}
++
++/**
++ * ubifs_pack_pnode - pack all the bit fields of a pnode.
++ * @c: UBIFS file-system description object
++ * @buf: buffer into which to pack
++ * @pnode: pnode to pack
++ */
++void ubifs_pack_pnode(struct ubifs_info *c, void *buf,
++ struct ubifs_pnode *pnode)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0;
++ uint16_t crc;
++
++ pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
++ if (c->big_lpt)
++ pack_bits(&addr, &pos, pnode->num, c->pcnt_bits);
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ pack_bits(&addr, &pos, pnode->lprops[i].free >> 3,
++ c->space_bits);
++ pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3,
++ c->space_bits);
++ if (pnode->lprops[i].flags & LPROPS_INDEX)
++ pack_bits(&addr, &pos, 1, 1);
++ else
++ pack_bits(&addr, &pos, 0, 1);
++ }
++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
++ c->pnode_sz - UBIFS_LPT_CRC_BYTES);
++ addr = buf;
++ pos = 0;
++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
++}
++
++/**
++ * ubifs_pack_nnode - pack all the bit fields of a nnode.
++ * @c: UBIFS file-system description object
++ * @buf: buffer into which to pack
++ * @nnode: nnode to pack
++ */
++void ubifs_pack_nnode(struct ubifs_info *c, void *buf,
++ struct ubifs_nnode *nnode)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0;
++ uint16_t crc;
++
++ pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
++ if (c->big_lpt)
++ pack_bits(&addr, &pos, nnode->num, c->pcnt_bits);
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ int lnum = nnode->nbranch[i].lnum;
++
++ if (lnum == 0)
++ lnum = c->lpt_last + 1;
++ pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
++ pack_bits(&addr, &pos, nnode->nbranch[i].offs,
++ c->lpt_offs_bits);
++ }
++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
++ c->nnode_sz - UBIFS_LPT_CRC_BYTES);
++ addr = buf;
++ pos = 0;
++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
++}
++
++/**
++ * ubifs_pack_ltab - pack the LPT's own lprops table.
++ * @c: UBIFS file-system description object
++ * @buf: buffer into which to pack
++ * @ltab: LPT's own lprops table to pack
++ */
++void ubifs_pack_ltab(struct ubifs_info *c, void *buf,
++ struct ubifs_lpt_lprops *ltab)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0;
++ uint16_t crc;
++
++ pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
++ for (i = 0; i < c->lpt_lebs; i++) {
++ pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits);
++ pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
++ }
++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
++ c->ltab_sz - UBIFS_LPT_CRC_BYTES);
++ addr = buf;
++ pos = 0;
++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
++}
++
++/**
++ * ubifs_pack_lsave - pack the LPT's save table.
++ * @c: UBIFS file-system description object
++ * @buf: buffer into which to pack
++ * @lsave: LPT's save table to pack
++ */
++void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0;
++ uint16_t crc;
++
++ pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
++ for (i = 0; i < c->lsave_cnt; i++)
++ pack_bits(&addr, &pos, lsave[i], c->lnum_bits);
++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
++ c->lsave_sz - UBIFS_LPT_CRC_BYTES);
++ addr = buf;
++ pos = 0;
++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
++}
++
++/**
++ * ubifs_add_lpt_dirt - add dirty space to LPT LEB properties.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number to which to add dirty space
++ * @dirty: amount of dirty space to add
++ */
++void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty)
++{
++ if (!dirty || !lnum)
++ return;
++ dbg_lp("LEB %d add %d to %d",
++ lnum, dirty, c->ltab[lnum - c->lpt_first].dirty);
++ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
++ c->ltab[lnum - c->lpt_first].dirty += dirty;
++}
++
++/**
++ * set_ltab - set LPT LEB properties.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number
++ * @free: amount of free space
++ * @dirty: amount of dirty space
++ */
++static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
++{
++ dbg_lp("LEB %d free %d dirty %d to %d %d",
++ lnum, c->ltab[lnum - c->lpt_first].free,
++ c->ltab[lnum - c->lpt_first].dirty, free, dirty);
++ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
++ c->ltab[lnum - c->lpt_first].free = free;
++ c->ltab[lnum - c->lpt_first].dirty = dirty;
++}
++
++/**
++ * ubifs_add_nnode_dirt - add dirty space to LPT LEB properties.
++ * @c: UBIFS file-system description object
++ * @nnode: nnode for which to add dirt
++ */
++void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode)
++{
++ struct ubifs_nnode *np = nnode->parent;
++
++ if (np)
++ ubifs_add_lpt_dirt(c, np->nbranch[nnode->iip].lnum,
++ c->nnode_sz);
++ else {
++ ubifs_add_lpt_dirt(c, c->lpt_lnum, c->nnode_sz);
++ if (!(c->lpt_drty_flgs & LTAB_DIRTY)) {
++ c->lpt_drty_flgs |= LTAB_DIRTY;
++ ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz);
++ }
++ }
++}
++
++/**
++ * add_pnode_dirt - add dirty space to LPT LEB properties.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode for which to add dirt
++ */
++static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
++{
++ ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum,
++ c->pnode_sz);
++}
++
++/**
++ * calc_nnode_num - calculate nnode number.
++ * @row: the row in the tree (root is zero)
++ * @col: the column in the row (leftmost is zero)
++ *
++ * The nnode number is a number that uniquely identifies a nnode and can be used
++ * easily to traverse the tree from the root to that nnode.
++ *
++ * This function calculates and returns the nnode number for the nnode at @row
++ * and @col.
++ */
++static int calc_nnode_num(int row, int col)
++{
++ int num, bits;
++
++ num = 1;
++ while (row--) {
++ bits = (col & (UBIFS_LPT_FANOUT - 1));
++ col >>= UBIFS_LPT_FANOUT_SHIFT;
++ num <<= UBIFS_LPT_FANOUT_SHIFT;
++ num |= bits;
++ }
++ return num;
++}
++
++/**
++ * calc_nnode_num_from_parent - calculate nnode number.
++ * @c: UBIFS file-system description object
++ * @parent: parent nnode
++ * @iip: index in parent
++ *
++ * The nnode number is a number that uniquely identifies a nnode and can be used
++ * easily to traverse the tree from the root to that nnode.
++ *
++ * This function calculates and returns the nnode number based on the parent's
++ * nnode number and the index in parent.
++ */
++static int calc_nnode_num_from_parent(struct ubifs_info *c,
++ struct ubifs_nnode *parent, int iip)
++{
++ int num, shft;
++
++ if (!parent)
++ return 1;
++ shft = (c->lpt_hght - parent->level) * UBIFS_LPT_FANOUT_SHIFT;
++ num = parent->num ^ (1 << shft);
++ num |= (UBIFS_LPT_FANOUT + iip) << shft;
++ return num;
++}
++
++/**
++ * calc_pnode_num_from_parent - calculate pnode number.
++ * @c: UBIFS file-system description object
++ * @parent: parent nnode
++ * @iip: index in parent
++ *
++ * The pnode number is a number that uniquely identifies a pnode and can be used
++ * easily to traverse the tree from the root to that pnode.
++ *
++ * This function calculates and returns the pnode number based on the parent's
++ * nnode number and the index in parent.
++ */
++static int calc_pnode_num_from_parent(struct ubifs_info *c,
++ struct ubifs_nnode *parent, int iip)
++{
++ int i, n = c->lpt_hght - 1, pnum = parent->num, num = 0;
++
++ for (i = 0; i < n; i++) {
++ num <<= UBIFS_LPT_FANOUT_SHIFT;
++ num |= pnum & (UBIFS_LPT_FANOUT - 1);
++ pnum >>= UBIFS_LPT_FANOUT_SHIFT;
++ }
++ num <<= UBIFS_LPT_FANOUT_SHIFT;
++ num |= iip;
++ return num;
++}
++
++/**
++ * ubifs_create_dflt_lpt - create default LPT.
++ * @c: UBIFS file-system description object
++ * @main_lebs: number of main area LEBs is passed and returned here
++ * @lpt_first: LEB number of first LPT LEB
++ * @lpt_lebs: number of LEBs for LPT is passed and returned here
++ * @big_lpt: use big LPT model is passed and returned here
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
++ int *lpt_lebs, int *big_lpt)
++{
++ int lnum, err = 0, node_sz, iopos, i, j, cnt, len, alen, row;
++ int blnum, boffs, bsz, bcnt;
++ struct ubifs_pnode *pnode = NULL;
++ struct ubifs_nnode *nnode = NULL;
++ void *buf = NULL, *p;
++ struct ubifs_lpt_lprops *ltab = NULL;
++ int *lsave = NULL;
++
++ err = calc_dflt_lpt_geom(c, main_lebs, big_lpt);
++ if (err)
++ return err;
++ *lpt_lebs = c->lpt_lebs;
++
++ /* Needed by 'ubifs_pack_nnode()' and 'set_ltab()' */
++ c->lpt_first = lpt_first;
++ /* Needed by 'set_ltab()' */
++ c->lpt_last = lpt_first + c->lpt_lebs - 1;
++ /* Needed by 'ubifs_pack_lsave()' */
++ c->main_first = c->leb_cnt - *main_lebs;
++
++ lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_KERNEL);
++ pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL);
++ nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL);
++ buf = vmalloc(c->leb_size);
++ ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
++ if (!pnode || !nnode || !buf || !ltab || !lsave) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ ubifs_assert(!c->ltab);
++ c->ltab = ltab; /* Needed by set_ltab */
++
++ /* Initialize LPT's own lprops */
++ for (i = 0; i < c->lpt_lebs; i++) {
++ ltab[i].free = c->leb_size;
++ ltab[i].dirty = 0;
++ ltab[i].tgc = 0;
++ ltab[i].cmt = 0;
++ }
++
++ lnum = lpt_first;
++ p = buf;
++ /* Number of leaf nodes (pnodes) */
++ cnt = c->pnode_cnt;
++
++ /*
++ * The first pnode contains the LEB properties for the LEBs that contain
++ * the root inode node and the root index node of the index tree.
++ */
++ node_sz = ALIGN(ubifs_idx_node_sz(c, 1), 8);
++ iopos = ALIGN(node_sz, c->min_io_size);
++ pnode->lprops[0].free = c->leb_size - iopos;
++ pnode->lprops[0].dirty = iopos - node_sz;
++ pnode->lprops[0].flags = LPROPS_INDEX;
++
++ node_sz = UBIFS_INO_NODE_SZ;
++ iopos = ALIGN(node_sz, c->min_io_size);
++ pnode->lprops[1].free = c->leb_size - iopos;
++ pnode->lprops[1].dirty = iopos - node_sz;
++
++ for (i = 2; i < UBIFS_LPT_FANOUT; i++)
++ pnode->lprops[i].free = c->leb_size;
++
++ /* Add first pnode */
++ ubifs_pack_pnode(c, p, pnode);
++ p += c->pnode_sz;
++ len = c->pnode_sz;
++ pnode->num += 1;
++
++ /* Reset pnode values for remaining pnodes */
++ pnode->lprops[0].free = c->leb_size;
++ pnode->lprops[0].dirty = 0;
++ pnode->lprops[0].flags = 0;
++
++ pnode->lprops[1].free = c->leb_size;
++ pnode->lprops[1].dirty = 0;
++
++ /*
++ * To calculate the internal node branches, we keep information about
++ * the level below.
++ */
++ blnum = lnum; /* LEB number of level below */
++ boffs = 0; /* Offset of level below */
++ bcnt = cnt; /* Number of nodes in level below */
++ bsz = c->pnode_sz; /* Size of nodes in level below */
++
++ /* Add all remaining pnodes */
++ for (i = 1; i < cnt; i++) {
++ if (len + c->pnode_sz > c->leb_size) {
++ alen = ALIGN(len, c->min_io_size);
++ set_ltab(c, lnum, c->leb_size - alen, alen - len);
++ memset(p, 0xff, alen - len);
++ err = ubi_leb_change(c->ubi, lnum++, buf, alen,
++ UBI_SHORTTERM);
++ if (err)
++ goto out;
++ p = buf;
++ len = 0;
++ }
++ ubifs_pack_pnode(c, p, pnode);
++ p += c->pnode_sz;
++ len += c->pnode_sz;
++ /*
++ * pnodes are simply numbered left to right starting at zero,
++ * which means the pnode number can be used easily to traverse
++ * down the tree to the corresponding pnode.
++ */
++ pnode->num += 1;
++ }
++
++ row = 0;
++ for (i = UBIFS_LPT_FANOUT; cnt > i; i <<= UBIFS_LPT_FANOUT_SHIFT)
++ row += 1;
++ /* Add all nnodes, one level at a time */
++ while (1) {
++ /* Number of internal nodes (nnodes) at next level */
++ cnt = DIV_ROUND_UP(cnt, UBIFS_LPT_FANOUT);
++ for (i = 0; i < cnt; i++) {
++ if (len + c->nnode_sz > c->leb_size) {
++ alen = ALIGN(len, c->min_io_size);
++ set_ltab(c, lnum, c->leb_size - alen,
++ alen - len);
++ memset(p, 0xff, alen - len);
++ err = ubi_leb_change(c->ubi, lnum++, buf, alen,
++ UBI_SHORTTERM);
++ if (err)
++ goto out;
++ p = buf;
++ len = 0;
++ }
++ /* Only 1 nnode at this level, so it is the root */
++ if (cnt == 1) {
++ c->lpt_lnum = lnum;
++ c->lpt_offs = len;
++ }
++ /* Set branches to the level below */
++ for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
++ if (bcnt) {
++ if (boffs + bsz > c->leb_size) {
++ blnum += 1;
++ boffs = 0;
++ }
++ nnode->nbranch[j].lnum = blnum;
++ nnode->nbranch[j].offs = boffs;
++ boffs += bsz;
++ bcnt--;
++ } else {
++ nnode->nbranch[j].lnum = 0;
++ nnode->nbranch[j].offs = 0;
++ }
++ }
++ nnode->num = calc_nnode_num(row, i);
++ ubifs_pack_nnode(c, p, nnode);
++ p += c->nnode_sz;
++ len += c->nnode_sz;
++ }
++ /* Only 1 nnode at this level, so it is the root */
++ if (cnt == 1)
++ break;
++ /* Update the information about the level below */
++ bcnt = cnt;
++ bsz = c->nnode_sz;
++ row -= 1;
++ }
++
++ if (*big_lpt) {
++ /* Need to add LPT's save table */
++ if (len + c->lsave_sz > c->leb_size) {
++ alen = ALIGN(len, c->min_io_size);
++ set_ltab(c, lnum, c->leb_size - alen, alen - len);
++ memset(p, 0xff, alen - len);
++ err = ubi_leb_change(c->ubi, lnum++, buf, alen,
++ UBI_SHORTTERM);
++ if (err)
++ goto out;
++ p = buf;
++ len = 0;
++ }
++
++ c->lsave_lnum = lnum;
++ c->lsave_offs = len;
++
++ for (i = 0; i < c->lsave_cnt && i < *main_lebs; i++)
++ lsave[i] = c->main_first + i;
++ for (; i < c->lsave_cnt; i++)
++ lsave[i] = c->main_first;
++
++ ubifs_pack_lsave(c, p, lsave);
++ p += c->lsave_sz;
++ len += c->lsave_sz;
++ }
++
++ /* Need to add LPT's own LEB properties table */
++ if (len + c->ltab_sz > c->leb_size) {
++ alen = ALIGN(len, c->min_io_size);
++ set_ltab(c, lnum, c->leb_size - alen, alen - len);
++ memset(p, 0xff, alen - len);
++ err = ubi_leb_change(c->ubi, lnum++, buf, alen, UBI_SHORTTERM);
++ if (err)
++ goto out;
++ p = buf;
++ len = 0;
++ }
++
++ c->ltab_lnum = lnum;
++ c->ltab_offs = len;
++
++ /* Update ltab before packing it */
++ len += c->ltab_sz;
++ alen = ALIGN(len, c->min_io_size);
++ set_ltab(c, lnum, c->leb_size - alen, alen - len);
++
++ ubifs_pack_ltab(c, p, ltab);
++ p += c->ltab_sz;
++
++ /* Write remaining buffer */
++ memset(p, 0xff, alen - len);
++ err = ubi_leb_change(c->ubi, lnum, buf, alen, UBI_SHORTTERM);
++ if (err)
++ goto out;
++
++ c->nhead_lnum = lnum;
++ c->nhead_offs = ALIGN(len, c->min_io_size);
++
++ dbg_lp("space_bits %d", c->space_bits);
++ dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits);
++ dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits);
++ dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits);
++ dbg_lp("pcnt_bits %d", c->pcnt_bits);
++ dbg_lp("lnum_bits %d", c->lnum_bits);
++ dbg_lp("pnode_sz %d", c->pnode_sz);
++ dbg_lp("nnode_sz %d", c->nnode_sz);
++ dbg_lp("ltab_sz %d", c->ltab_sz);
++ dbg_lp("lsave_sz %d", c->lsave_sz);
++ dbg_lp("lsave_cnt %d", c->lsave_cnt);
++ dbg_lp("lpt_hght %d", c->lpt_hght);
++ dbg_lp("big_lpt %d", c->big_lpt);
++ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
++ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
++ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
++ if (c->big_lpt)
++ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
++out:
++ c->ltab = NULL;
++ kfree(lsave);
++ vfree(ltab);
++ vfree(buf);
++ kfree(nnode);
++ kfree(pnode);
++ return err;
++}
++
++/**
++ * update_cats - add LEB properties of a pnode to LEB category lists and heaps.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode
++ *
++ * When a pnode is loaded into memory, the LEB properties it contains are added,
++ * by this function, to the LEB category lists and heaps.
++ */
++static void update_cats(struct ubifs_info *c, struct ubifs_pnode *pnode)
++{
++ int i;
++
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ int cat = pnode->lprops[i].flags & LPROPS_CAT_MASK;
++ int lnum = pnode->lprops[i].lnum;
++
++ if (!lnum)
++ return;
++ ubifs_add_to_cat(c, &pnode->lprops[i], cat);
++ }
++}
++
++/**
++ * replace_cats - add LEB properties of a pnode to LEB category lists and heaps.
++ * @c: UBIFS file-system description object
++ * @old_pnode: pnode copied
++ * @new_pnode: pnode copy
++ *
++ * During commit it is sometimes necessary to copy a pnode
++ * (see dirty_cow_pnode). When that happens, references in
++ * category lists and heaps must be replaced. This function does that.
++ */
++static void replace_cats(struct ubifs_info *c, struct ubifs_pnode *old_pnode,
++ struct ubifs_pnode *new_pnode)
++{
++ int i;
++
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ if (!new_pnode->lprops[i].lnum)
++ return;
++ ubifs_replace_cat(c, &old_pnode->lprops[i],
++ &new_pnode->lprops[i]);
++ }
++}
++
++/**
++ * check_lpt_crc - check LPT node crc is correct.
++ * @c: UBIFS file-system description object
++ * @buf: buffer containing node
++ * @len: length of node
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int check_lpt_crc(void *buf, int len)
++{
++ int pos = 0;
++ uint8_t *addr = buf;
++ uint16_t crc, calc_crc;
++
++ crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
++ calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
++ len - UBIFS_LPT_CRC_BYTES);
++ if (crc != calc_crc) {
++ ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc,
++ calc_crc);
++ dbg_dump_stack();
++ return -EINVAL;
++ }
++ return 0;
++}
++
++/**
++ * check_lpt_type - check LPT node type is correct.
++ * @c: UBIFS file-system description object
++ * @addr: address of type bit field is passed and returned updated here
++ * @pos: position of type bit field is passed and returned updated here
++ * @type: expected type
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int check_lpt_type(uint8_t **addr, int *pos, int type)
++{
++ int node_type;
++
++ node_type = ubifs_unpack_bits(addr, pos, UBIFS_LPT_TYPE_BITS);
++ if (node_type != type) {
++ ubifs_err("invalid type (%d) in LPT node type %d", node_type,
++ type);
++ dbg_dump_stack();
++ return -EINVAL;
++ }
++ return 0;
++}
++
++/**
++ * unpack_pnode - unpack a pnode.
++ * @c: UBIFS file-system description object
++ * @buf: buffer containing packed pnode to unpack
++ * @pnode: pnode structure to fill
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int unpack_pnode(struct ubifs_info *c, void *buf,
++ struct ubifs_pnode *pnode)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0, err;
++
++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_PNODE);
++ if (err)
++ return err;
++ if (c->big_lpt)
++ pnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ struct ubifs_lprops * const lprops = &pnode->lprops[i];
++
++ lprops->free = ubifs_unpack_bits(&addr, &pos, c->space_bits);
++ lprops->free <<= 3;
++ lprops->dirty = ubifs_unpack_bits(&addr, &pos, c->space_bits);
++ lprops->dirty <<= 3;
++
++ if (ubifs_unpack_bits(&addr, &pos, 1))
++ lprops->flags = LPROPS_INDEX;
++ else
++ lprops->flags = 0;
++ lprops->flags |= ubifs_categorize_lprops(c, lprops);
++ }
++ err = check_lpt_crc(buf, c->pnode_sz);
++ return err;
++}
++
++/**
++ * unpack_nnode - unpack a nnode.
++ * @c: UBIFS file-system description object
++ * @buf: buffer containing packed nnode to unpack
++ * @nnode: nnode structure to fill
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int unpack_nnode(struct ubifs_info *c, void *buf,
++ struct ubifs_nnode *nnode)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0, err;
++
++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_NNODE);
++ if (err)
++ return err;
++ if (c->big_lpt)
++ nnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ int lnum;
++
++ lnum = ubifs_unpack_bits(&addr, &pos, c->lpt_lnum_bits) +
++ c->lpt_first;
++ if (lnum == c->lpt_last + 1)
++ lnum = 0;
++ nnode->nbranch[i].lnum = lnum;
++ nnode->nbranch[i].offs = ubifs_unpack_bits(&addr, &pos,
++ c->lpt_offs_bits);
++ }
++ err = check_lpt_crc(buf, c->nnode_sz);
++ return err;
++}
++
++/**
++ * unpack_ltab - unpack the LPT's own lprops table.
++ * @c: UBIFS file-system description object
++ * @buf: buffer from which to unpack
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int unpack_ltab(struct ubifs_info *c, void *buf)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0, err;
++
++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_LTAB);
++ if (err)
++ return err;
++ for (i = 0; i < c->lpt_lebs; i++) {
++ int free = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
++ int dirty = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
++
++ if (free < 0 || free > c->leb_size || dirty < 0 ||
++ dirty > c->leb_size || free + dirty > c->leb_size)
++ return -EINVAL;
++
++ c->ltab[i].free = free;
++ c->ltab[i].dirty = dirty;
++ c->ltab[i].tgc = 0;
++ c->ltab[i].cmt = 0;
++ }
++ err = check_lpt_crc(buf, c->ltab_sz);
++ return err;
++}
++
++/**
++ * unpack_lsave - unpack the LPT's save table.
++ * @c: UBIFS file-system description object
++ * @buf: buffer from which to unpack
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int unpack_lsave(struct ubifs_info *c, void *buf)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int i, pos = 0, err;
++
++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_LSAVE);
++ if (err)
++ return err;
++ for (i = 0; i < c->lsave_cnt; i++) {
++ int lnum = ubifs_unpack_bits(&addr, &pos, c->lnum_bits);
++
++ if (lnum < c->main_first || lnum >= c->leb_cnt)
++ return -EINVAL;
++ c->lsave[i] = lnum;
++ }
++ err = check_lpt_crc(buf, c->lsave_sz);
++ return err;
++}
++
++/**
++ * validate_nnode - validate a nnode.
++ * @c: UBIFS file-system description object
++ * @nnode: nnode to validate
++ * @parent: parent nnode (or NULL for the root nnode)
++ * @iip: index in parent
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int validate_nnode(struct ubifs_info *c, struct ubifs_nnode *nnode,
++ struct ubifs_nnode *parent, int iip)
++{
++ int i, lvl, max_offs;
++
++ if (c->big_lpt) {
++ int num = calc_nnode_num_from_parent(c, parent, iip);
++
++ if (nnode->num != num)
++ return -EINVAL;
++ }
++ lvl = parent ? parent->level - 1 : c->lpt_hght;
++ if (lvl < 1)
++ return -EINVAL;
++ if (lvl == 1)
++ max_offs = c->leb_size - c->pnode_sz;
++ else
++ max_offs = c->leb_size - c->nnode_sz;
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ int lnum = nnode->nbranch[i].lnum;
++ int offs = nnode->nbranch[i].offs;
++
++ if (lnum == 0) {
++ if (offs != 0)
++ return -EINVAL;
++ continue;
++ }
++ if (lnum < c->lpt_first || lnum > c->lpt_last)
++ return -EINVAL;
++ if (offs < 0 || offs > max_offs)
++ return -EINVAL;
++ }
++ return 0;
++}
++
++/**
++ * validate_pnode - validate a pnode.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode to validate
++ * @parent: parent nnode
++ * @iip: index in parent
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int validate_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
++ struct ubifs_nnode *parent, int iip)
++{
++ int i;
++
++ if (c->big_lpt) {
++ int num = calc_pnode_num_from_parent(c, parent, iip);
++
++ if (pnode->num != num)
++ return -EINVAL;
++ }
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ int free = pnode->lprops[i].free;
++ int dirty = pnode->lprops[i].dirty;
++
++ if (free < 0 || free > c->leb_size || free % c->min_io_size ||
++ (free & 7))
++ return -EINVAL;
++ if (dirty < 0 || dirty > c->leb_size || (dirty & 7))
++ return -EINVAL;
++ if (dirty + free > c->leb_size)
++ return -EINVAL;
++ }
++ return 0;
++}
++
++/**
++ * set_pnode_lnum - set LEB numbers on a pnode.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode to update
++ *
++ * This function calculates the LEB numbers for the LEB properties it contains
++ * based on the pnode number.
++ */
++static void set_pnode_lnum(struct ubifs_info *c, struct ubifs_pnode *pnode)
++{
++ int i, lnum;
++
++ lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + c->main_first;
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ if (lnum >= c->leb_cnt)
++ return;
++ pnode->lprops[i].lnum = lnum++;
++ }
++}
++
++/**
++ * ubifs_read_nnode - read a nnode from flash and link it to the tree in memory.
++ * @c: UBIFS file-system description object
++ * @parent: parent nnode (or NULL for the root)
++ * @iip: index in parent
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
++{
++ struct ubifs_nbranch *branch = NULL;
++ struct ubifs_nnode *nnode = NULL;
++ void *buf = c->lpt_nod_buf;
++ int err, lnum, offs;
++
++ if (parent) {
++ branch = &parent->nbranch[iip];
++ lnum = branch->lnum;
++ offs = branch->offs;
++ } else {
++ lnum = c->lpt_lnum;
++ offs = c->lpt_offs;
++ }
++ nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_NOFS);
++ if (!nnode) {
++ err = -ENOMEM;
++ goto out;
++ }
++ if (lnum == 0) {
++ /*
++ * This nnode was not written which just means that the LEB
++ * properties in the subtree below it describe empty LEBs. We
++ * make the nnode as though we had read it, which in fact means
++ * doing almost nothing.
++ */
++ if (c->big_lpt)
++ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
++ } else {
++ err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz);
++ if (err)
++ goto out;
++ err = unpack_nnode(c, buf, nnode);
++ if (err)
++ goto out;
++ }
++ err = validate_nnode(c, nnode, parent, iip);
++ if (err)
++ goto out;
++ if (!c->big_lpt)
++ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
++ if (parent) {
++ branch->nnode = nnode;
++ nnode->level = parent->level - 1;
++ } else {
++ c->nroot = nnode;
++ nnode->level = c->lpt_hght;
++ }
++ nnode->parent = parent;
++ nnode->iip = iip;
++ return 0;
++
++out:
++ ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
++ kfree(nnode);
++ return err;
++}
++
++/**
++ * read_pnode - read a pnode from flash and link it to the tree in memory.
++ * @c: UBIFS file-system description object
++ * @parent: parent nnode
++ * @iip: index in parent
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
++{
++ struct ubifs_nbranch *branch;
++ struct ubifs_pnode *pnode = NULL;
++ void *buf = c->lpt_nod_buf;
++ int err, lnum, offs;
++
++ branch = &parent->nbranch[iip];
++ lnum = branch->lnum;
++ offs = branch->offs;
++ pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
++ if (!pnode) {
++ err = -ENOMEM;
++ goto out;
++ }
++ if (lnum == 0) {
++ /*
++ * This pnode was not written which just means that the LEB
++ * properties in it describe empty LEBs. We make the pnode as
++ * though we had read it.
++ */
++ int i;
++
++ if (c->big_lpt)
++ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ struct ubifs_lprops * const lprops = &pnode->lprops[i];
++
++ lprops->free = c->leb_size;
++ lprops->flags = ubifs_categorize_lprops(c, lprops);
++ }
++ } else {
++ err = ubi_read(c->ubi, lnum, buf, offs, c->pnode_sz);
++ if (err)
++ goto out;
++ err = unpack_pnode(c, buf, pnode);
++ if (err)
++ goto out;
++ }
++ err = validate_pnode(c, pnode, parent, iip);
++ if (err)
++ goto out;
++ if (!c->big_lpt)
++ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
++ branch->pnode = pnode;
++ pnode->parent = parent;
++ pnode->iip = iip;
++ set_pnode_lnum(c, pnode);
++ c->pnodes_have += 1;
++ return 0;
++
++out:
++ ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
++ dbg_dump_pnode(c, pnode, parent, iip);
++ dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
++ kfree(pnode);
++ return err;
++}
++
++/**
++ * read_ltab - read LPT's own lprops table.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int read_ltab(struct ubifs_info *c)
++{
++ int err;
++ void *buf;
++
++ buf = vmalloc(c->ltab_sz);
++ if (!buf)
++ return -ENOMEM;
++ err = ubi_read(c->ubi, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz);
++ if (err)
++ goto out;
++ err = unpack_ltab(c, buf);
++out:
++ vfree(buf);
++ return err;
++}
++
++/**
++ * read_lsave - read LPT's save table.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int read_lsave(struct ubifs_info *c)
++{
++ int err, i;
++ void *buf;
++
++ buf = vmalloc(c->lsave_sz);
++ if (!buf)
++ return -ENOMEM;
++ err = ubi_read(c->ubi, c->lsave_lnum, buf, c->lsave_offs, c->lsave_sz);
++ if (err)
++ goto out;
++ err = unpack_lsave(c, buf);
++ if (err)
++ goto out;
++ for (i = 0; i < c->lsave_cnt; i++) {
++ int lnum = c->lsave[i];
++
++ /*
++ * Due to automatic resizing, the values in the lsave table
++ * could be beyond the volume size - just ignore them.
++ */
++ if (lnum >= c->leb_cnt)
++ continue;
++ ubifs_lpt_lookup(c, lnum);
++ }
++out:
++ vfree(buf);
++ return err;
++}
++
++/**
++ * ubifs_get_nnode - get a nnode.
++ * @c: UBIFS file-system description object
++ * @parent: parent nnode (or NULL for the root)
++ * @iip: index in parent
++ *
++ * This function returns a pointer to the nnode on success or a negative error
++ * code on failure.
++ */
++struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c,
++ struct ubifs_nnode *parent, int iip)
++{
++ struct ubifs_nbranch *branch;
++ struct ubifs_nnode *nnode;
++ int err;
++
++ branch = &parent->nbranch[iip];
++ nnode = branch->nnode;
++ if (nnode)
++ return nnode;
++ err = ubifs_read_nnode(c, parent, iip);
++ if (err)
++ return ERR_PTR(err);
++ return branch->nnode;
++}
++
++/**
++ * ubifs_get_pnode - get a pnode.
++ * @c: UBIFS file-system description object
++ * @parent: parent nnode
++ * @iip: index in parent
++ *
++ * This function returns a pointer to the pnode on success or a negative error
++ * code on failure.
++ */
++struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c,
++ struct ubifs_nnode *parent, int iip)
++{
++ struct ubifs_nbranch *branch;
++ struct ubifs_pnode *pnode;
++ int err;
++
++ branch = &parent->nbranch[iip];
++ pnode = branch->pnode;
++ if (pnode)
++ return pnode;
++ err = read_pnode(c, parent, iip);
++ if (err)
++ return ERR_PTR(err);
++ update_cats(c, branch->pnode);
++ return branch->pnode;
++}
++
++/**
++ * ubifs_lpt_lookup - lookup LEB properties in the LPT.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number to lookup
++ *
++ * This function returns a pointer to the LEB properties on success or a
++ * negative error code on failure.
++ */
++struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum)
++{
++ int err, i, h, iip, shft;
++ struct ubifs_nnode *nnode;
++ struct ubifs_pnode *pnode;
++
++ if (!c->nroot) {
++ err = ubifs_read_nnode(c, NULL, 0);
++ if (err)
++ return ERR_PTR(err);
++ }
++ nnode = c->nroot;
++ i = lnum - c->main_first;
++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
++ for (h = 1; h < c->lpt_hght; h++) {
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ shft -= UBIFS_LPT_FANOUT_SHIFT;
++ nnode = ubifs_get_nnode(c, nnode, iip);
++ if (IS_ERR(nnode))
++ return ERR_PTR(PTR_ERR(nnode));
++ }
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ shft -= UBIFS_LPT_FANOUT_SHIFT;
++ pnode = ubifs_get_pnode(c, nnode, iip);
++ if (IS_ERR(pnode))
++ return ERR_PTR(PTR_ERR(pnode));
++ iip = (i & (UBIFS_LPT_FANOUT - 1));
++ dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum,
++ pnode->lprops[iip].free, pnode->lprops[iip].dirty,
++ pnode->lprops[iip].flags);
++ return &pnode->lprops[iip];
++}
++
++/**
++ * dirty_cow_nnode - ensure a nnode is not being committed.
++ * @c: UBIFS file-system description object
++ * @nnode: nnode to check
++ *
++ * Returns dirtied nnode on success or negative error code on failure.
++ */
++static struct ubifs_nnode *dirty_cow_nnode(struct ubifs_info *c,
++ struct ubifs_nnode *nnode)
++{
++ struct ubifs_nnode *n;
++ int i;
++
++ if (!test_bit(COW_CNODE, &nnode->flags)) {
++ /* nnode is not being committed */
++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
++ c->dirty_nn_cnt += 1;
++ ubifs_add_nnode_dirt(c, nnode);
++ }
++ return nnode;
++ }
++
++ /* nnode is being committed, so copy it */
++ n = kmalloc(sizeof(struct ubifs_nnode), GFP_NOFS);
++ if (unlikely(!n))
++ return ERR_PTR(-ENOMEM);
++
++ memcpy(n, nnode, sizeof(struct ubifs_nnode));
++ n->cnext = NULL;
++ __set_bit(DIRTY_CNODE, &n->flags);
++ __clear_bit(COW_CNODE, &n->flags);
++
++ /* The children now have new parent */
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ struct ubifs_nbranch *branch = &n->nbranch[i];
++
++ if (branch->cnode)
++ branch->cnode->parent = n;
++ }
++
++ ubifs_assert(!test_bit(OBSOLETE_CNODE, &nnode->flags));
++ __set_bit(OBSOLETE_CNODE, &nnode->flags);
++
++ c->dirty_nn_cnt += 1;
++ ubifs_add_nnode_dirt(c, nnode);
++ if (nnode->parent)
++ nnode->parent->nbranch[n->iip].nnode = n;
++ else
++ c->nroot = n;
++ return n;
++}
++
++/**
++ * dirty_cow_pnode - ensure a pnode is not being committed.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode to check
++ *
++ * Returns dirtied pnode on success or negative error code on failure.
++ */
++static struct ubifs_pnode *dirty_cow_pnode(struct ubifs_info *c,
++ struct ubifs_pnode *pnode)
++{
++ struct ubifs_pnode *p;
++
++ if (!test_bit(COW_CNODE, &pnode->flags)) {
++ /* pnode is not being committed */
++ if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) {
++ c->dirty_pn_cnt += 1;
++ add_pnode_dirt(c, pnode);
++ }
++ return pnode;
++ }
++
++ /* pnode is being committed, so copy it */
++ p = kmalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
++ if (unlikely(!p))
++ return ERR_PTR(-ENOMEM);
++
++ memcpy(p, pnode, sizeof(struct ubifs_pnode));
++ p->cnext = NULL;
++ __set_bit(DIRTY_CNODE, &p->flags);
++ __clear_bit(COW_CNODE, &p->flags);
++ replace_cats(c, pnode, p);
++
++ ubifs_assert(!test_bit(OBSOLETE_CNODE, &pnode->flags));
++ __set_bit(OBSOLETE_CNODE, &pnode->flags);
++
++ c->dirty_pn_cnt += 1;
++ add_pnode_dirt(c, pnode);
++ pnode->parent->nbranch[p->iip].pnode = p;
++ return p;
++}
++
++/**
++ * ubifs_lpt_lookup_dirty - lookup LEB properties in the LPT.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number to lookup
++ *
++ * This function returns a pointer to the LEB properties on success or a
++ * negative error code on failure.
++ */
++struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum)
++{
++ int err, i, h, iip, shft;
++ struct ubifs_nnode *nnode;
++ struct ubifs_pnode *pnode;
++
++ if (!c->nroot) {
++ err = ubifs_read_nnode(c, NULL, 0);
++ if (err)
++ return ERR_PTR(err);
++ }
++ nnode = c->nroot;
++ nnode = dirty_cow_nnode(c, nnode);
++ if (IS_ERR(nnode))
++ return ERR_PTR(PTR_ERR(nnode));
++ i = lnum - c->main_first;
++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
++ for (h = 1; h < c->lpt_hght; h++) {
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ shft -= UBIFS_LPT_FANOUT_SHIFT;
++ nnode = ubifs_get_nnode(c, nnode, iip);
++ if (IS_ERR(nnode))
++ return ERR_PTR(PTR_ERR(nnode));
++ nnode = dirty_cow_nnode(c, nnode);
++ if (IS_ERR(nnode))
++ return ERR_PTR(PTR_ERR(nnode));
++ }
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ shft -= UBIFS_LPT_FANOUT_SHIFT;
++ pnode = ubifs_get_pnode(c, nnode, iip);
++ if (IS_ERR(pnode))
++ return ERR_PTR(PTR_ERR(pnode));
++ pnode = dirty_cow_pnode(c, pnode);
++ if (IS_ERR(pnode))
++ return ERR_PTR(PTR_ERR(pnode));
++ iip = (i & (UBIFS_LPT_FANOUT - 1));
++ dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum,
++ pnode->lprops[iip].free, pnode->lprops[iip].dirty,
++ pnode->lprops[iip].flags);
++ ubifs_assert(test_bit(DIRTY_CNODE, &pnode->flags));
++ return &pnode->lprops[iip];
++}
++
++/**
++ * lpt_init_rd - initialize the LPT for reading.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int lpt_init_rd(struct ubifs_info *c)
++{
++ int err, i;
++
++ c->ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
++ if (!c->ltab)
++ return -ENOMEM;
++
++ i = max_t(int, c->nnode_sz, c->pnode_sz);
++ c->lpt_nod_buf = kmalloc(i, GFP_KERNEL);
++ if (!c->lpt_nod_buf)
++ return -ENOMEM;
++
++ for (i = 0; i < LPROPS_HEAP_CNT; i++) {
++ c->lpt_heap[i].arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ,
++ GFP_KERNEL);
++ if (!c->lpt_heap[i].arr)
++ return -ENOMEM;
++ c->lpt_heap[i].cnt = 0;
++ c->lpt_heap[i].max_cnt = LPT_HEAP_SZ;
++ }
++
++ c->dirty_idx.arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, GFP_KERNEL);
++ if (!c->dirty_idx.arr)
++ return -ENOMEM;
++ c->dirty_idx.cnt = 0;
++ c->dirty_idx.max_cnt = LPT_HEAP_SZ;
++
++ err = read_ltab(c);
++ if (err)
++ return err;
++
++ dbg_lp("space_bits %d", c->space_bits);
++ dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits);
++ dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits);
++ dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits);
++ dbg_lp("pcnt_bits %d", c->pcnt_bits);
++ dbg_lp("lnum_bits %d", c->lnum_bits);
++ dbg_lp("pnode_sz %d", c->pnode_sz);
++ dbg_lp("nnode_sz %d", c->nnode_sz);
++ dbg_lp("ltab_sz %d", c->ltab_sz);
++ dbg_lp("lsave_sz %d", c->lsave_sz);
++ dbg_lp("lsave_cnt %d", c->lsave_cnt);
++ dbg_lp("lpt_hght %d", c->lpt_hght);
++ dbg_lp("big_lpt %d", c->big_lpt);
++ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
++ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
++ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
++ if (c->big_lpt)
++ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
++
++ return 0;
++}
++
++/**
++ * lpt_init_wr - initialize the LPT for writing.
++ * @c: UBIFS file-system description object
++ *
++ * 'lpt_init_rd()' must have been called already.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int lpt_init_wr(struct ubifs_info *c)
++{
++ int err, i;
++
++ c->ltab_cmt = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
++ if (!c->ltab_cmt)
++ return -ENOMEM;
++
++ c->lpt_buf = vmalloc(c->leb_size);
++ if (!c->lpt_buf)
++ return -ENOMEM;
++
++ if (c->big_lpt) {
++ c->lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_NOFS);
++ if (!c->lsave)
++ return -ENOMEM;
++ err = read_lsave(c);
++ if (err)
++ return err;
++ }
++
++ for (i = 0; i < c->lpt_lebs; i++)
++ if (c->ltab[i].free == c->leb_size) {
++ err = ubifs_leb_unmap(c, i + c->lpt_first);
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++
++/**
++ * ubifs_lpt_init - initialize the LPT.
++ * @c: UBIFS file-system description object
++ * @rd: whether to initialize lpt for reading
++ * @wr: whether to initialize lpt for writing
++ *
++ * For mounting 'rw', @rd and @wr are both true. For mounting 'ro', @rd is true
++ * and @wr is false. For mounting from 'ro' to 'rw', @rd is false and @wr is
++ * true.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr)
++{
++ int err;
++
++ if (rd) {
++ err = lpt_init_rd(c);
++ if (err)
++ return err;
++ }
++
++ if (wr) {
++ err = lpt_init_wr(c);
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++
++/**
++ * struct lpt_scan_node - somewhere to put nodes while we scan LPT.
++ * @nnode: where to keep a nnode
++ * @pnode: where to keep a pnode
++ * @cnode: where to keep a cnode
++ * @in_tree: is the node in the tree in memory
++ * @ptr.nnode: pointer to the nnode (if it is an nnode) which may be here or in
++ * the tree
++ * @ptr.pnode: ditto for pnode
++ * @ptr.cnode: ditto for cnode
++ */
++struct lpt_scan_node {
++ union {
++ struct ubifs_nnode nnode;
++ struct ubifs_pnode pnode;
++ struct ubifs_cnode cnode;
++ };
++ int in_tree;
++ union {
++ struct ubifs_nnode *nnode;
++ struct ubifs_pnode *pnode;
++ struct ubifs_cnode *cnode;
++ } ptr;
++};
++
++/**
++ * scan_get_nnode - for the scan, get a nnode from either the tree or flash.
++ * @c: the UBIFS file-system description object
++ * @path: where to put the nnode
++ * @parent: parent of the nnode
++ * @iip: index in parent of the nnode
++ *
++ * This function returns a pointer to the nnode on success or a negative error
++ * code on failure.
++ */
++static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
++ struct lpt_scan_node *path,
++ struct ubifs_nnode *parent, int iip)
++{
++ struct ubifs_nbranch *branch;
++ struct ubifs_nnode *nnode;
++ void *buf = c->lpt_nod_buf;
++ int err;
++
++ branch = &parent->nbranch[iip];
++ nnode = branch->nnode;
++ if (nnode) {
++ path->in_tree = 1;
++ path->ptr.nnode = nnode;
++ return nnode;
++ }
++ nnode = &path->nnode;
++ path->in_tree = 0;
++ path->ptr.nnode = nnode;
++ memset(nnode, 0, sizeof(struct ubifs_nnode));
++ if (branch->lnum == 0) {
++ /*
++ * This nnode was not written which just means that the LEB
++ * properties in the subtree below it describe empty LEBs. We
++ * make the nnode as though we had read it, which in fact means
++ * doing almost nothing.
++ */
++ if (c->big_lpt)
++ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
++ } else {
++ err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
++ c->nnode_sz);
++ if (err)
++ return ERR_PTR(err);
++ err = unpack_nnode(c, buf, nnode);
++ if (err)
++ return ERR_PTR(err);
++ }
++ err = validate_nnode(c, nnode, parent, iip);
++ if (err)
++ return ERR_PTR(err);
++ if (!c->big_lpt)
++ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
++ nnode->level = parent->level - 1;
++ nnode->parent = parent;
++ nnode->iip = iip;
++ return nnode;
++}
++
++/**
++ * scan_get_pnode - for the scan, get a pnode from either the tree or flash.
++ * @c: the UBIFS file-system description object
++ * @path: where to put the pnode
++ * @parent: parent of the pnode
++ * @iip: index in parent of the pnode
++ *
++ * This function returns a pointer to the pnode on success or a negative error
++ * code on failure.
++ */
++static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
++ struct lpt_scan_node *path,
++ struct ubifs_nnode *parent, int iip)
++{
++ struct ubifs_nbranch *branch;
++ struct ubifs_pnode *pnode;
++ void *buf = c->lpt_nod_buf;
++ int err;
++
++ branch = &parent->nbranch[iip];
++ pnode = branch->pnode;
++ if (pnode) {
++ path->in_tree = 1;
++ path->ptr.pnode = pnode;
++ return pnode;
++ }
++ pnode = &path->pnode;
++ path->in_tree = 0;
++ path->ptr.pnode = pnode;
++ memset(pnode, 0, sizeof(struct ubifs_pnode));
++ if (branch->lnum == 0) {
++ /*
++ * This pnode was not written which just means that the LEB
++ * properties in it describe empty LEBs. We make the pnode as
++ * though we had read it.
++ */
++ int i;
++
++ if (c->big_lpt)
++ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ struct ubifs_lprops * const lprops = &pnode->lprops[i];
++
++ lprops->free = c->leb_size;
++ lprops->flags = ubifs_categorize_lprops(c, lprops);
++ }
++ } else {
++ ubifs_assert(branch->lnum >= c->lpt_first &&
++ branch->lnum <= c->lpt_last);
++ ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
++ err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
++ c->pnode_sz);
++ if (err)
++ return ERR_PTR(err);
++ err = unpack_pnode(c, buf, pnode);
++ if (err)
++ return ERR_PTR(err);
++ }
++ err = validate_pnode(c, pnode, parent, iip);
++ if (err)
++ return ERR_PTR(err);
++ if (!c->big_lpt)
++ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
++ pnode->parent = parent;
++ pnode->iip = iip;
++ set_pnode_lnum(c, pnode);
++ return pnode;
++}
++
++/**
++ * ubifs_lpt_scan_nolock - scan the LPT.
++ * @c: the UBIFS file-system description object
++ * @start_lnum: LEB number from which to start scanning
++ * @end_lnum: LEB number at which to stop scanning
++ * @scan_cb: callback function called for each lprops
++ * @data: data to be passed to the callback function
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
++ ubifs_lpt_scan_callback scan_cb, void *data)
++{
++ int err = 0, i, h, iip, shft;
++ struct ubifs_nnode *nnode;
++ struct ubifs_pnode *pnode;
++ struct lpt_scan_node *path;
++
++ if (start_lnum == -1) {
++ start_lnum = end_lnum + 1;
++ if (start_lnum >= c->leb_cnt)
++ start_lnum = c->main_first;
++ }
++
++ ubifs_assert(start_lnum >= c->main_first && start_lnum < c->leb_cnt);
++ ubifs_assert(end_lnum >= c->main_first && end_lnum < c->leb_cnt);
++
++ if (!c->nroot) {
++ err = ubifs_read_nnode(c, NULL, 0);
++ if (err)
++ return err;
++ }
++
++ path = kmalloc(sizeof(struct lpt_scan_node) * (c->lpt_hght + 1),
++ GFP_NOFS);
++ if (!path)
++ return -ENOMEM;
++
++ path[0].ptr.nnode = c->nroot;
++ path[0].in_tree = 1;
++again:
++ /* Descend to the pnode containing start_lnum */
++ nnode = c->nroot;
++ i = start_lnum - c->main_first;
++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
++ for (h = 1; h < c->lpt_hght; h++) {
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ shft -= UBIFS_LPT_FANOUT_SHIFT;
++ nnode = scan_get_nnode(c, path + h, nnode, iip);
++ if (IS_ERR(nnode)) {
++ err = PTR_ERR(nnode);
++ goto out;
++ }
++ }
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ shft -= UBIFS_LPT_FANOUT_SHIFT;
++ pnode = scan_get_pnode(c, path + h, nnode, iip);
++ if (IS_ERR(pnode)) {
++ err = PTR_ERR(pnode);
++ goto out;
++ }
++ iip = (i & (UBIFS_LPT_FANOUT - 1));
++
++ /* Loop for each lprops */
++ while (1) {
++ struct ubifs_lprops *lprops = &pnode->lprops[iip];
++ int ret, lnum = lprops->lnum;
++
++ ret = scan_cb(c, lprops, path[h].in_tree, data);
++ if (ret < 0) {
++ err = ret;
++ goto out;
++ }
++ if (ret & LPT_SCAN_ADD) {
++ /* Add all the nodes in path to the tree in memory */
++ for (h = 1; h < c->lpt_hght; h++) {
++ const size_t sz = sizeof(struct ubifs_nnode);
++ struct ubifs_nnode *parent;
++
++ if (path[h].in_tree)
++ continue;
++ nnode = kmalloc(sz, GFP_NOFS);
++ if (!nnode) {
++ err = -ENOMEM;
++ goto out;
++ }
++ memcpy(nnode, &path[h].nnode, sz);
++ parent = nnode->parent;
++ parent->nbranch[nnode->iip].nnode = nnode;
++ path[h].ptr.nnode = nnode;
++ path[h].in_tree = 1;
++ path[h + 1].cnode.parent = nnode;
++ }
++ if (path[h].in_tree)
++ ubifs_ensure_cat(c, lprops);
++ else {
++ const size_t sz = sizeof(struct ubifs_pnode);
++ struct ubifs_nnode *parent;
++
++ pnode = kmalloc(sz, GFP_NOFS);
++ if (!pnode) {
++ err = -ENOMEM;
++ goto out;
++ }
++ memcpy(pnode, &path[h].pnode, sz);
++ parent = pnode->parent;
++ parent->nbranch[pnode->iip].pnode = pnode;
++ path[h].ptr.pnode = pnode;
++ path[h].in_tree = 1;
++ update_cats(c, pnode);
++ c->pnodes_have += 1;
++ }
++ err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)
++ c->nroot, 0, 0);
++ if (err)
++ goto out;
++ err = dbg_check_cats(c);
++ if (err)
++ goto out;
++ }
++ if (ret & LPT_SCAN_STOP) {
++ err = 0;
++ break;
++ }
++ /* Get the next lprops */
++ if (lnum == end_lnum) {
++ /*
++ * We got to the end without finding what we were
++ * looking for
++ */
++ err = -ENOSPC;
++ goto out;
++ }
++ if (lnum + 1 >= c->leb_cnt) {
++ /* Wrap-around to the beginning */
++ start_lnum = c->main_first;
++ goto again;
++ }
++ if (iip + 1 < UBIFS_LPT_FANOUT) {
++ /* Next lprops is in the same pnode */
++ iip += 1;
++ continue;
++ }
++ /* We need to get the next pnode. Go up until we can go right */
++ iip = pnode->iip;
++ while (1) {
++ h -= 1;
++ ubifs_assert(h >= 0);
++ nnode = path[h].ptr.nnode;
++ if (iip + 1 < UBIFS_LPT_FANOUT)
++ break;
++ iip = nnode->iip;
++ }
++ /* Go right */
++ iip += 1;
++ /* Descend to the pnode */
++ h += 1;
++ for (; h < c->lpt_hght; h++) {
++ nnode = scan_get_nnode(c, path + h, nnode, iip);
++ if (IS_ERR(nnode)) {
++ err = PTR_ERR(nnode);
++ goto out;
++ }
++ iip = 0;
++ }
++ pnode = scan_get_pnode(c, path + h, nnode, iip);
++ if (IS_ERR(pnode)) {
++ err = PTR_ERR(pnode);
++ goto out;
++ }
++ iip = 0;
++ }
++out:
++ kfree(path);
++ return err;
++}
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++/**
++ * dbg_chk_pnode - check a pnode.
++ * @c: the UBIFS file-system description object
++ * @pnode: pnode to check
++ * @col: pnode column
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
++ int col)
++{
++ int i;
++
++ if (pnode->num != col) {
++ dbg_err("pnode num %d expected %d parent num %d iip %d",
++ pnode->num, col, pnode->parent->num, pnode->iip);
++ return -EINVAL;
++ }
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ struct ubifs_lprops *lp, *lprops = &pnode->lprops[i];
++ int lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + i +
++ c->main_first;
++ int found, cat = lprops->flags & LPROPS_CAT_MASK;
++ struct ubifs_lpt_heap *heap;
++ struct list_head *list = NULL;
++
++ if (lnum >= c->leb_cnt)
++ continue;
++ if (lprops->lnum != lnum) {
++ dbg_err("bad LEB number %d expected %d",
++ lprops->lnum, lnum);
++ return -EINVAL;
++ }
++ if (lprops->flags & LPROPS_TAKEN) {
++ if (cat != LPROPS_UNCAT) {
++ dbg_err("LEB %d taken but not uncat %d",
++ lprops->lnum, cat);
++ return -EINVAL;
++ }
++ continue;
++ }
++ if (lprops->flags & LPROPS_INDEX) {
++ switch (cat) {
++ case LPROPS_UNCAT:
++ case LPROPS_DIRTY_IDX:
++ case LPROPS_FRDI_IDX:
++ break;
++ default:
++ dbg_err("LEB %d index but cat %d",
++ lprops->lnum, cat);
++ return -EINVAL;
++ }
++ } else {
++ switch (cat) {
++ case LPROPS_UNCAT:
++ case LPROPS_DIRTY:
++ case LPROPS_FREE:
++ case LPROPS_EMPTY:
++ case LPROPS_FREEABLE:
++ break;
++ default:
++ dbg_err("LEB %d not index but cat %d",
++ lprops->lnum, cat);
++ return -EINVAL;
++ }
++ }
++ switch (cat) {
++ case LPROPS_UNCAT:
++ list = &c->uncat_list;
++ break;
++ case LPROPS_EMPTY:
++ list = &c->empty_list;
++ break;
++ case LPROPS_FREEABLE:
++ list = &c->freeable_list;
++ break;
++ case LPROPS_FRDI_IDX:
++ list = &c->frdi_idx_list;
++ break;
++ }
++ found = 0;
++ switch (cat) {
++ case LPROPS_DIRTY:
++ case LPROPS_DIRTY_IDX:
++ case LPROPS_FREE:
++ heap = &c->lpt_heap[cat - 1];
++ if (lprops->hpos < heap->cnt &&
++ heap->arr[lprops->hpos] == lprops)
++ found = 1;
++ break;
++ case LPROPS_UNCAT:
++ case LPROPS_EMPTY:
++ case LPROPS_FREEABLE:
++ case LPROPS_FRDI_IDX:
++ list_for_each_entry(lp, list, list)
++ if (lprops == lp) {
++ found = 1;
++ break;
++ }
++ break;
++ }
++ if (!found) {
++ dbg_err("LEB %d cat %d not found in cat heap/list",
++ lprops->lnum, cat);
++ return -EINVAL;
++ }
++ switch (cat) {
++ case LPROPS_EMPTY:
++ if (lprops->free != c->leb_size) {
++ dbg_err("LEB %d cat %d free %d dirty %d",
++ lprops->lnum, cat, lprops->free,
++ lprops->dirty);
++ return -EINVAL;
++ }
++ case LPROPS_FREEABLE:
++ case LPROPS_FRDI_IDX:
++ if (lprops->free + lprops->dirty != c->leb_size) {
++ dbg_err("LEB %d cat %d free %d dirty %d",
++ lprops->lnum, cat, lprops->free,
++ lprops->dirty);
++ return -EINVAL;
++ }
++ }
++ }
++ return 0;
++}
++
++/**
++ * dbg_check_lpt_nodes - check nnodes and pnodes.
++ * @c: the UBIFS file-system description object
++ * @cnode: next cnode (nnode or pnode) to check
++ * @row: row of cnode (root is zero)
++ * @col: column of cnode (leftmost is zero)
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
++ int row, int col)
++{
++ struct ubifs_nnode *nnode, *nn;
++ struct ubifs_cnode *cn;
++ int num, iip = 0, err;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
++ return 0;
++
++ while (cnode) {
++ ubifs_assert(row >= 0);
++ nnode = cnode->parent;
++ if (cnode->level) {
++ /* cnode is a nnode */
++ num = calc_nnode_num(row, col);
++ if (cnode->num != num) {
++ dbg_err("nnode num %d expected %d "
++ "parent num %d iip %d", cnode->num, num,
++ (nnode ? nnode->num : 0), cnode->iip);
++ return -EINVAL;
++ }
++ nn = (struct ubifs_nnode *)cnode;
++ while (iip < UBIFS_LPT_FANOUT) {
++ cn = nn->nbranch[iip].cnode;
++ if (cn) {
++ /* Go down */
++ row += 1;
++ col <<= UBIFS_LPT_FANOUT_SHIFT;
++ col += iip;
++ iip = 0;
++ cnode = cn;
++ break;
++ }
++ /* Go right */
++ iip += 1;
++ }
++ if (iip < UBIFS_LPT_FANOUT)
++ continue;
++ } else {
++ struct ubifs_pnode *pnode;
++
++ /* cnode is a pnode */
++ pnode = (struct ubifs_pnode *)cnode;
++ err = dbg_chk_pnode(c, pnode, col);
++ if (err)
++ return err;
++ }
++ /* Go up and to the right */
++ row -= 1;
++ col >>= UBIFS_LPT_FANOUT_SHIFT;
++ iip = cnode->iip + 1;
++ cnode = (struct ubifs_cnode *)nnode;
++ }
++ return 0;
++}
++
++#endif /* CONFIG_UBIFS_FS_DEBUG */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/lpt_commit.c avr32-2.6/fs/ubifs/lpt_commit.c
+--- linux-2.6.25.6/fs/ubifs/lpt_commit.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/lpt_commit.c 2008-06-12 15:09:45.475816115 +0200
+@@ -0,0 +1,1631 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ */
++
++/*
++ * This file implements commit-related functionality of the LEB properties
++ * subsystem.
++ */
++
++#include <linux/crc16.h>
++#include "ubifs.h"
++
++/**
++ * first_dirty_cnode - find first dirty cnode.
++ * @c: UBIFS file-system description object
++ * @nnode: nnode at which to start
++ *
++ * This function returns the first dirty cnode or %NULL if there is not one.
++ */
++static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode)
++{
++ ubifs_assert(nnode);
++ while (1) {
++ int i, cont = 0;
++
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ struct ubifs_cnode *cnode;
++
++ cnode = nnode->nbranch[i].cnode;
++ if (cnode &&
++ test_bit(DIRTY_CNODE, &cnode->flags)) {
++ if (cnode->level == 0)
++ return cnode;
++ nnode = (struct ubifs_nnode *)cnode;
++ cont = 1;
++ break;
++ }
++ }
++ if (!cont)
++ return (struct ubifs_cnode *)nnode;
++ }
++}
++
++/**
++ * next_dirty_cnode - find next dirty cnode.
++ * @cnode: cnode from which to begin searching
++ *
++ * This function returns the next dirty cnode or %NULL if there is not one.
++ */
++static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode)
++{
++ struct ubifs_nnode *nnode;
++ int i;
++
++ ubifs_assert(cnode);
++ nnode = cnode->parent;
++ if (!nnode)
++ return NULL;
++ for (i = cnode->iip + 1; i < UBIFS_LPT_FANOUT; i++) {
++ cnode = nnode->nbranch[i].cnode;
++ if (cnode && test_bit(DIRTY_CNODE, &cnode->flags)) {
++ if (cnode->level == 0)
++ return cnode; /* cnode is a pnode */
++ /* cnode is a nnode */
++ return first_dirty_cnode((struct ubifs_nnode *)cnode);
++ }
++ }
++ return (struct ubifs_cnode *)nnode;
++}
++
++/**
++ * get_cnodes_to_commit - create list of dirty cnodes to commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns the number of cnodes to commit.
++ */
++static int get_cnodes_to_commit(struct ubifs_info *c)
++{
++ struct ubifs_cnode *cnode, *cnext;
++ int cnt = 0;
++
++ if (!c->nroot)
++ return 0;
++
++ if (!test_bit(DIRTY_CNODE, &c->nroot->flags))
++ return 0;
++
++ c->lpt_cnext = first_dirty_cnode(c->nroot);
++ cnode = c->lpt_cnext;
++ if (!cnode)
++ return 0;
++ cnt += 1;
++ while (1) {
++ ubifs_assert(!test_bit(COW_ZNODE, &cnode->flags));
++ __set_bit(COW_ZNODE, &cnode->flags);
++ cnext = next_dirty_cnode(cnode);
++ if (!cnext) {
++ cnode->cnext = c->lpt_cnext;
++ break;
++ }
++ cnode->cnext = cnext;
++ cnode = cnext;
++ cnt += 1;
++ }
++ dbg_cmt("committing %d cnodes", cnt);
++ dbg_lp("committing %d cnodes", cnt);
++ ubifs_assert(cnt == c->dirty_nn_cnt + c->dirty_pn_cnt);
++ return cnt;
++}
++
++/**
++ * upd_ltab - update LPT LEB properties.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number
++ * @free: amount of free space
++ * @dirty: amount of dirty space to add
++ */
++static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
++{
++ dbg_lp("LEB %d free %d dirty %d to %d +%d",
++ lnum, c->ltab[lnum - c->lpt_first].free,
++ c->ltab[lnum - c->lpt_first].dirty, free, dirty);
++ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
++ c->ltab[lnum - c->lpt_first].free = free;
++ c->ltab[lnum - c->lpt_first].dirty += dirty;
++}
++
++/**
++ * alloc_lpt_leb - allocate an LPT LEB that is empty.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number is passed and returned here
++ *
++ * This function finds the next empty LEB in the ltab starting from @lnum. If a
++ * an empty LEB is found it is returned in @lnum and the function returns %0.
++ * Otherwise the function returns -ENOSPC. Note however, that LPT is designed
++ * never to run out of space.
++ */
++static int alloc_lpt_leb(struct ubifs_info *c, int *lnum)
++{
++ int i, n;
++
++ n = *lnum - c->lpt_first + 1;
++ for (i = n; i < c->lpt_lebs; i++) {
++ if (c->ltab[i].tgc || c->ltab[i].cmt)
++ continue;
++ if (c->ltab[i].free == c->leb_size) {
++ c->ltab[i].cmt = 1;
++ *lnum = i + c->lpt_first;
++ return 0;
++ }
++ }
++
++ for (i = 0; i < n; i++) {
++ if (c->ltab[i].tgc || c->ltab[i].cmt)
++ continue;
++ if (c->ltab[i].free == c->leb_size) {
++ c->ltab[i].cmt = 1;
++ *lnum = i + c->lpt_first;
++ return 0;
++ }
++ }
++ dbg_err("last LEB %d", *lnum);
++ dump_stack();
++ return -ENOSPC;
++}
++
++/**
++ * layout_cnodes - layout cnodes for commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int layout_cnodes(struct ubifs_info *c)
++{
++ int lnum, offs, len, alen, done_lsave, done_ltab, err;
++ struct ubifs_cnode *cnode;
++
++ cnode = c->lpt_cnext;
++ if (!cnode)
++ return 0;
++ lnum = c->nhead_lnum;
++ offs = c->nhead_offs;
++ /* Try to place lsave and ltab nicely */
++ done_lsave = !c->big_lpt;
++ done_ltab = 0;
++ if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
++ done_lsave = 1;
++ c->lsave_lnum = lnum;
++ c->lsave_offs = offs;
++ offs += c->lsave_sz;
++ }
++
++ if (offs + c->ltab_sz <= c->leb_size) {
++ done_ltab = 1;
++ c->ltab_lnum = lnum;
++ c->ltab_offs = offs;
++ offs += c->ltab_sz;
++ }
++
++ do {
++ if (cnode->level) {
++ len = c->nnode_sz;
++ c->dirty_nn_cnt -= 1;
++ } else {
++ len = c->pnode_sz;
++ c->dirty_pn_cnt -= 1;
++ }
++ while (offs + len > c->leb_size) {
++ alen = ALIGN(offs, c->min_io_size);
++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
++ err = alloc_lpt_leb(c, &lnum);
++ if (err)
++ return err;
++ offs = 0;
++ ubifs_assert(lnum >= c->lpt_first &&
++ lnum <= c->lpt_last);
++ /* Try to place lsave and ltab nicely */
++ if (!done_lsave) {
++ done_lsave = 1;
++ c->lsave_lnum = lnum;
++ c->lsave_offs = offs;
++ offs += c->lsave_sz;
++ continue;
++ }
++ if (!done_ltab) {
++ done_ltab = 1;
++ c->ltab_lnum = lnum;
++ c->ltab_offs = offs;
++ offs += c->ltab_sz;
++ continue;
++ }
++ break;
++ }
++ if (cnode->parent) {
++ cnode->parent->nbranch[cnode->iip].lnum = lnum;
++ cnode->parent->nbranch[cnode->iip].offs = offs;
++ } else {
++ c->lpt_lnum = lnum;
++ c->lpt_offs = offs;
++ }
++ offs += len;
++ cnode = cnode->cnext;
++ } while (cnode && cnode != c->lpt_cnext);
++
++ /* Make sure to place LPT's save table */
++ if (!done_lsave) {
++ if (offs + c->lsave_sz > c->leb_size) {
++ alen = ALIGN(offs, c->min_io_size);
++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
++ err = alloc_lpt_leb(c, &lnum);
++ if (err)
++ return err;
++ offs = 0;
++ ubifs_assert(lnum >= c->lpt_first &&
++ lnum <= c->lpt_last);
++ }
++ done_lsave = 1;
++ c->lsave_lnum = lnum;
++ c->lsave_offs = offs;
++ offs += c->lsave_sz;
++ }
++
++ /* Make sure to place LPT's own lprops table */
++ if (!done_ltab) {
++ if (offs + c->ltab_sz > c->leb_size) {
++ alen = ALIGN(offs, c->min_io_size);
++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
++ err = alloc_lpt_leb(c, &lnum);
++ if (err)
++ return err;
++ offs = 0;
++ ubifs_assert(lnum >= c->lpt_first &&
++ lnum <= c->lpt_last);
++ }
++ done_ltab = 1;
++ c->ltab_lnum = lnum;
++ c->ltab_offs = offs;
++ offs += c->ltab_sz;
++ }
++
++ alen = ALIGN(offs, c->min_io_size);
++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
++ return 0;
++}
++
++/**
++ * realloc_lpt_leb - allocate an LPT LEB that is empty.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number is passed and returned here
++ *
++ * This function duplicates exactly the results of the function alloc_lpt_leb.
++ * It is used during end commit to reallocate the same LEB numbers that were
++ * allocated by alloc_lpt_leb during start commit.
++ *
++ * This function finds the next LEB that was allocated by the alloc_lpt_leb
++ * function starting from @lnum. If a LEB is found it is returned in @lnum and
++ * the function returns %0. Otherwise the function returns -ENOSPC.
++ * Note however, that LPT is designed never to run out of space.
++ */
++static int realloc_lpt_leb(struct ubifs_info *c, int *lnum)
++{
++ int i, n;
++
++ n = *lnum - c->lpt_first + 1;
++ for (i = n; i < c->lpt_lebs; i++)
++ if (c->ltab[i].cmt) {
++ c->ltab[i].cmt = 0;
++ *lnum = i + c->lpt_first;
++ return 0;
++ }
++
++ for (i = 0; i < n; i++)
++ if (c->ltab[i].cmt) {
++ c->ltab[i].cmt = 0;
++ *lnum = i + c->lpt_first;
++ return 0;
++ }
++ dbg_err("last LEB %d", *lnum);
++ dump_stack();
++ return -ENOSPC;
++}
++
++/**
++ * write_cnodes - write cnodes for commit.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int write_cnodes(struct ubifs_info *c)
++{
++ int lnum, offs, len, from, err, wlen, alen, done_ltab, done_lsave;
++ struct ubifs_cnode *cnode;
++ void *buf = c->lpt_buf;
++
++ cnode = c->lpt_cnext;
++ if (!cnode)
++ return 0;
++ lnum = c->nhead_lnum;
++ offs = c->nhead_offs;
++ from = offs;
++ /* Ensure empty LEB is unmapped */
++ if (offs == 0) {
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ }
++ /* Try to place lsave and ltab nicely */
++ done_lsave = !c->big_lpt;
++ done_ltab = 0;
++ if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
++ done_lsave = 1;
++ ubifs_pack_lsave(c, buf + offs, c->lsave);
++ offs += c->lsave_sz;
++ }
++
++ if (offs + c->ltab_sz <= c->leb_size) {
++ done_ltab = 1;
++ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
++ offs += c->ltab_sz;
++ }
++
++ /* Loop for each cnode */
++ do {
++ if (cnode->level)
++ len = c->nnode_sz;
++ else
++ len = c->pnode_sz;
++ while (offs + len > c->leb_size) {
++ wlen = offs - from;
++ if (wlen) {
++ alen = ALIGN(wlen, c->min_io_size);
++ memset(buf + offs, 0xff, alen - wlen);
++ err = ubifs_leb_write(c, lnum, buf + from, from,
++ alen, UBI_SHORTTERM);
++ if (err)
++ return err;
++ }
++ err = realloc_lpt_leb(c, &lnum);
++ if (err)
++ return err;
++ offs = 0;
++ from = 0;
++ ubifs_assert(lnum >= c->lpt_first &&
++ lnum <= c->lpt_last);
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ /* Try to place lsave and ltab nicely */
++ if (!done_lsave) {
++ done_lsave = 1;
++ ubifs_pack_lsave(c, buf + offs, c->lsave);
++ offs += c->lsave_sz;
++ continue;
++ }
++ if (!done_ltab) {
++ done_ltab = 1;
++ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
++ offs += c->ltab_sz;
++ continue;
++ }
++ break;
++ }
++ if (cnode->level)
++ ubifs_pack_nnode(c, buf + offs,
++ (struct ubifs_nnode *)cnode);
++ else
++ ubifs_pack_pnode(c, buf + offs,
++ (struct ubifs_pnode *)cnode);
++ /*
++ * The reason for the barriers is the same as in case of TNC.
++ * See comment in 'write_index()'. 'dirty_cow_nnode()' and
++ * 'dirty_cow_pnode()' are the functions for which this is
++ * important.
++ */
++ clear_bit(DIRTY_CNODE, &cnode->flags);
++ smp_mb__before_clear_bit();
++ clear_bit(COW_ZNODE, &cnode->flags);
++ smp_mb__after_clear_bit();
++ offs += len;
++ cnode = cnode->cnext;
++ } while (cnode && cnode != c->lpt_cnext);
++
++ /* Make sure to place LPT's save table */
++ if (!done_lsave) {
++ if (offs + c->lsave_sz > c->leb_size) {
++ wlen = offs - from;
++ alen = ALIGN(wlen, c->min_io_size);
++ memset(buf + offs, 0xff, alen - wlen);
++ err = ubifs_leb_write(c, lnum, buf + from, from, alen,
++ UBI_SHORTTERM);
++ if (err)
++ return err;
++ err = realloc_lpt_leb(c, &lnum);
++ if (err)
++ return err;
++ offs = 0;
++ ubifs_assert(lnum >= c->lpt_first &&
++ lnum <= c->lpt_last);
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ }
++ done_lsave = 1;
++ ubifs_pack_lsave(c, buf + offs, c->lsave);
++ offs += c->lsave_sz;
++ }
++
++ /* Make sure to place LPT's own lprops table */
++ if (!done_ltab) {
++ if (offs + c->ltab_sz > c->leb_size) {
++ wlen = offs - from;
++ alen = ALIGN(wlen, c->min_io_size);
++ memset(buf + offs, 0xff, alen - wlen);
++ err = ubifs_leb_write(c, lnum, buf + from, from, alen,
++ UBI_SHORTTERM);
++ if (err)
++ return err;
++ err = realloc_lpt_leb(c, &lnum);
++ if (err)
++ return err;
++ offs = 0;
++ ubifs_assert(lnum >= c->lpt_first &&
++ lnum <= c->lpt_last);
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ }
++ done_ltab = 1;
++ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
++ offs += c->ltab_sz;
++ }
++
++ /* Write remaining data in buffer */
++ wlen = offs - from;
++ alen = ALIGN(wlen, c->min_io_size);
++ memset(buf + offs, 0xff, alen - wlen);
++ err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM);
++ if (err)
++ return err;
++ c->nhead_lnum = lnum;
++ c->nhead_offs = ALIGN(offs, c->min_io_size);
++
++ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
++ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
++ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
++ if (c->big_lpt)
++ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
++ return 0;
++}
++
++/**
++ * next_pnode - find next pnode.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode
++ *
++ * This function returns the next pnode or %NULL if there are no more pnodes.
++ */
++static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
++ struct ubifs_pnode *pnode)
++{
++ struct ubifs_nnode *nnode;
++ int iip;
++
++ /* Try to go right */
++ nnode = pnode->parent;
++ iip = pnode->iip + 1;
++ if (iip < UBIFS_LPT_FANOUT) {
++ /* We assume here that LEB zero is never an LPT LEB */
++ if (nnode->nbranch[iip].lnum)
++ return ubifs_get_pnode(c, nnode, iip);
++ else
++ return NULL;
++ }
++
++ /* Go up while can't go right */
++ do {
++ iip = nnode->iip + 1;
++ nnode = nnode->parent;
++ if (!nnode)
++ return NULL;
++ /* We assume here that LEB zero is never an LPT LEB */
++ } while (iip >= UBIFS_LPT_FANOUT || !nnode->nbranch[iip].lnum);
++
++ /* Go right */
++ nnode = ubifs_get_nnode(c, nnode, iip);
++ if (IS_ERR(nnode))
++ return (void *)nnode;
++
++ /* Go down to level 1 */
++ while (nnode->level > 1) {
++ nnode = ubifs_get_nnode(c, nnode, 0);
++ if (IS_ERR(nnode))
++ return (void *)nnode;
++ }
++
++ return ubifs_get_pnode(c, nnode, 0);
++}
++
++/**
++ * pnode_lookup - lookup a pnode in the LPT.
++ * @c: UBIFS file-system description object
++ * @i: pnode number (0 to main_lebs - 1)
++ *
++ * This function returns a pointer to the pnode on success or a negative
++ * error code on failure.
++ */
++static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i)
++{
++ int err, h, iip, shft;
++ struct ubifs_nnode *nnode;
++
++ if (!c->nroot) {
++ err = ubifs_read_nnode(c, NULL, 0);
++ if (err)
++ return ERR_PTR(err);
++ }
++ i <<= UBIFS_LPT_FANOUT_SHIFT;
++ nnode = c->nroot;
++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
++ for (h = 1; h < c->lpt_hght; h++) {
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ shft -= UBIFS_LPT_FANOUT_SHIFT;
++ nnode = ubifs_get_nnode(c, nnode, iip);
++ if (IS_ERR(nnode))
++ return ERR_PTR(PTR_ERR(nnode));
++ }
++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
++ return ubifs_get_pnode(c, nnode, iip);
++}
++
++/**
++ * add_pnode_dirt - add dirty space to LPT LEB properties.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode for which to add dirt
++ */
++static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
++{
++ ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum,
++ c->pnode_sz);
++}
++
++/**
++ * do_make_pnode_dirty - mark a pnode dirty.
++ * @c: UBIFS file-system description object
++ * @pnode: pnode to mark dirty
++ */
++static void do_make_pnode_dirty(struct ubifs_info *c, struct ubifs_pnode *pnode)
++{
++ /* Assumes cnext list is empty i.e. not called during commit */
++ if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) {
++ struct ubifs_nnode *nnode;
++
++ c->dirty_pn_cnt += 1;
++ add_pnode_dirt(c, pnode);
++ /* Mark parent and ancestors dirty too */
++ nnode = pnode->parent;
++ while (nnode) {
++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
++ c->dirty_nn_cnt += 1;
++ ubifs_add_nnode_dirt(c, nnode);
++ nnode = nnode->parent;
++ } else
++ break;
++ }
++ }
++}
++
++/**
++ * make_tree_dirty - mark the entire LEB properties tree dirty.
++ * @c: UBIFS file-system description object
++ *
++ * This function is used by the "small" LPT model to cause the entire LEB
++ * properties tree to be written. The "small" LPT model does not use LPT
++ * garbage collection because it is more efficient to write the entire tree
++ * (because it is small).
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int make_tree_dirty(struct ubifs_info *c)
++{
++ struct ubifs_pnode *pnode;
++
++ pnode = pnode_lookup(c, 0);
++ while (pnode) {
++ do_make_pnode_dirty(c, pnode);
++ pnode = next_pnode(c, pnode);
++ if (IS_ERR(pnode))
++ return PTR_ERR(pnode);
++ }
++ return 0;
++}
++
++/**
++ * need_write_all - determine if the LPT area is running out of free space.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns %1 if the LPT area is running out of free space and %0
++ * if it is not.
++ */
++static int need_write_all(struct ubifs_info *c)
++{
++ long long free = 0;
++ int i;
++
++ for (i = 0; i < c->lpt_lebs; i++) {
++ if (i + c->lpt_first == c->nhead_lnum)
++ free += c->leb_size - c->nhead_offs;
++ else if (c->ltab[i].free == c->leb_size)
++ free += c->leb_size;
++ else if (c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
++ free += c->leb_size;
++ }
++ /* Less than twice the size left */
++ if (free <= c->lpt_sz * 2)
++ return 1;
++ return 0;
++}
++
++/**
++ * lpt_tgc_start - start trivial garbage collection of LPT LEBs.
++ * @c: UBIFS file-system description object
++ *
++ * LPT trivial garbage collection is where a LPT LEB contains only dirty and
++ * free space and so may be reused as soon as the next commit is completed.
++ * This function is called during start commit to mark LPT LEBs for trivial GC.
++ */
++static void lpt_tgc_start(struct ubifs_info *c)
++{
++ int i;
++
++ for (i = 0; i < c->lpt_lebs; i++) {
++ if (i + c->lpt_first == c->nhead_lnum)
++ continue;
++ if (c->ltab[i].dirty > 0 &&
++ c->ltab[i].free + c->ltab[i].dirty == c->leb_size) {
++ c->ltab[i].tgc = 1;
++ c->ltab[i].free = c->leb_size;
++ c->ltab[i].dirty = 0;
++ dbg_lp("LEB %d", i + c->lpt_first);
++ }
++ }
++}
++
++/**
++ * lpt_tgc_end - end trivial garbage collection of LPT LEBs.
++ * @c: UBIFS file-system description object
++ *
++ * LPT trivial garbage collection is where a LPT LEB contains only dirty and
++ * free space and so may be reused as soon as the next commit is completed.
++ * This function is called after the commit is completed (master node has been
++ * written) and unmaps LPT LEBs that were marked for trivial GC.
++ */
++static int lpt_tgc_end(struct ubifs_info *c)
++{
++ int i, err;
++
++ for (i = 0; i < c->lpt_lebs; i++)
++ if (c->ltab[i].tgc) {
++ err = ubifs_leb_unmap(c, i + c->lpt_first);
++ if (err)
++ return err;
++ c->ltab[i].tgc = 0;
++ dbg_lp("LEB %d", i + c->lpt_first);
++ }
++ return 0;
++}
++
++/**
++ * populate_lsave - fill the lsave array with important LEB numbers.
++ * @c: the UBIFS file-system description object
++ *
++ * This function is only called for the "big" model. It records a small number
++ * of LEB numbers of important LEBs. Important LEBs are ones that are (from
++ * most important to least important): empty, freeable, freeable index, dirty
++ * index, dirty or free. Upon mount, we read this list of LEB numbers and bring
++ * their pnodes into memory. That will stop us from having to scan the LPT
++ * straight away. For the "small" model we assume that scanning the LPT is no
++ * big deal.
++ */
++static void populate_lsave(struct ubifs_info *c)
++{
++ struct ubifs_lprops *lprops;
++ struct ubifs_lpt_heap *heap;
++ int i, cnt = 0;
++
++ ubifs_assert(c->big_lpt);
++ if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
++ c->lpt_drty_flgs |= LSAVE_DIRTY;
++ ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
++ }
++ list_for_each_entry(lprops, &c->empty_list, list) {
++ c->lsave[cnt++] = lprops->lnum;
++ if (cnt >= c->lsave_cnt)
++ return;
++ }
++ list_for_each_entry(lprops, &c->freeable_list, list) {
++ c->lsave[cnt++] = lprops->lnum;
++ if (cnt >= c->lsave_cnt)
++ return;
++ }
++ list_for_each_entry(lprops, &c->frdi_idx_list, list) {
++ c->lsave[cnt++] = lprops->lnum;
++ if (cnt >= c->lsave_cnt)
++ return;
++ }
++ heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
++ for (i = 0; i < heap->cnt; i++) {
++ c->lsave[cnt++] = heap->arr[i]->lnum;
++ if (cnt >= c->lsave_cnt)
++ return;
++ }
++ heap = &c->lpt_heap[LPROPS_DIRTY - 1];
++ for (i = 0; i < heap->cnt; i++) {
++ c->lsave[cnt++] = heap->arr[i]->lnum;
++ if (cnt >= c->lsave_cnt)
++ return;
++ }
++ heap = &c->lpt_heap[LPROPS_FREE - 1];
++ for (i = 0; i < heap->cnt; i++) {
++ c->lsave[cnt++] = heap->arr[i]->lnum;
++ if (cnt >= c->lsave_cnt)
++ return;
++ }
++ /* Fill it up completely */
++ while (cnt < c->lsave_cnt)
++ c->lsave[cnt++] = c->main_first;
++}
++
++/**
++ * ubifs_lpt_start_commit - UBIFS commit starts.
++ * @c: the UBIFS file-system description object
++ *
++ * This function has to be called when UBIFS starts the commit operation.
++ * This function "freezes" all currently dirty LEB properties and does not
++ * change them anymore. Further changes are saved and tracked separately
++ * because they are not part of this commit. This function returns zero in case
++ * of success and a negative error code in case of failure.
++ */
++int ubifs_lpt_start_commit(struct ubifs_info *c)
++{
++ int err, cnt;
++
++ dbg_lp("");
++
++ mutex_lock(&c->lp_mutex);
++ err = dbg_check_ltab(c);
++ if (err)
++ goto out;
++
++ lpt_tgc_start(c);
++
++ if (!c->dirty_pn_cnt) {
++ dbg_cmt("no cnodes to commit");
++ err = 0;
++ goto out;
++ }
++
++ if (!c->big_lpt && need_write_all(c)) {
++ /* If needed, write everything */
++ err = make_tree_dirty(c);
++ if (err)
++ goto out;
++ lpt_tgc_start(c);
++ }
++
++ if (c->big_lpt)
++ populate_lsave(c);
++
++ cnt = get_cnodes_to_commit(c);
++ ubifs_assert(cnt != 0);
++
++ err = layout_cnodes(c);
++ if (err)
++ goto out;
++
++ /* Copy the LPT's own lprops for end commit to write */
++ memcpy(c->ltab_cmt, c->ltab,
++ sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
++ c->lpt_drty_flgs &= ~(LTAB_DIRTY | LSAVE_DIRTY);
++
++out:
++ mutex_unlock(&c->lp_mutex);
++ return err;
++}
++
++/**
++ * free_obsolete_cnodes - free obsolete cnodes for commit end.
++ * @c: UBIFS file-system description object
++ */
++static void free_obsolete_cnodes(struct ubifs_info *c)
++{
++ struct ubifs_cnode *cnode, *cnext;
++
++ cnext = c->lpt_cnext;
++ if (!cnext)
++ return;
++ do {
++ cnode = cnext;
++ cnext = cnode->cnext;
++ if (test_bit(OBSOLETE_CNODE, &cnode->flags))
++ kfree(cnode);
++ else
++ cnode->cnext = NULL;
++ } while (cnext != c->lpt_cnext);
++ c->lpt_cnext = NULL;
++}
++
++/**
++ * ubifs_lpt_end_commit - finish the commit operation.
++ * @c: the UBIFS file-system description object
++ *
++ * This function has to be called when the commit operation finishes. It
++ * flushes the changes which were "frozen" by 'ubifs_lprops_start_commit()' to
++ * the media. Returns zero in case of success and a negative error code in case
++ * of failure.
++ */
++int ubifs_lpt_end_commit(struct ubifs_info *c)
++{
++ int err;
++
++ dbg_lp("");
++
++ if (!c->lpt_cnext)
++ return 0;
++
++ err = write_cnodes(c);
++ if (err)
++ return err;
++
++ mutex_lock(&c->lp_mutex);
++ free_obsolete_cnodes(c);
++ mutex_unlock(&c->lp_mutex);
++
++ return 0;
++}
++
++/**
++ * nnode_lookup - lookup a nnode in the LPT.
++ * @c: UBIFS file-system description object
++ * @i: nnode number
++ *
++ * This function returns a pointer to the nnode on success or a negative
++ * error code on failure.
++ */
++static struct ubifs_nnode *nnode_lookup(struct ubifs_info *c, int i)
++{
++ int err, iip;
++ struct ubifs_nnode *nnode;
++
++ if (!c->nroot) {
++ err = ubifs_read_nnode(c, NULL, 0);
++ if (err)
++ return ERR_PTR(err);
++ }
++ nnode = c->nroot;
++ while (1) {
++ iip = i & (UBIFS_LPT_FANOUT - 1);
++ i >>= UBIFS_LPT_FANOUT_SHIFT;
++ if (!i)
++ break;
++ nnode = ubifs_get_nnode(c, nnode, iip);
++ if (IS_ERR(nnode))
++ return nnode;
++ }
++ return nnode;
++}
++
++/**
++ * make_nnode_dirty - find a nnode and, if found, make it dirty.
++ * @c: UBIFS file-system description object
++ * @node_num: nnode number of nnode to make dirty
++ * @lnum: LEB number where nnode was written
++ * @offs: offset where nnode was written
++ *
++ * This function is used by LPT garbage collection. LPT garbage collection is
++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
++ * simply involves marking all the nodes in the LEB being garbage-collected as
++ * dirty. The dirty nodes are written next commit, after which the LEB is free
++ * to be reused.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int make_nnode_dirty(struct ubifs_info *c, int node_num, int lnum,
++ int offs)
++{
++ struct ubifs_nnode *nnode;
++
++ nnode = nnode_lookup(c, node_num);
++ if (IS_ERR(nnode))
++ return PTR_ERR(nnode);
++ if (nnode->parent) {
++ struct ubifs_nbranch *branch;
++
++ branch = &nnode->parent->nbranch[nnode->iip];
++ if (branch->lnum != lnum || branch->offs != offs)
++ return 0; /* nnode is obsolete */
++ } else if (c->lpt_lnum != lnum || c->lpt_offs != offs)
++ return 0; /* nnode is obsolete */
++ /* Assumes cnext list is empty i.e. not called during commit */
++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
++ c->dirty_nn_cnt += 1;
++ ubifs_add_nnode_dirt(c, nnode);
++ /* Mark parent and ancestors dirty too */
++ nnode = nnode->parent;
++ while (nnode) {
++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
++ c->dirty_nn_cnt += 1;
++ ubifs_add_nnode_dirt(c, nnode);
++ nnode = nnode->parent;
++ } else
++ break;
++ }
++ }
++ return 0;
++}
++
++/**
++ * make_pnode_dirty - find a pnode and, if found, make it dirty.
++ * @c: UBIFS file-system description object
++ * @node_num: pnode number of pnode to make dirty
++ * @lnum: LEB number where pnode was written
++ * @offs: offset where pnode was written
++ *
++ * This function is used by LPT garbage collection. LPT garbage collection is
++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
++ * simply involves marking all the nodes in the LEB being garbage-collected as
++ * dirty. The dirty nodes are written next commit, after which the LEB is free
++ * to be reused.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum,
++ int offs)
++{
++ struct ubifs_pnode *pnode;
++ struct ubifs_nbranch *branch;
++
++ pnode = pnode_lookup(c, node_num);
++ if (IS_ERR(pnode))
++ return PTR_ERR(pnode);
++ branch = &pnode->parent->nbranch[pnode->iip];
++ if (branch->lnum != lnum || branch->offs != offs)
++ return 0;
++ do_make_pnode_dirty(c, pnode);
++ return 0;
++}
++
++/**
++ * make_ltab_dirty - make ltab node dirty.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number where ltab was written
++ * @offs: offset where ltab was written
++ *
++ * This function is used by LPT garbage collection. LPT garbage collection is
++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
++ * simply involves marking all the nodes in the LEB being garbage-collected as
++ * dirty. The dirty nodes are written next commit, after which the LEB is free
++ * to be reused.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int make_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
++{
++ if (lnum != c->ltab_lnum || offs != c->ltab_offs)
++ return 0; /* This ltab node is obsolete */
++ if (!(c->lpt_drty_flgs & LTAB_DIRTY)) {
++ c->lpt_drty_flgs |= LTAB_DIRTY;
++ ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz);
++ }
++ return 0;
++}
++
++/**
++ * make_lsave_dirty - make lsave node dirty.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number where lsave was written
++ * @offs: offset where lsave was written
++ *
++ * This function is used by LPT garbage collection. LPT garbage collection is
++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
++ * simply involves marking all the nodes in the LEB being garbage-collected as
++ * dirty. The dirty nodes are written next commit, after which the LEB is free
++ * to be reused.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int make_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
++{
++ if (lnum != c->lsave_lnum || offs != c->lsave_offs)
++ return 0; /* This lsave node is obsolete */
++ if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
++ c->lpt_drty_flgs |= LSAVE_DIRTY;
++ ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
++ }
++ return 0;
++}
++
++/**
++ * make_node_dirty - make node dirty.
++ * @c: UBIFS file-system description object
++ * @node_type: LPT node type
++ * @node_num: node number
++ * @lnum: LEB number where node was written
++ * @offs: offset where node was written
++ *
++ * This function is used by LPT garbage collection. LPT garbage collection is
++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
++ * simply involves marking all the nodes in the LEB being garbage-collected as
++ * dirty. The dirty nodes are written next commit, after which the LEB is free
++ * to be reused.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num,
++ int lnum, int offs)
++{
++ switch (node_type) {
++ case UBIFS_LPT_NNODE:
++ return make_nnode_dirty(c, node_num, lnum, offs);
++ case UBIFS_LPT_PNODE:
++ return make_pnode_dirty(c, node_num, lnum, offs);
++ case UBIFS_LPT_LTAB:
++ return make_ltab_dirty(c, lnum, offs);
++ case UBIFS_LPT_LSAVE:
++ return make_lsave_dirty(c, lnum, offs);
++ }
++ return -EINVAL;
++}
++
++/**
++ * get_lpt_node_len - return the length of a node based on its type.
++ * @c: UBIFS file-system description object
++ * @node_type: LPT node type
++ */
++static int get_lpt_node_len(struct ubifs_info *c, int node_type)
++{
++ switch (node_type) {
++ case UBIFS_LPT_NNODE:
++ return c->nnode_sz;
++ case UBIFS_LPT_PNODE:
++ return c->pnode_sz;
++ case UBIFS_LPT_LTAB:
++ return c->ltab_sz;
++ case UBIFS_LPT_LSAVE:
++ return c->lsave_sz;
++ }
++ return 0;
++}
++
++/**
++ * get_pad_len - return the length of padding in a buffer.
++ * @c: UBIFS file-system description object
++ * @buf: buffer
++ * @len: length of buffer
++ */
++static int get_pad_len(struct ubifs_info *c, uint8_t *buf, int len)
++{
++ int offs, pad_len;
++
++ if (c->min_io_size == 1)
++ return 0;
++ offs = c->leb_size - len;
++ pad_len = ALIGN(offs, c->min_io_size) - offs;
++ return pad_len;
++}
++
++/**
++ * get_lpt_node_type - return type (and node number) of a node in a buffer.
++ * @c: UBIFS file-system description object
++ * @buf: buffer
++ * @node_num: node number is returned here
++ */
++static int get_lpt_node_type(struct ubifs_info *c, uint8_t *buf, int *node_num)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int pos = 0, node_type;
++
++ node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
++ *node_num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
++ return node_type;
++}
++
++/**
++ * is_a_node - determine if a buffer contains a node.
++ * @c: UBIFS file-system description object
++ * @buf: buffer
++ * @len: length of buffer
++ *
++ * This function returns %1 if the buffer contains a node or %0 if it does not.
++ */
++static int is_a_node(struct ubifs_info *c, uint8_t *buf, int len)
++{
++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
++ int pos = 0, node_type, node_len;
++ uint16_t crc, calc_crc;
++
++ node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
++ if (node_type == UBIFS_LPT_NOT_A_NODE)
++ return 0;
++ node_len = get_lpt_node_len(c, node_type);
++ if (!node_len || node_len > len)
++ return 0;
++ pos = 0;
++ addr = buf;
++ crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
++ calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
++ node_len - UBIFS_LPT_CRC_BYTES);
++ if (crc != calc_crc)
++ return 0;
++ return 1;
++}
++
++
++/**
++ * lpt_gc_lnum - garbage collect a LPT LEB.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number to garbage collect
++ *
++ * LPT garbage collection is used only for the "big" LPT model
++ * (c->big_lpt == 1). Garbage collection simply involves marking all the nodes
++ * in the LEB being garbage-collected as dirty. The dirty nodes are written
++ * next commit, after which the LEB is free to be reused.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
++{
++ int err, len = c->leb_size, node_type, node_num, node_len, offs;
++ void *buf = c->lpt_buf;
++
++ dbg_lp("LEB %d", lnum);
++ err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
++ if (err) {
++ ubifs_err("cannot read LEB %d, error %d", lnum, err);
++ return err;
++ }
++ while (1) {
++ if (!is_a_node(c, buf, len)) {
++ int pad_len;
++
++ pad_len = get_pad_len(c, buf, len);
++ if (pad_len) {
++ buf += pad_len;
++ len -= pad_len;
++ continue;
++ }
++ return 0;
++ }
++ node_type = get_lpt_node_type(c, buf, &node_num);
++ node_len = get_lpt_node_len(c, node_type);
++ offs = c->leb_size - len;
++ ubifs_assert(node_len != 0);
++ mutex_lock(&c->lp_mutex);
++ err = make_node_dirty(c, node_type, node_num, lnum, offs);
++ mutex_unlock(&c->lp_mutex);
++ if (err)
++ return err;
++ buf += node_len;
++ len -= node_len;
++ }
++ return 0;
++}
++
++/**
++ * lpt_gc - LPT garbage collection.
++ * @c: UBIFS file-system description object
++ *
++ * Select a LPT LEB for LPT garbage collection and call 'lpt_gc_lnum()'.
++ * Returns %0 on success and a negative error code on failure.
++ */
++static int lpt_gc(struct ubifs_info *c)
++{
++ int i, lnum = -1, dirty = 0;
++
++ mutex_lock(&c->lp_mutex);
++ for (i = 0; i < c->lpt_lebs; i++) {
++ ubifs_assert(!c->ltab[i].tgc);
++ if (i + c->lpt_first == c->nhead_lnum ||
++ c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
++ continue;
++ if (c->ltab[i].dirty > dirty) {
++ dirty = c->ltab[i].dirty;
++ lnum = i + c->lpt_first;
++ }
++ }
++ mutex_unlock(&c->lp_mutex);
++ if (lnum == -1)
++ return -ENOSPC;
++ return lpt_gc_lnum(c, lnum);
++}
++
++/**
++ * ubifs_lpt_post_commit - post commit LPT trivial GC and LPT GC.
++ * @c: UBIFS file-system description object
++ *
++ * LPT trivial GC is completed after a commit. Also LPT GC is done after a
++ * commit for the "big" LPT model.
++ */
++int ubifs_lpt_post_commit(struct ubifs_info *c)
++{
++ int err;
++
++ mutex_lock(&c->lp_mutex);
++ err = lpt_tgc_end(c);
++ if (err)
++ goto out;
++ if (c->big_lpt)
++ while (need_write_all(c)) {
++ mutex_unlock(&c->lp_mutex);
++ err = lpt_gc(c);
++ if (err)
++ return err;
++ mutex_lock(&c->lp_mutex);
++ }
++out:
++ mutex_unlock(&c->lp_mutex);
++ return err;
++}
++
++/**
++ * first_nnode - find the first nnode in memory.
++ * @c: UBIFS file-system description object
++ * @hght: height of tree where nnode found is returned here
++ *
++ * This function returns a pointer to the nnode found or %NULL if no nnode is
++ * found. This function is a helper to 'ubifs_lpt_free()'.
++ */
++static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
++{
++ struct ubifs_nnode *nnode;
++ int h, i, found;
++
++ nnode = c->nroot;
++ *hght = 0;
++ if (!nnode)
++ return NULL;
++ for (h = 1; h < c->lpt_hght; h++) {
++ found = 0;
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ if (nnode->nbranch[i].nnode) {
++ found = 1;
++ nnode = nnode->nbranch[i].nnode;
++ *hght = h;
++ break;
++ }
++ }
++ if (!found)
++ break;
++ }
++ return nnode;
++}
++
++/**
++ * next_nnode - find the next nnode in memory.
++ * @c: UBIFS file-system description object
++ * @nnode: nnode from which to start.
++ * @hght: height of tree where nnode is, is passed and returned here
++ *
++ * This function returns a pointer to the nnode found or %NULL if no nnode is
++ * found. This function is a helper to 'ubifs_lpt_free()'.
++ */
++static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
++ struct ubifs_nnode *nnode, int *hght)
++{
++ struct ubifs_nnode *parent;
++ int iip, h, i, found;
++
++ parent = nnode->parent;
++ if (!parent)
++ return NULL;
++ if (nnode->iip == UBIFS_LPT_FANOUT - 1) {
++ *hght -= 1;
++ return parent;
++ }
++ for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
++ nnode = parent->nbranch[iip].nnode;
++ if (nnode)
++ break;
++ }
++ if (!nnode) {
++ *hght -= 1;
++ return parent;
++ }
++ for (h = *hght + 1; h < c->lpt_hght; h++) {
++ found = 0;
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
++ if (nnode->nbranch[i].nnode) {
++ found = 1;
++ nnode = nnode->nbranch[i].nnode;
++ *hght = h;
++ break;
++ }
++ }
++ if (!found)
++ break;
++ }
++ return nnode;
++}
++
++/**
++ * ubifs_lpt_free - free resources owned by the LPT.
++ * @c: UBIFS file-system description object
++ * @wr_only: free only resources used for writing
++ */
++void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
++{
++ struct ubifs_nnode *nnode;
++ int i, hght;
++
++ /* Free write-only things first */
++
++ free_obsolete_cnodes(c); /* Leftover from a failed commit */
++
++ vfree(c->ltab_cmt);
++ c->ltab_cmt = NULL;
++ vfree(c->lpt_buf);
++ c->lpt_buf = NULL;
++ kfree(c->lsave);
++ c->lsave = NULL;
++
++ if (wr_only)
++ return;
++
++ /* Now free the rest */
++
++ nnode = first_nnode(c, &hght);
++ while (nnode) {
++ for (i = 0; i < UBIFS_LPT_FANOUT; i++)
++ kfree(nnode->nbranch[i].nnode);
++ nnode = next_nnode(c, nnode, &hght);
++ }
++ for (i = 0; i < LPROPS_HEAP_CNT; i++)
++ kfree(c->lpt_heap[i].arr);
++ kfree(c->dirty_idx.arr);
++ kfree(c->nroot);
++ vfree(c->ltab);
++ kfree(c->lpt_nod_buf);
++}
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++/**
++ * dbg_is_all_ff - determine if a buffer contains only 0xff bytes.
++ * @buf: buffer
++ * @len: buffer length
++ */
++static int dbg_is_all_ff(uint8_t *buf, int len)
++{
++ int i;
++
++ for (i = 0; i < len; i++)
++ if (buf[i] != 0xff)
++ return 0;
++ return 1;
++}
++
++/**
++ * dbg_is_nnode_dirty - determine if a nnode is dirty.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB number where nnode was written
++ * @offs: offset where nnode was written
++ */
++static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs)
++{
++ struct ubifs_nnode *nnode;
++ int hght;
++
++ /* Entire tree is in memory so first_nnode / next_nnode are ok */
++ nnode = first_nnode(c, &hght);
++ for (; nnode; nnode = next_nnode(c, nnode, &hght)) {
++ struct ubifs_nbranch *branch;
++
++ cond_resched();
++ if (nnode->parent) {
++ branch = &nnode->parent->nbranch[nnode->iip];
++ if (branch->lnum != lnum || branch->offs != offs)
++ continue;
++ if (test_bit(DIRTY_CNODE, &nnode->flags))
++ return 1;
++ return 0;
++ } else {
++ if (c->lpt_lnum != lnum || c->lpt_offs != offs)
++ continue;
++ if (test_bit(DIRTY_CNODE, &nnode->flags))
++ return 1;
++ return 0;
++ }
++ }
++ return 1;
++}
++
++/**
++ * dbg_is_pnode_dirty - determine if a pnode is dirty.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB number where pnode was written
++ * @offs: offset where pnode was written
++ */
++static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs)
++{
++ int i, cnt;
++
++ cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
++ for (i = 0; i < cnt; i++) {
++ struct ubifs_pnode *pnode;
++ struct ubifs_nbranch *branch;
++
++ cond_resched();
++ pnode = pnode_lookup(c, i);
++ if (IS_ERR(pnode))
++ return PTR_ERR(pnode);
++ branch = &pnode->parent->nbranch[pnode->iip];
++ if (branch->lnum != lnum || branch->offs != offs)
++ continue;
++ if (test_bit(DIRTY_CNODE, &pnode->flags))
++ return 1;
++ return 0;
++ }
++ return 1;
++}
++
++/**
++ * dbg_is_ltab_dirty - determine if a ltab node is dirty.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB number where ltab node was written
++ * @offs: offset where ltab node was written
++ */
++static int dbg_is_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
++{
++ if (lnum != c->ltab_lnum || offs != c->ltab_offs)
++ return 1;
++ return (c->lpt_drty_flgs & LTAB_DIRTY) != 0;
++}
++
++/**
++ * dbg_is_lsave_dirty - determine if a lsave node is dirty.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB number where lsave node was written
++ * @offs: offset where lsave node was written
++ */
++static int dbg_is_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
++{
++ if (lnum != c->lsave_lnum || offs != c->lsave_offs)
++ return 1;
++ return (c->lpt_drty_flgs & LSAVE_DIRTY) != 0;
++}
++
++/**
++ * dbg_is_node_dirty - determine if a node is dirty.
++ * @c: the UBIFS file-system description object
++ * @node_type: node type
++ * @lnum: LEB number where node was written
++ * @offs: offset where node was written
++ */
++static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum,
++ int offs)
++{
++ switch (node_type) {
++ case UBIFS_LPT_NNODE:
++ return dbg_is_nnode_dirty(c, lnum, offs);
++ case UBIFS_LPT_PNODE:
++ return dbg_is_pnode_dirty(c, lnum, offs);
++ case UBIFS_LPT_LTAB:
++ return dbg_is_ltab_dirty(c, lnum, offs);
++ case UBIFS_LPT_LSAVE:
++ return dbg_is_lsave_dirty(c, lnum, offs);
++ }
++ return 1;
++}
++
++/**
++ * dbg_check_ltab_lnum - check the ltab for a LPT LEB number.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB number where node was written
++ * @offs: offset where node was written
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
++{
++ int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
++ int ret;
++ void *buf = c->dbg_buf;
++
++ dbg_lp("LEB %d", lnum);
++ err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
++ if (err) {
++ dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err);
++ return err;
++ }
++ while (1) {
++ if (!is_a_node(c, buf, len)) {
++ int i, pad_len;
++
++ pad_len = get_pad_len(c, buf, len);
++ if (pad_len) {
++ buf += pad_len;
++ len -= pad_len;
++ dirty += pad_len;
++ continue;
++ }
++ if (!dbg_is_all_ff(buf, len)) {
++ dbg_msg("invalid empty space in LEB %d at %d",
++ lnum, c->leb_size - len);
++ err = -EINVAL;
++ }
++ i = lnum - c->lpt_first;
++ if (len != c->ltab[i].free) {
++ dbg_msg("invalid free space in LEB %d "
++ "(free %d, expected %d)",
++ lnum, len, c->ltab[i].free);
++ err = -EINVAL;
++ }
++ if (dirty != c->ltab[i].dirty) {
++ dbg_msg("invalid dirty space in LEB %d "
++ "(dirty %d, expected %d)",
++ lnum, dirty, c->ltab[i].dirty);
++ err = -EINVAL;
++ }
++ return err;
++ }
++ node_type = get_lpt_node_type(c, buf, &node_num);
++ node_len = get_lpt_node_len(c, node_type);
++ ret = dbg_is_node_dirty(c, node_type, lnum, c->leb_size - len);
++ if (ret == 1)
++ dirty += node_len;
++ buf += node_len;
++ len -= node_len;
++ }
++}
++
++/**
++ * dbg_check_ltab - check the free and dirty space in the ltab.
++ * @c: the UBIFS file-system description object
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int dbg_check_ltab(struct ubifs_info *c)
++{
++ int lnum, err, i, cnt;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
++ return 0;
++
++ /* Bring the entire tree into memory */
++ cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
++ for (i = 0; i < cnt; i++) {
++ struct ubifs_pnode *pnode;
++
++ pnode = pnode_lookup(c, i);
++ if (IS_ERR(pnode))
++ return PTR_ERR(pnode);
++ cond_resched();
++ }
++
++ /* Check nodes */
++ err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)c->nroot, 0, 0);
++ if (err)
++ return err;
++
++ /* Check each LEB */
++ for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
++ err = dbg_check_ltab_lnum(c, lnum);
++ if (err) {
++ dbg_err("failed at LEB %d", lnum);
++ return err;
++ }
++ }
++
++ dbg_lp("succeeded");
++ return 0;
++}
++
++#endif /* CONFIG_UBIFS_FS_DEBUG */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/Makefile avr32-2.6/fs/ubifs/Makefile
+--- linux-2.6.25.6/fs/ubifs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/Makefile 2008-06-12 15:09:45.311815896 +0200
+@@ -0,0 +1,9 @@
++obj-$(CONFIG_UBIFS_FS) += ubifs.o
++
++ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
++ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
++ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
++ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o
++
++ubifs-$(CONFIG_UBIFS_FS_DEBUG) += debug.o
++ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/master.c avr32-2.6/fs/ubifs/master.c
+--- linux-2.6.25.6/fs/ubifs/master.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/master.c 2008-06-12 15:09:45.475816115 +0200
+@@ -0,0 +1,387 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/* This file implements reading and writing the master node */
++
++#include "ubifs.h"
++
++/**
++ * scan_for_master - search the valid master node.
++ * @c: UBIFS file-system description object
++ *
++ * This function scans the master node LEBs and search for the latest master
++ * node. Returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++static int scan_for_master(struct ubifs_info *c)
++{
++ struct ubifs_scan_leb *sleb;
++ struct ubifs_scan_node *snod;
++ int lnum, offs = 0, nodes_cnt;
++
++ lnum = UBIFS_MST_LNUM;
++
++ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
++ if (IS_ERR(sleb))
++ return PTR_ERR(sleb);
++ nodes_cnt = sleb->nodes_cnt;
++ if (nodes_cnt > 0) {
++ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
++ list);
++ if (snod->type != UBIFS_MST_NODE)
++ goto out;
++ memcpy(c->mst_node, snod->node, snod->len);
++ offs = snod->offs;
++ }
++ ubifs_scan_destroy(sleb);
++
++ lnum += 1;
++
++ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
++ if (IS_ERR(sleb))
++ return PTR_ERR(sleb);
++ if (sleb->nodes_cnt != nodes_cnt)
++ goto out;
++ if (!sleb->nodes_cnt)
++ goto out;
++ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
++ if (snod->type != UBIFS_MST_NODE)
++ goto out;
++ if (snod->offs != offs)
++ goto out;
++ if (memcmp((void *)c->mst_node + UBIFS_CH_SZ,
++ (void *)snod->node + UBIFS_CH_SZ,
++ UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
++ goto out;
++ c->mst_offs = offs;
++ ubifs_scan_destroy(sleb);
++ return 0;
++
++out:
++ ubifs_scan_destroy(sleb);
++ return -EINVAL;
++}
++
++/**
++ * validate_master - validate master node.
++ * @c: UBIFS file-system description object
++ *
++ * This function validates data which was read from master node. Returns zero
++ * if the data is all right and %-EINVAL if not.
++ */
++static int validate_master(const struct ubifs_info *c)
++{
++ unsigned long long main_sz;
++ int err;
++
++ if (c->max_sqnum >= SQNUM_WATERMARK) {
++ err = 1;
++ goto out;
++ }
++
++ if (c->cmt_no >= c->max_sqnum) {
++ err = 2;
++ goto out;
++ }
++
++ if (c->highest_inum >= INUM_WATERMARK) {
++ err = 3;
++ goto out;
++ }
++
++ if (c->lhead_lnum < UBIFS_LOG_LNUM ||
++ c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
++ c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
++ c->lhead_offs & (c->min_io_size - 1)) {
++ err = 4;
++ goto out;
++ }
++
++ if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
++ c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
++ err = 5;
++ goto out;
++ }
++
++ if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
++ c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
++ err = 6;
++ goto out;
++ }
++
++ if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
++ err = 7;
++ goto out;
++ }
++
++ if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
++ c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
++ c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
++ err = 8;
++ goto out;
++ }
++
++ main_sz = c->main_lebs * (unsigned long long)c->leb_size;
++ if (c->old_idx_sz & 7 || c->old_idx_sz >= main_sz) {
++ err = 9;
++ goto out;
++ }
++
++ if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
++ c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
++ err = 10;
++ goto out;
++ }
++
++ if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
++ c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
++ c->nhead_offs > c->leb_size) {
++ err = 11;
++ goto out;
++ }
++
++ if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
++ c->ltab_offs < 0 ||
++ c->ltab_offs + c->ltab_sz > c->leb_size) {
++ err = 12;
++ goto out;
++ }
++
++ if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
++ c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
++ c->lsave_offs + c->lsave_sz > c->leb_size)) {
++ err = 13;
++ goto out;
++ }
++
++ if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
++ err = 14;
++ goto out;
++ }
++
++ if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
++ err = 15;
++ goto out;
++ }
++
++ if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
++ err = 16;
++ goto out;
++ }
++
++ if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
++ c->lst.total_free & 7) {
++ err = 17;
++ goto out;
++ }
++
++ if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
++ err = 18;
++ goto out;
++ }
++
++ if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
++ err = 19;
++ goto out;
++ }
++
++ if (c->lst.total_free + c->lst.total_dirty +
++ c->lst.total_used > main_sz) {
++ err = 20;
++ goto out;
++ }
++
++ if (c->lst.total_dead + c->lst.total_dark +
++ c->lst.total_used + c->old_idx_sz > main_sz) {
++ err = 21;
++ goto out;
++ }
++
++ if (c->lst.total_dead < 0 ||
++ c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
++ c->lst.total_dead & 7) {
++ err = 22;
++ goto out;
++ }
++
++ if (c->lst.total_dark < 0 ||
++ c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
++ c->lst.total_dark & 7) {
++ err = 23;
++ goto out;
++ }
++
++ return 0;
++
++out:
++ ubifs_err("bad master node at offset %d error %d", c->mst_offs, err);
++ dbg_dump_node(c, c->mst_node);
++ return -EINVAL;
++}
++
++/**
++ * ubifs_read_master - read master node.
++ * @c: UBIFS file-system description object
++ *
++ * This function finds and reads the master node during file-system mount. If
++ * the flash is empty, it creates default master node as well. Returns zero in
++ * case of success and a negative error code in case of failure.
++ */
++int ubifs_read_master(struct ubifs_info *c)
++{
++ int err, old_leb_cnt;
++
++ c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
++ if (!c->mst_node)
++ return -ENOMEM;
++
++ err = scan_for_master(c);
++ if (err) {
++ err = ubifs_recover_master_node(c);
++ if (err)
++ /*
++ * Note, we do not free 'c->mst_node' here because the
++ * unmount routine will take care of this.
++ */
++ return err;
++ }
++
++ /* Make sure that the recovery flag is clear */
++ c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
++
++ c->max_sqnum = le64_to_cpu(c->mst_node->ch.sqnum);
++ c->highest_inum = le64_to_cpu(c->mst_node->highest_inum);
++ c->cmt_no = le64_to_cpu(c->mst_node->cmt_no);
++ c->zroot.lnum = le32_to_cpu(c->mst_node->root_lnum);
++ c->zroot.offs = le32_to_cpu(c->mst_node->root_offs);
++ c->zroot.len = le32_to_cpu(c->mst_node->root_len);
++ c->lhead_lnum = le32_to_cpu(c->mst_node->log_lnum);
++ c->gc_lnum = le32_to_cpu(c->mst_node->gc_lnum);
++ c->ihead_lnum = le32_to_cpu(c->mst_node->ihead_lnum);
++ c->ihead_offs = le32_to_cpu(c->mst_node->ihead_offs);
++ c->old_idx_sz = le64_to_cpu(c->mst_node->index_size);
++ c->lpt_lnum = le32_to_cpu(c->mst_node->lpt_lnum);
++ c->lpt_offs = le32_to_cpu(c->mst_node->lpt_offs);
++ c->nhead_lnum = le32_to_cpu(c->mst_node->nhead_lnum);
++ c->nhead_offs = le32_to_cpu(c->mst_node->nhead_offs);
++ c->ltab_lnum = le32_to_cpu(c->mst_node->ltab_lnum);
++ c->ltab_offs = le32_to_cpu(c->mst_node->ltab_offs);
++ c->lsave_lnum = le32_to_cpu(c->mst_node->lsave_lnum);
++ c->lsave_offs = le32_to_cpu(c->mst_node->lsave_offs);
++ c->lscan_lnum = le32_to_cpu(c->mst_node->lscan_lnum);
++ c->lst.empty_lebs = le32_to_cpu(c->mst_node->empty_lebs);
++ c->lst.idx_lebs = le32_to_cpu(c->mst_node->idx_lebs);
++ old_leb_cnt = le32_to_cpu(c->mst_node->leb_cnt);
++ c->lst.total_free = le64_to_cpu(c->mst_node->total_free);
++ c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
++ c->lst.total_used = le64_to_cpu(c->mst_node->total_used);
++ c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead);
++ c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark);
++
++ c->calc_idx_sz = c->old_idx_sz;
++
++ if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
++ c->no_orphs = 1;
++
++ if (old_leb_cnt != c->leb_cnt) {
++ /* The file system has been resized */
++ int growth = c->leb_cnt - old_leb_cnt;
++
++ if (c->leb_cnt < old_leb_cnt ||
++ c->leb_cnt < UBIFS_MIN_LEB_CNT) {
++ ubifs_err("bad leb_cnt on master node");
++ dbg_dump_node(c, c->mst_node);
++ return -EINVAL;
++ }
++
++ dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
++ old_leb_cnt, c->leb_cnt);
++ c->lst.empty_lebs += growth;
++ c->lst.total_free += growth * (long long)c->leb_size;
++ c->lst.total_dark += growth * (long long)c->dark_wm;
++
++ /*
++ * Reflect changes back onto the master node. N.B. the master
++ * node gets written immediately whenever mounting (or
++ * remounting) in read-write mode, so we do not need to write it
++ * here.
++ */
++ c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
++ c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
++ c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
++ c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
++ }
++
++ err = validate_master(c);
++ if (err)
++ return err;
++
++ err = dbg_old_index_check_init(c, &c->zroot);
++
++ return err;
++}
++
++/**
++ * ubifs_write_master - write master node.
++ * @c: UBIFS file-system description object
++ *
++ * This function writes the master node. The caller has to take the
++ * @c->mst_mutex lock before calling this function. Returns zero in case of
++ * success and a negative error code in case of failure. The master node is
++ * written twice to enable recovery.
++ */
++int ubifs_write_master(struct ubifs_info *c)
++{
++ int err, lnum, offs, len;
++
++ if (c->ro_media)
++ return -EINVAL;
++
++ lnum = UBIFS_MST_LNUM;
++ offs = c->mst_offs + c->mst_node_alsz;
++ len = UBIFS_MST_NODE_SZ;
++
++ if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ offs = 0;
++ }
++
++ c->mst_offs = offs;
++ c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
++
++ err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
++ if (err)
++ return err;
++
++ lnum += 1;
++
++ if (offs == 0) {
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ }
++ err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
++
++ return err;
++}
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/misc.h avr32-2.6/fs/ubifs/misc.h
+--- linux-2.6.25.6/fs/ubifs/misc.h 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/misc.h 2008-06-12 15:09:45.475816115 +0200
+@@ -0,0 +1,311 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Artem Bityutskiy (Битюцкий Артём)
++ * Adrian Hunter
++ */
++
++/*
++ * This file contains miscellaneous helper functions.
++ */
++
++#ifndef __UBIFS_MISC_H__
++#define __UBIFS_MISC_H__
++
++/**
++ * ubifs_zn_dirty - check if znode is dirty.
++ * @znode: znode to check
++ *
++ * This helper function returns %1 if @znode is dirty and %0 otherwise.
++ */
++static inline int ubifs_zn_dirty(const struct ubifs_znode *znode)
++{
++ return !!test_bit(DIRTY_ZNODE, &znode->flags);
++}
++
++/**
++ * ubifs_wake_up_bgt - wake up background thread.
++ * @c: UBIFS file-system description object
++ */
++static inline void ubifs_wake_up_bgt(struct ubifs_info *c)
++{
++ if (c->bgt && !c->need_bgt) {
++ c->need_bgt = 1;
++ wake_up_process(c->bgt);
++ }
++}
++
++/**
++ * ubifs_tnc_find_child - find next child in znode.
++ * @znode: znode to search at
++ * @start: the zbranch index to start at
++ *
++ * This helper function looks for znode child starting at index @start. Returns
++ * the child or %NULL if no children were found.
++ */
++static inline struct ubifs_znode *
++ubifs_tnc_find_child(struct ubifs_znode *znode, int start)
++{
++ while (start < znode->child_cnt) {
++ if (znode->zbranch[start].znode)
++ return znode->zbranch[start].znode;
++ start += 1;
++ }
++
++ return NULL;
++}
++
++/**
++ * ubifs_inode - get UBIFS inode information by VFS 'struct inode' object.
++ * @inode: the VFS 'struct inode' pointer
++ */
++static inline struct ubifs_inode *ubifs_inode(const struct inode *inode)
++{
++ return container_of(inode, struct ubifs_inode, vfs_inode);
++}
++
++/**
++ * ubifs_ro_mode - switch UBIFS to read read-only mode.
++ * @c: UBIFS file-system description object
++ * @err: error code which is the reason of switching to R/O mode
++ */
++static inline void ubifs_ro_mode(struct ubifs_info *c, int err)
++{
++ if (!c->ro_media) {
++ c->ro_media = 1;
++ ubifs_warn("switched to read-only mode, error %d", err);
++ dbg_dump_stack();
++ }
++}
++
++/**
++ * ubifs_compr_present - check if compressor was compiled in.
++ * @compr_type: compressor type to check
++ *
++ * This function returns %1 of compressor of type @compr_type is present, and
++ * %0 if not.
++ */
++static inline int ubifs_compr_present(int compr_type)
++{
++ ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
++ return !!ubifs_compressors[compr_type]->capi_name;
++}
++
++/**
++ * ubifs_compr_name - get compressor name string by its type.
++ * @compr_type: compressor type
++ *
++ * This function returns compressor type string.
++ */
++static inline const char *ubifs_compr_name(int compr_type)
++{
++ ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
++ return ubifs_compressors[compr_type]->name;
++}
++
++/**
++ * ubifs_wbuf_sync - synchronize write-buffer.
++ * @wbuf: write-buffer to synchronize
++ *
++ * This is the same as as 'ubifs_wbuf_sync_nolock()' but it does not assume
++ * that the write-buffer is already locked.
++ */
++static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
++{
++ int err;
++
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ err = ubifs_wbuf_sync_nolock(wbuf);
++ mutex_unlock(&wbuf->io_mutex);
++ return err;
++}
++
++/**
++ * ubifs_leb_unmap - unmap an LEB.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number to unmap
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
++{
++ int err;
++
++ err = ubi_leb_unmap(c->ubi, lnum);
++ if (err) {
++ ubifs_err("unmap LEB %d failed, error %d", lnum, err);
++ return err;
++ }
++
++ return 0;
++}
++
++/**
++ * ubifs_leb_write - write to a LEB.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number to write
++ * @buf: buffer to write from
++ * @offs: offset within LEB to write to
++ * @len: length to write
++ * @dtype: data type
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
++ const void *buf, int offs, int len, int dtype)
++{
++ int err;
++
++ err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
++ if (err) {
++ ubifs_err("writing %d bytes at %d:%d, error %d",
++ len, lnum, offs, err);
++ return err;
++ }
++
++ return 0;
++}
++
++/**
++ * ubifs_encode_dev - encode device node IDs.
++ * @dev: UBIFS device node information
++ * @rdev: device IDs to encode
++ *
++ * This is a helper function which encodes major/minor numbers of a device node
++ * into UBIFS device node description. We use standard Linux "new" and "huge"
++ * encodings.
++ */
++static inline int ubifs_encode_dev(union ubifs_dev_desc *dev, dev_t rdev)
++{
++ if (new_valid_dev(rdev)) {
++ dev->new = cpu_to_le32(new_encode_dev(rdev));
++ return sizeof(dev->new);
++ } else {
++ dev->huge = cpu_to_le64(huge_encode_dev(rdev));
++ return sizeof(dev->huge);
++ }
++}
++
++/**
++ * ubifs_add_dirt - add dirty space to LEB properties.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB to add dirty space for
++ * @dirty: dirty space to add
++ *
++ * This is a helper function which increased amount of dirty LEB space. Returns
++ * zero in case of success and a negative error code in case of failure.
++ */
++static inline int ubifs_add_dirt(struct ubifs_info *c, int lnum, int dirty)
++{
++ return ubifs_update_one_lp(c, lnum, LPROPS_NC, dirty, 0, 0);
++}
++
++/**
++ * ubifs_return_leb - return LEB to lprops.
++ * @c: the UBIFS file-system description object
++ * @lnum: LEB to return
++ *
++ * This helper function cleans the "taken" flag of a logical eraseblock in the
++ * lprops. Returns zero in case of success and a negative error code in case of
++ * failure.
++ */
++static inline int ubifs_return_leb(struct ubifs_info *c, int lnum)
++{
++ return ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
++ LPROPS_TAKEN, 0);
++}
++
++/**
++ * ubifs_idx_node_sz - return index node size.
++ * @c: the UBIFS file-system description object
++ * @child_cnt: number of children of this index node
++ */
++static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt)
++{
++ return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt;
++}
++
++/**
++ * ubifs_idx_branch - return pointer to an index branch.
++ * @c: the UBIFS file-system description object
++ * @idx: index node
++ * @bnum: branch number
++ */
++static inline
++struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
++ const struct ubifs_idx_node *idx,
++ int bnum)
++{
++ return (struct ubifs_branch *)((void *)idx->branches +
++ (UBIFS_BRANCH_SZ + c->key_len) * bnum);
++}
++
++/**
++ * ubifs_idx_key - return pointer to an index key.
++ * @c: the UBIFS file-system description object
++ * @idx: index node
++ */
++static inline void *ubifs_idx_key(const struct ubifs_info *c,
++ const struct ubifs_idx_node *idx)
++{
++ return (void *)((struct ubifs_branch *)idx->branches)->key;
++}
++
++/**
++ * ubifs_reported_space - calculate reported free space.
++ * @c: the UBIFS file-system description object
++ * @free: amount of free space
++ *
++ * This function calculates amount of free space which will be reported to
++ * user-space. User-space application tend to expect that if the file-system
++ * (e.g., via the 'statfs()' call) reports that it has N bytes available, they
++ * are able to write a file of size N. UBIFS attaches node headers to each data
++ * node and it has to write indexind nodes as well. This introduces additional
++ * overhead, and UBIFS it has to report sligtly less free space to meet the
++ * above expectetion.
++ *
++ * This function assumes free space is made up of uncompressed data nodes and
++ * full index nodes (one per data node, doubled because we always allow enough
++ * space to write the index twice).
++ *
++ * Note, the calculation is pessimistic, which means that most of the time
++ * UBIFS reports less space than it actually has.
++ */
++static inline long long ubifs_reported_space(const struct ubifs_info *c,
++ uint64_t free)
++{
++ int divisor, factor;
++
++ divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz << 1);
++ factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
++ do_div(free, divisor);
++
++ return free * factor;
++}
++
++/**
++ * ubifs_current_time - round current time to time granularity.
++ * @inode: inode
++ */
++static inline struct timespec ubifs_current_time(struct inode *inode)
++{
++ return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
++ current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
++}
++
++#endif /* __UBIFS_MISC_H__ */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/orphan.c avr32-2.6/fs/ubifs/orphan.c
+--- linux-2.6.25.6/fs/ubifs/orphan.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/orphan.c 2008-06-12 15:09:45.475816115 +0200
+@@ -0,0 +1,958 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Author: Adrian Hunter
++ */
++
++#include "ubifs.h"
++
++/*
++ * An orphan is an inode number whose inode node has been committed to the index
++ * with a link count of zero. That happens when an open file is deleted
++ * (unlinked) and then a commit is run. In the normal course of events the inode
++ * would be deleted when the file is closed. However in the case of an unclean
++ * unmount, orphans need to be accounted for. After an unclean unmount, the
++ * orphans' inodes must be deleted which means either scanning the entire index
++ * looking for them, or keeping a list on flash somewhere. This unit implements
++ * the latter approach.
++ *
++ * The orphan area is a fixed number of LEBs situated between the LPT area and
++ * the main area. The number of orphan area LEBs is specified when the file
++ * system is created. The minimum number is 1. The size of the orphan area
++ * should be so that it can hold the maximum number of orphans that are expected
++ * to ever exist at one time.
++ *
++ * The number of orphans that can fit in a LEB is:
++ *
++ * (c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64)
++ *
++ * For example: a 15872 byte LEB can fit 1980 orphans so 1 LEB may be enough.
++ *
++ * Orphans are accumulated in a rb-tree. When an inode's link count drops to
++ * zero, the inode number is added to the rb-tree. It is removed from the tree
++ * when the inode is deleted. Any new orphans that are in the orphan tree when
++ * the commit is run, are written to the orphan area in 1 or more orph nodes.
++ * If the orphan area is full, it is consolidated to make space. There is
++ * always enough space because validation prevents the user from creating more
++ * than the maximum number of orphans allowed.
++ */
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++static int dbg_check_orphans(struct ubifs_info *c);
++#else
++#define dbg_check_orphans(c) 0
++#endif
++
++/**
++ * ubifs_add_orphan - add an orphan.
++ * @c: UBIFS file-system description object
++ * @inum: orphan inode number
++ *
++ * Add an orphan. This function is called when an inodes link count drops to
++ * zero.
++ */
++int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
++{
++ struct ubifs_orphan *orphan, *o;
++ struct rb_node **p, *parent = NULL;
++
++ orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS);
++ if (!orphan)
++ return -ENOMEM;
++ orphan->inum = inum;
++ orphan->new = 1;
++
++ spin_lock(&c->orphan_lock);
++ if (c->tot_orphans >= c->max_orphans) {
++ spin_unlock(&c->orphan_lock);
++ kfree(orphan);
++ return -ENFILE;
++ }
++ p = &c->orph_tree.rb_node;
++ while (*p) {
++ parent = *p;
++ o = rb_entry(parent, struct ubifs_orphan, rb);
++ if (inum < o->inum)
++ p = &(*p)->rb_left;
++ else if (inum > o->inum)
++ p = &(*p)->rb_right;
++ else {
++ dbg_err("orphaned twice");
++ spin_unlock(&c->orphan_lock);
++ kfree(orphan);
++ return 0;
++ }
++ }
++ c->tot_orphans += 1;
++ c->new_orphans += 1;
++ rb_link_node(&orphan->rb, parent, p);
++ rb_insert_color(&orphan->rb, &c->orph_tree);
++ list_add_tail(&orphan->list, &c->orph_list);
++ list_add_tail(&orphan->new_list, &c->orph_new);
++ spin_unlock(&c->orphan_lock);
++ dbg_gen("ino %lu", inum);
++ return 0;
++}
++
++/**
++ * ubifs_delete_orphan - delete an orphan.
++ * @c: UBIFS file-system description object
++ * @inum: orphan inode number
++ *
++ * Delete an orphan. This function is called when an inode is deleted.
++ */
++void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
++{
++ struct ubifs_orphan *o;
++ struct rb_node *p;
++
++ spin_lock(&c->orphan_lock);
++ p = c->orph_tree.rb_node;
++ while (p) {
++ o = rb_entry(p, struct ubifs_orphan, rb);
++ if (inum < o->inum)
++ p = p->rb_left;
++ else if (inum > o->inum)
++ p = p->rb_right;
++ else {
++ if (o->dnext) {
++ spin_unlock(&c->orphan_lock);
++ dbg_gen("deleted twice ino %lu", inum);
++ return;
++ }
++ if (o->cnext) {
++ o->dnext = c->orph_dnext;
++ c->orph_dnext = o;
++ spin_unlock(&c->orphan_lock);
++ dbg_gen("delete later ino %lu", inum);
++ return;
++ }
++ rb_erase(p, &c->orph_tree);
++ list_del(&o->list);
++ c->tot_orphans -= 1;
++ if (o->new) {
++ list_del(&o->new_list);
++ c->new_orphans -= 1;
++ }
++ spin_unlock(&c->orphan_lock);
++ kfree(o);
++ dbg_gen("inum %lu", inum);
++ return;
++ }
++ }
++ spin_unlock(&c->orphan_lock);
++ dbg_err("missing orphan ino %lu", inum);
++ dbg_dump_stack();
++}
++
++/**
++ * ubifs_orphan_start_commit - start commit of orphans.
++ * @c: UBIFS file-system description object
++ *
++ * Start commit of orphans.
++ */
++int ubifs_orphan_start_commit(struct ubifs_info *c)
++{
++ struct ubifs_orphan *orphan, **last;
++
++ spin_lock(&c->orphan_lock);
++ last = &c->orph_cnext;
++ list_for_each_entry(orphan, &c->orph_new, new_list) {
++ ubifs_assert(orphan->new);
++ orphan->new = 0;
++ *last = orphan;
++ last = &orphan->cnext;
++ }
++ *last = orphan->cnext;
++ c->cmt_orphans = c->new_orphans;
++ c->new_orphans = 0;
++ dbg_cmt("%d orphans to commit", c->cmt_orphans);
++ INIT_LIST_HEAD(&c->orph_new);
++ if (c->tot_orphans == 0)
++ c->no_orphs = 1;
++ else
++ c->no_orphs = 0;
++ spin_unlock(&c->orphan_lock);
++ return 0;
++}
++
++/**
++ * avail_orphs - calculate available space.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns the number of orphans that can be written in the
++ * available space.
++ */
++static int avail_orphs(struct ubifs_info *c)
++{
++ int avail_lebs, avail, gap;
++
++ avail_lebs = c->orph_lebs - (c->ohead_lnum - c->orph_first) - 1;
++ avail = avail_lebs *
++ ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64));
++ gap = c->leb_size - c->ohead_offs;
++ if (gap >= UBIFS_ORPH_NODE_SZ + sizeof(__le64))
++ avail += (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64);
++ return avail;
++}
++
++/**
++ * tot_avail_orphs - calculate total space.
++ * @c: UBIFS file-system description object
++ *
++ * This function returns the number of orphans that can be written in half
++ * the total space. That leaves half the space for adding new orphans.
++ */
++static int tot_avail_orphs(struct ubifs_info *c)
++{
++ int avail_lebs, avail;
++
++ avail_lebs = c->orph_lebs;
++ avail = avail_lebs *
++ ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64));
++ return avail / 2;
++}
++
++/**
++ * do_write_orph_node - write a node
++ * @c: UBIFS file-system description object
++ * @len: length of node
++ * @atomic: write atomically
++ *
++ * This function writes a node to the orphan head from the orphan buffer. If
++ * %atomic is not zero, then the write is done atomically. On success, %0 is
++ * returned, otherwise a negative error code is returned.
++ */
++static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
++{
++ int err = 0;
++
++ if (atomic) {
++ ubifs_assert(c->ohead_offs == 0);
++ ubifs_prepare_node(c, c->orph_buf, len, 1);
++ len = ALIGN(len, c->min_io_size);
++ err = ubi_leb_change(c->ubi, c->ohead_lnum, c->orph_buf, len,
++ UBI_SHORTTERM);
++ } else {
++ if (c->ohead_offs == 0) {
++ /* Ensure LEB has been unmapped */
++ err = ubifs_leb_unmap(c, c->ohead_lnum);
++ if (err)
++ return err;
++ }
++ err = ubifs_write_node(c, c->orph_buf, len, c->ohead_lnum,
++ c->ohead_offs, UBI_SHORTTERM);
++ }
++ return err;
++}
++
++/**
++ * write_orph_node - write an orph node
++ * @c: UBIFS file-system description object
++ * @atomic: write atomically
++ *
++ * This function builds an orph node from the cnext list and writes it to the
++ * orphan head. On success, %0 is returned, otherwise a negative error code
++ * is returned.
++ */
++static int write_orph_node(struct ubifs_info *c, int atomic)
++{
++ struct ubifs_orphan *orphan, *cnext;
++ struct ubifs_orph_node *orph;
++ int gap, err, len, cnt, i;
++
++ ubifs_assert(c->cmt_orphans > 0);
++ gap = c->leb_size - c->ohead_offs;
++ if (gap < UBIFS_ORPH_NODE_SZ + sizeof(__le64)) {
++ c->ohead_lnum += 1;
++ c->ohead_offs = 0;
++ gap = c->leb_size;
++ if (c->ohead_lnum > c->orph_last) {
++ /*
++ * We limit the number of orphans so that this should
++ * never happen.
++ */
++ ubifs_err("out of space in orphan area");
++ return -EINVAL;
++ }
++ }
++ cnt = (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64);
++ if (cnt > c->cmt_orphans)
++ cnt = c->cmt_orphans;
++ len = UBIFS_ORPH_NODE_SZ + cnt * sizeof(__le64);
++ ubifs_assert(c->orph_buf);
++ orph = c->orph_buf;
++ orph->ch.node_type = UBIFS_ORPH_NODE;
++ spin_lock(&c->orphan_lock);
++ cnext = c->orph_cnext;
++ for (i = 0; i < cnt; i++) {
++ orphan = cnext;
++ orph->inos[i] = cpu_to_le64(orphan->inum);
++ cnext = orphan->cnext;
++ orphan->cnext = NULL;
++ }
++ c->orph_cnext = cnext;
++ c->cmt_orphans -= cnt;
++ spin_unlock(&c->orphan_lock);
++ if (c->cmt_orphans)
++ orph->cmt_no = cpu_to_le64(c->cmt_no + 1);
++ else
++ /* Mark the last node of the commit */
++ orph->cmt_no = cpu_to_le64((c->cmt_no + 1) | (1ULL << 63));
++ ubifs_assert(c->ohead_offs + len <= c->leb_size);
++ ubifs_assert(c->ohead_lnum >= c->orph_first);
++ ubifs_assert(c->ohead_lnum <= c->orph_last);
++ err = do_write_orph_node(c, len, atomic);
++ c->ohead_offs += ALIGN(len, c->min_io_size);
++ c->ohead_offs = ALIGN(c->ohead_offs, 8);
++ return err;
++}
++
++/**
++ * write_orph_nodes - write orph nodes until there are no more to commit
++ * @c: UBIFS file-system description object
++ * @atomic: write atomically
++ *
++ * This function writes orph nodes for all the orphans to commit. On success,
++ * %0 is returned, otherwise a negative error code is returned.
++ */
++static int write_orph_nodes(struct ubifs_info *c, int atomic)
++{
++ int err;
++
++ while (c->cmt_orphans > 0) {
++ err = write_orph_node(c, atomic);
++ if (err)
++ return err;
++ }
++ if (atomic) {
++ int lnum;
++
++ /* Unmap any unused LEBs after consolidation */
++ lnum = c->ohead_lnum + 1;
++ for (lnum = c->ohead_lnum + 1; lnum <= c->orph_last; lnum++) {
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ }
++ }
++ return 0;
++}
++
++/**
++ * consolidate - consolidate the orphan area.
++ * @c: UBIFS file-system description object
++ *
++ * This function enables consolidation by putting all the orphans into the list
++ * to commit. The list is in the order that the orphans were added, and the
++ * LEBs are written atomically in order, so at no time can orphans be lost by
++ * an unclean unmount.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int consolidate(struct ubifs_info *c)
++{
++ int tot_avail = tot_avail_orphs(c), err = 0;
++
++ spin_lock(&c->orphan_lock);
++ dbg_cmt("there is space for %d orphans and there are %d",
++ tot_avail, c->tot_orphans);
++ if (c->tot_orphans - c->new_orphans <= tot_avail) {
++ struct ubifs_orphan *orphan, **last;
++ int cnt = 0;
++
++ /* Change the cnext list to include all non-new orphans */
++ last = &c->orph_cnext;
++ list_for_each_entry(orphan, &c->orph_list, list) {
++ if (orphan->new)
++ continue;
++ *last = orphan;
++ last = &orphan->cnext;
++ cnt += 1;
++ }
++ *last = orphan->cnext;
++ ubifs_assert(cnt == c->tot_orphans - c->new_orphans);
++ c->cmt_orphans = cnt;
++ c->ohead_lnum = c->orph_first;
++ c->ohead_offs = 0;
++ } else {
++ /*
++ * We limit the number of orphans so that this should
++ * never happen.
++ */
++ ubifs_err("out of space in orphan area");
++ err = -EINVAL;
++ }
++ spin_unlock(&c->orphan_lock);
++ return err;
++}
++
++/**
++ * commit_orphans - commit orphans.
++ * @c: UBIFS file-system description object
++ *
++ * This function commits orphans to flash. On success, %0 is returned,
++ * otherwise a negative error code is returned.
++ */
++static int commit_orphans(struct ubifs_info *c)
++{
++ int avail, atomic = 0, err;
++
++ ubifs_assert(c->cmt_orphans > 0);
++ avail = avail_orphs(c);
++ if (avail < c->cmt_orphans) {
++ /* Not enough space to write new orphans, so consolidate */
++ err = consolidate(c);
++ if (err)
++ return err;
++ atomic = 1;
++ }
++ err = write_orph_nodes(c, atomic);
++ return err;
++}
++
++/**
++ * erase_deleted - erase the orphans marked for deletion.
++ * @c: UBIFS file-system description object
++ *
++ * During commit, the orphans being committed cannot be deleted, so they are
++ * marked for deletion and deleted by this function. Also, the recovery
++ * adds killed orphans to the deletion list, and therefore they are deleted
++ * here too.
++ */
++static void erase_deleted(struct ubifs_info *c)
++{
++ struct ubifs_orphan *orphan, *dnext;
++
++ spin_lock(&c->orphan_lock);
++ dnext = c->orph_dnext;
++ while (dnext) {
++ orphan = dnext;
++ dnext = orphan->dnext;
++ ubifs_assert(!orphan->new);
++ rb_erase(&orphan->rb, &c->orph_tree);
++ list_del(&orphan->list);
++ c->tot_orphans -= 1;
++ dbg_gen("deleting orphan ino %lu", orphan->inum);
++ kfree(orphan);
++ }
++ c->orph_dnext = NULL;
++ spin_unlock(&c->orphan_lock);
++}
++
++/**
++ * ubifs_orphan_end_commit - end commit of orphans.
++ * @c: UBIFS file-system description object
++ *
++ * End commit of orphans.
++ */
++int ubifs_orphan_end_commit(struct ubifs_info *c)
++{
++ int err;
++
++ if (c->cmt_orphans != 0) {
++ err = commit_orphans(c);
++ if (err)
++ return err;
++ }
++ erase_deleted(c);
++ err = dbg_check_orphans(c);
++ return err;
++}
++
++/**
++ * clear_orphans - erase all LEBs used for orphans.
++ * @c: UBIFS file-system description object
++ *
++ * If recovery is not required, then the orphans from the previous session
++ * are not needed. This function locates the LEBs used to record
++ * orphans, and un-maps them.
++ */
++static int clear_orphans(struct ubifs_info *c)
++{
++ int lnum, err;
++
++ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ }
++ c->ohead_lnum = c->orph_first;
++ c->ohead_offs = 0;
++ return 0;
++}
++
++/**
++ * insert_dead_orphan - insert an orphan.
++ * @c: UBIFS file-system description object
++ * @inum: orphan inode number
++ *
++ * This function is a helper to the 'do_kill_orphans()' function. The orphan
++ * must be kept until the next commit, so it is added to the rb-tree and the
++ * deletion list.
++ */
++static int insert_dead_orphan(struct ubifs_info *c, ino_t inum)
++{
++ struct ubifs_orphan *orphan, *o;
++ struct rb_node **p, *parent = NULL;
++
++ orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_KERNEL);
++ if (!orphan)
++ return -ENOMEM;
++ orphan->inum = inum;
++
++ p = &c->orph_tree.rb_node;
++ while (*p) {
++ parent = *p;
++ o = rb_entry(parent, struct ubifs_orphan, rb);
++ if (inum < o->inum)
++ p = &(*p)->rb_left;
++ else if (inum > o->inum)
++ p = &(*p)->rb_right;
++ else {
++ /* Already added - no problem */
++ kfree(orphan);
++ return 0;
++ }
++ }
++ c->tot_orphans += 1;
++ rb_link_node(&orphan->rb, parent, p);
++ rb_insert_color(&orphan->rb, &c->orph_tree);
++ list_add_tail(&orphan->list, &c->orph_list);
++ orphan->dnext = c->orph_dnext;
++ c->orph_dnext = orphan;
++ dbg_mnt("ino %lu, new %d, tot %d",
++ inum, c->new_orphans, c->tot_orphans);
++ return 0;
++}
++
++/**
++ * do_kill_orphans - remove orphan inodes from the index.
++ * @c: UBIFS file-system description object
++ * @sleb: scanned LEB
++ * @last_cmt_no: cmt_no of last orph node read is passed and returned here
++ * @outofdate: whether the LEB is out of date is returned here
++ * @last_flagged: whether the end orph node is encountered
++ *
++ * This function is a helper to the 'kill_orphans()' function. It goes through
++ * every orphan node in a LEB and for every inode number recorded, removes
++ * all keys for that inode from the TNC.
++ */
++static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
++ unsigned long long *last_cmt_no, int *outofdate,
++ int *last_flagged)
++{
++ struct ubifs_scan_node *snod;
++ struct ubifs_orph_node *orph;
++ unsigned long long cmt_no;
++ ino_t inum;
++ int i, n, err, first = 1;
++
++ list_for_each_entry(snod, &sleb->nodes, list) {
++ if (snod->type != UBIFS_ORPH_NODE) {
++ ubifs_err("invalid node type %d in orphan area at "
++ "%d:%d", snod->type, sleb->lnum, snod->offs);
++ dbg_dump_node(c, snod->node);
++ return -EINVAL;
++ }
++
++ orph = snod->node;
++
++ /* Check commit number */
++ cmt_no = le64_to_cpu(orph->cmt_no) & LLONG_MAX;
++ /*
++ * The commit number on the master node may be less, because
++ * of a failed commit. If there are several failed commits in a
++ * row, the commit number written on orph nodes will continue to
++ * increase (because the commit number is adjusted here) even
++ * though the commit number on the master node stays the same
++ * because the master node has not been re-written.
++ */
++ if (cmt_no > c->cmt_no)
++ c->cmt_no = cmt_no;
++ if (cmt_no < *last_cmt_no && *last_flagged) {
++ /*
++ * The last orph node had a higher commit number and was
++ * flagged as the last written for that commit number.
++ * That makes this orph node, out of date.
++ */
++ if (!first) {
++ ubifs_err("out of order commit number %llu in "
++ "orphan node at %d:%d",
++ cmt_no, sleb->lnum, snod->offs);
++ dbg_dump_node(c, snod->node);
++ return -EINVAL;
++ }
++ dbg_rcvry("out of date LEB %d", sleb->lnum);
++ *outofdate = 1;
++ return 0;
++ }
++
++ if (first)
++ first = 0;
++
++ n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
++ for (i = 0; i < n; i++) {
++ inum = le64_to_cpu(orph->inos[i]);
++ dbg_rcvry("deleting orphaned inode %lu", inum);
++ err = ubifs_tnc_remove_ino(c, inum);
++ if (err)
++ return err;
++ err = insert_dead_orphan(c, inum);
++ if (err)
++ return err;
++ }
++
++ *last_cmt_no = cmt_no;
++ if (le64_to_cpu(orph->cmt_no) & (1ULL << 63)) {
++ dbg_rcvry("last orph node for commit %llu at %d:%d",
++ cmt_no, sleb->lnum, snod->offs);
++ *last_flagged = 1;
++ } else
++ *last_flagged = 0;
++ }
++
++ return 0;
++}
++
++/**
++ * kill_orphans - remove all orphan inodes from the index.
++ * @c: UBIFS file-system description object
++ *
++ * If recovery is required, then orphan inodes recorded during the previous
++ * session (which ended with an unclean unmount) must be deleted from the index.
++ * This is done by updating the TNC, but since the index is not updated until
++ * the next commit, the LEBs where the orphan information is recorded are not
++ * erased until the next commit.
++ */
++static int kill_orphans(struct ubifs_info *c)
++{
++ unsigned long long last_cmt_no = 0;
++ int lnum, err = 0, outofdate = 0, last_flagged = 0;
++
++ c->ohead_lnum = c->orph_first;
++ c->ohead_offs = 0;
++ /* Check no-orphans flag and skip this if no orphans */
++ if (c->no_orphs) {
++ dbg_rcvry("no orphans");
++ return 0;
++ }
++ /*
++ * Orph nodes always start at c->orph_first and are written to each
++ * successive LEB in turn. Generally unused LEBs will have been unmapped
++ * but may contain out of date orph nodes if the unmap didn't go
++ * through. In addition, the last orph node written for each commit is
++ * marked (top bit of orph->cmt_no is set to 1). It is possible that
++ * there are orph nodes from the next commit (i.e. the commit did not
++ * complete successfully). In that case, no orphans will have been lost
++ * due to the way that orphans are written, and any orphans added will
++ * be valid orphans anyway and so can be deleted.
++ */
++ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
++ struct ubifs_scan_leb *sleb;
++
++ dbg_rcvry("LEB %d", lnum);
++ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
++ if (IS_ERR(sleb)) {
++ sleb = ubifs_recover_leb(c, lnum, 0, c->sbuf, 0);
++ if (IS_ERR(sleb)) {
++ err = PTR_ERR(sleb);
++ break;
++ }
++ }
++ err = do_kill_orphans(c, sleb, &last_cmt_no, &outofdate,
++ &last_flagged);
++ if (err || outofdate) {
++ ubifs_scan_destroy(sleb);
++ break;
++ }
++ if (sleb->endpt) {
++ c->ohead_lnum = lnum;
++ c->ohead_offs = sleb->endpt;
++ }
++ ubifs_scan_destroy(sleb);
++ }
++ return err;
++}
++
++/**
++ * ubifs_mount_orphans - delete orphan inodes and erase LEBs that recorded them.
++ * @c: UBIFS file-system description object
++ * @unclean: indicates recovery from unclean unmount
++ * @read_only: indicates read only mount
++ *
++ * This function is called when mounting to erase orphans from the previous
++ * session. If UBIFS was not unmounted cleanly, then the inodes recorded as
++ * orphans are deleted.
++ */
++int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only)
++{
++ int err = 0;
++
++ c->max_orphans = tot_avail_orphs(c);
++
++ if (!read_only) {
++ c->orph_buf = vmalloc(c->leb_size);
++ if (!c->orph_buf)
++ return -ENOMEM;
++ }
++
++ if (unclean)
++ err = kill_orphans(c);
++ else if (!read_only)
++ err = clear_orphans(c);
++
++ return err;
++}
++
++#ifdef CONFIG_UBIFS_FS_DEBUG
++
++struct check_orphan {
++ struct rb_node rb;
++ ino_t inum;
++};
++
++struct check_info {
++ unsigned long last_ino;
++ unsigned long tot_inos;
++ unsigned long missing;
++ unsigned long long leaf_cnt;
++ struct ubifs_ino_node *node;
++ struct rb_root root;
++};
++
++static int dbg_find_orphan(struct ubifs_info *c, ino_t inum)
++{
++ struct ubifs_orphan *o;
++ struct rb_node *p;
++
++ spin_lock(&c->orphan_lock);
++ p = c->orph_tree.rb_node;
++ while (p) {
++ o = rb_entry(p, struct ubifs_orphan, rb);
++ if (inum < o->inum)
++ p = p->rb_left;
++ else if (inum > o->inum)
++ p = p->rb_right;
++ else {
++ spin_unlock(&c->orphan_lock);
++ return 1;
++ }
++ }
++ spin_unlock(&c->orphan_lock);
++ return 0;
++}
++
++static int dbg_ins_check_orphan(struct rb_root *root, ino_t inum)
++{
++ struct check_orphan *orphan, *o;
++ struct rb_node **p, *parent = NULL;
++
++ orphan = kzalloc(sizeof(struct check_orphan), GFP_NOFS);
++ if (!orphan)
++ return -ENOMEM;
++ orphan->inum = inum;
++
++ p = &root->rb_node;
++ while (*p) {
++ parent = *p;
++ o = rb_entry(parent, struct check_orphan, rb);
++ if (inum < o->inum)
++ p = &(*p)->rb_left;
++ else if (inum > o->inum)
++ p = &(*p)->rb_right;
++ else {
++ kfree(orphan);
++ return 0;
++ }
++ }
++ rb_link_node(&orphan->rb, parent, p);
++ rb_insert_color(&orphan->rb, root);
++ return 0;
++}
++
++static int dbg_find_check_orphan(struct rb_root *root, ino_t inum)
++{
++ struct check_orphan *o;
++ struct rb_node *p;
++
++ p = root->rb_node;
++ while (p) {
++ o = rb_entry(p, struct check_orphan, rb);
++ if (inum < o->inum)
++ p = p->rb_left;
++ else if (inum > o->inum)
++ p = p->rb_right;
++ else
++ return 1;
++ }
++ return 0;
++}
++
++static void dbg_free_check_tree(struct rb_root *root)
++{
++ struct rb_node *this = root->rb_node;
++ struct check_orphan *o;
++
++ while (this) {
++ if (this->rb_left) {
++ this = this->rb_left;
++ continue;
++ } else if (this->rb_right) {
++ this = this->rb_right;
++ continue;
++ }
++ o = rb_entry(this, struct check_orphan, rb);
++ this = rb_parent(this);
++ if (this) {
++ if (this->rb_left == &o->rb)
++ this->rb_left = NULL;
++ else
++ this->rb_right = NULL;
++ }
++ kfree(o);
++ }
++}
++
++static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr,
++ void *priv)
++{
++ struct check_info *ci = priv;
++ ino_t inum;
++ int err;
++
++ inum = key_inum(c, &zbr->key);
++ if (inum != ci->last_ino) {
++ /* Lowest node type is the inode node, so it comes first */
++ if (key_type(c, &zbr->key) != UBIFS_INO_KEY)
++ ubifs_err("found orphan node ino %lu, type %d", inum,
++ key_type(c, &zbr->key));
++ ci->last_ino = inum;
++ ci->tot_inos += 1;
++ err = ubifs_tnc_read_node(c, zbr, ci->node);
++ if (err) {
++ ubifs_err("node read failed, error %d", err);
++ return err;
++ }
++ if (ci->node->nlink == 0)
++ /* Must be recorded as an orphan */
++ if (!dbg_find_check_orphan(&ci->root, inum) &&
++ !dbg_find_orphan(c, inum)) {
++ ubifs_err("missing orphan, ino %lu", inum);
++ ci->missing += 1;
++ }
++ }
++ ci->leaf_cnt += 1;
++ return 0;
++}
++
++static int dbg_read_orphans(struct check_info *ci, struct ubifs_scan_leb *sleb)
++{
++ struct ubifs_scan_node *snod;
++ struct ubifs_orph_node *orph;
++ ino_t inum;
++ int i, n, err;
++
++ list_for_each_entry(snod, &sleb->nodes, list) {
++ cond_resched();
++ if (snod->type != UBIFS_ORPH_NODE)
++ continue;
++ orph = snod->node;
++ n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
++ for (i = 0; i < n; i++) {
++ inum = le64_to_cpu(orph->inos[i]);
++ err = dbg_ins_check_orphan(&ci->root, inum);
++ if (err)
++ return err;
++ }
++ }
++ return 0;
++}
++
++static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci)
++{
++ int lnum, err = 0;
++
++ /* Check no-orphans flag and skip this if no orphans */
++ if (c->no_orphs)
++ return 0;
++
++ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
++ struct ubifs_scan_leb *sleb;
++
++ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
++ if (IS_ERR(sleb)) {
++ err = PTR_ERR(sleb);
++ break;
++ }
++
++ err = dbg_read_orphans(ci, sleb);
++ ubifs_scan_destroy(sleb);
++ if (err)
++ break;
++ }
++
++ return err;
++}
++
++static int dbg_check_orphans(struct ubifs_info *c)
++{
++ struct check_info ci;
++ int err;
++
++ if (!(ubifs_chk_flags & UBIFS_CHK_ORPH))
++ return 0;
++
++ ci.last_ino = 0;
++ ci.tot_inos = 0;
++ ci.missing = 0;
++ ci.leaf_cnt = 0;
++ ci.root = RB_ROOT;
++ ci.node = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
++ if (!ci.node) {
++ ubifs_err("out of memory");
++ return -ENOMEM;
++ }
++
++ err = dbg_scan_orphans(c, &ci);
++ if (err)
++ goto out;
++
++ err = dbg_walk_index(c, &dbg_orphan_check, NULL, &ci);
++ if (err) {
++ ubifs_err("cannot scan TNC, error %d", err);
++ goto out;
++ }
++
++ if (ci.missing) {
++ ubifs_err("%lu missing orphan(s)", ci.missing);
++ err = -EINVAL;
++ goto out;
++ }
++
++ dbg_cmt("last inode number is %lu", ci.last_ino);
++ dbg_cmt("total number of inodes is %lu", ci.tot_inos);
++ dbg_cmt("total number of leaf nodes is %llu", ci.leaf_cnt);
++
++out:
++ dbg_free_check_tree(&ci.root);
++ kfree(ci.node);
++ return err;
++}
++
++#endif /* CONFIG_UBIFS_FS_DEBUG */
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/recovery.c avr32-2.6/fs/ubifs/recovery.c
+--- linux-2.6.25.6/fs/ubifs/recovery.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/recovery.c 2008-06-12 15:09:45.475816115 +0200
+@@ -0,0 +1,1537 @@
++/*
++ * This file is part of UBIFS.
++ *
++ * Copyright (C) 2006-2008 Nokia Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * Authors: Adrian Hunter
++ * Artem Bityutskiy (Битюцкий Артём)
++ */
++
++/*
++ * This file implements functions needed to recover from unclean un-mounts.
++ * When UBIFS is mounted, it checks a flag on the master node to determine if
++ * an un-mount was completed sucessfully. If not, the process of mounting
++ * incorparates additional checking and fixing of on-flash data structures.
++ * UBIFS always cleans away all remnants of an unclean un-mount, so that
++ * errors do not accumulate. However UBIFS defers recovery if it is mounted
++ * read-only, and the flash is not modified in that case.
++ */
++
++#include <linux/crc32.h>
++#include "ubifs.h"
++
++/**
++ * is_empty - determine whether a buffer is empty (contains all 0xff).
++ * @buf: buffer to clean
++ * @len: length of buffer
++ *
++ * This function returns %1 if the buffer is empty (contains all 0xff) otherwise
++ * %0 is returned.
++ */
++static int is_empty(void *buf, int len)
++{
++ uint8_t *p = buf;
++ int i;
++
++ for (i = 0; i < len; i++)
++ if (*p++ != 0xff)
++ return 0;
++ return 1;
++}
++
++/**
++ * get_master_node - get the last valid master node allowing for corruption.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number
++ * @pbuf: buffer containing the LEB read, is returned here
++ * @mst: master node, if found, is returned here
++ * @cor: corruption, if found, is returned here
++ *
++ * This function allocates a buffer, reads the LEB into it, and finds and
++ * returns the last valid master node allowing for one area of corruption.
++ * The corrupt area, if there is one, must be consistent with the assumption
++ * that it is the result of an unclean unmount while the master node was being
++ * written. Under those circumstances, it is valid to use the previously written
++ * master node.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf,
++ struct ubifs_mst_node **mst, void **cor)
++{
++ const int sz = c->mst_node_alsz;
++ int err, offs, len;
++ void *sbuf, *buf;
++
++ sbuf = vmalloc(c->leb_size);
++ if (!sbuf)
++ return -ENOMEM;
++
++ err = ubi_read(c->ubi, lnum, sbuf, 0, c->leb_size);
++ if (err && err != -EBADMSG)
++ goto out_free;
++
++ /* Find the first position that is definitely not a node */
++ offs = 0;
++ buf = sbuf;
++ len = c->leb_size;
++ while (offs + UBIFS_MST_NODE_SZ <= c->leb_size) {
++ struct ubifs_ch *ch = buf;
++
++ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC)
++ break;
++ offs += sz;
++ buf += sz;
++ len -= sz;
++ }
++ /* See if there was a valid master node before that */
++ if (offs) {
++ int ret;
++
++ offs -= sz;
++ buf -= sz;
++ len += sz;
++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
++ if (ret != SCANNED_A_NODE && offs) {
++ /* Could have been corruption so check one place back */
++ offs -= sz;
++ buf -= sz;
++ len += sz;
++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
++ if (ret != SCANNED_A_NODE)
++ /*
++ * We accept only one area of corruption because
++ * we are assuming that it was caused while
++ * trying to write a master node.
++ */
++ goto out_err;
++ }
++ if (ret == SCANNED_A_NODE) {
++ struct ubifs_ch *ch = buf;
++
++ if (ch->node_type != UBIFS_MST_NODE)
++ goto out_err;
++ dbg_rcvry("found a master node at %d:%d", lnum, offs);
++ *mst = buf;
++ offs += sz;
++ buf += sz;
++ len -= sz;
++ }
++ }
++ /* Check for corruption */
++ if (offs < c->leb_size) {
++ if (!is_empty(buf, min_t(int, len, sz))) {
++ *cor = buf;
++ dbg_rcvry("found corruption at %d:%d", lnum, offs);
++ }
++ offs += sz;
++ buf += sz;
++ len -= sz;
++ }
++ /* Check remaining empty space */
++ if (offs < c->leb_size)
++ if (!is_empty(buf, len))
++ goto out_err;
++ *pbuf = sbuf;
++ return 0;
++
++out_err:
++ err = -EINVAL;
++out_free:
++ vfree(sbuf);
++ *mst = NULL;
++ *cor = NULL;
++ return err;
++}
++
++/**
++ * write_rcvrd_mst_node - write recovered master node.
++ * @c: UBIFS file-system description object
++ * @mst: master node
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int write_rcvrd_mst_node(struct ubifs_info *c,
++ struct ubifs_mst_node *mst)
++{
++ int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz;
++ uint32_t save_flags;
++
++ dbg_rcvry("recovery");
++
++ save_flags = mst->flags;
++ mst->flags = cpu_to_le32(le32_to_cpu(mst->flags) | UBIFS_MST_RCVRY);
++
++ ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
++ err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM);
++ if (err)
++ goto out;
++ err = ubi_leb_change(c->ubi, lnum + 1, mst, sz, UBI_SHORTTERM);
++ if (err)
++ goto out;
++out:
++ mst->flags = save_flags;
++ return err;
++}
++
++/**
++ * ubifs_recover_master_node - recover the master node.
++ * @c: UBIFS file-system description object
++ *
++ * This function recovers the master node from corruption that may occur due to
++ * an unclean unmount.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_recover_master_node(struct ubifs_info *c)
++{
++ void *buf1 = NULL, *buf2 = NULL, *cor1 = NULL, *cor2 = NULL;
++ struct ubifs_mst_node *mst1 = NULL, *mst2 = NULL, *mst;
++ const int sz = c->mst_node_alsz;
++ int err, offs1, offs2;
++
++ dbg_rcvry("recovery");
++
++ err = get_master_node(c, UBIFS_MST_LNUM, &buf1, &mst1, &cor1);
++ if (err)
++ goto out_free;
++
++ err = get_master_node(c, UBIFS_MST_LNUM + 1, &buf2, &mst2, &cor2);
++ if (err)
++ goto out_free;
++
++ if (mst1) {
++ offs1 = (void *)mst1 - buf1;
++ if ((le32_to_cpu(mst1->flags) & UBIFS_MST_RCVRY) &&
++ (offs1 == 0 && !cor1)) {
++ /*
++ * mst1 was written by recovery at offset 0 with no
++ * corruption.
++ */
++ dbg_rcvry("recovery recovery");
++ mst = mst1;
++ } else if (mst2) {
++ offs2 = (void *)mst2 - buf2;
++ if (offs1 == offs2) {
++ /* Same offset, so must be the same */
++ if (memcmp((void *)mst1 + UBIFS_CH_SZ,
++ (void *)mst2 + UBIFS_CH_SZ,
++ UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
++ goto out_err;
++ mst = mst1;
++ } else if (offs2 + sz == offs1) {
++ /* 1st LEB was written, 2nd was not */
++ if (cor1)
++ goto out_err;
++ mst = mst1;
++ } else if (offs1 == 0 && offs2 + sz >= c->leb_size) {
++ /* 1st LEB was unmapped and written, 2nd not */
++ if (cor1)
++ goto out_err;
++ mst = mst1;
++ } else
++ goto out_err;
++ } else {
++ /*
++ * 2nd LEB was unmapped and about to be written, so
++ * there must be only one master node in the first LEB
++ * and no corruption.
++ */
++ if (offs1 != 0 || cor1)
++ goto out_err;
++ mst = mst1;
++ }
++ } else {
++ if (!mst2)
++ goto out_err;
++ /*
++ * 1st LEB was unmapped and about to be written, so there must
++ * be no room left in 2nd LEB.
++ */
++ offs2 = (void *)mst2 - buf2;
++ if (offs2 + sz + sz <= c->leb_size)
++ goto out_err;
++ mst = mst2;
++ }
++
++ dbg_rcvry("recovered master node from LEB %d",
++ (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1));
++
++ memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
++
++ if ((c->vfs_sb->s_flags & MS_RDONLY)) {
++ /* Read-only mode. Keep a copy for switching to rw mode */
++ c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
++ if (!c->rcvrd_mst_node) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
++ } else {
++ /* Write the recovered master node */
++ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
++ err = write_rcvrd_mst_node(c, c->mst_node);
++ if (err)
++ goto out_free;
++ }
++
++ vfree(buf2);
++ vfree(buf1);
++
++ return 0;
++
++out_err:
++ err = -EINVAL;
++out_free:
++ ubifs_err("failed to recover master node");
++ if (mst1) {
++ dbg_err("dumping first master node");
++ dbg_dump_node(c, mst1);
++ }
++ if (mst2) {
++ dbg_err("dumping second master node");
++ dbg_dump_node(c, mst2);
++ }
++ vfree(buf2);
++ vfree(buf1);
++ return err;
++}
++
++/**
++ * ubifs_write_rcvrd_mst_node - write the recovered master node.
++ * @c: UBIFS file-system description object
++ *
++ * This function writes the master node that was recovered during mounting in
++ * read-only mode and must now be written because we are remounting rw.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_write_rcvrd_mst_node(struct ubifs_info *c)
++{
++ int err;
++
++ if (!c->rcvrd_mst_node)
++ return 0;
++ c->rcvrd_mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
++ err = write_rcvrd_mst_node(c, c->rcvrd_mst_node);
++ if (err)
++ return err;
++ kfree(c->rcvrd_mst_node);
++ c->rcvrd_mst_node = NULL;
++ return 0;
++}
++
++/**
++ * is_last_write - determine if an offset was in the last write to a LEB.
++ * @c: UBIFS file-system description object
++ * @buf: buffer to check
++ * @offs: offset to check
++ *
++ * This function returns %1 if @offs was in the last write to the LEB whose data
++ * is in @buf, otherwise %0 is returned. The determination is made by checking
++ * for subsequent empty space starting from the next min_io_size boundary (or a
++ * bit less than the common header size if min_io_size is one).
++ */
++static int is_last_write(const struct ubifs_info *c, void *buf, int offs)
++{
++ int empty_offs;
++ int check_len;
++ uint8_t *p;
++
++ if (c->min_io_size == 1) {
++ check_len = c->leb_size - offs;
++ p = buf + check_len;
++ for (; check_len > 0; check_len--)
++ if (*--p != 0xff)
++ break;
++ /*
++ * 'check_len' is the size of the corruption which cannot be
++ * more than the size of 1 node if it was caused by an unclean
++ * unmount.
++ */
++ if (check_len > UBIFS_MAX_NODE_SZ)
++ return 0;
++ return 1;
++ }
++
++ /*
++ * Round up to the next c->min_io_size boundary i.e. 'offs' is in the
++ * last wbuf written. After that should be empty space.
++ */
++ empty_offs = ALIGN(offs + 1, c->min_io_size);
++ check_len = c->leb_size - empty_offs;
++ p = buf + empty_offs - offs;
++
++ for (; check_len > 0; check_len--)
++ if (*p++ != 0xff)
++ return 0;
++ return 1;
++}
++
++/**
++ * clean_buf - clean the data from an LEB sitting in a buffer.
++ * @c: UBIFS file-system description object
++ * @buf: buffer to clean
++ * @lnum: LEB number to clean
++ * @offs: offset from which to clean
++ * @len: length of buffer
++ *
++ * This function pads up to the next min_io_size boundary (if there is one) and
++ * sets empty space to all 0xff. @buf, @offs and @len are updated to the next
++ * min_io_size boundary (if there is one).
++ */
++static void clean_buf(const struct ubifs_info *c, void **buf, int lnum,
++ int *offs, int *len)
++{
++ int empty_offs, pad_len;
++
++ lnum = lnum;
++ dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs);
++
++ if (c->min_io_size == 1) {
++ memset(*buf, 0xff, c->leb_size - *offs);
++ return;
++ }
++
++ ubifs_assert(!(*offs & 7));
++ empty_offs = ALIGN(*offs, c->min_io_size);
++ pad_len = empty_offs - *offs;
++ ubifs_pad(c, *buf, pad_len);
++ *offs += pad_len;
++ *buf += pad_len;
++ *len -= pad_len;
++ memset(*buf, 0xff, c->leb_size - empty_offs);
++}
++
++/**
++ * no_more_nodes - determine if there are no more nodes in a buffer.
++ * @c: UBIFS file-system description object
++ * @buf: buffer to check
++ * @len: length of buffer
++ * @lnum: LEB number of the LEB from which @buf was read
++ * @offs: offset from which @buf was read
++ *
++ * This function scans @buf for more nodes and returns %0 is a node is found and
++ * %1 if no more nodes are found.
++ */
++static int no_more_nodes(const struct ubifs_info *c, void *buf, int len,
++ int lnum, int offs)
++{
++ int skip, next_offs = 0;
++
++ if (len > UBIFS_DATA_NODE_SZ) {
++ struct ubifs_ch *ch = buf;
++ int dlen = le32_to_cpu(ch->len);
++
++ if (ch->node_type == UBIFS_DATA_NODE && dlen >= UBIFS_CH_SZ &&
++ dlen <= UBIFS_MAX_DATA_NODE_SZ)
++ /* The corrupt node looks like a data node */
++ next_offs = ALIGN(offs + dlen, 8);
++ }
++
++ if (c->min_io_size == 1)
++ skip = 8;
++ else
++ skip = ALIGN(offs + 1, c->min_io_size) - offs;
++
++ offs += skip;
++ buf += skip;
++ len -= skip;
++ while (len > 8) {
++ struct ubifs_ch *ch = buf;
++ uint32_t magic = le32_to_cpu(ch->magic);
++ int ret;
++
++ if (magic == UBIFS_NODE_MAGIC) {
++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
++ if (ret == SCANNED_A_NODE || ret > 0) {
++ /*
++ * There is a small chance this is just data in
++ * a data node, so check that possibility. e.g.
++ * this is part of a file that itself contains
++ * a UBIFS image.
++ */
++ if (next_offs && offs + le32_to_cpu(ch->len) <=
++ next_offs)
++ continue;
++ dbg_rcvry("unexpected node at %d:%d", lnum,
++ offs);
++ return 0;
++ }
++ }
++ offs += 8;
++ buf += 8;
++ len -= 8;
++ }
++ return 1;
++}
++
++/**
++ * fix_unclean_leb - fix an unclean LEB.
++ * @c: UBIFS file-system description object
++ * @sleb: scanned LEB information
++ * @start: offset where scan started
++ */
++static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
++ int start)
++{
++ int lnum = sleb->lnum, endpt = start;
++
++ /* Get the end offset of the last node we are keeping */
++ if (!list_empty(&sleb->nodes)) {
++ struct ubifs_scan_node *snod;
++
++ snod = list_entry(sleb->nodes.prev,
++ struct ubifs_scan_node, list);
++ endpt = snod->offs + snod->len;
++ }
++
++ if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) {
++ /* Add to recovery list */
++ struct ubifs_unclean_leb *ucleb;
++
++ dbg_rcvry("need to fix LEB %d start %d endpt %d",
++ lnum, start, sleb->endpt);
++ ucleb = kzalloc(sizeof(struct ubifs_unclean_leb), GFP_NOFS);
++ if (!ucleb)
++ return -ENOMEM;
++ ucleb->lnum = lnum;
++ ucleb->endpt = endpt;
++ list_add_tail(&ucleb->list, &c->unclean_leb_list);
++ } else {
++ /* Write the fixed LEB back to flash */
++ int err;
++
++ dbg_rcvry("fixing LEB %d start %d endpt %d",
++ lnum, start, sleb->endpt);
++ if (endpt == 0) {
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ } else {
++ int len = ALIGN(endpt, c->min_io_size);
++
++ if (start) {
++ err = ubi_read(c->ubi, lnum, sleb->buf, 0,
++ start);
++ if (err)
++ return err;
++ }
++ /* Pad to min_io_size */
++ if (len > endpt) {
++ int pad_len = len - ALIGN(endpt, 8);
++
++ if (pad_len > 0) {
++ void *buf = sleb->buf + len - pad_len;
++
++ ubifs_pad(c, buf, pad_len);
++ }
++ }
++ err = ubi_leb_change(c->ubi, lnum, sleb->buf, len,
++ UBI_UNKNOWN);
++ if (err)
++ return err;
++ }
++ }
++ return 0;
++}
++
++/**
++ * drop_incomplete_group - drop nodes from an incomplete group.
++ * @sleb: scanned LEB information
++ * @offs: offset of dropped nodes is returned here
++ *
++ * This function returns %1 if nodes are dropped and %0 otherwise.
++ */
++static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs)
++{
++ int dropped = 0;
++
++ while (!list_empty(&sleb->nodes)) {
++ struct ubifs_scan_node *snod;
++ struct ubifs_ch *ch;
++
++ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
++ list);
++ ch = snod->node;
++ if (ch->group_type != UBIFS_IN_NODE_GROUP)
++ return dropped;
++ dbg_rcvry("dropping node at %d:%d", sleb->lnum, snod->offs);
++ *offs = snod->offs;
++ list_del(&snod->list);
++ kfree(snod);
++ sleb->nodes_cnt -= 1;
++ dropped = 1;
++ }
++ return dropped;
++}
++
++/**
++ * ubifs_recover_leb - scan and recover a LEB.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number
++ * @offs: offset
++ * @sbuf: LEB-sized buffer to use
++ * @grouped: nodes may be grouped for recovery
++ *
++ * This function does a scan of a LEB, but caters for errors that might have
++ * been caused by the unclean unmount from which we are attempting to recover.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
++ int offs, void *sbuf, int grouped)
++{
++ int err, len = c->leb_size - offs, need_clean = 0, quiet = 1;
++ int empty_chkd = 0, start = offs;
++ struct ubifs_scan_leb *sleb;
++ void *buf = sbuf + offs;
++
++ dbg_rcvry("%d:%d", lnum, offs);
++
++ sleb = ubifs_start_scan(c, lnum, offs, sbuf);
++ if (IS_ERR(sleb))
++ return sleb;
++
++ if (sleb->ecc)
++ need_clean = 1;
++
++ while (len >= 8) {
++ int ret;
++
++ dbg_scan("look at LEB %d:%d (%d bytes left)",
++ lnum, offs, len);
++
++ cond_resched();
++
++ /*
++ * Scan quietly until there is an error from which we cannot
++ * recover
++ */
++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
++
++ if (ret == SCANNED_A_NODE) {
++ /* A valid node, and not a padding node */
++ struct ubifs_ch *ch = buf;
++ int node_len;
++
++ err = ubifs_add_snod(c, sleb, buf, offs);
++ if (err)
++ goto error;
++ node_len = ALIGN(le32_to_cpu(ch->len), 8);
++ offs += node_len;
++ buf += node_len;
++ len -= node_len;
++ continue;
++ }
++
++ if (ret > 0) {
++ /* Padding bytes or a valid padding node */
++ offs += ret;
++ buf += ret;
++ len -= ret;
++ continue;
++ }
++
++ if (ret == SCANNED_EMPTY_SPACE) {
++ if (!is_empty(buf, len)) {
++ if (!is_last_write(c, buf, offs))
++ break;
++ clean_buf(c, &buf, lnum, &offs, &len);
++ need_clean = 1;
++ }
++ empty_chkd = 1;
++ break;
++ }
++
++ if (ret == SCANNED_GARBAGE || ret == SCANNED_A_BAD_PAD_NODE)
++ if (is_last_write(c, buf, offs)) {
++ clean_buf(c, &buf, lnum, &offs, &len);
++ need_clean = 1;
++ empty_chkd = 1;
++ break;
++ }
++
++ if (ret == SCANNED_A_CORRUPT_NODE)
++ if (no_more_nodes(c, buf, len, lnum, offs)) {
++ clean_buf(c, &buf, lnum, &offs, &len);
++ need_clean = 1;
++ empty_chkd = 1;
++ break;
++ }
++
++ if (quiet) {
++ /* Redo the last scan but noisily */
++ quiet = 0;
++ continue;
++ }
++
++ switch (ret) {
++ case SCANNED_GARBAGE:
++ dbg_err("garbage");
++ goto corrupted;
++ case SCANNED_A_CORRUPT_NODE:
++ case SCANNED_A_BAD_PAD_NODE:
++ dbg_err("bad node");
++ goto corrupted;
++ default:
++ dbg_err("unknown");
++ goto corrupted;
++ }
++ }
++
++ if (!empty_chkd && !is_empty(buf, len)) {
++ if (is_last_write(c, buf, offs)) {
++ clean_buf(c, &buf, lnum, &offs, &len);
++ need_clean = 1;
++ } else {
++ ubifs_err("corrupt empty space at LEB %d:%d",
++ lnum, offs);
++ goto corrupted;
++ }
++ }
++
++ /* Drop nodes from incomplete group */
++ if (grouped && drop_incomplete_group(sleb, &offs)) {
++ buf = sbuf + offs;
++ len = c->leb_size - offs;
++ clean_buf(c, &buf, lnum, &offs, &len);
++ need_clean = 1;
++ }
++
++ if (offs % c->min_io_size) {
++ clean_buf(c, &buf, lnum, &offs, &len);
++ need_clean = 1;
++ }
++
++ ubifs_end_scan(c, sleb, lnum, offs);
++
++ if (need_clean) {
++ err = fix_unclean_leb(c, sleb, start);
++ if (err)
++ goto error;
++ }
++
++ return sleb;
++
++corrupted:
++ ubifs_scanned_corruption(c, lnum, offs, buf);
++ err = -EUCLEAN;
++error:
++ ubifs_err("LEB %d scanning failed", lnum);
++ ubifs_scan_destroy(sleb);
++ return ERR_PTR(err);
++}
++
++/**
++ * get_cs_sqnum - get commit start sequence number.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number of commit start node
++ * @offs: offset of commit start node
++ * @cs_sqnum: commit start sequence number is returned here
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
++ unsigned long long *cs_sqnum)
++{
++ struct ubifs_cs_node *cs_node = NULL;
++ int err, ret;
++
++ dbg_rcvry("at %d:%d", lnum, offs);
++ cs_node = kmalloc(UBIFS_CS_NODE_SZ, GFP_KERNEL);
++ if (!cs_node)
++ return -ENOMEM;
++ if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
++ goto out_err;
++ err = ubi_read(c->ubi, lnum, (void *)cs_node, offs, UBIFS_CS_NODE_SZ);
++ if (err && err != -EBADMSG)
++ goto out_free;
++ ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
++ if (ret != SCANNED_A_NODE) {
++ dbg_err("Not a valid node");
++ goto out_err;
++ }
++ if (cs_node->ch.node_type != UBIFS_CS_NODE) {
++ dbg_err("Node a CS node, type is %d", cs_node->ch.node_type);
++ goto out_err;
++ }
++ if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
++ dbg_err("CS node cmt_no %llu != current cmt_no %llu",
++ (unsigned long long)le64_to_cpu(cs_node->cmt_no),
++ c->cmt_no);
++ goto out_err;
++ }
++ *cs_sqnum = le64_to_cpu(cs_node->ch.sqnum);
++ dbg_rcvry("commit start sqnum %llu", *cs_sqnum);
++ kfree(cs_node);
++ return 0;
++
++out_err:
++ err = -EINVAL;
++out_free:
++ ubifs_err("failed to get CS sqnum");
++ kfree(cs_node);
++ return err;
++}
++
++/**
++ * ubifs_recover_log_leb - scan and recover a log LEB.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number
++ * @offs: offset
++ * @sbuf: LEB-sized buffer to use
++ *
++ * This function does a scan of a LEB, but caters for errors that might have
++ * been caused by the unclean unmount from which we are attempting to recover.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
++ int offs, void *sbuf)
++{
++ struct ubifs_scan_leb *sleb;
++ int next_lnum;
++
++ dbg_rcvry("LEB %d", lnum);
++ next_lnum = lnum + 1;
++ if (next_lnum >= UBIFS_LOG_LNUM + c->log_lebs)
++ next_lnum = UBIFS_LOG_LNUM;
++ if (next_lnum != c->ltail_lnum) {
++ /*
++ * We can only recover at the end of the log, so check that the
++ * next log LEB is empty or out of date.
++ */
++ sleb = ubifs_scan(c, next_lnum, 0, sbuf);
++ if (IS_ERR(sleb))
++ return sleb;
++ if (sleb->nodes_cnt) {
++ struct ubifs_scan_node *snod;
++ unsigned long long cs_sqnum = c->cs_sqnum;
++
++ snod = list_entry(sleb->nodes.next,
++ struct ubifs_scan_node, list);
++ if (cs_sqnum == 0) {
++ int err;
++
++ err = get_cs_sqnum(c, lnum, offs, &cs_sqnum);
++ if (err) {
++ ubifs_scan_destroy(sleb);
++ return ERR_PTR(err);
++ }
++ }
++ if (snod->sqnum > cs_sqnum) {
++ ubifs_err("unrecoverable log corruption "
++ "in LEB %d", lnum);
++ ubifs_scan_destroy(sleb);
++ return ERR_PTR(-EUCLEAN);
++ }
++ }
++ ubifs_scan_destroy(sleb);
++ }
++ return ubifs_recover_leb(c, lnum, offs, sbuf, 0);
++}
++
++/**
++ * recover_head - recover a head.
++ * @c: UBIFS file-system description object
++ * @lnum: LEB number of head to recover
++ * @offs: offset of head to recover
++ * @sbuf: LEB-sized buffer to use
++ *
++ * This function ensures that there is no data on the flash at a head location.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int recover_head(const struct ubifs_info *c, int lnum, int offs,
++ void *sbuf)
++{
++ int len, err, need_clean = 0;
++
++ if (c->min_io_size > 1)
++ len = c->min_io_size;
++ else
++ len = 512;
++ if (offs + len > c->leb_size)
++ len = c->leb_size - offs;
++
++ if (!len)
++ return 0;
++
++ /* Read at the head location and check it is empty flash */
++ err = ubi_read(c->ubi, lnum, sbuf, offs, len);
++ if (err)
++ need_clean = 1;
++ else {
++ uint8_t *p = sbuf;
++
++ while (len--)
++ if (*p++ != 0xff) {
++ need_clean = 1;
++ break;
++ }
++ }
++
++ if (need_clean) {
++ dbg_rcvry("cleaning head at %d:%d", lnum, offs);
++ if (offs == 0)
++ return ubifs_leb_unmap(c, lnum);
++ err = ubi_read(c->ubi, lnum, sbuf, 0, offs);
++ if (err)
++ return err;
++ return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN);
++ }
++
++ return 0;
++}
++
++/**
++ * ubifs_recover_inl_heads - recover index and LPT heads.
++ * @c: UBIFS file-system description object
++ * @sbuf: LEB-sized buffer to use
++ *
++ * This function ensures that there is no data on the flash at the index and
++ * LPT head locations.
++ *
++ * This deals with the recovery of a half-completed journal commit. UBIFS is
++ * careful never to overwrite the last version of the index or the LPT. Because
++ * the index and LPT are wandering trees, data from a half-completed commit will
++ * not be referenced anywhere in UBIFS. The data will be either in LEBs that are
++ * assumed to be empty and will be unmapped anyway before use, or in the index
++ * and LPT heads.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
++{
++ int err;
++
++ ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw);
++
++ dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
++ err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
++ if (err)
++ return err;
++
++ dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs);
++ err = recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf);
++ if (err)
++ return err;
++
++ return 0;
++}
++
++/**
++ * clean_an_unclean_leb - read and write a LEB to remove corruption.
++ * @c: UBIFS file-system description object
++ * @ucleb: unclean LEB information
++ * @sbuf: LEB-sized buffer to use
++ *
++ * This function reads a LEB up to a point pre-determined by the mount recovery,
++ * checks the nodes, and writes the result back to the flash, thereby cleaning
++ * off any following corruption, or non-fatal ECC errors.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++static int clean_an_unclean_leb(const struct ubifs_info *c,
++ struct ubifs_unclean_leb *ucleb, void *sbuf)
++{
++ int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
++ void *buf = sbuf;
++
++ dbg_rcvry("LEB %d len %d", lnum, len);
++
++ if (len == 0) {
++ /* Nothing to read, just unmap it */
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ return 0;
++ }
++
++ err = ubi_read(c->ubi, lnum, buf, offs, len);
++ if (err && err != -EBADMSG)
++ return err;
++
++ while (len >= 8) {
++ int ret;
++
++ cond_resched();
++
++ /* Scan quietly until there is an error */
++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
++
++ if (ret == SCANNED_A_NODE) {
++ /* A valid node, and not a padding node */
++ struct ubifs_ch *ch = buf;
++ int node_len;
++
++ node_len = ALIGN(le32_to_cpu(ch->len), 8);
++ offs += node_len;
++ buf += node_len;
++ len -= node_len;
++ continue;
++ }
++
++ if (ret > 0) {
++ /* Padding bytes or a valid padding node */
++ offs += ret;
++ buf += ret;
++ len -= ret;
++ continue;
++ }
++
++ if (ret == SCANNED_EMPTY_SPACE) {
++ ubifs_err("unexpected empty space at %d:%d",
++ lnum, offs);
++ return -EUCLEAN;
++ }
++
++ if (quiet) {
++ /* Redo the last scan but noisily */
++ quiet = 0;
++ continue;
++ }
++
++ ubifs_scanned_corruption(c, lnum, offs, buf);
++ return -EUCLEAN;
++ }
++
++ /* Pad to min_io_size */
++ len = ALIGN(ucleb->endpt, c->min_io_size);
++ if (len > ucleb->endpt) {
++ int pad_len = len - ALIGN(ucleb->endpt, 8);
++
++ if (pad_len > 0) {
++ buf = c->sbuf + len - pad_len;
++ ubifs_pad(c, buf, pad_len);
++ }
++ }
++
++ /* Write back the LEB atomically */
++ err = ubi_leb_change(c->ubi, lnum, sbuf, len, UBI_UNKNOWN);
++ if (err)
++ return err;
++
++ dbg_rcvry("cleaned LEB %d", lnum);
++
++ return 0;
++}
++
++/**
++ * ubifs_clean_lebs - clean LEBs recovered during read-only mount.
++ * @c: UBIFS file-system description object
++ * @sbuf: LEB-sized buffer to use
++ *
++ * This function cleans a LEB identified during recovery that needs to be
++ * written but was not because UBIFS was mounted read-only. This happens when
++ * remounting to read-write mode.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf)
++{
++ dbg_rcvry("recovery");
++ while (!list_empty(&c->unclean_leb_list)) {
++ struct ubifs_unclean_leb *ucleb;
++ int err;
++
++ ucleb = list_entry(c->unclean_leb_list.next,
++ struct ubifs_unclean_leb, list);
++ err = clean_an_unclean_leb(c, ucleb, sbuf);
++ if (err)
++ return err;
++ list_del(&ucleb->list);
++ kfree(ucleb);
++ }
++ return 0;
++}
++
++/**
++ * ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit.
++ * @c: UBIFS file-system description object
++ *
++ * Out-of-place garbage collection requires always one empty LEB with which to
++ * start garbage collection. The LEB number is recorded in c->gc_lnum and is
++ * written to the master node on unmounting. In the case of an unclean unmount
++ * the value of gc_lnum recorded in the master node is out of date and cannot
++ * be used. Instead, recovery must allocate an empty LEB for this purpose.
++ * However, there may not be enough empty space, in which case it must be
++ * possible to GC the dirtiest LEB into the GC head LEB.
++ *
++ * This function also runs the commit which causes the TNC updates from
++ * size-recovery and orphans to be written to the flash. That is important to
++ * ensure correct replay order for subsequent mounts.
++ *
++ * This function returns %0 on success and a negative error code on failure.
++ */
++int ubifs_rcvry_gc_commit(struct ubifs_info *c)
++{
++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
++ struct ubifs_lprops lp;
++ int lnum, err;
++
++ c->gc_lnum = -1;
++ if (wbuf->lnum == -1) {
++ dbg_rcvry("no GC head LEB");
++ goto find_free;
++ }
++ /*
++ * See whether the used space in the dirtiest LEB fits in the GC head
++ * LEB.
++ */
++ if (wbuf->offs == c->leb_size) {
++ dbg_rcvry("no room in GC head LEB");
++ goto find_free;
++ }
++ err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2);
++ if (err) {
++ if (err == -ENOSPC)
++ dbg_err("could not find a dirty LEB");
++ return err;
++ }
++ ubifs_assert(!(lp.flags & LPROPS_INDEX));
++ lnum = lp.lnum;
++ if (lp.free + lp.dirty == c->leb_size) {
++ /* An empty LEB was returned */
++ if (lp.free != c->leb_size) {
++ err = ubifs_change_one_lp(c, lnum, c->leb_size,
++ 0, 0, 0, 0);
++ if (err)
++ return err;
++ }
++ err = ubifs_leb_unmap(c, lnum);
++ if (err)
++ return err;
++ c->gc_lnum = lnum;
++ dbg_rcvry("allocated LEB %d for GC", lnum);
++ /* Run the commit */
++ dbg_rcvry("committing");
++ return ubifs_run_commit(c);
++ }
++ /*
++ * There was no empty LEB so the used space in the dirtiest LEB must fit
++ * in the GC head LEB.
++ */
++ if (lp.free + lp.dirty < wbuf->offs) {
++ dbg_rcvry("LEB %d doesn't fit in GC head LEB %d:%d",
++ lnum, wbuf->lnum, wbuf->offs);
++ err = ubifs_return_leb(c, lnum);
++ if (err)
++ return err;
++ goto find_free;
++ }
++ /*
++ * We run the commit before garbage collection otherwise subsequent
++ * mounts will see the GC and orphan deletion in a different order.
++ */
++ dbg_rcvry("committing");
++ err = ubifs_run_commit(c);
++ if (err)
++ return err;
++ /*
++ * The data in the dirtiest LEB fits in the GC head LEB, so do the GC
++ * - use locking to keep 'ubifs_assert()' happy.
++ */
++ dbg_rcvry("GC'ing LEB %d", lnum);
++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
++ err = ubifs_garbage_collect_leb(c, &lp);
++ if (err >= 0) {
++ int err2 = ubifs_wbuf_sync_nolock(wbuf);
++
++ if (err2)
++ err = err2;
++ }
++ mutex_unlock(&wbuf->io_mutex);
++ if (err < 0) {
++ dbg_err("GC failed, error %d", err);
++ if (err == -EAGAIN)
++ err = -EINVAL;
++ return err;
++ }
++ if (err != LEB_RETAINED) {
++ dbg_err("GC returned %d", err);
++ return -EINVAL;
++ }
++ err = ubifs_leb_unmap(c, c->gc_lnum);
++ if (err)
++ return err;
++ dbg_rcvry("allocated LEB %d for GC", lnum);
++ return 0;
++
++find_free:
++ /*
++ * There is no GC head LEB or the free space in the GC head LEB is too
++ * small. Allocate gc_lnum by calling 'ubifs_find_free_leb_for_idx()' so
++ * GC is not run.
++ */
++ lnum = ubifs_find_free_leb_for_idx(c);
++ if (lnum < 0) {
++ dbg_err("could not find an empty LEB");
++ return lnum;
++ }
++ /* And reset the index flag */
++ err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
++ LPROPS_INDEX, 0);
++ if (err)
++ return err;
++ c->gc_lnum = lnum;
++ dbg_rcvry("allocated LEB %d for GC", lnum);
++ /* Run the commit */
++ dbg_rcvry("committing");
++ return ubifs_run_commit(c);
++}
++
++/**
++ * struct size_entry - inode size information for recovery.
++ * @rb: link in the RB-tree of sizes
++ * @inum: inode number
++ * @i_size: size on inode
++ * @d_size: maximum size based on data nodes
++ * @exists: indicates whether the inode exists
++ * @inode: inode if pinned in memory awaiting rw mode to fix it
++ */
++struct size_entry {
++ struct rb_node rb;
++ ino_t inum;
++ loff_t i_size;
++ loff_t d_size;
++ int exists;
++ struct inode *inode;
++};
++
++/**
++ * add_ino - add an entry to the size tree.
++ * @c: UBIFS file-system description object
++ * @inum: inode number
++ * @i_size: size on inode
++ * @d_size: maximum size based on data nodes
++ * @exists: indicates whether the inode exists
++ */
++static int add_ino(struct ubifs_info *c, ino_t inum, loff_t i_size,
++ loff_t d_size, int exists)
++{
++ struct rb_node **p = &c->size_tree.rb_node, *parent = NULL;
++ struct size_entry *e;
++
++ while (*p) {
++ parent = *p;
++ e = rb_entry(parent, struct size_entry, rb);
++ if (inum < e->inum)
++ p = &(*p)->rb_left;
++ else
++ p = &(*p)->rb_right;
++ }
++
++ e = kzalloc(sizeof(struct size_entry), GFP_KERNEL);
++ if (!e)
++ return -ENOMEM;
++
++ e->inum = inum;
++ e->i_size = i_size;
++ e->d_size = d_size;
++ e->exists = exists;
++
++ rb_link_node(&e->rb, parent, p);
++ rb_insert_color(&e->rb, &c->size_tree);
++
++ return 0;
++}
++
++/**
++ * find_ino - find an entry on the size tree.
++ * @c: UBIFS file-system description object
++ * @inum: inode number
++ */
++static struct size_entry *find_ino(struct ubifs_info *c, ino_t inum)
++{
++ struct rb_node *p = c->size_tree.rb_node;
++ struct size_entry *e;
++
++ while (p) {
++ e = rb_entry(p, struct size_entry, rb);
++ if (inum < e->inum)
++ p = p->rb_left;
++ else if (inum > e->inum)
++ p = p->rb_right;
++ else
++ return e;
++ }
++ return NULL;
++}
++
++/**
++ * remove_ino - remove an entry from the size tree.
++ * @c: UBIFS file-system description object
++ * @inum: inode number
++ */
++static void remove_ino(struct ubifs_info *c, ino_t inum)
++{
++ struct size_entry *e = find_ino(c, inum);
++
++ if (!e)
++ return;
++ rb_erase(&e->rb, &c->size_tree);
++ kfree(e);
++}
++
++/**
++ * ubifs_destroy_size_tree - free resources related to the size tree.
++ * @c: UBIFS file-system description object
++ */
++void ubifs_destroy_size_tree(struct ubifs_info *c)
++{
++ struct rb_node *this = c->size_tree.rb_node;
++ struct size_entry *e;
++
++ while (this) {
++ if (this->rb_left) {
++ this = this->rb_left;
++ continue;
++ } else if (this->rb_right) {
++ this = this->rb_right;
++ continue;
++ }
++ e = rb_entry(this, struct size_entry, rb);
++ if (e->inode)
++ iput(e->inode);
++ this = rb_parent(this);
++ if (this) {
++ if (this->rb_left == &e->rb)
++ this->rb_left = NULL;
++ else
++ this->rb_right = NULL;
++ }
++ kfree(e);
++ }
++ c->size_tree = RB_ROOT;
++}
++
++/**
++ * ubifs_recover_size_accum - accumulate inode sizes for recovery.
++ * @c: UBIFS file-system description object
++ * @key: node key
++ * @deletion: node is for a deletion
++ * @new_size: inode size
++ *
++ * This function has two purposes:
++ * 1) to ensure there are no data nodes that fall outside the inode size
++ * 2) to ensure there are no data nodes for inodes that do not exist
++ * To accomplish those purposes, a rb-tree is constructed containing an entry
++ * for each inode number in the journal that has not been deleted, and recording
++ * the size from the inode node, the maximum size of any data node (also altered
++ * by truncations) and a flag indicating a inode number for which no inode node
++ * was present in the journal.
++ *
++ * Note that there is still the possibility that there are data nodes that have
++ * been committed that are beyond the inode size, however the only way to find
++ * them would be to scan the entire index. Alternatively, some provision could
++ * be made to record the size of inodes at the start of commit, which would seem
++ * very cumbersome for a scenario that is quite unlikely and the only negative
++ * consequence of which is wasted space.
++ *
++ * This functions returns %0 on success and a negative error code on failure.
++ */
++int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
++ int deletion, loff_t new_size)
++{
++ ino_t inum = key_inum(c, key);
++ struct size_entry *e;
++ int err;
++
++ switch (key_type(c, key)) {
++ case UBIFS_INO_KEY:
++ if (deletion)
++ remove_ino(c, inum);
++ else {
++ e = find_ino(c, inum);
++ if (e) {
++ e->i_size = new_size;
++ e->exists = 1;
++ } else {
++ err = add_ino(c, inum, new_size, 0, 1);
++ if (err)
++ return err;
++ }
++ }
++ break;
++ case UBIFS_DATA_KEY:
++ e = find_ino(c, inum);
++ if (e) {
++ if (new_size > e->d_size)
++ e->d_size = new_size;
++ } else {
++ err = add_ino(c, inum, 0, new_size, 0);
++ if (err)
++ return err;
++ }
++ break;
++ case UBIFS_TRUN_KEY:
++ e = find_ino(c, inum);
++ if (e)
++ e->d_size = new_size;
++ break;
++ }
++ return 0;
++}
++
++/**
++ * fix_size_in_place - fix inode size in place on flash.
++ * @c: UBIFS file-system description object
++ * @e: inode size information for recovery
++ */
++static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
++{
++ struct ubifs_ino_node *ino = c->sbuf;
++ unsigned char *p;
++ union ubifs_key key;
++ int err, lnum, offs, len;
++ loff_t i_size;
++ uint32_t crc;
++
++ /* Locate the inode node LEB number and offset */
++ ino_key_init(c, &key, e->inum);
++ err = ubifs_tnc_locate(c, &key, ino, &lnum, &offs);
++ if (err)
++ goto out;
++ /*
++ * If the size recorded on the inode node is greater than the size that
++ * was calculated from nodes in the journal then don't change the inode.
++ */
++ i_size = le64_to_cpu(ino->size);
++ if (i_size >= e->d_size)
++ return 0;
++ /* Read the LEB */
++ err = ubi_read(c->ubi, lnum, c->sbuf, 0, c->leb_size);
++ if (err)
++ goto out;
++ /* Change the size field and recalculate the CRC */
++ ino = c->sbuf + offs;
++ ino->size = cpu_to_le64(e->d_size);
++ len = le32_to_cpu(ino->ch.len);
++ crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8);
++ ino->ch.crc = cpu_to_le32(crc);
++ /* Work out where data in the LEB ends and free space begins */
++ p = c->sbuf;
++ len = c->leb_size - 1;
++ while (p[len] == 0xff)
++ len -= 1;
++ len = ALIGN(len + 1, c->min_io_size);
++ /* Atomically write the fixed LEB back again */
++ err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
++ if (err)
++ goto out;
++ dbg_rcvry("inode %lu at %d:%d size %lld -> %lld ", e->inum, lnum, offs,
++ i_size, e->d_size);
++ return 0;
++
++out:
++ ubifs_warn("inode %lu failed to fix size %lld -> %lld error %d",
++ e->inum, e->i_size, e->d_size, err);
++ return err;
++}
++
++/**
++ * ubifs_recover_size - recover inode size.
++ * @c: UBIFS file-system description object
++ *
++ * This function attempts to fix inode size discrepancies identified by the
++ * 'ubifs_recover_size_accum()' function.
++ *
++ * This functions returns %0 on success and a negative error code on failure.
++ */
++int ubifs_recover_size(struct ubifs_info *c)
++{
++ struct rb_node *this = rb_first(&c->size_tree);
++
++ while (this) {
++ struct size_entry *e;
++ int err;
++
++ e = rb_entry(this, struct size_entry, rb);
++ if (!e->exists) {
++ union ubifs_key key;
++
++ ino_key_init(c, &key, e->inum);
++ err = ubifs_tnc_lookup(c, &key, c->sbuf);
++ if (err && err != -ENOENT)
++ return err;
++ if (err == -ENOENT) {
++ /* Remove data nodes that have no inode */
++ dbg_rcvry("removing ino %lu", e->inum);
++ err = ubifs_tnc_remove_ino(c, e->inum);
++ if (err)
++ return err;
++ } else {
++ struct ubifs_ino_node *ino = c->sbuf;
++
++ e->exists = 1;
++ e->i_size = le64_to_cpu(ino->size);
++ }
++ }
++ if (e->exists && e->i_size < e->d_size) {
++ if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) {
++ /* Fix the inode size and pin it in memory */
++ struct inode *inode;
++
++ inode = ubifs_iget(c->vfs_sb, e->inum);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++ if (inode->i_size < e->d_size) {
++ dbg_rcvry("ino %lu size %lld -> %lld",
++ e->inum, e->d_size,
++ inode->i_size);
++ inode->i_size = e->d_size;
++ e->inode = inode;
++ this = rb_next(this);
++ continue;
++ }
++ iput(inode);
++ } else {
++ /* Fix the size in place */
++ err = fix_size_in_place(c, e);
++ if (err) {
++ if (e->inode)
++ /*
++ * We have changed the inode
++ * size in memory but failed to
++ * fix it on flash. Mark it
++ * dirty without budgeting, and
++ * hope we don't run out of
++ * space.
++ */
++ mark_inode_dirty_sync(e->inode);
++ /*
++ * We consider that failing to recover
++ * the size is not fatal, because it
++ * only affects files that were being
++ * written without synchronization and
++ * the only down side is that some space
++ * may be wasted.
++ */
++ err = 0;
++ }
++ if (e->inode)
++ iput(e->inode);
++ }
++ }
++ this = rb_next(this);
++ rb_erase(&e->rb, &c->size_tree);
++ kfree(e);
++ }
++ return 0;
++}
+diff --exclude=.git -urN linux-2.6.25.6/fs/ubifs/replay.c avr32-2.6/fs/ubifs/replay.c
+--- linux-2.6.25.6/fs/ubifs/replay.c 1970-01-01 01:00:00.000000000 +0100
++++ avr32-2.6/fs/ubifs/replay.c 2008-06-12 15:09:45.515816461 +0200
+@@ -0,0 +1,1075 @@