mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 16:53:49 +00:00
ufs: fix ufs_read_cylinder() failure handling
1) ufs_load_cylinder() should return NULL on ufs_read_cylinder() failures. ufs_error() is not enough. As it is, IO failure on attempt to read a part of cylinder group metadata is likely to end up with an oops. 2) we drop the wrong buffer heads when undoing sb_bread() on IO failure halfway through the read - we need to brelse() what we've got from sb_bread(), TYVM... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
7f71d6e346
commit
0bfd3e1078
@ -26,7 +26,7 @@
|
||||
* Read cylinder group into cache. The memory space for ufs_cg_private_info
|
||||
* structure is already allocated during ufs_read_super.
|
||||
*/
|
||||
static void ufs_read_cylinder (struct super_block * sb,
|
||||
static bool ufs_read_cylinder(struct super_block *sb,
|
||||
unsigned cgno, unsigned bitmap_nr)
|
||||
{
|
||||
struct ufs_sb_info * sbi = UFS_SB(sb);
|
||||
@ -46,9 +46,11 @@ static void ufs_read_cylinder (struct super_block * sb,
|
||||
* We have already the first fragment of cylinder group block in buffer
|
||||
*/
|
||||
UCPI_UBH(ucpi)->bh[0] = sbi->s_ucg[cgno];
|
||||
for (i = 1; i < UCPI_UBH(ucpi)->count; i++)
|
||||
if (!(UCPI_UBH(ucpi)->bh[i] = sb_bread(sb, UCPI_UBH(ucpi)->fragment + i)))
|
||||
for (i = 1; i < UCPI_UBH(ucpi)->count; i++) {
|
||||
UCPI_UBH(ucpi)->bh[i] = sb_bread(sb, UCPI_UBH(ucpi)->fragment + i);
|
||||
if (!UCPI_UBH(ucpi)->bh[i])
|
||||
goto failed;
|
||||
}
|
||||
sbi->s_cgno[bitmap_nr] = cgno;
|
||||
|
||||
ucpi->c_cgx = fs32_to_cpu(sb, ucg->cg_cgx);
|
||||
@ -67,13 +69,14 @@ static void ufs_read_cylinder (struct super_block * sb,
|
||||
ucpi->c_clusteroff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clusteroff);
|
||||
ucpi->c_nclusterblks = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_nclusterblks);
|
||||
UFSD("EXIT\n");
|
||||
return;
|
||||
return true;
|
||||
|
||||
failed:
|
||||
for (j = 1; j < i; j++)
|
||||
brelse (sbi->s_ucg[j]);
|
||||
brelse(UCPI_UBH(ucpi)->bh[j]);
|
||||
sbi->s_cgno[bitmap_nr] = UFS_CGNO_EMPTY;
|
||||
ufs_error (sb, "ufs_read_cylinder", "can't read cylinder group block %u", cgno);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -156,15 +159,14 @@ struct ufs_cg_private_info * ufs_load_cylinder (
|
||||
UFSD("EXIT (FAILED)\n");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
UFSD("EXIT\n");
|
||||
return sbi->s_ucpi[cgno];
|
||||
}
|
||||
} else {
|
||||
ufs_read_cylinder (sb, cgno, cgno);
|
||||
UFSD("EXIT\n");
|
||||
return sbi->s_ucpi[cgno];
|
||||
if (unlikely(!ufs_read_cylinder (sb, cgno, cgno))) {
|
||||
UFSD("EXIT (FAILED)\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
UFSD("EXIT\n");
|
||||
return sbi->s_ucpi[cgno];
|
||||
}
|
||||
/*
|
||||
* Cylinder group number cg is in cache but it was not last used,
|
||||
@ -195,7 +197,10 @@ struct ufs_cg_private_info * ufs_load_cylinder (
|
||||
sbi->s_ucpi[j] = sbi->s_ucpi[j-1];
|
||||
}
|
||||
sbi->s_ucpi[0] = ucpi;
|
||||
ufs_read_cylinder (sb, cgno, 0);
|
||||
if (unlikely(!ufs_read_cylinder (sb, cgno, 0))) {
|
||||
UFSD("EXIT (FAILED)\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
UFSD("EXIT\n");
|
||||
return sbi->s_ucpi[0];
|
||||
|
Loading…
Reference in New Issue
Block a user