From 5d22fa967af0e2e326ad9f431bce17270eb68941 Mon Sep 17 00:00:00 2001
From: Ingo Weinhold <ingo_weinhold@gmx.de>
Date: Tue, 15 Jul 2003 01:00:24 +0000
Subject: [PATCH] Shadow partition related changes: * Fixed handling of the
 deletion (removal) of shadow partitions. Formerly   the shadow partition
 corresponding to the disk device wasn't removed   properly. * Added a
 shadow_id field to the user_partition_data structure which   contains the ID
 of the shadow partition, if it is one. The id field   will hold the ID of the
 physical partition.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3974 a95241bf-73f2-0310-859d-f6bbb57e9c96
---
 .../kernel/disk_device_manager/KDiskDevice.h  |  4 +++
 .../kernel/disk_device_manager/KPartition.h   |  5 +--
 .../disk_device_manager/KPhysicalPartition.h  |  2 +-
 .../disk_device_manager/KShadowPartition.h    |  3 ++
 .../core/disk_device_manager/KDiskDevice.cpp  | 33 +++++++++++++++++++
 .../core/disk_device_manager/KPartition.cpp   |  5 +--
 .../KPhysicalPartition.cpp                    | 22 +++++++------
 .../disk_device_manager/KShadowPartition.cpp  | 15 +++++++++
 8 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/headers/private/kernel/disk_device_manager/KDiskDevice.h b/headers/private/kernel/disk_device_manager/KDiskDevice.h
index f30e941bf6..b16c99041b 100644
--- a/headers/private/kernel/disk_device_manager/KDiskDevice.h
+++ b/headers/private/kernel/disk_device_manager/KDiskDevice.h
@@ -36,6 +36,8 @@ public:
 	void WriteUnlock();
 	bool IsWriteLocked();
 
+	virtual bool PrepareForRemoval();
+
 	virtual void SetID(partition_id id);
 
 	virtual status_t PublishDevice();
@@ -63,6 +65,8 @@ public:
 	disk_device_data *DeviceData();
 	const disk_device_data *DeviceData() const;
 
+	status_t CreateShadowDevice(team_id team);
+	status_t DeleteShadowDevice();
 	void SetShadowOwner(team_id team);
 	team_id ShadowOwner() const;
 
diff --git a/headers/private/kernel/disk_device_manager/KPartition.h b/headers/private/kernel/disk_device_manager/KPartition.h
index a5c00f8642..cb0e25527d 100644
--- a/headers/private/kernel/disk_device_manager/KPartition.h
+++ b/headers/private/kernel/disk_device_manager/KPartition.h
@@ -133,7 +133,7 @@ public:
 	// Shadow Partition
 
 	virtual status_t CreateShadowPartition();	// creates a complete tree
-	virtual void DeleteShadowPartition();		// deletes ...
+	virtual void UnsetShadowPartition(bool doDelete);
 	virtual KShadowPartition *ShadowPartition() const = 0;
 	virtual bool IsShadowPartition() const = 0;
 	virtual KPhysicalPartition *PhysicalPartition() const = 0;
@@ -153,7 +153,8 @@ public:
 	void SetContentCookie(void *cookie);
 	void *ContentCookie() const;
 
-	void WriteUserData(UserDataWriter &writer, user_partition_data *data);
+	virtual void WriteUserData(UserDataWriter &writer,
+							   user_partition_data *data);
 
 	virtual void Dump(bool deep, int32 level);
 
diff --git a/headers/private/kernel/disk_device_manager/KPhysicalPartition.h b/headers/private/kernel/disk_device_manager/KPhysicalPartition.h
index 769465d57f..e3780002b4 100644
--- a/headers/private/kernel/disk_device_manager/KPhysicalPartition.h
+++ b/headers/private/kernel/disk_device_manager/KPhysicalPartition.h
@@ -34,7 +34,7 @@ public:
 	// Shadow Partition
 
 	virtual status_t CreateShadowPartition();	// creates a complete tree
-	virtual void DeleteShadowPartition();		// deletes ...
+	virtual void UnsetShadowPartition(bool doDelete);
 	virtual KShadowPartition *ShadowPartition() const;
 	virtual bool IsShadowPartition() const;
 	virtual KPhysicalPartition *PhysicalPartition() const;
diff --git a/headers/private/kernel/disk_device_manager/KShadowPartition.h b/headers/private/kernel/disk_device_manager/KShadowPartition.h
index 5140650697..18b515020c 100644
--- a/headers/private/kernel/disk_device_manager/KShadowPartition.h
+++ b/headers/private/kernel/disk_device_manager/KShadowPartition.h
@@ -29,6 +29,9 @@ public:
 
 	void SyncWithPhysicalPartition();
 
+	virtual void WriteUserData(UserDataWriter &writer,
+							   user_partition_data *data);
+
 	virtual void Dump(bool deep, int32 level);
 
 protected:
diff --git a/src/kernel/core/disk_device_manager/KDiskDevice.cpp b/src/kernel/core/disk_device_manager/KDiskDevice.cpp
index 458d267ed7..67216120a3 100644
--- a/src/kernel/core/disk_device_manager/KDiskDevice.cpp
+++ b/src/kernel/core/disk_device_manager/KDiskDevice.cpp
@@ -161,6 +161,15 @@ KDiskDevice::IsWriteLocked()
 	return fLocker.IsWriteLocked();
 }
 
