dm raid1: report fault status

This patch adds extra information to the mirror status output, so that
it can be determined which device(s) have failed. For each mirror device,
a character is printed indicating the most severe error encountered. The
characters are:
* A => Alive - No failures
* D => Dead - A write failure occurred leaving mirror out-of-sync
* S => Sync - A sychronization failure occurred, mirror out-of-sync
* R => Read - A read failure occurred, mirror data unaffected
This allows userspace to properly reconfigure the mirror set.

Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

authored by Jonathan Brassow and committed by Alasdair G Kergon af195ac8 06386bbf

+36 -8
+36 -8
drivers/md/dm-raid1.c
··· 1781 1781 rh_start_recovery(&ms->rh); 1782 1782 } 1783 1783 1784 + /* 1785 + * device_status_char 1786 + * @m: mirror device/leg we want the status of 1787 + * 1788 + * We return one character representing the most severe error 1789 + * we have encountered. 1790 + * A => Alive - No failures 1791 + * D => Dead - A write failure occurred leaving mirror out-of-sync 1792 + * S => Sync - A sychronization failure occurred, mirror out-of-sync 1793 + * R => Read - A read failure occurred, mirror data unaffected 1794 + * 1795 + * Returns: <char> 1796 + */ 1797 + static char device_status_char(struct mirror *m) 1798 + { 1799 + if (!atomic_read(&(m->error_count))) 1800 + return 'A'; 1801 + 1802 + return (test_bit(DM_RAID1_WRITE_ERROR, &(m->error_type))) ? 'D' : 1803 + (test_bit(DM_RAID1_SYNC_ERROR, &(m->error_type))) ? 'S' : 1804 + (test_bit(DM_RAID1_READ_ERROR, &(m->error_type))) ? 'R' : 'U'; 1805 + } 1806 + 1807 + 1784 1808 static int mirror_status(struct dm_target *ti, status_type_t type, 1785 1809 char *result, unsigned int maxlen) 1786 1810 { 1787 1811 unsigned int m, sz = 0; 1788 1812 struct mirror_set *ms = (struct mirror_set *) ti->private; 1813 + struct dirty_log *log = ms->rh.log; 1814 + char buffer[ms->nr_mirrors + 1]; 1789 1815 1790 1816 switch (type) { 1791 1817 case STATUSTYPE_INFO: 1792 1818 DMEMIT("%d ", ms->nr_mirrors); 1793 - for (m = 0; m < ms->nr_mirrors; m++) 1819 + for (m = 0; m < ms->nr_mirrors; m++) { 1794 1820 DMEMIT("%s ", ms->mirror[m].dev->name); 1821 + buffer[m] = device_status_char(&(ms->mirror[m])); 1822 + } 1823 + buffer[m] = '\0'; 1795 1824 1796 - DMEMIT("%llu/%llu 0 ", 1797 - (unsigned long long)ms->rh.log->type-> 1798 - get_sync_count(ms->rh.log), 1799 - (unsigned long long)ms->nr_regions); 1825 + DMEMIT("%llu/%llu 1 %s ", 1826 + (unsigned long long)log->type->get_sync_count(ms->rh.log), 1827 + (unsigned long long)ms->nr_regions, buffer); 1800 1828 1801 - sz += ms->rh.log->type->status(ms->rh.log, type, result+sz, maxlen-sz); 1829 + sz += log->type->status(ms->rh.log, type, result+sz, maxlen-sz); 1802 1830 1803 1831 break; 1804 1832 1805 1833 case STATUSTYPE_TABLE: 1806 - sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); 1834 + sz = log->type->status(ms->rh.log, type, result, maxlen); 1807 1835 1808 1836 DMEMIT("%d", ms->nr_mirrors); 1809 1837 for (m = 0; m < ms->nr_mirrors; m++) ··· 1847 1819 1848 1820 static struct target_type mirror_target = { 1849 1821 .name = "mirror", 1850 - .version = {1, 0, 3}, 1822 + .version = {1, 0, 20}, 1851 1823 .module = THIS_MODULE, 1852 1824 .ctr = mirror_ctr, 1853 1825 .dtr = mirror_dtr,