[RFC,8/9] ntsync: Introduce NTSYNC_IOC_PUT_MUTEX.
Commit Message
This corresponds to the NT syscall NtReleaseMutant().
Signed-off-by: Elizabeth Figura <zfigura@codeweavers.com>
---
drivers/misc/ntsync.c | 67 +++++++++++++++++++++++++++++++++++++
include/uapi/linux/ntsync.h | 2 ++
2 files changed, 69 insertions(+)
Comments
On Wed, Jan 24, 2024, at 01:40, Elizabeth Figura wrote:
> @@ -738,6 +803,8 @@ static long ntsync_char_ioctl(struct file *file,
> diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h
> index 26d1b3d4847f..2e44e7e77776 100644
> --- a/include/uapi/linux/ntsync.h
> +++ b/include/uapi/linux/ntsync.h
> @@ -46,5 +46,7 @@ struct ntsync_wait_args {
> struct ntsync_wait_args)
> #define NTSYNC_IOC_CREATE_MUTEX _IOWR(NTSYNC_IOC_BASE, 5, \
> struct ntsync_mutex_args)
> +#define NTSYNC_IOC_PUT_MUTEX _IOWR(NTSYNC_IOC_BASE, 6, \
> + struct ntsync_mutex_args)
>
In your implementation, this argument is not written back to
user space, so I think this should be _IOW rather than than _IORW.
Again, no practical difference here.
Arnd
On Wednesday, 24 January 2024 01:42:19 CST Arnd Bergmann wrote:
> On Wed, Jan 24, 2024, at 01:40, Elizabeth Figura wrote:
> > @@ -738,6 +803,8 @@ static long ntsync_char_ioctl(struct file *file,
> > diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h
> > index 26d1b3d4847f..2e44e7e77776 100644
> > --- a/include/uapi/linux/ntsync.h
> > +++ b/include/uapi/linux/ntsync.h
> > @@ -46,5 +46,7 @@ struct ntsync_wait_args {
> > struct ntsync_wait_args)
> > #define NTSYNC_IOC_CREATE_MUTEX _IOWR(NTSYNC_IOC_BASE, 5, \
> > struct ntsync_mutex_args)
> > +#define NTSYNC_IOC_PUT_MUTEX _IOWR(NTSYNC_IOC_BASE, 6, \
> > + struct ntsync_mutex_args)
> >
>
> In your implementation, this argument is not written back to
> user space, so I think this should be _IOW rather than than _IORW.
>
> Again, no practical difference here.
Hm, but there is a put_user() at the end of the function, or am I missing something?
On Wed, Jan 24, 2024, at 19:03, Elizabeth Figura wrote:
> On Wednesday, 24 January 2024 01:42:19 CST Arnd Bergmann wrote:
>> On Wed, Jan 24, 2024, at 01:40, Elizabeth Figura wrote:
>> > @@ -738,6 +803,8 @@ static long ntsync_char_ioctl(struct file *file,
>> > diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h
>> > index 26d1b3d4847f..2e44e7e77776 100644
>> > --- a/include/uapi/linux/ntsync.h
>> > +++ b/include/uapi/linux/ntsync.h
>> > @@ -46,5 +46,7 @@ struct ntsync_wait_args {
>> > struct ntsync_wait_args)
>> > #define NTSYNC_IOC_CREATE_MUTEX _IOWR(NTSYNC_IOC_BASE, 5, \
>> > struct ntsync_mutex_args)
>> > +#define NTSYNC_IOC_PUT_MUTEX _IOWR(NTSYNC_IOC_BASE, 6, \
>> > + struct ntsync_mutex_args)
>> >
>>
>> In your implementation, this argument is not written back to
>> user space, so I think this should be _IOW rather than than _IORW.
>>
>> Again, no practical difference here.
>
> Hm, but there is a put_user() at the end of the function, or am I
> missing something?
No, I was just looking at the wrong thing, your version is good.
Arnd
@@ -449,6 +449,71 @@ static int ntsync_put_sem(struct ntsync_device *dev, void __user *argp)
return ret;
}
+/*
+ * Actually change the mutex state, returning -EPERM if not the owner.
+ */
+static int put_mutex_state(struct ntsync_obj *mutex,
+ const struct ntsync_mutex_args *args)
+{
+ lockdep_assert_held(&mutex->lock);
+
+ if (mutex->u.mutex.owner != args->owner)
+ return -EPERM;
+
+ if (!--mutex->u.mutex.count)
+ mutex->u.mutex.owner = 0;
+ return 0;
+}
+
+static int ntsync_put_mutex(struct ntsync_device *dev, void __user *argp)
+{
+ struct ntsync_mutex_args __user *user_args = argp;
+ struct ntsync_mutex_args args;
+ struct ntsync_obj *mutex;
+ __u32 prev_count;
+ int ret;
+
+ if (copy_from_user(&args, argp, sizeof(args)))
+ return -EFAULT;
+ if (!args.owner)
+ return -EINVAL;
+
+ mutex = get_obj_typed(dev, args.mutex, NTSYNC_TYPE_MUTEX);
+ if (!mutex)
+ return -EINVAL;
+
+ if (atomic_read(&mutex->all_hint) > 0) {
+ spin_lock(&dev->wait_all_lock);
+ spin_lock_nest_lock(&mutex->lock, &dev->wait_all_lock);
+
+ prev_count = mutex->u.mutex.count;
+ ret = put_mutex_state(mutex, &args);
+ if (!ret) {
+ try_wake_all_obj(dev, mutex);
+ try_wake_any_mutex(mutex);
+ }
+
+ spin_unlock(&mutex->lock);
+ spin_unlock(&dev->wait_all_lock);
+ } else {
+ spin_lock(&mutex->lock);
+
+ prev_count = mutex->u.mutex.count;
+ ret = put_mutex_state(mutex, &args);
+ if (!ret)
+ try_wake_any_mutex(mutex);
+
+ spin_unlock(&mutex->lock);
+ }
+
+ put_obj(mutex);
+
+ if (!ret && put_user(prev_count, &user_args->count))
+ ret = -EFAULT;
+
+ return ret;
+}
+
static int ntsync_schedule(const struct ntsync_q *q, ktime_t *timeout)
{
int ret = 0;
@@ -738,6 +803,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd,
return ntsync_create_sem(dev, argp);
case NTSYNC_IOC_DELETE:
return ntsync_delete(dev, argp);
+ case NTSYNC_IOC_PUT_MUTEX:
+ return ntsync_put_mutex(dev, argp);
case NTSYNC_IOC_PUT_SEM:
return ntsync_put_sem(dev, argp);
case NTSYNC_IOC_WAIT_ALL:
@@ -46,5 +46,7 @@ struct ntsync_wait_args {
struct ntsync_wait_args)
#define NTSYNC_IOC_CREATE_MUTEX _IOWR(NTSYNC_IOC_BASE, 5, \
struct ntsync_mutex_args)
+#define NTSYNC_IOC_PUT_MUTEX _IOWR(NTSYNC_IOC_BASE, 6, \
+ struct ntsync_mutex_args)
#endif