065-rootfs_split.patch 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. --- a/drivers/mtd/Kconfig
  2. +++ b/drivers/mtd/Kconfig
  3. @@ -47,6 +47,16 @@ config MTD_PARTITIONS
  4. devices. Partitioning on NFTL 'devices' is a different - that's the
  5. 'normal' form of partitioning used on a block device.
  6. +config MTD_ROOTFS_ROOT_DEV
  7. + bool "Automatically set 'rootfs' partition to be root filesystem"
  8. + depends on MTD_PARTITIONS
  9. + default y
  10. +
  11. +config MTD_ROOTFS_SPLIT
  12. + bool "Automatically split 'rootfs' partition for squashfs"
  13. + depends on MTD_PARTITIONS
  14. + default y
  15. +
  16. config MTD_REDBOOT_PARTS
  17. tristate "RedBoot partition table parsing"
  18. depends on MTD_PARTITIONS
  19. --- a/drivers/mtd/mtdpart.c
  20. +++ b/drivers/mtd/mtdpart.c
  21. @@ -20,6 +20,8 @@
  22. #include <linux/mtd/mtd.h>
  23. #include <linux/mtd/partitions.h>
  24. #include <linux/mtd/compatmac.h>
  25. +#include <linux/squashfs_fs.h>
  26. +#include <linux/root_dev.h>
  27. /* Our partition linked list */
  28. static LIST_HEAD(mtd_partitions);
  29. @@ -39,7 +41,7 @@ struct mtd_part {
  30. * the pointer to that structure with this macro.
  31. */
  32. #define PART(x) ((struct mtd_part *)(x))
  33. -
  34. +#define IS_PART(mtd) (mtd->read == part_read)
  35. /*
  36. * MTD methods which simply translate the effective address and pass through
  37. @@ -308,6 +310,312 @@ int del_mtd_partitions(struct mtd_info *
  38. return 0;
  39. }
  40. +static u_int32_t cur_offset = 0;
  41. +static int add_one_partition(struct mtd_info *master, const struct mtd_partition *part,
  42. + int i, struct mtd_part **slp)
  43. +{
  44. + struct mtd_part *slave;
  45. +
  46. + /* allocate the partition structure */
  47. + slave = kzalloc (sizeof(*slave), GFP_KERNEL);
  48. + if (!slave) {
  49. + printk ("memory allocation error while creating partitions for \"%s\"\n",
  50. + master->name);
  51. + del_mtd_partitions(master);
  52. + return -ENOMEM;
  53. + }
  54. + list_add(&slave->list, &mtd_partitions);
  55. +
  56. + /* set up the MTD object for this partition */
  57. + slave->mtd.type = master->type;
  58. + slave->mtd.flags = master->flags & ~part->mask_flags;
  59. + slave->mtd.size = part->size;
  60. + slave->mtd.writesize = master->writesize;
  61. + slave->mtd.oobsize = master->oobsize;
  62. + slave->mtd.oobavail = master->oobavail;
  63. + slave->mtd.subpage_sft = master->subpage_sft;
  64. +
  65. + slave->mtd.name = part->name;
  66. + slave->mtd.owner = master->owner;
  67. +
  68. + slave->mtd.read = part_read;
  69. + slave->mtd.write = part_write;
  70. + slave->mtd.refresh_device = part->refresh_partition;
  71. +
  72. + if(master->point && master->unpoint){
  73. + slave->mtd.point = part_point;
  74. + slave->mtd.unpoint = part_unpoint;
  75. + }
  76. +
  77. + if (master->read_oob)
  78. + slave->mtd.read_oob = part_read_oob;
  79. + if (master->write_oob)
  80. + slave->mtd.write_oob = part_write_oob;
  81. + if(master->read_user_prot_reg)
  82. + slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
  83. + if(master->read_fact_prot_reg)
  84. + slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
  85. + if(master->write_user_prot_reg)
  86. + slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
  87. + if(master->lock_user_prot_reg)
  88. + slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
  89. + if(master->get_user_prot_info)
  90. + slave->mtd.get_user_prot_info = part_get_user_prot_info;
  91. + if(master->get_fact_prot_info)
  92. + slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
  93. + if (master->sync)
  94. + slave->mtd.sync = part_sync;
  95. + if (!i && master->suspend && master->resume) {
  96. + slave->mtd.suspend = part_suspend;
  97. + slave->mtd.resume = part_resume;
  98. + }
  99. + if (master->writev)
  100. + slave->mtd.writev = part_writev;
  101. + if (master->lock)
  102. + slave->mtd.lock = part_lock;
  103. + if (master->unlock)
  104. + slave->mtd.unlock = part_unlock;
  105. + if (master->block_isbad)
  106. + slave->mtd.block_isbad = part_block_isbad;
  107. + if (master->block_markbad)
  108. + slave->mtd.block_markbad = part_block_markbad;
  109. + slave->mtd.erase = part_erase;
  110. + slave->master = master;
  111. + slave->offset = part->offset;
  112. + slave->index = i;
  113. +
  114. + if (slave->offset == MTDPART_OFS_APPEND)
  115. + slave->offset = cur_offset;
  116. + if (slave->offset == MTDPART_OFS_NXTBLK) {
  117. + slave->offset = cur_offset;
  118. + if ((cur_offset % master->erasesize) != 0) {
  119. + /* Round up to next erasesize */
  120. + slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
  121. + printk(KERN_NOTICE "Moving partition %d: "
  122. + "0x%08x -> 0x%08x\n", i,
  123. + cur_offset, slave->offset);
  124. + }
  125. + }
  126. + if (slave->mtd.size == MTDPART_SIZ_FULL)
  127. + slave->mtd.size = master->size - slave->offset;
  128. + cur_offset = slave->offset + slave->mtd.size;
  129. +
  130. + printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
  131. + slave->offset + slave->mtd.size, slave->mtd.name);
  132. +
  133. + /* let's do some sanity checks */
  134. + if (slave->offset >= master->size) {
  135. + /* let's register it anyway to preserve ordering */
  136. + slave->offset = 0;
  137. + slave->mtd.size = 0;
  138. + printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
  139. + part->name);
  140. + }
  141. + if (slave->offset + slave->mtd.size > master->size) {
  142. + slave->mtd.size = master->size - slave->offset;
  143. + printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
  144. + part->name, master->name, slave->mtd.size);
  145. + }
  146. + if (master->numeraseregions>1) {
  147. + /* Deal with variable erase size stuff */
  148. + int i;
  149. + struct mtd_erase_region_info *regions = master->eraseregions;
  150. +
  151. + /* Find the first erase regions which is part of this partition. */
  152. + for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
  153. + ;
  154. +
  155. + for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
  156. + if (slave->mtd.erasesize < regions[i].erasesize) {
  157. + slave->mtd.erasesize = regions[i].erasesize;
  158. + }
  159. + }
  160. + } else {
  161. + /* Single erase size */
  162. + slave->mtd.erasesize = master->erasesize;
  163. + }
  164. +
  165. + if ((slave->mtd.flags & MTD_WRITEABLE) &&
  166. + (slave->offset % slave->mtd.erasesize)) {
  167. + /* Doesn't start on a boundary of major erase size */
  168. + /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
  169. + slave->mtd.flags &= ~MTD_WRITEABLE;
  170. + printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
  171. + part->name);
  172. + }
  173. + if ((slave->mtd.flags & MTD_WRITEABLE) &&
  174. + (slave->mtd.size % slave->mtd.erasesize)) {
  175. + slave->mtd.flags &= ~MTD_WRITEABLE;
  176. + printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
  177. + part->name);
  178. + }
  179. +
  180. + slave->mtd.ecclayout = master->ecclayout;
  181. + if (master->block_isbad) {
  182. + uint32_t offs = 0;
  183. +
  184. + while(offs < slave->mtd.size) {
  185. + if (master->block_isbad(master,
  186. + offs + slave->offset))
  187. + slave->mtd.ecc_stats.badblocks++;
  188. + offs += slave->mtd.erasesize;
  189. + }
  190. + }
  191. +
  192. + if(part->mtdp)
  193. + { /* store the object pointer (caller may or may not register it */
  194. + *part->mtdp = &slave->mtd;
  195. + slave->registered = 0;
  196. + }
  197. + else
  198. + {
  199. + /* register our partition */
  200. + add_mtd_device(&slave->mtd);
  201. + slave->registered = 1;
  202. + }
  203. +
  204. + if (slp)
  205. + *slp = slave;
  206. +
  207. + return 0;
  208. +}
  209. +
  210. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  211. +#define ROOTFS_SPLIT_NAME "rootfs_data"
  212. +#define ROOTFS_REMOVED_NAME "<removed>"
  213. +static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
  214. +{
  215. + char buf[512];
  216. + struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
  217. + int len, ret;
  218. +
  219. + ret = master->read(master, offset, sizeof(*sb), &len, buf);
  220. + if (ret || (len != sizeof(*sb))) {
  221. + printk(KERN_ALERT "split_squashfs: error occured while reading "
  222. + "from \"%s\"\n", master->name);
  223. + return -EINVAL;
  224. + }
  225. +
  226. + if (*((u32 *) buf) != SQUASHFS_MAGIC) {
  227. + printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
  228. + master->name);
  229. + *split_offset = 0;
  230. + return 0;
  231. + }
  232. +
  233. + if (sb->bytes_used <= 0) {
  234. + printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
  235. + master->name);
  236. + *split_offset = 0;
  237. + return 0;
  238. + }
  239. +
  240. + len = (u32) sb->bytes_used;
  241. + len += (offset & 0x000fffff);
  242. + len += (master->erasesize - 1);
  243. + len &= ~(master->erasesize - 1);
  244. + len -= (offset & 0x000fffff);
  245. + *split_offset = offset + len;
  246. +
  247. + return 0;
  248. +}
  249. +
  250. +static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, struct mtd_partition *part,
  251. + int index)
  252. +{
  253. + struct mtd_partition *dpart;
  254. + struct mtd_part *slave = NULL;
  255. + int split_offset = 0;
  256. + int ret;
  257. +
  258. + ret = split_squashfs(master, part->offset, &split_offset);
  259. + if (ret)
  260. + return ret;
  261. +
  262. + if (split_offset <= 0)
  263. + return 0;
  264. +
  265. + dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
  266. + if (dpart == NULL) {
  267. + printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
  268. + ROOTFS_SPLIT_NAME);
  269. + return -ENOMEM;
  270. + }
  271. +
  272. + memcpy(dpart, part, sizeof(*part));
  273. + dpart->name = (unsigned char *)&dpart[1];
  274. + strcpy(dpart->name, ROOTFS_SPLIT_NAME);
  275. +
  276. + dpart->size -= split_offset - dpart->offset;
  277. + dpart->offset = split_offset;
  278. +
  279. + if (dpart == NULL)
  280. + return 1;
  281. +
  282. + printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%X, len=%X \n",
  283. + ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
  284. +
  285. + ret = add_one_partition(master, dpart, index, &slave);
  286. + if (ret)
  287. + kfree(dpart);
  288. + else if (slave)
  289. + rpart->split = &slave->mtd;
  290. +
  291. + return ret;
  292. +}
  293. +
  294. +static int refresh_rootfs_split(struct mtd_info *mtd)
  295. +{
  296. + struct mtd_partition tpart;
  297. + struct mtd_part *part;
  298. + int index = 0;
  299. + int offset, size;
  300. + int ret;
  301. +
  302. + part = PART(mtd);
  303. +
  304. + /* check for the new squashfs offset first */
  305. + ret = split_squashfs(part->master, part->offset, &offset);
  306. + if (ret)
  307. + return ret;
  308. +
  309. + if ((offset > 0) && !mtd->split) {
  310. + printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
  311. + /* if we don't have a rootfs split partition, create a new one */
  312. + tpart.name = mtd->name;
  313. + tpart.size = mtd->size;
  314. + tpart.offset = part->offset;
  315. +
  316. + /* find the index of the last partition */
  317. + if (!list_empty(&mtd_partitions))
  318. + index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1;
  319. +
  320. + return split_rootfs_data(part->master, &part->mtd, &tpart, index);
  321. + } else if ((offset > 0) && mtd->split) {
  322. + /* update the offsets of the existing partition */
  323. + size = mtd->size + part->offset - offset;
  324. +
  325. + part = PART(mtd->split);
  326. + part->offset = offset;
  327. + part->mtd.size = size;
  328. + printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
  329. + __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
  330. + part->offset, part->mtd.size);
  331. + strcpy(part->mtd.name, ROOTFS_SPLIT_NAME);
  332. + } else if ((offset <= 0) && mtd->split) {
  333. + printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
  334. +
  335. + /* mark existing partition as removed */
  336. + part = PART(mtd->split);
  337. + strcpy(part->mtd.name, ROOTFS_REMOVED_NAME);
  338. + part->offset = 0;
  339. + part->mtd.size = 0;
  340. + }
  341. +
  342. + return 0;
  343. +}
  344. +#endif /* CONFIG_MTD_ROOTFS_SPLIT */
  345. +
  346. /*
  347. * This function, given a master MTD object and a partition table, creates
  348. * and registers slave MTD objects which are bound to the master according to
  349. @@ -320,168 +628,31 @@ int add_mtd_partitions(struct mtd_info *
  350. int nbparts)
  351. {
  352. struct mtd_part *slave;
  353. - u_int32_t cur_offset = 0;
  354. - int i;
  355. + struct mtd_partition *part;
  356. + int i, j, ret = 0;
  357. printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
  358. - for (i = 0; i < nbparts; i++) {
  359. -
  360. - /* allocate the partition structure */
  361. - slave = kzalloc (sizeof(*slave), GFP_KERNEL);
  362. - if (!slave) {
  363. - printk ("memory allocation error while creating partitions for \"%s\"\n",
  364. - master->name);
  365. - del_mtd_partitions(master);
  366. - return -ENOMEM;
  367. - }
  368. - list_add(&slave->list, &mtd_partitions);
  369. -
  370. - /* set up the MTD object for this partition */
  371. - slave->mtd.type = master->type;
  372. - slave->mtd.flags = master->flags & ~parts[i].mask_flags;
  373. - slave->mtd.size = parts[i].size;
  374. - slave->mtd.writesize = master->writesize;
  375. - slave->mtd.oobsize = master->oobsize;
  376. - slave->mtd.oobavail = master->oobavail;
  377. - slave->mtd.subpage_sft = master->subpage_sft;
  378. -
  379. - slave->mtd.name = parts[i].name;
  380. - slave->mtd.owner = master->owner;
  381. -
  382. - slave->mtd.read = part_read;
  383. - slave->mtd.write = part_write;
  384. -
  385. - if(master->point && master->unpoint){
  386. - slave->mtd.point = part_point;
  387. - slave->mtd.unpoint = part_unpoint;
  388. - }
  389. -
  390. - if (master->read_oob)
  391. - slave->mtd.read_oob = part_read_oob;
  392. - if (master->write_oob)
  393. - slave->mtd.write_oob = part_write_oob;
  394. - if(master->read_user_prot_reg)
  395. - slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
  396. - if(master->read_fact_prot_reg)
  397. - slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
  398. - if(master->write_user_prot_reg)
  399. - slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
  400. - if(master->lock_user_prot_reg)
  401. - slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
  402. - if(master->get_user_prot_info)
  403. - slave->mtd.get_user_prot_info = part_get_user_prot_info;
  404. - if(master->get_fact_prot_info)
  405. - slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
  406. - if (master->sync)
  407. - slave->mtd.sync = part_sync;
  408. - if (!i && master->suspend && master->resume) {
  409. - slave->mtd.suspend = part_suspend;
  410. - slave->mtd.resume = part_resume;
  411. - }
  412. - if (master->writev)
  413. - slave->mtd.writev = part_writev;
  414. - if (master->lock)
  415. - slave->mtd.lock = part_lock;
  416. - if (master->unlock)
  417. - slave->mtd.unlock = part_unlock;
  418. - if (master->block_isbad)
  419. - slave->mtd.block_isbad = part_block_isbad;
  420. - if (master->block_markbad)
  421. - slave->mtd.block_markbad = part_block_markbad;
  422. - slave->mtd.erase = part_erase;
  423. - slave->master = master;
  424. - slave->offset = parts[i].offset;
  425. - slave->index = i;
  426. -
  427. - if (slave->offset == MTDPART_OFS_APPEND)
  428. - slave->offset = cur_offset;
  429. - if (slave->offset == MTDPART_OFS_NXTBLK) {
  430. - slave->offset = cur_offset;
  431. - if ((cur_offset % master->erasesize) != 0) {
  432. - /* Round up to next erasesize */
  433. - slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
  434. - printk(KERN_NOTICE "Moving partition %d: "
  435. - "0x%08x -> 0x%08x\n", i,
  436. - cur_offset, slave->offset);
  437. - }
  438. - }
  439. - if (slave->mtd.size == MTDPART_SIZ_FULL)
  440. - slave->mtd.size = master->size - slave->offset;
  441. - cur_offset = slave->offset + slave->mtd.size;
  442. -
  443. - printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
  444. - slave->offset + slave->mtd.size, slave->mtd.name);
  445. -
  446. - /* let's do some sanity checks */
  447. - if (slave->offset >= master->size) {
  448. - /* let's register it anyway to preserve ordering */
  449. - slave->offset = 0;
  450. - slave->mtd.size = 0;
  451. - printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
  452. - parts[i].name);
  453. - }
  454. - if (slave->offset + slave->mtd.size > master->size) {
  455. - slave->mtd.size = master->size - slave->offset;
  456. - printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
  457. - parts[i].name, master->name, slave->mtd.size);
  458. - }
  459. - if (master->numeraseregions>1) {
  460. - /* Deal with variable erase size stuff */
  461. - int i;
  462. - struct mtd_erase_region_info *regions = master->eraseregions;
  463. -
  464. - /* Find the first erase regions which is part of this partition. */
  465. - for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
  466. - ;
  467. -
  468. - for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
  469. - if (slave->mtd.erasesize < regions[i].erasesize) {
  470. - slave->mtd.erasesize = regions[i].erasesize;
  471. - }
  472. + for (i = 0, j = 0; i < nbparts; i++) {
  473. + part = (struct mtd_partition *) &parts[i];
  474. + ret = add_one_partition(master, part, j, &slave);
  475. + if (ret)
  476. + return ret;
  477. + j++;
  478. +
  479. + if (strcmp(part->name, "rootfs") == 0 && slave->registered) {
  480. +#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
  481. + if (ROOT_DEV == 0) {
  482. + printk(KERN_NOTICE "mtd: partition \"rootfs\" "
  483. + "set to be root filesystem\n");
  484. + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
  485. }
  486. - } else {
  487. - /* Single erase size */
  488. - slave->mtd.erasesize = master->erasesize;
  489. - }
  490. -
  491. - if ((slave->mtd.flags & MTD_WRITEABLE) &&
  492. - (slave->offset % slave->mtd.erasesize)) {
  493. - /* Doesn't start on a boundary of major erase size */
  494. - /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
  495. - slave->mtd.flags &= ~MTD_WRITEABLE;
  496. - printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
  497. - parts[i].name);
  498. - }
  499. - if ((slave->mtd.flags & MTD_WRITEABLE) &&
  500. - (slave->mtd.size % slave->mtd.erasesize)) {
  501. - slave->mtd.flags &= ~MTD_WRITEABLE;
  502. - printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
  503. - parts[i].name);
  504. - }
  505. -
  506. - slave->mtd.ecclayout = master->ecclayout;
  507. - if (master->block_isbad) {
  508. - uint32_t offs = 0;
  509. -
  510. - while(offs < slave->mtd.size) {
  511. - if (master->block_isbad(master,
  512. - offs + slave->offset))
  513. - slave->mtd.ecc_stats.badblocks++;
  514. - offs += slave->mtd.erasesize;
  515. - }
  516. - }
  517. -
  518. - if(parts[i].mtdp)
  519. - { /* store the object pointer (caller may or may not register it */
  520. - *parts[i].mtdp = &slave->mtd;
  521. - slave->registered = 0;
  522. - }
  523. - else
  524. - {
  525. - /* register our partition */
  526. - add_mtd_device(&slave->mtd);
  527. - slave->registered = 1;
  528. +#endif
  529. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  530. + ret = split_rootfs_data(master, &slave->mtd, part, j);
  531. + if (ret == 0)
  532. + j++;
  533. +#endif
  534. }
  535. }
  536. @@ -557,6 +728,32 @@ int parse_mtd_partitions(struct mtd_info
  537. return ret;
  538. }
  539. +int refresh_mtd_partitions(struct mtd_info *mtd)
  540. +{
  541. + int ret = 0;
  542. +
  543. + if (IS_PART(mtd)) {
  544. + struct mtd_part *part;
  545. + struct mtd_info *master;
  546. +
  547. + part = PART(mtd);
  548. + master = part->master;
  549. + if (master->refresh_device)
  550. + ret = master->refresh_device(master);
  551. + }
  552. +
  553. + if (!ret && mtd->refresh_device)
  554. + ret = mtd->refresh_device(mtd);
  555. +
  556. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  557. + if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
  558. + refresh_rootfs_split(mtd);
  559. +#endif
  560. +
  561. + return 0;
  562. +}
  563. +
  564. EXPORT_SYMBOL_GPL(parse_mtd_partitions);
  565. +EXPORT_SYMBOL_GPL(refresh_mtd_partitions);
  566. EXPORT_SYMBOL_GPL(register_mtd_parser);
  567. EXPORT_SYMBOL_GPL(deregister_mtd_parser);
  568. --- a/drivers/mtd/devices/block2mtd.c
  569. +++ b/drivers/mtd/devices/block2mtd.c
  570. @@ -34,6 +34,8 @@ struct block2mtd_dev {
  571. struct block_device *blkdev;
  572. struct mtd_info mtd;
  573. struct mutex write_mutex;
  574. + rwlock_t bdev_mutex;
  575. + char devname[0];
  576. };
  577. @@ -86,6 +88,12 @@ static int block2mtd_erase(struct mtd_in
  578. size_t len = instr->len;
  579. int err;
  580. + read_lock(&dev->bdev_mutex);
  581. + if (!dev->blkdev) {
  582. + err = -EINVAL;
  583. + goto done;
  584. + }
  585. +
  586. instr->state = MTD_ERASING;
  587. mutex_lock(&dev->write_mutex);
  588. err = _block2mtd_erase(dev, from, len);
  589. @@ -98,6 +106,10 @@ static int block2mtd_erase(struct mtd_in
  590. instr->state = MTD_ERASE_DONE;
  591. mtd_erase_callback(instr);
  592. +
  593. +done:
  594. + read_unlock(&dev->bdev_mutex);
  595. +
  596. return err;
  597. }
  598. @@ -109,10 +121,14 @@ static int block2mtd_read(struct mtd_inf
  599. struct page *page;
  600. int index = from >> PAGE_SHIFT;
  601. int offset = from & (PAGE_SIZE-1);
  602. - int cpylen;
  603. + int cpylen, err = 0;
  604. +
  605. + read_lock(&dev->bdev_mutex);
  606. + if (!dev->blkdev || (from > mtd->size)) {
  607. + err = -EINVAL;
  608. + goto done;
  609. + }
  610. - if (from > mtd->size)
  611. - return -EINVAL;
  612. if (from + len > mtd->size)
  613. len = mtd->size - from;
  614. @@ -127,10 +143,14 @@ static int block2mtd_read(struct mtd_inf
  615. len = len - cpylen;
  616. page = page_read(dev->blkdev->bd_inode->i_mapping, index);
  617. - if (!page)
  618. - return -ENOMEM;
  619. - if (IS_ERR(page))
  620. - return PTR_ERR(page);
  621. + if (!page) {
  622. + err = -ENOMEM;
  623. + goto done;
  624. + }
  625. + if (IS_ERR(page)) {
  626. + err = PTR_ERR(page);
  627. + goto done;
  628. + }
  629. memcpy(buf, page_address(page) + offset, cpylen);
  630. page_cache_release(page);
  631. @@ -141,7 +161,10 @@ static int block2mtd_read(struct mtd_inf
  632. offset = 0;
  633. index++;
  634. }
  635. - return 0;
  636. +
  637. +done:
  638. + read_unlock(&dev->bdev_mutex);
  639. + return err;
  640. }
  641. @@ -193,12 +216,22 @@ static int block2mtd_write(struct mtd_in
  642. size_t *retlen, const u_char *buf)
  643. {
  644. struct block2mtd_dev *dev = mtd->priv;
  645. - int err;
  646. + int err = 0;
  647. +
  648. + read_lock(&dev->bdev_mutex);
  649. + if (!dev->blkdev) {
  650. + err = -EINVAL;
  651. + goto done;
  652. + }
  653. if (!len)
  654. - return 0;
  655. - if (to >= mtd->size)
  656. - return -ENOSPC;
  657. + goto done;
  658. +
  659. + if (to >= mtd->size) {
  660. + err = -ENOSPC;
  661. + goto done;
  662. + }
  663. +
  664. if (to + len > mtd->size)
  665. len = mtd->size - to;
  666. @@ -207,6 +240,9 @@ static int block2mtd_write(struct mtd_in
  667. mutex_unlock(&dev->write_mutex);
  668. if (err > 0)
  669. err = 0;
  670. +
  671. +done:
  672. + read_unlock(&dev->bdev_mutex);
  673. return err;
  674. }
  675. @@ -215,51 +251,29 @@ static int block2mtd_write(struct mtd_in
  676. static void block2mtd_sync(struct mtd_info *mtd)
  677. {
  678. struct block2mtd_dev *dev = mtd->priv;
  679. - sync_blockdev(dev->blkdev);
  680. - return;
  681. -}
  682. -
  683. -
  684. -static void block2mtd_free_device(struct block2mtd_dev *dev)
  685. -{
  686. - if (!dev)
  687. - return;
  688. -
  689. - kfree(dev->mtd.name);
  690. - if (dev->blkdev) {
  691. - invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
  692. - 0, -1);
  693. - close_bdev_excl(dev->blkdev);
  694. - }
  695. + read_lock(&dev->bdev_mutex);
  696. + if (dev->blkdev)
  697. + sync_blockdev(dev->blkdev);
  698. + read_unlock(&dev->bdev_mutex);
  699. - kfree(dev);
  700. + return;
  701. }
  702. -/* FIXME: ensure that mtd->size % erase_size == 0 */
  703. -static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
  704. +static int _open_bdev(struct block2mtd_dev *dev)
  705. {
  706. struct block_device *bdev;
  707. - struct block2mtd_dev *dev;
  708. - struct mtd_partition *part;
  709. -
  710. - if (!devname)
  711. - return NULL;
  712. -
  713. - dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
  714. - if (!dev)
  715. - return NULL;
  716. /* Get a handle on the device */
  717. - bdev = open_bdev_excl(devname, O_RDWR, NULL);
  718. + bdev = open_bdev_excl(dev->devname, O_RDWR, NULL);
  719. #ifndef MODULE
  720. if (IS_ERR(bdev)) {
  721. /* We might not have rootfs mounted at this point. Try
  722. to resolve the device name by other means. */
  723. - dev_t devt = name_to_dev_t(devname);
  724. + dev_t devt = name_to_dev_t(dev->devname);
  725. if (devt) {
  726. bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
  727. }
  728. @@ -267,17 +281,96 @@ static struct block2mtd_dev *add_device(
  729. #endif
  730. if (IS_ERR(bdev)) {
  731. - ERROR("error: cannot open device %s", devname);
  732. - goto devinit_err;
  733. + ERROR("error: cannot open device %s", dev->devname);
  734. + return 1;
  735. }
  736. dev->blkdev = bdev;
  737. if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
  738. ERROR("attempting to use an MTD device as a block device");
  739. - goto devinit_err;
  740. + return 1;
  741. }
  742. + return 0;
  743. +}
  744. +
  745. +static void _close_bdev(struct block2mtd_dev *dev)
  746. +{
  747. + struct block_device *bdev;
  748. +
  749. + if (!dev->blkdev)
  750. + return;
  751. +
  752. + bdev = dev->blkdev;
  753. + invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
  754. + close_bdev_excl(dev->blkdev);
  755. + dev->blkdev = NULL;
  756. +}
  757. +
  758. +static void block2mtd_free_device(struct block2mtd_dev *dev)
  759. +{
  760. + if (!dev)
  761. + return;
  762. +
  763. + kfree(dev->mtd.name);
  764. + _close_bdev(dev);
  765. + kfree(dev);
  766. +}
  767. +
  768. +
  769. +static int block2mtd_refresh(struct mtd_info *mtd)
  770. +{
  771. + struct block2mtd_dev *dev = mtd->priv;
  772. + struct block_device *bdev;
  773. + dev_t devt;
  774. + int err = 0;
  775. +
  776. + /* no other mtd function can run at this point */
  777. + write_lock(&dev->bdev_mutex);
  778. +
  779. + /* get the device number for the whole disk */
  780. + devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
  781. +
  782. + /* close the old block device */
  783. + _close_bdev(dev);
  784. +
  785. + /* open the whole disk, issue a partition rescan, then */
  786. + bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
  787. + if (!bdev || !bdev->bd_disk)
  788. + err = -EINVAL;
  789. + else {
  790. + err = rescan_partitions(bdev->bd_disk, bdev);
  791. + }
  792. + if (bdev)
  793. + close_bdev_excl(bdev);
  794. +
  795. + /* try to open the partition block device again */
  796. + _open_bdev(dev);
  797. + write_unlock(&dev->bdev_mutex);
  798. +
  799. + return err;
  800. +}
  801. +
  802. +/* FIXME: ensure that mtd->size % erase_size == 0 */
  803. +static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
  804. +{
  805. + struct block2mtd_dev *dev;
  806. + struct mtd_partition *part;
  807. +
  808. + if (!devname)
  809. + return NULL;
  810. +
  811. + dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
  812. + if (!dev)
  813. + return NULL;
  814. +
  815. + strcpy(dev->devname, devname);
  816. +
  817. + if (_open_bdev(dev))
  818. + goto devinit_err;
  819. +
  820. mutex_init(&dev->write_mutex);
  821. + rwlock_init(&dev->bdev_mutex);
  822. /* Setup the MTD structure */
  823. /* make the name contain the block device in */
  824. @@ -304,6 +397,7 @@ static struct block2mtd_dev *add_device(
  825. dev->mtd.read = block2mtd_read;
  826. dev->mtd.priv = dev;
  827. dev->mtd.owner = THIS_MODULE;
  828. + dev->mtd.refresh_device = block2mtd_refresh;
  829. part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
  830. part->name = dev->mtd.name;
  831. --- a/drivers/mtd/mtdchar.c
  832. +++ b/drivers/mtd/mtdchar.c
  833. @@ -17,6 +17,7 @@
  834. #include <linux/mtd/mtd.h>
  835. #include <linux/mtd/compatmac.h>
  836. +#include <linux/mtd/partitions.h>
  837. #include <asm/uaccess.h>
  838. @@ -754,6 +755,13 @@ static int mtd_ioctl(struct inode *inode
  839. file->f_pos = 0;
  840. break;
  841. }
  842. +#ifdef CONFIG_MTD_PARTITIONS
  843. + case MTDREFRESH:
  844. + {
  845. + ret = refresh_mtd_partitions(mtd);
  846. + break;
  847. + }
  848. +#endif
  849. default:
  850. ret = -ENOTTY;
  851. --- a/include/linux/mtd/mtd.h
  852. +++ b/include/linux/mtd/mtd.h
  853. @@ -98,6 +98,7 @@ struct mtd_oob_ops {
  854. uint8_t *oobbuf;
  855. };
  856. +struct mtd_info;
  857. struct mtd_info {
  858. u_char type;
  859. u_int32_t flags;
  860. @@ -202,6 +203,9 @@ struct mtd_info {
  861. struct module *owner;
  862. int usecount;
  863. + int (*refresh_device)(struct mtd_info *mtd);
  864. + struct mtd_info *split;
  865. +
  866. /* If the driver is something smart, like UBI, it may need to maintain
  867. * its own reference counting. The below functions are only for driver.
  868. * The driver may register its callbacks. These callbacks are not
  869. --- a/include/linux/mtd/partitions.h
  870. +++ b/include/linux/mtd/partitions.h
  871. @@ -36,6 +36,7 @@
  872. * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
  873. */
  874. +struct mtd_partition;
  875. struct mtd_partition {
  876. char *name; /* identifier string */
  877. u_int32_t size; /* partition size */
  878. @@ -43,6 +44,7 @@ struct mtd_partition {
  879. u_int32_t mask_flags; /* master MTD flags to mask out for this partition */
  880. struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
  881. struct mtd_info **mtdp; /* pointer to store the MTD object */
  882. + int (*refresh_partition)(struct mtd_info *);
  883. };
  884. #define MTDPART_OFS_NXTBLK (-2)
  885. @@ -52,6 +54,7 @@ struct mtd_partition {
  886. int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
  887. int del_mtd_partitions(struct mtd_info *);
  888. +int refresh_mtd_partitions(struct mtd_info *);
  889. /*
  890. * Functions dealing with the various ways of partitioning the space
  891. --- a/include/mtd/mtd-abi.h
  892. +++ b/include/mtd/mtd-abi.h
  893. @@ -95,6 +95,7 @@ struct otp_info {
  894. #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout)
  895. #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
  896. #define MTDFILEMODE _IO('M', 19)
  897. +#define MTDREFRESH _IO('M', 23)
  898. /*
  899. * Obsolete legacy interface. Keep it in order not to break userspace