All of lore.kernel.org
 help / color / mirror / Atom feed
From: dmitry pervushin <dpervushin@gmail.com>
To: linux-mtd@lists.infradead.org
Subject: [PATCH] [UBI] 1/5 - UBI notifications, take two
Date: Mon, 15 Dec 2008 14:13:55 +0300	[thread overview]
Message-ID: <1229339635.7900.21.camel@hp.diimka.lan> (raw)

Implement notifications about UBI volume changes

Signed-off-by: dmitry pervushin <dimka@embeddedalley.com>

---
 drivers/mtd/ubi/build.c |   39 +++++++++++++++++++++++++++++++++++++++
 drivers/mtd/ubi/cdev.c  |    2 ++
 drivers/mtd/ubi/kapi.c  |   25 +++++++++++++++++++++++++
 drivers/mtd/ubi/ubi.h   |   35 +++++++++++++++++++++++++++++++++++
 drivers/mtd/ubi/vmt.c   |    8 ++++++++
 include/linux/mtd/ubi.h |   16 ++++++++++++++++
 6 files changed, 125 insertions(+)

Index: ubifs-2.6/drivers/mtd/ubi/build.c
===================================================================
--- ubifs-2.6.orig/drivers/mtd/ubi/build.c
+++ ubifs-2.6/drivers/mtd/ubi/build.c
@@ -122,6 +122,51 @@ static struct device_attribute dev_mtd_n
 	__ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL);
 
 /**
+ * ubi_enum_volumes - enumerate all existing volumes and send notification
+ *
+ * @t: notification type to send
+ * @ubi: UBI device number
+ * @nb: notifier to be called
+ *
+ * Walk on volume list that are created on device @ubi, or if @ubi < 0, on all
+ * available UBI devices. For each volume, send the notification - either
+ * system-wide if @nb is NULL, or only to the registered @nb
+ *
+ * Returns number of volumes processed
+ */
+int ubi_enum_volumes(enum ubi_volume_notification_type t, int ubi,
+		struct notifier_block *nb)
+{
+	int ubi_num, i, count = 0;
+	struct ubi_device *ubi_dev;
+	struct ubi_volume_notification nt;
+
+	ubi_num = ubi < 0 ? 0 : ubi;
+	spin_lock(&ubi_devices_lock);
+	do {
+		nt.ubi_num = ubi_num++;
+		ubi_dev = ubi_devices[nt.ubi_num];
+		if (!ubi_dev)
+			continue;
+		spin_lock(&ubi_dev->volumes_lock);
+		for (i = 0; i < ubi_dev->vtbl_slots; i++) {
+			if (!ubi_dev->volumes[i])
+				continue;
+			nt.vol_id = ubi_dev->volumes[i]->vol_id;
+			if (nb)
+				nb->notifier_call(nb, t, &nt);
+			else
+				blocking_notifier_call_chain(&ubi_notifiers,
+					t, &nt);
+			count++;
+		}
+		spin_unlock(&ubi_dev->volumes_lock);
+	} while (ubi < 0 && ubi_num < UBI_MAX_DEVICES);
+	spin_unlock(&ubi_devices_lock);
+	return count;
+}
+
+/**
  * ubi_get_device - get UBI device.
  * @ubi_num: UBI device number
  *
@@ -876,6 +921,7 @@ int ubi_attach_mtd_dev(struct mtd_info *
 	wake_up_process(ubi->bgt_thread);
 
 	ubi_devices[ubi_num] = ubi;
+	ubi_enum_volumes(UBI_VOLUME_ADDED, ubi_num, NULL);
 	return ubi_num;
 
 out_uif:
@@ -937,6 +983,8 @@ int ubi_detach_mtd_dev(int ubi_num, int
 	ubi_devices[ubi_num] = NULL;
 	spin_unlock(&ubi_devices_lock);
 
+	ubi_enum_volumes(UBI_VOLUME_DELETED, ubi_num, NULL);
+
 	ubi_assert(ubi_num == ubi->ubi_num);
 	dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
 
Index: ubifs-2.6/drivers/mtd/ubi/cdev.c
===================================================================
--- ubifs-2.6.orig/drivers/mtd/ubi/cdev.c
+++ ubifs-2.6/drivers/mtd/ubi/cdev.c
@@ -396,6 +396,8 @@ static ssize_t vol_cdev_write(struct fil
 		}
 		vol->checked = 1;
 		ubi_gluebi_updated(vol);
+		ubi_volume_notify(UBI_VOLUME_CHANGED,
+				ubi->ubi_num, vol->vol_id);
 		revoke_exclusive(desc, UBI_READWRITE);
 	}
 
Index: ubifs-2.6/drivers/mtd/ubi/kapi.c
===================================================================
--- ubifs-2.6.orig/drivers/mtd/ubi/kapi.c
+++ ubifs-2.6/drivers/mtd/ubi/kapi.c
@@ -656,3 +656,52 @@ int ubi_sync(int ubi_num)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ubi_sync);
+
+BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
+
+/**
+ * ubi_register_volume_notifier - register the volume notification function
+ *
+ * @nb: pointer to the filled struct &notifier_block
+ * @ignore_existing: boolean flag; if set to 1, UBI will not send
+ * 	notifications about ADDing existing volumes
+ *
+ * The function @nb.notifier_call will be called when volume is added,
+ * removed, resized or renamed. Its first parameter is &enum
+ * ubi_volume_notification_type, and the second points to the structure
+ * that contains information about "changed" volume - ubi_device_num and
+ * volume_id. When the notifier is called, it is safe to use all UBI API.
+ *
+ * Returns %0 on success, error code otherwise
+ */
+int ubi_register_volume_notifier(struct notifier_block *nb,
+				int ignore_existing)
+{
+	int r;
+
+	r = blocking_notifier_chain_register(&ubi_notifiers, nb);
+	if (!r)
+		goto out;
+	if (ignore_existing)
+		goto out;
+	down_read(&ubi_notifiers.rwsem);
+	ubi_enum_volumes(UBI_VOLUME_ADDED, -1, nb);
+	up_read(&ubi_notifiers.rwsem);
+out:
+	return r;
+}
+EXPORT_SYMBOL_GPL(ubi_register_volume_notifier);
+
+/**
+ * ubi_unregister_volume_notifier - unregister the volume notifier registered
+ * by ubi_register_volume_notifier
+ *
+ * @nb: pointer to the filled struct &notifier_block
+ *
+ * Returns %0 on success, error code otherwise
+ */
+int ubi_unregister_volume_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&ubi_notifiers, nb);
+}
+EXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier);
Index: ubifs-2.6/drivers/mtd/ubi/ubi.h
===================================================================
--- ubifs-2.6.orig/drivers/mtd/ubi/ubi.h
+++ ubifs-2.6/drivers/mtd/ubi/ubi.h
@@ -38,6 +38,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/ubi.h>
+#include <linux/notifier.h>
 
 #include "ubi-media.h"
 #include "scan.h"
