All of lore.kernel.org
 help / color / mirror / Atom feed
* io_uring/register.c:554:9: sparse: sparse: cast to non-scalar
@ 2025-01-24 12:38 kernel test robot
  0 siblings, 0 replies; only message in thread
From: kernel test robot @ 2025-01-24 12:38 UTC (permalink / raw)
  To: Jens Axboe; +Cc: oe-kbuild-all, linux-kernel

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
head:   bc8198dc7ebc492ec3e9fa1617dcdfbe98e73b17
commit: 2c5aae129f427f83eeba5efbfb4e60a777cd073c io_uring/register: document io_register_resize_rings() shared mem usage
date:   9 days ago
config: alpha-randconfig-r112-20250124 (https://download.01.org/0day-ci/archive/20250124/202501242000.A2sKqaCL-lkp@intel.com/config)
compiler: alpha-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250124/202501242000.A2sKqaCL-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501242000.A2sKqaCL-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   io_uring/register.c: note: in included file:
   include/linux/io_uring_types.h:190:37: sparse: sparse: array of flexible structures
>> io_uring/register.c:554:9: sparse: sparse: cast to non-scalar
>> io_uring/register.c:554:9: sparse: sparse: cast from non-scalar

vim +554 io_uring/register.c

   393	
   394	#define swap_old(ctx, o, n, field)		\
   395		do {					\
   396			(o).field = (ctx)->field;	\
   397			(ctx)->field = (n).field;	\
   398		} while (0)
   399	
   400	#define RESIZE_FLAGS	(IORING_SETUP_CQSIZE | IORING_SETUP_CLAMP)
   401	#define COPY_FLAGS	(IORING_SETUP_NO_SQARRAY | IORING_SETUP_SQE128 | \
   402				 IORING_SETUP_CQE32 | IORING_SETUP_NO_MMAP)
   403	
   404	static int io_register_resize_rings(struct io_ring_ctx *ctx, void __user *arg)
   405	{
   406		struct io_ring_ctx_rings o = { }, n = { }, *to_free = NULL;
   407		size_t size, sq_array_offset;
   408		struct io_uring_params p;
   409		unsigned i, tail;
   410		void *ptr;
   411		int ret;
   412	
   413		/* for single issuer, must be owner resizing */
   414		if (ctx->flags & IORING_SETUP_SINGLE_ISSUER &&
   415		    current != ctx->submitter_task)
   416			return -EEXIST;
   417		/* limited to DEFER_TASKRUN for now */
   418		if (!(ctx->flags & IORING_SETUP_DEFER_TASKRUN))
   419			return -EINVAL;
   420		if (copy_from_user(&p, arg, sizeof(p)))
   421			return -EFAULT;
   422		if (p.flags & ~RESIZE_FLAGS)
   423			return -EINVAL;
   424	
   425		/* properties that are always inherited */
   426		p.flags |= (ctx->flags & COPY_FLAGS);
   427	
   428		ret = io_uring_fill_params(p.sq_entries, &p);
   429		if (unlikely(ret))
   430			return ret;
   431	
   432		/* nothing to do, but copy params back */
   433		if (p.sq_entries == ctx->sq_entries && p.cq_entries == ctx->cq_entries) {
   434			if (copy_to_user(arg, &p, sizeof(p)))
   435				return -EFAULT;
   436			return 0;
   437		}
   438	
   439		size = rings_size(p.flags, p.sq_entries, p.cq_entries,
   440					&sq_array_offset);
   441		if (size == SIZE_MAX)
   442			return -EOVERFLOW;
   443	
   444		if (!(p.flags & IORING_SETUP_NO_MMAP))
   445			n.rings = io_pages_map(&n.ring_pages, &n.n_ring_pages, size);
   446		else
   447			n.rings = __io_uaddr_map(&n.ring_pages, &n.n_ring_pages,
   448							p.cq_off.user_addr, size);
   449		if (IS_ERR(n.rings))
   450			return PTR_ERR(n.rings);
   451	
   452		/*
   453		 * At this point n.rings is shared with userspace, just like o.rings
   454		 * is as well. While we don't expect userspace to modify it while
   455		 * a resize is in progress, and it's most likely that userspace will
   456		 * shoot itself in the foot if it does, we can't always assume good
   457		 * intent... Use read/write once helpers from here on to indicate the
   458		 * shared nature of it.
   459		 */
   460		WRITE_ONCE(n.rings->sq_ring_mask, p.sq_entries - 1);
   461		WRITE_ONCE(n.rings->cq_ring_mask, p.cq_entries - 1);
   462		WRITE_ONCE(n.rings->sq_ring_entries, p.sq_entries);
   463		WRITE_ONCE(n.rings->cq_ring_entries, p.cq_entries);
   464	
   465		if (copy_to_user(arg, &p, sizeof(p))) {
   466			io_register_free_rings(&p, &n);
   467			return -EFAULT;
   468		}
   469	
   470		if (p.flags & IORING_SETUP_SQE128)
   471			size = array_size(2 * sizeof(struct io_uring_sqe), p.sq_entries);
   472		else
   473			size = array_size(sizeof(struct io_uring_sqe), p.sq_entries);
   474		if (size == SIZE_MAX) {
   475			io_register_free_rings(&p, &n);
   476			return -EOVERFLOW;
   477		}
   478	
   479		if (!(p.flags & IORING_SETUP_NO_MMAP))
   480			ptr = io_pages_map(&n.sqe_pages, &n.n_sqe_pages, size);
   481		else
   482			ptr = __io_uaddr_map(&n.sqe_pages, &n.n_sqe_pages,
   483						p.sq_off.user_addr,
   484						size);
   485		if (IS_ERR(ptr)) {
   486			io_register_free_rings(&p, &n);
   487			return PTR_ERR(ptr);
   488		}
   489	
   490		/*
   491		 * If using SQPOLL, park the thread
   492		 */
   493		if (ctx->sq_data) {
   494			mutex_unlock(&ctx->uring_lock);
   495			io_sq_thread_park(ctx->sq_data);
   496			mutex_lock(&ctx->uring_lock);
   497		}
   498	
   499		/*
   500		 * We'll do the swap. Grab the ctx->resize_lock, which will exclude
   501		 * any new mmap's on the ring fd. Clear out existing mappings to prevent
   502		 * mmap from seeing them, as we'll unmap them. Any attempt to mmap
   503		 * existing rings beyond this point will fail. Not that it could proceed
   504		 * at this point anyway, as the io_uring mmap side needs go grab the
   505		 * ctx->resize_lock as well. Likewise, hold the completion lock over the
   506		 * duration of the actual swap.
   507		 */
   508		mutex_lock(&ctx->resize_lock);
   509		spin_lock(&ctx->completion_lock);
   510		o.rings = ctx->rings;
   511		ctx->rings = NULL;
   512		o.sq_sqes = ctx->sq_sqes;
   513		ctx->sq_sqes = NULL;
   514	
   515		/*
   516		 * Now copy SQ and CQ entries, if any. If either of the destination
   517		 * rings can't hold what is already there, then fail the operation.
   518		 */
   519		n.sq_sqes = ptr;
   520		tail = READ_ONCE(o.rings->sq.tail);
   521		if (tail - READ_ONCE(o.rings->sq.head) > p.sq_entries)
   522			goto overflow;
   523		for (i = READ_ONCE(o.rings->sq.head); i < tail; i++) {
   524			unsigned src_head = i & (ctx->sq_entries - 1);
   525			unsigned dst_head = i & (p.sq_entries - 1);
   526	
   527			n.sq_sqes[dst_head] = o.sq_sqes[src_head];
   528		}
   529		WRITE_ONCE(n.rings->sq.head, READ_ONCE(o.rings->sq.head));
   530		WRITE_ONCE(n.rings->sq.tail, READ_ONCE(o.rings->sq.tail));
   531	
   532		tail = READ_ONCE(o.rings->cq.tail);
   533		if (tail - READ_ONCE(o.rings->cq.head) > p.cq_entries) {
   534	overflow:
   535			/* restore old rings, and return -EOVERFLOW via cleanup path */
   536			ctx->rings = o.rings;
   537			ctx->sq_sqes = o.sq_sqes;
   538			to_free = &n;
   539			ret = -EOVERFLOW;
   540			goto out;
   541		}
   542		for (i = READ_ONCE(o.rings->cq.head); i < tail; i++) {
   543			unsigned src_head = i & (ctx->cq_entries - 1);
   544			unsigned dst_head = i & (p.cq_entries - 1);
   545	
   546			n.rings->cqes[dst_head] = o.rings->cqes[src_head];
   547		}
   548		WRITE_ONCE(n.rings->cq.head, READ_ONCE(o.rings->cq.head));
   549		WRITE_ONCE(n.rings->cq.tail, READ_ONCE(o.rings->cq.tail));
   550		/* invalidate cached cqe refill */
   551		ctx->cqe_cached = ctx->cqe_sentinel = NULL;
   552	
   553		WRITE_ONCE(n.rings->sq_dropped, READ_ONCE(o.rings->sq_dropped));
 > 554		WRITE_ONCE(n.rings->sq_flags, READ_ONCE(o.rings->sq_flags));
   555		WRITE_ONCE(n.rings->cq_flags, READ_ONCE(o.rings->cq_flags));
   556		WRITE_ONCE(n.rings->cq_overflow, READ_ONCE(o.rings->cq_overflow));
   557	
   558		/* all done, store old pointers and assign new ones */
   559		if (!(ctx->flags & IORING_SETUP_NO_SQARRAY))
   560			ctx->sq_array = (u32 *)((char *)n.rings + sq_array_offset);
   561	
   562		ctx->sq_entries = p.sq_entries;
   563		ctx->cq_entries = p.cq_entries;
   564	
   565		ctx->rings = n.rings;
   566		ctx->sq_sqes = n.sq_sqes;
   567		swap_old(ctx, o, n, n_ring_pages);
   568		swap_old(ctx, o, n, n_sqe_pages);
   569		swap_old(ctx, o, n, ring_pages);
   570		swap_old(ctx, o, n, sqe_pages);
   571		to_free = &o;
   572		ret = 0;
   573	out:
   574		spin_unlock(&ctx->completion_lock);
   575		mutex_unlock(&ctx->resize_lock);
   576		io_register_free_rings(&p, to_free);
   577	
   578		if (ctx->sq_data)
   579			io_sq_thread_unpark(ctx->sq_data);
   580	
   581		return ret;
   582	}
   583	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-01-24 12:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-24 12:38 io_uring/register.c:554:9: sparse: sparse: cast to non-scalar kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.