]> git.hungrycats.org Git - linux/commitdiff
Fix use-after-free bug in MTD partitioning code.
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>
Tue, 10 Aug 2004 16:25:01 +0000 (17:25 +0100)
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>
Tue, 10 Aug 2004 16:25:01 +0000 (17:25 +0100)
Define callback wrapper function mtd_erase_callback() to handle
partition offsets during the callback, rather than attempting to
fix them up in the freed erase_info structure after the callback
has already happened.

22 files changed:
drivers/mtd/Kconfig
drivers/mtd/Makefile
drivers/mtd/chips/amd_flash.c
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/chips/jedec.c
drivers/mtd/chips/map_ram.c
drivers/mtd/chips/sharp.c
drivers/mtd/devices/blkmtd.c
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/mtdram.c
drivers/mtd/devices/phram.c
drivers/mtd/devices/pmc551.c
drivers/mtd/devices/slram.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/nand_base.c
include/linux/mtd/mtd.h

index 2839166ac76e5b39ea675682c80d9f63ffe420cd..f0aaaa225fb58eb02ca7cda6c4c49d149fad66eb 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Kconfig,v 1.5 2004/06/04 15:59:32 gleixner Exp $
+# $Id: Kconfig,v 1.6 2004/08/09 13:19:42 dwmw2 Exp $
 
 menu "Memory Technology Devices (MTD)"
 
@@ -28,7 +28,7 @@ config MTD_DEBUG_VERBOSE
          Determines the verbosity level of the MTD debugging messages.
 
 config MTD_PARTITIONS
-       tristate "MTD partitioning support"
+       bool "MTD partitioning support"
        depends on MTD
        help
          If you have a device which needs to divide its flash chip(s) up
index 85239c969b9ed6fff5efb48ee1c4129d2db84ffe..9316119a0e9e9c2aee7a348bbca536e1633c08d1 100644 (file)
@@ -1,10 +1,13 @@
 #
 # Makefile for the memory technology device drivers.
 #
-# $Id: Makefile.common,v 1.3 2004/07/12 16:07:30 dwmw2 Exp $
+# $Id: Makefile.common,v 1.4 2004/08/09 13:19:42 dwmw2 Exp $
 
 # Core functionality.
-obj-$(CONFIG_MTD)              += mtdcore.o
+mtd-y                          := mtdcore.o
+mtd-$(CONFIG_MTD_PARTITIONS)   += mtdpart.o
+obj-$(CONFIG_MTD)              += $(mtd-y)
+
 obj-$(CONFIG_MTD_CONCAT)       += mtdconcat.o
 obj-$(CONFIG_MTD_PARTITIONS)   += mtdpart.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
index ca710c78c6f3f9c47b78cf294580f44c5e54104a..1c1640ebecf27c222a5899435cd7c81d268712a2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Author: Jonas Holmberg <jonas.holmberg@axis.com>
  *
- * $Id: amd_flash.c,v 1.24 2004/07/12 13:34:30 dwmw2 Exp $
+ * $Id: amd_flash.c,v 1.25 2004/08/09 13:19:43 dwmw2 Exp $
  *
  * Copyright (c) 2001 Axis Communications AB
  *
@@ -1307,9 +1307,7 @@ static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr)
        }
                
        instr->state = MTD_ERASE_DONE;
-       if (instr->callback) {
-               instr->callback(instr);
-       }
+       mtd_erase_callback(instr);
        
        return 0;
 }
index a36168e8404bf0e760b8b0ab67ca840446f265f8..e71624edb2aa75a9df4a2777382555648b6ba659 100644 (file)
@@ -4,7 +4,7 @@
  *
  * (C) 2000 Red Hat. GPL'd
  *
- * $Id: cfi_cmdset_0001.c,v 1.153 2004/07/12 21:52:20 dwmw2 Exp $
+ * $Id: cfi_cmdset_0001.c,v 1.154 2004/08/09 13:19:43 dwmw2 Exp $
  *
  * 
  * 10/10/2000  Nicolas Pitre <nico@cam.org>
@@ -1554,8 +1554,7 @@ int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
                return ret;
 
        instr->state = MTD_ERASE_DONE;
