Skip to content

Commit 0bfd3e1

Browse files
author
Al Viro
committed
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>
1 parent 7f71d6e commit 0bfd3e1

1 file changed

Lines changed: 18 additions & 13 deletions

File tree

fs/ufs/cylinder.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* Read cylinder group into cache. The memory space for ufs_cg_private_info
2727
* structure is already allocated during ufs_read_super.
2828
*/
29-
static void ufs_read_cylinder (struct super_block * sb,
29+
static bool ufs_read_cylinder(struct super_block *sb,
3030
unsigned cgno, unsigned bitmap_nr)
3131
{
3232
struct ufs_sb_info * sbi = UFS_SB(sb);
@@ -46,9 +46,11 @@ static void ufs_read_cylinder (struct super_block * sb,
4646
* We have already the first fragment of cylinder group block in buffer
4747
*/
4848
UCPI_UBH(ucpi)->bh[0] = sbi->s_ucg[cgno];
49-
for (i = 1; i < UCPI_UBH(ucpi)->count; i++)
50-
if (!(UCPI_UBH(ucpi)->bh[i] = sb_bread(sb, UCPI_UBH(ucpi)->fragment + i)))
49+
for (i = 1; i < UCPI_UBH(ucpi)->count; i++) {
50+
UCPI_UBH(ucpi)->bh[i] = sb_bread(sb, UCPI_UBH(ucpi)->fragment + i);
51+
if (!UCPI_UBH(ucpi)->bh[i])
5152
goto failed;
53+
}
5254
sbi->s_cgno[bitmap_nr] = cgno;
5355

5456
ucpi->c_cgx = fs32_to_cpu(sb, ucg->cg_cgx);
@@ -67,13 +69,14 @@ static void ufs_read_cylinder (struct super_block * sb,
6769
ucpi->c_clusteroff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clusteroff);
6870
ucpi->c_nclusterblks = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_nclusterblks);
6971
UFSD("EXIT\n");
70-
return;
72+
return true;
7173

7274
failed:
7375
for (j = 1; j < i; j++)
74-
brelse (sbi->s_ucg[j]);
76+
brelse(UCPI_UBH(ucpi)->bh[j]);
7577
sbi->s_cgno[bitmap_nr] = UFS_CGNO_EMPTY;
7678
ufs_error (sb, "ufs_read_cylinder", "can't read cylinder group block %u", cgno);
79+
return false;
7780
}
7881

7982
/*
@@ -156,15 +159,14 @@ struct ufs_cg_private_info * ufs_load_cylinder (
156159
UFSD("EXIT (FAILED)\n");
157160
return NULL;
158161
}
159-
else {
160-
UFSD("EXIT\n");
161-
return sbi->s_ucpi[cgno];
162-
}
163162
} else {
164-
ufs_read_cylinder (sb, cgno, cgno);
165-
UFSD("EXIT\n");
166-
return sbi->s_ucpi[cgno];
163+
if (unlikely(!ufs_read_cylinder (sb, cgno, cgno))) {
164+
UFSD("EXIT (FAILED)\n");
165+
return NULL;
166+
}
167167
}
168+
UFSD("EXIT\n");
169+
return sbi->s_ucpi[cgno];
168170
}
169171
/*
170172
* 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 (
195197
sbi->s_ucpi[j] = sbi->s_ucpi[j-1];
196198
}
197199
sbi->s_ucpi[0] = ucpi;
198-
ufs_read_cylinder (sb, cgno, 0);
200+
if (unlikely(!ufs_read_cylinder (sb, cgno, 0))) {
201+
UFSD("EXIT (FAILED)\n");
202+
return NULL;
203+
}
199204
}
200205
UFSD("EXIT\n");
201206
return sbi->s_ucpi[0];

0 commit comments

Comments
 (0)