diff -urN mtd.orig/drivers/mtd/mtdchar.c mtd/drivers/mtd/mtdchar.c --- mtd.orig/drivers/mtd/mtdchar.c Tue Jul 16 20:28:45 2002 +++ mtd/drivers/mtd/mtdchar.c Tue Aug 20 15:29:49 2002 @@ -442,6 +442,15 @@ break; } + case MEMREVALIDATE: + { + if (revalidate_mtd_device(mtd)) + return -EINVAL; + + ret = 0; + break; + } + default: DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO); diff -urN mtd.orig/drivers/mtd/mtdcore.c mtd/drivers/mtd/mtdcore.c --- mtd.orig/drivers/mtd/mtdcore.c Thu Mar 7 21:38:10 2002 +++ mtd/drivers/mtd/mtdcore.c Tue Aug 20 13:41:29 2002 @@ -105,6 +105,41 @@ } /** + * revalidate_mtd_device - revalidate an MTD device + * @mtd: pointer to MTD device info structure + * + * Notify each currently active MTD 'user' of device is changed. Returns + * zero on success or 1 on failure, which currently will only happen + * if the requested device does not appear to be present in the list. + */ + +int revalidate_mtd_device (struct mtd_info *mtd) +{ + struct mtd_notifier *not=mtd_notifiers; + int i; + + down(&mtd_table_mutex); + + for (i=0; i < MAX_MTD_DEVICES; i++) + { + if (mtd_table[i] == mtd) + { + while (not) + { + if (not->revalidate) + (*(not->revalidate))(mtd); + not = not->next; + } + up (&mtd_table_mutex); + return 0; + } + } + + up(&mtd_table_mutex); + return 1; +} + +/** * register_mtd_user - register a 'user' of MTD devices. * @new: pointer to notifier info structure * diff -urN mtd.orig/drivers/mtd/nftlcore.c mtd/drivers/mtd/nftlcore.c --- mtd.orig/drivers/mtd/nftlcore.c Wed Mar 6 17:38:17 2002 +++ mtd/drivers/mtd/nftlcore.c Tue Aug 20 15:32:19 2002 @@ -87,33 +87,33 @@ struct NFTLrecord *NFTLs[MAX_NFTLS]; -static void NFTL_setup(struct mtd_info *mtd) +static void NFTL_setup(struct mtd_info *mtd, int firstfree, struct NFTLrecord *nftl) { int i; - struct NFTLrecord *nftl; unsigned long temp; - int firstfree = -1; DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n"); - for (i = 0; i < MAX_NFTLS; i++) { - if (!NFTLs[i] && firstfree == -1) - firstfree = i; - else if (NFTLs[i] && NFTLs[i]->mtd == mtd) { - /* This is a Spare Media Header for an NFTL we've already found */ - DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); + if (nftl == NULL) { + for (i = 0; i < MAX_NFTLS; i++) { + if (!NFTLs[i] && firstfree == -1) + firstfree = i; + else if (NFTLs[i] && NFTLs[i]->mtd == mtd) { + /* This is a Spare Media Header for an NFTL we've already found */ + DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); + return; + } + } + if (firstfree == -1) { + printk(KERN_WARNING "No more NFTL slot available\n"); return; } - } - if (firstfree == -1) { - printk(KERN_WARNING "No more NFTL slot available\n"); - return; - } - nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); - if (!nftl) { - printk(KERN_WARNING "Out of memory for NFTL data structures\n"); - return; + nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); + if (!nftl) { + printk(KERN_WARNING "Out of memory for NFTL data structures\n"); + return; + } } init_MUTEX(&nftl->mutex); @@ -175,7 +175,7 @@ #endif } -static void NFTL_unsetup(int i) +static void NFTL_unsetup(int i, int keep) { struct NFTLrecord *nftl = NFTLs[i]; @@ -189,7 +189,18 @@ kfree(nftl->EUNtable); nftl_gendisk.nr_real--; - kfree(nftl); + if (!keep) kfree(nftl); +} + +static void NFTL_resetup(int i) +{ + struct NFTLrecord *nftl = NFTLs[i]; + + DEBUG(MTD_DEBUG_LEVEL1, "NFTL_resetup %d\n", i); + + NFTL_unsetup(i, 1); + + NFTL_setup(nftl->mtd, i, nftl); } /* Search the MTD device for NFTL partitions */ @@ -207,7 +218,7 @@ DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", mtd->read, mtd->size, mtd->erasesize); - NFTL_setup(mtd); + NFTL_setup(mtd, -1, NULL); } } @@ -217,7 +228,23 @@ for (i = 0; i < MAX_NFTLS; i++) { if (NFTLs[i] && NFTLs[i]->mtd == mtd) - NFTL_unsetup(i); + NFTL_unsetup(i, 0); + } +} + +static void NFTL_notify_revalidate(struct mtd_info *mtd) +{ + int i; + + for (i = 0; i < MAX_NFTLS; i++) { + if (NFTLs[i] && NFTLs[i]->mtd == mtd) { + if (NFTLs[i]->usecount) { + printk(KERN_WARNING "Could not revalidate NFTL device\n"); + continue; + } + + NFTL_resetup(i); + } } } @@ -1048,8 +1075,9 @@ ****************************************************************************/ static struct mtd_notifier nftl_notifier = { - add: NFTL_notify_add, - remove: NFTL_notify_remove + add: NFTL_notify_add, + remove: NFTL_notify_remove, + revalidate: NFTL_notify_revalidate }; extern char nftlmountrev[]; diff -urN mtd.orig/include/linux/mtd/mtd.h mtd/include/linux/mtd/mtd.h --- mtd.orig/include/linux/mtd/mtd.h Tue Nov 27 17:55:12 2001 +++ mtd/include/linux/mtd/mtd.h Tue Aug 20 15:30:25 2002 @@ -93,6 +93,7 @@ #define MEMUNLOCK _IOW('M', 6, struct erase_info_user) #define MEMGETREGIONCOUNT _IOR('M', 7, int) #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) +#define MEMREVALIDATE _IO('M', 9) #ifndef __KERNEL__ @@ -219,6 +220,7 @@ extern int add_mtd_device(struct mtd_info *mtd); extern int del_mtd_device (struct mtd_info *mtd); +extern int revalidate_mtd_device(struct mtd_info *mtd); extern struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num); @@ -244,6 +246,7 @@ struct mtd_notifier { void (*add)(struct mtd_info *mtd); void (*remove)(struct mtd_info *mtd); + void (*revalidate)(struct mtd_info *mtd); struct mtd_notifier *next; }; diff -urN mtd.orig/util/nftl_format.c mtd/util/nftl_format.c --- mtd.orig/util/nftl_format.c Wed May 1 14:59:04 2002 +++ mtd/util/nftl_format.c Tue Aug 20 15:08:30 2002 @@ -333,5 +333,13 @@ printf("MEMWRITEOOB at %lx: %s\n", (unsigned long)oob.start, sys_errlist[errno]); } + /* Phase 4. Revalidating the device */ + printf("Phase 4. Revalidating the device\n"); + if (ioctl(fd, MEMREVALIDATE, 0)) { + perror("ioctl(MEMREVALIDATE)"); + close(fd); + return 1; + } + exit(0); }