diff --git a/fs/block_dev.c b/fs/block_dev.c index ea1480a..3a49adb 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -660,37 +660,32 @@ void bd_forget(struct inode *inode) int bd_claim(struct block_device *bdev, void *holder) { - int res; + void *bd_holder; + struct block_device *bd_contains; + spin_lock(&bdev_lock); - /* first decide result */ - if (bdev->bd_holder == holder) - res = 0; /* already a holder */ - else if (bdev->bd_holder != NULL) - res = -EBUSY; /* held by someone else */ - else if (bdev->bd_contains == bdev) - res = 0; /* is a whole device which isn't held */ - - else if (bdev->bd_contains->bd_holder == bd_claim) - res = 0; /* is a partition of a device that is being partitioned */ - else if (bdev->bd_contains->bd_holder != NULL) - res = -EBUSY; /* is a partition of a held device */ - else - res = 0; /* is a partition of an un-held device */ + bd_holder = bdev->bd_holder; + bd_contains = bdev->bd_contains; - /* now impose change */ - if (res==0) { - /* note that for a whole device bd_holders - * will be incremented twice, and bd_holder will - * be set to bd_claim before being set to holder - */ - bdev->bd_contains->bd_holders ++; - bdev->bd_contains->bd_holder = bd_claim; - bdev->bd_holders++; - bdev->bd_holder = holder; + if ((bd_holder && bd_holder != holder) || + (bd_contains != bdev && + bd_contains->bd_holder && bd_contains->bd_holder != bd_claim)) { + spin_unlock(&bdev_lock); + return -EBUSY; } + + /* note that for a whole device bd_holders + * will be incremented twice, and bd_holder will + * be set to bd_claim before being set to holder + */ + bdev->bd_contains->bd_holders ++; + bdev->bd_contains->bd_holder = bd_claim; + bdev->bd_holders++; + bdev->bd_holder = holder; + spin_unlock(&bdev_lock); - return res; + return 0; } EXPORT_SYMBOL(bd_claim); @@ -874,7 +869,7 @@ static struct bd_holder *find_bd_holder(struct block_device *bdev, */ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) { - int ret; + int err; if (!bo) return -EINVAL; @@ -882,14 +877,17 @@ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) if (!bd_holder_grab_dirs(bdev, bo)) return -EBUSY; - 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); + err = add_symlink(bo->sdir, bo->sdev); + if (err) + return err; + + err = add_symlink(bo->hdir, bo->hdev); + if (err) { + del_symlink(bo->sdir, bo->sdev); + return err; } - if (ret == 0) - list_add_tail(&bo->list, &bdev->bd_holder_list); + + list_add_tail(&bo->list, &bdev->bd_holder_list); return ret; }