Skip to content

Commit

Permalink
RDMA/core: Make ib_uverbs_async_event_file into a uobject
Browse files Browse the repository at this point in the history
This makes async events aligned with completion events as both are full
uobjects of FD type and use the same uobject lifecycle.

A bunch of duplicate code is consolidated and the general flow between the
two FDs is now very similar.

Link: https://lore.kernel.org/r/1578504126-9400-14-git-send-email-yishaih@mellanox.com
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
  • Loading branch information
Jason Gunthorpe committed Jan 13, 2020
1 parent 39e83af commit 3e032c0
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 143 deletions.
3 changes: 2 additions & 1 deletion drivers/infiniband/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
uverbs_std_types_cq.o \
uverbs_std_types_flow_action.o uverbs_std_types_dm.o \
uverbs_std_types_mr.o uverbs_std_types_counters.o \
uverbs_uapi.o uverbs_std_types_device.o
uverbs_uapi.o uverbs_std_types_device.o \
uverbs_std_types_async_fd.o
ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o
1 change: 1 addition & 0 deletions drivers/infiniband/core/rdma_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
unsigned int num_attrs);
void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);

extern const struct uapi_definition uverbs_def_obj_async_fd[];
extern const struct uapi_definition uverbs_def_obj_counters[];
extern const struct uapi_definition uverbs_def_obj_cq[];
extern const struct uapi_definition uverbs_def_obj_device[];
Expand Down
15 changes: 6 additions & 9 deletions drivers/infiniband/core/uverbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ struct ib_uverbs_device {
struct srcu_struct disassociate_srcu;
struct mutex lists_mutex; /* protect lists */
struct list_head uverbs_file_list;
struct list_head uverbs_events_file_list;
struct uverbs_api *uapi;
};

Expand All @@ -124,10 +123,9 @@ struct ib_uverbs_event_queue {
};

struct ib_uverbs_async_event_file {
struct ib_uobject uobj;
struct ib_uverbs_event_queue ev_queue;
struct ib_uverbs_file *uverbs_file;
struct kref ref;
struct list_head list;
struct ib_event_handler event_handler;
};

