ANDROID: dm: verity-fec: add sysfs attribute fec/corrected
authorSami Tolvanen <samitolvanen@google.com>
Wed, 30 Mar 2016 21:10:13 +0000 (14:10 -0700)
committerAmit Pundir <amit.pundir@linaro.org>
Mon, 18 Dec 2017 15:41:22 +0000 (21:11 +0530)
Add a sysfs entry that allows user space to determine whether dm-verity
has come across correctable errors on the underlying block device.

Bug: 22655252
Bug: 27928374
Change-Id: I80547a2aa944af2fb9ffde002650482877ade31b
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
(cherry picked from commit 7911fad5f0a2cf5afc2215657219a21e6630e001)

[AmitP: Folded following android-4.9 commit changes into this patch
        3278f53e4658 ("ANDROID: dm verity fec: add missing release from fec_ktype")]
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
drivers/md/dm-verity-fec.c
drivers/md/dm-verity-fec.h

index e13f90832b6b54256f88d45ba30cee16660f58ef..776a4f77f76ce6031d54401a23dd39ca89ca6524 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "dm-verity-fec.h"
 #include <linux/math64.h>
+#include <linux/sysfs.h>
 
 #define DM_MSG_PREFIX  "verity-fec"
 
@@ -175,9 +176,11 @@ error:
        if (r < 0 && neras)
                DMERR_LIMIT("%s: FEC %llu: failed to correct: %d",
                            v->data_dev->name, (unsigned long long)rsb, r);
-       else if (r > 0)
+       else if (r > 0) {
                DMWARN_LIMIT("%s: FEC %llu: corrected %d errors",
                             v->data_dev->name, (unsigned long long)rsb, r);
+               atomic_add_unless(&v->fec->corrected, 1, INT_MAX);
+       }
 
        return r;
 }
@@ -545,6 +548,7 @@ unsigned verity_fec_status_table(struct dm_verity *v, unsigned sz,
 void verity_fec_dtr(struct dm_verity *v)
 {
        struct dm_verity_fec *f = v->fec;
+       struct kobject *kobj = &f->kobj_holder.kobj;
 
        if (!verity_fec_is_enabled(v))
                goto out;
@@ -561,6 +565,12 @@ void verity_fec_dtr(struct dm_verity *v)
 
        if (f->dev)
                dm_put_device(v->ti, f->dev);
+
+       if (kobj->state_initialized) {
+               kobject_put(kobj);
+               wait_for_completion(dm_get_completion_from_kobject(kobj));
+       }
+
 out:
        kfree(f);
        v->fec = NULL;
@@ -649,6 +659,28 @@ int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
        return 0;
 }
 
+static ssize_t corrected_show(struct kobject *kobj, struct kobj_attribute *attr,
+                             char *buf)
+{
+       struct dm_verity_fec *f = container_of(kobj, struct dm_verity_fec,
+                                              kobj_holder.kobj);
+
+       return sprintf(buf, "%d\n", atomic_read(&f->corrected));
+}
+
+static struct kobj_attribute attr_corrected = __ATTR_RO(corrected);
+
+static struct attribute *fec_attrs[] = {
+       &attr_corrected.attr,
+       NULL
+};
+
+static struct kobj_type fec_ktype = {
+       .sysfs_ops = &kobj_sysfs_ops,
+       .default_attrs = fec_attrs,
+       .release = dm_kobject_release
+};
+
 /*
  * Allocate dm_verity_fec for v->fec. Must be called before verity_fec_ctr.
  */
@@ -672,8 +704,10 @@ int verity_fec_ctr_alloc(struct dm_verity *v)
  */
 int verity_fec_ctr(struct dm_verity *v)
 {
+       int r;
        struct dm_verity_fec *f = v->fec;
        struct dm_target *ti = v->ti;
+       struct mapped_device *md = dm_table_get_md(ti->table);
        u64 hash_blocks;
 
        if (!verity_fec_is_enabled(v)) {
@@ -681,6 +715,16 @@ int verity_fec_ctr(struct dm_verity *v)
                return 0;
        }
 
+       /* Create a kobject and sysfs attributes */
+       init_completion(&f->kobj_holder.completion);
+
+       r = kobject_init_and_add(&f->kobj_holder.kobj, &fec_ktype,
+                                &disk_to_dev(dm_disk(md))->kobj, "%s", "fec");
+       if (r) {
+               ti->error = "Cannot create kobject";
+               return r;
+       }
+
        /*
         * FEC is computed over data blocks, possible metadata, and
         * hash blocks. In other words, FEC covers total of fec_blocks
index bb31ce87a933b80d11140f31607f804ff81d209a..4db0cae262eb7ccc489ee3ce44fbde7660626fdc 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef DM_VERITY_FEC_H
 #define DM_VERITY_FEC_H
 
+#include "dm.h"
+#include "dm-core.h"
 #include "dm-verity.h"
 #include <linux/rslib.h>
 
@@ -51,6 +53,8 @@ struct dm_verity_fec {
        mempool_t *extra_pool;  /* mempool for extra buffers */
        mempool_t *output_pool; /* mempool for output */
        struct kmem_cache *cache;       /* cache for buffers */
+       atomic_t corrected;             /* corrected errors */
+       struct dm_kobject_holder kobj_holder;   /* for sysfs attributes */
 };
 
 /* per-bio data */