xref: /haiku/src/add-ons/kernel/file_systems/udf/Volume.cpp (revision c530d46cca3cb9bde36e243e634796eb2e17a23a)
1e1f5f06bSSalvatore Benedetto /*
2*c530d46cSJérôme Duval  * Copyright 2012, Jérôme Duval, korli@users.berlios.de.
3e1f5f06bSSalvatore Benedetto  * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com
4e1f5f06bSSalvatore Benedetto  * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
5e1f5f06bSSalvatore Benedetto  * Distributed under the terms of the MIT License.
6e1f5f06bSSalvatore Benedetto  */
7e1f5f06bSSalvatore Benedetto 
829008bcfSTyler Dauwalder #include "Volume.h"
929008bcfSTyler Dauwalder 
103f4628f1STyler Dauwalder #include "Icb.h"
110d383564STyler Dauwalder #include "MemoryChunk.h"
12*c530d46cSJérôme Duval #include "MetadataPartition.h"
13d4e8b936STyler Dauwalder #include "PhysicalPartition.h"
1421c162a3STyler Dauwalder #include "Recognition.h"
1529008bcfSTyler Dauwalder 
16e0c80398SSalvatore Benedetto extern fs_volume_ops gUDFVolumeOps;
17e0c80398SSalvatore Benedetto extern fs_vnode_ops gUDFVnodeOps;
1829008bcfSTyler Dauwalder 
19e1f5f06bSSalvatore Benedetto /*! \brief Creates an unmounted volume with the given id. */
20e1f5f06bSSalvatore Benedetto Volume::Volume(fs_volume *fsVolume)
21e1f5f06bSSalvatore Benedetto 	:
22e1f5f06bSSalvatore Benedetto 	fBlockCache(NULL),
23e1f5f06bSSalvatore Benedetto 	fBlockShift(0),
24e1f5f06bSSalvatore Benedetto 	fBlockSize(0),
25e1f5f06bSSalvatore Benedetto 	fDevice(-1),
26e1f5f06bSSalvatore Benedetto 	fFSVolume(fsVolume),
27e1f5f06bSSalvatore Benedetto 	fLength(0),
28e1f5f06bSSalvatore Benedetto 	fMounted(false),
29e1f5f06bSSalvatore Benedetto 	fOffset(0),
30e1f5f06bSSalvatore Benedetto 	fRootIcb(NULL)
3129008bcfSTyler Dauwalder {
3221c162a3STyler Dauwalder 	for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++)
3321c162a3STyler Dauwalder 		fPartitions[i] = NULL;
3429008bcfSTyler Dauwalder }
3529008bcfSTyler Dauwalder 
360c342879SSalvatore Benedetto 
37d4e8b936STyler Dauwalder Volume::~Volume()
3829008bcfSTyler Dauwalder {
39d4e8b936STyler Dauwalder 	_Unset();
4029008bcfSTyler Dauwalder }
4129008bcfSTyler Dauwalder 
420c342879SSalvatore Benedetto 
4329008bcfSTyler Dauwalder /*! \brief Attempts to mount the given device.
443f4628f1STyler Dauwalder 
459fd15595SSalvatore Benedetto 	\param lenght The length of the device in number of blocks
4629008bcfSTyler Dauwalder */
4729008bcfSTyler Dauwalder status_t
480c342879SSalvatore Benedetto Volume::Mount(const char *deviceName, off_t offset, off_t length,
4921c162a3STyler Dauwalder 	uint32 blockSize, uint32 flags)
5021c162a3STyler Dauwalder {
510c342879SSalvatore Benedetto 	TRACE(("Volume::Mount: deviceName = `%s', offset = %Ld, length = %Ld, "
520c342879SSalvatore Benedetto 		"blockSize: %ld, flags: %ld\n", deviceName, offset, length, blockSize,
530c342879SSalvatore Benedetto 		flags));
5421c162a3STyler Dauwalder 	if (!deviceName)
550c342879SSalvatore Benedetto 		return B_BAD_VALUE;
560c342879SSalvatore Benedetto 	if (Mounted())
5721c162a3STyler Dauwalder 		// Already mounted, thank you for asking
580c342879SSalvatore Benedetto 		return B_BUSY;
5921c162a3STyler Dauwalder 
6021c162a3STyler Dauwalder 	// Open the device read only
6121c162a3STyler Dauwalder 	int device = open(deviceName, O_RDONLY);
620c342879SSalvatore Benedetto 	if (device < B_OK) {
630c342879SSalvatore Benedetto 		TRACE_ERROR(("Volume::Mount: failed to open device = %s\n", deviceName));
640c342879SSalvatore Benedetto 		return device;
650c342879SSalvatore Benedetto 	}
6621c162a3STyler Dauwalder 
67*c530d46cSJérôme Duval 	DEBUG_INIT_ETC("Volume", ("deviceName: %s", deviceName));
680c342879SSalvatore Benedetto 	status_t status = B_OK;
6921c162a3STyler Dauwalder 
7021c162a3STyler Dauwalder 	// If the device is actually a normal file, try to disable the cache
7121c162a3STyler Dauwalder 	// for the file in the parent filesystem
72e1f5f06bSSalvatore Benedetto #if 0 //  _KERNEL_MODE
7321c162a3STyler Dauwalder 	struct stat stat;
7421c162a3STyler Dauwalder 	error = fstat(device, &stat) < 0 ? B_ERROR : B_OK;
7521c162a3STyler Dauwalder 	if (!error) {
7621c162a3STyler Dauwalder 		if (stat.st_mode & S_IFREG && ioctl(device, IOCTL_FILE_UNCACHED_IO, NULL) < 0) {
7721c162a3STyler Dauwalder 			DIE(("Unable to disable cache of underlying file system.\n"));
7821c162a3STyler Dauwalder 		}
7921c162a3STyler Dauwalder 	}
80e376a854STyler Dauwalder #endif
8121c162a3STyler Dauwalder 
829b8775eaSTyler Dauwalder 	logical_volume_descriptor logicalVolumeDescriptor;
83e1f5f06bSSalvatore Benedetto 	partition_descriptor partitionDescriptors[kMaxPartitionDescriptors];
8421c162a3STyler Dauwalder 	uint8 partitionDescriptorCount;
8521c162a3STyler Dauwalder 	uint32 blockShift;
8621c162a3STyler Dauwalder 
871379cacaSTyler Dauwalder 	// Run through the volume recognition and descriptor sequences to
881379cacaSTyler Dauwalder 	// see if we have a potentially valid UDF volume on our hands
890c342879SSalvatore Benedetto 	status = udf_recognize(device, offset, length, blockSize, blockShift,
90*c530d46cSJérôme Duval 				fPrimaryVolumeDescriptor, logicalVolumeDescriptor,
91*c530d46cSJérôme Duval 				partitionDescriptors, partitionDescriptorCount);
9221c162a3STyler Dauwalder 
9321c162a3STyler Dauwalder 	// Set up the block cache
94e0c80398SSalvatore Benedetto 	if (!status) {
95e0c80398SSalvatore Benedetto 		TRACE(("Volume::Mount: partition recognized\n"));
960c342879SSalvatore Benedetto 		fBlockCache = block_cache_create(device, length, blockSize, IsReadOnly());
97e0c80398SSalvatore Benedetto 	} else {
980c342879SSalvatore Benedetto 		TRACE_ERROR(("Volume::Mount: failed to recognize partition\n"));
990c342879SSalvatore Benedetto 		return status;
1000c342879SSalvatore Benedetto 	}
10121c162a3STyler Dauwalder 
102d4e8b936STyler Dauwalder 	int physicalCount = 0;
103d4e8b936STyler Dauwalder 	int virtualCount = 0;
104d4e8b936STyler Dauwalder 	int sparableCount = 0;
105d4e8b936STyler Dauwalder 	int metadataCount = 0;
106d4e8b936STyler Dauwalder 
10721c162a3STyler Dauwalder 	// Set up the partitions
10821c162a3STyler Dauwalder 	// Set up physical and sparable partitions first
109e0c80398SSalvatore Benedetto 	offset = 0;
110d4e8b936STyler Dauwalder 	for (uint8 i = 0; i < logicalVolumeDescriptor.partition_map_count()
1110c342879SSalvatore Benedetto 	     && !status; i++)
112d4e8b936STyler Dauwalder 	{
11321c162a3STyler Dauwalder 		uint8 *maps = logicalVolumeDescriptor.partition_maps();
114e0c80398SSalvatore Benedetto 		partition_map_header *header = (partition_map_header *)(maps + offset);
115e0c80398SSalvatore Benedetto 		TRACE(("Volume::Mount: partition map %d (type %d):\n", i,
116e0c80398SSalvatore Benedetto 			header->type()));
11721c162a3STyler Dauwalder 		if (header->type() == 1) {
118e0c80398SSalvatore Benedetto 			TRACE(("Volume::Mount: map type -> physical\n"));
119e0c80398SSalvatore Benedetto 			physical_partition_map* map = (physical_partition_map *)header;
120d4e8b936STyler Dauwalder 			// Find the corresponding partition descriptor
1211379cacaSTyler Dauwalder 			partition_descriptor *descriptor = NULL;
122d4e8b936STyler Dauwalder 			for (uint8 j = 0; j < partitionDescriptorCount; j++) {
123d4e8b936STyler Dauwalder 				if (map->partition_number() ==
124e0c80398SSalvatore Benedetto 				    partitionDescriptors[j].partition_number()) {
125d4e8b936STyler Dauwalder 					descriptor = &partitionDescriptors[j];
126d4e8b936STyler Dauwalder 					break;
127d4e8b936STyler Dauwalder 				}
128d4e8b936STyler Dauwalder 			}
129d4e8b936STyler Dauwalder 			// Create and add the partition
130d4e8b936STyler Dauwalder 			if (descriptor) {
131e0c80398SSalvatore Benedetto 				PhysicalPartition *partition
132e0c80398SSalvatore Benedetto 					= new(nothrow) PhysicalPartition(map->partition_number(),
133e0c80398SSalvatore Benedetto 						descriptor->start(), descriptor->length());
1340c342879SSalvatore Benedetto 				status = partition ? B_OK : B_NO_MEMORY;
1350c342879SSalvatore Benedetto 				if (!status) {
136e0c80398SSalvatore Benedetto 					TRACE(("Volume::Mount: adding PhysicalPartition(number: %d, "
137e0c80398SSalvatore Benedetto 						"start: %ld, length: %ld)\n", map->partition_number(),
138d4e8b936STyler Dauwalder 						descriptor->start(), descriptor->length()));
1390c342879SSalvatore Benedetto 					status = _SetPartition(i, partition);
1400c342879SSalvatore Benedetto 					if (!status)
141d4e8b936STyler Dauwalder 						physicalCount++;
142d4e8b936STyler Dauwalder 				}
14321c162a3STyler Dauwalder 			} else {
14489264fe4SSalvatore Benedetto 				TRACE_ERROR(("Volume::Mount: no matching partition descriptor found!\n"));
1450c342879SSalvatore Benedetto 				status = B_ERROR;
146d4e8b936STyler Dauwalder 			}
147d4e8b936STyler Dauwalder 		} else if (header->type() == 2) {
1481379cacaSTyler Dauwalder 			// Figure out what kind of type 2 partition map we have based
149d4e8b936STyler Dauwalder 			// on the type identifier
1501379cacaSTyler Dauwalder 			const entity_id &typeId = header->partition_type_id();
151d4e8b936STyler Dauwalder 			DUMP(typeId);
152d4e8b936STyler Dauwalder 			DUMP(kSparablePartitionMapId);
153d4e8b936STyler Dauwalder 			if (typeId.matches(kVirtualPartitionMapId)) {
1540c342879SSalvatore Benedetto 				TRACE(("map type: virtual\n"));
1551379cacaSTyler Dauwalder 				virtual_partition_map* map =
1561379cacaSTyler Dauwalder 					reinterpret_cast<virtual_partition_map*>(header);
157d4e8b936STyler Dauwalder 				virtualCount++;
158d4e8b936STyler Dauwalder 				(void)map;	// kill the warning for now
159d4e8b936STyler Dauwalder 			} else if (typeId.matches(kSparablePartitionMapId)) {
1600c342879SSalvatore Benedetto 				TRACE(("map type: sparable\n"));
1611379cacaSTyler Dauwalder 				sparable_partition_map* map =
1621379cacaSTyler Dauwalder 					reinterpret_cast<sparable_partition_map*>(header);
163d4e8b936STyler Dauwalder 				sparableCount++;
164d4e8b936STyler Dauwalder 				(void)map;	// kill the warning for now
165d4e8b936STyler Dauwalder 			} else if (typeId.matches(kMetadataPartitionMapId)) {
1660c342879SSalvatore Benedetto 				TRACE(("map type: metadata\n"));
1671379cacaSTyler Dauwalder 				metadata_partition_map* map =
1681379cacaSTyler Dauwalder 					reinterpret_cast<metadata_partition_map*>(header);
169*c530d46cSJérôme Duval 
170*c530d46cSJérôme Duval 
171*c530d46cSJérôme Duval 				// Find the corresponding partition descriptor
172*c530d46cSJérôme Duval 				partition_descriptor *descriptor = NULL;
173*c530d46cSJérôme Duval 				for (uint8 j = 0; j < partitionDescriptorCount; j++) {
174*c530d46cSJérôme Duval 					if (map->partition_number() ==
175*c530d46cSJérôme Duval 						partitionDescriptors[j].partition_number()) {
176*c530d46cSJérôme Duval 						descriptor = &partitionDescriptors[j];
177*c530d46cSJérôme Duval 						break;
178*c530d46cSJérôme Duval 					}
179*c530d46cSJérôme Duval 				}
180*c530d46cSJérôme Duval 				Partition *parent = _GetPartition(map->partition_number());
181*c530d46cSJérôme Duval 				// Create and add the partition
182*c530d46cSJérôme Duval 				if (descriptor != NULL && parent != NULL) {
183*c530d46cSJérôme Duval 					MetadataPartition *partition
184*c530d46cSJérôme Duval 						= new(nothrow) MetadataPartition(this,
185*c530d46cSJérôme Duval 							map->partition_number(), *parent,
186*c530d46cSJérôme Duval 							map->metadata_file_location(),
187*c530d46cSJérôme Duval 							map->metadata_mirror_file_location(),
188*c530d46cSJérôme Duval 							map->metadata_bitmap_file_location(),
189*c530d46cSJérôme Duval 							map->allocation_unit_size(),
190*c530d46cSJérôme Duval 							map->alignment_unit_size(),
191*c530d46cSJérôme Duval 							map->flags() & 1);
192*c530d46cSJérôme Duval 					status = partition ? partition->InitCheck() : B_NO_MEMORY;
193*c530d46cSJérôme Duval 					if (!status) {
194*c530d46cSJérôme Duval 						TRACE(("Volume::Mount: adding MetadataPartition()"));
195*c530d46cSJérôme Duval 						status = _SetPartition(i, partition);
196*c530d46cSJérôme Duval 						if (status == B_OK)
197d4e8b936STyler Dauwalder 							metadataCount++;
198*c530d46cSJérôme Duval 					} else {
199*c530d46cSJérôme Duval 						TRACE_ERROR(("Volume::Mount: metadata partition "
200*c530d46cSJérôme Duval 							"creation failed! 0x%lx\n", status));
201*c530d46cSJérôme Duval 					}
202*c530d46cSJérôme Duval 				} else {
203*c530d46cSJérôme Duval 					TRACE_ERROR(("Volume::Mount: no matching partition descriptor found!\n"));
204*c530d46cSJérôme Duval 					status = B_ERROR;
205*c530d46cSJérôme Duval 				}
206d4e8b936STyler Dauwalder 			} else {
2070c342879SSalvatore Benedetto 				TRACE(("map type: unrecognized (`%.23s')\n",
208d4e8b936STyler Dauwalder 				       typeId.identifier()));
2090c342879SSalvatore Benedetto 				status = B_ERROR;
21021c162a3STyler Dauwalder 			}
211d4e8b936STyler Dauwalder 		} else {
2120c342879SSalvatore Benedetto 			TRACE(("Invalid partition type %d found!\n", header->type()));
2130c342879SSalvatore Benedetto 			status = B_ERROR;
214d4e8b936STyler Dauwalder 		}
21521c162a3STyler Dauwalder 		offset += header->length();
21621c162a3STyler Dauwalder 	}
21721c162a3STyler Dauwalder 
218d4e8b936STyler Dauwalder 	// Do some checking as to what sorts of partitions we've actually found.
2190c342879SSalvatore Benedetto 	if (!status) {
2200c342879SSalvatore Benedetto 		status = (physicalCount == 1 && virtualCount == 0
221*c530d46cSJérôme Duval 		         && sparableCount == 0)
222d4e8b936STyler Dauwalder 		        || (physicalCount == 2 && virtualCount == 0
223*c530d46cSJérôme Duval 		           && sparableCount == 0)
224d4e8b936STyler Dauwalder 		        ? B_OK : B_ERROR;
2250c342879SSalvatore Benedetto 		if (status) {
2260c342879SSalvatore Benedetto 			TRACE(("Invalid partition layout found:\n"));
2270c342879SSalvatore Benedetto 			TRACE(("  physical partitions: %d\n", physicalCount));
2280c342879SSalvatore Benedetto 			TRACE(("  virtual partitions:  %d\n", virtualCount));
2290c342879SSalvatore Benedetto 			TRACE(("  sparable partitions: %d\n", sparableCount));
2300c342879SSalvatore Benedetto 			TRACE(("  metadata partitions: %d\n", metadataCount));
231d4e8b936STyler Dauwalder 		}
232d4e8b936STyler Dauwalder 	}
233d4e8b936STyler Dauwalder 
234d4e8b936STyler Dauwalder 	// We're now going to start creating Icb's, which will expect
235d4e8b936STyler Dauwalder 	// certain parts of the volume to be initialized properly. Thus,
236d4e8b936STyler Dauwalder 	// we initialize those parts here.
2370c342879SSalvatore Benedetto 	if (!status) {
238d4e8b936STyler Dauwalder 		fDevice = device;
239d4e8b936STyler Dauwalder 		fOffset = offset;
2400c342879SSalvatore Benedetto 		fLength = length;
241d4e8b936STyler Dauwalder 		fBlockSize = blockSize;
242d4e8b936STyler Dauwalder 		fBlockShift = blockShift;
243d4e8b936STyler Dauwalder 	}
24420d84995SRene Gollent 	TRACE(("Volume::Mount: device = %d, offset = %Ld, length = %Ld, "
24520d84995SRene Gollent 		"blockSize = %ld, blockShift = %ld\n", device, offset, length,
24689264fe4SSalvatore Benedetto 		blockSize, blockShift));
247d4e8b936STyler Dauwalder 	// At this point we've found a valid set of volume descriptors and
248d4e8b936STyler Dauwalder 	// our partitions are all set up. We now need to investigate the file
249d4e8b936STyler Dauwalder 	// set descriptor pointed to by the logical volume descriptor.
2500c342879SSalvatore Benedetto 	if (!status) {
251e0c80398SSalvatore Benedetto 		TRACE(("Volume::Mount: Partition has been set up\n"));
252d4e8b936STyler Dauwalder 		MemoryChunk chunk(logicalVolumeDescriptor.file_set_address().length());
25321c162a3STyler Dauwalder 
2540c342879SSalvatore Benedetto 		status = chunk.InitCheck();
25521c162a3STyler Dauwalder 
2560c342879SSalvatore Benedetto 		if (!status) {
257d4e8b936STyler Dauwalder 			off_t address;
258d4e8b936STyler Dauwalder 			// Read in the file set descriptor
2590c342879SSalvatore Benedetto 			status = MapBlock(logicalVolumeDescriptor.file_set_address(),
260d4e8b936STyler Dauwalder 				&address);
2610c342879SSalvatore Benedetto 			if (!status)
262d4e8b936STyler Dauwalder 				address <<= blockShift;
2630c342879SSalvatore Benedetto 			if (!status) {
264e0c80398SSalvatore Benedetto 				ssize_t bytesRead
265e0c80398SSalvatore Benedetto 					= read_pos(device, address, chunk.Data(), blockSize);
266d8b4553aSTyler Dauwalder 				if (bytesRead != ssize_t(blockSize)) {
2670c342879SSalvatore Benedetto 					status = B_IO_ERROR;
268e0c80398SSalvatore Benedetto 					TRACE_ERROR(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n",
269d4e8b936STyler Dauwalder 						address, blockSize, bytesRead));
270d4e8b936STyler Dauwalder 				}
271d4e8b936STyler Dauwalder 			}
272d4e8b936STyler Dauwalder 			// See if it's valid, and if so, create the root icb
2730c342879SSalvatore Benedetto 			if (!status) {
2741379cacaSTyler Dauwalder 				file_set_descriptor *fileSet =
2751379cacaSTyler Dauwalder 				 	reinterpret_cast<file_set_descriptor*>(chunk.Data());
27617b66e62STyler Dauwalder 				PDUMP(fileSet);
2770c342879SSalvatore Benedetto 				status = fileSet->tag().id() == TAGID_FILE_SET_DESCRIPTOR
278d8b4553aSTyler Dauwalder 				        ? B_OK : B_ERROR;
2790c342879SSalvatore Benedetto 				if (!status)
2800c342879SSalvatore Benedetto 					status = fileSet->tag().init_check(
28117b66e62STyler Dauwalder 					        logicalVolumeDescriptor.file_set_address().block());
2820c342879SSalvatore Benedetto 				if (!status) {
28321c162a3STyler Dauwalder 					PDUMP(fileSet);
284f50008f9STyler Dauwalder 					fRootIcb = new(nothrow) Icb(this, fileSet->root_directory_icb());
285e0c80398SSalvatore Benedetto 					if (fRootIcb == NULL || fRootIcb->InitCheck() != B_OK)
286e0c80398SSalvatore Benedetto 						return B_NO_MEMORY;
287d8b4553aSTyler Dauwalder 				}
288e0c80398SSalvatore Benedetto 
28920d84995SRene Gollent 				TRACE(("Volume::Mount: Root Node id = %Ld\n", fRootIcb->Id()));
2900c342879SSalvatore Benedetto 				if (!status) {
291e0c80398SSalvatore Benedetto 					status = publish_vnode(fFSVolume, fRootIcb->Id(), fRootIcb,
292e0c80398SSalvatore Benedetto 						&gUDFVnodeOps, fRootIcb->Mode(), 0);
293e0c80398SSalvatore Benedetto 					if (status != B_OK) {
294e0c80398SSalvatore Benedetto 						TRACE_ERROR(("Error creating vnode for root icb! "
2950c342879SSalvatore Benedetto 						       "status = 0x%lx, `%s'\n", status,
2960c342879SSalvatore Benedetto 						       strerror(status)));
297d4e8b936STyler Dauwalder 						// Clean up the icb we created, since _Unset()
298d4e8b936STyler Dauwalder 						// won't do this for us.
299d4e8b936STyler Dauwalder 						delete fRootIcb;
300d4e8b936STyler Dauwalder 						fRootIcb = NULL;
301d4e8b936STyler Dauwalder 					}
30220d84995SRene Gollent 					TRACE(("Volume::Mount: Root vnode published. Id = %Ld\n",
303e0c80398SSalvatore Benedetto 						fRootIcb->Id()));
304d4e8b936STyler Dauwalder 				}
305d4e8b936STyler Dauwalder 			}
30621c162a3STyler Dauwalder 		}
30721c162a3STyler Dauwalder 	}
30821c162a3STyler Dauwalder 
309d4e8b936STyler Dauwalder 	// If we've made it this far, we're good to go; set the volume
310d4e8b936STyler Dauwalder 	// name and then flag that we're mounted. On the other hand, if
311d4e8b936STyler Dauwalder 	// an error occurred, we need to clean things up.
3120c342879SSalvatore Benedetto 	if (!status) {
313d4e8b936STyler Dauwalder 		fName.SetTo(logicalVolumeDescriptor.logical_volume_identifier());
314d4e8b936STyler Dauwalder 		fMounted = true;
315d4e8b936STyler Dauwalder 	} else {
316d4e8b936STyler Dauwalder 		_Unset();
31721c162a3STyler Dauwalder 	}
31821c162a3STyler Dauwalder 
3190c342879SSalvatore Benedetto 	RETURN(status);
3204ac73018STyler Dauwalder }
3214ac73018STyler Dauwalder 
3229fd15595SSalvatore Benedetto 
323a71fd512STyler Dauwalder const char*
324a71fd512STyler Dauwalder Volume::Name() const {
325dce2dc5cSTyler Dauwalder 	return fName.Utf8();
326a71fd512STyler Dauwalder }
3273f4628f1STyler Dauwalder 
328d4e8b936STyler Dauwalder /*! \brief Maps the given logical block to a physical block.
3293f4628f1STyler Dauwalder */
3303f4628f1STyler Dauwalder status_t
3311379cacaSTyler Dauwalder Volume::MapBlock(long_address address, off_t *mappedBlock)
3320d383564STyler Dauwalder {
333e0c80398SSalvatore Benedetto 	TRACE(("Volume::MapBlock: partition = %d, block = %ld, mappedBlock = %p\n",
3341379cacaSTyler Dauwalder 		address.partition(), address.block(), mappedBlock));
335*c530d46cSJérôme Duval 	DEBUG_INIT_ETC("Volume", ("partition = %d, block = %ld, mappedBlock = %p",
336*c530d46cSJérôme Duval 		address.partition(), address.block(), mappedBlock));
337d4e8b936STyler Dauwalder 	status_t error = mappedBlock ? B_OK : B_BAD_VALUE;
338d4e8b936STyler Dauwalder 	if (!error) {
339d4e8b936STyler Dauwalder 		Partition *partition = _GetPartition(address.partition());
340d4e8b936STyler Dauwalder 		error = partition ? B_OK : B_BAD_ADDRESS;
341d4e8b936STyler Dauwalder 		if (!error)
342d4e8b936STyler Dauwalder 			error = partition->MapBlock(address.block(), *mappedBlock);
3433f4628f1STyler Dauwalder 	}
344d4e8b936STyler Dauwalder 	RETURN(error);
3453f4628f1STyler Dauwalder }
3463f4628f1STyler Dauwalder 
347d4e8b936STyler Dauwalder /*! \brief Unsets the volume and deletes any partitions.
348d4e8b936STyler Dauwalder 
349d4e8b936STyler Dauwalder 	Does *not* delete the root icb object.
350d4e8b936STyler Dauwalder */
351d4e8b936STyler Dauwalder void
352d4e8b936STyler Dauwalder Volume::_Unset()
353d4e8b936STyler Dauwalder {
354d8b4553aSTyler Dauwalder 	DEBUG_INIT("Volume");
355e1f5f06bSSalvatore Benedetto 	fFSVolume->id = 0;
356bb4462fdSTyler Dauwalder 	if (fDevice >= 0) {
357e1f5f06bSSalvatore Benedetto 		block_cache_delete(fBlockCache, true);
358237ced11STyler Dauwalder 		close(fDevice);
359bb4462fdSTyler Dauwalder 	}
360237ced11STyler Dauwalder 	fDevice = -1;
361d4e8b936STyler Dauwalder 	fMounted = false;
362d4e8b936STyler Dauwalder 	fOffset = 0;
363d4e8b936STyler Dauwalder 	fLength = 0;
364d4e8b936STyler Dauwalder 	fBlockSize = 0;
365d4e8b936STyler Dauwalder 	fBlockShift = 0;
366dce2dc5cSTyler Dauwalder 	fName.SetTo("", 0);
367d4e8b936STyler Dauwalder 	// delete our partitions
368d4e8b936STyler Dauwalder 	for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++)
369d4e8b936STyler Dauwalder 		_SetPartition(i, NULL);
370d4e8b936STyler Dauwalder }
371d4e8b936STyler Dauwalder 
372d4e8b936STyler Dauwalder /*! \brief Sets the partition associated with the given number after
373d4e8b936STyler Dauwalder 	deleting any previously associated partition.
374d4e8b936STyler Dauwalder 
375d4e8b936STyler Dauwalder 	\param number The partition number (should be the same as the index
376d4e8b936STyler Dauwalder 	              into the lvd's partition map array).
377d4e8b936STyler Dauwalder 	\param partition The new partition (may be NULL).
3783f4628f1STyler Dauwalder */
3793f4628f1STyler Dauwalder status_t
380d4e8b936STyler Dauwalder Volume::_SetPartition(uint number, Partition *partition)
3813f4628f1STyler Dauwalder {
382d4e8b936STyler Dauwalder 	status_t error = number < UDF_MAX_PARTITION_MAPS
383d4e8b936STyler Dauwalder 	                 ? B_OK : B_BAD_VALUE;
384d4e8b936STyler Dauwalder 	if (!error) {
385d4e8b936STyler Dauwalder 		delete fPartitions[number];
386d4e8b936STyler Dauwalder 		fPartitions[number] = partition;
3873f4628f1STyler Dauwalder 	}
388d4e8b936STyler Dauwalder 	return error;
3890d383564STyler Dauwalder }
3900d383564STyler Dauwalder 
391d4e8b936STyler Dauwalder /*! \brief Returns the partition associated with the given number, or
392d4e8b936STyler Dauwalder 	NULL if no such partition exists or the number is invalid.
3933f4628f1STyler Dauwalder */
394e1f5f06bSSalvatore Benedetto Partition*
395d4e8b936STyler Dauwalder Volume::_GetPartition(uint number)
3963f4628f1STyler Dauwalder {
397d4e8b936STyler Dauwalder 	return (number < UDF_MAX_PARTITION_MAPS)
398d4e8b936STyler Dauwalder 	       ? fPartitions[number] : NULL;
3993f4628f1STyler Dauwalder }
400