aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c83
1 files changed, 49 insertions, 34 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 045f98854f14..bc8f27cc4483 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -17,11 +17,13 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/blkpg.h> 18#include <linux/blkpg.h>
19#include <linux/buffer_head.h> 19#include <linux/buffer_head.h>
20#include <linux/writeback.h>
20#include <linux/mpage.h> 21#include <linux/mpage.h>
21#include <linux/mount.h> 22#include <linux/mount.h>
22#include <linux/uio.h> 23#include <linux/uio.h>
23#include <linux/namei.h> 24#include <linux/namei.h>
24#include <asm/uaccess.h> 25#include <asm/uaccess.h>
26#include "internal.h"
25 27
26struct bdev_inode { 28struct bdev_inode {
27 struct block_device bdev; 29 struct block_device bdev;
@@ -543,11 +545,11 @@ static struct kobject *bdev_get_holder(struct block_device *bdev)
543 return kobject_get(bdev->bd_disk->holder_dir); 545 return kobject_get(bdev->bd_disk->holder_dir);
544} 546}
545 547
546static void add_symlink(struct kobject *from, struct kobject *to) 548static int add_symlink(struct kobject *from, struct kobject *to)
547{ 549{
548 if (!from || !to) 550 if (!from || !to)
549 return; 551 return 0;
550 sysfs_create_link(from, to, kobject_name(to)); 552 return sysfs_create_link(from, to, kobject_name(to));
551} 553}
552 554
553static void del_symlink(struct kobject *from, struct kobject *to) 555static void del_symlink(struct kobject *from, struct kobject *to)
@@ -648,30 +650,38 @@ static void free_bd_holder(struct bd_holder *bo)
648 * If there is no matching entry with @bo in @bdev->bd_holder_list, 650 * If there is no matching entry with @bo in @bdev->bd_holder_list,
649 * add @bo to the list, create symlinks. 651 * add @bo to the list, create symlinks.
650 * 652 *
651 * Returns 1 if @bo was added to the list. 653 * Returns 0 if symlinks are created or already there.
652 * Returns 0 if @bo wasn't used by any reason and should be freed. 654 * Returns -ve if something fails and @bo can be freed.
653 */ 655 */
654static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) 656static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
655{ 657{
656 struct bd_holder *tmp; 658 struct bd_holder *tmp;
659 int ret;
657 660
658 if (!bo) 661 if (!bo)
659 return 0; 662 return -EINVAL;
660 663
661 list_for_each_entry(tmp, &bdev->bd_holder_list, list) { 664 list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
662 if (tmp->sdir == bo->sdir) { 665 if (tmp->sdir == bo->sdir) {
663 tmp->count++; 666 tmp->count++;
667 /* We've already done what we need to do here. */
668 free_bd_holder(bo);
664 return 0; 669 return 0;
665 } 670 }
666 } 671 }
667 672
668 if (!bd_holder_grab_dirs(bdev, bo)) 673 if (!bd_holder_grab_dirs(bdev, bo))
669 return 0; 674 return -EBUSY;
670 675
671 add_symlink(bo->sdir, bo->sdev); 676 ret = add_symlink(bo->sdir, bo->sdev);
672 add_symlink(bo->hdir, bo->hdev); 677 if (ret == 0) {
673 list_add_tail(&bo->list, &bdev->bd_holder_list); 678 ret = add_symlink(bo->hdir, bo->hdev);
674 return 1; 679 if (ret)
680 del_symlink(bo->sdir, bo->sdev);
681 }
682 if (ret == 0)
683 list_add_tail(&bo->list, &bdev->bd_holder_list);
684 return ret;
675} 685}
676 686
677/** 687/**
@@ -741,7 +751,9 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
741 751
742 mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); 752 mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
743 res = bd_claim(bdev, holder); 753 res = bd_claim(bdev, holder);
744 if (res || !add_bd_holder(bdev, bo)) 754 if (res == 0)
755 res = add_bd_holder(bdev, bo);
756 if (res)
745 free_bd_holder(bo); 757 free_bd_holder(bo);
746 mutex_unlock(&bdev->bd_mutex); 758 mutex_unlock(&bdev->bd_mutex);
747 759
@@ -1021,7 +1033,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
1021 rescan_partitions(bdev->bd_disk, bdev); 1033 rescan_partitions(bdev->bd_disk, bdev);
1022 } else { 1034 } else {
1023 mutex_lock_nested(&bdev->bd_contains->bd_mutex, 1035 mutex_lock_nested(&bdev->bd_contains->bd_mutex,
1024 BD_MUTEX_PARTITION); 1036 BD_MUTEX_WHOLE);
1025 bdev->bd_contains->bd_part_count++; 1037 bdev->bd_contains->bd_part_count++;
1026 mutex_unlock(&bdev->bd_contains->bd_mutex); 1038 mutex_unlock(&bdev->bd_contains->bd_mutex);
1027 } 1039 }
@@ -1142,22 +1154,6 @@ static int blkdev_close(struct inode * inode, struct file * filp)
1142 return blkdev_put(bdev); 1154 return blkdev_put(bdev);
1143} 1155}
1144 1156
1145static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
1146 size_t count, loff_t *ppos)
1147{
1148 struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
1149
1150 return generic_file_write_nolock(file, &local_iov, 1, ppos);
1151}
1152
1153static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
1154 size_t count, loff_t pos)
1155{
1156 struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
1157
1158 return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
1159}
1160
1161static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) 1157static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
1162{ 1158{
1163 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); 1159 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
@@ -1177,18 +1173,16 @@ const struct file_operations def_blk_fops = {
1177 .open = blkdev_open, 1173 .open = blkdev_open,
1178 .release = blkdev_close, 1174 .release = blkdev_close,
1179 .llseek = block_llseek, 1175 .llseek = block_llseek,
1180 .read = generic_file_read, 1176 .read = do_sync_read,
1181 .write = blkdev_file_write, 1177 .write = do_sync_write,
1182 .aio_read = generic_file_aio_read, 1178 .aio_read = generic_file_aio_read,
1183 .aio_write = blkdev_file_aio_write, 1179 .aio_write = generic_file_aio_write_nolock,
1184 .mmap = generic_file_mmap, 1180 .mmap = generic_file_mmap,
1185 .fsync = block_fsync, 1181 .fsync = block_fsync,
1186 .unlocked_ioctl = block_ioctl, 1182 .unlocked_ioctl = block_ioctl,
1187#ifdef CONFIG_COMPAT 1183#ifdef CONFIG_COMPAT
1188 .compat_ioctl = compat_blkdev_ioctl, 1184 .compat_ioctl = compat_blkdev_ioctl,
1189#endif 1185#endif
1190 .readv = generic_file_readv,
1191 .writev = generic_file_write_nolock,
1192 .sendfile = generic_file_sendfile, 1186 .sendfile = generic_file_sendfile,
1193 .splice_read = generic_file_splice_read, 1187 .splice_read = generic_file_splice_read,
1194 .splice_write = generic_file_splice_write, 1188 .splice_write = generic_file_splice_write,
@@ -1303,3 +1297,24 @@ void close_bdev_excl(struct block_device *bdev)
1303} 1297}
1304 1298
1305EXPORT_SYMBOL(close_bdev_excl); 1299EXPORT_SYMBOL(close_bdev_excl);
1300
1301int __invalidate_device(struct block_device *bdev)
1302{
1303 struct super_block *sb = get_super(bdev);
1304 int res = 0;
1305
1306 if (sb) {
1307 /*
1308 * no need to lock the super, get_super holds the
1309 * read mutex so the filesystem cannot go away
1310 * under us (->put_super runs with the write lock
1311 * hold).
1312 */
1313 shrink_dcache_sb(sb);
1314 res = invalidate_inodes(sb);
1315 drop_super(sb);
1316 }
1317 invalidate_bdev(bdev, 0);
1318 return res;
1319}
1320EXPORT_SYMBOL(__invalidate_device);