Make the unmount_device request take a handle to the device file
itself instead of a handle to a file opened on the device.
diff --git a/server/fd.c b/server/fd.c
index 8de8216..c7569af 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -580,7 +580,7 @@
static struct list device_hash[DEVICE_HASH_SIZE];
/* retrieve the device object for a given fd, creating it if needed */
-static struct device *get_device( dev_t dev )
+static struct device *get_device( dev_t dev, int create )
{
struct device *device;
unsigned int i, hash = dev % DEVICE_HASH_SIZE;
@@ -593,6 +593,8 @@
else list_init( &device_hash[hash] );
/* not found, create it */
+
+ if (!create) return NULL;
if ((device = alloc_object( &device_ops )))
{
device->dev = dev;
@@ -695,7 +697,7 @@
struct inode *inode;
unsigned int hash = ino % INODE_HASH_SIZE;
- if (!(device = get_device( dev ))) return NULL;
+ if (!(device = get_device( dev, 1 ))) return NULL;
LIST_FOR_EACH_ENTRY( inode, &device->inode_hash[hash], struct inode, entry )
{
@@ -1580,12 +1582,22 @@
}
/* close all Unix file descriptors on a device to allow unmounting it */
-static void unmount_device( struct device *device )
+static void unmount_device( struct fd *device_fd )
{
unsigned int i;
+ struct stat st;
+ struct device *device;
struct inode *inode;
struct fd *fd;
+ if (device_fd->unix_fd == -1 || fstat( device_fd->unix_fd, &st ) == -1 || !S_ISBLK( st.st_mode ))
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if (!(device = get_device( st.st_rdev, 0 ))) return;
+
for (i = 0; i < INODE_HASH_SIZE; i++)
{
LIST_FOR_EACH_ENTRY( inode, &device->inode_hash[i], struct inode, entry )
@@ -1600,6 +1612,7 @@
/* remove it from the hash table */
list_remove( &device->entry );
list_init( &device->entry );
+ release_object( device );
}
/* same as get_handle_obj but retrieve the struct fd associated to the object */
@@ -1682,8 +1695,7 @@
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
{
- if (fd->inode) unmount_device( fd->inode->device );
- else set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ unmount_device( fd );
release_object( fd );
}
}