summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-07-10 21:25:02 -0700
committerKent Overstreet <kmo@daterainc.com>2013-07-12 00:22:47 -0700
commitc9502ea4424b31728703d113fc6b30bfead14633 (patch)
tree5ce21818de392f7873708f8db65b031223b04c2e /drivers
parent54d12f2b4fd0f218590d1490b41a18d0e2328a9a (diff)
bcache: Fix a sysfs splat on shutdown
If we stopped a bcache device when we were already detaching (or something like that), bcache_device_unlink() would try to remove a symlink from sysfs that was already gone because the bcache dev kobject had already been removed from sysfs. So keep track of whether we've removed stuff from sysfs. Signed-off-by: Kent Overstreet <kmo@daterainc.com> Cc: linux-stable <stable@vger.kernel.org> # >= v3.10
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/bcache/bcache.h1
-rw-r--r--drivers/md/bcache/super.c11
2 files changed, 11 insertions, 1 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 342ba86c6e4..68f1ded81ae 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -434,6 +434,7 @@ struct bcache_device {
/* If nonzero, we're detaching/unregistering from cache set */
atomic_t detaching;
+ int flush_done;
uint64_t nr_stripes;
unsigned stripe_size_bits;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 728fdc673f3..7a1dcdb2536 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -706,7 +706,8 @@ static void bcache_device_detach(struct bcache_device *d)
atomic_set(&d->detaching, 0);
}
- bcache_device_unlink(d);
+ if (!d->flush_done)
+ bcache_device_unlink(d);
d->c->devices[d->id] = NULL;
closure_put(&d->c->caching);
@@ -1055,6 +1056,14 @@ static void cached_dev_flush(struct closure *cl)
struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
struct bcache_device *d = &dc->disk;
+ mutex_lock(&bch_register_lock);
+ d->flush_done = 1;
+
+ if (d->c)
+ bcache_device_unlink(d);
+
+ mutex_unlock(&bch_register_lock);
+
bch_cache_accounting_destroy(&dc->accounting);
kobject_del(&d->kobj);