Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[pandora-kernel.git] / fs / block_dev.c
index 0c361ea..36c0e7a 100644 (file)
@@ -641,35 +641,48 @@ static void free_bd_holder(struct bd_holder *bo)
        kfree(bo);
 }
 
+/**
+ * find_bd_holder - find matching struct bd_holder from the block device
+ *
+ * @bdev:      struct block device to be searched
+ * @bo:                target struct bd_holder
+ *
+ * Returns matching entry with @bo in @bdev->bd_holder_list.
+ * If found, increment the reference count and return the pointer.
+ * If not found, returns NULL.
+ */
+static struct bd_holder *find_bd_holder(struct block_device *bdev,
+                                       struct bd_holder *bo)
+{
+       struct bd_holder *tmp;
+
+       list_for_each_entry(tmp, &bdev->bd_holder_list, list)
+               if (tmp->sdir == bo->sdir) {
+                       tmp->count++;
+                       return tmp;
+               }
+
+       return NULL;
+}
+
 /**
  * add_bd_holder - create sysfs symlinks for bd_claim() relationship
  *
  * @bdev:      block device to be bd_claimed
  * @bo:                preallocated and initialized by alloc_bd_holder()
  *
- * If there is no matching entry with @bo in @bdev->bd_holder_list,
- * add @bo to the list, create symlinks.
+ * Add @bo to @bdev->bd_holder_list, create symlinks.
  *
- * Returns 0 if symlinks are created or already there.
- * Returns -ve if something fails and @bo can be freed.
+ * Returns 0 if symlinks are created.
+ * Returns -ve if something fails.
  */
 static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
 {
-       struct bd_holder *tmp;
        int ret;
 
        if (!bo)
                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 -EBUSY;
 
@@ -740,7 +753,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
                                struct kobject *kobj)
 {
        int res;
-       struct bd_holder *bo;
+       struct bd_holder *bo, *found;
 
        if (!kobj)
                return -EINVAL;
@@ -751,9 +764,16 @@ 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 == 0)
-               res = add_bd_holder(bdev, bo);
-       if (res)
+       if (res == 0) {
+               found = find_bd_holder(bdev, bo);
+               if (found == NULL) {
+                       res = add_bd_holder(bdev, bo);
+                       if (res)
+                               bd_release(bdev);
+               }
+       }
+
+       if (res || found)
                free_bd_holder(bo);
        mutex_unlock(&bdev->bd_mutex);
 
@@ -1131,6 +1151,8 @@ static int blkdev_open(struct inode * inode, struct file * filp)
        filp->f_flags |= O_LARGEFILE;
 
        bdev = bd_acquire(inode);
+       if (bdev == NULL)
+               return -ENOMEM;
 
        res = do_open(bdev, filp, BD_MUTEX_NORMAL);
        if (res)
@@ -1154,22 +1176,6 @@ static int blkdev_close(struct inode * inode, struct file * filp)
        return blkdev_put(bdev);
 }
 
-static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
-                                  size_t count, loff_t *ppos)
-{
-       struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
-       return generic_file_write_nolock(file, &local_iov, 1, ppos);
-}
-
-static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
-                                  size_t count, loff_t pos)
-{
-       struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
-       return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
-}
-
 static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
        return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
@@ -1189,18 +1195,16 @@ const struct file_operations def_blk_fops = {
        .open           = blkdev_open,
        .release        = blkdev_close,
        .llseek         = block_llseek,
-       .read           = generic_file_read,
-       .write          = blkdev_file_write,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
-       .aio_write      = blkdev_file_aio_write, 
+       .aio_write      = generic_file_aio_write_nolock,
        .mmap           = generic_file_mmap,
        .fsync          = block_fsync,
        .unlocked_ioctl = block_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .readv          = generic_file_readv,
-       .writev         = generic_file_write_nolock,
        .sendfile       = generic_file_sendfile,
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,