xref: /haiku/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp (revision 4644c7cc9276e5a7df9bfb20386490d7d9610e5a)
10cbc783bSAxel Dörfler /*
2eac83fb3SAxel Dörfler  * Copyright 2003-2017, Haiku, Inc. All Rights Reserved.
30cbc783bSAxel Dörfler  * Distributed under the terms of the MIT License.
42dc6403dSIngo Weinhold  *
50cbc783bSAxel Dörfler  * Authors:
6285f4cf4SIngo Weinhold  *		Ingo Weinhold, ingo_weinhold@gmx.de
738bbc957SAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
80cbc783bSAxel Dörfler  */
90cbc783bSAxel Dörfler 
100cbc783bSAxel Dörfler /*! \file ddm_userland_interface.cpp
110cbc783bSAxel Dörfler 
120cbc783bSAxel Dörfler  	\brief Interface for userspace calls.
132dc6403dSIngo Weinhold */
142d690920SAxel Dörfler 
1549fb53eeSAxel Dörfler #include <ddm_userland_interface.h>
1649fb53eeSAxel Dörfler 
172d690920SAxel Dörfler #include <stdlib.h>
182d690920SAxel Dörfler 
192d690920SAxel Dörfler #include <AutoDeleter.h>
2038bbc957SAxel Dörfler #include <fs/KPath.h>
212d690920SAxel Dörfler #include <KDiskDevice.h>
222d690920SAxel Dörfler #include <KDiskDeviceManager.h>
232d690920SAxel Dörfler #include <KDiskDeviceUtils.h>
242d690920SAxel Dörfler #include <KDiskSystem.h>
252d690920SAxel Dörfler #include <KFileDiskDevice.h>
262d690920SAxel Dörfler #include <syscall_args.h>
272d690920SAxel Dörfler 
282d690920SAxel Dörfler #include "UserDataWriter.h"
292d690920SAxel Dörfler 
302d690920SAxel Dörfler using namespace BPrivate::DiskDevice;
312d690920SAxel Dörfler 
322d690920SAxel Dörfler // debugging
332d690920SAxel Dörfler #define ERROR(x)
342d690920SAxel Dörfler 
35bf95c9aeSIngo Weinhold 
367b45b55bSIngo Weinhold // TODO: Replace all instances, when it has been decided how to handle
377b45b55bSIngo Weinhold // notifications during jobs.
387b45b55bSIngo Weinhold #define DUMMY_JOB_ID	0
397b45b55bSIngo Weinhold 
407b45b55bSIngo Weinhold 
412d690920SAxel Dörfler /*! \brief Wrapper around user_strlcpy() that returns a status_t
422d690920SAxel Dörfler 	indicating appropriate success or failure.
432d690920SAxel Dörfler 
442d690920SAxel Dörfler 	\param allowTruncation If \c true, does not return an error if
452d690920SAxel Dörfler 	       \a from is longer than \to. If \c false, returns \c B_NAME_TOO_LONG
462d690920SAxel Dörfler 	       if \a from is longer than \to.
472d690920SAxel Dörfler */
48d6e565c7SIngo Weinhold static status_t
ddm_strlcpy(char * to,const char * from,size_t size,bool allowTruncation=false)49d6e565c7SIngo Weinhold ddm_strlcpy(char *to, const char *from, size_t size,
50d6e565c7SIngo Weinhold 	bool allowTruncation = false)
51d6e565c7SIngo Weinhold {
52d6e565c7SIngo Weinhold 	ssize_t fromLen = user_strlcpy(to, from, size);
53d6e565c7SIngo Weinhold 	if (fromLen < 0)
54d6e565c7SIngo Weinhold 		return fromLen;
55d6e565c7SIngo Weinhold 	if ((size_t)fromLen >= size && !allowTruncation)
56d6e565c7SIngo Weinhold 		return B_NAME_TOO_LONG;
57d6e565c7SIngo Weinhold 	return B_OK;
582d690920SAxel Dörfler }
592d690920SAxel Dörfler 
60d6e565c7SIngo Weinhold 
617b45b55bSIngo Weinhold template<typename Type>
627b45b55bSIngo Weinhold static inline status_t
copy_from_user_value(Type & value,const Type * userValue)637b45b55bSIngo Weinhold copy_from_user_value(Type& value, const Type* userValue)
647b45b55bSIngo Weinhold {
65*4644c7ccSJérôme Duval 	if (userValue == NULL)
667b45b55bSIngo Weinhold 		return B_BAD_VALUE;
677b45b55bSIngo Weinhold 
687b45b55bSIngo Weinhold 	if (!IS_USER_ADDRESS(userValue))
697b45b55bSIngo Weinhold 		return B_BAD_ADDRESS;
707b45b55bSIngo Weinhold 
717b45b55bSIngo Weinhold 	return user_memcpy(&value, userValue, sizeof(Type));
727b45b55bSIngo Weinhold }
737b45b55bSIngo Weinhold 
747b45b55bSIngo Weinhold 
757b45b55bSIngo Weinhold template<typename Type>
767b45b55bSIngo Weinhold static inline status_t
copy_to_user_value(Type * userValue,const Type & value)777b45b55bSIngo Weinhold copy_to_user_value(Type* userValue, const Type& value)
787b45b55bSIngo Weinhold {
79*4644c7ccSJérôme Duval 	if (userValue == NULL)
807b45b55bSIngo Weinhold 		return B_BAD_VALUE;
817b45b55bSIngo Weinhold 
827b45b55bSIngo Weinhold 	if (!IS_USER_ADDRESS(userValue))
837b45b55bSIngo Weinhold 		return B_BAD_ADDRESS;
847b45b55bSIngo Weinhold 
857b45b55bSIngo Weinhold 	return user_memcpy(userValue, &value, sizeof(Type));
867b45b55bSIngo Weinhold }
877b45b55bSIngo Weinhold 
887b45b55bSIngo Weinhold 
897b45b55bSIngo Weinhold template<bool kAllowsNull>
907b45b55bSIngo Weinhold struct UserStringParameter {
917b45b55bSIngo Weinhold 	char*	value;
927b45b55bSIngo Weinhold 
UserStringParameterUserStringParameter937b45b55bSIngo Weinhold 	inline UserStringParameter()
947b45b55bSIngo Weinhold 		: value(NULL)
957b45b55bSIngo Weinhold 	{
967b45b55bSIngo Weinhold 	}
977b45b55bSIngo Weinhold 
~UserStringParameterUserStringParameter987b45b55bSIngo Weinhold 	inline ~UserStringParameter()
997b45b55bSIngo Weinhold 	{
1007b45b55bSIngo Weinhold 		free(value);
1017b45b55bSIngo Weinhold 	}
1027b45b55bSIngo Weinhold 
InitUserStringParameter1037b45b55bSIngo Weinhold 	inline status_t Init(const char* userValue, size_t maxSize)
1047b45b55bSIngo Weinhold 	{
1057b45b55bSIngo Weinhold 		if (userValue == NULL) {
1067b45b55bSIngo Weinhold 			if (!kAllowsNull)
1077b45b55bSIngo Weinhold 				return B_BAD_VALUE;
1087b45b55bSIngo Weinhold 
1097b45b55bSIngo Weinhold 			return B_OK;
1107b45b55bSIngo Weinhold 		}
1117b45b55bSIngo Weinhold 
1127b45b55bSIngo Weinhold 		if (!IS_USER_ADDRESS(userValue))
1137b45b55bSIngo Weinhold 			return B_BAD_ADDRESS;
1147b45b55bSIngo Weinhold 
1157b45b55bSIngo Weinhold 		value = (char*)malloc(maxSize);
1167b45b55bSIngo Weinhold 		if (value == NULL)
1177b45b55bSIngo Weinhold 			return B_NO_MEMORY;
1187b45b55bSIngo Weinhold 
1197b45b55bSIngo Weinhold 		ssize_t bytesCopied = user_strlcpy(value, userValue, maxSize);
1207b45b55bSIngo Weinhold 		if (bytesCopied < 0)
1217b45b55bSIngo Weinhold 			return bytesCopied;
1227b45b55bSIngo Weinhold 
1237b45b55bSIngo Weinhold 		if ((size_t)bytesCopied >= maxSize)
1247b45b55bSIngo Weinhold 			return B_BUFFER_OVERFLOW;
1257b45b55bSIngo Weinhold 
1267b45b55bSIngo Weinhold 		return B_OK;
1277b45b55bSIngo Weinhold 	}
1286cc43bfbSAxel Dörfler 
operator const char*UserStringParameter1296cc43bfbSAxel Dörfler 	inline operator const char*()
1306cc43bfbSAxel Dörfler 	{
1316cc43bfbSAxel Dörfler 		return value;
1326cc43bfbSAxel Dörfler 	}
1336cc43bfbSAxel Dörfler 
operator char*UserStringParameter1346cc43bfbSAxel Dörfler 	inline operator char*()
1356cc43bfbSAxel Dörfler 	{
1366cc43bfbSAxel Dörfler 		return value;
1376cc43bfbSAxel Dörfler 	}
1387b45b55bSIngo Weinhold };
1397b45b55bSIngo Weinhold 
1407b45b55bSIngo Weinhold 
14132788795SIngo Weinhold #if 0
142d6e565c7SIngo Weinhold static void
1432d690920SAxel Dörfler move_descendants(KPartition *partition, off_t moveBy)
1442d690920SAxel Dörfler {
1452d690920SAxel Dörfler 	if (!partition)
1462d690920SAxel Dörfler 		return;
1472d690920SAxel Dörfler 	partition->SetOffset(partition->Offset() + moveBy);
1482d690920SAxel Dörfler 	// move children
1492d690920SAxel Dörfler 	for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
1502d690920SAxel Dörfler 		move_descendants(child, moveBy);
1512d690920SAxel Dörfler }
1522d690920SAxel Dörfler 
153d6e565c7SIngo Weinhold 
154d6e565c7SIngo Weinhold static status_t
1552d690920SAxel Dörfler move_descendants_contents(KPartition *partition)
1562d690920SAxel Dörfler {
1572d690920SAxel Dörfler 	if (!partition)
1582d690920SAxel Dörfler 		return B_BAD_VALUE;
1592d690920SAxel Dörfler 	// implicit content disk system changes
1602d690920SAxel Dörfler 	KDiskSystem *diskSystem = partition->DiskSystem();
1612d690920SAxel Dörfler 	if (diskSystem || partition->AlgorithmData()) {
1622d690920SAxel Dörfler 		status_t error = diskSystem->ShadowPartitionChanged(partition,
163bf95c9aeSIngo Weinhold 			NULL, B_PARTITION_MOVE);
1642d690920SAxel Dörfler 		if (error != B_OK)
1652d690920SAxel Dörfler 			return error;
1662d690920SAxel Dörfler 	}
1672d690920SAxel Dörfler 	// move children's contents
1682d690920SAxel Dörfler 	for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
1692d690920SAxel Dörfler 		status_t error = move_descendants_contents(child);
1702d690920SAxel Dörfler 		if (error != B_OK)
1712d690920SAxel Dörfler 			return error;
1722d690920SAxel Dörfler 	}
1732d690920SAxel Dörfler 	return B_OK;
1742d690920SAxel Dörfler }
17532788795SIngo Weinhold #endif // 0
1762d690920SAxel Dörfler 
177d6e565c7SIngo Weinhold 
1782d690920SAxel Dörfler partition_id
_user_get_next_disk_device_id(int32 * _cookie,size_t * neededSize)1792d690920SAxel Dörfler _user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize)
1802d690920SAxel Dörfler {
1812d690920SAxel Dörfler 	int32 cookie;
182*4644c7ccSJérôme Duval 	status_t error = copy_from_user_value(cookie, _cookie);
183*4644c7ccSJérôme Duval 	if (error != B_OK)
184*4644c7ccSJérôme Duval 		return error;
1852d690920SAxel Dörfler 
1862d690920SAxel Dörfler 	partition_id id = B_ENTRY_NOT_FOUND;
1872d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
1882d690920SAxel Dörfler 	// get the next device
1892d690920SAxel Dörfler 	if (KDiskDevice *device = manager->RegisterNextDevice(&cookie)) {
1902d690920SAxel Dörfler 		PartitionRegistrar _(device, true);
1912d690920SAxel Dörfler 		id = device->ID();
192*4644c7ccSJérôme Duval 		if (neededSize != NULL) {
1932d690920SAxel Dörfler 			if (DeviceReadLocker locker = device) {
1942d690920SAxel Dörfler 				// get the needed size
1952d690920SAxel Dörfler 				UserDataWriter writer;
1968354dac7SIngo Weinhold 				device->WriteUserData(writer);
1976cc43bfbSAxel Dörfler 				status_t status = copy_to_user_value(neededSize,
1986cc43bfbSAxel Dörfler 					writer.AllocatedSize());
1996cc43bfbSAxel Dörfler 				if (status != B_OK)
2006cc43bfbSAxel Dörfler 					return status;
201*4644c7ccSJérôme Duval 			} else
2022d690920SAxel Dörfler 				id = B_ERROR;
2032d690920SAxel Dörfler 		}
2042d690920SAxel Dörfler 	}
205*4644c7ccSJérôme Duval 
206*4644c7ccSJérôme Duval 	error = copy_to_user_value(_cookie, cookie);
207*4644c7ccSJérôme Duval 	if (error != B_OK)
208*4644c7ccSJérôme Duval 		return error;
2092d690920SAxel Dörfler 	return id;
2102d690920SAxel Dörfler }
2112d690920SAxel Dörfler 
212d6e565c7SIngo Weinhold 
2132d690920SAxel Dörfler partition_id
_user_find_disk_device(const char * _filename,size_t * neededSize)2142d690920SAxel Dörfler _user_find_disk_device(const char *_filename, size_t *neededSize)
2152d690920SAxel Dörfler {
2166cc43bfbSAxel Dörfler 	UserStringParameter<false> filename;
2176cc43bfbSAxel Dörfler 	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
2186cc43bfbSAxel Dörfler 	if (error != B_OK)
2192d690920SAxel Dörfler 		return error;
2202d690920SAxel Dörfler 
2212d690920SAxel Dörfler 	partition_id id = B_ENTRY_NOT_FOUND;
2222d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
2232d690920SAxel Dörfler 	// find the device
2242d690920SAxel Dörfler 	if (KDiskDevice *device = manager->RegisterDevice(filename)) {
2252d690920SAxel Dörfler 		PartitionRegistrar _(device, true);
2262d690920SAxel Dörfler 		id = device->ID();
227*4644c7ccSJérôme Duval 		if (neededSize != NULL) {
2282d690920SAxel Dörfler 			if (DeviceReadLocker locker = device) {
2292d690920SAxel Dörfler 				// get the needed size
2302d690920SAxel Dörfler 				UserDataWriter writer;
2318354dac7SIngo Weinhold 				device->WriteUserData(writer);
2326cc43bfbSAxel Dörfler 				error = copy_to_user_value(neededSize, writer.AllocatedSize());
2336cc43bfbSAxel Dörfler 				if (error != B_OK)
2346cc43bfbSAxel Dörfler 					return error;
2352d690920SAxel Dörfler 			} else
2362d690920SAxel Dörfler 				return B_ERROR;
2372d690920SAxel Dörfler 		}
2382d690920SAxel Dörfler 	}
2392d690920SAxel Dörfler 	return id;
2402d690920SAxel Dörfler }
2412d690920SAxel Dörfler 
242d6e565c7SIngo Weinhold 
2432d690920SAxel Dörfler partition_id
_user_find_partition(const char * _filename,size_t * neededSize)2442d690920SAxel Dörfler _user_find_partition(const char *_filename, size_t *neededSize)
2452d690920SAxel Dörfler {
2466cc43bfbSAxel Dörfler 	UserStringParameter<false> filename;
2476cc43bfbSAxel Dörfler 	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
2486cc43bfbSAxel Dörfler 	if (error != B_OK)
2492d690920SAxel Dörfler 		return error;
2502d690920SAxel Dörfler 
2512d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
2522d690920SAxel Dörfler 	// find the partition
253*4644c7ccSJérôme Duval 	KPartition *partition = manager->RegisterPartition(filename);
254*4644c7ccSJérôme Duval 	if (partition == NULL)
255*4644c7ccSJérôme Duval 		return B_ENTRY_NOT_FOUND;
2562d690920SAxel Dörfler 	PartitionRegistrar _(partition, true);
257*4644c7ccSJérôme Duval 	partition_id id = partition->ID();
258*4644c7ccSJérôme Duval 	if (neededSize != NULL) {
2592d690920SAxel Dörfler 		// get and lock the partition's device
260*4644c7ccSJérôme Duval 		KDiskDevice *device = manager->RegisterDevice(partition->ID(), false);
261*4644c7ccSJérôme Duval 		if (device == NULL)
2622d690920SAxel Dörfler 			return B_ENTRY_NOT_FOUND;
2632d690920SAxel Dörfler 		PartitionRegistrar _2(device, true);
2642d690920SAxel Dörfler 		if (DeviceReadLocker locker = device) {
2652d690920SAxel Dörfler 			// get the needed size
2662d690920SAxel Dörfler 			UserDataWriter writer;
2678354dac7SIngo Weinhold 			device->WriteUserData(writer);
2686cc43bfbSAxel Dörfler 			error = copy_to_user_value(neededSize, writer.AllocatedSize());
2696cc43bfbSAxel Dörfler 			if (error != B_OK)
2706cc43bfbSAxel Dörfler 				return error;
2712d690920SAxel Dörfler 		} else
2722d690920SAxel Dörfler 			return B_ERROR;
2732d690920SAxel Dörfler 	}
2742d690920SAxel Dörfler 	return id;
2752d690920SAxel Dörfler }
2762d690920SAxel Dörfler 
277d6e565c7SIngo Weinhold 
27838bbc957SAxel Dörfler partition_id
_user_find_file_disk_device(const char * _filename,size_t * neededSize)27938bbc957SAxel Dörfler _user_find_file_disk_device(const char *_filename, size_t *neededSize)
28038bbc957SAxel Dörfler {
28138bbc957SAxel Dörfler 	UserStringParameter<false> filename;
28238bbc957SAxel Dörfler 	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
28338bbc957SAxel Dörfler 	if (error != B_OK)
28438bbc957SAxel Dörfler 		return error;
28538bbc957SAxel Dörfler 
286eac83fb3SAxel Dörfler 	KPath path(filename, KPath::NORMALIZE);
28738bbc957SAxel Dörfler 
28838bbc957SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
28938bbc957SAxel Dörfler 	// find the device
290*4644c7ccSJérôme Duval 	KFileDiskDevice* device = manager->RegisterFileDevice(path.Path());
291*4644c7ccSJérôme Duval 	if (device == NULL)
292*4644c7ccSJérôme Duval 		return B_ENTRY_NOT_FOUND;
29338bbc957SAxel Dörfler 	PartitionRegistrar _(device, true);
294*4644c7ccSJérôme Duval 	partition_id id = device->ID();
295*4644c7ccSJérôme Duval 	if (neededSize != NULL) {
29638bbc957SAxel Dörfler 		if (DeviceReadLocker locker = device) {
29738bbc957SAxel Dörfler 			// get the needed size
29838bbc957SAxel Dörfler 			UserDataWriter writer;
29938bbc957SAxel Dörfler 			device->WriteUserData(writer);
30038bbc957SAxel Dörfler 			error = copy_to_user_value(neededSize, writer.AllocatedSize());
30138bbc957SAxel Dörfler 			if (error != B_OK)
30238bbc957SAxel Dörfler 				return error;
30338bbc957SAxel Dörfler 		} else
30438bbc957SAxel Dörfler 			return B_ERROR;
30538bbc957SAxel Dörfler 	}
30638bbc957SAxel Dörfler 	return id;
30738bbc957SAxel Dörfler }
30838bbc957SAxel Dörfler 
30938bbc957SAxel Dörfler 
3102d690920SAxel Dörfler /*!	\brief Writes data describing the disk device identified by ID and all
3112d690920SAxel Dörfler 		   its partitions into the supplied buffer.
3122d690920SAxel Dörfler 
3132d690920SAxel Dörfler 	The function passes the buffer size required to hold the data back
3142d690920SAxel Dörfler 	through the \a _neededSize parameter, if the device could be found at
3152d690920SAxel Dörfler 	least and no serious error occured. If fails with \c B_BUFFER_OVERFLOW,
3162d690920SAxel Dörfler 	if the supplied buffer is too small or a \c NULL buffer is supplied
3172d690920SAxel Dörfler 	(and \c bufferSize is 0).
3182d690920SAxel Dörfler 
3192d690920SAxel Dörfler 	The device is identified by \a id. If \a deviceOnly is \c true, then
3202d690920SAxel Dörfler 	it must be the ID of a disk device, otherwise the disk device is
3212d690920SAxel Dörfler 	chosen, on which the partition \a id refers to resides.
3222d690920SAxel Dörfler 
3232d690920SAxel Dörfler 	\param id The ID of an arbitrary partition on the disk device (including
3242d690920SAxel Dörfler 		   the disk device itself), whose data shall be returned
3252d690920SAxel Dörfler 		   (if \a deviceOnly is \c false), or the ID of the disk device
3262d690920SAxel Dörfler 		   itself (if \a deviceOnly is true).
3272d690920SAxel Dörfler 	\param deviceOnly Specifies whether only IDs of disk devices (\c true),
3282d690920SAxel Dörfler 		   or also IDs of partitions (\c false) are accepted for \a id.
3292d690920SAxel Dörfler 	\param buffer The buffer into which the disk device data shall be written.
3302d690920SAxel Dörfler 		   May be \c NULL.
3312d690920SAxel Dörfler 	\param bufferSize The size of \a buffer.
3322d690920SAxel Dörfler 	\param _neededSize Pointer to a variable into which the actually needed
3332d690920SAxel Dörfler 		   buffer size is written. May be \c NULL.
3342d690920SAxel Dörfler 	\return
3352d690920SAxel Dörfler 	- \c B_OK: Everything went fine. The device was found and, if not \c NULL,
3362d690920SAxel Dörfler 	  in \a _neededSize the actually needed buffer size is returned. And
3372d690920SAxel Dörfler 	  \a buffer will contain the disk device data.
3382d690920SAxel Dörfler 	- \c B_BAD_VALUE: \c NULL \a buffer, but not 0 \a bufferSize.
3392d690920SAxel Dörfler 	- \c B_BUFFER_OVERFLOW: The supplied buffer was too small. \a _neededSize,
3402d690920SAxel Dörfler 	  if not \c NULL, will contain the required buffer size.
3412d690920SAxel Dörfler 	- \c B_NO_MEMORY: Insufficient memory to complete the operation.
3422d690920SAxel Dörfler 	- \c B_ENTRY_NOT_FOUND: \a id is no valid disk device ID (if \a deviceOnly
3432d690920SAxel Dörfler 	  is \c true) or not even a valid partition ID (if \a deviceOnly is
3442d690920SAxel Dörfler 	  \c false).
3452d690920SAxel Dörfler 	- \c B_ERROR: An unexpected error occured.
3462d690920SAxel Dörfler 	- another error code...
3472d690920SAxel Dörfler */
3482d690920SAxel Dörfler status_t
_user_get_disk_device_data(partition_id id,bool deviceOnly,user_disk_device_data * buffer,size_t bufferSize,size_t * _neededSize)3498354dac7SIngo Weinhold _user_get_disk_device_data(partition_id id, bool deviceOnly,
350d6e565c7SIngo Weinhold 	user_disk_device_data *buffer, size_t bufferSize, size_t *_neededSize)
3512d690920SAxel Dörfler {
352*4644c7ccSJérôme Duval 	if (buffer == NULL && bufferSize > 0)
3532d690920SAxel Dörfler 		return B_BAD_VALUE;
3542d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
3552d690920SAxel Dörfler 	// get the device
356*4644c7ccSJérôme Duval 	KDiskDevice *device = manager->RegisterDevice(id, deviceOnly);
357*4644c7ccSJérôme Duval 	if (device == NULL)
358*4644c7ccSJérôme Duval 		return B_ENTRY_NOT_FOUND;
359*4644c7ccSJérôme Duval 
3602d690920SAxel Dörfler 	PartitionRegistrar _(device, true);
3612d690920SAxel Dörfler 	if (DeviceReadLocker locker = device) {
3622d690920SAxel Dörfler 		// do a dry run first to get the needed size
3632d690920SAxel Dörfler 		UserDataWriter writer;
3648354dac7SIngo Weinhold 		device->WriteUserData(writer);
3652d690920SAxel Dörfler 		size_t neededSize = writer.AllocatedSize();
366*4644c7ccSJérôme Duval 		if (_neededSize != NULL) {
3672d690920SAxel Dörfler 			status_t error = copy_ref_var_to_user(neededSize, _neededSize);
3682d690920SAxel Dörfler 			if (error != B_OK)
3692d690920SAxel Dörfler 				return error;
3702d690920SAxel Dörfler 		}
3712d690920SAxel Dörfler 		// if no buffer has been supplied or the buffer is too small,
3722d690920SAxel Dörfler 		// then we're done
373*4644c7ccSJérôme Duval 		if (buffer == NULL || bufferSize < neededSize)
3742d690920SAxel Dörfler 			return B_BUFFER_OVERFLOW;
375*4644c7ccSJérôme Duval 		if (!IS_USER_ADDRESS(buffer))
376*4644c7ccSJérôme Duval 			return B_BAD_ADDRESS;
3772d690920SAxel Dörfler 		// otherwise allocate a kernel buffer
3782d690920SAxel Dörfler 		user_disk_device_data *kernelBuffer
3792d690920SAxel Dörfler 			= static_cast<user_disk_device_data*>(malloc(neededSize));
380*4644c7ccSJérôme Duval 		if (kernelBuffer == NULL)
3812d690920SAxel Dörfler 			return B_NO_MEMORY;
3822d690920SAxel Dörfler 		MemoryDeleter deleter(kernelBuffer);
3832d690920SAxel Dörfler 		// write the device data into the buffer
3842d690920SAxel Dörfler 		writer.SetTo(kernelBuffer, bufferSize);
3858354dac7SIngo Weinhold 		device->WriteUserData(writer);
3862d690920SAxel Dörfler 		// sanity check
3872d690920SAxel Dörfler 		if (writer.AllocatedSize() != neededSize) {
3882d690920SAxel Dörfler 			ERROR(("Size of written disk device user data changed from "
3892d690920SAxel Dörfler 				   "%lu to %lu while device was locked!\n"));
3902d690920SAxel Dörfler 			return B_ERROR;
3912d690920SAxel Dörfler 		}
3922d690920SAxel Dörfler 		// relocate
3932d690920SAxel Dörfler 		status_t error = writer.Relocate(buffer);
3942d690920SAxel Dörfler 		if (error != B_OK)
3952d690920SAxel Dörfler 			return error;
3962d690920SAxel Dörfler 		// copy out
3972d690920SAxel Dörfler 		return user_memcpy(buffer, kernelBuffer, neededSize);
3982d690920SAxel Dörfler 	} else
3992d690920SAxel Dörfler 		return B_ERROR;
4002d690920SAxel Dörfler }
4012d690920SAxel Dörfler 
402d6e565c7SIngo Weinhold 
4032d690920SAxel Dörfler partition_id
_user_register_file_device(const char * _filename)4042d690920SAxel Dörfler _user_register_file_device(const char *_filename)
4052d690920SAxel Dörfler {
4066cc43bfbSAxel Dörfler 	UserStringParameter<false> filename;
4076cc43bfbSAxel Dörfler 	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
4086cc43bfbSAxel Dörfler 	if (error != B_OK)
4092d690920SAxel Dörfler 		return error;
4106cc43bfbSAxel Dörfler 
411eac83fb3SAxel Dörfler 	KPath path(filename, KPath::NORMALIZE);
412260e077fSAxel Dörfler 
4132d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
4142d690920SAxel Dörfler 	if (ManagerLocker locker = manager) {
415*4644c7ccSJérôme Duval 		KFileDiskDevice *device = manager->FindFileDevice(path.Path());
416*4644c7ccSJérôme Duval 		if (device != NULL)
4172d690920SAxel Dörfler 			return device->ID();
418260e077fSAxel Dörfler 		return manager->CreateFileDevice(path.Path());
4192d690920SAxel Dörfler 	}
4202d690920SAxel Dörfler 	return B_ERROR;
4212d690920SAxel Dörfler }
4222d690920SAxel Dörfler 
423d6e565c7SIngo Weinhold 
4242d690920SAxel Dörfler status_t
_user_unregister_file_device(partition_id deviceID,const char * _filename)4252d690920SAxel Dörfler _user_unregister_file_device(partition_id deviceID, const char *_filename)
4262d690920SAxel Dörfler {
427*4644c7ccSJérôme Duval 	if (deviceID < 0 && _filename == NULL)
4282d690920SAxel Dörfler 		return B_BAD_VALUE;
4292d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
430*4644c7ccSJérôme Duval 	if (deviceID >= 0)
4312d690920SAxel Dörfler 		return manager->DeleteFileDevice(deviceID);
432*4644c7ccSJérôme Duval 
4336cc43bfbSAxel Dörfler 	UserStringParameter<false> filename;
4346cc43bfbSAxel Dörfler 	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
4356cc43bfbSAxel Dörfler 	if (error != B_OK)
4362d690920SAxel Dörfler 		return error;
4376cc43bfbSAxel Dörfler 
4382d690920SAxel Dörfler 	return manager->DeleteFileDevice(filename);
4392d690920SAxel Dörfler }
4402d690920SAxel Dörfler 
441d6e565c7SIngo Weinhold 
44238bbc957SAxel Dörfler status_t
_user_get_file_disk_device_path(partition_id id,char * buffer,size_t bufferSize)44338bbc957SAxel Dörfler _user_get_file_disk_device_path(partition_id id, char* buffer,
44438bbc957SAxel Dörfler 	size_t bufferSize)
44538bbc957SAxel Dörfler {
44638bbc957SAxel Dörfler 	if (id < 0 || buffer == NULL || bufferSize == 0)
44738bbc957SAxel Dörfler 		return B_BAD_VALUE;
448*4644c7ccSJérôme Duval 	if (!IS_USER_ADDRESS(buffer))
449*4644c7ccSJérôme Duval 		return B_BAD_ADDRESS;
45038bbc957SAxel Dörfler 
45138bbc957SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
452*4644c7ccSJérôme Duval 	KDiskDevice *device = manager->RegisterDevice(id, true);
453*4644c7ccSJérôme Duval 	if (device != NULL) {
45438bbc957SAxel Dörfler 		PartitionRegistrar _(device, true);
45538bbc957SAxel Dörfler 		if (DeviceReadLocker locker = device) {
45638bbc957SAxel Dörfler 			KFileDiskDevice* fileDevice
45738bbc957SAxel Dörfler 				= dynamic_cast<KFileDiskDevice*>(device);
45838bbc957SAxel Dörfler 			if (fileDevice == NULL)
45938bbc957SAxel Dörfler 				return B_BAD_VALUE;
46038bbc957SAxel Dörfler 
46180ea5e35SIngo Weinhold 			ssize_t copied = user_strlcpy(buffer, fileDevice->FilePath(),
46280ea5e35SIngo Weinhold 				bufferSize);
46380ea5e35SIngo Weinhold 			if (copied < 0)
46480ea5e35SIngo Weinhold 				return copied;
46580ea5e35SIngo Weinhold 			return (size_t)copied < bufferSize ? B_OK : B_BUFFER_OVERFLOW;
46638bbc957SAxel Dörfler 		}
46738bbc957SAxel Dörfler 	}
46838bbc957SAxel Dörfler 
46938bbc957SAxel Dörfler 	return B_ERROR;
47038bbc957SAxel Dörfler }
47138bbc957SAxel Dörfler 
47238bbc957SAxel Dörfler 
4732d690920SAxel Dörfler status_t
_user_get_disk_system_info(disk_system_id id,user_disk_system_info * _info)4742d690920SAxel Dörfler _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)
4752d690920SAxel Dörfler {
476*4644c7ccSJérôme Duval 	if (_info == NULL)
4772d690920SAxel Dörfler 		return B_BAD_VALUE;
4782d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
4792d690920SAxel Dörfler 	if (ManagerLocker locker = manager) {
480*4644c7ccSJérôme Duval 		KDiskSystem *diskSystem = manager->FindDiskSystem(id);
481*4644c7ccSJérôme Duval 		if (diskSystem != NULL) {
4822d690920SAxel Dörfler 			user_disk_system_info info;
4832d690920SAxel Dörfler 			diskSystem->GetInfo(&info);
484*4644c7ccSJérôme Duval 			return copy_to_user_value(_info, info);
4852d690920SAxel Dörfler 		}
4862d690920SAxel Dörfler 	}
4872d690920SAxel Dörfler 	return B_ENTRY_NOT_FOUND;
4882d690920SAxel Dörfler }
4892d690920SAxel Dörfler 
490d6e565c7SIngo Weinhold 
4912d690920SAxel Dörfler status_t
_user_get_next_disk_system_info(int32 * _cookie,user_disk_system_info * _info)4922d690920SAxel Dörfler _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info)
4932d690920SAxel Dörfler {
494*4644c7ccSJérôme Duval 	if (_info == NULL)
4952d690920SAxel Dörfler 		return B_BAD_VALUE;
496*4644c7ccSJérôme Duval 	if (!IS_USER_ADDRESS(_info))
497*4644c7ccSJérôme Duval 		return B_BAD_ADDRESS;
4982d690920SAxel Dörfler 	int32 cookie;
499*4644c7ccSJérôme Duval 	status_t result = copy_from_user_value(cookie, _cookie);
500*4644c7ccSJérôme Duval 	if (result != B_OK)
501*4644c7ccSJérôme Duval 		return result;
502*4644c7ccSJérôme Duval 	result = B_ENTRY_NOT_FOUND;
5032d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
5042d690920SAxel Dörfler 	if (ManagerLocker locker = manager) {
505*4644c7ccSJérôme Duval 		KDiskSystem *diskSystem = manager->NextDiskSystem(&cookie);
506*4644c7ccSJérôme Duval 		if (diskSystem != NULL) {
5072d690920SAxel Dörfler 			user_disk_system_info info;
5082d690920SAxel Dörfler 			diskSystem->GetInfo(&info);
509*4644c7ccSJérôme Duval 			result = copy_to_user_value(_info, info);
5102d690920SAxel Dörfler 		}
5112d690920SAxel Dörfler 	}
512*4644c7ccSJérôme Duval 	status_t error = copy_to_user_value(_cookie, cookie);
513*4644c7ccSJérôme Duval 	if (error != B_OK)
514*4644c7ccSJérôme Duval 		result = error;
5152d690920SAxel Dörfler 	return result;
5162d690920SAxel Dörfler }
5172d690920SAxel Dörfler 
518d6e565c7SIngo Weinhold 
5192d690920SAxel Dörfler status_t
_user_find_disk_system(const char * _name,user_disk_system_info * _info)5202d690920SAxel Dörfler _user_find_disk_system(const char *_name, user_disk_system_info *_info)
5212d690920SAxel Dörfler {
522*4644c7ccSJérôme Duval 	if (_name == NULL || _info == NULL)
5232d690920SAxel Dörfler 		return B_BAD_VALUE;
524*4644c7ccSJérôme Duval 	if (!IS_USER_ADDRESS(_name) || !IS_USER_ADDRESS(_info))
525*4644c7ccSJérôme Duval 		return B_BAD_ADDRESS;
5262d690920SAxel Dörfler 	char name[B_DISK_SYSTEM_NAME_LENGTH];
5272d690920SAxel Dörfler 	status_t error = ddm_strlcpy(name, _name, B_DISK_SYSTEM_NAME_LENGTH);
528*4644c7ccSJérôme Duval 	if (error != B_OK)
5292d690920SAxel Dörfler 		return error;
5302d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
5312d690920SAxel Dörfler 	if (ManagerLocker locker = manager) {
532*4644c7ccSJérôme Duval 		KDiskSystem *diskSystem = manager->FindDiskSystem(name);
533*4644c7ccSJérôme Duval 		if (diskSystem != NULL) {
5342d690920SAxel Dörfler 			user_disk_system_info info;
5352d690920SAxel Dörfler 			diskSystem->GetInfo(&info);
536*4644c7ccSJérôme Duval 			return copy_to_user_value(_info, info);
5372d690920SAxel Dörfler 		}
5382d690920SAxel Dörfler 	}
5392d690920SAxel Dörfler 	return B_ENTRY_NOT_FOUND;
5402d690920SAxel Dörfler }
5412d690920SAxel Dörfler 
542d6e565c7SIngo Weinhold 
5432d690920SAxel Dörfler status_t
_user_defragment_partition(partition_id partitionID,int32 * _changeCounter)5447b45b55bSIngo Weinhold _user_defragment_partition(partition_id partitionID, int32* _changeCounter)
5452d690920SAxel Dörfler {
5467b45b55bSIngo Weinhold 	// copy parameters in
5477b45b55bSIngo Weinhold 	int32 changeCounter;
5487b45b55bSIngo Weinhold 
549*4644c7ccSJérôme Duval 	status_t error = copy_from_user_value(changeCounter, _changeCounter);
550*4644c7ccSJérôme Duval 	if (error != B_OK)
5517b45b55bSIngo Weinhold 		return error;
5527b45b55bSIngo Weinhold 
5532d690920SAxel Dörfler 	// get the partition
5547b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
5552d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
556*4644c7ccSJérôme Duval 	if (partition == NULL)
5572d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
5587b45b55bSIngo Weinhold 
5592d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
5602d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
5612d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
5627b45b55bSIngo Weinhold 
5637b45b55bSIngo Weinhold 	// check change counter
5647b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter())
5657b45b55bSIngo Weinhold 		return B_BAD_VALUE;
5667b45b55bSIngo Weinhold 
5677b45b55bSIngo Weinhold 	// the partition must be initialized
5687b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
569*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
5707b45b55bSIngo Weinhold 		return B_BAD_VALUE;
5717b45b55bSIngo Weinhold 
5727b45b55bSIngo Weinhold 	// mark the partition busy and unlock
5737b45b55bSIngo Weinhold 	if (!partition->CheckAndMarkBusy(false))
5747b45b55bSIngo Weinhold 		return B_BUSY;
5757b45b55bSIngo Weinhold 	locker.Unlock();
5767b45b55bSIngo Weinhold 
5777b45b55bSIngo Weinhold 	// defragment
5787b45b55bSIngo Weinhold 	error = diskSystem->Defragment(partition, DUMMY_JOB_ID);
5797b45b55bSIngo Weinhold 
5807b45b55bSIngo Weinhold 	// re-lock and unmark busy
5817b45b55bSIngo Weinhold 	locker.Lock();
5827b45b55bSIngo Weinhold 	partition->UnmarkBusy(false);
5837b45b55bSIngo Weinhold 
5842d690920SAxel Dörfler 	if (error != B_OK)
5852d690920SAxel Dörfler 		return error;
5867b45b55bSIngo Weinhold 
5877b45b55bSIngo Weinhold 	// return change counter
588*4644c7ccSJérôme Duval 	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
5892d690920SAxel Dörfler }
5902d690920SAxel Dörfler 
591d6e565c7SIngo Weinhold 
5922d690920SAxel Dörfler status_t
_user_repair_partition(partition_id partitionID,int32 * _changeCounter,bool checkOnly)5937b45b55bSIngo Weinhold _user_repair_partition(partition_id partitionID, int32* _changeCounter,
5942d690920SAxel Dörfler 	bool checkOnly)
5952d690920SAxel Dörfler {
5967b45b55bSIngo Weinhold 	// copy parameters in
5977b45b55bSIngo Weinhold 	int32 changeCounter;
5987b45b55bSIngo Weinhold 
599*4644c7ccSJérôme Duval 	status_t error = copy_from_user_value(changeCounter, _changeCounter);
600*4644c7ccSJérôme Duval 	if (error != B_OK)
6017b45b55bSIngo Weinhold 		return error;
6027b45b55bSIngo Weinhold 
6032d690920SAxel Dörfler 	// get the partition
6047b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
6052d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
606*4644c7ccSJérôme Duval 	if (partition == NULL)
6072d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
6087b45b55bSIngo Weinhold 
6092d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
6102d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
6112d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
6127b45b55bSIngo Weinhold 
6137b45b55bSIngo Weinhold 	// check change counter
6147b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter())
6157b45b55bSIngo Weinhold 		return B_BAD_VALUE;
6167b45b55bSIngo Weinhold 
6177b45b55bSIngo Weinhold 	// the partition must be initialized
6187b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
619*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
6207b45b55bSIngo Weinhold 		return B_BAD_VALUE;
6217b45b55bSIngo Weinhold 
6227b45b55bSIngo Weinhold 	// mark the partition busy and unlock
6237b45b55bSIngo Weinhold 	if (!partition->CheckAndMarkBusy(false))
6247b45b55bSIngo Weinhold 		return B_BUSY;
6257b45b55bSIngo Weinhold 	locker.Unlock();
6267b45b55bSIngo Weinhold 
6277b45b55bSIngo Weinhold 	// repair/check
6287b45b55bSIngo Weinhold 	error = diskSystem->Repair(partition, checkOnly, DUMMY_JOB_ID);
6297b45b55bSIngo Weinhold 
6307b45b55bSIngo Weinhold 	// re-lock and unmark busy
6317b45b55bSIngo Weinhold 	locker.Lock();
6327b45b55bSIngo Weinhold 	partition->UnmarkBusy(false);
6337b45b55bSIngo Weinhold 
6342d690920SAxel Dörfler 	if (error != B_OK)
6352d690920SAxel Dörfler 		return error;
6367b45b55bSIngo Weinhold 
6377b45b55bSIngo Weinhold 	// return change counter
638*4644c7ccSJérôme Duval 	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
6392d690920SAxel Dörfler }
6402d690920SAxel Dörfler 
641d6e565c7SIngo Weinhold 
6422d690920SAxel Dörfler status_t
_user_resize_partition(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,off_t size,off_t contentSize)6437b45b55bSIngo Weinhold _user_resize_partition(partition_id partitionID, int32* _changeCounter,
6447b45b55bSIngo Weinhold 	partition_id childID, int32* _childChangeCounter, off_t size,
645300868ceSIngo Weinhold 	off_t contentSize)
6462d690920SAxel Dörfler {
6477b45b55bSIngo Weinhold 	// copy parameters in
6487b45b55bSIngo Weinhold 	int32 changeCounter;
6497b45b55bSIngo Weinhold 	int32 childChangeCounter;
6507b45b55bSIngo Weinhold 
651*4644c7ccSJérôme Duval 	status_t error = copy_from_user_value(changeCounter, _changeCounter);
652*4644c7ccSJérôme Duval 	if (error == B_OK)
653*4644c7ccSJérôme Duval 		error = copy_from_user_value(childChangeCounter, _childChangeCounter);
654*4644c7ccSJérôme Duval 	if (error != B_OK)
6557b45b55bSIngo Weinhold 		return error;
6567b45b55bSIngo Weinhold 
6572d690920SAxel Dörfler 	// get the partition
6587b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
6592d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
660*4644c7ccSJérôme Duval 	if (partition == NULL)
6612d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
6627b45b55bSIngo Weinhold 
6632d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
6642d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
6652d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
6667b45b55bSIngo Weinhold 
6677b45b55bSIngo Weinhold 	// register child
6687b45b55bSIngo Weinhold 	KPartition* child = manager->RegisterPartition(childID);
669*4644c7ccSJérôme Duval 	if (child == NULL)
6707b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
6717b45b55bSIngo Weinhold 
6727b45b55bSIngo Weinhold 	PartitionRegistrar registrar3(child, true);
6737b45b55bSIngo Weinhold 
6747b45b55bSIngo Weinhold 	// check change counters
6757b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter()
6767b45b55bSIngo Weinhold 		|| childChangeCounter != child->ChangeCounter()) {
6772d690920SAxel Dörfler 		return B_BAD_VALUE;
6782d690920SAxel Dörfler 	}
6797b45b55bSIngo Weinhold 
6807b45b55bSIngo Weinhold 	// the partition must be initialized
6817b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
682*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
683300868ceSIngo Weinhold 		return B_BAD_VALUE;
6847b45b55bSIngo Weinhold 
6857b45b55bSIngo Weinhold 	// child must indeed be a child of partition
6867b45b55bSIngo Weinhold 	if (child->Parent() != partition)
6877b45b55bSIngo Weinhold 		return B_BAD_VALUE;
6887b45b55bSIngo Weinhold 
6897b45b55bSIngo Weinhold 	// check sizes
6907b45b55bSIngo Weinhold 	if (size < 0 || contentSize < 0 || size < contentSize
6917b45b55bSIngo Weinhold 		|| size > partition->ContentSize()) {
6927b45b55bSIngo Weinhold 		return B_BAD_VALUE;
6937b45b55bSIngo Weinhold 	}
6947b45b55bSIngo Weinhold 
6957b45b55bSIngo Weinhold 	// mark the partitions busy and unlock
6967b45b55bSIngo Weinhold 	if (partition->IsBusy() || child->IsBusy())
6977b45b55bSIngo Weinhold 		return B_BUSY;
6987b45b55bSIngo Weinhold 	partition->SetBusy(true);
6997b45b55bSIngo Weinhold 	child->SetBusy(true);
7007b45b55bSIngo Weinhold 	locker.Unlock();
7017b45b55bSIngo Weinhold 
7027b45b55bSIngo Weinhold 	// resize contents first, if shrinking
7037b45b55bSIngo Weinhold 	if (child->DiskSystem() && contentSize < child->ContentSize())
7047b45b55bSIngo Weinhold 		error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID);
7057b45b55bSIngo Weinhold 
7067b45b55bSIngo Weinhold 	// resize the partition
7077b45b55bSIngo Weinhold 	if (error == B_OK && size != child->Size())
7087b45b55bSIngo Weinhold 		error = diskSystem->ResizeChild(child, size, DUMMY_JOB_ID);
7097b45b55bSIngo Weinhold 
7107b45b55bSIngo Weinhold 	// resize contents last, if growing
7117b45b55bSIngo Weinhold 	if (error == B_OK && child->DiskSystem()
7127b45b55bSIngo Weinhold 		&& contentSize > child->ContentSize()) {
7137b45b55bSIngo Weinhold 		error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID);
7147b45b55bSIngo Weinhold 	}
7157b45b55bSIngo Weinhold 
7167b45b55bSIngo Weinhold 	// re-lock and unmark busy
7177b45b55bSIngo Weinhold 	locker.Lock();
7187b45b55bSIngo Weinhold 	partition->SetBusy(false);
7197b45b55bSIngo Weinhold 	child->SetBusy(false);
7207b45b55bSIngo Weinhold 
7217b45b55bSIngo Weinhold 	if (error != B_OK)
7227b45b55bSIngo Weinhold 		return error;
7237b45b55bSIngo Weinhold 
7247b45b55bSIngo Weinhold 	// return change counters
725*4644c7ccSJérôme Duval 	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
726*4644c7ccSJérôme Duval 	if (error == B_OK)
727*4644c7ccSJérôme Duval 		error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
7287b45b55bSIngo Weinhold 	return error;
7297b45b55bSIngo Weinhold }
7307b45b55bSIngo Weinhold 
731d6e565c7SIngo Weinhold 
7322d690920SAxel Dörfler status_t
_user_move_partition(partition_id partitionID,int32 * changeCounter,partition_id childID,int32 * childChangeCounter,off_t newOffset,partition_id * descendantIDs,int32 * descendantChangeCounters,int32 descendantCount)733300868ceSIngo Weinhold _user_move_partition(partition_id partitionID, int32* changeCounter,
734300868ceSIngo Weinhold 	partition_id childID, int32* childChangeCounter, off_t newOffset,
735300868ceSIngo Weinhold 	partition_id* descendantIDs, int32* descendantChangeCounters,
736300868ceSIngo Weinhold 	int32 descendantCount)
7372d690920SAxel Dörfler {
738300868ceSIngo Weinhold #if 0
7392d690920SAxel Dörfler 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
7402d690920SAxel Dörfler 	// get the partition
7412d690920SAxel Dörfler 	KPartition *partition = manager->WriteLockPartition(partitionID);
7422d690920SAxel Dörfler 	if (!partition)
7432d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
7442d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
7452d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
7462d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
7472d690920SAxel Dörfler 	// check the new offset
7482d690920SAxel Dörfler 	if (newOffset == partition->Offset())
7492d690920SAxel Dörfler 		return B_OK;
7502d690920SAxel Dörfler 	off_t proposedOffset = newOffset;
7512d690920SAxel Dörfler 	status_t error = validate_move_partition(partition, changeCounter,
7522d690920SAxel Dörfler 		&proposedOffset, true);
7532d690920SAxel Dörfler 	if (error != B_OK)
7542d690920SAxel Dörfler 		return error;
7552d690920SAxel Dörfler 	if (proposedOffset != newOffset)
7562d690920SAxel Dörfler 		return B_BAD_VALUE;
7572d690920SAxel Dörfler 	// new offset is fine -- move the thing
7582d690920SAxel Dörfler 	off_t moveBy = newOffset - partition->Offset();
7592d690920SAxel Dörfler 	move_descendants(partition, moveBy);
7602d690920SAxel Dörfler 	partition->Changed(B_PARTITION_CHANGED_OFFSET);
7612d690920SAxel Dörfler 	// implicit partitioning system changes
7622d690920SAxel Dörfler 	error = partition->Parent()->DiskSystem()->ShadowPartitionChanged(
763bf95c9aeSIngo Weinhold 		partition->Parent(), partition, B_PARTITION_MOVE_CHILD);
7642d690920SAxel Dörfler 	if (error != B_OK)
7652d690920SAxel Dörfler 		return error;
7662d690920SAxel Dörfler 	// implicit descendants' content disk system changes
7672d690920SAxel Dörfler 	return move_descendants_contents(partition);
768300868ceSIngo Weinhold #endif
769300868ceSIngo Weinhold return B_BAD_VALUE;
7702d690920SAxel Dörfler }
7712d690920SAxel Dörfler 
772d6e565c7SIngo Weinhold 
7732d690920SAxel Dörfler status_t
_user_set_partition_name(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,const char * _name)7747b45b55bSIngo Weinhold _user_set_partition_name(partition_id partitionID, int32* _changeCounter,
7757b45b55bSIngo Weinhold 	partition_id childID, int32* _childChangeCounter, const char* _name)
7762d690920SAxel Dörfler {
7777b45b55bSIngo Weinhold 	// copy parameters in
7787b45b55bSIngo Weinhold 	UserStringParameter<false> name;
7797b45b55bSIngo Weinhold 	int32 changeCounter;
7807b45b55bSIngo Weinhold 	int32 childChangeCounter;
7817b45b55bSIngo Weinhold 
782*4644c7ccSJérôme Duval 	status_t error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
783*4644c7ccSJérôme Duval 	if (error == B_OK)
784*4644c7ccSJérôme Duval 		error = copy_from_user_value(changeCounter, _changeCounter);
785*4644c7ccSJérôme Duval 	if (error == B_OK)
786*4644c7ccSJérôme Duval 		error = copy_from_user_value(childChangeCounter, _childChangeCounter);
787*4644c7ccSJérôme Duval 	if (error != B_OK)
7882d690920SAxel Dörfler 		return error;
7897b45b55bSIngo Weinhold 
7902d690920SAxel Dörfler 	// get the partition
7917b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
7922d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
793*4644c7ccSJérôme Duval 	if (partition == NULL)
7942d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
7957b45b55bSIngo Weinhold 
7962d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
7972d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
7982d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
7997b45b55bSIngo Weinhold 
8007b45b55bSIngo Weinhold 	// register child
8017b45b55bSIngo Weinhold 	KPartition* child = manager->RegisterPartition(childID);
802*4644c7ccSJérôme Duval 	if (child == NULL)
8037b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
8047b45b55bSIngo Weinhold 
8057b45b55bSIngo Weinhold 	PartitionRegistrar registrar3(child, true);
8067b45b55bSIngo Weinhold 
8077b45b55bSIngo Weinhold 	// check change counters
8087b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter()
8097b45b55bSIngo Weinhold 		|| childChangeCounter != child->ChangeCounter()) {
8107b45b55bSIngo Weinhold 		return B_BAD_VALUE;
8117b45b55bSIngo Weinhold 	}
8127b45b55bSIngo Weinhold 
8137b45b55bSIngo Weinhold 	// the partition must be initialized
8147b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
815*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
8167b45b55bSIngo Weinhold 		return B_BAD_VALUE;
8177b45b55bSIngo Weinhold 
8187b45b55bSIngo Weinhold 	// child must indeed be a child of partition
8197b45b55bSIngo Weinhold 	if (child->Parent() != partition)
8207b45b55bSIngo Weinhold 		return B_BAD_VALUE;
8217b45b55bSIngo Weinhold 
8227b45b55bSIngo Weinhold 	// mark the partitions busy and unlock
8237b45b55bSIngo Weinhold 	if (partition->IsBusy() || child->IsBusy())
8247b45b55bSIngo Weinhold 		return B_BUSY;
8257b45b55bSIngo Weinhold 	partition->SetBusy(true);
8267b45b55bSIngo Weinhold 	child->SetBusy(true);
8277b45b55bSIngo Weinhold 	locker.Unlock();
8287b45b55bSIngo Weinhold 
8297b45b55bSIngo Weinhold 	// set the child name
8307b45b55bSIngo Weinhold 	error = diskSystem->SetName(child, name.value, DUMMY_JOB_ID);
8317b45b55bSIngo Weinhold 
8327b45b55bSIngo Weinhold 	// re-lock and unmark busy
8337b45b55bSIngo Weinhold 	locker.Lock();
8347b45b55bSIngo Weinhold 	partition->SetBusy(false);
8357b45b55bSIngo Weinhold 	child->SetBusy(false);
8367b45b55bSIngo Weinhold 
8372d690920SAxel Dörfler 	if (error != B_OK)
8382d690920SAxel Dörfler 		return error;
8397b45b55bSIngo Weinhold 
8407b45b55bSIngo Weinhold 	// return change counters
841*4644c7ccSJérôme Duval 	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
842*4644c7ccSJérôme Duval 	if (error == B_OK)
843*4644c7ccSJérôme Duval 		error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
8442d690920SAxel Dörfler 	return error;
8457b45b55bSIngo Weinhold }
8467b45b55bSIngo Weinhold 
847d6e565c7SIngo Weinhold 
8482d690920SAxel Dörfler status_t
_user_set_partition_content_name(partition_id partitionID,int32 * _changeCounter,const char * _name)8497b45b55bSIngo Weinhold _user_set_partition_content_name(partition_id partitionID,
8507b45b55bSIngo Weinhold 	int32* _changeCounter, const char* _name)
8512d690920SAxel Dörfler {
8527b45b55bSIngo Weinhold 	// copy parameters in
8537b45b55bSIngo Weinhold 	UserStringParameter<true> name;
8547b45b55bSIngo Weinhold 	int32 changeCounter;
8557b45b55bSIngo Weinhold 
856*4644c7ccSJérôme Duval 	status_t error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
857*4644c7ccSJérôme Duval 	if (error == B_OK)
858*4644c7ccSJérôme Duval 		error = copy_from_user_value(changeCounter, _changeCounter);
859*4644c7ccSJérôme Duval 	if (error != B_OK)
8602d690920SAxel Dörfler 		return error;
8617b45b55bSIngo Weinhold 
8622d690920SAxel Dörfler 	// get the partition
8637b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
8642d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
865*4644c7ccSJérôme Duval 	if (partition == NULL)
8662d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
8677b45b55bSIngo Weinhold 
8682d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
8692d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
8702d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
8717b45b55bSIngo Weinhold 
8727b45b55bSIngo Weinhold 	// check change counter
8737b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter())
8747b45b55bSIngo Weinhold 		return B_BAD_VALUE;
8757b45b55bSIngo Weinhold 
8767b45b55bSIngo Weinhold 	// the partition must be initialized
8777b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
878*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
8797b45b55bSIngo Weinhold 		return B_BAD_VALUE;
8807b45b55bSIngo Weinhold 
8817b45b55bSIngo Weinhold 	// mark the partition busy and unlock
8827b45b55bSIngo Weinhold 	if (!partition->CheckAndMarkBusy(false))
8837b45b55bSIngo Weinhold 		return B_BUSY;
8847b45b55bSIngo Weinhold 	locker.Unlock();
8857b45b55bSIngo Weinhold 
8867b45b55bSIngo Weinhold 	// set content parameters
8877b45b55bSIngo Weinhold 	error = diskSystem->SetContentName(partition, name.value, DUMMY_JOB_ID);
8887b45b55bSIngo Weinhold 
8897b45b55bSIngo Weinhold 	// re-lock and unmark busy
8907b45b55bSIngo Weinhold 	locker.Lock();
8917b45b55bSIngo Weinhold 	partition->UnmarkBusy(false);
8927b45b55bSIngo Weinhold 
8932d690920SAxel Dörfler 	if (error != B_OK)
8942d690920SAxel Dörfler 		return error;
8957b45b55bSIngo Weinhold 
8967b45b55bSIngo Weinhold 	// return change counter
897*4644c7ccSJérôme Duval 	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
8982d690920SAxel Dörfler }
8992d690920SAxel Dörfler 
900d6e565c7SIngo Weinhold 
9012d690920SAxel Dörfler status_t
_user_set_partition_type(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,const char * _type)9027b45b55bSIngo Weinhold _user_set_partition_type(partition_id partitionID, int32* _changeCounter,
9037b45b55bSIngo Weinhold 	partition_id childID, int32* _childChangeCounter, const char* _type)
9042d690920SAxel Dörfler {
9057b45b55bSIngo Weinhold 	// copy parameters in
9067b45b55bSIngo Weinhold 	UserStringParameter<false> type;
9077b45b55bSIngo Weinhold 	int32 changeCounter;
9087b45b55bSIngo Weinhold 	int32 childChangeCounter;
9097b45b55bSIngo Weinhold 
910*4644c7ccSJérôme Duval 	status_t error = type.Init(_type, B_DISK_DEVICE_TYPE_LENGTH);
911*4644c7ccSJérôme Duval 	if (error == B_OK)
912*4644c7ccSJérôme Duval 		error = copy_from_user_value(changeCounter, _changeCounter);
913*4644c7ccSJérôme Duval 	if (error == B_OK)
914*4644c7ccSJérôme Duval 		error = copy_from_user_value(childChangeCounter, _childChangeCounter);
915*4644c7ccSJérôme Duval 	if (error != B_OK)
9162d690920SAxel Dörfler 		return error;
917*4644c7ccSJérôme Duval 
9187b45b55bSIngo Weinhold 
9192d690920SAxel Dörfler 	// get the partition
9207b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
9212d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
922*4644c7ccSJérôme Duval 	if (partition == NULL)
9232d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
9247b45b55bSIngo Weinhold 
9252d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
9262d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
9272d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
9287b45b55bSIngo Weinhold 
9297b45b55bSIngo Weinhold 	// register child
9307b45b55bSIngo Weinhold 	KPartition* child = manager->RegisterPartition(childID);
931*4644c7ccSJérôme Duval 	if (child == NULL)
9327b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
9337b45b55bSIngo Weinhold 
9347b45b55bSIngo Weinhold 	PartitionRegistrar registrar3(child, true);
9357b45b55bSIngo Weinhold 
9367b45b55bSIngo Weinhold 	// check change counters
9377b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter()
9387b45b55bSIngo Weinhold 		|| childChangeCounter != child->ChangeCounter()) {
939300868ceSIngo Weinhold 		return B_BAD_VALUE;
9402d690920SAxel Dörfler 	}
9412d690920SAxel Dörfler 
9427b45b55bSIngo Weinhold 	// the partition must be initialized
9437b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
944*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
9457b45b55bSIngo Weinhold 		return B_BAD_VALUE;
9467b45b55bSIngo Weinhold 
9477b45b55bSIngo Weinhold 	// child must indeed be a child of partition
9487b45b55bSIngo Weinhold 	if (child->Parent() != partition)
9497b45b55bSIngo Weinhold 		return B_BAD_VALUE;
9507b45b55bSIngo Weinhold 
9517b45b55bSIngo Weinhold 	// mark the partition busy and unlock
9527b45b55bSIngo Weinhold 	if (partition->IsBusy() || child->IsBusy())
9537b45b55bSIngo Weinhold 		return B_BUSY;
9547b45b55bSIngo Weinhold 	partition->SetBusy(true);
9557b45b55bSIngo Weinhold 	child->SetBusy(true);
9567b45b55bSIngo Weinhold 	locker.Unlock();
9577b45b55bSIngo Weinhold 
9587b45b55bSIngo Weinhold 	// set the child type
9597b45b55bSIngo Weinhold 	error = diskSystem->SetType(child, type.value, DUMMY_JOB_ID);
9607b45b55bSIngo Weinhold 
9617b45b55bSIngo Weinhold 	// re-lock and unmark busy
9627b45b55bSIngo Weinhold 	locker.Lock();
9637b45b55bSIngo Weinhold 	partition->SetBusy(false);
9647b45b55bSIngo Weinhold 	child->SetBusy(false);
9657b45b55bSIngo Weinhold 
9667b45b55bSIngo Weinhold 	if (error != B_OK)
9677b45b55bSIngo Weinhold 		return error;
9687b45b55bSIngo Weinhold 
9697b45b55bSIngo Weinhold 	// return change counters
970*4644c7ccSJérôme Duval 	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
971*4644c7ccSJérôme Duval 	if (error == B_OK)
972*4644c7ccSJérôme Duval 		error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
9737b45b55bSIngo Weinhold 	return error;
9747b45b55bSIngo Weinhold }
9757b45b55bSIngo Weinhold 
976d6e565c7SIngo Weinhold 
9772d690920SAxel Dörfler status_t
_user_set_partition_parameters(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,const char * _parameters)9787b45b55bSIngo Weinhold _user_set_partition_parameters(partition_id partitionID, int32* _changeCounter,
979f75b8de3SAxel Dörfler 	partition_id childID, int32* _childChangeCounter, const char* _parameters)
9802d690920SAxel Dörfler {
9817b45b55bSIngo Weinhold 	// copy parameters in
982f75b8de3SAxel Dörfler 	UserStringParameter<true> parameters;
9837b45b55bSIngo Weinhold 	int32 changeCounter;
9847b45b55bSIngo Weinhold 	int32 childChangeCounter;
9857b45b55bSIngo Weinhold 
986*4644c7ccSJérôme Duval 	status_t error
987*4644c7ccSJérôme Duval 		= parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
988*4644c7ccSJérôme Duval 	if (error == B_OK)
989*4644c7ccSJérôme Duval 		error = copy_from_user_value(changeCounter, _changeCounter);
990*4644c7ccSJérôme Duval 	if (error == B_OK)
991*4644c7ccSJérôme Duval 		error = copy_from_user_value(childChangeCounter, _childChangeCounter);
992*4644c7ccSJérôme Duval 	if (error != B_OK)
9937b45b55bSIngo Weinhold 		return error;
9947b45b55bSIngo Weinhold 
9952d690920SAxel Dörfler 	// get the partition
9967b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
9972d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
998*4644c7ccSJérôme Duval 	if (partition == NULL)
9997b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
10007b45b55bSIngo Weinhold 
10012d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
10022d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
10032d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
10047b45b55bSIngo Weinhold 
10057b45b55bSIngo Weinhold 	// register child
10067b45b55bSIngo Weinhold 	KPartition* child = manager->RegisterPartition(childID);
1007*4644c7ccSJérôme Duval 	if (child == NULL)
10087b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
10097b45b55bSIngo Weinhold 
10107b45b55bSIngo Weinhold 	PartitionRegistrar registrar3(child, true);
10117b45b55bSIngo Weinhold 
10127b45b55bSIngo Weinhold 	// check change counters
10137b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter()
10147b45b55bSIngo Weinhold 		|| childChangeCounter != child->ChangeCounter()) {
1015300868ceSIngo Weinhold 		return B_BAD_VALUE;
10162d690920SAxel Dörfler 	}
10172d690920SAxel Dörfler 
10187b45b55bSIngo Weinhold 	// the partition must be initialized
10197b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
1020*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
10217b45b55bSIngo Weinhold 		return B_BAD_VALUE;
10227b45b55bSIngo Weinhold 
10237b45b55bSIngo Weinhold 	// child must indeed be a child of partition
10247b45b55bSIngo Weinhold 	if (child->Parent() != partition)
10257b45b55bSIngo Weinhold 		return B_BAD_VALUE;
10267b45b55bSIngo Weinhold 
10277b45b55bSIngo Weinhold 	// mark the partition busy and unlock
10287b45b55bSIngo Weinhold 	if (partition->IsBusy() || child->IsBusy())
10297b45b55bSIngo Weinhold 		return B_BUSY;
10307b45b55bSIngo Weinhold 	partition->SetBusy(true);
10317b45b55bSIngo Weinhold 	child->SetBusy(true);
10327b45b55bSIngo Weinhold 	locker.Unlock();
10337b45b55bSIngo Weinhold 
10347b45b55bSIngo Weinhold 	// set the child parameters
10357b45b55bSIngo Weinhold 	error = diskSystem->SetParameters(child, parameters.value, DUMMY_JOB_ID);
10367b45b55bSIngo Weinhold 
10377b45b55bSIngo Weinhold 	// re-lock and unmark busy
10387b45b55bSIngo Weinhold 	locker.Lock();
10397b45b55bSIngo Weinhold 	partition->SetBusy(false);
10407b45b55bSIngo Weinhold 	child->SetBusy(false);
10417b45b55bSIngo Weinhold 
10427b45b55bSIngo Weinhold 	if (error != B_OK)
10437b45b55bSIngo Weinhold 		return error;
10447b45b55bSIngo Weinhold 
10457b45b55bSIngo Weinhold 	// return change counters
1046*4644c7ccSJérôme Duval 	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
1047*4644c7ccSJérôme Duval 	if (error == B_OK)
1048*4644c7ccSJérôme Duval 		error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
10497b45b55bSIngo Weinhold 	return error;
10507b45b55bSIngo Weinhold }
10517b45b55bSIngo Weinhold 
1052d6e565c7SIngo Weinhold 
10532d690920SAxel Dörfler status_t
_user_set_partition_content_parameters(partition_id partitionID,int32 * _changeCounter,const char * _parameters)10542d690920SAxel Dörfler _user_set_partition_content_parameters(partition_id partitionID,
1055f75b8de3SAxel Dörfler 	int32* _changeCounter, const char* _parameters)
10562d690920SAxel Dörfler {
10577b45b55bSIngo Weinhold 	// copy parameters in
1058f75b8de3SAxel Dörfler 	UserStringParameter<true> parameters;
10597b45b55bSIngo Weinhold 	int32 changeCounter;
10607b45b55bSIngo Weinhold 
1061f75b8de3SAxel Dörfler 	status_t error
1062f75b8de3SAxel Dörfler 		= parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
1063*4644c7ccSJérôme Duval 	if (error == B_OK)
1064*4644c7ccSJérôme Duval 		error = copy_from_user_value(changeCounter, _changeCounter);
1065*4644c7ccSJérôme Duval 	if (error != B_OK)
10667b45b55bSIngo Weinhold 		return error;
10677b45b55bSIngo Weinhold 
10682d690920SAxel Dörfler 	// get the partition
10697b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
10702d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
1071*4644c7ccSJérôme Duval 	if (partition == NULL)
10727b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
10737b45b55bSIngo Weinhold 
10742d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
10752d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
10762d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
10777b45b55bSIngo Weinhold 
10787b45b55bSIngo Weinhold 	// check change counter
10797b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter())
1080300868ceSIngo Weinhold 		return B_BAD_VALUE;
10817b45b55bSIngo Weinhold 
10827b45b55bSIngo Weinhold 	// the partition must be initialized
10837b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
1084*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
10857b45b55bSIngo Weinhold 		return B_BAD_VALUE;
10867b45b55bSIngo Weinhold 
10877b45b55bSIngo Weinhold 	// mark the partition busy and unlock
10887b45b55bSIngo Weinhold 	if (!partition->CheckAndMarkBusy(true))
10897b45b55bSIngo Weinhold 		return B_BUSY;
10907b45b55bSIngo Weinhold 	locker.Unlock();
10917b45b55bSIngo Weinhold 
10927b45b55bSIngo Weinhold 	// set content parameters
10937b45b55bSIngo Weinhold 	error = diskSystem->SetContentParameters(partition, parameters.value,
10947b45b55bSIngo Weinhold 		DUMMY_JOB_ID);
10957b45b55bSIngo Weinhold 
10967b45b55bSIngo Weinhold 	// re-lock and unmark busy
10977b45b55bSIngo Weinhold 	locker.Lock();
10987b45b55bSIngo Weinhold 	partition->UnmarkBusy(true);
10997b45b55bSIngo Weinhold 
11007b45b55bSIngo Weinhold 	if (error != B_OK)
11017b45b55bSIngo Weinhold 		return error;
11027b45b55bSIngo Weinhold 
11037b45b55bSIngo Weinhold 	// return change counter
1104*4644c7ccSJérôme Duval 	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
11052d690920SAxel Dörfler }
11062d690920SAxel Dörfler 
1107d6e565c7SIngo Weinhold 
11082d690920SAxel Dörfler status_t
_user_initialize_partition(partition_id partitionID,int32 * _changeCounter,const char * _diskSystemName,const char * _name,const char * _parameters)11097b45b55bSIngo Weinhold _user_initialize_partition(partition_id partitionID, int32* _changeCounter,
1110f75b8de3SAxel Dörfler 	const char* _diskSystemName, const char* _name, const char* _parameters)
11112d690920SAxel Dörfler {
11127b45b55bSIngo Weinhold 	// copy parameters in
11137b45b55bSIngo Weinhold 	UserStringParameter<false> diskSystemName;
11147b45b55bSIngo Weinhold 	UserStringParameter<true> name;
1115f75b8de3SAxel Dörfler 	UserStringParameter<true> parameters;
11167b45b55bSIngo Weinhold 	int32 changeCounter;
1117aa4d8ee6SIngo Weinhold 
1118*4644c7ccSJérôme Duval 	status_t error
1119*4644c7ccSJérôme Duval 		= diskSystemName.Init(_diskSystemName, B_DISK_SYSTEM_NAME_LENGTH);
1120*4644c7ccSJérôme Duval 	if (error == B_OK)
1121*4644c7ccSJérôme Duval 		error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
1122*4644c7ccSJérôme Duval 	if (error == B_OK)
1123*4644c7ccSJérôme Duval 		error = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
1124*4644c7ccSJérôme Duval 	if (error == B_OK)
1125*4644c7ccSJérôme Duval 		error = copy_from_user_value(changeCounter, _changeCounter);
1126*4644c7ccSJérôme Duval 	if (error != B_OK)
11272d690920SAxel Dörfler 		return error;
1128aa4d8ee6SIngo Weinhold 
11292d690920SAxel Dörfler 	// get the partition
1130aa4d8ee6SIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
11312d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
1132*4644c7ccSJérôme Duval 	if (partition == NULL)
1133aa4d8ee6SIngo Weinhold 		return B_ENTRY_NOT_FOUND;
1134aa4d8ee6SIngo Weinhold 
11352d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
11362d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
11372d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
1138aa4d8ee6SIngo Weinhold 
11397b45b55bSIngo Weinhold 	// check change counter
11407b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter())
11417b45b55bSIngo Weinhold 		return B_BAD_VALUE;
11427b45b55bSIngo Weinhold 
11437b45b55bSIngo Weinhold 	// the partition must be uninitialized
1144*4644c7ccSJérôme Duval 	if (partition->DiskSystem() != NULL)
11457b45b55bSIngo Weinhold 		return B_BAD_VALUE;
11467b45b55bSIngo Weinhold 
11477b45b55bSIngo Weinhold 	// load the new disk system
1148c9830ce0SIngo Weinhold 	KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName.value,
1149c9830ce0SIngo Weinhold 		true);
1150*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
1151aa4d8ee6SIngo Weinhold 		return B_ENTRY_NOT_FOUND;
11522d690920SAxel Dörfler 	DiskSystemLoader loader(diskSystem, true);
1153aa4d8ee6SIngo Weinhold 
11547b45b55bSIngo Weinhold 	// mark the partition busy and unlock
11557b45b55bSIngo Weinhold 	if (!partition->CheckAndMarkBusy(true))
11567b45b55bSIngo Weinhold 		return B_BUSY;
11577b45b55bSIngo Weinhold 	locker.Unlock();
1158aa4d8ee6SIngo Weinhold 
11597b45b55bSIngo Weinhold 	// let the disk system initialize the partition
11607b45b55bSIngo Weinhold 	error = diskSystem->Initialize(partition, name.value, parameters.value,
11617b45b55bSIngo Weinhold 		DUMMY_JOB_ID);
11627b45b55bSIngo Weinhold 
11637b45b55bSIngo Weinhold 	// re-lock and unmark busy
11647b45b55bSIngo Weinhold 	locker.Lock();
11657b45b55bSIngo Weinhold 	partition->UnmarkBusy(true);
11667b45b55bSIngo Weinhold 
1167aa4d8ee6SIngo Weinhold 	if (error != B_OK)
1168aa4d8ee6SIngo Weinhold 		return error;
1169aa4d8ee6SIngo Weinhold 
1170f84387d6SIngo Weinhold 	// Set the disk system. Re-check whether a disk system is already set on the
1171f84387d6SIngo Weinhold 	// partition. Some disk systems just write the on-disk structures and let
1172f84387d6SIngo Weinhold 	// the DDM rescan the partition, in which case the disk system will already
1173f84387d6SIngo Weinhold 	// be set. In very unfortunate cases the on-disk structure of the previous
1174f84387d6SIngo Weinhold 	// disk system has not been destroyed and the previous disk system has a
1175f84387d6SIngo Weinhold 	// higher priority than the new one. The old disk system will thus prevail.
1176f84387d6SIngo Weinhold 	// Not setting the new disk system will at least prevent that the partition
1177f84387d6SIngo Weinhold 	// object gets into an inconsistent state.
1178f84387d6SIngo Weinhold 	if (partition->DiskSystem() == NULL)
1179aa4d8ee6SIngo Weinhold 		partition->SetDiskSystem(diskSystem);
1180aa4d8ee6SIngo Weinhold 
11817b45b55bSIngo Weinhold 	// return change counter
1182*4644c7ccSJérôme Duval 	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
11832d690920SAxel Dörfler }
11842d690920SAxel Dörfler 
1185d6e565c7SIngo Weinhold 
11862d690920SAxel Dörfler status_t
_user_uninitialize_partition(partition_id partitionID,int32 * _changeCounter,partition_id parentID,int32 * _parentChangeCounter)11874419d699SJessica Hamilton _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter,
11884419d699SJessica Hamilton 	partition_id parentID, int32* _parentChangeCounter)
11892d690920SAxel Dörfler {
11907b45b55bSIngo Weinhold 	// copy parameters in
11917b45b55bSIngo Weinhold 	int32 changeCounter;
11924419d699SJessica Hamilton 	int32 parentChangeCounter;
11934419d699SJessica Hamilton 	bool haveParent = parentID >= 0;
11947b45b55bSIngo Weinhold 
1195*4644c7ccSJérôme Duval 	status_t error = copy_from_user_value(changeCounter, _changeCounter);
1196*4644c7ccSJérôme Duval 	if (haveParent && error == B_OK)
1197*4644c7ccSJérôme Duval 		error = copy_from_user_value(parentChangeCounter, _parentChangeCounter);
1198*4644c7ccSJérôme Duval 	if (error != B_OK)
11994419d699SJessica Hamilton 		return error;
12007b45b55bSIngo Weinhold 
12012d690920SAxel Dörfler 	// get the partition
12027b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
12032d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
1204*4644c7ccSJérôme Duval 	if (partition == NULL)
12052d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
12067b45b55bSIngo Weinhold 
12072d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
12082d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
12092d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
12107b45b55bSIngo Weinhold 
12114419d699SJessica Hamilton 	// register parent
12124419d699SJessica Hamilton 	KPartition* parent = NULL;
12134419d699SJessica Hamilton 	if (haveParent)
12144419d699SJessica Hamilton 		parent = manager->RegisterPartition(parentID);
12154419d699SJessica Hamilton 
12164419d699SJessica Hamilton 	PartitionRegistrar registrar3(parent, true);
12174419d699SJessica Hamilton 
12187b45b55bSIngo Weinhold 	// check change counter
12197b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter())
1220300868ceSIngo Weinhold 		return B_BAD_VALUE;
12214419d699SJessica Hamilton 	if (haveParent && parentChangeCounter != parent->ChangeCounter())
12224419d699SJessica Hamilton 		return B_BAD_VALUE;
12237b45b55bSIngo Weinhold 
12247b45b55bSIngo Weinhold 	// the partition must be initialized
1225*4644c7ccSJérôme Duval 	if (partition->DiskSystem() == NULL)
12267b45b55bSIngo Weinhold 		return B_BAD_VALUE;
12277b45b55bSIngo Weinhold 
12287b45b55bSIngo Weinhold 	// check busy
1229b3a5629bSIngo Weinhold 	if (!partition->CheckAndMarkBusy(true))
12307b45b55bSIngo Weinhold 		return B_BUSY;
12317b45b55bSIngo Weinhold 
12324ed39e6aSAdrien Destugues 	if (partition->IsMounted() || partition->IsChildMounted())
1233f26118f2SAdrien Destugues 		return B_BAD_VALUE;
12347b45b55bSIngo Weinhold 
1235285f4cf4SIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
1236285f4cf4SIngo Weinhold 
1237285f4cf4SIngo Weinhold 	locker.Unlock();
1238285f4cf4SIngo Weinhold 
1239285f4cf4SIngo Weinhold 	// Let the disk system uninitialize the partition. This operation is not
1240285f4cf4SIngo Weinhold 	// mandatory. If implemented, it will destroy the on-disk structures, so
1241285f4cf4SIngo Weinhold 	// that the disk system cannot accidentally identify the partition later on.
1242285f4cf4SIngo Weinhold 	if (diskSystem != NULL)
1243285f4cf4SIngo Weinhold 		diskSystem->Uninitialize(partition, DUMMY_JOB_ID);
1244285f4cf4SIngo Weinhold 
1245285f4cf4SIngo Weinhold 	// re-lock and uninitialize the partition object
1246285f4cf4SIngo Weinhold 	locker.Lock();
12477b45b55bSIngo Weinhold 	error = partition->UninitializeContents(true);
12480cbc783bSAxel Dörfler 
12490cbc783bSAxel Dörfler 	partition->UnmarkBusy(true);
12500cbc783bSAxel Dörfler 
12517b45b55bSIngo Weinhold 	if (error != B_OK)
12527b45b55bSIngo Weinhold 		return error;
12537b45b55bSIngo Weinhold 
12547b45b55bSIngo Weinhold 	// return change counter
12557b45b55bSIngo Weinhold 	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
1256*4644c7ccSJérôme Duval 	if (haveParent && error == B_OK)
1257*4644c7ccSJérôme Duval 		error = copy_to_user_value(_parentChangeCounter, parent->ChangeCounter());
12587b45b55bSIngo Weinhold 	return error;
12592d690920SAxel Dörfler }
12602d690920SAxel Dörfler 
1261d6e565c7SIngo Weinhold 
12622d690920SAxel Dörfler status_t
_user_create_child_partition(partition_id partitionID,int32 * _changeCounter,off_t offset,off_t size,const char * _type,const char * _name,const char * _parameters,partition_id * childID,int32 * childChangeCounter)12637b45b55bSIngo Weinhold _user_create_child_partition(partition_id partitionID, int32* _changeCounter,
12647b45b55bSIngo Weinhold 	off_t offset, off_t size, const char* _type, const char* _name,
1265f75b8de3SAxel Dörfler 	const char* _parameters, partition_id* childID, int32* childChangeCounter)
12662d690920SAxel Dörfler {
12677b45b55bSIngo Weinhold 	// copy parameters in
12687b45b55bSIngo Weinhold 	UserStringParameter<false> type;
12697b45b55bSIngo Weinhold 	UserStringParameter<true> name;
1270f75b8de3SAxel Dörfler 	UserStringParameter<true> parameters;
12717b45b55bSIngo Weinhold 	int32 changeCounter;
12727b45b55bSIngo Weinhold 
1273*4644c7ccSJérôme Duval 	status_t error = type.Init(_type, B_DISK_DEVICE_TYPE_LENGTH);
1274*4644c7ccSJérôme Duval 	if (error == B_OK)
1275*4644c7ccSJérôme Duval 		error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
1276*4644c7ccSJérôme Duval 	if (error == B_OK)
1277*4644c7ccSJérôme Duval 		error = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
1278*4644c7ccSJérôme Duval 	if (error == B_OK)
1279*4644c7ccSJérôme Duval 		error = copy_from_user_value(changeCounter, _changeCounter);
1280*4644c7ccSJérôme Duval 	if (error != B_OK)
12812d690920SAxel Dörfler 		return error;
12827b45b55bSIngo Weinhold 
12832d690920SAxel Dörfler 	// get the partition
12847b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
12852d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
1286*4644c7ccSJérôme Duval 	if (partition == NULL)
12877b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
12887b45b55bSIngo Weinhold 
12892d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
12902d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
12912d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
12927b45b55bSIngo Weinhold 
12937b45b55bSIngo Weinhold 	// check change counter
12947b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter())
12957b45b55bSIngo Weinhold 		return B_BAD_VALUE;
12967b45b55bSIngo Weinhold 
12977b45b55bSIngo Weinhold 	// the partition must be initialized
12987b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
1299*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
13007b45b55bSIngo Weinhold 		return B_BAD_VALUE;
13017b45b55bSIngo Weinhold 
13027b45b55bSIngo Weinhold 	// mark the partition busy and unlock
13037b45b55bSIngo Weinhold 	if (!partition->CheckAndMarkBusy(false))
13047b45b55bSIngo Weinhold 		return B_BUSY;
13057b45b55bSIngo Weinhold 	locker.Unlock();
13067b45b55bSIngo Weinhold 
13072d690920SAxel Dörfler 	// create the child
13082d690920SAxel Dörfler 	KPartition *child = NULL;
13097b45b55bSIngo Weinhold 	error = diskSystem->CreateChild(partition, offset, size, type.value,
13107b45b55bSIngo Weinhold 		name.value, parameters.value, DUMMY_JOB_ID, &child, -1);
13117b45b55bSIngo Weinhold 
13127b45b55bSIngo Weinhold 	// re-lock and unmark busy
13137b45b55bSIngo Weinhold 	locker.Lock();
13147b45b55bSIngo Weinhold 	partition->UnmarkBusy(false);
13157b45b55bSIngo Weinhold 
13167b45b55bSIngo Weinhold 	if (error != B_OK)
13172d690920SAxel Dörfler 		return error;
13187b45b55bSIngo Weinhold 
13197b45b55bSIngo Weinhold 	if (child == NULL)
13207b45b55bSIngo Weinhold 		return B_ERROR;
13217b45b55bSIngo Weinhold 
13227b45b55bSIngo Weinhold 	child->UnmarkBusy(true);
13237b45b55bSIngo Weinhold 
13247b45b55bSIngo Weinhold 	// return change counter and child ID
1325*4644c7ccSJérôme Duval 	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
1326*4644c7ccSJérôme Duval 	if (error == B_OK)
1327*4644c7ccSJérôme Duval 		error = copy_to_user_value(childID, child->ID());
13287b45b55bSIngo Weinhold 	return error;
13297b45b55bSIngo Weinhold }
13307b45b55bSIngo Weinhold 
1331d6e565c7SIngo Weinhold 
13322d690920SAxel Dörfler status_t
_user_delete_child_partition(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 childChangeCounter)13337b45b55bSIngo Weinhold _user_delete_child_partition(partition_id partitionID, int32* _changeCounter,
1334300868ceSIngo Weinhold 	partition_id childID, int32 childChangeCounter)
13352d690920SAxel Dörfler {
13367b45b55bSIngo Weinhold 	// copy parameters in
13377b45b55bSIngo Weinhold 	int32 changeCounter;
13387b45b55bSIngo Weinhold 
13397b45b55bSIngo Weinhold 	status_t error;
13407b45b55bSIngo Weinhold 	if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK)
13417b45b55bSIngo Weinhold 		return error;
13427b45b55bSIngo Weinhold 
13432d690920SAxel Dörfler 	// get the partition
13447b45b55bSIngo Weinhold 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
13452d690920SAxel Dörfler 	KPartition* partition = manager->WriteLockPartition(partitionID);
1346*4644c7ccSJérôme Duval 	if (partition == NULL)
13472d690920SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
13487b45b55bSIngo Weinhold 
13492d690920SAxel Dörfler 	PartitionRegistrar registrar1(partition, true);
13502d690920SAxel Dörfler 	PartitionRegistrar registrar2(partition->Device(), true);
13512d690920SAxel Dörfler 	DeviceWriteLocker locker(partition->Device(), true);
13527b45b55bSIngo Weinhold 
13537b45b55bSIngo Weinhold 	// register child
13547b45b55bSIngo Weinhold 	KPartition* child = manager->RegisterPartition(childID);
1355*4644c7ccSJérôme Duval 	if (child == NULL)
13567b45b55bSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
13577b45b55bSIngo Weinhold 
13587b45b55bSIngo Weinhold 	PartitionRegistrar registrar3(child, true);
13597b45b55bSIngo Weinhold 
13607b45b55bSIngo Weinhold 	// check change counters
13617b45b55bSIngo Weinhold 	if (changeCounter != partition->ChangeCounter()
13627b45b55bSIngo Weinhold 		|| childChangeCounter != child->ChangeCounter()) {
13637b45b55bSIngo Weinhold 		return B_BAD_VALUE;
13647b45b55bSIngo Weinhold 	}
13657b45b55bSIngo Weinhold 
13667b45b55bSIngo Weinhold 	// the partition must be initialized
13677b45b55bSIngo Weinhold 	KDiskSystem* diskSystem = partition->DiskSystem();
1368*4644c7ccSJérôme Duval 	if (diskSystem == NULL)
13697b45b55bSIngo Weinhold 		return B_BAD_VALUE;
13707b45b55bSIngo Weinhold 
13717b45b55bSIngo Weinhold 	// child must indeed be a child of partition
13727b45b55bSIngo Weinhold 	if (child->Parent() != partition)
13737b45b55bSIngo Weinhold 		return B_BAD_VALUE;
13747b45b55bSIngo Weinhold 
13757b45b55bSIngo Weinhold 	// mark the partition and child busy and unlock
13767b45b55bSIngo Weinhold 	if (partition->IsBusy() || !child->CheckAndMarkBusy(true))
13777b45b55bSIngo Weinhold 		return B_BUSY;
13787b45b55bSIngo Weinhold 	partition->SetBusy(true);
13797b45b55bSIngo Weinhold 	locker.Unlock();
13807b45b55bSIngo Weinhold 
13817b45b55bSIngo Weinhold 	// delete the child
13827b45b55bSIngo Weinhold 	error = diskSystem->DeleteChild(child, DUMMY_JOB_ID);
13837b45b55bSIngo Weinhold 
13847b45b55bSIngo Weinhold 	// re-lock and unmark busy
13857b45b55bSIngo Weinhold 	locker.Lock();
13867b45b55bSIngo Weinhold 	partition->SetBusy(false);
13877b45b55bSIngo Weinhold 	child->UnmarkBusy(true);
13887b45b55bSIngo Weinhold 
13892d690920SAxel Dörfler 	if (error != B_OK)
13902d690920SAxel Dörfler 		return error;
13917b45b55bSIngo Weinhold 
13927b45b55bSIngo Weinhold 	// return change counter
139349fb53eeSAxel Dörfler 	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
13942d690920SAxel Dörfler }
13953f78b216SAxel Dörfler 
13963f78b216SAxel Dörfler 
13973f78b216SAxel Dörfler status_t
_user_start_watching_disks(uint32 eventMask,port_id port,int32 token)13983f78b216SAxel Dörfler _user_start_watching_disks(uint32 eventMask, port_id port, int32 token)
13993f78b216SAxel Dörfler {
14003f78b216SAxel Dörfler 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
14013f78b216SAxel Dörfler 	return manager->Notifications().UpdateUserListener(eventMask, port, token);
14023f78b216SAxel Dörfler }
14033f78b216SAxel Dörfler 
14043f78b216SAxel Dörfler 
14053f78b216SAxel Dörfler status_t
_user_stop_watching_disks(port_id port,int32 token)14063f78b216SAxel Dörfler _user_stop_watching_disks(port_id port, int32 token)
14073f78b216SAxel Dörfler {
14083f78b216SAxel Dörfler 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
14093f78b216SAxel Dörfler 	return manager->Notifications().RemoveUserListeners(port, token);
14103f78b216SAxel Dörfler }
14113f78b216SAxel Dörfler 
1412