162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * lowlevel.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * PURPOSE 662306a36Sopenharmony_ci * Low Level Device Routines for the UDF filesystem 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * COPYRIGHT 962306a36Sopenharmony_ci * (C) 1999-2001 Ben Fennema 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * HISTORY 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * 03/26/99 blf Created. 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "udfdecl.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/blkdev.h> 1962306a36Sopenharmony_ci#include <linux/cdrom.h> 2062306a36Sopenharmony_ci#include <linux/uaccess.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "udf_sb.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciunsigned int udf_get_last_session(struct super_block *sb) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct cdrom_device_info *cdi = disk_to_cdi(sb->s_bdev->bd_disk); 2762306a36Sopenharmony_ci struct cdrom_multisession ms_info; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci if (!cdi) { 3062306a36Sopenharmony_ci udf_debug("CDROMMULTISESSION not supported.\n"); 3162306a36Sopenharmony_ci return 0; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci ms_info.addr_format = CDROM_LBA; 3562306a36Sopenharmony_ci if (cdrom_multisession(cdi, &ms_info) == 0) { 3662306a36Sopenharmony_ci udf_debug("XA disk: %s, vol_desc_start=%d\n", 3762306a36Sopenharmony_ci ms_info.xa_flag ? "yes" : "no", ms_info.addr.lba); 3862306a36Sopenharmony_ci if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */ 3962306a36Sopenharmony_ci return ms_info.addr.lba; 4062306a36Sopenharmony_ci } 4162306a36Sopenharmony_ci return 0; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciudf_pblk_t udf_get_last_block(struct super_block *sb) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci struct cdrom_device_info *cdi = disk_to_cdi(sb->s_bdev->bd_disk); 4762306a36Sopenharmony_ci unsigned long lblock = 0; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci /* 5062306a36Sopenharmony_ci * The cdrom layer call failed or returned obviously bogus value? 5162306a36Sopenharmony_ci * Try using the device size... 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci if (!cdi || cdrom_get_last_written(cdi, &lblock) || lblock == 0) { 5462306a36Sopenharmony_ci if (sb_bdev_nr_blocks(sb) > ~(udf_pblk_t)0) 5562306a36Sopenharmony_ci return 0; 5662306a36Sopenharmony_ci lblock = sb_bdev_nr_blocks(sb); 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (lblock) 6062306a36Sopenharmony_ci return lblock - 1; 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 63