]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/md/bcache/super.c
bcache: avoid flushing btree node in cache_set_flush() if io disabled
[linux.git] / drivers / md / bcache / super.c
index 1b63ac876169ed02aab084a0e6bb69f28e823974..dc6702c2c4b64371b4f0bc2d87ff0b50e01a380d 100644 (file)
@@ -1437,8 +1437,6 @@ int bch_flash_dev_create(struct cache_set *c, uint64_t size)
 
 bool bch_cached_dev_error(struct cached_dev *dc)
 {
-       struct cache_set *c;
-
        if (!dc || test_bit(BCACHE_DEV_CLOSING, &dc->disk.flags))
                return false;
 
@@ -1449,21 +1447,6 @@ bool bch_cached_dev_error(struct cached_dev *dc)
        pr_err("stop %s: too many IO errors on backing device %s\n",
                dc->disk.disk->disk_name, dc->backing_dev_name);
 
-       /*
-        * If the cached device is still attached to a cache set,
-        * even dc->io_disable is true and no more I/O requests
-        * accepted, cache device internal I/O (writeback scan or
-        * garbage collection) may still prevent bcache device from
-        * being stopped. So here CACHE_SET_IO_DISABLE should be
-        * set to c->flags too, to make the internal I/O to cache
-        * device rejected and stopped immediately.
-        * If c is NULL, that means the bcache device is not attached
-        * to any cache set, then no CACHE_SET_IO_DISABLE bit to set.
-        */
-       c = dc->disk.c;
-       if (c && test_and_set_bit(CACHE_SET_IO_DISABLE, &c->flags))
-               pr_info("CACHE_SET_IO_DISABLE already set");
-
        bcache_device_stop(&dc->disk);
        return true;
 }
@@ -1564,19 +1547,23 @@ static void cache_set_flush(struct closure *cl)
        kobject_put(&c->internal);
        kobject_del(&c->kobj);
 
-       if (c->gc_thread)
+       if (!IS_ERR_OR_NULL(c->gc_thread))
                kthread_stop(c->gc_thread);
 
        if (!IS_ERR_OR_NULL(c->root))
                list_add(&c->root->list, &c->btree_cache);
 
-       /* Should skip this if we're unregistering because of an error */
-       list_for_each_entry(b, &c->btree_cache, list) {
-               mutex_lock(&b->write_lock);
-               if (btree_node_dirty(b))
-                       __bch_btree_node_write(b, NULL);
-               mutex_unlock(&b->write_lock);
-       }
+       /*
+        * Avoid flushing cached nodes if cache set is retiring
+        * due to too many I/O errors detected.
+        */
+       if (!test_bit(CACHE_SET_IO_DISABLE, &c->flags))
+               list_for_each_entry(b, &c->btree_cache, list) {
+                       mutex_lock(&b->write_lock);
+                       if (btree_node_dirty(b))
+                               __bch_btree_node_write(b, NULL);
+                       mutex_unlock(&b->write_lock);
+               }
 
        for_each_cache(ca, c, i)
                if (ca->alloc_thread)