bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] rumpdisk: Protect open/close/read/write with a rwlock


From: Samuel Thibault
Subject: Re: [PATCH] rumpdisk: Protect open/close/read/write with a rwlock
Date: Sun, 27 Feb 2022 01:41:39 +0100
User-agent: NeoMutt/20170609 (1.8.3)

Damien Zammit, le dim. 27 févr. 2022 00:27:02 +0000, a ecrit:
> TESTED to boot off a rump based disk

Applied, thanks!

> ---
>  rumpdisk/block-rump.c | 77 ++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 66 insertions(+), 11 deletions(-)
> 
> diff --git a/rumpdisk/block-rump.c b/rumpdisk/block-rump.c
> index 10fa66ad..464c5cdd 100644
> --- a/rumpdisk/block-rump.c
> +++ b/rumpdisk/block-rump.c
> @@ -52,6 +52,9 @@ static bool disabled;
> 
>  static mach_port_t master_host;
> 
> +/* rwlock to protect concurrent close while reading/writing */
> +pthread_rwlock_t rumpdisk_rwlock = PTHREAD_RWLOCK_INITIALIZER;
> +
>  /* One of these is associated with each open instance of a device.  */
>  struct block_data
>  {
> @@ -83,7 +86,8 @@ search_bd (const char *name)
> 
>    while (bd)
>      {
> -      if (!strcmp (bd->name, name))
> +      /* Check name and refcount > 0 */
> +      if (!strcmp (bd->name, name) && bd->taken)
>       return bd;
>        bd = bd->next;
>      }
> @@ -183,16 +187,26 @@ rumpdisk_device_close (void *d)
>    struct block_data *bd = d;
>    io_return_t err;
> 
> +  pthread_rwlock_wrlock (&rumpdisk_rwlock);
> +
>    bd->taken--;
>    if (bd->taken)
> -    return D_SUCCESS;
> +    {
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
> +      return D_SUCCESS;
> +    }
> 
>    err = rump_errno2host (rump_sys_close (bd->rump_fd));
>    if (err != D_SUCCESS)
> -    return err;
> +    {
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
> +      return err;
> +    }
> 
>    ports_port_deref (bd);
>    ports_destroy_right (bd);
> +
> +  pthread_rwlock_unlock (&rumpdisk_rwlock);
>    return D_SUCCESS;
>  }
> 
> @@ -229,6 +243,9 @@ rumpdisk_device_open (mach_port_t reply_port, 
> mach_msg_type_name_t reply_port_ty
>    if (! is_disk_device (name))
>      return D_NO_SUCH_DEVICE;
> 
> +  /* Protect against concurrent open/close */
> +  pthread_rwlock_wrlock (&rumpdisk_rwlock);
> +
>    /* Find previous device or open if new */
>    bd = search_bd (name);
>    if (bd)
> @@ -236,6 +253,8 @@ rumpdisk_device_open (mach_port_t reply_port, 
> mach_msg_type_name_t reply_port_ty
>        bd->taken++;
>        *devp = ports_get_right (bd);
>        *devicePoly = MACH_MSG_TYPE_MAKE_SEND;
> +
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
>        return D_SUCCESS;
>      }
> 
> @@ -243,12 +262,16 @@ rumpdisk_device_open (mach_port_t reply_port, 
> mach_msg_type_name_t reply_port_ty
> 
>    fd = rump_sys_open (dev_name, dev_mode_to_rump_mode (mode));
>    if (fd < 0)
> -    return rump_errno2host (errno);
> +    {
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
> +      return rump_errno2host (errno);
> +    }
> 
>    ret = rump_sys_ioctl (fd, DIOCGMEDIASIZE, &media_size);
>    if (ret < 0)
>      {
>        mach_print ("DIOCGMEDIASIZE ioctl fails\n");
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
>        return rump_errno2host (errno);
>      }
> 
> @@ -256,6 +279,7 @@ rumpdisk_device_open (mach_port_t reply_port, 
> mach_msg_type_name_t reply_port_ty
>    if (ret < 0)
>      {
>        mach_print ("DIOCGSECTORSIZE ioctl fails\n");
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
>        return rump_errno2host (errno);
>      }
> 
> @@ -263,6 +287,7 @@ rumpdisk_device_open (mach_port_t reply_port, 
> mach_msg_type_name_t reply_port_ty
>    if (err != 0)
>      {
>        rump_sys_close (fd);
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
>        return err;
>      }
> 
> @@ -280,6 +305,8 @@ rumpdisk_device_open (mach_port_t reply_port, 
> mach_msg_type_name_t reply_port_ty
> 
>    *devp = ports_get_right (bd);
>    *devicePoly = MACH_MSG_TYPE_MAKE_SEND;
> +
> +  pthread_rwlock_unlock (&rumpdisk_rwlock);
>    return D_SUCCESS;
>  }
> 
> @@ -296,6 +323,14 @@ rumpdisk_device_write (void *d, mach_port_t reply_port,
>    if ((bd->mode & D_WRITE) == 0)
>      return D_INVALID_OPERATION;
> 
> +  pthread_rwlock_rdlock (&rumpdisk_rwlock);
> +  /* Ensure device is still open */
> +  if (! bd->taken)
> +    {
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
> +      return D_INVALID_OPERATION;
> +    }
> +
>    if ((vm_offset_t) data % pagesize)
>      {
>        /* Not aligned, have to copy to aligned buffer.  */
> @@ -307,7 +342,10 @@ rumpdisk_device_write (void *d, mach_port_t reply_port,
>        /* While at it, make it contiguous */
>        ret = vm_allocate_contiguous (master_host, mach_task_self (), &buf, 
> &pap, count, 0, 0x100000000ULL, 0);
>        if (ret != KERN_SUCCESS)
> -     return ENOMEM;
> +     {
> +       pthread_rwlock_unlock (&rumpdisk_rwlock);
> +       return ENOMEM;
> +     }
> 
>        memcpy ((void*) buf, data, count);
> 
> @@ -317,7 +355,10 @@ rumpdisk_device_write (void *d, mach_port_t reply_port,
>        vm_deallocate (mach_task_self (), (vm_address_t) buf, count);
> 
>        if (written < 0)
> -     return rump_errno2host (err);
> +     {
> +       pthread_rwlock_unlock (&rumpdisk_rwlock);
> +       return rump_errno2host (err);
> +     }
>      }
>    else
>      {
> @@ -343,7 +384,10 @@ rumpdisk_device_write (void *d, mach_port_t reply_port,
>         done = rump_sys_pwrite (bd->rump_fd, (const void *)data + written, 
> todo, (off_t)bn * bd->block_size + written);
> 
>         if (done < 0)
> -         return rump_errno2host (errno);
> +         {
> +           pthread_rwlock_unlock (&rumpdisk_rwlock);
> +           return rump_errno2host (errno);
> +         }
> 
>         written += done;
>       }
> @@ -352,6 +396,7 @@ rumpdisk_device_write (void *d, mach_port_t reply_port,
>    vm_deallocate (mach_task_self (), (vm_address_t) data, count);
> 
>    *bytes_written = (int)written;
> +  pthread_rwlock_unlock (&rumpdisk_rwlock);
>    return D_SUCCESS;
>  }
> 
> @@ -375,11 +420,22 @@ rumpdisk_device_read (void *d, mach_port_t reply_port,
>    if (count == 0)
>      return D_SUCCESS;
> 
> +  pthread_rwlock_rdlock (&rumpdisk_rwlock);
> +  /* Ensure device is still open */
> +  if (! bd->taken)
> +    {
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
> +      return D_INVALID_OPERATION;
> +    }
> +
>    /* TODO: directly write at *data when it is aligned */
>    *data = 0;
>    ret = vm_allocate (mach_task_self (), &buf, npages * pagesize, TRUE);
>    if (ret != KERN_SUCCESS)
> -    return ENOMEM;
> +    {
> +      pthread_rwlock_unlock (&rumpdisk_rwlock);
> +      return ENOMEM;
> +    }
> 
>    /* Ensure physical allocation by writing a single byte of each */
>    for (i = 0; i < npages; i++)
> @@ -400,6 +456,7 @@ rumpdisk_device_read (void *d, mach_port_t reply_port,
>       {
>         err = errno;
>         vm_deallocate (mach_task_self (), buf, npages * pagesize);
> +       pthread_rwlock_unlock (&rumpdisk_rwlock);
>         return rump_errno2host (err);
>       }
> 
> @@ -408,6 +465,7 @@ rumpdisk_device_read (void *d, mach_port_t reply_port,
> 
>    *bytes_read = done;
>    *data = (void*) buf;
> +  pthread_rwlock_unlock (&rumpdisk_rwlock);
>    return D_SUCCESS;
>  }
> 
> @@ -455,9 +513,6 @@ rumpdisk_device_get_status (void *d, dev_flavor_t flavor, 
> dev_status_t status,
>   * Short term strategy:
>   *
>   * Make device_read/write multithreaded.
> - * Note: this would require an rwlock between device_open/close/read/write, 
> to
> - * protect against e.g. concurrent open, unexpected close while read/write is
> - * called, etc.
>   *
>   * Long term strategy:
>   *
> --
> 2.35.1
> 
> 
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]