]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/block_dev.c
[PATCH] blockdev.c: check driver layer errors
[net-next-2.6.git] / fs / block_dev.c
index 045f98854f14ab91c71cc6a61a9cafb1716a53c4..8cc144ffc3828ecfad6f6b432611be5ddc44f2a8 100644 (file)
@@ -543,11 +543,11 @@ static struct kobject *bdev_get_holder(struct block_device *bdev)
                return kobject_get(bdev->bd_disk->holder_dir);
 }
 
-static void add_symlink(struct kobject *from, struct kobject *to)
+static int add_symlink(struct kobject *from, struct kobject *to)
 {
        if (!from || !to)
-               return;
-       sysfs_create_link(from, to, kobject_name(to));
+               return 0;
+       return sysfs_create_link(from, to, kobject_name(to));
 }
 
 static void del_symlink(struct kobject *from, struct kobject *to)
@@ -648,30 +648,38 @@ static void free_bd_holder(struct bd_holder *bo)
  * If there is no matching entry with @bo in @bdev->bd_holder_list,
  * add @bo to the list, create symlinks.
  *
- * Returns 1 if @bo was added to the list.
- * Returns 0 if @bo wasn't used by any reason and should be freed.
+ * Returns 0 if symlinks are created or already there.
+ * Returns -ve if something fails and @bo can be freed.
  */
 static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
 {
        struct bd_holder *tmp;
+       int ret;
 
        if (!bo)
-               return 0;
+               return -EINVAL;
 
        list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
                if (tmp->sdir == bo->sdir) {
                        tmp->count++;
+                       /* We've already done what we need to do here. */
+                       free_bd_holder(bo);
                        return 0;
                }
        }
 
        if (!bd_holder_grab_dirs(bdev, bo))
-               return 0;
+               return -EBUSY;
 
-       add_symlink(bo->sdir, bo->sdev);
-       add_symlink(bo->hdir, bo->hdev);
-       list_add_tail(&bo->list, &bdev->bd_holder_list);
-       return 1;
+       ret = add_symlink(bo->sdir, bo->sdev);
+       if (ret == 0) {
+               ret = add_symlink(bo->hdir, bo->hdev);
+               if (ret)
+                       del_symlink(bo->sdir, bo->sdev);
+       }
+       if (ret == 0)
+               list_add_tail(&bo->list, &bdev->bd_holder_list);
+       return ret;
 }
 
 /**
@@ -741,7 +749,9 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
 
        mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
        res = bd_claim(bdev, holder);
-       if (res || !add_bd_holder(bdev, bo))
+       if (res == 0)
+               res = add_bd_holder(bdev, bo);
+       if (res)
                free_bd_holder(bo);
        mutex_unlock(&bdev->bd_mutex);