Skip to content

Commit

Permalink
vdpa: Enable user to query vdpa device info
Browse files Browse the repository at this point in the history
Enable user to query vdpa device information.

$ vdpa dev add mgmtdev vdpasim_net name foo2

Show the newly created vdpa device by its name:
$ vdpa dev show foo2
foo2: type network mgmtdev vdpasim_net vendor_id 0 max_vqs 2 max_vq_size 256

$ vdpa dev show foo2 -jp
{
    "dev": {
        "foo2": {
            "type": "network",
            "mgmtdev": "vdpasim_net",
            "vendor_id": 0,
            "max_vqs": 2,
            "max_vq_size": 256
        }
    }
}

Signed-off-by: Parav Pandit <[email protected]>
Reviewed-by: Eli Cohen <[email protected]>
Reviewed-by: Jason Wang <[email protected]>
Link: https://lore.kernel.org/r/[email protected]

Including a memory leak fix:

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Michael S. Tsirkin <[email protected]>
  • Loading branch information
paravmellanox authored and mstsirkin committed Feb 23, 2021
1 parent 903f7bc commit bc0d90e
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 0 deletions.
131 changes: 131 additions & 0 deletions drivers/vdpa/vdpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,131 @@ static int vdpa_nl_cmd_dev_del_set_doit(struct sk_buff *skb, struct genl_info *i
return err;
}

static int
vdpa_dev_fill(struct vdpa_device *vdev, struct sk_buff *msg, u32 portid, u32 seq,
int flags, struct netlink_ext_ack *extack)
{
u16 max_vq_size;
u32 device_id;
u32 vendor_id;
void *hdr;
int err;

hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, VDPA_CMD_DEV_NEW);
if (!hdr)
return -EMSGSIZE;

err = vdpa_nl_mgmtdev_handle_fill(msg, vdev->mdev);
if (err)
goto msg_err;

device_id = vdev->config->get_device_id(vdev);
vendor_id = vdev->config->get_vendor_id(vdev);
max_vq_size = vdev->config->get_vq_num_max(vdev);

err = -EMSGSIZE;
if (nla_put_string(msg, VDPA_ATTR_DEV_NAME, dev_name(&vdev->dev)))
goto msg_err;
if (nla_put_u32(msg, VDPA_ATTR_DEV_ID, device_id))
goto msg_err;
if (nla_put_u32(msg, VDPA_ATTR_DEV_VENDOR_ID, vendor_id))
goto msg_err;
if (nla_put_u32(msg, VDPA_ATTR_DEV_MAX_VQS, vdev->nvqs))
goto msg_err;
if (nla_put_u16(msg, VDPA_ATTR_DEV_MAX_VQ_SIZE, max_vq_size))
goto msg_err;

genlmsg_end(msg, hdr);
return 0;

msg_err:
genlmsg_cancel(msg, hdr);
return err;
}

static int vdpa_nl_cmd_dev_get_doit(struct sk_buff *skb, struct genl_info *info)
{
struct vdpa_device *vdev;
struct sk_buff *msg;
const char *devname;
struct device *dev;
int err;

if (!info->attrs[VDPA_ATTR_DEV_NAME])
return -EINVAL;
devname = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]);
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return -ENOMEM;

mutex_lock(&vdpa_dev_mutex);
dev = bus_find_device(&vdpa_bus, NULL, devname, vdpa_name_match);
if (!dev) {
NL_SET_ERR_MSG_MOD(info->extack, "device not found");
err = -ENODEV;
goto err;
}
vdev = container_of(dev, struct vdpa_device, dev);
if (!vdev->mdev) {
err = -EINVAL;
goto mdev_err;
}
err = vdpa_dev_fill(vdev, msg, info->snd_portid, info->snd_seq, 0, info->extack);
if (!err)
err = genlmsg_reply(msg, info);
mdev_err:
put_device(dev);
err:
mutex_unlock(&vdpa_dev_mutex);
if (err)
nlmsg_free(msg);
return err;
}

struct vdpa_dev_dump_info {
struct sk_buff *msg;
struct netlink_callback *cb;
int start_idx;
int idx;
};

static int vdpa_dev_dump(struct device *dev, void *data)
{
struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev);
struct vdpa_dev_dump_info *info = data;
int err;

if (!vdev->mdev)
return 0;
if (info->idx < info->start_idx) {
info->idx++;
return 0;
}
err = vdpa_dev_fill(vdev, info->msg, NETLINK_CB(info->cb->skb).portid,
info->cb->nlh->nlmsg_seq, NLM_F_MULTI, info->cb->extack);
if (err)
return err;

info->idx++;
return 0;
}

static int vdpa_nl_cmd_dev_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb)
{
struct vdpa_dev_dump_info info;

info.msg = msg;
info.cb = cb;
info.start_idx = cb->args[0];
info.idx = 0;

mutex_lock(&vdpa_dev_mutex);
bus_for_each_dev(&vdpa_bus, NULL, &info, vdpa_dev_dump);
mutex_unlock(&vdpa_dev_mutex);
cb->args[0] = info.idx;
return msg->len;
}

static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
[VDPA_ATTR_MGMTDEV_BUS_NAME] = { .type = NLA_NUL_STRING },
[VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING },
Expand All @@ -503,6 +628,12 @@ static const struct genl_ops vdpa_nl_ops[] = {
.doit = vdpa_nl_cmd_dev_del_set_doit,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = VDPA_CMD_DEV_GET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = vdpa_nl_cmd_dev_get_doit,
.dumpit = vdpa_nl_cmd_dev_get_dumpit,
},
};

static struct genl_family vdpa_nl_family __ro_after_init = {
Expand Down
5 changes: 5 additions & 0 deletions include/uapi/linux/vdpa.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum vdpa_command {
VDPA_CMD_MGMTDEV_GET, /* can dump */
VDPA_CMD_DEV_NEW,
VDPA_CMD_DEV_DEL,
VDPA_CMD_DEV_GET, /* can dump */
};

enum vdpa_attr {
Expand All @@ -27,6 +28,10 @@ enum vdpa_attr {
VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, /* u64 */

VDPA_ATTR_DEV_NAME, /* string */
VDPA_ATTR_DEV_ID, /* u32 */
VDPA_ATTR_DEV_VENDOR_ID, /* u32 */
VDPA_ATTR_DEV_MAX_VQS, /* u32 */
VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */

/* new attributes must be added above here */
VDPA_ATTR_MAX,
Expand Down

0 comments on commit bc0d90e

Please sign in to comment.