On 10/21/24 10:28 AM, Pavel Begunkov wrote: > On 10/21/24 16:35, Jens Axboe wrote: >> On 10/16/24 12:52 PM, David Wei wrote: >>> +static int io_zcrx_create_area(struct io_ring_ctx *ctx, >>> + struct io_zcrx_ifq *ifq, >>> + struct io_zcrx_area **res, >>> + struct io_uring_zcrx_area_reg *area_reg) >>> +{ >>> + struct io_zcrx_area *area; >>> + int i, ret, nr_pages; >>> + struct iovec iov; >>> + >>> + if (area_reg->flags || area_reg->rq_area_token) >>> + return -EINVAL; >>> + if (area_reg->__resv1 || area_reg->__resv2[0] || area_reg->__resv2[1]) >>> + return -EINVAL; >>> + if (area_reg->addr & ~PAGE_MASK || area_reg->len & ~PAGE_MASK) >>> + return -EINVAL; >>> + >>> + iov.iov_base = u64_to_user_ptr(area_reg->addr); >>> + iov.iov_len = area_reg->len; >>> + ret = io_buffer_validate(&iov); >>> + if (ret) >>> + return ret; >>> + >>> + ret = -ENOMEM; >>> + area = kzalloc(sizeof(*area), GFP_KERNEL); >>> + if (!area) >>> + goto err; >>> + >>> + area->pages = io_pin_pages((unsigned long)area_reg->addr, area_reg->len, >>> + &nr_pages); >>> + if (IS_ERR(area->pages)) { >>> + ret = PTR_ERR(area->pages); >>> + area->pages = NULL; >>> + goto err; >>> + } >>> + area->nia.num_niovs = nr_pages; >>> + >>> + area->nia.niovs = kvmalloc_array(nr_pages, sizeof(area->nia.niovs[0]), >>> + GFP_KERNEL | __GFP_ZERO); >>> + if (!area->nia.niovs) >>> + goto err; >>> + >>> + area->freelist = kvmalloc_array(nr_pages, sizeof(area->freelist[0]), >>> + GFP_KERNEL | __GFP_ZERO); >>> + if (!area->freelist) >>> + goto err; >>> + >>> + for (i = 0; i < nr_pages; i++) { >>> + area->freelist[i] = i; >>> + } >>> + >>> + area->free_count = nr_pages; >>> + area->ifq = ifq; >>> + /* we're only supporting one area per ifq for now */ >>> + area->area_id = 0; >>> + area_reg->rq_area_token = (u64)area->area_id << IORING_ZCRX_AREA_SHIFT; >>> + spin_lock_init(&area->freelist_lock); >>> + *res = area; >>> + return 0; >>> +err: >>> + if (area) >>> + io_zcrx_free_area(area); >>> + return ret; >>> +} >> >> Minor nit, but I think this would be nicer returning area and just using >> ERR_PTR() for the errors. > > I'd rather avoid it. Too often null vs IS_ERR checking gets > messed up down the road and the compiler doesn't help with it > at all. The main issue imho is when people mix NULL and ERR_PTR, the pure "valid pointer or non-null error pointer" seem to be OK in terms of maintainability. But like I said, not a huge deal, and it's not hot path material so doesn't matter in terms of that. > Not related to the patch, but would be nice to have a type safer > way for that, e.g. returning some new type not directly > cast'able to the pointer. Definitely, room for improvement in the infrastructure for this. -- Jens Axboe