-       if (instr->callback)
-               instr->callback(instr);
+       mtd_erase_callback(instr);
        
        return 0;
 }
index 6f2b2aaf88a68b8f8069c4e56ba24792abe75522..5bd15f548f22e47f00103b14e6eb1245ca5d1b4a 100644 (file)
@@ -13,7 +13,7 @@
  *
  * This code is GPL
  *
- * $Id: cfi_cmdset_0002.c,v 1.103 2004/07/14 16:24:03 dwmw2 Exp $
+ * $Id: cfi_cmdset_0002.c,v 1.106 2004/08/09 14:02:32 dwmw2 Exp $
  *
  */
 
@@ -1420,8 +1420,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
                return ret;
 
        instr->state = MTD_ERASE_DONE;
-       if (instr->callback)
-               instr->callback(instr);
+       mtd_erase_callback(instr);
        
        return 0;
 }
@@ -1444,8 +1443,7 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
                return ret;
 
        instr->state = MTD_ERASE_DONE;
-       if (instr->callback)
-               instr->callback(instr);
+       mtd_erase_callback(instr);
        
        return 0;
 }
index 7a552263f2da3ad581034007b95b437b42e18bc5..326eaf7a2bbb99a67ebc656ed9e569029663ed8b 100644 (file)
@@ -4,7 +4,7 @@
  *
  * (C) 2000 Red Hat. GPL'd
  *
- * $Id: cfi_cmdset_0020.c,v 1.14 2004/07/20 02:44:25 dwmw2 Exp $
+ * $Id: cfi_cmdset_0020.c,v 1.15 2004/08/09 13:19:43 dwmw2 Exp $
  * 
  * 10/10/2000  Nicolas Pitre <nico@cam.org>
  *     - completely revamped method functions so they are aware and
@@ -966,8 +966,7 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
        }
                
        instr->state = MTD_ERASE_DONE;
-       if (instr->callback)
-               instr->callback(instr);
+       mtd_erase_callback(instr);
        
        return 0;
 }
index 0b6e96f7ccfa3c767b76a631d899f8c7526bc217..2dfd53ed39d2b07e6710a3868a33acef650bf794 100644 (file)
@@ -11,7 +11,7 @@
  * not going to guess how to send commands to them, plus I expect they will
  * all speak CFI..
  *
- * $Id: jedec.c,v 1.20 2004/07/12 14:03:01 dwmw2 Exp $
+ * $Id: jedec.c,v 1.21 2004/08/09 13:19:43 dwmw2 Exp $
  */
 
 #include <linux/init.h>
@@ -780,8 +780,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
                    
    //printk("done\n");
    instr->state = MTD_ERASE_DONE;
-   if (instr->callback)
-       instr->callback(instr);
+   mtd_erase_callback(instr);
    return 0;
    
    #undef flread
index db6f6c40f428d5e0631fbea6c3c839efb5bf0448..283be02dc311af6f7fedf517a074b0c1d884c941 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Common code to handle map devices which are simple RAM
  * (C) 2000 Red Hat. GPL'd.
- * $Id: map_ram.c,v 1.19 2004/07/12 21:58:44 dwmw2 Exp $
+ * $Id: map_ram.c,v 1.20 2004/08/09 13:19:43 dwmw2 Exp $
  */
 
 #include <linux/module.h>
@@ -114,8 +114,7 @@ static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr)
 
        instr->state = MTD_ERASE_DONE;
 
-       if (instr->callback)
-               instr->callback(instr);
+       mtd_erase_callback(instr);
 
        return 0;
 }
index 1313c70298a5e88314d7d72fc847ec966e20c4f3..c3cf0f63bc93639ad151a35b8867e554452548a7 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
  *           2000,2001 Lineo, Inc.
  *
- * $Id: sharp.c,v 1.13 2004/07/12 14:06:34 dwmw2 Exp $
+ * $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $
  *
  * Devices supported:
  *   LH28F016SCT Symmetrical block flash memory, 2Mx8
@@ -425,8 +425,7 @@ static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
        }
 
        instr->state = MTD_ERASE_DONE;
-       if(instr->callback)
-               instr->callback(instr);
+       mtd_erase_callback(instr);
 
        return 0;
 }
