include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[linux-3.10.git] / drivers / mtd / ubi / kapi.c
index 14c66b4..17f287d 100644 (file)
 
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+#include <linux/fs.h>
 #include <asm/div64.h>
 #include "ubi.h"
 
 /**
+ * ubi_do_get_device_info - get information about UBI device.
+ * @ubi: UBI device description object
+ * @di: the information is stored here
+ *
+ * This function is the same as 'ubi_get_device_info()', but it assumes the UBI
+ * device is locked and cannot disappear.
+ */
+void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di)
+{
+       di->ubi_num = ubi->ubi_num;
+       di->leb_size = ubi->leb_size;
+       di->min_io_size = ubi->min_io_size;
+       di->ro_mode = ubi->ro_mode;
+       di->cdev = ubi->cdev.dev;
+}
+EXPORT_SYMBOL_GPL(ubi_do_get_device_info);
+
+/**
  * ubi_get_device_info - get information about UBI device.
  * @ubi_num: UBI device number
  * @di: the information is stored here
  *
- * This function returns %0 in case of success and a %-ENODEV if there is no
- * such UBI device.
+ * This function returns %0 in case of success, %-EINVAL if the UBI device
+ * number is invalid, and %-ENODEV if there is no such UBI device.
  */
 int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
 {
-       const struct ubi_device *ubi;
-
-       if (!try_module_get(THIS_MODULE))
-               return -ENODEV;
+       struct ubi_device *ubi;
 
-       if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES ||
-           !ubi_devices[ubi_num]) {
-               module_put(THIS_MODULE);
+       if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
+               return -EINVAL;
+       ubi = ubi_get_device(ubi_num);
+       if (!ubi)
                return -ENODEV;
-       }
-
-       ubi = ubi_devices[ubi_num];
-       di->ubi_num = ubi->ubi_num;
-       di->leb_size = ubi->leb_size;
-       di->min_io_size = ubi->min_io_size;
-       di->ro_mode = ubi->ro_mode;
-       di->cdev = MKDEV(ubi->major, 0);
-       module_put(THIS_MODULE);
+       ubi_do_get_device_info(ubi, di);
+       ubi_put_device(ubi);
        return 0;
 }
 EXPORT_SYMBOL_GPL(ubi_get_device_info);
 
 /**
- * ubi_get_volume_info - get information about UBI volume.
- * @desc: volume descriptor
+ * ubi_do_get_volume_info - get information about UBI volume.
+ * @ubi: UBI device description object
+ * @vol: volume description object
  * @vi: the information is stored here
  */
-void ubi_get_volume_info(struct ubi_volume_desc *desc,
-                        struct ubi_volume_info *vi)
+void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
+                           struct ubi_volume_info *vi)
 {
-       const struct ubi_volume *vol = desc->vol;
-       const struct ubi_device *ubi = vol->ubi;
-
        vi->vol_id = vol->vol_id;
        vi->ubi_num = ubi->ubi_num;
        vi->size = vol->reserved_pebs;
@@ -79,7 +89,18 @@ void ubi_get_volume_info(struct ubi_volume_desc *desc,
        vi->usable_leb_size = vol->usable_leb_size;
        vi->name_len = vol->name_len;
        vi->name = vol->name;
-       vi->cdev = MKDEV(ubi->major, vi->vol_id + 1);
+       vi->cdev = vol->cdev.dev;
+}
+
+/**
+ * ubi_get_volume_info - get information about UBI volume.
+ * @desc: volume descriptor
+ * @vi: the information is stored here
+ */
+void ubi_get_volume_info(struct ubi_volume_desc *desc,
+                        struct ubi_volume_info *vi)
+{
+       ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi);
 }
 EXPORT_SYMBOL_GPL(ubi_get_volume_info);
 
@@ -105,37 +126,44 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
 {
        int err;
        struct ubi_volume_desc *desc;
-       struct ubi_device *ubi = ubi_devices[ubi_num];
+       struct ubi_device *ubi;
        struct ubi_volume *vol;
 
-       dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode);
+       dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode);
 
-       err = -ENODEV;
-       if (!try_module_get(THIS_MODULE))
-               return ERR_PTR(err);
-
-       if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi)
-               goto out_put;
+       if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
+               return ERR_PTR(-EINVAL);
 
-       err = -EINVAL;
-       if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
-               goto out_put;
        if (mode != UBI_READONLY && mode != UBI_READWRITE &&
            mode != UBI_EXCLUSIVE)
