[IB] uverbs: Add a mask of device methods allowed for userspace
[safe/jmp/linux-2.6] / drivers / infiniband / core / uverbs_main.c
index e7058fb..6a5e508 100644 (file)
@@ -312,8 +312,10 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
        }
 
        entry = kmalloc(sizeof *entry, GFP_ATOMIC);
-       if (!entry)
+       if (!entry) {
+               spin_unlock_irqrestore(&file->lock, flags);
                return;
+       }
 
        uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
 
@@ -343,8 +345,10 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
        }
 
        entry = kmalloc(sizeof *entry, GFP_ATOMIC);
-       if (!entry)
+       if (!entry) {
+               spin_unlock_irqrestore(&file->async_file->lock, flags);
                return;
+       }
 
        entry->desc.async.element    = element;
        entry->desc.async.event_type = event;
@@ -510,7 +514,8 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
 
        if (hdr.command < 0                             ||
            hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
-           !uverbs_cmd_table[hdr.command])
+           !uverbs_cmd_table[hdr.command]              ||
+           !(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
                return -EINVAL;
 
        if (!file->ucontext &&
@@ -598,6 +603,15 @@ static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 }
 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
 
+static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)
+{
+       struct ib_uverbs_device *dev =
+               container_of(class_dev, struct ib_uverbs_device, class_dev);
+
+       return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
+}
+static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
+
 static void ib_uverbs_release_class_dev(struct class_device *class_dev)
 {
        struct ib_uverbs_device *dev =
@@ -662,6 +676,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
 
        if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev))
                goto err_class;
+       if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_abi_version))
+               goto err_class;
 
        ib_set_client_data(device, &uverbs_client, uverbs_dev);