AppleLVMGroup.h   [plain text]


/*
 * Copyright (c) 2001-2007 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * The contents of this file constitute Original Code as defined in and
 * are subject to the Apple Public Source License Version 1.1 (the
 * "License").  You may not use this file except in compliance with the
 * License.  Please obtain a copy of the License at
 * http://www.apple.com/publicsource and read it before using this file.
 *
 * This Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * @APPLE_LICENSE_HEADER_END@
 */


#ifndef _APPLELVMGROUP_H
#define _APPLELVMGROUP_H

#define kAppleRAIDLevelNameLVG "LVG"

// The LVG TOC is part of the primary meta data and is duplicated across all disks.
// The primary meta data has a sequence number as do the logical volume enties
// and the raid header.  The order of writing these out should be first the logical
// volume entry, then the table of contents and finally the raid header.  Any structure
// with sequence number that is higher than a raid header sequence number can be
// assumed to be part of a failed update to the logical volume group.

typedef struct AppleLVGTOCEntryOnDisk {

    char			lveUUID[64];		// XXX lve -> toc
    UInt64			lveVolumeSize;
    UInt64			lveEntryOffset;
    UInt64			lveEntrySize;
    char			reserved[40];		// 64 + 8 + 8 + 8 + 40 = 128

} AppleLVGTOCEntryOnDisk;

#define AppleLVGTOCEntrySanityCheck()	assert(sizeof(AppleLVGTOCEntryOnDisk) == 128);

#define ByteSwapLVGTOCEntry(entry) \
{ \
        (entry)->lveVolumeSize		= OSSwapBigToHostInt64((entry)->lveVolumeSize); \
        (entry)->lveEntryOffset		= OSSwapBigToHostInt64((entry)->lveEntryOffset); \
        (entry)->lveEntrySize		= OSSwapBigToHostInt32((entry)->lveEntrySize); \
}

#ifdef KERNEL


class AppleLVMGroup : public AppleRAIDSet
{
    OSDeclareDefaultStructors(AppleLVMGroup);

    friend class AppleRAIDStorageRequest;
    
 private:
    UInt64 *				arMemberBlockCounts;
    UInt64 *				arMemberStartingOffset;
    AppleLVMVolume **			arMetaDataVolumes;
    UInt32				arExpectingLiveAdd;
    
    bool				arPrimaryNeedsUpdate;
    IOBufferMemoryDescriptor *		arPrimaryBuffer;
    UInt32				arLogicalVolumeCount;
    UInt32				arLogicalVolumeActiveCount;
    AppleLVMVolume **			arLogicalVolumes;
    
    UInt64				arExtentCount;
    AppleLVMLogicalExtent *		arExtents;

 protected:
    virtual bool init();
    virtual void free();

    virtual void unpauseSet(void);
    virtual bool updateLVGTOC(void);
    virtual UInt64 findFreeLVEOffset(AppleLVMVolume * newLV);
    
 public:
    static AppleRAIDSet * createRAIDSet(AppleRAIDMember * firstMember);
    virtual bool addSpare(AppleRAIDMember * member);
    virtual bool addMember(AppleRAIDMember * member);
    virtual bool removeMember(AppleRAIDMember * member, IOOptionBits options);

    virtual bool resizeSet(UInt32 newMemberCount);
    virtual bool startSet(void);
    virtual bool publishSet(void);
    virtual bool unpublishSet(void);
    virtual bool handleOpen(IOService * client, IOOptionBits options, void * access);

    virtual UInt32 getMaxRequestCount(void) const { return 16; };   // XXX 32bit / min lv size + 1
    
    virtual UInt64 getMemberSize(UInt32 memberIndex) const;
    virtual UInt64 getMemberStartingOffset(UInt32 memberIndex) const;
    virtual UInt32 getMemberIndexFromOffset(UInt64 offset) const;
    virtual bool memberOffsetFromLVGOffset(UInt64 lvgOffset, AppleRAIDMember ** member, UInt64 * memberOffset);
    virtual OSDictionary * getSetProperties(void);

    virtual AppleRAIDMemoryDescriptor * allocateMemoryDescriptor(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex);

    // LVG stuff
    
    virtual IOBufferMemoryDescriptor * readPrimaryMetaData(AppleRAIDMember * member);
    virtual IOReturn writePrimaryMetaData(IOBufferMemoryDescriptor * primaryBuffer);

    virtual IOBufferMemoryDescriptor * readLogicalVolumeEntry(UInt64 offset, UInt32 size);
    virtual IOReturn writeLogicalVolumeEntry(IOBufferMemoryDescriptor * lveBuffer, UInt64 offset);
    virtual bool clearLogicalVolumeEntry(UInt64 offset, UInt32 size);
    
    virtual bool initializeSecondary(void);
    virtual bool addExtentToLVG(AppleLVMLogicalExtent * newExtent);
    virtual bool removeExtentFromLVG(AppleLVMLogicalExtent * extent);
    virtual bool buildExtentList(AppleRAIDExtentOnDisk * onDiskExtent);
    virtual UInt64 calculateFreeSpace(void);

    inline UInt64 getExtentCount(void) const	{ return arExtentCount; };
    
    virtual bool addLogicalVolumeToTOC(AppleLVMVolume * lv);
    virtual bool removeLogicalVolumeFromTOC(AppleLVMVolume * lv);
    virtual OSArray * buildLogicalVolumeListFromTOC(AppleRAIDMember * member);
    virtual bool initializeVolumes(AppleRAIDPrimaryOnDisk * primary);

    virtual IOReturn createLogicalVolume(OSDictionary * lveProps, AppleLVMVolumeOnDisk * lvOnDisk);
    virtual IOReturn updateLogicalVolume(AppleLVMVolume * lv, OSDictionary * lveProps, AppleLVMVolumeOnDisk * lve);
    virtual IOReturn destroyLogicalVolume(AppleLVMVolume * lv);

    virtual bool publishVolume(AppleLVMVolume * lv);
    virtual bool unpublishVolume(AppleLVMVolume * lv);

    virtual void completeRAIDRequest(AppleRAIDStorageRequest * storageRequest);
};



class AppleLVMMemoryDescriptor : public AppleRAIDMemoryDescriptor
{
    OSDeclareDefaultStructors(AppleLVMMemoryDescriptor);
    
    friend class AppleRAIDEventSource;		// XXX remove this
    friend class AppleLVMGroup;			// XXX remove this
    
 private:
    UInt64		mdRequestIndex;
    IOByteCount		mdRequestOffset;
    
 protected:
    virtual bool initWithStorageRequest(AppleRAIDStorageRequest * storageRequest, UInt32 requestIndex);
    virtual bool configureForMemoryDescriptor(IOMemoryDescriptor * memoryDescriptor, UInt64 requestStart, UInt64 requestSize, AppleLVMVolume * lv);
    
 public:
    static AppleRAIDMemoryDescriptor * withStorageRequest(AppleRAIDStorageRequest * storageRequest, UInt32 memberIndex);
    virtual addr64_t getPhysicalSegment(IOByteCount offset, IOByteCount * length, IOOptionBits options = 0);
};


#endif KERNEL

#endif /* ! _APPLELVMGROUP_H */