If a matching bd_holder is found in bd_holder_list, add_bd_holder() completes its job by just incrementing the reference count. In this case, it should be considered as success but it used to return 'fail' to let the caller free bd_holder. Fixed it to return success and free given object by itself. Also, if either one of symlinking fails, the bd_holder should not be added to the list so that it can be discarded later. Otherwise, the caller will free bd_holder which is in the list. This patch is neccessary only for -mm (later than 2.6.18-rc1-mm1). fs/block_dev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) Signed-off-by: Jun'ichi Nomura diff -urp linux-2.6.18-rc5-mm1.orig/fs/block_dev.c linux-2.6.18-rc5-mm1/fs/block_dev.c --- linux-2.6.18-rc5-mm1.orig/fs/block_dev.c 2006-09-11 19:33:35.000000000 -0400 +++ linux-2.6.18-rc5-mm1/fs/block_dev.c 2006-09-11 19:21:46.000000000 -0400 @@ -655,8 +655,8 @@ static void free_bd_holder(struct bd_hol * If there is no matching entry with @bo in @bdev->bd_holder_list, * add @bo to the list, create symlinks. * - * Returns 0 if @bo was added to the list. - * Returns -ve 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) { @@ -669,7 +669,9 @@ static int add_bd_holder(struct block_de list_for_each_entry(tmp, &bdev->bd_holder_list, list) { if (tmp->sdir == bo->sdir) { tmp->count++; - return -EEXIST; + /* We've already done what we need to do here. */ + free_bd_holder(bo); + return 0; } } @@ -682,7 +684,8 @@ static int add_bd_holder(struct block_de if (ret) del_symlink(bo->sdir, bo->sdev); } - list_add_tail(&bo->list, &bdev->bd_holder_list); + if (ret == 0) + list_add_tail(&bo->list, &bdev->bd_holder_list); return ret; }