+// PrepareForRemoval
+bool
+KDiskDevice::PrepareForRemoval()
+{
+	if (ShadowOwner() >= 0)
+		DeleteShadowDevice();
+	return KPhysicalPartition::PrepareForRemoval();
+}
+
 // SetID
 void
 KDiskDevice::SetID(partition_id id)
@@ -284,6 +293,30 @@ KDiskDevice::DeviceData() const
 	return &fDeviceData;
 }
 
+// CreateShadowDevice
+status_t
+KDiskDevice::CreateShadowDevice(team_id team)
+{
+	if (fShadowOwner >= 0 || team < 0 || !HasMedia())
+		return B_BAD_VALUE;
+	// create the shadow partitions
+	status_t error = CreateShadowPartition();
+	if (error == B_OK)
+		SetShadowOwner(team);
+	return error;
+}
+
+// DeleteShadowDevice
+status_t
+KDiskDevice::DeleteShadowDevice()
+{
+	if (fShadowOwner < 0)
+		return B_BAD_VALUE;
+	UnsetShadowPartition(true);
+	SetShadowOwner(-1);
+	return B_OK;
+}
+
 // SetShadowOwner
 void
 KDiskDevice::SetShadowOwner(team_id team)
diff --git a/src/kernel/core/disk_device_manager/KPartition.cpp b/src/kernel/core/disk_device_manager/KPartition.cpp
index e0e0f6e89a..e6f69fa28e 100644
--- a/src/kernel/core/disk_device_manager/KPartition.cpp
+++ b/src/kernel/core/disk_device_manager/KPartition.cpp
@@ -658,9 +658,9 @@ KPartition::CreateShadowPartition()
 	return B_ERROR;
 }
 
-// DeleteShadowPartition
+// UnsetShadowPartition
 void
-KPartition::DeleteShadowPartition()
+KPartition::UnsetShadowPartition(bool doDelete)
 {
 	// implemented by derived classes
 }
@@ -743,6 +743,7 @@ KPartition::WriteUserData(UserDataWriter &writer, user_partition_data *data)
 	// fill in data
 	if (data) {
 		data->id = ID();
+		data->shadow_id = -1;
 		data->offset = Offset();
 		data->size = Size();
 		data->block_size = BlockSize();
diff --git a/src/kernel/core/disk_device_manager/KPhysicalPartition.cpp b/src/kernel/core/disk_device_manager/KPhysicalPartition.cpp
index d09c9ad28e..50740ae045 100644
--- a/src/kernel/core/disk_device_manager/KPhysicalPartition.cpp
+++ b/src/kernel/core/disk_device_manager/KPhysicalPartition.cpp
@@ -42,7 +42,7 @@ KPhysicalPartition::PrepareForRemoval()
 {
 	bool result = KPartition::PrepareForRemoval();
 	if (result) {
-		DeleteShadowPartition();
+		UnsetShadowPartition(false);
 		UnpublishDevice();
 	}
 	return result;
@@ -179,29 +179,31 @@ KPhysicalPartition::CreateShadowPartition()
 		// cleanup on error
 		if (error != B_OK) {
 			for (int32 k = 0; k <= i; i++)
-				ChildAt(k)->DeleteShadowPartition();
-			DeleteShadowPartition();
+				ChildAt(k)->UnsetShadowPartition(true);
+			UnsetShadowPartition(true);
 			return error;
 		}
 	}
 	return B_OK;
 }
 
-// DeleteShadowPartition
+// UnsetShadowPartition
 void
-KPhysicalPartition::DeleteShadowPartition()
+KPhysicalPartition::UnsetShadowPartition(bool doDelete)
 {
 	if (!fShadowPartition)
 		return;
-	// delete children's shadows
+	// unset children's shadows
 	for (int32 i = 0; KPartition *child = ChildAt(i); i++)
-		child->DeleteShadowPartition();
-	// delete the thing
+		child->UnsetShadowPartition(false);
+	// unset the thing
 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
 	if (ManagerLocker locker = manager) {
 		fShadowPartition->UnsetPhysicalPartition();
-		PartitionRegistrar _(fShadowPartition);
-		manager->PartitionRemoved(fShadowPartition);
+		if (doDelete) {
+			PartitionRegistrar _(fShadowPartition);
+			manager->PartitionRemoved(fShadowPartition);
+		}
 		fShadowPartition = NULL;
 	}
 }
diff --git a/src/kernel/core/disk_device_manager/KShadowPartition.cpp b/src/kernel/core/disk_device_manager/KShadowPartition.cpp
index f17e63dde9..0221ccea28 100644
--- a/src/kernel/core/disk_device_manager/KShadowPartition.cpp
+++ b/src/kernel/core/disk_device_manager/KShadowPartition.cpp
@@ -10,6 +10,7 @@
 #include <Drivers.h>
 #include <Errors.h>
 
+#include "ddm_userland_interface.h"
 #include "KDiskDevice.h"
 #include "KDiskDeviceManager.h"
 #include "KDiskDeviceUtils.h"
@@ -107,6 +108,20 @@ KShadowPartition::SyncWithPhysicalPartition()
 	SetContentParameters(fPhysicalPartition->ContentParameters());
 }
 
+// WriteUserData
+void
+KShadowPartition::WriteUserData(UserDataWriter &writer,
+								user_partition_data *data)
+{
+	KPartition::WriteUserData(writer, data);
+	// fix the ID in the user data
+	if (data) {
+		if (fPhysicalPartition)
+			data->id = fPhysicalPartition->ID();
+		data->shadow_id = ID();
+	}
+}
+
 // Dump
 void
 KShadowPartition::Dump(bool deep, int32 level)