udf: Cleanup volume descriptor sequence processing
Cleanup processing of volume descriptor sequence so that it is more readable, make code handle errors (e.g. media problems) better. Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
d0db181c07
commit
c0eb31ed13
135
fs/udf/super.c
135
fs/udf/super.c
|
@ -85,16 +85,12 @@ static int udf_remount_fs(struct super_block *, int *, char *);
|
||||||
static int udf_check_valid(struct super_block *, int, int);
|
static int udf_check_valid(struct super_block *, int, int);
|
||||||
static int udf_vrs(struct super_block *sb, int silent);
|
static int udf_vrs(struct super_block *sb, int silent);
|
||||||
static int udf_load_partition(struct super_block *, kernel_lb_addr *);
|
static int udf_load_partition(struct super_block *, kernel_lb_addr *);
|
||||||
static int udf_load_logicalvol(struct super_block *, struct buffer_head *,
|
|
||||||
kernel_lb_addr *);
|
|
||||||
static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
|
static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
|
||||||
static void udf_find_anchor(struct super_block *);
|
static void udf_find_anchor(struct super_block *);
|
||||||
static int udf_find_fileset(struct super_block *, kernel_lb_addr *,
|
static int udf_find_fileset(struct super_block *, kernel_lb_addr *,
|
||||||
kernel_lb_addr *);
|
kernel_lb_addr *);
|
||||||
static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
|
|
||||||
static void udf_load_fileset(struct super_block *, struct buffer_head *,
|
static void udf_load_fileset(struct super_block *, struct buffer_head *,
|
||||||
kernel_lb_addr *);
|
kernel_lb_addr *);
|
||||||
static int udf_load_partdesc(struct super_block *, struct buffer_head *);
|
|
||||||
static void udf_open_lvid(struct super_block *);
|
static void udf_open_lvid(struct super_block *);
|
||||||
static void udf_close_lvid(struct super_block *);
|
static void udf_close_lvid(struct super_block *);
|
||||||
static unsigned int udf_count_free(struct super_block *);
|
static unsigned int udf_count_free(struct super_block *);
|
||||||
|
@ -935,11 +931,18 @@ static int udf_find_fileset(struct super_block *sb,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
|
static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
|
||||||
{
|
{
|
||||||
struct primaryVolDesc *pvoldesc;
|
struct primaryVolDesc *pvoldesc;
|
||||||
struct ustr instr;
|
struct ustr instr;
|
||||||
struct ustr outstr;
|
struct ustr outstr;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
uint16_t ident;
|
||||||
|
|
||||||
|
bh = udf_read_tagged(sb, block, block, &ident);
|
||||||
|
if (!bh)
|
||||||
|
return 1;
|
||||||
|
BUG_ON(ident != TAG_IDENT_PVD);
|
||||||
|
|
||||||
pvoldesc = (struct primaryVolDesc *)bh->b_data;
|
pvoldesc = (struct primaryVolDesc *)bh->b_data;
|
||||||
|
|
||||||
|
@ -965,6 +968,9 @@ static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
|
||||||
if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128))
|
if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128))
|
||||||
if (udf_CS0toUTF8(&outstr, &instr))
|
if (udf_CS0toUTF8(&outstr, &instr))
|
||||||
udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
|
udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
|
||||||
|
|
||||||
|
brelse(bh);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
|
static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
|
||||||
|
@ -1018,16 +1024,27 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
|
static int udf_load_partdesc(struct super_block *sb, sector_t block)
|
||||||
{
|
{
|
||||||
|
struct buffer_head *bh;
|
||||||
struct partitionHeaderDesc *phd;
|
struct partitionHeaderDesc *phd;
|
||||||
struct partitionDesc *p = (struct partitionDesc *)bh->b_data;
|
struct partitionDesc *p;
|
||||||
struct udf_part_map *map;
|
struct udf_part_map *map;
|
||||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int i;
|
int i;
|
||||||
u16 partitionNumber = le16_to_cpu(p->partitionNumber);
|
uint16_t partitionNumber;
|
||||||
|
uint16_t ident;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
bh = udf_read_tagged(sb, block, block, &ident);
|
||||||
|
if (!bh)
|
||||||
|
return 1;
|
||||||
|
if (ident != TAG_IDENT_PD)
|
||||||
|
goto out_bh;
|
||||||
|
|
||||||
|
p = (struct partitionDesc *)bh->b_data;
|
||||||
|
partitionNumber = le16_to_cpu(p->partitionNumber);
|
||||||
for (i = 0; i < sbi->s_partitions; i++) {
|
for (i = 0; i < sbi->s_partitions; i++) {
|
||||||
map = &sbi->s_partmaps[i];
|
map = &sbi->s_partmaps[i];
|
||||||
udf_debug("Searching map: (%d == %d)\n",
|
udf_debug("Searching map: (%d == %d)\n",
|
||||||
|
@ -1040,7 +1057,7 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
|
||||||
if (!found) {
|
if (!found) {
|
||||||
udf_debug("Partition (%d) not found in partition map\n",
|
udf_debug("Partition (%d) not found in partition map\n",
|
||||||
partitionNumber);
|
partitionNumber);
|
||||||
return 0;
|
goto out_bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */
|
map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */
|
||||||
|
@ -1062,7 +1079,7 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
|
||||||
|
|
||||||
if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
|
if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
|
||||||
strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
|
strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
|
||||||
return 0;
|
goto out_bh;
|
||||||
|
|
||||||
phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
|
phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
|
||||||
if (phd->unallocSpaceTable.extLength) {
|
if (phd->unallocSpaceTable.extLength) {
|
||||||
|
@ -1076,7 +1093,8 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
|
||||||
if (!map->s_uspace.s_table) {
|
if (!map->s_uspace.s_table) {
|
||||||
udf_debug("cannot load unallocSpaceTable (part %d)\n",
|
udf_debug("cannot load unallocSpaceTable (part %d)\n",
|
||||||
i);
|
i);
|
||||||
return 1;
|
ret = 1;
|
||||||
|
goto out_bh;
|
||||||
}
|
}
|
||||||
map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
|
map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
|
||||||
udf_debug("unallocSpaceTable (part %d) @ %ld\n",
|
udf_debug("unallocSpaceTable (part %d) @ %ld\n",
|
||||||
|
@ -1110,7 +1128,8 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
|
||||||
map->s_fspace.s_table = udf_iget(sb, loc);
|
map->s_fspace.s_table = udf_iget(sb, loc);
|
||||||
if (!map->s_fspace.s_table) {
|
if (!map->s_fspace.s_table) {
|
||||||
udf_debug("cannot load freedSpaceTable (part %d)\n", i);
|
udf_debug("cannot load freedSpaceTable (part %d)\n", i);
|
||||||
return 1;
|
ret = 1;
|
||||||
|
goto out_bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
|
map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
|
||||||
|
@ -1132,10 +1151,12 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
out_bh:
|
||||||
|
brelse(bh);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
|
static int udf_load_logicalvol(struct super_block *sb, sector_t block,
|
||||||
kernel_lb_addr *fileset)
|
kernel_lb_addr *fileset)
|
||||||
{
|
{
|
||||||
struct logicalVolDesc *lvd;
|
struct logicalVolDesc *lvd;
|
||||||
|
@ -1143,12 +1164,21 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||||
struct genericPartitionMap *gpm;
|
struct genericPartitionMap *gpm;
|
||||||
|
uint16_t ident;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
bh = udf_read_tagged(sb, block, block, &ident);
|
||||||
|
if (!bh)
|
||||||
|
return 1;
|
||||||
|
BUG_ON(ident != TAG_IDENT_LVD);
|
||||||
lvd = (struct logicalVolDesc *)bh->b_data;
|
lvd = (struct logicalVolDesc *)bh->b_data;
|
||||||
|
|
||||||
i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
|
i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
|
||||||
if (i != 0)
|
if (i != 0) {
|
||||||
return i;
|
ret = i;
|
||||||
|
goto out_bh;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0, offset = 0;
|
for (i = 0, offset = 0;
|
||||||
i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
|
i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
|
||||||
|
@ -1187,7 +1217,6 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
|
||||||
UDF_ID_SPARABLE,
|
UDF_ID_SPARABLE,
|
||||||
strlen(UDF_ID_SPARABLE))) {
|
strlen(UDF_ID_SPARABLE))) {
|
||||||
uint32_t loc;
|
uint32_t loc;
|
||||||
uint16_t ident;
|
|
||||||
struct sparingTable *st;
|
struct sparingTable *st;
|
||||||
struct sparablePartitionMap *spm =
|
struct sparablePartitionMap *spm =
|
||||||
(struct sparablePartitionMap *)gpm;
|
(struct sparablePartitionMap *)gpm;
|
||||||
|
@ -1243,7 +1272,9 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
|
||||||
if (lvd->integritySeqExt.extLength)
|
if (lvd->integritySeqExt.extLength)
|
||||||
udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
|
udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
|
||||||
|
|
||||||
return 0;
|
out_bh:
|
||||||
|
brelse(bh);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1301,19 +1332,25 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
|
||||||
struct generic_desc *gd;
|
struct generic_desc *gd;
|
||||||
struct volDescPtr *vdp;
|
struct volDescPtr *vdp;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
int i, j;
|
|
||||||
uint32_t vdsn;
|
uint32_t vdsn;
|
||||||
uint16_t ident;
|
uint16_t ident;
|
||||||
long next_s = 0, next_e = 0;
|
long next_s = 0, next_e = 0;
|
||||||
|
|
||||||
memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
|
memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
|
||||||
|
|
||||||
/* Read the main descriptor sequence */
|
/*
|
||||||
|
* Read the main descriptor sequence and find which descriptors
|
||||||
|
* are in it.
|
||||||
|
*/
|
||||||
for (; (!done && block <= lastblock); block++) {
|
for (; (!done && block <= lastblock); block++) {
|
||||||
|
|
||||||
bh = udf_read_tagged(sb, block, block, &ident);
|
bh = udf_read_tagged(sb, block, block, &ident);
|
||||||
if (!bh)
|
if (!bh) {
|
||||||
break;
|
printk(KERN_ERR "udf: Block %Lu of volume descriptor "
|
||||||
|
"sequence is corrupted or we could not read "
|
||||||
|
"it.\n", (unsigned long long)block);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Process each descriptor (ISO 13346 3/8.3-8.4) */
|
/* Process each descriptor (ISO 13346 3/8.3-8.4) */
|
||||||
gd = (struct generic_desc *)bh->b_data;
|
gd = (struct generic_desc *)bh->b_data;
|
||||||
|
@ -1379,42 +1416,32 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
|
||||||
}
|
}
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
}
|
}
|
||||||
for (i = 0; i < VDS_POS_LENGTH; i++) {
|
/*
|
||||||
if (!vds[i].block)
|
* Now read interesting descriptors again and process them
|
||||||
continue;
|
* in a suitable order
|
||||||
|
*/
|
||||||
|
if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) {
|
||||||
|
printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block))
|
||||||
|
return 1;
|
||||||
|
|
||||||
bh = udf_read_tagged(sb, vds[i].block, vds[i].block,
|
if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb,
|
||||||
&ident);
|
vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset))
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (i == VDS_POS_PRIMARY_VOL_DESC)
|
if (vds[VDS_POS_PARTITION_DESC].block) {
|
||||||
udf_load_pvoldesc(sb, bh);
|
/*
|
||||||
else if (i == VDS_POS_LOGICAL_VOL_DESC) {
|
* We rescan the whole descriptor sequence to find
|
||||||
if (udf_load_logicalvol(sb, bh, fileset)) {
|
* partition descriptor blocks and process them.
|
||||||
brelse(bh);
|
*/
|
||||||
|
for (block = vds[VDS_POS_PARTITION_DESC].block;
|
||||||
|
block < vds[VDS_POS_TERMINATING_DESC].block;
|
||||||
|
block++)
|
||||||
|
if (udf_load_partdesc(sb, block))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (i == VDS_POS_PARTITION_DESC) {
|
|
||||||
struct buffer_head *bh2 = NULL;
|
|
||||||
if (udf_load_partdesc(sb, bh)) {
|
|
||||||
brelse(bh);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
for (j = vds[i].block + 1;
|
|
||||||
j < vds[VDS_POS_TERMINATING_DESC].block;
|
|
||||||
j++) {
|
|
||||||
bh2 = udf_read_tagged(sb, j, j, &ident);
|
|
||||||
gd = (struct generic_desc *)bh2->b_data;
|
|
||||||
if (ident == TAG_IDENT_PD)
|
|
||||||
if (udf_load_partdesc(sb, bh2)) {
|
|
||||||
brelse(bh);
|
|
||||||
brelse(bh2);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
brelse(bh2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
brelse(bh);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue