• Bug#1105129: Please backport ntsync driver from Linux-6.14 to trixie (7

    From Piotr Morgwai Kotarbinski@1:229/2 to All on Sun May 11 22:50:01 2025
    [continued from previous message]

    + * obj->all_waiters is protected by dev->wait_all_lock rather
    + * than obj->lock, so there is no need to acquire obj->lock
    + * here.
    + */
    + list_add_tail(&entry->node, &obj->all_waiters);
    + }
    + if (args.alert) {
    + struct ntsync_q_entry *entry = &q->entries[args.count];
    + struct ntsync_obj *obj = entry->obj;
    +
    + dev_lock_obj(dev, obj);
    + list_add_tail(&entry->node, &obj->any_waiters);
    + dev_unlock_obj(dev, obj);
    + }
    +
    + /* check if we are already signaled */
    +
    + try_wake_all(dev, q, NULL);
    +
    + mutex_unlock(&dev->wait_all_lock);
    +
    + /*
    + * Check if the alert event is signaled, making sure to do so only
    + * after checking if the other objects are signaled.
    + */
    +
    + if (args.alert) {
    + struct ntsync_obj *obj = q->entries[args.count].obj;
    +
    + if (atomic_read(&q->signaled) == -1) {
    + bool all = ntsync_lock_obj(dev, obj);
    + try_wake_any_obj(obj);
    + ntsync_unlock_obj(dev, obj, all);
    + }
    + }
    +
    + /* sleep */
    +
    + ret = ntsync_schedule(q, &args);
    +
    + /* and finally, unqueue */
    +
    + mutex_lock(&dev->wait_all_lock);
    +
    + for (i = 0; i < args.count; i++) {
    + struct ntsync_q_entry *entry = &q->entries[i];
    + struct ntsync_obj *obj = entry->obj;
    +
    + /*
    + * obj->all_waiters is protected by dev->wait_all_lock rather
    + * than obj->lock, so there is no need to acquire it here.
    + */
    + list_del(&entry->node);
    +
    + atomic_dec(&obj->all_hint);
    +
    + put_obj(obj);
    + }
    +
    + mutex_unlock(&dev->wait_all_lock);
    +
    + if (args.alert) {
    + struct ntsync_q_entry *entry = &q->entries[args.count];
    + struct ntsync_obj *obj = entry->obj;
    + bool all;
    +
    + all = ntsync_lock_obj(dev, obj);
    + list_del(&entry->node);
    + ntsync_unlock_obj(dev, obj, all);
    +
    + put_obj(obj);
    + }
    +
    + signaled = atomic_read(&q->signaled);
    + if (signaled != -1) {
    + struct ntsync_wait_args __user *user_args = argp;
    +
    + /* even if we caught a signal, we need to communicate success */
    + ret = q->ownerdead ? -EOWNERDEAD : 0;
    +
    + if (put_user(signaled, &user_args->index))
    + ret = -EFAULT;
    + } else if (!ret) {
    + ret = -ETIMEDOUT;
    + }
    +
    + kfree(q);
    + return ret;
    }

    static int ntsync_char_open(struct inode *inode, struct file *file)
    @@ -198,6 +1158,8 @@ static int ntsync_char_open(struct inode
    if (!dev)
    return -ENOMEM;

    + mutex_init(&dev->wait_all_lock);
    +
    file->private_data = dev;
    dev->file = file;
    return nonseekable_open(inode, file);
    @@ -219,8 +1181,16 @@ static long ntsync_char_ioctl(struct fil
    void __user *argp = (void __user *)parm;

    switch (cmd) {
    + case NTSYNC_IOC_CREATE_EVENT:
    + return ntsync_create_event(dev, argp);
    + case NTSYNC_IOC_CREATE_MUTEX:
    + return ntsync_create_mutex(dev, argp);
    case NTSYNC_IOC_CREATE_SEM:
    return ntsync_create_sem(dev, argp);
    + case NTSYNC_IOC_WAIT_ALL:
    + return ntsync_wait_all(dev, argp);
    + case NTSYNC_IOC_WAIT_ANY:
    + return ntsync_wait_any(dev, argp);
    default:
    return -ENOIOCTLCMD;
    }
    @@ -238,6 +1208,7 @@ static struct miscdevice ntsync_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = NTSYNC_NAME,
    .fops = &ntsync_fops,
    + .mode = 0666,
    };

    module_misc_device(ntsync_misc);
    Index: linux-6.12.27/include/uapi/linux/ntsync.h ===================================================================
    --- linux-6.12.27.orig/include/uapi/linux/ntsync.h
    +++ linux-6.12.27/include/uapi/linux/ntsync.h
    @@ -11,13 +11,49 @@
    #include <linux/types.h>

    struct ntsync_sem_args {
    - __u32 sem;
    __u32 count;
    __u32 max;
    };

    -#define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args)
    +struct ntsync_mutex_args {
    + __u32 owner;
    + __u32 count;
    +};
    +
    +struct ntsync_event_args {
    + __u32 manual;
    + __u32 signaled;
    +};
    +
    +#define NTSYNC_WAIT_REALTIME 0x1
    +
    +struct ntsync_wait_args {
    + __u64 timeout;
    + __u64 objs;
    + __u32 count;
    + __u32 index;
    + __u32 flags;
    + __u32 owner;
    + __u32 alert;
    + __u32 pad;
    +};
    +
    +#define NTSYNC_MAX_WAIT_COUNT 64
    +
    +#define NTSYNC_IOC_CREATE_SEM _IOW ('N', 0x80, struct ntsync_sem_args)
    +#define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args)
    +#define NTSYNC_IOC_WAIT_ALL _IOWR('N', 0x83, struct ntsync_wait_args)
    +#define NTSYNC_IOC_CREATE_MUTEX _IOW ('N', 0x84, struct ntsync_mutex_args)
    +#define NTSYNC_IOC_CREATE_EVENT _IOW ('N',