index b25e20a5a5cab7dd7a532cc7b7a462bdcabfdbcc..a3eb97a9490fd83aee336505a12b7e3745933c94 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: blkmtd-25.c,v 1.6 2004/07/15 15:09:15 dwmw2 Exp $
+ * $Id: blkmtd.c,v 1.23 2004/08/09 14:03:19 dwmw2 Exp $
  *
  * blkmtd.c - use a block device as a fake MTD
  *
@@ -39,7 +39,7 @@
 
 /* Default erase size in K, always make it a multiple of PAGE_SIZE */
 #define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10)        /* 128KiB */
-#define VERSION "$Revision: 1.6 $"
+#define VERSION "$Revision: 1.23 $"
 
 /* Info for the block device */
 struct blkmtd_dev {
@@ -435,9 +435,7 @@ static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
        }
 
        DEBUG(3, "blkmtd: erase: checking callback\n");
-       if (instr->callback) {
-               (*(instr->callback))(instr);
-       }
+       mtd_erase_callback(instr);
        DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
        return err;
 }
index 0cdec06574ea3d2e06058357a397269ddfe154c7..fefbf5eaf80514f92421e149518413281d158a22 100644 (file)
@@ -4,7 +4,7 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: doc2000.c,v 1.60 2004/04/07 08:30:04 gleixner Exp $
+ * $Id: doc2000.c,v 1.62 2004/08/09 14:04:02 dwmw2 Exp $
  */
 
 #include <linux/kernel.h>
@@ -1277,8 +1277,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
        instr->state = MTD_ERASE_DONE;
 
  callback:
-       if (instr->callback)
-               instr->callback(instr);
+       mtd_erase_callback(instr);
 
        up(&this->lock);
        return 0;
index 1128009f1ca510a297a68be5cf2cd6ff6bfe80d6..df588ac6503d2ffedb81c154e2fc8d046ffd6794 100644 (file)
@@ -4,7 +4,7 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: doc2001.c,v 1.42 2004/04/04 12:36:45 gleixner Exp $
+ * $Id: doc2001.c,v 1.44 2004/08/09 14:04:24 dwmw2 Exp $
  */
 
 #include <linux/kernel.h>
@@ -845,8 +845,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
                instr->state = MTD_ERASE_DONE;
        dummy = ReadDOC(docptr, LastDataRead);
 
-       if (instr->callback) 
-               instr->callback(instr);
+       mtd_erase_callback(instr);
 
        return 0;
 }
index da4275cb73eb18100ddcbe8575f53cec6463bb63..d30ba118f9201f73ad9e9e36369ebbf8b299e563 100644 (file)
@@ -6,7 +6,7 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: doc2001plus.c,v 1.8 2004/04/04 12:36:45 gleixner Exp $
+ * $Id: doc2001plus.c,v 1.9 2004/08/09 13:19:44 dwmw2 Exp $
  *
  * Released under GPL
  */
@@ -1111,8 +1111,7 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
        /* Disable flash internally */
        WriteDOC(0, docptr, Mplus_FlashSelect);
 
-       if (instr->callback) 
-               instr->callback(instr);
+       mtd_erase_callback(instr);
 
        return 0;
 }
index d67ca4cb206f60e23ca11badc1acc0a5b8bf2be6..dfd335e4a2a80ca6e3da1bddbd920e7e4af606ce 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
  *
- * $Id: lart.c,v 1.6 2004/07/14 17:21:38 dwmw2 Exp $
+ * $Id: lart.c,v 1.7 2004/08/09 13:19:44 dwmw2 Exp $
  *
  * Author: Abraham vd Merwe <abraham@2d3d.co.za>
  *
@@ -433,7 +433,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
         }
 
    instr->state = MTD_ERASE_DONE;
-   if (instr->callback) instr->callback (instr);
+   mtd_erase_callback(instr);
 
    return (0);
 }
index 64397ddf82c8f07f4a1b4331de19e60cecdc60c4..5fe0a08655e25b85bf2c8b898cee702c37e6be04 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * mtdram - a test mtd device
- * $Id: mtdram.c,v 1.32 2003/05/21 15:15:07 dwmw2 Exp $
+ * $Id: mtdram.c,v 1.33 2004/08/09 13:19:44 dwmw2 Exp $
  * Author: Alexander Larsson <alex@cendio.se>
  *
  * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