-               goto out_put;
+               return ERR_PTR(-EINVAL);
+
+       /*
+        * First of all, we have to get the UBI device to prevent its removal.
+        */
+       ubi = ubi_get_device(ubi_num);
+       if (!ubi)
+               return ERR_PTR(-ENODEV);
+
+       if (vol_id < 0 || vol_id >= ubi->vtbl_slots) {
+               err = -EINVAL;
+               goto out_put_ubi;
+       }
 
        desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL);
        if (!desc) {
                err = -ENOMEM;
-               goto out_put;
+               goto out_put_ubi;
        }
 
+       err = -ENODEV;
+       if (!try_module_get(THIS_MODULE))
+               goto out_free;
+
        spin_lock(&ubi->volumes_lock);
        vol = ubi->volumes[vol_id];
-       if (!vol) {
-               err = -ENODEV;
+       if (!vol)
                goto out_unlock;
-       }
 
        err = -EBUSY;
        switch (mode) {
@@ -157,21 +185,19 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
                vol->exclusive = 1;
                break;
        }
+       get_device(&vol->dev);
+       vol->ref_count += 1;
        spin_unlock(&ubi->volumes_lock);
 
        desc->vol = vol;
        desc->mode = mode;
 
-       /*
-        * To prevent simultaneous checks of the same volume we use @vtbl_mutex,
-        * although it is not the purpose it was introduced for.
-        */
-       mutex_lock(&ubi->vtbl_mutex);
+       mutex_lock(&ubi->ckvol_mutex);
        if (!vol->checked) {
                /* This is the first open - check the volume */
                err = ubi_check_volume(ubi, vol_id);
                if (err < 0) {
-                       mutex_unlock(&ubi->vtbl_mutex);
+                       mutex_unlock(&ubi->ckvol_mutex);
                        ubi_close_volume(desc);
                        return ERR_PTR(err);
                }
@@ -182,14 +208,19 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
                }
                vol->checked = 1;
        }
-       mutex_unlock(&ubi->vtbl_mutex);
+       mutex_unlock(&ubi->ckvol_mutex);
+
        return desc;
 
 out_unlock:
        spin_unlock(&ubi->volumes_lock);
-       kfree(desc);
-out_put:
        module_put(THIS_MODULE);
+out_free:
+       kfree(desc);
+out_put_ubi:
+       ubi_put_device(ubi);
+       dbg_err("cannot open device %d, volume %d, error %d",
+               ubi_num, vol_id, err);
        return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(ubi_open_volume);
@@ -206,10 +237,10 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
                                           int mode)
 {
        int i, vol_id = -1, len;
-       struct ubi_volume_desc *ret;
        struct ubi_device *ubi;
+       struct ubi_volume_desc *ret;
 
-       dbg_msg("open volume %s, mode %d", name, mode);
+       dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode);
 
        if (!name)
                return ERR_PTR(-EINVAL);
@@ -218,14 +249,12 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
        if (len > UBI_VOL_NAME_MAX)
                return ERR_PTR(-EINVAL);
 
-       ret = ERR_PTR(-ENODEV);
-       if (!try_module_get(THIS_MODULE))
-               return ret;
-
-       if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi_devices[ubi_num])
-               goto out_put;
+       if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
+               return ERR_PTR(-EINVAL);
 
-       ubi = ubi_devices[ubi_num];
+       ubi = ubi_get_device(ubi_num);
+       if (!ubi)
+               return ERR_PTR(-ENODEV);
 
        spin_lock(&ubi->volumes_lock);
        /* Walk all volumes of this UBI device */
@@ -239,28 +268,70 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
        }
        spin_unlock(&ubi->volumes_lock);
 
-       if (vol_id < 0)
-               goto out_put;
-
-       ret = ubi_open_volume(ubi_num, vol_id, mode);
+       if (vol_id >= 0)
+               ret = ubi_open_volume(ubi_num, vol_id, mode);
+       else
+               ret = ERR_PTR(-ENODEV);
 
