065-rootfs_split.patch 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3/drivers/mtd/devices/block2mtd.c
  2. --- linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c 2009-03-09 05:13:51.000000000 +0100
  3. +++ linux-2.6.29-rc3/drivers/mtd/devices/block2mtd.c 2009-03-09 18:18:49.000000000 +0100
  4. @@ -28,6 +28,8 @@
  5. struct block_device *blkdev;
  6. struct mtd_info mtd;
  7. struct mutex write_mutex;
  8. + rwlock_t bdev_mutex;
  9. + char devname[0];
  10. };
  11. @@ -80,6 +82,12 @@
  12. size_t len = instr->len;
  13. int err;
  14. + read_lock(&dev->bdev_mutex);
  15. + if (!dev->blkdev) {
  16. + err = -EINVAL;
  17. + goto done;
  18. + }
  19. +
  20. instr->state = MTD_ERASING;
  21. mutex_lock(&dev->write_mutex);
  22. err = _block2mtd_erase(dev, from, len);
  23. @@ -92,6 +100,10 @@
  24. instr->state = MTD_ERASE_DONE;
  25. mtd_erase_callback(instr);
  26. +
  27. +done:
  28. + read_unlock(&dev->bdev_mutex);
  29. +
  30. return err;
  31. }
  32. @@ -103,10 +115,14 @@
  33. struct page *page;
  34. int index = from >> PAGE_SHIFT;
  35. int offset = from & (PAGE_SIZE-1);
  36. - int cpylen;
  37. + int cpylen, err = 0;
  38. +
  39. + read_lock(&dev->bdev_mutex);
  40. + if (!dev->blkdev || (from > mtd->size)) {
  41. + err = -EINVAL;
  42. + goto done;
  43. + }
  44. - if (from > mtd->size)
  45. - return -EINVAL;
  46. if (from + len > mtd->size)
  47. len = mtd->size - from;
  48. @@ -121,10 +137,14 @@
  49. len = len - cpylen;
  50. page = page_read(dev->blkdev->bd_inode->i_mapping, index);
  51. - if (!page)
  52. - return -ENOMEM;
  53. - if (IS_ERR(page))
  54. - return PTR_ERR(page);
  55. + if (!page) {
  56. + err = -ENOMEM;
  57. + goto done;
  58. + }
  59. + if (IS_ERR(page)) {
  60. + err = PTR_ERR(page);
  61. + goto done;
  62. + }
  63. memcpy(buf, page_address(page) + offset, cpylen);
  64. page_cache_release(page);
  65. @@ -135,7 +155,10 @@
  66. offset = 0;
  67. index++;
  68. }
  69. - return 0;
  70. +
  71. +done:
  72. + read_unlock(&dev->bdev_mutex);
  73. + return err;
  74. }
  75. @@ -187,12 +210,22 @@
  76. size_t *retlen, const u_char *buf)
  77. {
  78. struct block2mtd_dev *dev = mtd->priv;
  79. - int err;
  80. + int err = 0;
  81. +
  82. + read_lock(&dev->bdev_mutex);
  83. + if (!dev->blkdev) {
  84. + err = -EINVAL;
  85. + goto done;
  86. + }
  87. if (!len)
  88. - return 0;
  89. - if (to >= mtd->size)
  90. - return -ENOSPC;
  91. + goto done;
  92. +
  93. + if (to >= mtd->size) {
  94. + err = -ENOSPC;
  95. + goto done;
  96. + }
  97. +
  98. if (to + len > mtd->size)
  99. len = mtd->size - to;
  100. @@ -201,6 +234,9 @@
  101. mutex_unlock(&dev->write_mutex);
  102. if (err > 0)
  103. err = 0;
  104. +
  105. +done:
  106. + read_unlock(&dev->bdev_mutex);
  107. return err;
  108. }
  109. @@ -209,30 +245,15 @@
  110. static void block2mtd_sync(struct mtd_info *mtd)
  111. {
  112. struct block2mtd_dev *dev = mtd->priv;
  113. - sync_blockdev(dev->blkdev);
  114. - return;
  115. -}
  116. -
  117. + read_lock(&dev->bdev_mutex);
  118. + if (dev->blkdev)
  119. + sync_blockdev(dev->blkdev);
  120. + read_unlock(&dev->bdev_mutex);
  121. -static void block2mtd_free_device(struct block2mtd_dev *dev)
  122. -{
  123. - if (!dev)
  124. - return;
  125. -
  126. - kfree(dev->mtd.name);
  127. -
  128. - if (dev->blkdev) {
  129. - invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
  130. - 0, -1);
  131. - close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
  132. - }
  133. -
  134. - kfree(dev);
  135. + return;
  136. }
  137. -
  138. -/* FIXME: ensure that mtd->size % erase_size == 0 */
  139. -static struct block2mtd_dev *add_device(char *devname, int erase_size)
  140. +static int _open_bdev(struct block2mtd_dev *dev)
  141. {
  142. struct block_device *bdev;
  143. struct block2mtd_dev *dev;
  144. @@ -246,14 +267,14 @@
  145. return NULL;
  146. /* Get a handle on the device */
  147. - bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
  148. + bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL);
  149. #ifndef MODULE
  150. if (IS_ERR(bdev)) {
  151. /* We might not have rootfs mounted at this point. Try
  152. to resolve the device name by other means. */
  153. - dev_t devt = name_to_dev_t(devname);
  154. + dev_t devt = name_to_dev_t(dev->devname);
  155. if (devt) {
  156. bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
  157. }
  158. @@ -261,17 +282,97 @@
  159. #endif
  160. if (IS_ERR(bdev)) {
  161. - ERROR("error: cannot open device %s", devname);
  162. - goto devinit_err;
  163. + ERROR("error: cannot open device %s", dev->devname);
  164. + return 1;
  165. }
  166. dev->blkdev = bdev;
  167. if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
  168. ERROR("attempting to use an MTD device as a block device");
  169. - goto devinit_err;
  170. + return 1;
  171. }
  172. + return 0;
  173. +}
  174. +
  175. +static void _close_bdev(struct block2mtd_dev *dev)
  176. +{
  177. + struct block_device *bdev;
  178. +
  179. + if (!dev->blkdev)
  180. + return;
  181. +
  182. + bdev = dev->blkdev;
  183. + invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
  184. + close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
  185. + dev->blkdev = NULL;
  186. +}
  187. +
  188. +static void block2mtd_free_device(struct block2mtd_dev *dev)
  189. +{
  190. + if (!dev)
  191. + return;
  192. +
  193. + kfree(dev->mtd.name);
  194. + _close_bdev(dev);
  195. + kfree(dev);
  196. +}
  197. +
  198. +
  199. +static int block2mtd_refresh(struct mtd_info *mtd)
  200. +{
  201. + struct block2mtd_dev *dev = mtd->priv;
  202. + struct block_device *bdev;
  203. + dev_t devt;
  204. + int err = 0;
  205. +
  206. + /* no other mtd function can run at this point */
  207. + write_lock(&dev->bdev_mutex);
  208. +
  209. + /* get the device number for the whole disk */
  210. + devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
  211. +
  212. + /* close the old block device */
  213. + _close_bdev(dev);
  214. +
  215. + /* open the whole disk, issue a partition rescan, then */
  216. + bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
  217. + if (!bdev || !bdev->bd_disk)
  218. + err = -EINVAL;
  219. + else {
  220. + err = rescan_partitions(bdev->bd_disk, bdev);
  221. + }
  222. + if (bdev)
  223. + close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
  224. +
  225. + /* try to open the partition block device again */
  226. + _open_bdev(dev);
  227. + write_unlock(&dev->bdev_mutex);
  228. +
  229. + return err;
  230. +}
  231. +
  232. +/* FIXME: ensure that mtd->size % erase_size == 0 */
  233. +static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
  234. +{
  235. + struct block2mtd_dev *dev;
  236. + struct mtd_partition *part;
  237. + char *name;
  238. +
  239. + if (!devname)
  240. + return NULL;
  241. +
  242. + dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
  243. + if (!dev)
  244. + return NULL;
  245. +
  246. + strcpy(dev->devname, devname);
  247. +
  248. + if (_open_bdev(dev))
  249. + goto devinit_err;
  250. +
  251. mutex_init(&dev->write_mutex);
  252. + rwlock_init(&dev->bdev_mutex);
  253. /* Setup the MTD structure */
  254. /* make the name contain the block device in */
  255. @@ -295,6 +396,7 @@
  256. dev->mtd.read = block2mtd_read;
  257. dev->mtd.priv = dev;
  258. dev->mtd.owner = THIS_MODULE;
  259. + dev->mtd.refresh_device = block2mtd_refresh;
  260. if (add_mtd_device(&dev->mtd)) {
  261. /* Device didnt get added, so free the entry */
  262. diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/Kconfig linux-2.6.29-rc3/drivers/mtd/Kconfig
  263. --- linux-2.6.29-rc3.orig/drivers/mtd/Kconfig 2009-03-09 05:13:51.000000000 +0100
  264. +++ linux-2.6.29-rc3/drivers/mtd/Kconfig 2009-03-09 18:10:48.000000000 +0100
  265. @@ -53,6 +53,16 @@
  266. should normally be compiled as kernel modules. The modules perform
  267. various checks and verifications when loaded.
  268. +config MTD_ROOTFS_ROOT_DEV
  269. + bool "Automatically set 'rootfs' partition to be root filesystem"
  270. + depends on MTD_PARTITIONS
  271. + default y
  272. +
  273. +config MTD_ROOTFS_SPLIT
  274. + bool "Automatically split 'rootfs' partition for squashfs"
  275. + depends on MTD_PARTITIONS
  276. + default y
  277. +
  278. config MTD_REDBOOT_PARTS
  279. tristate "RedBoot partition table parsing"
  280. depends on MTD_PARTITIONS
  281. diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/mtdchar.c linux-2.6.29-rc3/drivers/mtd/mtdchar.c
  282. --- linux-2.6.29-rc3.orig/drivers/mtd/mtdchar.c 2009-03-09 05:13:51.000000000 +0100
  283. +++ linux-2.6.29-rc3/drivers/mtd/mtdchar.c 2009-03-09 18:10:48.000000000 +0100
  284. @@ -16,6 +16,7 @@
  285. #include <linux/mtd/mtd.h>
  286. #include <linux/mtd/compatmac.h>
  287. +#include <linux/mtd/partitions.h>
  288. #include <asm/uaccess.h>
  289. @@ -773,6 +774,13 @@
  290. file->f_pos = 0;
  291. break;
  292. }
  293. +#ifdef CONFIG_MTD_PARTITIONS
  294. + case MTDREFRESH:
  295. + {
  296. + ret = refresh_mtd_partitions(mtd);
  297. + break;
  298. + }
  299. +#endif
  300. default:
  301. ret = -ENOTTY;
  302. diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/mtdpart.c linux-2.6.29-rc3/drivers/mtd/mtdpart.c
  303. --- linux-2.6.29-rc3.orig/drivers/mtd/mtdpart.c 2009-03-09 05:13:51.000000000 +0100
  304. +++ linux-2.6.29-rc3/drivers/mtd/mtdpart.c 2009-03-09 18:29:58.000000000 +0100
  305. @@ -18,6 +18,8 @@
  306. #include <linux/mtd/mtd.h>
  307. #include <linux/mtd/partitions.h>
  308. #include <linux/mtd/compatmac.h>
  309. +#include <linux/squashfs_fs.h>
  310. +#include <linux/root_dev.h>
  311. /* Our partition linked list */
  312. static LIST_HEAD(mtd_partitions);
  313. @@ -37,7 +39,7 @@
  314. * the pointer to that structure with this macro.
  315. */
  316. #define PART(x) ((struct mtd_part *)(x))
  317. -
  318. +#define IS_PART(mtd) (mtd->read == part_read)
  319. /*
  320. * MTD methods which simply translate the effective address and pass through
  321. @@ -489,6 +491,148 @@
  322. return slave;
  323. }
  324. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  325. +#define ROOTFS_SPLIT_NAME "rootfs_data"
  326. +#define ROOTFS_REMOVED_NAME "<removed>"
  327. +static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
  328. +{
  329. + char buf[512];
  330. + struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
  331. + int len, ret;
  332. +
  333. + ret = master->read(master, offset, sizeof(*sb), &len, buf);
  334. + if (ret || (len != sizeof(*sb))) {
  335. + printk(KERN_ALERT "split_squashfs: error occured while reading "
  336. + "from \"%s\"\n", master->name);
  337. + return -EINVAL;
  338. + }
  339. +
  340. + if (*((u32 *) buf) != SQUASHFS_MAGIC) {
  341. + printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
  342. + master->name);
  343. + *split_offset = 0;
  344. + return 0;
  345. + }
  346. +
  347. + if (sb->bytes_used <= 0) {
  348. + printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
  349. + master->name);
  350. + *split_offset = 0;
  351. + return 0;
  352. + }
  353. +
  354. + len = (u32) sb->bytes_used;
  355. + len += (offset & 0x000fffff);
  356. + len += (master->erasesize - 1);
  357. + len &= ~(master->erasesize - 1);
  358. + len -= (offset & 0x000fffff);
  359. + *split_offset = offset + len;
  360. +
  361. + return 0;
  362. +}
  363. +
  364. +static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part,
  365. + int index)
  366. +{
  367. + struct mtd_partition *dpart;
  368. + struct mtd_part *slave = NULL;
  369. + int split_offset = 0;
  370. + int ret;
  371. +
  372. + ret = split_squashfs(master, part->offset, &split_offset);
  373. + if (ret)
  374. + return ret;
  375. +
  376. + if (split_offset <= 0)
  377. + return 0;
  378. +
  379. + dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
  380. + if (dpart == NULL) {
  381. + printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
  382. + ROOTFS_SPLIT_NAME);
  383. + return -ENOMEM;
  384. + }
  385. +
  386. + memcpy(dpart, part, sizeof(*part));
  387. + dpart->name = (unsigned char *)&dpart[1];
  388. + strcpy(dpart->name, ROOTFS_SPLIT_NAME);
  389. +
  390. + dpart->size -= split_offset - dpart->offset;
  391. + dpart->offset = split_offset;
  392. +
  393. + if (dpart == NULL)
  394. + return 1;
  395. +
  396. + printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%X, len=%X \n",
  397. + ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
  398. +
  399. + slave = add_one_partition(master, dpart, index, split_offset);
  400. + if (!slave) {
  401. + kfree(dpart);
  402. + return -ENOMEM;
  403. + }
  404. + rpart->split = &slave->mtd;
  405. +
  406. + return 0;
  407. +}
  408. +
  409. +static int refresh_rootfs_split(struct mtd_info *mtd)
  410. +{
  411. + struct mtd_partition tpart;
  412. + struct mtd_part *part;
  413. + char *name;
  414. + int index = 0;
  415. + int offset, size;
  416. + int ret;
  417. +
  418. + part = PART(mtd);
  419. +
  420. + /* check for the new squashfs offset first */
  421. + ret = split_squashfs(part->master, part->offset, &offset);
  422. + if (ret)
  423. + return ret;
  424. +
  425. + if ((offset > 0) && !mtd->split) {
  426. + printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
  427. + /* if we don't have a rootfs split partition, create a new one */
  428. + tpart.name = (char *) mtd->name;
  429. + tpart.size = mtd->size;
  430. + tpart.offset = part->offset;
  431. +
  432. + /* find the index of the last partition */
  433. + if (!list_empty(&mtd_partitions))
  434. + index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1;
  435. +
  436. + return split_rootfs_data(part->master, &part->mtd, &tpart, index);
  437. + } else if ((offset > 0) && mtd->split) {
  438. + /* update the offsets of the existing partition */
  439. + size = mtd->size + part->offset - offset;
  440. +
  441. + part = PART(mtd->split);
  442. + part->offset = offset;
  443. + part->mtd.size = size;
  444. + printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
  445. + __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
  446. + part->offset, part->mtd.size);
  447. + name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
  448. + strcpy(name, ROOTFS_SPLIT_NAME);
  449. + part->mtd.name = name;
  450. + } else if ((offset <= 0) && mtd->split) {
  451. + printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
  452. +
  453. + /* mark existing partition as removed */
  454. + part = PART(mtd->split);
  455. + name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
  456. + strcpy(name, ROOTFS_REMOVED_NAME);
  457. + part->mtd.name = name;
  458. + part->offset = 0;
  459. + part->mtd.size = 0;
  460. + }
  461. +
  462. + return 0;
  463. +}
  464. +#endif /* CONFIG_MTD_ROOTFS_SPLIT */
  465. +
  466. /*
  467. * This function, given a master MTD object and a partition table, creates
  468. * and registers slave MTD objects which are bound to the master according to
  469. @@ -502,14 +646,29 @@
  470. {
  471. struct mtd_part *slave;
  472. uint64_t cur_offset = 0;
  473. - int i;
  474. + int i, j, ret;
  475. printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
  476. - for (i = 0; i < nbparts; i++) {
  477. - slave = add_one_partition(master, parts + i, i, cur_offset);
  478. + for (i = 0, j = 0; i < nbparts; i++) {
  479. + slave = add_one_partition(master, parts + i, j++, cur_offset);
  480. if (!slave)
  481. return -ENOMEM;
  482. +
  483. + if (!strcmp(parts[i].name, "rootfs") && slave->registered) {
  484. +#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
  485. + if (ROOT_DEV == 0) {
  486. + printk(KERN_NOTICE "mtd: partition \"rootfs\" "
  487. + "set to be root filesystem\n");
  488. + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
  489. + }
  490. +#endif
  491. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  492. + ret = split_rootfs_data(master, &slave->mtd, &parts[i], j);
  493. + if (ret == 0)
  494. + j++;
  495. +#endif
  496. + }
  497. cur_offset = slave->offset + slave->mtd.size;
  498. }
  499. @@ -517,6 +676,32 @@
  500. }
  501. EXPORT_SYMBOL(add_mtd_partitions);
  502. +int refresh_mtd_partitions(struct mtd_info *mtd)
  503. +{
  504. + int ret = 0;
  505. +
  506. + if (IS_PART(mtd)) {
  507. + struct mtd_part *part;
  508. + struct mtd_info *master;
  509. +
  510. + part = PART(mtd);
  511. + master = part->master;
  512. + if (master->refresh_device)
  513. + ret = master->refresh_device(master);
  514. + }
  515. +
  516. + if (!ret && mtd->refresh_device)
  517. + ret = mtd->refresh_device(mtd);
  518. +
  519. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  520. + if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
  521. + refresh_rootfs_split(mtd);
  522. +#endif
  523. +
  524. + return 0;
  525. +}
  526. +EXPORT_SYMBOL_GPL(refresh_mtd_partitions);
  527. +
  528. static DEFINE_SPINLOCK(part_parser_lock);
  529. static LIST_HEAD(part_parsers);
  530. diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/mtd.h linux-2.6.29-rc3/include/linux/mtd/mtd.h
  531. --- linux-2.6.29-rc3.orig/include/linux/mtd/mtd.h 2009-03-09 05:13:58.000000000 +0100
  532. +++ linux-2.6.29-rc3/include/linux/mtd/mtd.h 2009-03-09 18:10:48.000000000 +0100
  533. @@ -100,6 +100,7 @@
  534. uint8_t *oobbuf;
  535. };
  536. +struct mtd_info;
  537. struct mtd_info {
  538. u_char type;
  539. uint32_t flags;
  540. @@ -225,6 +226,9 @@
  541. struct module *owner;
  542. int usecount;
  543. + int (*refresh_device)(struct mtd_info *mtd);
  544. + struct mtd_info *split;
  545. +
  546. /* If the driver is something smart, like UBI, it may need to maintain
  547. * its own reference counting. The below functions are only for driver.
  548. * The driver may register its callbacks. These callbacks are not
  549. diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/partitions.h linux-2.6.29-rc3/include/linux/mtd/partitions.h
  550. --- linux-2.6.29-rc3.orig/include/linux/mtd/partitions.h 2009-03-09 05:13:58.000000000 +0100
  551. +++ linux-2.6.29-rc3/include/linux/mtd/partitions.h 2009-03-09 18:10:48.000000000 +0100
  552. @@ -34,6 +34,7 @@
  553. * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
  554. */
  555. +struct mtd_partition;
  556. struct mtd_partition {
  557. char *name; /* identifier string */
  558. uint64_t size; /* partition size */
  559. @@ -41,6 +42,7 @@
  560. uint32_t mask_flags; /* master MTD flags to mask out for this partition */
  561. struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
  562. struct mtd_info **mtdp; /* pointer to store the MTD object */
  563. + int (*refresh_partition)(struct mtd_info *);
  564. };
  565. #define MTDPART_OFS_NXTBLK (-2)
  566. @@ -50,6 +52,7 @@
  567. int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
  568. int del_mtd_partitions(struct mtd_info *);
  569. +int refresh_mtd_partitions(struct mtd_info *);
  570. /*
  571. * Functions dealing with the various ways of partitioning the space
  572. diff -ruN linux-2.6.29-rc3.orig/include/mtd/mtd-abi.h linux-2.6.29-rc3/include/mtd/mtd-abi.h
  573. --- linux-2.6.29-rc3.orig/include/mtd/mtd-abi.h 2009-03-09 05:13:57.000000000 +0100
  574. +++ linux-2.6.29-rc3/include/mtd/mtd-abi.h 2009-03-09 18:10:48.000000000 +0100
  575. @@ -93,6 +93,7 @@
  576. #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout)
  577. #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
  578. #define MTDFILEMODE _IO('M', 19)
  579. +#define MTDREFRESH _IO('M', 23)
  580. /*
  581. * Obsolete legacy interface. Keep it in order not to break userspace