@@ -57,9 +57,8 @@ ram_erase(struct mtd_info *mtd, struct erase_info *instr)
   memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
        
   instr->state = MTD_ERASE_DONE;
+  mtd_erase_callback(instr);
 
-  if (instr->callback)
-    (*(instr->callback))(instr);
   return 0;
 }
 
index 5f66e9bfb10cb75a5bb5ec5404e8e9570433ed04..03a955cdf17a0249d3efb301a94bbee5cacadf08 100644 (file)
@@ -1,6 +1,6 @@
 /**
  *
- * $Id: phram.c,v 1.1 2003/08/21 17:52:30 joern Exp $
+ * $Id: phram.c,v 1.2 2004/08/09 13:19:44 dwmw2 Exp $
  *
  * Copyright (c) Jochen Schaeuble <psionic@psionic.de>
  * 07/2003     rewritten by Joern Engel <joern@wh.fh-wedel.de>
@@ -55,10 +55,7 @@ int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
 
        instr->state = MTD_ERASE_DONE;
 
-       if (instr->callback)
-               (*(instr->callback))(instr);
-       else
-               kfree(instr);
+       mtd_erase_callback(instr);
 
        return 0;
 }
index cebb2821bc4e8be1ec2bd413c96352db15b73853..c2c2a3c369b046808f37bac09acac7be86f38dc3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: pmc551.c,v 1.27 2004/07/20 02:44:26 dwmw2 Exp $
+ * $Id: pmc551.c,v 1.28 2004/08/09 13:19:44 dwmw2 Exp $
  *
  * PMC551 PCI Mezzanine Ram Device
  *
@@ -169,9 +169,7 @@ out:
        printk(KERN_DEBUG "pmc551_erase() done\n");
 #endif
 
-        if (instr->callback) {
-                (*(instr->callback))(instr);
-       }
+        mtd_erase_callback(instr);
         return 0;
 }
 
index 4dbcfcfd68fc45992dab5e8c65492bff487587a3..fd579ae45dab8489dfe2b1896406195f9b83cb8d 100644 (file)
@@ -1,6 +1,6 @@
 /*======================================================================
 
-  $Id: slram.c,v 1.30 2003/05/20 21:03:08 dwmw2 Exp $
+  $Id: slram.c,v 1.31 2004/08/09 13:19:44 dwmw2 Exp $
 
   This driver provides a method to access memory not used by the kernel
   itself (i.e. if the kernel commandline mem=xxx is used). To actually
@@ -98,12 +98,7 @@ int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
 
        instr->state = MTD_ERASE_DONE;
 
-       if (instr->callback) {
-               (*(instr->callback))(instr);
-       }
-       else {
-               kfree(instr);
-       }
+       mtd_erase_callback(instr);
 
        return(0);
 }
index 66eb3bf8974db55e3fd8f15b828d11970e294c86..3db73d8c26b8671d3ce2802bb5f4aa76289b3a94 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: mtdchar.c,v 1.62 2004/07/14 13:20:42 dwmw2 Exp $
+ * $Id: mtdchar.c,v 1.64 2004/08/09 13:59:46 dwmw2 Exp $
  *
  * Character-device access to raw MTD devices.
  *
@@ -262,7 +262,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
     IOCTL calls for getting device parameters.
 
 ======================================================================*/
-static void mtd_erase_callback (struct erase_info *instr)
+static void mtdchar_erase_callback (struct erase_info *instr)
 {
        wake_up((wait_queue_head_t *)instr->priv);
 }
@@ -336,7 +336,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                                return -EFAULT;
                        }
                        erase->mtd = mtd;
