18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * partition.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * PURPOSE
58c2ecf20Sopenharmony_ci *      Partition handling routines for the OSTA-UDF(tm) filesystem.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * COPYRIGHT
88c2ecf20Sopenharmony_ci *      This file is distributed under the terms of the GNU General Public
98c2ecf20Sopenharmony_ci *      License (GPL). Copies of the GPL can be obtained from:
108c2ecf20Sopenharmony_ci *              ftp://prep.ai.mit.edu/pub/gnu/GPL
118c2ecf20Sopenharmony_ci *      Each contributing author retains all rights to their own work.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci *  (C) 1998-2001 Ben Fennema
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * HISTORY
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * 12/06/98 blf  Created file.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include "udfdecl.h"
228c2ecf20Sopenharmony_ci#include "udf_sb.h"
238c2ecf20Sopenharmony_ci#include "udf_i.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include <linux/fs.h>
268c2ecf20Sopenharmony_ci#include <linux/string.h>
278c2ecf20Sopenharmony_ci#include <linux/mutex.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciuint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
308c2ecf20Sopenharmony_ci			uint16_t partition, uint32_t offset)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct udf_sb_info *sbi = UDF_SB(sb);
338c2ecf20Sopenharmony_ci	struct udf_part_map *map;
348c2ecf20Sopenharmony_ci	if (partition >= sbi->s_partitions) {
358c2ecf20Sopenharmony_ci		udf_debug("block=%u, partition=%u, offset=%u: invalid partition\n",
368c2ecf20Sopenharmony_ci			  block, partition, offset);
378c2ecf20Sopenharmony_ci		return 0xFFFFFFFF;
388c2ecf20Sopenharmony_ci	}
398c2ecf20Sopenharmony_ci	map = &sbi->s_partmaps[partition];
408c2ecf20Sopenharmony_ci	if (map->s_partition_func)
418c2ecf20Sopenharmony_ci		return map->s_partition_func(sb, block, partition, offset);
428c2ecf20Sopenharmony_ci	else
438c2ecf20Sopenharmony_ci		return map->s_partition_root + block + offset;
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ciuint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
478c2ecf20Sopenharmony_ci			       uint16_t partition, uint32_t offset)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	struct buffer_head *bh = NULL;
508c2ecf20Sopenharmony_ci	uint32_t newblock;
518c2ecf20Sopenharmony_ci	uint32_t index;
528c2ecf20Sopenharmony_ci	uint32_t loc;
538c2ecf20Sopenharmony_ci	struct udf_sb_info *sbi = UDF_SB(sb);
548c2ecf20Sopenharmony_ci	struct udf_part_map *map;
558c2ecf20Sopenharmony_ci	struct udf_virtual_data *vdata;
568c2ecf20Sopenharmony_ci	struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	map = &sbi->s_partmaps[partition];
598c2ecf20Sopenharmony_ci	vdata = &map->s_type_specific.s_virtual;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	if (block > vdata->s_num_entries) {
628c2ecf20Sopenharmony_ci		udf_debug("Trying to access block beyond end of VAT (%u max %u)\n",
638c2ecf20Sopenharmony_ci			  block, vdata->s_num_entries);
648c2ecf20Sopenharmony_ci		return 0xFFFFFFFF;
658c2ecf20Sopenharmony_ci	}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
688c2ecf20Sopenharmony_ci		loc = le32_to_cpu(((__le32 *)(iinfo->i_data +
698c2ecf20Sopenharmony_ci			vdata->s_start_offset))[block]);
708c2ecf20Sopenharmony_ci		goto translate;
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci	index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
738c2ecf20Sopenharmony_ci	if (block >= index) {
748c2ecf20Sopenharmony_ci		block -= index;
758c2ecf20Sopenharmony_ci		newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
768c2ecf20Sopenharmony_ci		index = block % (sb->s_blocksize / sizeof(uint32_t));
778c2ecf20Sopenharmony_ci	} else {
788c2ecf20Sopenharmony_ci		newblock = 0;
798c2ecf20Sopenharmony_ci		index = vdata->s_start_offset / sizeof(uint32_t) + block;
808c2ecf20Sopenharmony_ci	}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	loc = udf_block_map(sbi->s_vat_inode, newblock);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	bh = sb_bread(sb, loc);
858c2ecf20Sopenharmony_ci	if (!bh) {
868c2ecf20Sopenharmony_ci		udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%u,%u) VAT: %u[%u]\n",
878c2ecf20Sopenharmony_ci			  sb, block, partition, loc, index);
888c2ecf20Sopenharmony_ci		return 0xFFFFFFFF;
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	loc = le32_to_cpu(((__le32 *)bh->b_data)[index]);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	brelse(bh);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_citranslate:
968c2ecf20Sopenharmony_ci	if (iinfo->i_location.partitionReferenceNum == partition) {
978c2ecf20Sopenharmony_ci		udf_debug("recursive call to udf_get_pblock!\n");
988c2ecf20Sopenharmony_ci		return 0xFFFFFFFF;
998c2ecf20Sopenharmony_ci	}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	return udf_get_pblock(sb, loc,
1028c2ecf20Sopenharmony_ci			      iinfo->i_location.partitionReferenceNum,
1038c2ecf20Sopenharmony_ci			      offset);
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ciinline uint32_t udf_get_pblock_virt20(struct super_block *sb, uint32_t block,
1078c2ecf20Sopenharmony_ci				      uint16_t partition, uint32_t offset)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	return udf_get_pblock_virt15(sb, block, partition, offset);
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ciuint32_t udf_get_pblock_spar15(struct super_block *sb, uint32_t block,
1138c2ecf20Sopenharmony_ci			       uint16_t partition, uint32_t offset)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	int i;
1168c2ecf20Sopenharmony_ci	struct sparingTable *st = NULL;
1178c2ecf20Sopenharmony_ci	struct udf_sb_info *sbi = UDF_SB(sb);
1188c2ecf20Sopenharmony_ci	struct udf_part_map *map;
1198c2ecf20Sopenharmony_ci	uint32_t packet;
1208c2ecf20Sopenharmony_ci	struct udf_sparing_data *sdata;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	map = &sbi->s_partmaps[partition];
1238c2ecf20Sopenharmony_ci	sdata = &map->s_type_specific.s_sparing;
1248c2ecf20Sopenharmony_ci	packet = (block + offset) & ~(sdata->s_packet_len - 1);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
1278c2ecf20Sopenharmony_ci		if (sdata->s_spar_map[i] != NULL) {
1288c2ecf20Sopenharmony_ci			st = (struct sparingTable *)
1298c2ecf20Sopenharmony_ci					sdata->s_spar_map[i]->b_data;
1308c2ecf20Sopenharmony_ci			break;
1318c2ecf20Sopenharmony_ci		}
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (st) {
1358c2ecf20Sopenharmony_ci		for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) {
1368c2ecf20Sopenharmony_ci			struct sparingEntry *entry = &st->mapEntry[i];
1378c2ecf20Sopenharmony_ci			u32 origLoc = le32_to_cpu(entry->origLocation);
1388c2ecf20Sopenharmony_ci			if (origLoc >= 0xFFFFFFF0)
1398c2ecf20Sopenharmony_ci				break;
1408c2ecf20Sopenharmony_ci			else if (origLoc == packet)
1418c2ecf20Sopenharmony_ci				return le32_to_cpu(entry->mappedLocation) +
1428c2ecf20Sopenharmony_ci					((block + offset) &
1438c2ecf20Sopenharmony_ci						(sdata->s_packet_len - 1));
1448c2ecf20Sopenharmony_ci			else if (origLoc > packet)
1458c2ecf20Sopenharmony_ci				break;
1468c2ecf20Sopenharmony_ci		}
1478c2ecf20Sopenharmony_ci	}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	return map->s_partition_root + block + offset;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ciint udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	struct udf_sparing_data *sdata;
1558c2ecf20Sopenharmony_ci	struct sparingTable *st = NULL;
1568c2ecf20Sopenharmony_ci	struct sparingEntry mapEntry;
1578c2ecf20Sopenharmony_ci	uint32_t packet;
1588c2ecf20Sopenharmony_ci	int i, j, k, l;
1598c2ecf20Sopenharmony_ci	struct udf_sb_info *sbi = UDF_SB(sb);
1608c2ecf20Sopenharmony_ci	u16 reallocationTableLen;
1618c2ecf20Sopenharmony_ci	struct buffer_head *bh;
1628c2ecf20Sopenharmony_ci	int ret = 0;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	mutex_lock(&sbi->s_alloc_mutex);
1658c2ecf20Sopenharmony_ci	for (i = 0; i < sbi->s_partitions; i++) {
1668c2ecf20Sopenharmony_ci		struct udf_part_map *map = &sbi->s_partmaps[i];
1678c2ecf20Sopenharmony_ci		if (old_block > map->s_partition_root &&
1688c2ecf20Sopenharmony_ci		    old_block < map->s_partition_root + map->s_partition_len) {
1698c2ecf20Sopenharmony_ci			sdata = &map->s_type_specific.s_sparing;
1708c2ecf20Sopenharmony_ci			packet = (old_block - map->s_partition_root) &
1718c2ecf20Sopenharmony_ci						~(sdata->s_packet_len - 1);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci			for (j = 0; j < 4; j++)
1748c2ecf20Sopenharmony_ci				if (sdata->s_spar_map[j] != NULL) {
1758c2ecf20Sopenharmony_ci					st = (struct sparingTable *)
1768c2ecf20Sopenharmony_ci						sdata->s_spar_map[j]->b_data;
1778c2ecf20Sopenharmony_ci					break;
1788c2ecf20Sopenharmony_ci				}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci			if (!st) {
1818c2ecf20Sopenharmony_ci				ret = 1;
1828c2ecf20Sopenharmony_ci				goto out;
1838c2ecf20Sopenharmony_ci			}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci			reallocationTableLen =
1868c2ecf20Sopenharmony_ci					le16_to_cpu(st->reallocationTableLen);
1878c2ecf20Sopenharmony_ci			for (k = 0; k < reallocationTableLen; k++) {
1888c2ecf20Sopenharmony_ci				struct sparingEntry *entry = &st->mapEntry[k];
1898c2ecf20Sopenharmony_ci				u32 origLoc = le32_to_cpu(entry->origLocation);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci				if (origLoc == 0xFFFFFFFF) {
1928c2ecf20Sopenharmony_ci					for (; j < 4; j++) {
1938c2ecf20Sopenharmony_ci						int len;
1948c2ecf20Sopenharmony_ci						bh = sdata->s_spar_map[j];
1958c2ecf20Sopenharmony_ci						if (!bh)
1968c2ecf20Sopenharmony_ci							continue;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci						st = (struct sparingTable *)
1998c2ecf20Sopenharmony_ci								bh->b_data;
2008c2ecf20Sopenharmony_ci						entry->origLocation =
2018c2ecf20Sopenharmony_ci							cpu_to_le32(packet);
2028c2ecf20Sopenharmony_ci						len =
2038c2ecf20Sopenharmony_ci						  sizeof(struct sparingTable) +
2048c2ecf20Sopenharmony_ci						  reallocationTableLen *
2058c2ecf20Sopenharmony_ci						  sizeof(struct sparingEntry);
2068c2ecf20Sopenharmony_ci						udf_update_tag((char *)st, len);
2078c2ecf20Sopenharmony_ci						mark_buffer_dirty(bh);
2088c2ecf20Sopenharmony_ci					}
2098c2ecf20Sopenharmony_ci					*new_block = le32_to_cpu(
2108c2ecf20Sopenharmony_ci							entry->mappedLocation) +
2118c2ecf20Sopenharmony_ci						     ((old_block -
2128c2ecf20Sopenharmony_ci							map->s_partition_root) &
2138c2ecf20Sopenharmony_ci						     (sdata->s_packet_len - 1));
2148c2ecf20Sopenharmony_ci					ret = 0;
2158c2ecf20Sopenharmony_ci					goto out;
2168c2ecf20Sopenharmony_ci				} else if (origLoc == packet) {
2178c2ecf20Sopenharmony_ci					*new_block = le32_to_cpu(
2188c2ecf20Sopenharmony_ci							entry->mappedLocation) +
2198c2ecf20Sopenharmony_ci						     ((old_block -
2208c2ecf20Sopenharmony_ci							map->s_partition_root) &
2218c2ecf20Sopenharmony_ci						     (sdata->s_packet_len - 1));
2228c2ecf20Sopenharmony_ci					ret = 0;
2238c2ecf20Sopenharmony_ci					goto out;
2248c2ecf20Sopenharmony_ci				} else if (origLoc > packet)
2258c2ecf20Sopenharmony_ci					break;
2268c2ecf20Sopenharmony_ci			}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci			for (l = k; l < reallocationTableLen; l++) {
2298c2ecf20Sopenharmony_ci				struct sparingEntry *entry = &st->mapEntry[l];
2308c2ecf20Sopenharmony_ci				u32 origLoc = le32_to_cpu(entry->origLocation);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci				if (origLoc != 0xFFFFFFFF)
2338c2ecf20Sopenharmony_ci					continue;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci				for (; j < 4; j++) {
2368c2ecf20Sopenharmony_ci					bh = sdata->s_spar_map[j];
2378c2ecf20Sopenharmony_ci					if (!bh)
2388c2ecf20Sopenharmony_ci						continue;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci					st = (struct sparingTable *)bh->b_data;
2418c2ecf20Sopenharmony_ci					mapEntry = st->mapEntry[l];
2428c2ecf20Sopenharmony_ci					mapEntry.origLocation =
2438c2ecf20Sopenharmony_ci							cpu_to_le32(packet);
2448c2ecf20Sopenharmony_ci					memmove(&st->mapEntry[k + 1],
2458c2ecf20Sopenharmony_ci						&st->mapEntry[k],
2468c2ecf20Sopenharmony_ci						(l - k) *
2478c2ecf20Sopenharmony_ci						sizeof(struct sparingEntry));
2488c2ecf20Sopenharmony_ci					st->mapEntry[k] = mapEntry;
2498c2ecf20Sopenharmony_ci					udf_update_tag((char *)st,
2508c2ecf20Sopenharmony_ci						sizeof(struct sparingTable) +
2518c2ecf20Sopenharmony_ci						reallocationTableLen *
2528c2ecf20Sopenharmony_ci						sizeof(struct sparingEntry));
2538c2ecf20Sopenharmony_ci					mark_buffer_dirty(bh);
2548c2ecf20Sopenharmony_ci				}
2558c2ecf20Sopenharmony_ci				*new_block =
2568c2ecf20Sopenharmony_ci					le32_to_cpu(
2578c2ecf20Sopenharmony_ci					      st->mapEntry[k].mappedLocation) +
2588c2ecf20Sopenharmony_ci					((old_block - map->s_partition_root) &
2598c2ecf20Sopenharmony_ci					 (sdata->s_packet_len - 1));
2608c2ecf20Sopenharmony_ci				ret = 0;
2618c2ecf20Sopenharmony_ci				goto out;
2628c2ecf20Sopenharmony_ci			}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci			ret = 1;
2658c2ecf20Sopenharmony_ci			goto out;
2668c2ecf20Sopenharmony_ci		} /* if old_block */
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	if (i == sbi->s_partitions) {
2708c2ecf20Sopenharmony_ci		/* outside of partitions */
2718c2ecf20Sopenharmony_ci		/* for now, fail =) */
2728c2ecf20Sopenharmony_ci		ret = 1;
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ciout:
2768c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->s_alloc_mutex);
2778c2ecf20Sopenharmony_ci	return ret;
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
2818c2ecf20Sopenharmony_ci					uint16_t partition, uint32_t offset)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
2848c2ecf20Sopenharmony_ci	struct udf_part_map *map;
2858c2ecf20Sopenharmony_ci	struct kernel_lb_addr eloc;
2868c2ecf20Sopenharmony_ci	uint32_t elen;
2878c2ecf20Sopenharmony_ci	sector_t ext_offset;
2888c2ecf20Sopenharmony_ci	struct extent_position epos = {};
2898c2ecf20Sopenharmony_ci	uint32_t phyblock;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
2928c2ecf20Sopenharmony_ci						(EXT_RECORDED_ALLOCATED >> 30))
2938c2ecf20Sopenharmony_ci		phyblock = 0xFFFFFFFF;
2948c2ecf20Sopenharmony_ci	else {
2958c2ecf20Sopenharmony_ci		map = &UDF_SB(sb)->s_partmaps[partition];
2968c2ecf20Sopenharmony_ci		/* map to sparable/physical partition desc */
2978c2ecf20Sopenharmony_ci		phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
2988c2ecf20Sopenharmony_ci			map->s_type_specific.s_metadata.s_phys_partition_ref,
2998c2ecf20Sopenharmony_ci			ext_offset + offset);
3008c2ecf20Sopenharmony_ci	}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	brelse(epos.bh);
3038c2ecf20Sopenharmony_ci	return phyblock;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ciuint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
3078c2ecf20Sopenharmony_ci				uint16_t partition, uint32_t offset)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	struct udf_sb_info *sbi = UDF_SB(sb);
3108c2ecf20Sopenharmony_ci	struct udf_part_map *map;
3118c2ecf20Sopenharmony_ci	struct udf_meta_data *mdata;
3128c2ecf20Sopenharmony_ci	uint32_t retblk;
3138c2ecf20Sopenharmony_ci	struct inode *inode;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	udf_debug("READING from METADATA\n");
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	map = &sbi->s_partmaps[partition];
3188c2ecf20Sopenharmony_ci	mdata = &map->s_type_specific.s_metadata;
3198c2ecf20Sopenharmony_ci	inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	if (!inode)
3228c2ecf20Sopenharmony_ci		return 0xFFFFFFFF;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	retblk = udf_try_read_meta(inode, block, partition, offset);
3258c2ecf20Sopenharmony_ci	if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) {
3268c2ecf20Sopenharmony_ci		udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n");
3278c2ecf20Sopenharmony_ci		if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) {
3288c2ecf20Sopenharmony_ci			mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
3298c2ecf20Sopenharmony_ci				mdata->s_mirror_file_loc,
3308c2ecf20Sopenharmony_ci				mdata->s_phys_partition_ref);
3318c2ecf20Sopenharmony_ci			if (IS_ERR(mdata->s_mirror_fe))
3328c2ecf20Sopenharmony_ci				mdata->s_mirror_fe = NULL;
3338c2ecf20Sopenharmony_ci			mdata->s_flags |= MF_MIRROR_FE_LOADED;
3348c2ecf20Sopenharmony_ci		}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci		inode = mdata->s_mirror_fe;
3378c2ecf20Sopenharmony_ci		if (!inode)
3388c2ecf20Sopenharmony_ci			return 0xFFFFFFFF;
3398c2ecf20Sopenharmony_ci		retblk = udf_try_read_meta(inode, block, partition, offset);
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	return retblk;
3438c2ecf20Sopenharmony_ci}
344