diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 414 |
1 files changed, 250 insertions, 164 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 36c0e7af9d0f..8b18e43b82fe 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -129,43 +129,191 @@ blkdev_get_block(struct inode *inode, sector_t iblock, | |||
129 | return 0; | 129 | return 0; |
130 | } | 130 | } |
131 | 131 | ||
132 | static int | 132 | static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error) |
133 | blkdev_get_blocks(struct inode *inode, sector_t iblock, | ||
134 | struct buffer_head *bh, int create) | ||
135 | { | 133 | { |
136 | sector_t end_block = max_block(I_BDEV(inode)); | 134 | struct kiocb *iocb = bio->bi_private; |
137 | unsigned long max_blocks = bh->b_size >> inode->i_blkbits; | 135 | atomic_t *bio_count = &iocb->ki_bio_count; |
138 | 136 | ||
139 | if ((iblock + max_blocks) > end_block) { | 137 | if (bio_data_dir(bio) == READ) |
140 | max_blocks = end_block - iblock; | 138 | bio_check_pages_dirty(bio); |
141 | if ((long)max_blocks <= 0) { | 139 | else { |
142 | if (create) | 140 | bio_release_pages(bio); |
143 | return -EIO; /* write fully beyond EOF */ | 141 | bio_put(bio); |
144 | /* | 142 | } |
145 | * It is a read which is fully beyond EOF. We return | 143 | |
146 | * a !buffer_mapped buffer | 144 | /* iocb->ki_nbytes stores error code from LLDD */ |
147 | */ | 145 | if (error) |
148 | max_blocks = 0; | 146 | iocb->ki_nbytes = -EIO; |
149 | } | 147 | |
148 | if (atomic_dec_and_test(bio_count)) { | ||
149 | if (iocb->ki_nbytes < 0) | ||
150 | aio_complete(iocb, iocb->ki_nbytes, 0); | ||
151 | else | ||
152 | aio_complete(iocb, iocb->ki_left, 0); | ||
150 | } | 153 | } |
151 | 154 | ||
152 | bh->b_bdev = I_BDEV(inode); | ||
153 | bh->b_blocknr = iblock; | ||
154 | bh->b_size = max_blocks << inode->i_blkbits; | ||
155 | if (max_blocks) | ||
156 | set_buffer_mapped(bh); | ||
157 | return 0; | 155 | return 0; |
158 | } | 156 | } |
159 | 157 | ||
158 | #define VEC_SIZE 16 | ||
159 | struct pvec { | ||
160 | unsigned short nr; | ||
161 | unsigned short idx; | ||
162 | struct page *page[VEC_SIZE]; | ||
163 | }; | ||
164 | |||
165 | #define PAGES_SPANNED(addr, len) \ | ||
166 | (DIV_ROUND_UP((addr) + (len), PAGE_SIZE) - (addr) / PAGE_SIZE); | ||
167 | |||
168 | /* | ||
169 | * get page pointer for user addr, we internally cache struct page array for | ||
170 | * (addr, count) range in pvec to avoid frequent call to get_user_pages. If | ||
171 | * internal page list is exhausted, a batch count of up to VEC_SIZE is used | ||
172 | * to get next set of page struct. | ||
173 | */ | ||
174 | static struct page *blk_get_page(unsigned long addr, size_t count, int rw, | ||
175 | struct pvec *pvec) | ||
176 | { | ||
177 | int ret, nr_pages; | ||
178 | if (pvec->idx == pvec->nr) { | ||
179 | nr_pages = PAGES_SPANNED(addr, count); | ||
180 | nr_pages = min(nr_pages, VEC_SIZE); | ||
181 | down_read(¤t->mm->mmap_sem); | ||
182 | ret = get_user_pages(current, current->mm, addr, nr_pages, | ||
183 | rw == READ, 0, pvec->page, NULL); | ||
184 | up_read(¤t->mm->mmap_sem); | ||
185 | if (ret < 0) | ||
186 | return ERR_PTR(ret); | ||
187 | pvec->nr = ret; | ||
188 | pvec->idx = 0; | ||
189 | } | ||
190 | return pvec->page[pvec->idx++]; | ||
191 | } | ||
192 | |||
160 | static ssize_t | 193 | static ssize_t |
161 | blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 194 | blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, |
162 | loff_t offset, unsigned long nr_segs) | 195 | loff_t pos, unsigned long nr_segs) |
163 | { | 196 | { |
164 | struct file *file = iocb->ki_filp; | 197 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
165 | struct inode *inode = file->f_mapping->host; | 198 | unsigned blkbits = blksize_bits(bdev_hardsect_size(I_BDEV(inode))); |
199 | unsigned blocksize_mask = (1 << blkbits) - 1; | ||
200 | unsigned long seg = 0; /* iov segment iterator */ | ||
201 | unsigned long nvec; /* number of bio vec needed */ | ||
202 | unsigned long cur_off; /* offset into current page */ | ||
203 | unsigned long cur_len; /* I/O len of current page, up to PAGE_SIZE */ | ||
204 | |||
205 | unsigned long addr; /* user iovec address */ | ||
206 | size_t count; /* user iovec len */ | ||
207 | size_t nbytes = iocb->ki_nbytes = iocb->ki_left; /* total xfer size */ | ||
208 | loff_t size; /* size of block device */ | ||
209 | struct bio *bio; | ||
210 | atomic_t *bio_count = &iocb->ki_bio_count; | ||
211 | struct page *page; | ||
212 | struct pvec pvec; | ||
213 | |||
214 | pvec.nr = 0; | ||
215 | pvec.idx = 0; | ||
216 | |||
217 | if (pos & blocksize_mask) | ||
218 | return -EINVAL; | ||
219 | |||
220 | size = i_size_read(inode); | ||
221 | if (pos + nbytes > size) { | ||
222 | nbytes = size - pos; | ||
223 | iocb->ki_left = nbytes; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * check first non-zero iov alignment, the remaining | ||
228 | * iov alignment is checked inside bio loop below. | ||
229 | */ | ||
230 | do { | ||
231 | addr = (unsigned long) iov[seg].iov_base; | ||
232 | count = min(iov[seg].iov_len, nbytes); | ||
233 | if (addr & blocksize_mask || count & blocksize_mask) | ||
234 | return -EINVAL; | ||
235 | } while (!count && ++seg < nr_segs); | ||
236 | atomic_set(bio_count, 1); | ||
237 | |||
238 | while (nbytes) { | ||
239 | /* roughly estimate number of bio vec needed */ | ||
240 | nvec = (nbytes + PAGE_SIZE - 1) / PAGE_SIZE; | ||
241 | nvec = max(nvec, nr_segs - seg); | ||
242 | nvec = min(nvec, (unsigned long) BIO_MAX_PAGES); | ||
243 | |||
244 | /* bio_alloc should not fail with GFP_KERNEL flag */ | ||
245 | bio = bio_alloc(GFP_KERNEL, nvec); | ||
246 | bio->bi_bdev = I_BDEV(inode); | ||
247 | bio->bi_end_io = blk_end_aio; | ||
248 | bio->bi_private = iocb; | ||
249 | bio->bi_sector = pos >> blkbits; | ||
250 | same_bio: | ||
251 | cur_off = addr & ~PAGE_MASK; | ||
252 | cur_len = PAGE_SIZE - cur_off; | ||
253 | if (count < cur_len) | ||
254 | cur_len = count; | ||
255 | |||
256 | page = blk_get_page(addr, count, rw, &pvec); | ||
257 | if (unlikely(IS_ERR(page))) | ||
258 | goto backout; | ||
259 | |||
260 | if (bio_add_page(bio, page, cur_len, cur_off)) { | ||
261 | pos += cur_len; | ||
262 | addr += cur_len; | ||
263 | count -= cur_len; | ||
264 | nbytes -= cur_len; | ||
265 | |||
266 | if (count) | ||
267 | goto same_bio; | ||
268 | while (++seg < nr_segs) { | ||
269 | addr = (unsigned long) iov[seg].iov_base; | ||
270 | count = iov[seg].iov_len; | ||
271 | if (!count) | ||
272 | continue; | ||
273 | if (unlikely(addr & blocksize_mask || | ||
274 | count & blocksize_mask)) { | ||
275 | page = ERR_PTR(-EINVAL); | ||
276 | goto backout; | ||
277 | } | ||
278 | count = min(count, nbytes); | ||
279 | goto same_bio; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /* bio is ready, submit it */ | ||
284 | if (rw == READ) | ||
285 | bio_set_pages_dirty(bio); | ||
286 | atomic_inc(bio_count); | ||
287 | submit_bio(rw, bio); | ||
288 | } | ||
289 | |||
290 | completion: | ||
291 | iocb->ki_left -= nbytes; | ||
292 | nbytes = iocb->ki_left; | ||
293 | iocb->ki_pos += nbytes; | ||
294 | |||
295 | blk_run_address_space(inode->i_mapping); | ||
296 | if (atomic_dec_and_test(bio_count)) | ||
297 | aio_complete(iocb, nbytes, 0); | ||
298 | |||
299 | return -EIOCBQUEUED; | ||
166 | 300 | ||
167 | return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode), | 301 | backout: |
168 | iov, offset, nr_segs, blkdev_get_blocks, NULL); | 302 | /* |
303 | * back out nbytes count constructed so far for this bio, | ||
304 | * we will throw away current bio. | ||
305 | */ | ||
306 | nbytes += bio->bi_size; | ||
307 | bio_release_pages(bio); | ||
308 | bio_put(bio); | ||
309 | |||
310 | /* | ||
311 | * if no bio was submmitted, return the error code. | ||
312 | * otherwise, proceed with pending I/O completion. | ||
313 | */ | ||
314 | if (atomic_read(bio_count) == 1) | ||
315 | return PTR_ERR(page); | ||
316 | goto completion; | ||
169 | } | 317 | } |
170 | 318 | ||
171 | static int blkdev_writepage(struct page *page, struct writeback_control *wbc) | 319 | static int blkdev_writepage(struct page *page, struct writeback_control *wbc) |
@@ -190,7 +338,7 @@ static int blkdev_commit_write(struct file *file, struct page *page, unsigned fr | |||
190 | 338 | ||
191 | /* | 339 | /* |
192 | * private llseek: | 340 | * private llseek: |
193 | * for a block special file file->f_dentry->d_inode->i_size is zero | 341 | * for a block special file file->f_path.dentry->d_inode->i_size is zero |
194 | * so we compute the size by hand (just as in block_read/write above) | 342 | * so we compute the size by hand (just as in block_read/write above) |
195 | */ | 343 | */ |
196 | static loff_t block_llseek(struct file *file, loff_t offset, int origin) | 344 | static loff_t block_llseek(struct file *file, loff_t offset, int origin) |
@@ -235,11 +383,11 @@ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync) | |||
235 | */ | 383 | */ |
236 | 384 | ||
237 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock); | 385 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock); |
238 | static kmem_cache_t * bdev_cachep __read_mostly; | 386 | static struct kmem_cache * bdev_cachep __read_mostly; |
239 | 387 | ||
240 | static struct inode *bdev_alloc_inode(struct super_block *sb) | 388 | static struct inode *bdev_alloc_inode(struct super_block *sb) |
241 | { | 389 | { |
242 | struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, SLAB_KERNEL); | 390 | struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); |
243 | if (!ei) | 391 | if (!ei) |
244 | return NULL; | 392 | return NULL; |
245 | return &ei->vfs_inode; | 393 | return &ei->vfs_inode; |
@@ -253,7 +401,7 @@ static void bdev_destroy_inode(struct inode *inode) | |||
253 | kmem_cache_free(bdev_cachep, bdi); | 401 | kmem_cache_free(bdev_cachep, bdi); |
254 | } | 402 | } |
255 | 403 | ||
256 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | 404 | static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) |
257 | { | 405 | { |
258 | struct bdev_inode *ei = (struct bdev_inode *) foo; | 406 | struct bdev_inode *ei = (struct bdev_inode *) foo; |
259 | struct block_device *bdev = &ei->bdev; | 407 | struct block_device *bdev = &ei->bdev; |
@@ -263,7 +411,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | |||
263 | { | 411 | { |
264 | memset(bdev, 0, sizeof(*bdev)); | 412 | memset(bdev, 0, sizeof(*bdev)); |
265 | mutex_init(&bdev->bd_mutex); | 413 | mutex_init(&bdev->bd_mutex); |
266 | mutex_init(&bdev->bd_mount_mutex); | 414 | sema_init(&bdev->bd_mount_sem, 1); |
267 | INIT_LIST_HEAD(&bdev->bd_inodes); | 415 | INIT_LIST_HEAD(&bdev->bd_inodes); |
268 | INIT_LIST_HEAD(&bdev->bd_list); | 416 | INIT_LIST_HEAD(&bdev->bd_list); |
269 | #ifdef CONFIG_SYSFS | 417 | #ifdef CONFIG_SYSFS |
@@ -762,7 +910,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
762 | if (!bo) | 910 | if (!bo) |
763 | return -ENOMEM; | 911 | return -ENOMEM; |
764 | 912 | ||
765 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); | 913 | mutex_lock(&bdev->bd_mutex); |
766 | res = bd_claim(bdev, holder); | 914 | res = bd_claim(bdev, holder); |
767 | if (res == 0) { | 915 | if (res == 0) { |
768 | found = find_bd_holder(bdev, bo); | 916 | found = find_bd_holder(bdev, bo); |
@@ -796,7 +944,7 @@ static void bd_release_from_kobject(struct block_device *bdev, | |||
796 | if (!kobj) | 944 | if (!kobj) |
797 | return; | 945 | return; |
798 | 946 | ||
799 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); | 947 | mutex_lock(&bdev->bd_mutex); |
800 | bd_release(bdev); | 948 | bd_release(bdev); |
801 | if ((bo = del_bd_holder(bdev, kobj))) | 949 | if ((bo = del_bd_holder(bdev, kobj))) |
802 | free_bd_holder(bo); | 950 | free_bd_holder(bo); |
@@ -854,22 +1002,6 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) | |||
854 | 1002 | ||
855 | EXPORT_SYMBOL(open_by_devnum); | 1003 | EXPORT_SYMBOL(open_by_devnum); |
856 | 1004 | ||
857 | static int | ||
858 | blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags); | ||
859 | |||
860 | struct block_device *open_partition_by_devnum(dev_t dev, unsigned mode) | ||
861 | { | ||
862 | struct block_device *bdev = bdget(dev); | ||
863 | int err = -ENOMEM; | ||
864 | int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY; | ||
865 | if (bdev) | ||
866 | err = blkdev_get_partition(bdev, mode, flags); | ||
867 | return err ? ERR_PTR(err) : bdev; | ||
868 | } | ||
869 | |||
870 | EXPORT_SYMBOL(open_partition_by_devnum); | ||
871 | |||
872 | |||
873 | /* | 1005 | /* |
874 | * This routine checks whether a removable media has been changed, | 1006 | * This routine checks whether a removable media has been changed, |
875 | * and invalidates all buffer-cache-entries in that case. This | 1007 | * and invalidates all buffer-cache-entries in that case. This |
@@ -916,66 +1048,11 @@ void bd_set_size(struct block_device *bdev, loff_t size) | |||
916 | } | 1048 | } |
917 | EXPORT_SYMBOL(bd_set_size); | 1049 | EXPORT_SYMBOL(bd_set_size); |
918 | 1050 | ||
919 | static int __blkdev_put(struct block_device *bdev, unsigned int subclass) | 1051 | static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, |
920 | { | 1052 | int for_part); |
921 | int ret = 0; | 1053 | static int __blkdev_put(struct block_device *bdev, int for_part); |
922 | struct inode *bd_inode = bdev->bd_inode; | ||
923 | struct gendisk *disk = bdev->bd_disk; | ||
924 | 1054 | ||
925 | mutex_lock_nested(&bdev->bd_mutex, subclass); | 1055 | static int do_open(struct block_device *bdev, struct file *file, int for_part) |
926 | lock_kernel(); | ||
927 | if (!--bdev->bd_openers) { | ||
928 | sync_blockdev(bdev); | ||
929 | kill_bdev(bdev); | ||
930 | } | ||
931 | if (bdev->bd_contains == bdev) { | ||
932 | if (disk->fops->release) | ||
933 | ret = disk->fops->release(bd_inode, NULL); | ||
934 | } else { | ||
935 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, | ||
936 | subclass + 1); | ||
937 | bdev->bd_contains->bd_part_count--; | ||
938 | mutex_unlock(&bdev->bd_contains->bd_mutex); | ||
939 | } | ||
940 | if (!bdev->bd_openers) { | ||
941 | struct module *owner = disk->fops->owner; | ||
942 | |||
943 | put_disk(disk); | ||
944 | module_put(owner); | ||
945 | |||
946 | if (bdev->bd_contains != bdev) { | ||
947 | kobject_put(&bdev->bd_part->kobj); | ||
948 | bdev->bd_part = NULL; | ||
949 | } | ||
950 | bdev->bd_disk = NULL; | ||
951 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | ||
952 | if (bdev != bdev->bd_contains) | ||
953 | __blkdev_put(bdev->bd_contains, subclass + 1); | ||
954 | bdev->bd_contains = NULL; | ||
955 | } | ||
956 | unlock_kernel(); | ||
957 | mutex_unlock(&bdev->bd_mutex); | ||
958 | bdput(bdev); | ||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | int blkdev_put(struct block_device *bdev) | ||
963 | { | ||
964 | return __blkdev_put(bdev, BD_MUTEX_NORMAL); | ||
965 | } | ||
966 | EXPORT_SYMBOL(blkdev_put); | ||
967 | |||
968 | int blkdev_put_partition(struct block_device *bdev) | ||
969 | { | ||
970 | return __blkdev_put(bdev, BD_MUTEX_PARTITION); | ||
971 | } | ||
972 | EXPORT_SYMBOL(blkdev_put_partition); | ||
973 | |||
974 | static int | ||
975 | blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags); | ||
976 | |||
977 | static int | ||
978 | do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | ||
979 | { | 1056 | { |
980 | struct module *owner = NULL; | 1057 | struct module *owner = NULL; |
981 | struct gendisk *disk; | 1058 | struct gendisk *disk; |
@@ -992,8 +1069,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | |||
992 | } | 1069 | } |
993 | owner = disk->fops->owner; | 1070 | owner = disk->fops->owner; |
994 | 1071 | ||
995 | mutex_lock_nested(&bdev->bd_mutex, subclass); | 1072 | mutex_lock_nested(&bdev->bd_mutex, for_part); |
996 | |||
997 | if (!bdev->bd_openers) { | 1073 | if (!bdev->bd_openers) { |
998 | bdev->bd_disk = disk; | 1074 | bdev->bd_disk = disk; |
999 | bdev->bd_contains = bdev; | 1075 | bdev->bd_contains = bdev; |
@@ -1020,25 +1096,21 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | |||
1020 | ret = -ENOMEM; | 1096 | ret = -ENOMEM; |
1021 | if (!whole) | 1097 | if (!whole) |
1022 | goto out_first; | 1098 | goto out_first; |
1023 | ret = blkdev_get_whole(whole, file->f_mode, file->f_flags); | 1099 | BUG_ON(for_part); |
1100 | ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1); | ||
1024 | if (ret) | 1101 | if (ret) |
1025 | goto out_first; | 1102 | goto out_first; |
1026 | bdev->bd_contains = whole; | 1103 | bdev->bd_contains = whole; |
1027 | mutex_lock_nested(&whole->bd_mutex, BD_MUTEX_WHOLE); | ||
1028 | whole->bd_part_count++; | ||
1029 | p = disk->part[part - 1]; | 1104 | p = disk->part[part - 1]; |
1030 | bdev->bd_inode->i_data.backing_dev_info = | 1105 | bdev->bd_inode->i_data.backing_dev_info = |
1031 | whole->bd_inode->i_data.backing_dev_info; | 1106 | whole->bd_inode->i_data.backing_dev_info; |
1032 | if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { | 1107 | if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { |
1033 | whole->bd_part_count--; | ||
1034 | mutex_unlock(&whole->bd_mutex); | ||
1035 | ret = -ENXIO; | 1108 | ret = -ENXIO; |
1036 | goto out_first; | 1109 | goto out_first; |
1037 | } | 1110 | } |
1038 | kobject_get(&p->kobj); | 1111 | kobject_get(&p->kobj); |
1039 | bdev->bd_part = p; | 1112 | bdev->bd_part = p; |
1040 | bd_set_size(bdev, (loff_t) p->nr_sects << 9); | 1113 | bd_set_size(bdev, (loff_t) p->nr_sects << 9); |
1041 | mutex_unlock(&whole->bd_mutex); | ||
1042 | } | 1114 | } |
1043 | } else { | 1115 | } else { |
1044 | put_disk(disk); | 1116 | put_disk(disk); |
@@ -1051,14 +1123,11 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | |||
1051 | } | 1123 | } |
1052 | if (bdev->bd_invalidated) | 1124 | if (bdev->bd_invalidated) |
1053 | rescan_partitions(bdev->bd_disk, bdev); | 1125 | rescan_partitions(bdev->bd_disk, bdev); |
1054 | } else { | ||
1055 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, | ||
1056 | BD_MUTEX_WHOLE); | ||
1057 | bdev->bd_contains->bd_part_count++; | ||
1058 | mutex_unlock(&bdev->bd_contains->bd_mutex); | ||
1059 | } | 1126 | } |
1060 | } | 1127 | } |
1061 | bdev->bd_openers++; | 1128 | bdev->bd_openers++; |
1129 | if (for_part) | ||
1130 | bdev->bd_part_count++; | ||
1062 | mutex_unlock(&bdev->bd_mutex); | 1131 | mutex_unlock(&bdev->bd_mutex); |
1063 | unlock_kernel(); | 1132 | unlock_kernel(); |
1064 | return 0; | 1133 | return 0; |
@@ -1067,7 +1136,7 @@ out_first: | |||
1067 | bdev->bd_disk = NULL; | 1136 | bdev->bd_disk = NULL; |
1068 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 1137 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
1069 | if (bdev != bdev->bd_contains) | 1138 | if (bdev != bdev->bd_contains) |
1070 | __blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE); | 1139 | __blkdev_put(bdev->bd_contains, 1); |
1071 | bdev->bd_contains = NULL; | 1140 | bdev->bd_contains = NULL; |
1072 | put_disk(disk); | 1141 | put_disk(disk); |
1073 | module_put(owner); | 1142 | module_put(owner); |
@@ -1079,7 +1148,8 @@ out: | |||
1079 | return ret; | 1148 | return ret; |
1080 | } | 1149 | } |
1081 | 1150 | ||
1082 | int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) | 1151 | static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, |
1152 | int for_part) | ||
1083 | { | 1153 | { |
1084 | /* | 1154 | /* |
1085 | * This crockload is due to bad choice of ->open() type. | 1155 | * This crockload is due to bad choice of ->open() type. |
@@ -1091,51 +1161,17 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) | |||
1091 | struct dentry fake_dentry = {}; | 1161 | struct dentry fake_dentry = {}; |
1092 | fake_file.f_mode = mode; | 1162 | fake_file.f_mode = mode; |
1093 | fake_file.f_flags = flags; | 1163 | fake_file.f_flags = flags; |
1094 | fake_file.f_dentry = &fake_dentry; | 1164 | fake_file.f_path.dentry = &fake_dentry; |
1095 | fake_dentry.d_inode = bdev->bd_inode; | 1165 | fake_dentry.d_inode = bdev->bd_inode; |
1096 | 1166 | ||
1097 | return do_open(bdev, &fake_file, BD_MUTEX_NORMAL); | 1167 | return do_open(bdev, &fake_file, for_part); |
1098 | } | 1168 | } |
1099 | 1169 | ||
1100 | EXPORT_SYMBOL(blkdev_get); | 1170 | int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) |
1101 | |||
1102 | static int | ||
1103 | blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags) | ||
1104 | { | ||
1105 | /* | ||
1106 | * This crockload is due to bad choice of ->open() type. | ||
1107 | * It will go away. | ||
1108 | * For now, block device ->open() routine must _not_ | ||
1109 | * examine anything in 'inode' argument except ->i_rdev. | ||
1110 | */ | ||
1111 | struct file fake_file = {}; | ||
1112 | struct dentry fake_dentry = {}; | ||
1113 | fake_file.f_mode = mode; | ||
1114 | fake_file.f_flags = flags; | ||
1115 | fake_file.f_dentry = &fake_dentry; | ||
1116 | fake_dentry.d_inode = bdev->bd_inode; | ||
1117 | |||
1118 | return do_open(bdev, &fake_file, BD_MUTEX_WHOLE); | ||
1119 | } | ||
1120 | |||
1121 | static int | ||
1122 | blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags) | ||
1123 | { | 1171 | { |
1124 | /* | 1172 | return __blkdev_get(bdev, mode, flags, 0); |
1125 | * This crockload is due to bad choice of ->open() type. | ||
1126 | * It will go away. | ||
1127 | * For now, block device ->open() routine must _not_ | ||
1128 | * examine anything in 'inode' argument except ->i_rdev. | ||
1129 | */ | ||
1130 | struct file fake_file = {}; | ||
1131 | struct dentry fake_dentry = {}; | ||
1132 | fake_file.f_mode = mode; | ||
1133 | fake_file.f_flags = flags; | ||
1134 | fake_file.f_dentry = &fake_dentry; | ||
1135 | fake_dentry.d_inode = bdev->bd_inode; | ||
1136 | |||
1137 | return do_open(bdev, &fake_file, BD_MUTEX_PARTITION); | ||
1138 | } | 1173 | } |
1174 | EXPORT_SYMBOL(blkdev_get); | ||
1139 | 1175 | ||
1140 | static int blkdev_open(struct inode * inode, struct file * filp) | 1176 | static int blkdev_open(struct inode * inode, struct file * filp) |
1141 | { | 1177 | { |
@@ -1154,7 +1190,7 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
1154 | if (bdev == NULL) | 1190 | if (bdev == NULL) |
1155 | return -ENOMEM; | 1191 | return -ENOMEM; |
1156 | 1192 | ||
1157 | res = do_open(bdev, filp, BD_MUTEX_NORMAL); | 1193 | res = do_open(bdev, filp, 0); |
1158 | if (res) | 1194 | if (res) |
1159 | return res; | 1195 | return res; |
1160 | 1196 | ||
@@ -1168,6 +1204,56 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
1168 | return res; | 1204 | return res; |
1169 | } | 1205 | } |
1170 | 1206 | ||
1207 | static int __blkdev_put(struct block_device *bdev, int for_part) | ||
1208 | { | ||
1209 | int ret = 0; | ||
1210 | struct inode *bd_inode = bdev->bd_inode; | ||
1211 | struct gendisk *disk = bdev->bd_disk; | ||
1212 | struct block_device *victim = NULL; | ||
1213 | |||
1214 | mutex_lock_nested(&bdev->bd_mutex, for_part); | ||
1215 | lock_kernel(); | ||
1216 | if (for_part) | ||
1217 | bdev->bd_part_count--; | ||
1218 | |||
1219 | if (!--bdev->bd_openers) { | ||
1220 | sync_blockdev(bdev); | ||
1221 | kill_bdev(bdev); | ||
1222 | } | ||
1223 | if (bdev->bd_contains == bdev) { | ||
1224 | if (disk->fops->release) | ||
1225 | ret = disk->fops->release(bd_inode, NULL); | ||
1226 | } | ||
1227 | if (!bdev->bd_openers) { | ||
1228 | struct module *owner = disk->fops->owner; | ||
1229 | |||
1230 | put_disk(disk); | ||
1231 | module_put(owner); | ||
1232 | |||
1233 | if (bdev->bd_contains != bdev) { | ||
1234 | kobject_put(&bdev->bd_part->kobj); | ||
1235 | bdev->bd_part = NULL; | ||
1236 | } | ||
1237 | bdev->bd_disk = NULL; | ||
1238 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | ||
1239 | if (bdev != bdev->bd_contains) | ||
1240 | victim = bdev->bd_contains; | ||
1241 | bdev->bd_contains = NULL; | ||
1242 | } | ||
1243 | unlock_kernel(); | ||
1244 | mutex_unlock(&bdev->bd_mutex); | ||
1245 | bdput(bdev); | ||
1246 | if (victim) | ||
1247 | __blkdev_put(victim, 1); | ||
1248 | return ret; | ||
1249 | } | ||
1250 | |||
1251 | int blkdev_put(struct block_device *bdev) | ||
1252 | { | ||
1253 | return __blkdev_put(bdev, 0); | ||
1254 | } | ||
1255 | EXPORT_SYMBOL(blkdev_put); | ||
1256 | |||
1171 | static int blkdev_close(struct inode * inode, struct file * filp) | 1257 | static int blkdev_close(struct inode * inode, struct file * filp) |
1172 | { | 1258 | { |
1173 | struct block_device *bdev = I_BDEV(filp->f_mapping->host); | 1259 | struct block_device *bdev = I_BDEV(filp->f_mapping->host); |