-                       erase->callback = mtd_erase_callback;
+                       erase->callback = mtdchar_erase_callback;
                        erase->priv = (unsigned long)&waitq;
                        
                        /*
@@ -511,7 +511,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
        }
 
        default:
-               DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %lx)\n", cmd, (unsigned long)MEMGETINFO);
                ret = -ENOTTY;
        }
 
index f007d0740f7379e10d6187f68fe7d4eadea07b21..810e2f55004fa735741f56641b2f6be2ba5198bb 100644 (file)
@@ -5,7 +5,7 @@
  *
  * This code is GPL
  *
- * $Id: mtdpart.c,v 1.46 2004/07/12 13:28:07 dwmw2 Exp $
+ * $Id: mtdpart.c,v 1.49 2004/08/10 13:41:27 dwmw2 Exp $
  *
  *     02-21-2002      Thomas Gleixner <gleixner@autronix.de>
  *                     added support for read_oob, write_oob
@@ -246,11 +246,22 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
                return -EINVAL;
        instr->addr += part->offset;
        ret = part->master->erase(part->master, instr);
-       if (instr->fail_addr != 0xffffffff)
-               instr->fail_addr -= part->offset;
        return ret;
 }
 
+void mtd_erase_callback(struct erase_info *instr)
+{
+       if (instr->mtd->erase == part_erase) {
+               struct mtd_part *part = PART(instr->mtd);
+
+               if (instr->fail_addr != 0xffffffff)
+                       instr->fail_addr -= part->offset;
+               instr->addr -= part->offset;
+       }
+       if (instr->callback)
+               instr->callback(instr);
+}
+
 static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
 {
        struct mtd_part *part = PART(mtd);
index 596bc8f70188bd8f063d45a34d79e9f6612d5a40..ff6adf43f73a4075076f1a2676f3da02004014b8 100644 (file)
@@ -37,7 +37,7 @@
  *     The AG-AND chips have nice features for speed improvement,
  *     which are not supported yet. Read / program 4 pages in one go.
  *
- * $Id: nand_base.c,v 1.113 2004/07/14 16:31:31 gleixner Exp $
+ * $Id: nand_base.c,v 1.115 2004/08/09 13:19:45 dwmw2 Exp $
  *
  * 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
@@ -58,7 +58,7 @@
 #include <linux/bitops.h>
 #include <asm/io.h>
 
-#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
+#ifdef CONFIG_MTD_PARTITIONS
 #include <linux/mtd/partitions.h>
 #endif
 
@@ -1284,12 +1284,12 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
        nand_release_chip(mtd);
 
        /*
-        * Return success, if no ECC failures, else -EIO
+        * Return success, if no ECC failures, else -EBADMSG
         * fs driver will take care of that, because
-        * retlen == desired len and result == -EIO
+        * retlen == desired len and result == -EBADMSG
         */
        *retlen = read;
-       return ecc_failed ? -EIO : 0;
+       return ecc_failed ? -EBADMSG : 0;
 }
 
 /**
@@ -2108,8 +2108,8 @@ erase_exit:
 
        ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
        /* Do call back function */
-       if (!ret && instr->callback)
-               instr->callback (instr);
+       if (!ret)
+               mtd_erase_callback(instr);
 
        /* Deselect and wake up anyone waiting on the device */
        nand_release_chip(mtd);
@@ -2555,11 +2555,11 @@ void nand_release (struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
 
-#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
-       /* Unregister partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+       /* Deregister partitions */
        del_mtd_partitions (mtd);
 #endif
-       /* Unregister the device */
+       /* Deregister the device */
        del_mtd_device (mtd);
 
        /* Free bad block table memory, if allocated */
index fd7b15d077b311586ab83c19588bcf5abe5406db..b3d134392b3128c5582185e468a35c909c9314df 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * $Id: mtd.h,v 1.54 2004/07/15 01:13:12 dwmw2 Exp $
+ * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
  *
  * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
  *
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/uio.h>
 
+#include <linux/mtd/compatmac.h>
 #include <mtd/mtd-abi.h>
 
 #define MTD_CHAR_MAJOR 90
@@ -192,6 +193,17 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
 #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
 #define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0) 
 
+
+#ifdef CONFIG_MTD_PARTITIONS
+void mtd_erase_callback(struct erase_info *instr);
+#else
+static inline void mtd_erase_callback(struct erase_info *instr)
+{
+       if (instr->callback)
+               instr->callback(instr);
+}
+#endif
+
 /*
  * Debugging macro and defines
  */