struct ib_uverbs_completion_event_file {
Expand All @@ -144,8 +142,7 @@ struct ib_uverbs_file {
* ucontext_lock held
*/
struct ib_ucontext *ucontext;
struct ib_event_handler event_handler;
struct ib_uverbs_async_event_file *async_file;
struct ib_uverbs_async_event_file *async_file;
struct list_head list;

/*
Expand Down Expand Up @@ -217,10 +214,10 @@ struct ib_ucq_object {
};

extern const struct file_operations uverbs_event_fops;
extern const struct file_operations uverbs_async_event_fops;
void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue);
struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file,
struct ib_device *ib_dev);
void ib_uverbs_free_async_event_file(struct ib_uverbs_file *uverbs_file);
void ib_uverbs_init_async_event_file(struct ib_uverbs_async_event_file *ev_file);
void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue);
void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res);

void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
Expand Down
30 changes: 12 additions & 18 deletions drivers/infiniband/core/uverbs_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs)
struct ib_uverbs_get_context cmd;
struct ib_uverbs_get_context_resp resp;
struct ib_ucontext *ucontext;
struct file *filp;
struct ib_rdmacg_object cg_obj;
struct ib_device *ib_dev;
struct ib_uobject *uobj;
int ret;

ret = uverbs_request(attrs, &cmd, sizeof(cmd));
Expand Down Expand Up @@ -254,30 +254,28 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs)

xa_init_flags(&ucontext->mmap_xa, XA_FLAGS_ALLOC);

ret = get_unused_fd_flags(O_CLOEXEC);
if (ret < 0)
uobj = uobj_alloc(UVERBS_OBJECT_ASYNC_EVENT, attrs, &ib_dev);
if (IS_ERR(uobj)) {
ret = PTR_ERR(uobj);
goto err_free;
resp.async_fd = ret;

filp = ib_uverbs_alloc_async_event_file(file, ib_dev);
if (IS_ERR(filp)) {
ret = PTR_ERR(filp);
goto err_fd;
}

resp.async_fd = uobj->id;
resp.num_comp_vectors = file->device->num_comp_vectors;

ret = uverbs_response(attrs, &resp, sizeof(resp));
if (ret)
goto err_file;
goto err_uobj;

ret = ib_dev->ops.alloc_ucontext(ucontext, &attrs->driver_udata);
if (ret)
goto err_file;
goto err_uobj;

rdma_restrack_uadd(&ucontext->res);

fd_install(resp.async_fd, filp);
ib_uverbs_init_async_event_file(
container_of(uobj, struct ib_uverbs_async_event_file, uobj));
rdma_alloc_commit_uobject(uobj, attrs);

/*
* Make sure that ib_uverbs_get_ucontext() sees the pointer update
Expand All @@ -289,12 +287,8 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs)

return 0;

err_file:
ib_uverbs_free_async_event_file(file);
fput(filp);

err_fd:
put_unused_fd(resp.async_fd);
err_uobj:
rdma_alloc_abort_uobject(uobj, attrs);

err_free:
kfree(ucontext);
Expand Down
130 changes: 23 additions & 107 deletions drivers/infiniband/core/uverbs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,6 @@ static void ib_uverbs_release_dev(struct device *device)
kfree(dev);
}

static void ib_uverbs_release_async_event_file(struct kref *ref)
{
struct ib_uverbs_async_event_file *file =
container_of(ref, struct ib_uverbs_async_event_file, ref);

kfree(file);
}

void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
struct ib_uverbs_completion_event_file *ev_file,
struct ib_ucq_object *uobj)
Expand Down Expand Up @@ -203,8 +195,7 @@ void ib_uverbs_release_file(struct kref *ref)
ib_uverbs_comp_dev(file->device);

if (file->async_file)
kref_put(&file->async_file->ref,
ib_uverbs_release_async_event_file);
uverbs_uobject_put(&file->async_file->uobj);
put_device(&file->device->dev);

if (file->disassociate_page)
Expand Down Expand Up @@ -339,35 +330,6 @@ static int ib_uverbs_comp_event_fasync(int fd, struct file *filp, int on)
return fasync_helper(fd, filp, on, &comp_ev_file->ev_queue.async_queue);
}

static int ib_uverbs_async_event_close(struct inode *inode, struct file *filp)
{
struct ib_uverbs_async_event_file *file = filp->private_data;
struct ib_uverbs_file *uverbs_file = file->uverbs_file;
struct ib_uverbs_event *entry, *tmp;
int closed_already = 0;

mutex_lock(&uverbs_file->device->lists_mutex);
spin_lock_irq(&file->ev_queue.lock);
closed_already = file->ev_queue.is_closed;
file->ev_queue.is_closed = 1;
list_for_each_entry_safe(entry, tmp, &file->ev_queue.event_list, list) {
if (entry->counter)
list_del(&entry->obj_list);
kfree(entry);
}
spin_unlock_irq(&file->ev_queue.lock);
if (!closed_already) {
list_del(&file->list);
ib_unregister_event_handler(&uverbs_file->event_handler);
}
mutex_unlock(&uverbs_file->device->lists_mutex);

kref_put(&uverbs_file->ref, ib_uverbs_release_file);
kref_put(&file->ref, ib_uverbs_release_async_event_file);

return 0;
}

const struct file_operations uverbs_event_fops = {
.owner = THIS_MODULE,
.read = ib_uverbs_comp_event_read,
Expand All @@ -377,11 +339,11 @@ const struct file_operations uverbs_event_fops = {
.llseek = no_llseek,
};

static const struct file_operations uverbs_async_event_fops = {
const struct file_operations uverbs_async_event_fops = {
.owner = THIS_MODULE,
.read = ib_uverbs_async_event_read,
.poll = ib_uverbs_async_event_poll,
.release = ib_uverbs_async_event_close,
.release = uverbs_uobject_fd_release,
.fasync = ib_uverbs_async_event_fasync,
.llseek = no_llseek,
};
Expand Down Expand Up @@ -491,17 +453,11 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event)
{
ib_uverbs_async_handler(
container_of(handler, struct ib_uverbs_file, event_handler)
->async_file,
container_of(handler, struct ib_uverbs_async_event_file,
event_handler),
event->element.port_num, event->event, NULL, NULL);
}

void ib_uverbs_free_async_event_file(struct ib_uverbs_file *file)
{
kref_put(&file->async_file->ref, ib_uverbs_release_async_event_file);
file->async_file = NULL;
}

void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue)
{
spin_lock_init(&ev_queue->lock);
Expand All @@ -511,45 +467,23 @@ void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue)
ev_queue->async_queue = NULL;
}

struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file,
struct ib_device *ib_dev)
void ib_uverbs_init_async_event_file(
struct ib_uverbs_async_event_file *async_file)
{
struct ib_uverbs_async_event_file *ev_file;
struct file *filp;

ev_file = kzalloc(sizeof(*ev_file), GFP_KERNEL);
if (!ev_file)
return ERR_PTR(-ENOMEM);

ib_uverbs_init_event_queue(&ev_file->ev_queue);
ev_file->uverbs_file = uverbs_file;
kref_get(&ev_file->uverbs_file->ref);
kref_init(&ev_file->ref);
filp = anon_inode_getfile("[infinibandevent]", &uverbs_async_event_fops,
ev_file, O_RDONLY);
if (IS_ERR(filp))
goto err_put_refs;

mutex_lock(&uverbs_file->device->lists_mutex);
list_add_tail(&ev_file->list,
&uverbs_file->device->uverbs_events_file_list);
mutex_unlock(&uverbs_file->device->lists_mutex);

WARN_ON(uverbs_file->async_file);
uverbs_file->async_file = ev_file;
kref_get(&uverbs_file->async_file->ref);
INIT_IB_EVENT_HANDLER(&uverbs_file->event_handler,
ib_dev,
ib_uverbs_event_handler);
ib_register_event_handler(&uverbs_file->event_handler);
/* At that point async file stuff was fully set */
struct ib_uverbs_file *uverbs_file = async_file->uobj.ufile;
struct ib_device *ib_dev = async_file->uobj.context->device;

return filp;
ib_uverbs_init_event_queue(&async_file->ev_queue);

err_put_refs:
kref_put(&ev_file->uverbs_file->ref, ib_uverbs_release_file);
kref_put(&ev_file->ref, ib_uverbs_release_async_event_file);
return filp;
if (!WARN_ON(uverbs_file->async_file)) {
uverbs_file->async_file = async_file;
/* Pairs with the put in ib_uverbs_release_file */
uverbs_uobject_get(&async_file->uobj);
}

INIT_IB_EVENT_HANDLER(&async_file->event_handler, ib_dev,
ib_uverbs_event_handler);
ib_register_event_handler(&async_file->event_handler);
}

static ssize_t verify_hdr(struct ib_uverbs_cmd_hdr *hdr,
Expand Down Expand Up @@ -1178,7 +1112,6 @@ static void ib_uverbs_add_one(struct ib_device *device)
mutex_init(&uverbs_dev->xrcd_tree_mutex);
mutex_init(&uverbs_dev->lists_mutex);
INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list);
INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list);
rcu_assign_pointer(uverbs_dev->ib_dev, device);
uverbs_dev->num_comp_vectors = device->num_comp_vectors;

