1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * lowlevel.c 4 * 5 * PURPOSE 6 * Low Level Device Routines for the UDF filesystem 7 * 8 * COPYRIGHT 9 * (C) 1999-2001 Ben Fennema 10 * 11 * HISTORY 12 * 13 * 03/26/99 blf Created. 14 */ 15 16 #include "udfdecl.h" 17 18 #include <linux/blkdev.h> 19 #include <linux/cdrom.h> 20 #include <linux/uaccess.h> 21 22 #include "udf_sb.h" 23 24 unsigned int udf_get_last_session(struct super_block *sb) 25 { 26 struct cdrom_device_info *cdi = disk_to_cdi(sb->s_bdev->bd_disk); 27 struct cdrom_multisession ms_info; 28 29 if (!cdi) { 30 udf_debug("CDROMMULTISESSION not supported.\n"); 31 return 0; 32 } 33 34 ms_info.addr_format = CDROM_LBA; 35 if (cdrom_multisession(cdi, &ms_info) == 0) { 36 udf_debug("XA disk: %s, vol_desc_start=%d\n", 37 ms_info.xa_flag ? "yes" : "no", ms_info.addr.lba); 38 if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */ 39 return ms_info.addr.lba; 40 } 41 return 0; 42 } 43 44 udf_pblk_t udf_get_last_block(struct super_block *sb) 45 { 46 struct cdrom_device_info *cdi = disk_to_cdi(sb->s_bdev->bd_disk); 47 unsigned long lblock = 0; 48 49 /* 50 * The cdrom layer call failed or returned obviously bogus value? 51 * Try using the device size... 52 */ 53 if (!cdi || cdrom_get_last_written(cdi, &lblock) || lblock == 0) { 54 if (sb_bdev_nr_blocks(sb) > ~(udf_pblk_t)0) 55 return 0; 56 lblock = sb_bdev_nr_blocks(sb); 57 } 58 59 if (lblock) 60 return lblock - 1; 61 return 0; 62 } 63