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

UBI: add notification API

UBI volume notifications are intended to create the API to get clients
notified about volume creation/deletion, renaming and re-sizing. A
client can subscribe to these notifications using 'ubi_volume_register()'
and cancel the subscription using 'ubi_volume_unregister()'. When UBI
volumes change, a blocking notifier is called. Clients also can request
"added" events on all volumes that existed before client subscribed
to the notifications.

If we use notifications instead of calling functions like 'ubi_gluebi_xxx()',
we can make the MTD emulation layer to be more flexible: build it as a
separate module and load/unload it on demand.

[Artem: many cleanups, rework locking, add "updated" event, provide
device/volume info in notifiers]

Signed-off-by: Dmitry Pervushin <dpervushin@embeddedalley.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>

authored by

Dmitry Pervushin and committed by
Artem Bityutskiy
0e0ee1cc b86a2c56

+241 -21
+95 -5
drivers/mtd/ubi/build.c
··· 122 122 __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL); 123 123 124 124 /** 125 + * ubi_volume_notify - send a volume change notification. 126 + * @ubi: UBI device description object 127 + * @vol: volume description object of the changed volume 128 + * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc) 129 + * 130 + * This is a helper function which notifies all subscribers about a volume 131 + * change event (creation, removal, re-sizing, re-naming, updating). Returns 132 + * zero in case of success and a negative error code in case of failure. 133 + */ 134 + int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype) 135 + { 136 + struct ubi_notification nt; 137 + 138 + ubi_do_get_device_info(ubi, &nt.di); 139 + ubi_do_get_volume_info(ubi, vol, &nt.vi); 140 + return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt); 141 + } 142 + 143 + /** 144 + * ubi_notify_all - send a notification to all volumes. 145 + * @ubi: UBI device description object 146 + * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc) 147 + * @nb: the notifier to call 148 + * 149 + * This function walks all volumes of UBI device @ubi and sends the @ntype 150 + * notification for each volume. If @nb is %NULL, then all registered notifiers 151 + * are called, otherwise only the @nb notifier is called. Returns the number of 152 + * sent notifications. 153 + */ 154 + int ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb) 155 + { 156 + struct ubi_notification nt; 157 + int i, count = 0; 158 + 159 + ubi_do_get_device_info(ubi, &nt.di); 160 + 161 + mutex_lock(&ubi->device_mutex); 162 + for (i = 0; i < ubi->vtbl_slots; i++) { 163 + /* 164 + * Since the @ubi->device is locked, and we are not going to 165 + * change @ubi->volumes, we do not have to lock 166 + * @ubi->volumes_lock. 167 + */ 168 + if (!ubi->volumes[i]) 169 + continue; 170 + 171 + ubi_do_get_volume_info(ubi, ubi->volumes[i], &nt.vi); 172 + if (nb) 173 + nb->notifier_call(nb, ntype, &nt); 174 + else 175 + blocking_notifier_call_chain(&ubi_notifiers, ntype, 176 + &nt); 177 + count += 1; 178 + } 179 + mutex_unlock(&ubi->device_mutex); 180 + 181 + return count; 182 + } 183 + 184 + /** 185 + * ubi_enumerate_volumes - send "add" notification for all existing volumes. 186 + * @nb: the notifier to call 187 + * 188 + * This function walks all UBI devices and volumes and sends the 189 + * %UBI_VOLUME_ADDED notification for each volume. If @nb is %NULL, then all 190 + * registered notifiers are called, otherwise only the @nb notifier is called. 191 + * Returns the number of sent notifications. 192 + */ 193 + int ubi_enumerate_volumes(struct notifier_block *nb) 194 + { 195 + int i, count = 0; 196 + 197 + /* 198 + * Since the @ubi_devices_mutex is locked, and we are not going to 199 + * change @ubi_devices, we do not have to lock @ubi_devices_lock. 200 + */ 201 + for (i = 0; i < UBI_MAX_DEVICES; i++) { 202 + struct ubi_device *ubi = ubi_devices[i]; 203 + 204 + if (!ubi) 205 + continue; 206 + count += ubi_notify_all(ubi, UBI_VOLUME_ADDED, nb); 207 + } 208 + 209 + return count; 210 + } 211 + 212 + /** 125 213 * ubi_get_device - get UBI device. 126 214 * @ubi_num: UBI device number 127 215 * ··· 979 891 spin_unlock(&ubi->wl_lock); 980 892 981 893 ubi_devices[ubi_num] = ubi; 894 + ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL); 982 895 return ubi_num; 983 896 984 897 out_uif: ··· 1022 933 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 1023 934 return -EINVAL; 1024 935 1025 - spin_lock(&ubi_devices_lock); 1026 - ubi = ubi_devices[ubi_num]; 1027 - if (!ubi) { 1028 - spin_unlock(&ubi_devices_lock); 936 + ubi = ubi_get_device(ubi_num); 937 + if (!ubi) 1029 938 return -EINVAL; 1030 - } 1031 939 940 + spin_lock(&ubi_devices_lock); 941 + put_device(&ubi->dev); 942 + ubi->ref_count -= 1; 1032 943 if (ubi->ref_count) { 1033 944 if (!anyway) { 1034 945 spin_unlock(&ubi_devices_lock); ··· 1042 953 spin_unlock(&ubi_devices_lock); 1043 954 1044 955 ubi_assert(ubi_num == ubi->ubi_num); 956 + ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL); 1045 957 dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num); 1046 958 1047 959 /*
+1
drivers/mtd/ubi/cdev.c
··· 396 396 } 397 397 vol->checked = 1; 398 398 ubi_gluebi_updated(vol); 399 + ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED); 399 400 revoke_exclusive(desc, UBI_READWRITE); 400 401 } 401 402
+92 -16
drivers/mtd/ubi/kapi.c
··· 26 26 #include "ubi.h" 27 27 28 28 /** 29 + * ubi_do_get_device_info - get information about UBI device. 30 + * @ubi: UBI device description object 31 + * @di: the information is stored here 32 + * 33 + * This function is the same as 'ubi_get_device_info()', but it assumes the UBI 34 + * device is locked and cannot disappear. 35 + */ 36 + void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di) 37 + { 38 + di->ubi_num = ubi->ubi_num; 39 + di->leb_size = ubi->leb_size; 40 + di->min_io_size = ubi->min_io_size; 41 + di->ro_mode = ubi->ro_mode; 42 + di->cdev = ubi->cdev.dev; 43 + } 44 + EXPORT_SYMBOL_GPL(ubi_do_get_device_info); 45 + 46 + /** 29 47 * ubi_get_device_info - get information about UBI device. 30 48 * @ubi_num: UBI device number 31 49 * @di: the information is stored here ··· 57 39 58 40 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 59 41 return -EINVAL; 60 - 61 42 ubi = ubi_get_device(ubi_num); 62 43 if (!ubi) 63 44 return -ENODEV; 64 - 65 - di->ubi_num = ubi->ubi_num; 66 - di->leb_size = ubi->leb_size; 67 - di->min_io_size = ubi->min_io_size; 68 - di->ro_mode = ubi->ro_mode; 69 - di->cdev = ubi->cdev.dev; 70 - 45 + ubi_do_get_device_info(ubi, di); 71 46 ubi_put_device(ubi); 72 47 return 0; 73 48 } 74 49 EXPORT_SYMBOL_GPL(ubi_get_device_info); 75 50 76 51 /** 77 - * ubi_get_volume_info - get information about UBI volume. 78 - * @desc: volume descriptor 52 + * ubi_do_get_volume_info - get information about UBI volume. 53 + * @ubi: UBI device description object 54 + * @vol: volume description object 79 55 * @vi: the information is stored here 80 56 */ 81 - void ubi_get_volume_info(struct ubi_volume_desc *desc, 82 - struct ubi_volume_info *vi) 57 + void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol, 58 + struct ubi_volume_info *vi) 83 59 { 84 - const struct ubi_volume *vol = desc->vol; 85 - const struct ubi_device *ubi = vol->ubi; 86 - 87 60 vi->vol_id = vol->vol_id; 88 61 vi->ubi_num = ubi->ubi_num; 89 62 vi->size = vol->reserved_pebs; ··· 87 78 vi->name_len = vol->name_len; 88 79 vi->name = vol->name; 89 80 vi->cdev = vol->cdev.dev; 81 + } 82 + 83 + /** 84 + * ubi_get_volume_info - get information about UBI volume. 85 + * @desc: volume descriptor 86 + * @vi: the information is stored here 87 + */ 88 + void ubi_get_volume_info(struct ubi_volume_desc *desc, 89 + struct ubi_volume_info *vi) 90 + { 91 + ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi); 90 92 } 91 93 EXPORT_SYMBOL_GPL(ubi_get_volume_info); 92 94 ··· 581 561 EXPORT_SYMBOL_GPL(ubi_leb_unmap); 582 562 583 563 /** 584 - * ubi_leb_map - map logical erasblock to a physical eraseblock. 564 + * ubi_leb_map - map logical eraseblock to a physical eraseblock. 585 565 * @desc: volume descriptor 586 566 * @lnum: logical eraseblock number 587 567 * @dtype: expected data type ··· 679 659 return 0; 680 660 } 681 661 EXPORT_SYMBOL_GPL(ubi_sync); 662 + 663 + BLOCKING_NOTIFIER_HEAD(ubi_notifiers); 664 + 665 + /** 666 + * ubi_register_volume_notifier - register a volume notifier. 667 + * @nb: the notifier description object 668 + * @ignore_existing: if non-zero, do not send "added" notification for all 669 + * already existing volumes 670 + * 671 + * This function registers a volume notifier, which means that 672 + * 'nb->notifier_call()' will be invoked when an UBI volume is created, 673 + * removed, re-sized, re-named, or updated. The first argument of the function 674 + * is the notification type. The second argument is pointer to a 675 + * &struct ubi_notification object which describes the notification event. 676 + * Using UBI API from the volume notifier is prohibited. 677 + * 678 + * This function returns zero in case of success and a negative error code 679 + * in case of failure. 680 + */ 681 + int ubi_register_volume_notifier(struct notifier_block *nb, 682 + int ignore_existing) 683 + { 684 + int err; 685 + 686 + err = blocking_notifier_chain_register(&ubi_notifiers, nb); 687 + if (err != 0) 688 + return err; 689 + if (ignore_existing) 690 + return 0; 691 + 692 + /* 693 + * We are going to walk all UBI devices and all volumes, and 694 + * notify the user about existing volumes by the %UBI_VOLUME_ADDED 695 + * event. We have to lock the @ubi_devices_mutex to make sure UBI 696 + * devices do not disappear. 697 + */ 698 + mutex_lock(&ubi_devices_mutex); 699 + ubi_enumerate_volumes(nb); 700 + mutex_unlock(&ubi_devices_mutex); 701 + 702 + return err; 703 + } 704 + EXPORT_SYMBOL_GPL(ubi_register_volume_notifier); 705 + 706 + /** 707 + * ubi_unregister_volume_notifier - unregister the volume notifier. 708 + * @nb: the notifier description object 709 + * 710 + * This function unregisters volume notifier @nm and returns zero in case of 711 + * success and a negative error code in case of failure. 712 + */ 713 + int ubi_unregister_volume_notifier(struct notifier_block *nb) 714 + { 715 + return blocking_notifier_chain_unregister(&ubi_notifiers, nb); 716 + } 717 + EXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier);
+12
drivers/mtd/ubi/ubi.h
··· 38 38 #include <linux/vmalloc.h> 39 39 #include <linux/mtd/mtd.h> 40 40 #include <linux/mtd/ubi.h> 41 + #include <linux/notifier.h> 41 42 42 43 #include "ubi-media.h" 43 44 #include "scan.h" ··· 484 483 extern const struct file_operations ubi_vol_cdev_operations; 485 484 extern struct class *ubi_class; 486 485 extern struct mutex ubi_devices_mutex; 486 + extern struct blocking_notifier_head ubi_notifiers; 487 487 488 488 /* vtbl.c */ 489 489 int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, ··· 577 575 void ubi_put_device(struct ubi_device *ubi); 578 576 struct ubi_device *ubi_get_by_major(int major); 579 577 int ubi_major2num(int major); 578 + int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, 579 + int ntype); 580 + int ubi_notify_all(struct ubi_device *ubi, int ntype, 581 + struct notifier_block *nb); 582 + int ubi_enumerate_volumes(struct notifier_block *nb); 583 + 584 + /* kapi.c */ 585 + void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di); 586 + void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol, 587 + struct ubi_volume_info *vi); 580 588 581 589 /* 582 590 * ubi_rb_for_each_entry - walk an RB-tree.
+4
drivers/mtd/ubi/vmt.c
··· 358 358 ubi->vol_count += 1; 359 359 spin_unlock(&ubi->volumes_lock); 360 360 361 + ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED); 361 362 if (paranoid_check_volumes(ubi)) 362 363 dbg_err("check failed while creating volume %d", vol_id); 363 364 return err; ··· 467 466 ubi->vol_count -= 1; 468 467 spin_unlock(&ubi->volumes_lock); 469 468 469 + ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED); 470 470 if (!no_vtbl && paranoid_check_volumes(ubi)) 471 471 dbg_err("check failed while removing volume %d", vol_id); 472 472 ··· 591 589 (long long)vol->used_ebs * vol->usable_leb_size; 592 590 } 593 591 592 + ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED); 594 593 if (paranoid_check_volumes(ubi)) 595 594 dbg_err("check failed while re-sizing volume %d", vol_id); 596 595 return err; ··· 638 635 vol->name_len = re->new_name_len; 639 636 memcpy(vol->name, re->new_name, re->new_name_len + 1); 640 637 spin_unlock(&ubi->volumes_lock); 638 + ubi_volume_notify(ubi, vol, UBI_VOLUME_RENAMED); 641 639 } 642 640 } 643 641
+37
include/linux/mtd/ubi.h
··· 132 132 dev_t cdev; 133 133 }; 134 134 135 + /* 136 + * enum - volume notification types. 137 + * @UBI_VOLUME_ADDED: volume has been added 138 + * @UBI_VOLUME_REMOVED: start volume volume 139 + * @UBI_VOLUME_RESIZED: volume size has been re-sized 140 + * @UBI_VOLUME_RENAMED: volume name has been re-named 141 + * @UBI_VOLUME_UPDATED: volume name has been updated 142 + * 143 + * These constants define which type of event has happened when a volume 144 + * notification function is invoked. 145 + */ 146 + enum { 147 + UBI_VOLUME_ADDED, 148 + UBI_VOLUME_REMOVED, 149 + UBI_VOLUME_RESIZED, 150 + UBI_VOLUME_RENAMED, 151 + UBI_VOLUME_UPDATED, 152 + }; 153 + 154 + /* 155 + * struct ubi_notification - UBI notification description structure. 156 + * @di: UBI device description object 157 + * @vi: UBI volume description object 158 + * 159 + * UBI notifiers are called with a pointer to an object of this type. The 160 + * object describes the notification. Namely, it provides a description of the 161 + * UBI device and UBI volume the notification informs about. 162 + */ 163 + struct ubi_notification { 164 + struct ubi_device_info di; 165 + struct ubi_volume_info vi; 166 + }; 167 + 135 168 /* UBI descriptor given to users when they open UBI volumes */ 136 169 struct ubi_volume_desc; 137 170 ··· 174 141 struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode); 175 142 struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, 176 143 int mode); 144 + int ubi_register_volume_notifier(struct notifier_block *nb, 145 + int ignore_existing); 146 + int ubi_unregister_volume_notifier(struct notifier_block *nb); 147 + 177 148 void ubi_close_volume(struct ubi_volume_desc *desc); 178 149 int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, 179 150 int len, int check);