UBI: add notification API
[pandora-kernel.git] / drivers / mtd / ubi / build.c
index 961416a..5399f41 100644 (file)
  * @name: MTD device name or number string
  * @vid_hdr_offs: VID header offset
  */
-struct mtd_dev_param
-{
+struct mtd_dev_param {
        char name[MTD_PARAM_LEN_MAX];
        int vid_hdr_offs;
 };
 
 /* Numbers of elements set in the @mtd_dev_param array */
-static int mtd_devs = 0;
+static int mtd_devs;
 
 /* MTD devices specification parameters */
 static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
@@ -122,6 +121,94 @@ static struct device_attribute dev_bgt_enabled =
 static struct device_attribute dev_mtd_num =
        __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL);
 
+/**
+ * ubi_volume_notify - send a volume change notification.
+ * @ubi: UBI device description object
+ * @vol: volume description object of the changed volume
+ * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
+ *
+ * This is a helper function which notifies all subscribers about a volume
+ * change event (creation, removal, re-sizing, re-naming, updating). Returns
+ * zero in case of success and a negative error code in case of failure.
+ */
+int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype)
+{
+       struct ubi_notification nt;
+
+       ubi_do_get_device_info(ubi, &nt.di);
+       ubi_do_get_volume_info(ubi, vol, &nt.vi);
+       return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt);
+}
+
+/**
+ * ubi_notify_all - send a notification to all volumes.
+ * @ubi: UBI device description object
+ * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
+ * @nb: the notifier to call
+ *
+ * This function walks all volumes of UBI device @ubi and sends the @ntype
+ * notification for each volume. If @nb is %NULL, then all registered notifiers
+ * are called, otherwise only the @nb notifier is called. Returns the number of
+ * sent notifications.
+ */
+int ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb)
+{
+       struct ubi_notification nt;
+       int i, count = 0;
+
+       ubi_do_get_device_info(ubi, &nt.di);
+
+       mutex_lock(&ubi->device_mutex);
+       for (i = 0; i < ubi->vtbl_slots; i++) {
+               /*
+                * Since the @ubi->device is locked, and we are not going to
+                * change @ubi->volumes, we do not have to lock
+                * @ubi->volumes_lock.
+                */
+               if (!ubi->volumes[i])
+                       continue;
+
+               ubi_do_get_volume_info(ubi, ubi->volumes[i], &nt.vi);
+               if (nb)
+                       nb->notifier_call(nb, ntype, &nt);
+               else
+                       blocking_notifier_call_chain(&ubi_notifiers, ntype,
+                                                    &nt);
+               count += 1;
+       }
+       mutex_unlock(&ubi->device_mutex);
+
+       return count;
+}
+
+/**
+ * ubi_enumerate_volumes - send "add" notification for all existing volumes.
+ * @nb: the notifier to call
+ *
+ * This function walks all UBI devices and volumes and sends the
+ * %UBI_VOLUME_ADDED notification for each volume. If @nb is %NULL, then all
+ * registered notifiers are called, otherwise only the @nb notifier is called.
+ * Returns the number of sent notifications.
+ */
+int ubi_enumerate_volumes(struct notifier_block *nb)
+{
+       int i, count = 0;
+
+       /*
+        * Since the @ubi_devices_mutex is locked, and we are not going to
+        * change @ubi_devices, we do not have to lock @ubi_devices_lock.
+        */
+       for (i = 0; i < UBI_MAX_DEVICES; i++) {
+               struct ubi_device *ubi = ubi_devices[i];
+
+               if (!ubi)
+                       continue;
+               count += ubi_notify_all(ubi, UBI_VOLUME_ADDED, nb);
+       }
+
+       return count;
+}
+
 /**
  * ubi_get_device - get UBI device.
  * @ubi_num: UBI device number
@@ -160,8 +247,7 @@ void ubi_put_device(struct ubi_device *ubi)
 }
 
 /**
- * ubi_get_by_major - get UBI device description object by character device
- *                    major number.
+ * ubi_get_by_major - get UBI device by character device major number.
  * @major: major number
  *
  * This function is similar to 'ubi_get_device()', but it searches the device
@@ -265,8 +351,12 @@ static ssize_t dev_attribute_show(struct device *dev,
        return ret;
 }
 
-/* Fake "release" method for UBI devices */
-static void dev_release(struct device *dev) { }
+static void dev_release(struct device *dev)
+{
+       struct ubi_device *ubi = container_of(dev, struct ubi_device, dev);
+
+       kfree(ubi);
+}
 
 /**
  * ubi_sysfs_init - initialize sysfs for an UBI device.
@@ -354,12 +444,31 @@ static void kill_volumes(struct ubi_device *ubi)
                        ubi_free_volume(ubi, ubi->volumes[i]);
 }
 
+/**
+ * free_user_volumes - free all user volumes.
+ * @ubi: UBI device description object
+ *
+ * Normally the volumes are freed at the release function of the volume device
+ * objects. However, on error paths the volumes have to be freed before the
+ * device objects have been initialized.
+ */
+static void free_user_volumes(struct ubi_device *ubi)
+{
+       int i;
+
+       for (i = 0; i < ubi->vtbl_slots; i++)
+               if (ubi->volumes[i]) {
+                       kfree(ubi->volumes[i]->eba_tbl);
+                       kfree(ubi->volumes[i]);
+               }
+}
+
 /**
  * uif_init - initialize user interfaces for an UBI device.
  * @ubi: UBI device description object
  *
  * This function returns zero in case of success and a negative error code in
- * case of failure.
+ * case of failure. Note, this function destroys all volumes if it fails.
  */
 static int uif_init(struct ubi_device *ubi)
 {
@@ -384,7 +493,7 @@ static int uif_init(struct ubi_device *ubi)
 
        ubi_assert(MINOR(dev) == 0);
        cdev_init(&ubi->cdev, &ubi_cdev_operations);
-       dbg_msg("%s major is %u", ubi->ubi_name, MAJOR(dev));
+       dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev));
        ubi->cdev.owner = THIS_MODULE;
 
        err = cdev_add(&ubi->cdev, dev, 1);
@@ -422,6 +531,10 @@ out_unreg:
 /**
  * uif_close - close user interfaces for an UBI device.
  * @ubi: UBI device description object
+ *
+ * Note, since this function un-registers UBI volume device objects (@vol->dev),
+ * the memory allocated voe the volumes is freed as well (in the release
+ * function).
  */
 static void uif_close(struct ubi_device *ubi)
 {
@@ -431,6 +544,21 @@ static void uif_close(struct ubi_device *ubi)
        unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
 }
 
+/**
+ * free_internal_volumes - free internal volumes.
+ * @ubi: UBI device description object
+ */
+static void free_internal_volumes(struct ubi_device *ubi)
+{
+       int i;
+
+       for (i = ubi->vtbl_slots;
+            i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+               kfree(ubi->volumes[i]->eba_tbl);
+               kfree(ubi->volumes[i]);
+       }
+}
+
 /**
  * attach_by_scanning - attach an MTD device using scanning method.
  * @ubi: UBI device descriptor
@@ -475,6 +603,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
 out_wl:
        ubi_wl_close(ubi);
 out_vtbl:
+       free_internal_volumes(ubi);
        vfree(ubi->vtbl);
 out_si:
        ubi_scan_destroy_si(si);
@@ -482,7 +611,7 @@ out_si:
 }
 
 /**
- * io_init - initialize I/O unit for a given UBI device.
+ * io_init - initialize I/O sub-system for a given UBI device.
  * @ubi: UBI device description object
  *
  * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are
@@ -530,7 +659,11 @@ static int io_init(struct ubi_device *ubi)
        ubi->min_io_size = ubi->mtd->writesize;
        ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
 
-       /* Make sure minimal I/O unit is power of 2 */
+       /*
+        * Make sure minimal I/O unit is power of 2. Note, there is no
+        * fundamental reason for this assumption. It is just an optimization
+        * which allows us to avoid costly division operations.
+        */
        if (!is_power_of_2(ubi->min_io_size)) {
                ubi_err("min. I/O unit (%d) is not power of 2",
                        ubi->min_io_size);
@@ -581,12 +714,21 @@ static int io_init(struct ubi_device *ubi)
        if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||
            ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
            ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
-           ubi->leb_start % ubi->min_io_size) {
+           ubi->leb_start & (ubi->min_io_size - 1)) {
                ubi_err("bad VID header (%d) or data offsets (%d)",
                        ubi->vid_hdr_offset, ubi->leb_start);
                return -EINVAL;
        }
 
+       /*
+        * Set maximum amount of physical erroneous eraseblocks to be 10%.
+        * Erroneous PEB are those which have read errors.
+        */
+       ubi->max_erroneous = ubi->peb_count / 10;
+       if (ubi->max_erroneous < 16)
+               ubi->max_erroneous = 16;
+       dbg_msg("max_erroneous    %d", ubi->max_erroneous);
+
        /*
         * It may happen that EC and VID headers are situated in one minimal
         * I/O unit. In this case we can only accept this UBI image in
@@ -646,7 +788,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 
        /*
         * Clear the auto-resize flag in the volume in-memory copy of the
-        * volume table, and 'ubi_resize_volume()' will propogate this change
+        * volume table, and 'ubi_resize_volume()' will propagate this change
         * to the flash.
         */
        ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG;
@@ -655,7 +797,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
                struct ubi_vtbl_record vtbl_rec;
 
                /*
-                * No avalilable PEBs to re-size the volume, clear the flag on
+                * No available PEBs to re-size the volume, clear the flag on
                 * flash and exit.
                 */
                memcpy(&vtbl_rec, &ubi->vtbl[vol_id],
@@ -682,13 +824,13 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 
 /**
  * ubi_attach_mtd_dev - attach an MTD device.
- * @mtd_dev: MTD device description object
+ * @mtd: MTD device description object
  * @ubi_num: number to assign to the new UBI device
  * @vid_hdr_offset: VID header offset
  *
  * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
  * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
- * which case this function finds a vacant device nubert and assings it
+ * which case this function finds a vacant device number and assigns it
  * automatically. Returns the new UBI device number in case of success and a
  * negative error code in case of failure.
  *
@@ -698,7 +840,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 {
        struct ubi_device *ubi;
-       int i, err;
+       int i, err, do_free = 1;
 
        /*
         * Check if we already have the same MTD device attached.
@@ -735,7 +877,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
                        if (!ubi_devices[ubi_num])
                                break;
                if (ubi_num == UBI_MAX_DEVICES) {
-                       dbg_err("only %d UBI devices may be created", UBI_MAX_DEVICES);
+                       dbg_err("only %d UBI devices may be created",
+                               UBI_MAX_DEVICES);
                        return -ENFILE;
                }
        } else {
@@ -760,7 +903,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 
        mutex_init(&ubi->buf_mutex);
        mutex_init(&ubi->ckvol_mutex);
-       mutex_init(&ubi->volumes_mutex);
+       mutex_init(&ubi->device_mutex);
        spin_lock_init(&ubi->volumes_lock);
 
        ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
@@ -769,19 +912,20 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
        if (err)
                goto out_free;
 
+       err = -ENOMEM;
        ubi->peb_buf1 = vmalloc(ubi->peb_size);
        if (!ubi->peb_buf1)
                goto out_free;
 
        ubi->peb_buf2 = vmalloc(ubi->peb_size);
        if (!ubi->peb_buf2)
-                goto out_free;
+               goto out_free;
 
-#ifdef CONFIG_MTD_UBI_DEBUG
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
        mutex_init(&ubi->dbg_buf_mutex);
        ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
        if (!ubi->dbg_peb_buf)
-                goto out_free;
+               goto out_free;
 #endif
 
        err = attach_by_scanning(ubi);
@@ -798,7 +942,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 
        err = uif_init(ubi);
        if (err)
-               goto out_detach;
+               goto out_nofree;
 
        ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
        if (IS_ERR(ubi->bgt_thread)) {
@@ -824,25 +968,34 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
                ubi->beb_rsvd_pebs);
        ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
 
-       /* Enable the background thread */
-       if (!DBG_DISABLE_BGT) {
+       /*
+        * The below lock makes sure we do not race with 'ubi_thread()' which
+        * checks @ubi->thread_enabled. Otherwise we may fail to wake it up.
+        */
+       spin_lock(&ubi->wl_lock);
+       if (!DBG_DISABLE_BGT)
                ubi->thread_enabled = 1;
-               wake_up_process(ubi->bgt_thread);
-       }
+       wake_up_process(ubi->bgt_thread);
+       spin_unlock(&ubi->wl_lock);
 
        ubi_devices[ubi_num] = ubi;
+       ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
        return ubi_num;
 
 out_uif:
        uif_close(ubi);
+out_nofree:
+       do_free = 0;
 out_detach:
-       ubi_eba_close(ubi);
        ubi_wl_close(ubi);
+       if (do_free)
+               free_user_volumes(ubi);
+       free_internal_volumes(ubi);
        vfree(ubi->vtbl);
 out_free:
        vfree(ubi->peb_buf1);
        vfree(ubi->peb_buf2);
-#ifdef CONFIG_MTD_UBI_DEBUG
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
        vfree(ubi->dbg_peb_buf);
 #endif
        kfree(ubi);
@@ -869,13 +1022,13 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
        if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
                return -EINVAL;
 
-       spin_lock(&ubi_devices_lock);
-       ubi = ubi_devices[ubi_num];
-       if (!ubi) {
-               spin_unlock(&ubi_devices_lock);
+       ubi = ubi_get_device(ubi_num);
+       if (!ubi)
                return -EINVAL;
-       }
 
+       spin_lock(&ubi_devices_lock);
+       put_device(&ubi->dev);
+       ubi->ref_count -= 1;
        if (ubi->ref_count) {
                if (!anyway) {
                        spin_unlock(&ubi_devices_lock);
@@ -889,6 +1042,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
        spin_unlock(&ubi_devices_lock);
 
        ubi_assert(ubi_num == ubi->ubi_num);
+       ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
        dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
 
        /*
@@ -898,18 +1052,24 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
        if (ubi->bgt_thread)
                kthread_stop(ubi->bgt_thread);
 
+       /*
+        * Get a reference to the device in order to prevent 'dev_release()'
+        * from freeing @ubi object.
+        */
+       get_device(&ubi->dev);
+
        uif_close(ubi);
-       ubi_eba_close(ubi);
        ubi_wl_close(ubi);
+       free_internal_volumes(ubi);
        vfree(ubi->vtbl);
        put_mtd_device(ubi->mtd);
        vfree(ubi->peb_buf1);
        vfree(ubi->peb_buf2);
-#ifdef CONFIG_MTD_UBI_DEBUG
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
        vfree(ubi->dbg_peb_buf);
 #endif
        ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
-       kfree(ubi);
+       put_device(&ubi->dev);
        return 0;
 }
 
@@ -1044,8 +1204,7 @@ static void __exit ubi_exit(void)
 module_exit(ubi_exit);
 
 /**
- * bytes_str_to_int - convert a string representing number of bytes to an
- * integer.
+ * bytes_str_to_int - convert a number of bytes string into an integer.
  * @str: the string to convert
  *
  * This function returns positive resulting integer in case of success and a