-out_put:
-       module_put(THIS_MODULE);
+       /*
+        * We should put the UBI device even in case of success, because
+        * 'ubi_open_volume()' took a reference as well.
+        */
+       ubi_put_device(ubi);
        return ret;
 }
 EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
 
 /**
+ * ubi_open_volume_path - open UBI volume by its character device node path.
+ * @pathname: volume character device node path
+ * @mode: open mode
+ *
+ * This function is similar to 'ubi_open_volume()', but opens a volume the path
+ * to its character device node.
+ */
+struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
+{
+       int error, ubi_num, vol_id, mod;
+       struct inode *inode;
+       struct path path;
+
+       dbg_gen("open volume %s, mode %d", pathname, mode);
+
+       if (!pathname || !*pathname)
+               return ERR_PTR(-EINVAL);
+
+       error = kern_path(pathname, LOOKUP_FOLLOW, &path);
+       if (error)
+               return ERR_PTR(error);
+
+       inode = path.dentry->d_inode;
+       mod = inode->i_mode;
+       ubi_num = ubi_major2num(imajor(inode));
+       vol_id = iminor(inode) - 1;
+       path_put(&path);
+
+       if (!S_ISCHR(mod))
+               return ERR_PTR(-EINVAL);
+       if (vol_id >= 0 && ubi_num >= 0)
+               return ubi_open_volume(ubi_num, vol_id, mode);
+       return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(ubi_open_volume_path);
+
+/**
  * ubi_close_volume - close UBI volume.
  * @desc: volume descriptor
  */
 void ubi_close_volume(struct ubi_volume_desc *desc)
 {
        struct ubi_volume *vol = desc->vol;
+       struct ubi_device *ubi = vol->ubi;
 
-       dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode);
+       dbg_gen("close device %d, volume %d, mode %d",
+               ubi->ubi_num, vol->vol_id, desc->mode);
 
-       spin_lock(&vol->ubi->volumes_lock);
+       spin_lock(&ubi->volumes_lock);
        switch (desc->mode) {
        case UBI_READONLY:
                vol->readers -= 1;
@@ -271,9 +342,12 @@ void ubi_close_volume(struct ubi_volume_desc *desc)
        case UBI_EXCLUSIVE:
                vol->exclusive = 0;
        }
-       spin_unlock(&vol->ubi->volumes_lock);
+       vol->ref_count -= 1;
+       spin_unlock(&ubi->volumes_lock);
 
        kfree(desc);
+       put_device(&vol->dev);
+       ubi_put_device(ubi);
        module_put(THIS_MODULE);
 }
 EXPORT_SYMBOL_GPL(ubi_close_volume);
@@ -312,7 +386,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
        struct ubi_device *ubi = vol->ubi;
        int err, vol_id = vol->vol_id;
 
-       dbg_msg("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
+       dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
 
        if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
            lnum >= vol->used_ebs || offset < 0 || len < 0 ||
@@ -333,7 +407,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
        if (len == 0)
                return 0;
 
-       err = ubi_eba_read_leb(ubi, vol_id, lnum, buf, offset, len, check);
+       err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
        if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) {
                ubi_warn("mark volume %d as corrupted", vol_id);
                vol->corrupted = 1;
@@ -377,7 +451,7 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
        struct ubi_device *ubi = vol->ubi;
        int vol_id = vol->vol_id;
 
-       dbg_msg("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
+       dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
 
        if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
                return -EINVAL;
@@ -386,8 +460,8 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
                return -EROFS;
 
        if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 ||
-           offset + len > vol->usable_leb_size || offset % ubi->min_io_size ||
-           len % ubi->min_io_size)
+           offset + len > vol->usable_leb_size ||
+           offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
                return -EINVAL;
 
        if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
@@ -400,7 +474,7 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
        if (len == 0)
                return 0;
 
-       return ubi_eba_write_leb(ubi, vol_id, lnum, buf, offset, len, dtype);
+       return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype);
 }
 EXPORT_SYMBOL_GPL(ubi_leb_write);
 
@@ -427,7 +501,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
        struct ubi_device *ubi = vol->ubi;
        int vol_id = vol->vol_id;
 
-       dbg_msg("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
+       dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
 
        if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
                return -EINVAL;
@@ -436,7 +510,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
                return -EROFS;
 
        if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 ||
-           len > vol->usable_leb_size || len % ubi->min_io_size)
+           len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
                return -EINVAL;
 
        if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
@@ -449,7 +523,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
        if (len == 0)
                return 0;
 
-       return ubi_eba_atomic_leb_change(ubi, vol_id, lnum, buf, len, dtype);
+       return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype);
 }
 EXPORT_SYMBOL_GPL(ubi_leb_change);
 
