
static int __io_sqe_files_update(struct io_ring_ctx *ctx,
				 struct io_uring_rsrc_update *up,
				 unsigned nr_args)
{
	struct fixed_rsrc_data *data = ctx->file_data;
	struct fixed_rsrc_ref_node *ref_node;
	struct file *file, **file_slot;
	__s32 __user *fds;
	int fd, i, err;
	__u32 done;
	bool needs_switch = false;

	if (check_add_overflow(up->offset, nr_args, &done))
		return -EOVERFLOW;
	if (done > ctx->nr_user_files)
		return -EINVAL;

	ref_node = alloc_fixed_rsrc_ref_node(ctx);
	if (!ref_node)
		return -ENOMEM;
	init_fixed_file_ref_node(ctx, ref_node);

	fds = u64_to_user_ptr(up->data);
	for (done = 0; done < nr_args; done++) {
		err = 0;
		if (copy_from_user(&fd, &fds[done], sizeof(fd))) {
			err = -EFAULT;
			break;
		}
		if (fd == IORING_REGISTER_FILES_SKIP)
			continue;

		i = array_index_nospec(up->offset + done, ctx->nr_user_files);
		file_slot = io_fixed_file_slot(ctx->file_data, i);

		if (*file_slot) {
			err = io_queue_file_removal(data, *file_slot);
			if (err)
				break;
			*file_slot = NULL;
			needs_switch = true;
		}
		if (fd != -1) {
			file = fget(fd);
			if (!file) {
				err = -EBADF;
				break;
			}
			/*
			 * Don't allow io_uring instances to be registered. If
			 * UNIX isn't enabled, then this causes a reference
			 * cycle and this instance can never get freed. If UNIX
			 * is enabled we'll handle it just fine, but there's
			 * still no point in allowing a ring fd as it doesn't
			 * support regular read/write anyway.
			 */
			if (file->f_op == &io_uring_fops) {
				fput(file);
				err = -EBADF;
				break;
			}
			*file_slot = file;
			err = io_sqe_file_register(ctx, file, i);
			if (err) {
				*file_slot = NULL;
				fput(file);
				break;
			}
		}
	}

	if (needs_switch) {
		percpu_ref_kill(&data->node->refs);
		io_sqe_rsrc_set_node(ctx, data, ref_node);
	} else
		destroy_fixed_rsrc_ref_node(ref_node);

	return done ? done : err;

static int __io_sqe_files_update(struct io_ring_ctx *ctx,
				 struct io_uring_rsrc_update *up,
				 unsigned nr_args)
{
	struct fixed_rsrc_data *data = ctx->file_data;
	struct fixed_rsrc_ref_node *ref_node;
	struct file *file, **file_slot;
	__s32 __user *fds;
	int fd, i, err;
	__u32 done;
	bool needs_switch = false;

	if (check_add_overflow(up->offset, nr_args, &done))
		return -EOVERFLOW;
	if (done > ctx->nr_user_files)
		return -EINVAL;

	ref_node = alloc_fixed_rsrc_ref_node(ctx);
	if (!ref_node)
		return -ENOMEM;
	init_fixed_file_ref_node(ctx, ref_node);

	fds = u64_to_user_ptr(up->data);
	for (done = 0; done < nr_args; done++) {
		err = 0;
		if (copy_from_user(&fd, &fds[done], sizeof(fd))) {
			err = -EFAULT;
			break;
		}
		if (fd == IORING_REGISTER_FILES_SKIP)
			continue;

		i = array_index_nospec(up->offset + done, ctx->nr_user_files);
		file_slot = io_fixed_file_slot(ctx->file_data, i);

		if (*file_slot) {
			err = io_queue_file_removal(data, *file_slot);
			if (err)
				break;
			*file_slot = NULL;
			needs_switch = true;
		}
		if (fd != -1) {
			file = fget(fd);
			if (!file) {
				err = -EBADF;
				break;
			}
			 
			if (file->f_op == &io_uring_fops) {
				fput(file);
				err = -EBADF;
				break;
			}
			*file_slot = file;
			err = io_sqe_file_register(ctx, file, i);
			if (err) {
				*file_slot = NULL;
				fput(file);
				break;
			}
		}
	}

	if (needs_switch) {
		percpu_ref_kill(&data->node->refs);
		io_sqe_rsrc_set_node(ctx, data, ref_node);
	} else
		destroy_fixed_rsrc_ref_node(ref_node);

	return done ? done : err;