xref: /openbmc/linux/fs/udf/lowlevel.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
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 Gorcunov unsigned 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 Kara udf_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