Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: prepare partition add and del functions for ioctl requests

mtd_is_master, mtd_add_partition and mtd_del_partition functions
are added to give the possibility of partition manipulation
by ioctl request.

The old partition add function is modified to fit the dynamic
allocation.

Signed-off-by: Roman Tereshonkov <roman.tereshonkov@nokia.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

authored by

Roman Tereshonkov and committed by
David Woodhouse
5daa7b21 93ac5a55

+141 -18
+136 -18
drivers/mtd/mtdpart.c
··· 29 29 #include <linux/kmod.h> 30 30 #include <linux/mtd/mtd.h> 31 31 #include <linux/mtd/partitions.h> 32 + #include <linux/err.h> 32 33 33 34 /* Our partition linked list */ 34 35 static LIST_HEAD(mtd_partitions); 36 + static DEFINE_MUTEX(mtd_partitions_mutex); 35 37 36 38 /* Our partition node structure */ 37 39 struct mtd_part { ··· 328 326 return res; 329 327 } 330 328 329 + static inline void free_partition(struct mtd_part *p) 330 + { 331 + kfree(p->mtd.name); 332 + kfree(p); 333 + } 334 + 331 335 /* 332 336 * This function unregisters and destroy all slave MTD objects which are 333 337 * attached to the given master MTD object. ··· 342 334 int del_mtd_partitions(struct mtd_info *master) 343 335 { 344 336 struct mtd_part *slave, *next; 337 + int ret, err = 0; 345 338 339 + mutex_lock(&mtd_partitions_mutex); 346 340 list_for_each_entry_safe(slave, next, &mtd_partitions, list) 347 341 if (slave->master == master) { 342 + ret = del_mtd_device(&slave->mtd); 343 + if (ret < 0) { 344 + err = ret; 345 + continue; 346 + } 348 347 list_del(&slave->list); 349 - del_mtd_device(&slave->mtd); 350 - kfree(slave); 348 + free_partition(slave); 351 349 } 350 + mutex_unlock(&mtd_partitions_mutex); 352 351 353 - return 0; 352 + return err; 354 353 } 355 354 EXPORT_SYMBOL(del_mtd_partitions); 356 355 357 - static struct mtd_part *add_one_partition(struct mtd_info *master, 358 - const struct mtd_partition *part, int partno, 359 - uint64_t cur_offset) 356 + static struct mtd_part *allocate_partition(struct mtd_info *master, 357 + const struct mtd_partition *part, int partno, 358 + uint64_t cur_offset) 360 359 { 361 360 struct mtd_part *slave; 361 + char *name; 362 362 363 363 /* allocate the partition structure */ 364 364 slave = kzalloc(sizeof(*slave), GFP_KERNEL); 365 - if (!slave) { 365 + name = kstrdup(part->name, GFP_KERNEL); 366 + if (!name || !slave) { 366 367 printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", 367 - master->name); 368 - del_mtd_partitions(master); 369 - return NULL; 368 + master->name); 369 + kfree(name); 370 + kfree(slave); 371 + return ERR_PTR(-ENOMEM); 370 372 } 371 - list_add(&slave->list, &mtd_partitions); 372 373 373 374 /* set up the MTD object for this partition */ 374 375 slave->mtd.type = master->type; ··· 388 371 slave->mtd.oobavail = master->oobavail; 389 372 slave->mtd.subpage_sft = master->subpage_sft; 390 373 391 - slave->mtd.name = part->name; 374 + slave->mtd.name = name; 392 375 slave->mtd.owner = master->owner; 393 376 slave->mtd.backing_dev_info = master->backing_dev_info; 394 377 ··· 535 518 } 536 519 537 520 out_register: 538 - /* register our partition */ 539 - add_mtd_device(&slave->mtd); 540 - 541 521 return slave; 542 522 } 523 + 524 + int mtd_add_partition(struct mtd_info *master, char *name, 525 + long long offset, long long length) 526 + { 527 + struct mtd_partition part; 528 + struct mtd_part *p, *new; 529 + uint64_t start, end; 530 + int ret = 0; 531 + 532 + /* the direct offset is expected */ 533 + if (offset == MTDPART_OFS_APPEND || 534 + offset == MTDPART_OFS_NXTBLK) 535 + return -EINVAL; 536 + 537 + if (length == MTDPART_SIZ_FULL) 538 + length = master->size - offset; 539 + 540 + if (length <= 0) 541 + return -EINVAL; 542 + 543 + part.name = name; 544 + part.size = length; 545 + part.offset = offset; 546 + part.mask_flags = 0; 547 + part.ecclayout = NULL; 548 + 549 + new = allocate_partition(master, &part, -1, offset); 550 + if (IS_ERR(new)) 551 + return PTR_ERR(new); 552 + 553 + start = offset; 554 + end = offset + length; 555 + 556 + mutex_lock(&mtd_partitions_mutex); 557 + list_for_each_entry(p, &mtd_partitions, list) 558 + if (p->master == master) { 559 + if ((start >= p->offset) && 560 + (start < (p->offset + p->mtd.size))) 561 + goto err_inv; 562 + 563 + if ((end >= p->offset) && 564 + (end < (p->offset + p->mtd.size))) 565 + goto err_inv; 566 + } 567 + 568 + list_add(&new->list, &mtd_partitions); 569 + mutex_unlock(&mtd_partitions_mutex); 570 + 571 + add_mtd_device(&new->mtd); 572 + 573 + return ret; 574 + err_inv: 575 + mutex_unlock(&mtd_partitions_mutex); 576 + free_partition(new); 577 + return -EINVAL; 578 + } 579 + EXPORT_SYMBOL_GPL(mtd_add_partition); 580 + 581 + int mtd_del_partition(struct mtd_info *master, int partno) 582 + { 583 + struct mtd_part *slave, *next; 584 + int ret = -EINVAL; 585 + 586 + mutex_lock(&mtd_partitions_mutex); 587 + list_for_each_entry_safe(slave, next, &mtd_partitions, list) 588 + if ((slave->master == master) && 589 + (slave->mtd.index == partno)) { 590 + ret = del_mtd_device(&slave->mtd); 591 + if (ret < 0) 592 + break; 593 + 594 + list_del(&slave->list); 595 + free_partition(slave); 596 + break; 597 + } 598 + mutex_unlock(&mtd_partitions_mutex); 599 + 600 + return ret; 601 + } 602 + EXPORT_SYMBOL_GPL(mtd_del_partition); 543 603 544 604 /* 545 605 * This function, given a master MTD object and a partition table, creates ··· 638 544 printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 639 545 640 546 for (i = 0; i < nbparts; i++) { 641 - slave = add_one_partition(master, parts + i, i, cur_offset); 642 - if (!slave) 643 - return -ENOMEM; 547 + slave = allocate_partition(master, parts + i, i, cur_offset); 548 + if (IS_ERR(slave)) 549 + return PTR_ERR(slave); 550 + 551 + mutex_lock(&mtd_partitions_mutex); 552 + list_add(&slave->list, &mtd_partitions); 553 + mutex_unlock(&mtd_partitions_mutex); 554 + 555 + add_mtd_device(&slave->mtd); 556 + 644 557 cur_offset = slave->offset + slave->mtd.size; 645 558 } 646 559 ··· 719 618 return ret; 720 619 } 721 620 EXPORT_SYMBOL_GPL(parse_mtd_partitions); 621 + 622 + int mtd_is_master(struct mtd_info *mtd) 623 + { 624 + struct mtd_part *part; 625 + int nopart = 0; 626 + 627 + mutex_lock(&mtd_partitions_mutex); 628 + list_for_each_entry(part, &mtd_partitions, list) 629 + if (&part->mtd == mtd) { 630 + nopart = 1; 631 + break; 632 + } 633 + mutex_unlock(&mtd_partitions_mutex); 634 + 635 + return nopart; 636 + } 637 + EXPORT_SYMBOL_GPL(mtd_is_master);
+5
include/linux/mtd/partitions.h
··· 89 89 static inline int mtd_has_cmdlinepart(void) { return 0; } 90 90 #endif 91 91 92 + int mtd_is_master(struct mtd_info *mtd); 93 + int mtd_add_partition(struct mtd_info *master, char *name, 94 + long long offset, long long length); 95 + int mtd_del_partition(struct mtd_info *master, int partno); 96 + 92 97 #endif