drivers/infiniband/core/uverbs_ioctl.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/core/uverbs_ioctl.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/core/uverbs_ioctl.c
Extension
.c
Size
18519 bytes
Lines
613
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (IS_ERR(attr->uobjects[i])) {
			ret = PTR_ERR(attr->uobjects[i]);
			break;
		}
	}

	attr->len = i;
	__set_bit(attr_bkey, pbundle->spec_finalize);
	return ret;
}

static void uverbs_free_idrs_array(const struct uverbs_api_attr *attr_uapi,
				   struct uverbs_objs_arr_attr *attr,
				   bool commit,
				   struct uverbs_attr_bundle *attrs)
{
	const struct uverbs_attr_spec *spec = &attr_uapi->spec;
	size_t i;

	for (i = 0; i != attr->len; i++)
		uverbs_finalize_object(attr->uobjects[i],
				       spec->u2.objs_arr.access, false, commit,
				       attrs);
}

static int uverbs_process_attr(struct bundle_priv *pbundle,
			       const struct uverbs_api_attr *attr_uapi,
			       struct ib_uverbs_attr *uattr, u32 attr_bkey)
{
	const struct uverbs_attr_spec *spec = &attr_uapi->spec;
	struct uverbs_attr_bundle *bundle =
		container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
	struct uverbs_attr *e = &bundle->attrs[attr_bkey];
	const struct uverbs_attr_spec *val_spec = spec;
	struct uverbs_obj_attr *o_attr;

	switch (spec->type) {
	case UVERBS_ATTR_TYPE_ENUM_IN:
		if (uattr->attr_data.enum_data.elem_id >= spec->u.enum_def.num_elems)
			return -EOPNOTSUPP;

		if (uattr->attr_data.enum_data.reserved)
			return -EINVAL;

		val_spec = &spec->u2.enum_def.ids[uattr->attr_data.enum_data.elem_id];

		/* Currently we only support PTR_IN based enums */
		if (val_spec->type != UVERBS_ATTR_TYPE_PTR_IN)
			return -EOPNOTSUPP;

		e->ptr_attr.enum_id = uattr->attr_data.enum_data.elem_id;
		fallthrough;
	case UVERBS_ATTR_TYPE_PTR_IN:
		/* Ensure that any data provided by userspace beyond the known
		 * struct is zero. Userspace that knows how to use some future
		 * longer struct will fail here if used with an old kernel and
		 * non-zero content, making ABI compat/discovery simpler.
		 */
		if (uattr->len > val_spec->u.ptr.len &&
		    val_spec->zero_trailing &&
		    !uverbs_is_attr_cleared(uattr, val_spec->u.ptr.len))
			return -EOPNOTSUPP;

		fallthrough;
	case UVERBS_ATTR_TYPE_PTR_OUT:
		if (uattr->len < val_spec->u.ptr.min_len ||
		    (!val_spec->zero_trailing &&
		     uattr->len > val_spec->u.ptr.len))
			return -EINVAL;

		if (spec->type != UVERBS_ATTR_TYPE_ENUM_IN &&
		    uattr->attr_data.reserved)
			return -EINVAL;

		e->ptr_attr.uattr_idx = uattr - pbundle->uattrs;
		e->ptr_attr.len = uattr->len;

		if (val_spec->alloc_and_copy && !uverbs_attr_ptr_is_inline(e)) {
			void *p;

			p = uverbs_alloc(bundle, uattr->len);
			if (IS_ERR(p))
				return PTR_ERR(p);

			e->ptr_attr.ptr = p;

			if (copy_from_user(p, u64_to_user_ptr(uattr->data),
					   uattr->len))
				return -EFAULT;
		} else {

Annotation

Implementation Notes