1/* 2 * Copyright (c) 2001-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include "AppleRAID.h" 24 25#define super IOMedia 26OSDefineMetaClassAndStructors(AppleLVMVolume, IOMedia) 27 28 29OSDictionary * AppleLVMVolume::propsFromHeader(AppleLVMVolumeOnDisk * lve) 30{ 31 OSString * errmsg = 0; 32 OSDictionary * lvProps = OSDynamicCast(OSDictionary, OSUnserializeXML(lve->plist, &errmsg)); 33 if (!lvProps) { 34 if (errmsg) { 35 IOLog("AppleLVMVolume::propsFromHeader - XML parsing failed with %s\n", errmsg->getCStringNoCopy()); 36 errmsg->release(); 37 } 38 return NULL; 39 } 40 41 return lvProps; 42} 43 44 45AppleLVMVolume * AppleLVMVolume::withHeader(AppleLVMVolumeOnDisk * lve, OSDictionary * lvProps) 46{ 47 if (!lve) return false; 48 49 if (!lvProps) lvProps = AppleLVMVolume::propsFromHeader(lve); 50 if (!lvProps) return false; 51 52 AppleLVMVolume *me = new AppleLVMVolume; 53 if (!me) return NULL; 54 55 if (!me->init() || !me->initWithHeader(lvProps)) { 56 me->release(); 57 return NULL; 58 } 59 60 me->lvEntrySize = lve->lvHeaderSize; 61 62 return me; 63} 64 65 66//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 67//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 68//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 69 70 71void AppleLVMVolume::free() 72{ 73 if (lvProps) lvProps->release(); 74 75// if (lvSnapShot) lvSnapShot->release(); 76// if (lvParent) lvParent->release(); 77// if (lvBitMap) lvBitMap->release(); 78 79 AppleLVMLogicalExtent * extent = NULL; 80 AppleLVMLogicalExtent * nextExtent = lvExtent[0]; 81 while (nextExtent) { 82 extent = nextExtent; 83 nextExtent = nextExtent->skip[0]; 84 delete extent; 85 } 86 87 super::free(); 88} 89 90 91bool AppleLVMVolume::init(void) 92{ 93 if (!OSObject::init()) return false; // why? more "using" weirdness? 94 95 lvIndex = 0xffffffff; 96 lvSequenceNumber = 0; 97 lvClaimedSize = 0; 98 lvCalculatedSize = 0; 99 lvTypeID = 0; 100 lvEntryOffset = 0; 101 102 lvExtentCount = 0; 103 lvExtent[0] = NULL; 104 105 lvPublished = false; 106 107 lvParent = NULL; 108 lvSnapShot = NULL; 109 lvBitMap = NULL; 110 111 return true; 112} 113 114bool AppleLVMVolume::initWithHeader(OSDictionary * props) 115{ 116 IOLog1("AppleLVMVolume::initWithHeader() entered\n"); 117 118 if (lvProps) lvProps->release(); 119 lvProps = props; 120 lvProps->retain(); 121 122 if (!getVolumeUUID()) return false; 123 if (!getGroupUUID()) return false; 124 125 OSNumber * number; 126 number = OSDynamicCast(OSNumber, lvProps->getObject(kAppleLVMVolumeSequenceKey)); 127 if (!number) return false; 128 lvSequenceNumber = number->unsigned32BitValue(); 129 130 number = OSDynamicCast(OSNumber, lvProps->getObject(kAppleLVMVolumeExtentCountKey)); 131 if (!number) return false; 132 lvExtentCount = number->unsigned64BitValue(); 133 134 number = OSDynamicCast(OSNumber, lvProps->getObject(kAppleLVMVolumeSizeKey)); 135 if (!number) return false; 136 lvClaimedSize = number->unsigned64BitValue(); 137 138 OSString * type = OSDynamicCast(OSString, lvProps->getObject(kAppleLVMVolumeTypeKey)); 139 if (!type) return false; 140 if (type->isEqualTo(kAppleLVMVolumeTypeConcat)) lvTypeID = kLVMTypeConcat; 141 if (type->isEqualTo(kAppleLVMVolumeTypeBitMap)) lvTypeID = kLVMTypeBitMap; 142 if (type->isEqualTo(kAppleLVMVolumeTypeSnapRO)) lvTypeID = kLVMTypeSnapRO; 143 if (type->isEqualTo(kAppleLVMVolumeTypeSnapRW)) lvTypeID = kLVMTypeSnapRW; 144 if (type->isEqualTo(kAppleLVMVolumeTypeMaster)) lvTypeID = kLVMTypeMaster; 145 if (!lvTypeID) return false; 146 147 lvSnapShot = NULL; // just clear these, they might not exist yet. 148 lvBitMap = NULL; 149 lvParent = NULL; 150 151 IOLog1("AppleLVMVolume::initWithHeader() successful for %s, size = %llu extent count = %llu\n", 152 getVolumeUUIDString(), lvClaimedSize, lvExtentCount); 153 154 return true; 155} 156 157 158//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 159//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 160//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 161 162 163OSDictionary * AppleLVMVolume::getVolumeProperties(void) 164{ 165 // make a copy 166 assert(lvProps); 167 OSDictionary * props = OSDictionary::withDictionary(lvProps, lvProps->getCount() + 2); 168 if (!props) return NULL; 169 170 // not from header 171 OSString * status = NULL; 172 if (isPublished()) { 173 status = OSString::withCString(kAppleRAIDStatusOnline); 174 } else { 175 status = OSString::withCString(kAppleRAIDStatusOffline); 176 } 177 if (status) { 178 props->setObject(kAppleLVMVolumeStatusKey, status); 179 status->release(); 180 } 181 182 props->setObject(kIOBSDNameKey, getDiskName()); 183 184 return props; 185} 186 187 188const OSString * AppleLVMVolume::getVolumeUUID(void) 189{ 190 assert(lvProps); 191 const OSString * string = OSDynamicCast(OSString, lvProps->getObject(kAppleLVMVolumeUUIDKey)); 192 193 return string; 194} 195 196 197const char * AppleLVMVolume::getVolumeUUIDString(void) 198{ 199 const OSString * uuid = getVolumeUUID(); 200 201 return uuid ? uuid->getCStringNoCopy() : "--internal error, uuid not set--"; 202} 203 204 205const OSString * AppleLVMVolume::getDiskName(void) 206{ 207 if (!getPropertyTable()) return NULL; // this panics if not set (unpublished) 208 const OSMetaClassBase * name = getProperty(kIOBSDNameKey); 209 if (!name) return NULL; 210 return OSDynamicCast(OSString, name); 211} 212 213 214const OSString * AppleLVMVolume::getGroupUUID(void) 215{ 216 assert(lvProps); 217 const OSString * lvgUUID = OSDynamicCast(OSString, lvProps->getObject(kAppleLVMGroupUUIDKey)); 218 219 return lvgUUID; 220} 221 222 223const OSString * AppleLVMVolume::getParentUUID(void) 224{ 225 assert(lvProps); 226 const OSString * parentUUID = (OSDynamicCast(OSString, lvProps->getObject(kAppleLVMParentUUIDKey))); 227 228 return parentUUID; 229} 230 231 232const OSString * AppleLVMVolume::getHint(void) // IOMedia also has getContentHint() 233{ 234 assert(lvProps); 235 const OSString * hint = OSDynamicCast(OSString, lvProps->getObject(kAppleLVMVolumeContentHintKey)); 236 237 return hint; 238} 239 240 241//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 242//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 243//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 244 245 246bool AppleLVMVolume::addExtents(AppleLVMGroup * lvg, AppleLVMVolumeOnDisk * lve) 247{ 248 249 // XXX failure cases need to mark lv as broken 250 251 AppleRAIDExtentOnDisk * extent = (AppleRAIDExtentOnDisk *)((char *)lve + lve->lvExtentsStart); 252 if ((void *)(extent + lvExtentCount) > (void *)((char *)lve + lve->lvHeaderSize - sizeof(AppleRAIDExtentOnDisk))) { 253 IOLog("AppleLVMVolume::addExtents() too many extents detected for logical volume \"%s\"\n", getVolumeUUIDString()); 254 return false; 255 } 256 257 UInt64 count = lvExtentCount; 258 while (count) { 259 AppleLVMLogicalExtent * newExtent = addExtent(lvg, extent); 260 if (!newExtent) { 261 IOLog("AppleLVMVolume::addExtents() overlapping extent detected in logical volume \"%s\"\n", getVolumeUUIDString()); 262 return false; 263 } 264 if (!lvg->addExtentToLVG(newExtent)) { 265 IOLog("AppleLVMVolume::addExtents() overlapping logical volumes detected for logical volume \"%s\"\n", getVolumeUUIDString()); 266 return false; 267 } 268 count--; 269 extent++; 270 } 271 272 if (lvClaimedSize != lvCalculatedSize) { 273 IOLog("AppleLVMVolume::addExtents() size error for extent list for logical volume \"%s\"\n", getVolumeUUIDString()); 274 IOLog("AppleLVMVolume::addExtents() expected size %llu, calculated size %llu\n", lvClaimedSize, lvCalculatedSize); 275 return false; 276 } 277 278 IOLog1("AppleLVMVolume::addExtents() successful for %s, extent count = %llu, size = %llu\n", 279 getVolumeUUIDString(), lvExtentCount, lvCalculatedSize); 280 281 return true; 282} 283 284AppleLVMLogicalExtent * AppleLVMVolume::addExtent(AppleLVMGroup * lvg, AppleRAIDExtentOnDisk * extentOnDisk) 285{ 286 AppleLVMLogicalExtent ** extent = &lvExtent[0]; 287 AppleLVMLogicalExtent * extentInCore = new AppleLVMLogicalExtent; 288 UInt64 volumeOffset = 0; 289 290 // find end of list 291 while (*extent) { 292 volumeOffset += (*extent)->lvExtentSize; 293 extent = &((*extent)->skip[0]); 294 } 295 296 // XXX hm, there is no range checking here 297 298 extentInCore->skip[0] = 0; 299 extentInCore->lvgNext = 0; 300 301 extentInCore->lvMemberIndex = lvg->getMemberIndexFromOffset(extentOnDisk->extentByteOffset); 302 303 extentInCore->lvExtentVolumeOffset = volumeOffset; 304 extentInCore->lvExtentGroupOffset = extentOnDisk->extentByteOffset; 305 extentInCore->lvExtentMemberOffset = extentOnDisk->extentByteOffset - lvg->getMemberStartingOffset(extentInCore->lvMemberIndex); 306 307 extentInCore->lvExtentSize = extentOnDisk->extentByteCount; 308 309 *extent = extentInCore; 310 lvCalculatedSize = volumeOffset + extentInCore->lvExtentSize; 311 312 IOLog1("AppleLVMVolume::addExtent() successful, offset = %llu, size = %llu totalSize = %llu\n", // XXX <<<<<<<< log2 313 extentInCore->lvExtentVolumeOffset, extentInCore->lvExtentSize, lvCalculatedSize); 314 315 return extentInCore; 316} 317 318bool AppleLVMVolume::removeExtents(AppleLVMGroup * lvg) 319{ 320 AppleLVMLogicalExtent * extent = lvExtent[0]; 321 AppleLVMLogicalExtent * prevExtent; 322 lvExtent[0] = NULL; 323 lvCalculatedSize = 0; 324 while (extent) { 325 326 lvg->removeExtentFromLVG(extent); 327 328 prevExtent = extent; 329 extent = extent->skip[0]; 330 331 delete prevExtent; 332 } 333 334 return true; 335} 336 337AppleLVMLogicalExtent * AppleLVMVolume::findExtent(UInt64 offset) 338{ 339 // find the extent relative to the offset in this volume 340 341 AppleLVMLogicalExtent * extent = lvExtent[0]; 342 AppleLVMLogicalExtent * nextExtent = extent ? extent->skip[0] : NULL; 343 while (nextExtent) { 344 if (nextExtent->lvExtentVolumeOffset > offset) break; 345 extent = nextExtent; 346 nextExtent = nextExtent->skip[0]; 347 } 348 349 return extent; 350} 351 352bool AppleLVMVolume::hasExtentsOnMember(AppleRAIDMember * member) 353{ 354 UInt32 memberIndex = member->getMemberIndex(); 355 356 AppleLVMLogicalExtent * extent = lvExtent[0]; 357 while (extent) { 358 if (extent->lvMemberIndex == memberIndex) return true; 359 extent = extent->skip[0]; 360 } 361 362 return false; 363} 364 365bool AppleLVMVolume::buildExtentList(AppleRAIDExtentOnDisk * extentList) 366{ 367 AppleLVMLogicalExtent * incoreExtent = lvExtent[0]; 368 while (incoreExtent) { 369 extentList->extentByteOffset = incoreExtent->lvExtentGroupOffset; 370 extentList->extentByteCount = incoreExtent->lvExtentSize; 371 372 extentList++; 373 incoreExtent = incoreExtent->skip[0]; 374 } 375 376 return true; 377} 378 379 380// 381// snapshot stuff 382// 383 384bool AppleLVMVolume::setParent(AppleLVMVolume * parent) 385{ 386 lvParent = parent; 387 388 // XXXSNAP 389 390 return true; 391} 392 393bool AppleLVMVolume::setBitMap(AppleLVMVolume * bitmap) 394{ 395 lvBitMap = bitmap; 396 397 // XXXSNAP 398 399 return true; 400} 401 402 403bool AppleLVMVolume::setSnapShot(AppleLVMVolume * snapshot) 404{ 405 lvSnapShot = snapshot; 406 407 // XXXSNAP 408 409 return true; 410} 411 412 413bool AppleLVMVolume::zeroVolume() 414{ 415 assert(isABitMap()); 416 417 // XXXSNAP 418 // call into a bitmap object? 419 420 return true; 421} 422 423