1*5ce34554SBagas Sanjaya // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * lowlevel.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * PURPOSE 61da177e4SLinus Torvalds * Low Level Device Routines for the UDF filesystem 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * COPYRIGHT 91da177e4SLinus Torvalds * (C) 1999-2001 Ben Fennema 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * HISTORY 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * 03/26/99 blf Created. 141da177e4SLinus Torvalds */ 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds #include "udfdecl.h" 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds #include <linux/blkdev.h> 191da177e4SLinus Torvalds #include <linux/cdrom.h> 20e973606cSFabian Frederick #include <linux/uaccess.h> 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #include "udf_sb.h" 231da177e4SLinus Torvalds udf_get_last_session(struct super_block * sb)24cb00ea35SCyrill Gorcunovunsigned int udf_get_last_session(struct super_block *sb) 251da177e4SLinus Torvalds { 268b075e5bSChristoph Hellwig struct cdrom_device_info *cdi = disk_to_cdi(sb->s_bdev->bd_disk); 271da177e4SLinus Torvalds struct cdrom_multisession ms_info; 281da177e4SLinus Torvalds 298b075e5bSChristoph Hellwig if (!cdi) { 308b075e5bSChristoph Hellwig udf_debug("CDROMMULTISESSION not supported.\n"); 318b075e5bSChristoph Hellwig return 0; 328b075e5bSChristoph Hellwig } 338b075e5bSChristoph Hellwig 341da177e4SLinus Torvalds ms_info.addr_format = CDROM_LBA; 358b075e5bSChristoph Hellwig if (cdrom_multisession(cdi, &ms_info) == 0) { 361da177e4SLinus Torvalds udf_debug("XA disk: %s, vol_desc_start=%d\n", 37a983f368SJoe Perches ms_info.xa_flag ? "yes" : "no", ms_info.addr.lba); 381da177e4SLinus Torvalds if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */ 398b075e5bSChristoph Hellwig return ms_info.addr.lba; 401da177e4SLinus Torvalds } 418b075e5bSChristoph Hellwig return 0; 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds udf_get_last_block(struct super_block * sb)44bd904f3cSJan Karaudf_pblk_t udf_get_last_block(struct super_block *sb) 451da177e4SLinus Torvalds { 46e4ae4735SChristoph Hellwig struct cdrom_device_info *cdi = disk_to_cdi(sb->s_bdev->bd_disk); 471da177e4SLinus Torvalds unsigned long lblock = 0; 481da177e4SLinus Torvalds 4924a5d59fSJan Kara /* 508b075e5bSChristoph Hellwig * The cdrom layer call failed or returned obviously bogus value? 5124a5d59fSJan Kara * Try using the device size... 5224a5d59fSJan Kara */ 53bd904f3cSJan Kara if (!cdi || cdrom_get_last_written(cdi, &lblock) || lblock == 0) { 54bd904f3cSJan Kara if (sb_bdev_nr_blocks(sb) > ~(udf_pblk_t)0) 55bd904f3cSJan Kara return 0; 56e4ae4735SChristoph Hellwig lblock = sb_bdev_nr_blocks(sb); 57bd904f3cSJan Kara } 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds if (lblock) 601da177e4SLinus Torvalds return lblock - 1; 611da177e4SLinus Torvalds return 0; 621da177e4SLinus Torvalds } 63