X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Finfiniband%2Fcore%2Fuverbs_main.c;h=eb36a81dd09bff2d544675de4c37c447614d3262;hb=132380a06b24704fd6c9be55c44d4ef3972cead2;hp=5ec2d49e9bb6ebae15bd88da1206e94d7f6eb860;hpb=9ead190bfde2a434c74ea604382d08acb2eceef5;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 5ec2d49..eb36a81 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -32,8 +32,6 @@ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. - * - * $Id: uverbs_main.c 2733 2005-06-28 19:14:34Z roland $ */ #include @@ -122,7 +120,15 @@ static void ib_uverbs_release_dev(struct kref *ref) struct ib_uverbs_device *dev = container_of(ref, struct ib_uverbs_device, ref); - kfree(dev); + complete(&dev->comp); +} + +static void ib_uverbs_release_event_file(struct kref *ref) +{ + struct ib_uverbs_event_file *file = + container_of(ref, struct ib_uverbs_event_file, ref); + + kfree(file); } void ib_uverbs_release_ucq(struct ib_uverbs_file *file, @@ -183,12 +189,13 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, if (!context) return 0; + context->closing = 1; + list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { struct ib_ah *ah = uobj->object; idr_remove_uobj(&ib_uverbs_ah_idr, uobj); ib_destroy_ah(ah); - list_del(&uobj->list); kfree(uobj); } @@ -200,7 +207,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, idr_remove_uobj(&ib_uverbs_qp_idr, uobj); ib_uverbs_detach_umcast(qp, uqp); ib_destroy_qp(qp); - list_del(&uobj->list); ib_uverbs_release_uevent(file, &uqp->uevent); kfree(uqp); } @@ -213,7 +219,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, idr_remove_uobj(&ib_uverbs_cq_idr, uobj); ib_destroy_cq(cq); - list_del(&uobj->list); ib_uverbs_release_ucq(file, ev_file, ucq); kfree(ucq); } @@ -225,7 +230,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, idr_remove_uobj(&ib_uverbs_srq_idr, uobj); ib_destroy_srq(srq); - list_del(&uobj->list); ib_uverbs_release_uevent(file, uevent); kfree(uevent); } @@ -234,17 +238,10 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { struct ib_mr *mr = uobj->object; - struct ib_device *mrdev = mr->device; - struct ib_umem_object *memobj; idr_remove_uobj(&ib_uverbs_mr_idr, uobj); ib_dereg_mr(mr); - - memobj = container_of(uobj, struct ib_umem_object, uobject); - ib_umem_release_on_close(mrdev, &memobj->umem); - - list_del(&uobj->list); - kfree(memobj); + kfree(uobj); } list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) { @@ -252,7 +249,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, idr_remove_uobj(&ib_uverbs_pd_idr, uobj); ib_dealloc_pd(pd); - list_del(&uobj->list); kfree(uobj); } @@ -341,14 +337,6 @@ static unsigned int ib_uverbs_event_poll(struct file *filp, return pollflags; } -void ib_uverbs_release_event_file(struct kref *ref) -{ - struct ib_uverbs_event_file *file = - container_of(ref, struct ib_uverbs_event_file, ref); - - kfree(file); -} - static int ib_uverbs_event_fasync(int fd, struct file *filp, int on) { struct ib_uverbs_event_file *file = filp->private_data; @@ -362,7 +350,7 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp) struct ib_uverbs_event *entry, *tmp; spin_lock_irq(&file->lock); - file->file = NULL; + file->is_closed = 1; list_for_each_entry_safe(entry, tmp, &file->event_list, list) { if (entry->counter) list_del(&entry->obj_list); @@ -370,8 +358,6 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp) } spin_unlock_irq(&file->lock); - ib_uverbs_event_fasync(-1, filp, 0); - if (file->is_async) { ib_unregister_event_handler(&file->uverbs_file->event_handler); kref_put(&file->uverbs_file->ref, ib_uverbs_release_file); @@ -381,7 +367,7 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp) return 0; } -static struct file_operations uverbs_event_fops = { +static const struct file_operations uverbs_event_fops = { .owner = THIS_MODULE, .read = ib_uverbs_event_read, .poll = ib_uverbs_event_poll, @@ -400,7 +386,7 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context) return; spin_lock_irqsave(&file->lock, flags); - if (!file->file) { + if (file->is_closed) { spin_unlock_irqrestore(&file->lock, flags); return; } @@ -433,7 +419,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file, unsigned long flags; spin_lock_irqsave(&file->async_file->lock, flags); - if (!file->async_file->file) { + if (file->async_file->is_closed) { spin_unlock_irqrestore(&file->async_file->lock, flags); return; } @@ -519,6 +505,7 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, ev_file->uverbs_file = uverbs_file; ev_file->async_queue = NULL; ev_file->is_async = is_async; + ev_file->is_closed = 0; *fd = get_unused_fd(); if (*fd < 0) { @@ -526,25 +513,18 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, goto err; } - filp = get_empty_filp(); - if (!filp) { - ret = -ENFILE; - goto err_fd; - } - - ev_file->file = filp; - /* * fops_get() can't fail here, because we're coming from a * system call on a uverbs file, which will already have a * module reference. */ - filp->f_op = fops_get(&uverbs_event_fops); - filp->f_vfsmnt = mntget(uverbs_event_mnt); - filp->f_dentry = dget(uverbs_event_mnt->mnt_root); - filp->f_mapping = filp->f_dentry->d_inode->i_mapping; - filp->f_flags = O_RDONLY; - filp->f_mode = FMODE_READ; + filp = alloc_file(uverbs_event_mnt, dget(uverbs_event_mnt->mnt_root), + FMODE_READ, fops_get(&uverbs_event_fops)); + if (!filp) { + ret = -ENFILE; + goto err_fd; + } + filp->private_data = ev_file; return filp; @@ -626,6 +606,18 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) return file->device->ib_dev->mmap(file->ucontext, vma); } +/* + * ib_uverbs_open() does not need the BKL: + * + * - dev_table[] accesses are protected by map_lock, the + * ib_uverbs_device structures are properly reference counted, and + * everything else is purely local to the file being created, so + * races against other open calls are not a problem; + * - there is no ioctl method to race against; + * - the device is added to dev_table[] as the last part of module + * initialization, the open method will either immediately run + * -ENXIO, or all required initialization will be done. + */ static int ib_uverbs_open(struct inode *inode, struct file *filp) { struct ib_uverbs_device *dev; @@ -667,7 +659,6 @@ err_module: err: kref_put(&dev->ref, ib_uverbs_release_dev); - return ret; } @@ -685,14 +676,14 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp) return 0; } -static struct file_operations uverbs_fops = { +static const struct file_operations uverbs_fops = { .owner = THIS_MODULE, .write = ib_uverbs_write, .open = ib_uverbs_open, .release = ib_uverbs_close }; -static struct file_operations uverbs_mmap_fops = { +static const struct file_operations uverbs_mmap_fops = { .owner = THIS_MODULE, .write = ib_uverbs_write, .mmap = ib_uverbs_mmap, @@ -706,27 +697,29 @@ static struct ib_client uverbs_client = { .remove = ib_uverbs_remove_one }; -static ssize_t show_ibdev(struct class_device *class_dev, char *buf) +static ssize_t show_ibdev(struct device *device, struct device_attribute *attr, + char *buf) { - struct ib_uverbs_device *dev = class_get_devdata(class_dev); + struct ib_uverbs_device *dev = dev_get_drvdata(device); if (!dev) return -ENODEV; return sprintf(buf, "%s\n", dev->ib_dev->name); } -static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); +static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); -static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf) +static ssize_t show_dev_abi_version(struct device *device, + struct device_attribute *attr, char *buf) { - struct ib_uverbs_device *dev = class_get_devdata(class_dev); + struct ib_uverbs_device *dev = dev_get_drvdata(device); if (!dev) return -ENODEV; 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 DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL); static ssize_t show_abi_version(struct class *class, char *buf) { @@ -746,6 +739,7 @@ static void ib_uverbs_add_one(struct ib_device *device) return; kref_init(&uverbs_dev->ref); + init_completion(&uverbs_dev->comp); spin_lock(&map_lock); uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); @@ -757,29 +751,26 @@ static void ib_uverbs_add_one(struct ib_device *device) spin_unlock(&map_lock); uverbs_dev->ib_dev = device; - uverbs_dev->num_comp_vectors = 1; + uverbs_dev->num_comp_vectors = device->num_comp_vectors; - uverbs_dev->dev = cdev_alloc(); - if (!uverbs_dev->dev) + uverbs_dev->cdev = cdev_alloc(); + if (!uverbs_dev->cdev) goto err; - uverbs_dev->dev->owner = THIS_MODULE; - uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops; - kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum); - if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1)) + uverbs_dev->cdev->owner = THIS_MODULE; + uverbs_dev->cdev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops; + kobject_set_name(&uverbs_dev->cdev->kobj, "uverbs%d", uverbs_dev->devnum); + if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1)) goto err_cdev; - uverbs_dev->class_dev = class_device_create(uverbs_class, NULL, - uverbs_dev->dev->dev, - device->dma_device, - "uverbs%d", uverbs_dev->devnum); - if (IS_ERR(uverbs_dev->class_dev)) + uverbs_dev->dev = device_create(uverbs_class, device->dma_device, + uverbs_dev->cdev->dev, uverbs_dev, + "uverbs%d", uverbs_dev->devnum); + if (IS_ERR(uverbs_dev->dev)) goto err_cdev; - class_set_devdata(uverbs_dev->class_dev, uverbs_dev); - - if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev)) + if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev)) goto err_class; - if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version)) + if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version)) goto err_class; spin_lock(&map_lock); @@ -791,14 +782,16 @@ static void ib_uverbs_add_one(struct ib_device *device) return; err_class: - class_device_destroy(uverbs_class, uverbs_dev->dev->dev); + device_destroy(uverbs_class, uverbs_dev->cdev->dev); err_cdev: - cdev_del(uverbs_dev->dev); + cdev_del(uverbs_dev->cdev); clear_bit(uverbs_dev->devnum, dev_map); err: kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); + wait_for_completion(&uverbs_dev->comp); + kfree(uverbs_dev); return; } @@ -809,23 +802,27 @@ static void ib_uverbs_remove_one(struct ib_device *device) if (!uverbs_dev) return; - class_set_devdata(uverbs_dev->class_dev, NULL); - class_device_destroy(uverbs_class, uverbs_dev->dev->dev); - cdev_del(uverbs_dev->dev); + dev_set_drvdata(uverbs_dev->dev, NULL); + device_destroy(uverbs_class, uverbs_dev->cdev->dev); + cdev_del(uverbs_dev->cdev); spin_lock(&map_lock); dev_table[uverbs_dev->devnum] = NULL; spin_unlock(&map_lock); clear_bit(uverbs_dev->devnum, dev_map); + kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); + wait_for_completion(&uverbs_dev->comp); + kfree(uverbs_dev); } -static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) { return get_sb_pseudo(fs_type, "infinibandevent:", NULL, - INFINIBANDEVENTFS_MAGIC); + INFINIBANDEVENTFS_MAGIC, mnt); } static struct file_system_type uverbs_event_fs = { @@ -905,7 +902,6 @@ static void __exit ib_uverbs_cleanup(void) unregister_filesystem(&uverbs_event_fs); class_destroy(uverbs_class); unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); - flush_scheduled_work(); idr_destroy(&ib_uverbs_pd_idr); idr_destroy(&ib_uverbs_mr_idr); idr_destroy(&ib_uverbs_mw_idr);