Expand Down Expand Up @@ -1223,7 +1156,6 @@ static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev,
struct ib_device *ib_dev)
{
struct ib_uverbs_file *file;
struct ib_uverbs_async_event_file *event_file;
struct ib_event event;

/* Pending running commands to terminate */
Expand All @@ -1246,31 +1178,15 @@ static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev,
*/
mutex_unlock(&uverbs_dev->lists_mutex);

ib_uverbs_event_handler(&file->event_handler, &event);
if (file->async_file)
ib_uverbs_event_handler(
&file->async_file->event_handler, &event);

uverbs_destroy_ufile_hw(file, RDMA_REMOVE_DRIVER_REMOVE);
kref_put(&file->ref, ib_uverbs_release_file);

mutex_lock(&uverbs_dev->lists_mutex);
}

while (!list_empty(&uverbs_dev->uverbs_events_file_list)) {
event_file = list_first_entry(&uverbs_dev->
uverbs_events_file_list,
struct ib_uverbs_async_event_file,
list);
spin_lock_irq(&event_file->ev_queue.lock);
event_file->ev_queue.is_closed = 1;
spin_unlock_irq(&event_file->ev_queue.lock);

list_del(&event_file->list);
ib_unregister_event_handler(
&event_file->uverbs_file->event_handler);
event_file->uverbs_file->event_handler.device =
NULL;

wake_up_interruptible(&event_file->ev_queue.poll_wait);
kill_fasync(&event_file->ev_queue.async_queue, SIGIO, POLL_IN);
}
mutex_unlock(&uverbs_dev->lists_mutex);

uverbs_disassociate_api(uverbs_dev->uapi);
Expand Down
25 changes: 17 additions & 8 deletions drivers/infiniband/core/uverbs_std_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,17 +202,15 @@ static int uverbs_free_pd(struct ib_uobject *uobject,
return 0;
}

static int
uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj,
enum rdma_remove_reason why)
void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue)
{
struct ib_uverbs_completion_event_file *file =
container_of(uobj, struct ib_uverbs_completion_event_file,
uobj);
struct ib_uverbs_event_queue *event_queue = &file->ev_queue;
struct ib_uverbs_event *entry, *tmp;

spin_lock_irq(&event_queue->lock);
/*
* The user must ensure that no new items are added to the event_list
* once is_closed is set.
*/
event_queue->is_closed = 1;
spin_unlock_irq(&event_queue->lock);
wake_up_interruptible(&event_queue->poll_wait);
Expand All @@ -225,8 +223,19 @@ uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj,
kfree(entry);
}
spin_unlock_irq(&event_queue->lock);
}

static int
uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj,
enum rdma_remove_reason why)
{
struct ib_uverbs_completion_event_file *file =
container_of(uobj, struct ib_uverbs_completion_event_file,
uobj);

ib_uverbs_free_event_queue(&file->ev_queue);
return 0;
};
}

int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs)
{
Expand Down
Loading

0 comments on commit 3e032c0

Please sign in to comment.