summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSlava Pestov <sviatoslavpestov@gmail.com>2015-01-27 00:16:11 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:33:06 -0800
commitbcf72741f90b5a40b58e214fdb093d4a8f14162e (patch)
treea17bec867e05afb912f536582166551dad23fe04
parent7e9d45f8d73183b3980f2fe0eca478aedf557f77 (diff)
bcache: notify user space of state changes using kobject_uevent
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--drivers/md/bcache/Makefile4
-rw-r--r--drivers/md/bcache/bcache.h4
-rw-r--r--drivers/md/bcache/io.c5
-rw-r--r--drivers/md/bcache/notify.c124
-rw-r--r--drivers/md/bcache/notify.h21
-rw-r--r--drivers/md/bcache/super.c21
6 files changed, 177 insertions, 2 deletions
diff --git a/drivers/md/bcache/Makefile b/drivers/md/bcache/Makefile
index 1fc9c32d4d33..769c199337f5 100644
--- a/drivers/md/bcache/Makefile
+++ b/drivers/md/bcache/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_BCACHE) += bcache.o
bcache-y := alloc.o bkey.o bkey_methods.o blockdev.o bset.o\
btree.o buckets.o closure.o debug.o extents.o gc.o inode.o io.o\
- journal.o keybuf.o keylist.o move.o movinggc.o request.o six.o stats.o\
- super.o sysfs.o tier.o trace.o util.o writeback.o
+ journal.o keybuf.o keylist.o move.o movinggc.o notify.o request.o six.o\
+ stats.o super.o sysfs.o tier.o trace.o util.o writeback.o
ccflags-y := -Werror
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 3639964e4aa4..1250669cf37e 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -552,6 +552,10 @@ struct cache_set {
struct task_struct *tiering_read;
struct bch_pd_controller tiering_pd;
+ /* NOTIFICATIONS */
+ struct mutex uevent_lock;
+ struct kobj_uevent_env uevent_env;
+
/* DEBUG JUNK */
struct dentry *debug;
#ifdef CONFIG_BCACHE_DEBUG
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 285e8f80bc7b..eee3de4882c7 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -15,6 +15,7 @@
#include "gc.h"
#include "io.h"
#include "keylist.h"
+#include "notify.h"
#include "stats.h"
#include "super.h"
@@ -195,9 +196,13 @@ void bch_count_io_errors(struct cache *ca, int error, const char *m)
&ca->io_errors);
if (errors < ca->set->error_limit) {
+ bch_notify_cache_error(ca, false, m);
+
pr_err("%s: IO error on %s, recovering",
bdevname(ca->disk_sb.bdev, buf), m);
} else {
+ bch_notify_cache_error(ca, true, m);
+
if (bch_cache_remove(ca, true))
pr_err("%s: too many IO errors on %s, removing",
bdevname(ca->disk_sb.bdev, buf), m);
diff --git a/drivers/md/bcache/notify.c b/drivers/md/bcache/notify.c
new file mode 100644
index 000000000000..9d3a8ca78ae2
--- /dev/null
+++ b/drivers/md/bcache/notify.c
@@ -0,0 +1,124 @@
+/*
+ * Code for sending uevent notifications to user-space.
+ *
+ * Copyright 2015 Datera, Inc.
+ */
+
+#include "bcache.h"
+
+#include <linux/kobject.h>
+
+#define notify_var(c, format, ...) \
+({ \
+ int ret; \
+ lockdep_assert_held(&(c)->uevent_lock); \
+ ret = add_uevent_var(&(c)->uevent_env, format, ##__VA_ARGS__); \
+ WARN_ON_ONCE(ret); \
+})
+
+static void notify_get(struct cache_set *c)
+{
+ struct kobj_uevent_env *env = &c->uevent_env;
+
+ mutex_lock(&c->uevent_lock);
+ env->envp_idx = 0;
+ env->buflen = 0;
+
+ notify_var(c, "SET_UUID=%pU", c->sb.set_uuid.b);
+}
+
+static void notify_get_cache(struct cache *ca)
+{
+ struct cache_set *c = ca->set;
+ char buf[BDEVNAME_SIZE];
+
+ notify_get(c);
+ notify_var(c, "UUID=%pU", ca->sb.disk_uuid.b);
+ notify_var(c, "BLOCKDEV=%s", bdevname(ca->disk_sb.bdev, buf));
+}
+
+static void notify_put(struct cache_set *c)
+{
+ struct kobj_uevent_env *env = &c->uevent_env;
+
+ env->envp[env->envp_idx] = NULL;
+ kobject_uevent_env(&c->kobj, KOBJ_CHANGE, env->envp);
+ mutex_unlock(&c->uevent_lock);
+}
+
+void bch_notify_cache_set_read_write(struct cache_set *c)
+{
+ notify_get(c);
+ notify_var(c, "STATE=active");
+ notify_put(c);
+}
+
+void bch_notify_cache_set_read_only(struct cache_set *c)
+{
+ notify_get(c);
+ notify_var(c, "STATE=readonly");
+ notify_put(c);
+}
+
+void bch_notify_cache_set_stopped(struct cache_set *c)
+{
+ notify_get(c);
+ notify_var(c, "STATE=stopped");
+ notify_put(c);
+}
+
+void bch_notify_cache_read_write(struct cache *ca)
+{
+ struct cache_set *c = ca->set;
+
+ notify_get_cache(ca);
+ notify_var(c, "STATE=active");
+ notify_put(c);
+}
+
+void bch_notify_cache_read_only(struct cache *ca)
+{
+ struct cache_set *c = ca->set;
+
+ notify_get_cache(ca);
+ notify_var(c, "STATE=readonly");
+ notify_put(c);
+}
+
+void bch_notify_cache_added(struct cache *ca)
+{
+ struct cache_set *c = ca->set;
+
+ notify_get_cache(ca);
+ notify_var(c, "STATE=removing");
+ notify_put(c);
+}
+
+void bch_notify_cache_removing(struct cache *ca)
+{
+ struct cache_set *c = ca->set;
+
+ notify_get_cache(ca);
+ notify_var(c, "STATE=removing");
+ notify_put(c);
+}
+
+void bch_notify_cache_removed(struct cache *ca)
+{
+ struct cache_set *c = ca->set;
+
+ notify_get_cache(ca);
+ notify_var(c, "STATE=removed");
+ notify_put(c);
+}
+
+void bch_notify_cache_error(struct cache *ca, bool fatal, const char *m)
+{
+ struct cache_set *c = ca->set;
+
+ notify_get_cache(ca);
+ notify_var(c, "STATE=error");
+ notify_var(c, "FATAL=%d", fatal);
+ notify_var(c, "MESSAGE=%s", m);
+ notify_put(c);
+}
diff --git a/drivers/md/bcache/notify.h b/drivers/md/bcache/notify.h
new file mode 100644
index 000000000000..b915feff3c00
--- /dev/null
+++ b/drivers/md/bcache/notify.h
@@ -0,0 +1,21 @@
+/*
+ * Code for sending uevent notifications to user-space.
+ *
+ * Copyright 2015 Datera, Inc.
+ */
+
+#ifndef _NOTIFY_H
+#define _NOTIFY_H
+
+void bch_notify_cache_set_read_write(struct cache_set *);
+void bch_notify_cache_set_read_only(struct cache_set *);
+void bch_notify_cache_set_stopped(struct cache_set *);
+
+void bch_notify_cache_read_write(struct cache *);
+void bch_notify_cache_read_only(struct cache *);
+void bch_notify_cache_added(struct cache *);
+void bch_notify_cache_removing(struct cache *);
+void bch_notify_cache_removed(struct cache *);
+void bch_notify_cache_error(struct cache *, bool, const char *);
+
+#endif /* _NOTIFY_H */
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index b7e9b48616bd..d0dd1231471a 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -18,6 +18,7 @@
#include "keylist.h"
#include "move.h"
#include "movinggc.h"
+#include "notify.h"
#include "stats.h"
#include "super.h"
#include "tier.h"
@@ -671,6 +672,8 @@ static void bch_cache_set_read_only(struct cache_set *c)
c->journal.work.work.func(&c->journal.work.work);
}
+ bch_notify_cache_set_read_only(c);
+
trace_bcache_cache_set_read_only_done(c);
}
@@ -741,6 +744,8 @@ static void cache_set_free(struct closure *cl)
list_del(&c->list);
mutex_unlock(&bch_register_lock);
+ bch_notify_cache_set_stopped(c);
+
pr_info("Cache set %pU unregistered", c->sb.set_uuid.b);
closure_debug_destroy(&c->cl);
@@ -937,6 +942,8 @@ static const char *bch_cache_set_alloc(struct cache_sb *sb,
c->bucket_reserve_percent = 10;
c->sector_reserve_percent = 20;
+ mutex_init(&c->uevent_lock);
+
c->search = mempool_create_slab_pool(32, bch_search_cache);
if (!c->search)
goto err;
@@ -1161,6 +1168,8 @@ static const char *run_cache_set(struct cache_set *c)
closure_put(&c->caching);
+ bch_notify_cache_set_read_write(c);
+
return NULL;
err:
closure_sync(&cl);
@@ -1262,6 +1271,9 @@ static void __bch_cache_read_only(struct cache *ca)
* This will suspend the running task until outstanding writes complete.
*/
bch_await_scheduled_data_writes(ca);
+
+ bch_notify_cache_read_only(ca);
+
/*
* Device data write barrier -- no non-meta-data writes should
* occur after this point. However, writes to btree buckets,
@@ -1386,6 +1398,8 @@ const char *bch_cache_read_write(struct cache *ca)
wake_up_process(ca->set->tiering_read);
+ bch_notify_cache_read_write(ca);
+
return err;
}
@@ -1516,6 +1530,8 @@ static void bch_cache_remove_work(struct work_struct *work)
char buf[BDEVNAME_SIZE];
bool force = (test_bit(CACHE_DEV_FORCE_REMOVE, &ca->flags));
+ bch_notify_cache_removing(ca);
+
mutex_lock(&bch_register_lock);
allmi = cache_member_info_get(c);
mi = &allmi->m[ca->sb.nr_this_dev];
@@ -1691,6 +1707,9 @@ static void bch_cache_remove_work(struct work_struct *work)
mutex_lock(&bch_register_lock);
bch_cache_stop(ca);
mutex_unlock(&bch_register_lock);
+
+ bch_notify_cache_removed(ca);
+
return;
}
@@ -1997,6 +2016,8 @@ have_slot:
if (bch_cache_journal_alloc(ca))
goto err_put;
+ bch_notify_cache_added(ca);
+
err = bch_cache_read_write(ca);
if (err)
goto err_put;