/* Serializes UBI devices creations and removals */
 DEFINE_MUTEX(ubi_devices_mutex);
 
-/* Protects @ubi_devices and @ubi->ref_count */
+/* Protects @ubi_devices, @ubi->ref_count and @ubi->is_dead */
 static DEFINE_SPINLOCK(ubi_devices_lock);
 
 /* "Show" method for files in '/<sysfs>/class/ubi/' */
 
        spin_lock(&ubi_devices_lock);
        ubi = ubi_devices[ubi_num];
+       if (ubi && ubi->is_dead)
+               ubi = NULL;
+
        if (ubi) {
                ubi_assert(ubi->ref_count >= 0);
                ubi->ref_count += 1;
        spin_lock(&ubi_devices_lock);
        for (i = 0; i < UBI_MAX_DEVICES; i++) {
                ubi = ubi_devices[i];
-               if (ubi && MAJOR(ubi->cdev.dev) == major) {
+               if (ubi && !ubi->is_dead && MAJOR(ubi->cdev.dev) == major) {
                        ubi_assert(ubi->ref_count >= 0);
                        ubi->ref_count += 1;
                        get_device(&ubi->dev);
        for (i = 0; i < UBI_MAX_DEVICES; i++) {
                struct ubi_device *ubi = ubi_devices[i];
 
-               if (ubi && MAJOR(ubi->cdev.dev) == major) {
+               if (ubi && !ubi->is_dead && MAJOR(ubi->cdev.dev) == major) {
                        ubi_num = ubi->ubi_num;
                        break;
                }
        int i;
 
        for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
-               if (!ubi->volumes[i])
+               if (!ubi->volumes[i] || ubi->volumes[i]->is_dead)
                        continue;
                ubi_eba_replace_table(ubi->volumes[i], NULL);
                ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
                return -EINVAL;
 
        spin_lock(&ubi_devices_lock);
-       put_device(&ubi->dev);
        ubi->ref_count -= 1;
        if (ubi->ref_count) {
                if (!anyway) {
                ubi_err(ubi, "%s reference count %d, destroy anyway",
                        ubi->ubi_name, ubi->ref_count);
        }
+       ubi->is_dead = true;
+       spin_unlock(&ubi_devices_lock);
+
+       ubi_notify_all(ubi, UBI_VOLUME_SHUTDOWN, NULL);
+
+       spin_lock(&ubi_devices_lock);
+       put_device(&ubi->dev);
        ubi_devices[ubi_num] = NULL;
        spin_unlock(&ubi_devices_lock);
 
 
        struct ubi_device *ubi = vol->ubi;
 
        spin_lock(&ubi->volumes_lock);
-       if (!ubi->volumes[vol->vol_id]) {
+       if (!ubi->volumes[vol->vol_id] || ubi->volumes[vol->vol_id]->is_dead) {
                spin_unlock(&ubi->volumes_lock);
                return -ENODEV;
        }
 
        /* Ensure that the name is unique */
        for (i = 0; i < ubi->vtbl_slots; i++)
-               if (ubi->volumes[i] &&
+               if (ubi->volumes[i] && !ubi->volumes[i]->is_dead &&
                    ubi->volumes[i]->name_len == req->name_len &&
                    !strcmp(ubi->volumes[i]->name, req->name)) {
                        ubi_err(ubi, "volume \"%s\" exists (ID %d)",
                err = -EBUSY;
                goto out_unlock;
        }
+
+       /*
+        * Mark volume as dead at this point to prevent that anyone
+        * can take a reference to the volume from now on.
+        * This is necessary as we have to release the spinlock before
+        * calling ubi_volume_notify.
+        */
+       vol->is_dead = true;
+       spin_unlock(&ubi->volumes_lock);
+
+       ubi_volume_notify(ubi, vol, UBI_VOLUME_SHUTDOWN);
+
+       spin_lock(&ubi->volumes_lock);
        ubi->volumes[vol_id] = NULL;
        spin_unlock(&ubi->volumes_lock);
 
 
  *                     or a volume was removed)
  * @UBI_VOLUME_RESIZED: a volume has been re-sized
  * @UBI_VOLUME_RENAMED: a volume has been re-named
+ * @UBI_VOLUME_SHUTDOWN: a volume is going to removed, shutdown users
  * @UBI_VOLUME_UPDATED: data has been written to a volume
  *
  * These constants define which type of event has happened when a volume
        UBI_VOLUME_REMOVED,
        UBI_VOLUME_RESIZED,
        UBI_VOLUME_RENAMED,
+       UBI_VOLUME_SHUTDOWN,
        UBI_VOLUME_UPDATED,
 };