@@ -469,9 +543,9 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
 {
        struct ubi_volume *vol = desc->vol;
        struct ubi_device *ubi = vol->ubi;
-       int err, vol_id = vol->vol_id;
+       int err;
 
-       dbg_msg("erase LEB %d:%d", vol_id, lnum);
+       dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
 
        if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
                return -EROFS;
@@ -482,7 +556,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
        if (vol->upd_marker)
                return -EBADF;
 
-       err = ubi_eba_unmap_leb(ubi, vol_id, lnum);
+       err = ubi_eba_unmap_leb(ubi, vol, lnum);
        if (err)
                return err;
 
@@ -530,9 +604,8 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
 {
        struct ubi_volume *vol = desc->vol;
        struct ubi_device *ubi = vol->ubi;
-       int vol_id = vol->vol_id;
 
-       dbg_msg("unmap LEB %d:%d", vol_id, lnum);
+       dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
 
        if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
                return -EROFS;
@@ -543,11 +616,55 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
        if (vol->upd_marker)
                return -EBADF;
 
-       return ubi_eba_unmap_leb(ubi, vol_id, lnum);
+       return ubi_eba_unmap_leb(ubi, vol, lnum);
 }
 EXPORT_SYMBOL_GPL(ubi_leb_unmap);
 
 /**
+ * ubi_leb_map - map logical eraseblock to a physical eraseblock.
+ * @desc: volume descriptor
+ * @lnum: logical eraseblock number
+ * @dtype: expected data type
+ *
+ * This function maps an un-mapped logical eraseblock @lnum to a physical
+ * eraseblock. This means, that after a successful invocation of this
+ * function the logical eraseblock @lnum will be empty (contain only %0xFF
+ * bytes) and be mapped to a physical eraseblock, even if an unclean reboot
+ * happens.
+ *
+ * This function returns zero in case of success, %-EBADF if the volume is
+ * damaged because of an interrupted update, %-EBADMSG if the logical
+ * eraseblock is already mapped, and other negative error codes in case of
+ * other failures.
+ */
+int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
+{
+       struct ubi_volume *vol = desc->vol;
+       struct ubi_device *ubi = vol->ubi;
+
+       dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
+
+       if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
+               return -EROFS;
+
+       if (lnum < 0 || lnum >= vol->reserved_pebs)
+               return -EINVAL;
+
+       if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
+           dtype != UBI_UNKNOWN)
+               return -EINVAL;
+
+       if (vol->upd_marker)
+               return -EBADF;
+
+       if (vol->eba_tbl[lnum] >= 0)
+               return -EBADMSG;
+
+       return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
+}
+EXPORT_SYMBOL_GPL(ubi_leb_map);
+
+/**
  * ubi_is_mapped - check if logical eraseblock is mapped.
  * @desc: volume descriptor
  * @lnum: logical eraseblock number
@@ -567,7 +684,7 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
 {
        struct ubi_volume *vol = desc->vol;
 
-       dbg_msg("test LEB %d:%d", vol->vol_id, lnum);
+       dbg_gen("test LEB %d:%d", vol->vol_id, lnum);
 
        if (lnum < 0 || lnum >= vol->reserved_pebs)
                return -EINVAL;
@@ -578,3 +695,83 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
        return vol->eba_tbl[lnum] >= 0;
 }
 EXPORT_SYMBOL_GPL(ubi_is_mapped);
+
+/**
+ * ubi_sync - synchronize UBI device buffers.
+ * @ubi_num: UBI device to synchronize
+ *
+ * The underlying MTD device may cache data in hardware or in software. This
+ * function ensures the caches are flushed. Returns zero in case of success and
+ * a negative error code in case of failure.
+ */
+int ubi_sync(int ubi_num)
+{
+       struct ubi_device *ubi;
+
+       ubi = ubi_get_device(ubi_num);
+       if (!ubi)
+               return -ENODEV;
+
+       if (ubi->mtd->sync)
+               ubi->mtd->sync(ubi->mtd);
+
+       ubi_put_device(ubi);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ubi_sync);
+
+BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
+
+/**
+ * ubi_register_volume_notifier - register a volume notifier.
+ * @nb: the notifier description object
+ * @ignore_existing: if non-zero, do not send "added" notification for all
+ *                   already existing volumes
+ *
+ * This function registers a volume notifier, which means that
+ * 'nb->notifier_call()' will be invoked when an UBI  volume is created,
+ * removed, re-sized, re-named, or updated. The first argument of the function
+ * is the notification type. The second argument is pointer to a
+ * &struct ubi_notification object which describes the notification event.
+ * Using UBI API from the volume notifier is prohibited.
+ *
+ * This function returns zero in case of success and a negative error code
+ * in case of failure.
+ */
+int ubi_register_volume_notifier(struct notifier_block *nb,
+                                int ignore_existing)
+{
+       int err;
+
+       err = blocking_notifier_chain_register(&ubi_notifiers, nb);
+       if (err != 0)
+               return err;
+       if (ignore_existing)
+               return 0;
+
+       /*
+        * We are going to walk all UBI devices and all volumes, and
+        * notify the user about existing volumes by the %UBI_VOLUME_ADDED
+        * event. We have to lock the @ubi_devices_mutex to make sure UBI
+        * devices do not disappear.
+        */
+       mutex_lock(&ubi_devices_mutex);
+       ubi_enumerate_volumes(nb);
+       mutex_unlock(&ubi_devices_mutex);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(ubi_register_volume_notifier);
+
+/**
+ * ubi_unregister_volume_notifier - unregister the volume notifier.
+ * @nb: the notifier description object
+ *
+ * This function unregisters volume notifier @nm and returns zero in case of
+ * success and a negative error code in case of failure.
+ */
+int ubi_unregister_volume_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&ubi_notifiers, nb);
+}
+EXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier);