diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2019-12-09 14:08:39 +0300 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2020-01-21 04:12:40 +0300 |
commit | 6092b6be304494e311b65935f5e09b510cbd57cc (patch) | |
tree | ed8b47c26582d547ec3bdcd65e27f531a96b6b39 /fs | |
parent | e6160e469f56a23cb69e1dc37aa0d895bf29ac24 (diff) | |
download | linux-6092b6be304494e311b65935f5e09b510cbd57cc.tar.xz |
fs/adfs: map: break up adfs_read_map()
Split up adfs_read_map() into separate helpers to layout the map,
read the map, and release the map buffers.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/adfs/map.c | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/fs/adfs/map.c b/fs/adfs/map.c index c322d37e8f91..4b677cd5d015 100644 --- a/fs/adfs/map.c +++ b/fs/adfs/map.c @@ -331,12 +331,63 @@ static int adfs_checkmap(struct super_block *sb, struct adfs_discmap *dm) return crosscheck == 0xff && zonecheck; } +/* + * Layout the map - the first zone contains a copy of the disc record, + * and the last zone must be limited to the size of the filesystem. + */ +static void adfs_map_layout(struct adfs_discmap *dm, unsigned int nzones, + struct adfs_discrecord *dr) +{ + unsigned int zone, zone_size; + u64 size; + + zone_size = (8 << dr->log2secsize) - le16_to_cpu(dr->zone_spare); + + dm[0].dm_bh = NULL; + dm[0].dm_startblk = 0; + dm[0].dm_startbit = ADFS_DR_SIZE_BITS; + dm[0].dm_endbit = zone_size; + + for (zone = 1; zone < nzones; zone++) { + dm[zone].dm_bh = NULL; + dm[zone].dm_startblk = zone * zone_size - ADFS_DR_SIZE_BITS; + dm[zone].dm_startbit = 0; + dm[zone].dm_endbit = zone_size; + } + + size = adfs_disc_size(dr) >> dr->log2bpmb; + size -= (nzones - 1) * zone_size - ADFS_DR_SIZE_BITS; + dm[nzones - 1].dm_endbit = size; +} + +static int adfs_map_read(struct adfs_discmap *dm, struct super_block *sb, + unsigned int map_addr, unsigned int nzones) +{ + unsigned int zone; + + for (zone = 0; zone < nzones; zone++) { + dm[zone].dm_bh = sb_bread(sb, map_addr + zone); + if (!dm[zone].dm_bh) + return -EIO; + } + + return 0; +} + +static void adfs_map_relse(struct adfs_discmap *dm, unsigned int nzones) +{ + unsigned int zone; + + for (zone = 0; zone < nzones; zone++) + brelse(dm[zone].dm_bh); +} + struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_discrecord *dr) { + struct adfs_sb_info *asb = ADFS_SB(sb); struct adfs_discmap *dm; unsigned int map_addr, zone_size, nzones; - int i, zone; - struct adfs_sb_info *asb = ADFS_SB(sb); + int ret; nzones = asb->s_map_size; zone_size = (8 << dr->log2secsize) - le16_to_cpu(dr->zone_spare); @@ -352,34 +403,21 @@ struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_discrecor return ERR_PTR(-ENOMEM); } - for (zone = 0; zone < nzones; zone++, map_addr++) { - dm[zone].dm_startbit = 0; - dm[zone].dm_endbit = zone_size; - dm[zone].dm_startblk = zone * zone_size - ADFS_DR_SIZE_BITS; - dm[zone].dm_bh = sb_bread(sb, map_addr); + adfs_map_layout(dm, nzones, dr); - if (!dm[zone].dm_bh) { - adfs_error(sb, "unable to read map"); - goto error_free; - } + ret = adfs_map_read(dm, sb, map_addr, nzones); + if (ret) { + adfs_error(sb, "unable to read map"); + goto error_free; } - /* adjust the limits for the first and last map zones */ - i = zone - 1; - dm[0].dm_startblk = 0; - dm[0].dm_startbit = ADFS_DR_SIZE_BITS; - dm[i].dm_endbit = (adfs_disc_size(dr) >> dr->log2bpmb) + - (ADFS_DR_SIZE_BITS - i * zone_size); - if (adfs_checkmap(sb, dm)) return dm; adfs_error(sb, "map corrupted"); error_free: - while (--zone >= 0) - brelse(dm[zone].dm_bh); - + adfs_map_relse(dm, nzones); kfree(dm); return ERR_PTR(-EIO); } |