-/*
- * Check whether there is an anchor block in the given block
- */
-static int udf_check_anchor_block(struct super_block *sb, sector_t block)
-{
- struct buffer_head *bh;
- uint16_t ident;
-
- if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
- udf_fixed_to_variable(block) >=
- sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
- return 0;
-
- bh = udf_read_tagged(sb, block, block, &ident);
- if (!bh)
- return 0;
- brelse(bh);
-
- return ident == TAG_IDENT_AVDP;
-}
-
-/* Search for an anchor volume descriptor pointer */
-static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock)
-{
- sector_t last[6];
- int i;
- struct udf_sb_info *sbi = UDF_SB(sb);
-
- last[0] = lastblock;
- last[1] = last[0] - 1;
- last[2] = last[0] + 1;
- last[3] = last[0] - 2;
- last[4] = last[0] - 150;
- last[5] = last[0] - 152;
-
- /* according to spec, anchor is in either:
- * block 256
- * lastblock-256
- * lastblock
- * however, if the disc isn't closed, it could be 512 */
-
- for (i = 0; i < ARRAY_SIZE(last); i++) {
- if (last[i] < 0)
- continue;
- if (last[i] >= sb->s_bdev->bd_inode->i_size >>
- sb->s_blocksize_bits)
- continue;
-
- if (udf_check_anchor_block(sb, last[i])) {
- sbi->s_anchor[0] = last[i];
- sbi->s_anchor[1] = last[i] - 256;
- return last[i];
- }
-
- if (last[i] < 256)
- continue;
-
- if (udf_check_anchor_block(sb, last[i] - 256)) {
- sbi->s_anchor[1] = last[i] - 256;
- return last[i];
- }
- }
-
- if (udf_check_anchor_block(sb, sbi->s_session + 256)) {
- sbi->s_anchor[0] = sbi->s_session + 256;
- return last[0];
- }
- if (udf_check_anchor_block(sb, sbi->s_session + 512)) {
- sbi->s_anchor[0] = sbi->s_session + 512;
- return last[0];
- }
- return 0;
-}
-
-/*
- * Find an anchor volume descriptor. The function expects sbi->s_lastblock to
- * be the last block on the media.
- *
- * Return 1 if not found, 0 if ok
- *
- */
-static void udf_find_anchor(struct super_block *sb)
-{
- sector_t lastblock;
- struct buffer_head *bh = NULL;
- uint16_t ident;
- int i;
- struct udf_sb_info *sbi = UDF_SB(sb);
-
- lastblock = udf_scan_anchors(sb, sbi->s_last_block);
- if (lastblock)
- goto check_anchor;
-
- /* No anchor found? Try VARCONV conversion of block numbers */
- UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
- /* Firstly, we try to not convert number of the last block */
- lastblock = udf_scan_anchors(sb,
- udf_variable_to_fixed(sbi->s_last_block));
- if (lastblock)
- goto check_anchor;
-
- /* Secondly, we try with converted number of the last block */
- lastblock = udf_scan_anchors(sb, sbi->s_last_block);
- if (!lastblock) {
- /* VARCONV didn't help. Clear it. */
- UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
- }
-
-check_anchor:
- /*
- * Check located anchors and the anchor block supplied via
- * mount options
- */
- for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
- if (!sbi->s_anchor[i])
- continue;
- bh = udf_read_tagged(sb, sbi->s_anchor[i],
- sbi->s_anchor[i], &ident);
- if (!bh)
- sbi->s_anchor[i] = 0;
- else {
- brelse(bh);
- if (ident != TAG_IDENT_AVDP)
- sbi->s_anchor[i] = 0;
- }
- }
-
- sbi->s_last_block = lastblock;
-}
-