@@ -447,6 +448,7 @@ extern struct file_operations ubi_cdev_o
 extern struct file_operations ubi_vol_cdev_operations;
 extern struct class *ubi_class;
 extern struct mutex ubi_devices_mutex;
+extern struct blocking_notifier_head ubi_notifiers;
 
 /* vtbl.c */
 int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
@@ -539,7 +541,40 @@ struct ubi_device *ubi_get_device(int ub
 void ubi_put_device(struct ubi_device *ubi);
 struct ubi_device *ubi_get_by_major(int major);
 int ubi_major2num(int major);
+int ubi_enum_volumes(enum ubi_volume_notification_type t,
+		int ubi_num, struct notifier_block *nb);
 
+static inline char *ubi_notification(enum ubi_volume_notification_type t)
+{
+	static char *nstr[] = {
+	 [UBI_VOLUME_ADDED]	= "Added",
+	 [UBI_VOLUME_DELETED]	= "Deleted",
+	 [UBI_VOLUME_RENAMED]	= "Renamed",
+	 [UBI_VOLUME_CHANGED]	= "Changed",
+	};
+	return nstr[t];
+}
+/**
+ * ubi_volume_notify - notify all registered clients about volume changes
+ *
+ * @t: notification type
+ * @ubi_device: device number
+ * @volume_name: name of created/removed/changed volume
+ */
+static inline int ubi_volume_notify(enum ubi_volume_notification_type t,
+		int ubi_num, int volume_id)
+{
+       struct ubi_volume_notification nt;
+
+       nt.ubi_num = ubi_num;
+       nt.vol_id = volume_id;
+       dbg_gen("%s: %s volume id %d on device %d\n",
+		       __func__,
+		       ubi_notification(t),
+		       volume_id,
+		       ubi_num);
+       return blocking_notifier_call_chain(&ubi_notifiers, t, &nt);
+}
 /*
  * ubi_rb_for_each_entry - walk an RB-tree.
  * @rb: a pointer to type 'struct rb_node' to to use as a loop counter
Index: ubifs-2.6/drivers/mtd/ubi/vmt.c
===================================================================
--- ubifs-2.6.orig/drivers/mtd/ubi/vmt.c
+++ ubifs-2.6/drivers/mtd/ubi/vmt.c
@@ -361,6 +361,7 @@ int ubi_create_volume(struct ubi_device
 	ubi->vol_count += 1;
 	spin_unlock(&ubi->volumes_lock);
 
+	ubi_volume_notify(UBI_VOLUME_ADDED, ubi->ubi_num, vol->vol_id);
 	err = paranoid_check_volumes(ubi);
 	return err;
 
@@ -431,6 +432,7 @@ int ubi_remove_volume(struct ubi_volume_
 		err = -EBUSY;
 		goto out_unlock;
 	}
+	ubi_volume_notify(UBI_VOLUME_DELETED, ubi->ubi_num, vol->vol_id);
 	ubi->volumes[vol_id] = NULL;
 	spin_unlock(&ubi->volumes_lock);
 
@@ -473,6 +475,7 @@ int ubi_remove_volume(struct ubi_volume_
 	return err;
 
 out_err:
+	ubi_volume_notify(UBI_VOLUME_ADDED, ubi->ubi_num, vol->vol_id);
 	ubi_err("cannot remove volume %d, error %d", vol_id, err);
 	spin_lock(&ubi->volumes_lock);
 	ubi->volumes[vol_id] = vol;
@@ -590,6 +593,7 @@ int ubi_resize_volume(struct ubi_volume_
 			(long long)vol->used_ebs * vol->usable_leb_size;
 	}
 
+	ubi_volume_notify(UBI_VOLUME_CHANGED, ubi->ubi_num, vol->vol_id);
 	err = paranoid_check_volumes(ubi);
 	return err;
 
@@ -635,6 +639,8 @@ int ubi_rename_volumes(struct ubi_device
 			vol->name_len = re->new_name_len;
 			memcpy(vol->name, re->new_name, re->new_name_len + 1);
 			spin_unlock(&ubi->volumes_lock);
+			ubi_volume_notify(UBI_VOLUME_RENAMED,
+				ubi->ubi_num, vol->vol_id);
 		}
 	}
 
Index: ubifs-2.6/include/linux/mtd/ubi.h
===================================================================
--- ubifs-2.6.orig/include/linux/mtd/ubi.h
+++ ubifs-2.6/include/linux/mtd/ubi.h
@@ -184,4 +184,20 @@ static inline int ubi_change(struct ubi_
 	return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
 }
 
+int ubi_register_volume_notifier(struct notifier_block *nb,
+		int ignore_existing);
+int ubi_unregister_volume_notifier(struct notifier_block *nb);
+
+struct ubi_volume_notification {
+	int ubi_num;
+	int vol_id;
+};
+
+enum ubi_volume_notification_type {
+	UBI_VOLUME_ADDED,
+	UBI_VOLUME_DELETED,
+	UBI_VOLUME_CHANGED,
+	UBI_VOLUME_RENAMED,
+};
+
 #endif /* !__LINUX_UBI_H__ */

             reply	other threads:[~2008-12-15 11:14 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-15 11:13 dmitry pervushin [this message]
2008-12-15 14:04 ` [PATCH] [UBI] 1/5 - UBI notifications, take two Artem Bityutskiy
2008-12-17 19:53   ` dmitry pervushin
2008-12-18  7:31     ` Artem Bityutskiy
2008-12-18 11:07       ` dmitry pervushin
2008-12-18 11:11         ` Artem Bityutskiy
2008-12-18 11:14           ` Artem Bityutskiy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1229339635.7900.21.camel@hp.diimka.lan \
    --to=dpervushin@gmail.com \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.