linux-bk/fs/block_dev.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/block_dev.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 *  Copyright (C) 2001  Andrea Arcangeli <andrea@suse.de> SuSE
   6 */
   7
   8#include <linux/config.h>
   9#include <linux/init.h>
  10#include <linux/mm.h>
  11#include <linux/fcntl.h>
  12#include <linux/slab.h>
  13#include <linux/kmod.h>
  14#include <linux/major.h>
  15#include <linux/devfs_fs_kernel.h>
  16#include <linux/smp_lock.h>
  17#include <linux/highmem.h>
  18#include <linux/blkdev.h>
  19#include <linux/module.h>
  20#include <linux/blkpg.h>
  21#include <linux/buffer_head.h>
  22#include <linux/mpage.h>
  23#include <linux/mount.h>
  24#include <linux/uio.h>
  25#include <linux/namei.h>
  26#include <asm/uaccess.h>
  27
  28
  29static sector_t max_block(struct block_device *bdev)
  30{
  31        sector_t retval = ~((sector_t)0);
  32        loff_t sz = i_size_read(bdev->bd_inode);
  33
  34        if (sz) {
  35                unsigned int size = block_size(bdev);
  36                unsigned int sizebits = blksize_bits(size);
  37                retval = (sz >> sizebits);
  38        }
  39        return retval;
  40}
  41
  42/* Kill _all_ buffers, dirty or not.. */
  43static void kill_bdev(struct block_device *bdev)
  44{
  45        invalidate_bdev(bdev, 1);
  46        truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  47}       
  48
  49int set_blocksize(struct block_device *bdev, int size)
  50{
  51        int oldsize;
  52
  53        /* Size must be a power of two, and between 512 and PAGE_SIZE */
  54        if (size > PAGE_SIZE || size < 512 || (size & (size-1)))
  55                return -EINVAL;
  56
  57        /* Size cannot be smaller than the size supported by the device */
  58        if (size < bdev_hardsect_size(bdev))
  59                return -EINVAL;
  60
  61        oldsize = bdev->bd_block_size;
  62        if (oldsize == size)
  63                return 0;
  64
  65        /* Ok, we're actually changing the blocksize.. */
  66        sync_blockdev(bdev);
  67        bdev->bd_block_size = size;
  68        bdev->bd_inode->i_blkbits = blksize_bits(size);
  69        kill_bdev(bdev);
  70        return 0;
  71}
  72
  73EXPORT_SYMBOL(set_blocksize);
  74
  75int sb_set_blocksize(struct super_block *sb, int size)
  76{
  77        int bits;
  78        if (set_blocksize(sb->s_bdev, size) < 0)
  79                return 0;
  80        sb->s_blocksize = size;
  81        for (bits = 9, size >>= 9; size >>= 1; bits++)
  82                ;
  83        sb->s_blocksize_bits = bits;
  84        return sb->s_blocksize;
  85}
  86
  87EXPORT_SYMBOL(sb_set_blocksize);
  88
  89int sb_min_blocksize(struct super_block *sb, int size)
  90{
  91        int minsize = bdev_hardsect_size(sb->s_bdev);
  92        if (size < minsize)
  93                size = minsize;
  94        return sb_set_blocksize(sb, size);
  95}
  96
  97EXPORT_SYMBOL(sb_min_blocksize);
  98
  99static int
 100blkdev_get_block(struct inode *inode, sector_t iblock,
 101                struct buffer_head *bh, int create)
 102{
 103        if (iblock >= max_block(inode->i_bdev))
 104                return -EIO;
 105
 106        bh->b_bdev = inode->i_bdev;
 107        bh->b_blocknr = iblock;
 108        set_buffer_mapped(bh);
 109        return 0;
 110}
 111
 112static int
 113blkdev_get_blocks(struct inode *inode, sector_t iblock,
 114                unsigned long max_blocks, struct buffer_head *bh, int create)
 115{
 116        if ((iblock + max_blocks) > max_block(inode->i_bdev))
 117                return -EIO;
 118
 119        bh->b_bdev = inode->i_bdev;
 120        bh->b_blocknr = iblock;
 121        bh->b_size = max_blocks << inode->i_blkbits;
 122        set_buffer_mapped(bh);
 123        return 0;
 124}
 125
 126static int
 127blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 128                        loff_t offset, unsigned long nr_segs)
 129{
 130        struct file *file = iocb->ki_filp;
 131        struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 132
 133        return blockdev_direct_IO(rw, iocb, inode, inode->i_bdev, iov, offset,
 134                                nr_segs, blkdev_get_blocks, NULL);
 135}
 136
 137static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
 138{
 139        return block_write_full_page(page, blkdev_get_block, wbc);
 140}
 141
 142static int blkdev_readpage(struct file * file, struct page * page)
 143{
 144        return block_read_full_page(page, blkdev_get_block);
 145}
 146
 147static int blkdev_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 148{
 149        return block_prepare_write(page, from, to, blkdev_get_block);
 150}
 151
 152static int blkdev_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
 153{
 154        return block_commit_write(page, from, to);
 155}
 156
 157/*
 158 * private llseek:
 159 * for a block special file file->f_dentry->d_inode->i_size is zero
 160 * so we compute the size by hand (just as in block_read/write above)
 161 */
 162static loff_t block_llseek(struct file *file, loff_t offset, int origin)
 163{
 164        struct inode *bd_inode;
 165        loff_t size;
 166        loff_t retval;
 167
 168        bd_inode = file->f_dentry->d_inode->i_bdev->bd_inode;
 169        down(&bd_inode->i_sem);
 170        size = i_size_read(bd_inode);
 171
 172        switch (origin) {
 173                case 2:
 174                        offset += size;
 175                        break;
 176                case 1:
 177                        offset += file->f_pos;
 178        }
 179        retval = -EINVAL;
 180        if (offset >= 0 && offset <= size) {
 181                if (offset != file->f_pos) {
 182                        file->f_pos = offset;
 183                }
 184                retval = offset;
 185        }
 186        up(&bd_inode->i_sem);
 187        return retval;
 188}
 189        
 190/*
 191 *      Filp may be NULL when we are called by an msync of a vma
 192 *      since the vma has no handle.
 193 */
 194 
 195static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
 196{
 197        struct inode * inode = dentry->d_inode;
 198
 199        return sync_blockdev(inode->i_bdev);
 200}
 201
 202/*
 203 * pseudo-fs
 204 */
 205
 206static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 207static kmem_cache_t * bdev_cachep;
 208
 209struct bdev_inode {
 210        struct block_device bdev;
 211        struct inode vfs_inode;
 212};
 213
 214static inline struct bdev_inode *BDEV_I(struct inode *inode)
 215{
 216        return container_of(inode, struct bdev_inode, vfs_inode);
 217}
 218
 219static struct inode *bdev_alloc_inode(struct super_block *sb)
 220{
 221        struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, SLAB_KERNEL);
 222        if (!ei)
 223                return NULL;
 224        return &ei->vfs_inode;
 225}
 226
 227static void bdev_destroy_inode(struct inode *inode)
 228{
 229        kmem_cache_free(bdev_cachep, BDEV_I(inode));
 230}
 231
 232static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
 233{
 234        struct bdev_inode *ei = (struct bdev_inode *) foo;
 235        struct block_device *bdev = &ei->bdev;
 236
 237        if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 238            SLAB_CTOR_CONSTRUCTOR)
 239        {
 240                memset(bdev, 0, sizeof(*bdev));
 241                sema_init(&bdev->bd_sem, 1);
 242                INIT_LIST_HEAD(&bdev->bd_inodes);
 243                INIT_LIST_HEAD(&bdev->bd_list);
 244                inode_init_once(&ei->vfs_inode);
 245        }
 246}
 247
 248static inline void __bd_forget(struct inode *inode)
 249{
 250        list_del_init(&inode->i_devices);
 251        inode->i_bdev = NULL;
 252        inode->i_mapping = &inode->i_data;
 253}
 254
 255static void bdev_clear_inode(struct inode *inode)
 256{
 257        struct block_device *bdev = &BDEV_I(inode)->bdev;
 258        struct list_head *p;
 259        spin_lock(&bdev_lock);
 260        while ( (p = bdev->bd_inodes.next) != &bdev->bd_inodes ) {
 261                __bd_forget(list_entry(p, struct inode, i_devices));
 262        }
 263        list_del_init(&bdev->bd_list);
 264        spin_unlock(&bdev_lock);
 265}
 266
 267static struct super_operations bdev_sops = {
 268        .statfs = simple_statfs,
 269        .alloc_inode = bdev_alloc_inode,
 270        .destroy_inode = bdev_destroy_inode,
 271        .drop_inode = generic_delete_inode,
 272        .clear_inode = bdev_clear_inode,
 273};
 274
 275static struct super_block *bd_get_sb(struct file_system_type *fs_type,
 276        int flags, const char *dev_name, void *data)
 277{
 278        return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576);
 279}
 280
 281static struct file_system_type bd_type = {
 282        .name           = "bdev",
 283        .get_sb         = bd_get_sb,
 284        .kill_sb        = kill_anon_super,
 285};
 286
 287static struct vfsmount *bd_mnt;
 288struct super_block *blockdev_superblock;
 289
 290void __init bdev_cache_init(void)
 291{
 292        int err;
 293        bdev_cachep = kmem_cache_create("bdev_cache",
 294                                        sizeof(struct bdev_inode),
 295                                        0,
 296                                        SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 297                                        init_once,
 298                                        NULL);
 299        if (!bdev_cachep)
 300                panic("Cannot create bdev_cache SLAB cache");
 301        err = register_filesystem(&bd_type);
 302        if (err)
 303                panic("Cannot register bdev pseudo-fs");
 304        bd_mnt = kern_mount(&bd_type);
 305        err = PTR_ERR(bd_mnt);
 306        if (IS_ERR(bd_mnt))
 307                panic("Cannot create bdev pseudo-fs");
 308        blockdev_superblock = bd_mnt->mnt_sb;   /* For writeback */
 309}
 310
 311/*
 312 * Most likely _very_ bad one - but then it's hardly critical for small
 313 * /dev and can be fixed when somebody will need really large one.
 314 * Keep in mind that it will be fed through icache hash function too.
 315 */
 316static inline unsigned long hash(dev_t dev)
 317{
 318        return MAJOR(dev)+MINOR(dev);
 319}
 320
 321static int bdev_test(struct inode *inode, void *data)
 322{
 323        return BDEV_I(inode)->bdev.bd_dev == *(dev_t *)data;
 324}
 325
 326static int bdev_set(struct inode *inode, void *data)
 327{
 328        BDEV_I(inode)->bdev.bd_dev = *(dev_t *)data;
 329        return 0;
 330}
 331
 332static LIST_HEAD(all_bdevs);
 333
 334struct block_device *bdget(dev_t dev)
 335{
 336        struct block_device *bdev;
 337        struct inode *inode;
 338
 339        inode = iget5_locked(bd_mnt->mnt_sb, hash(dev),
 340                        bdev_test, bdev_set, &dev);
 341
 342        if (!inode)
 343                return NULL;
 344
 345        bdev = &BDEV_I(inode)->bdev;
 346
 347        if (inode->i_state & I_NEW) {
 348                bdev->bd_contains = NULL;
 349                bdev->bd_inode = inode;
 350                bdev->bd_block_size = (1 << inode->i_blkbits);
 351                bdev->bd_part_count = 0;
 352                bdev->bd_invalidated = 0;
 353                inode->i_mode = S_IFBLK;
 354                inode->i_rdev = dev;
 355                inode->i_bdev = bdev;
 356                inode->i_data.a_ops = &def_blk_aops;
 357                mapping_set_gfp_mask(&inode->i_data, GFP_USER);
 358                inode->i_data.backing_dev_info = &default_backing_dev_info;
 359                spin_lock(&bdev_lock);
 360                list_add(&bdev->bd_list, &all_bdevs);
 361                spin_unlock(&bdev_lock);
 362                unlock_new_inode(inode);
 363        }
 364        return bdev;
 365}
 366
 367EXPORT_SYMBOL(bdget);
 368
 369long nr_blockdev_pages(void)
 370{
 371        struct list_head *p;
 372        long ret = 0;
 373        spin_lock(&bdev_lock);
 374        list_for_each(p, &all_bdevs) {
 375                struct block_device *bdev;
 376                bdev = list_entry(p, struct block_device, bd_list);
 377                ret += bdev->bd_inode->i_mapping->nrpages;
 378        }
 379        spin_unlock(&bdev_lock);
 380        return ret;
 381}
 382
 383void bdput(struct block_device *bdev)
 384{
 385        iput(bdev->bd_inode);
 386}
 387
 388EXPORT_SYMBOL(bdput);
 389 
 390int bd_acquire(struct inode *inode)
 391{
 392        struct block_device *bdev;
 393        spin_lock(&bdev_lock);
 394        if (inode->i_bdev && igrab(inode->i_bdev->bd_inode)) {
 395                spin_unlock(&bdev_lock);
 396                return 0;
 397        }
 398        spin_unlock(&bdev_lock);
 399        bdev = bdget(inode->i_rdev);
 400        if (!bdev)
 401                return -ENOMEM;
 402        spin_lock(&bdev_lock);
 403        if (inode->i_bdev)
 404                __bd_forget(inode);
 405        inode->i_bdev = bdev;
 406        inode->i_mapping = bdev->bd_inode->i_mapping;
 407        list_add(&inode->i_devices, &bdev->bd_inodes);
 408        spin_unlock(&bdev_lock);
 409        return 0;
 410}
 411
 412/* Call when you free inode */
 413
 414void bd_forget(struct inode *inode)
 415{
 416        spin_lock(&bdev_lock);
 417        if (inode->i_bdev)
 418                __bd_forget(inode);
 419        spin_unlock(&bdev_lock);
 420}
 421
 422int bd_claim(struct block_device *bdev, void *holder)
 423{
 424        int res;
 425        spin_lock(&bdev_lock);
 426
 427        /* first decide result */
 428        if (bdev->bd_holder == holder)
 429                res = 0;         /* already a holder */
 430        else if (bdev->bd_holder != NULL)
 431                res = -EBUSY;    /* held by someone else */
 432        else if (bdev->bd_contains == bdev)
 433                res = 0;         /* is a whole device which isn't held */
 434
 435        else if (bdev->bd_contains->bd_holder == bd_claim)
 436                res = 0;         /* is a partition of a device that is being partitioned */
 437        else if (bdev->bd_contains->bd_holder != NULL)
 438                res = -EBUSY;    /* is a partition of a held device */
 439        else
 440                res = 0;         /* is a partition of an un-held device */
 441
 442        /* now impose change */
 443        if (res==0) {
 444                /* note that for a whole device bd_holders
 445                 * will be incremented twice, and bd_holder will
 446                 * be set to bd_claim before being set to holder
 447                 */
 448                bdev->bd_contains->bd_holders ++;
 449                bdev->bd_contains->bd_holder = bd_claim;
 450                bdev->bd_holders++;
 451                bdev->bd_holder = holder;
 452        }
 453        spin_unlock(&bdev_lock);
 454        return res;
 455}
 456
 457EXPORT_SYMBOL(bd_claim);
 458
 459void bd_release(struct block_device *bdev)
 460{
 461        spin_lock(&bdev_lock);
 462        if (!--bdev->bd_contains->bd_holders)
 463                bdev->bd_contains->bd_holder = NULL;
 464        if (!--bdev->bd_holders)
 465                bdev->bd_holder = NULL;
 466        spin_unlock(&bdev_lock);
 467}
 468
 469EXPORT_SYMBOL(bd_release);
 470
 471/*
 472 * Tries to open block device by device number.  Use it ONLY if you
 473 * really do not have anything better - i.e. when you are behind a
 474 * truly sucky interface and all you are given is a device number.  _Never_
 475 * to be used for internal purposes.  If you ever need it - reconsider
 476 * your API.
 477 */
 478struct block_device *open_by_devnum(dev_t dev, unsigned mode, int kind)
 479{
 480        struct block_device *bdev = bdget(dev);
 481        int err = -ENOMEM;
 482        int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY;
 483        if (bdev)
 484                err = blkdev_get(bdev, mode, flags, kind);
 485        return err ? ERR_PTR(err) : bdev;
 486}
 487
 488EXPORT_SYMBOL(open_by_devnum);
 489
 490/*
 491 * This routine checks whether a removable media has been changed,
 492 * and invalidates all buffer-cache-entries in that case. This
 493 * is a relatively slow routine, so we have to try to minimize using
 494 * it. Thus it is called only upon a 'mount' or 'open'. This
 495 * is the best way of combining speed and utility, I think.
 496 * People changing diskettes in the middle of an operation deserve
 497 * to lose :-)
 498 */
 499int check_disk_change(struct block_device *bdev)
 500{
 501        struct gendisk *disk = bdev->bd_disk;
 502        struct block_device_operations * bdops = disk->fops;
 503
 504        if (!bdops->media_changed)
 505                return 0;
 506        if (!bdops->media_changed(bdev->bd_disk))
 507                return 0;
 508
 509        if (__invalidate_device(bdev, 0))
 510                printk("VFS: busy inodes on changed media.\n");
 511
 512        if (bdops->revalidate_disk)
 513                bdops->revalidate_disk(bdev->bd_disk);
 514        if (bdev->bd_disk->minors > 1)
 515                bdev->bd_invalidated = 1;
 516        return 1;
 517}
 518
 519EXPORT_SYMBOL(check_disk_change);
 520
 521static void bd_set_size(struct block_device *bdev, loff_t size)
 522{
 523        unsigned bsize = bdev_hardsect_size(bdev);
 524        i_size_write(bdev->bd_inode, size);
 525        while (bsize < PAGE_CACHE_SIZE) {
 526                if (size & bsize)
 527                        break;
 528                bsize <<= 1;
 529        }
 530        bdev->bd_block_size = bsize;
 531        bdev->bd_inode->i_blkbits = blksize_bits(bsize);
 532}
 533
 534static int do_open(struct block_device *bdev, struct inode *inode, struct file *file)
 535{
 536        struct module *owner = NULL;
 537        struct gendisk *disk;
 538        int ret = -ENXIO;
 539        int part;
 540
 541        lock_kernel();
 542        disk = get_gendisk(bdev->bd_dev, &part);
 543        if (!disk) {
 544                unlock_kernel();
 545                bdput(bdev);
 546                return ret;
 547        }
 548        owner = disk->fops->owner;
 549
 550        down(&bdev->bd_sem);
 551        if (!bdev->bd_openers) {
 552                bdev->bd_disk = disk;
 553                bdev->bd_contains = bdev;
 554                if (!part) {
 555                        struct backing_dev_info *bdi;
 556                        if (disk->fops->open) {
 557                                ret = disk->fops->open(inode, file);
 558                                if (ret)
 559                                        goto out_first;
 560                        }
 561                        if (!bdev->bd_openers) {
 562                                bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
 563                                bdi = blk_get_backing_dev_info(bdev);
 564                                if (bdi == NULL)
 565                                        bdi = &default_backing_dev_info;
 566                                bdev->bd_inode->i_data.backing_dev_info = bdi;
 567                        }
 568                        if (bdev->bd_invalidated)
 569                                rescan_partitions(disk, bdev);
 570                } else {
 571                        struct hd_struct *p;
 572                        struct block_device *whole;
 573                        whole = bdget_disk(disk, 0);
 574                        ret = -ENOMEM;
 575                        if (!whole)
 576                                goto out_first;
 577                        ret = blkdev_get(whole, file->f_mode, file->f_flags, BDEV_RAW);
 578                        if (ret)
 579                                goto out_first;
 580                        bdev->bd_contains = whole;
 581                        down(&whole->bd_sem);
 582                        whole->bd_part_count++;
 583                        p = disk->part[part - 1];
 584                        bdev->bd_inode->i_data.backing_dev_info =
 585                           whole->bd_inode->i_data.backing_dev_info;
 586                        if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) {
 587                                whole->bd_part_count--;
 588                                up(&whole->bd_sem);
 589                                ret = -ENXIO;
 590                                goto out_first;
 591                        }
 592                        kobject_get(&p->kobj);
 593                        bdev->bd_part = p;
 594                        bd_set_size(bdev, (loff_t) p->nr_sects << 9);
 595                        up(&whole->bd_sem);
 596                }
 597        } else {
 598                put_disk(disk);
 599                module_put(owner);
 600                if (bdev->bd_contains == bdev) {
 601                        if (bdev->bd_disk->fops->open) {
 602                                ret = bdev->bd_disk->fops->open(inode, file);
 603                                if (ret)
 604                                        goto out;
 605                        }
 606                        if (bdev->bd_invalidated)
 607                                rescan_partitions(bdev->bd_disk, bdev);
 608                } else {
 609                        down(&bdev->bd_contains->bd_sem);
 610                        bdev->bd_contains->bd_part_count++;
 611                        up(&bdev->bd_contains->bd_sem);
 612                }
 613        }
 614        bdev->bd_openers++;
 615        up(&bdev->bd_sem);
 616        unlock_kernel();
 617        return 0;
 618
 619out_first:
 620        bdev->bd_disk = NULL;
 621        bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
 622        if (bdev != bdev->bd_contains)
 623                blkdev_put(bdev->bd_contains, BDEV_RAW);
 624        bdev->bd_contains = NULL;
 625        put_disk(disk);
 626        module_put(owner);
 627out:
 628        up(&bdev->bd_sem);
 629        unlock_kernel();
 630        if (ret)
 631                bdput(bdev);
 632        return ret;
 633}
 634
 635int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
 636{
 637        /*
 638         * This crockload is due to bad choice of ->open() type.
 639         * It will go away.
 640         * For now, block device ->open() routine must _not_
 641         * examine anything in 'inode' argument except ->i_rdev.
 642         */
 643        struct file fake_file = {};
 644        struct dentry fake_dentry = {};
 645        fake_file.f_mode = mode;
 646        fake_file.f_flags = flags;
 647        fake_file.f_dentry = &fake_dentry;
 648        fake_dentry.d_inode = bdev->bd_inode;
 649
 650        return do_open(bdev, bdev->bd_inode, &fake_file);
 651}
 652
 653EXPORT_SYMBOL(blkdev_get);
 654
 655int blkdev_open(struct inode * inode, struct file * filp)
 656{
 657        struct block_device *bdev;
 658        int res;
 659
 660        /*
 661         * Preserve backwards compatibility and allow large file access
 662         * even if userspace doesn't ask for it explicitly. Some mkfs
 663         * binary needs it. We might want to drop this workaround
 664         * during an unstable branch.
 665         */
 666        filp->f_flags |= O_LARGEFILE;
 667
 668        bd_acquire(inode);
 669        bdev = inode->i_bdev;
 670
 671        res = do_open(bdev, inode, filp);
 672        if (res)
 673                return res;
 674
 675        if (!(filp->f_flags & O_EXCL) )
 676                return 0;
 677
 678        if (!(res = bd_claim(bdev, filp)))
 679                return 0;
 680
 681        blkdev_put(bdev, BDEV_FILE);
 682        return res;
 683}
 684
 685EXPORT_SYMBOL(blkdev_open);
 686
 687int blkdev_put(struct block_device *bdev, int kind)
 688{
 689        int ret = 0;
 690        struct inode *bd_inode = bdev->bd_inode;
 691        struct gendisk *disk = bdev->bd_disk;
 692
 693        down(&bdev->bd_sem);
 694        lock_kernel();
 695        if (!--bdev->bd_openers) {
 696                switch (kind) {
 697                case BDEV_FILE:
 698                case BDEV_FS:
 699                        sync_blockdev(bd_inode->i_bdev);
 700                        break;
 701                }
 702                kill_bdev(bdev);
 703        }
 704        if (bdev->bd_contains == bdev) {
 705                if (disk->fops->release)
 706                        ret = disk->fops->release(bd_inode, NULL);
 707        } else {
 708                down(&bdev->bd_contains->bd_sem);
 709                bdev->bd_contains->bd_part_count--;
 710                up(&bdev->bd_contains->bd_sem);
 711        }
 712        if (!bdev->bd_openers) {
 713                struct module *owner = disk->fops->owner;
 714
 715                put_disk(disk);
 716                module_put(owner);
 717
 718                if (bdev->bd_contains != bdev) {
 719                        kobject_put(&bdev->bd_part->kobj);
 720                        bdev->bd_part = NULL;
 721                }
 722                bdev->bd_disk = NULL;
 723                bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
 724                if (bdev != bdev->bd_contains) {
 725                        blkdev_put(bdev->bd_contains, BDEV_RAW);
 726                }
 727                bdev->bd_contains = NULL;
 728        }
 729        unlock_kernel();
 730        up(&bdev->bd_sem);
 731        bdput(bdev);
 732        return ret;
 733}
 734
 735EXPORT_SYMBOL(blkdev_put);
 736
 737int blkdev_close(struct inode * inode, struct file * filp)
 738{
 739        if (inode->i_bdev->bd_holder == filp)
 740                bd_release(inode->i_bdev);
 741        return blkdev_put(inode->i_bdev, BDEV_FILE);
 742}
 743
 744static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
 745                                   size_t count, loff_t *ppos)
 746{
 747        struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
 748
 749        return generic_file_write_nolock(file, &local_iov, 1, ppos);
 750}
 751
 752static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
 753                                   size_t count, loff_t pos)
 754{
 755        struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
 756
 757        return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
 758}
 759
 760
 761struct address_space_operations def_blk_aops = {
 762        .readpage       = blkdev_readpage,
 763        .writepage      = blkdev_writepage,
 764        .sync_page      = block_sync_page,
 765        .prepare_write  = blkdev_prepare_write,
 766        .commit_write   = blkdev_commit_write,
 767        .writepages     = generic_writepages,
 768        .direct_IO      = blkdev_direct_IO,
 769};
 770
 771struct file_operations def_blk_fops = {
 772        .open           = blkdev_open,
 773        .release        = blkdev_close,
 774        .llseek         = block_llseek,
 775        .read           = generic_file_read,
 776        .write          = blkdev_file_write,
 777        .aio_read       = generic_file_aio_read,
 778        .aio_write      = blkdev_file_aio_write, 
 779        .mmap           = generic_file_mmap,
 780        .fsync          = block_fsync,
 781        .ioctl          = blkdev_ioctl,
 782        .readv          = generic_file_readv,
 783        .writev         = generic_file_writev,
 784        .sendfile       = generic_file_sendfile,
 785};
 786
 787EXPORT_SYMBOL(def_blk_fops);
 788
 789int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
 790{
 791        int res;
 792        mm_segment_t old_fs = get_fs();
 793        set_fs(KERNEL_DS);
 794        res = blkdev_ioctl(bdev->bd_inode, NULL, cmd, arg);
 795        set_fs(old_fs);
 796        return res;
 797}
 798
 799EXPORT_SYMBOL(ioctl_by_bdev);
 800
 801/**
 802 * lookup_bdev  - lookup a struct block_device by name
 803 *
 804 * @path:       special file representing the block device
 805 *
 806 * Get a reference to the blockdevice at @path in the current
 807 * namespace if possible and return it.  Return ERR_PTR(error)
 808 * otherwise.
 809 */
 810struct block_device *lookup_bdev(const char *path)
 811{
 812        struct block_device *bdev;
 813        struct inode *inode;
 814        struct nameidata nd;
 815        int error;
 816
 817        if (!path || !*path)
 818                return ERR_PTR(-EINVAL);
 819
 820        error = path_lookup(path, LOOKUP_FOLLOW, &nd);
 821        if (error)
 822                return ERR_PTR(error);
 823
 824        inode = nd.dentry->d_inode;
 825        error = -ENOTBLK;
 826        if (!S_ISBLK(inode->i_mode))
 827                goto fail;
 828        error = -EACCES;
 829        if (nd.mnt->mnt_flags & MNT_NODEV)
 830                goto fail;
 831        error = bd_acquire(inode);
 832        if (error)
 833                goto fail;
 834        bdev = inode->i_bdev;
 835
 836out:
 837        path_release(&nd);
 838        return bdev;
 839fail:
 840        bdev = ERR_PTR(error);
 841        goto out;
 842}
 843
 844/**
 845 * open_bdev_excl  -  open a block device by name and set it up for use
 846 *
 847 * @path:       special file representing the block device
 848 * @flags:      %MS_RDONLY for opening read-only
 849 * @kind:       usage (same as the 4th paramter to blkdev_get)
 850 * @holder:     owner for exclusion
 851 *
 852 * Open the blockdevice described by the special file at @path, claim it
 853 * for the @holder and properly set it up for @kind usage.
 854 */
 855struct block_device *open_bdev_excl(const char *path, int flags,
 856                                    int kind, void *holder)
 857{
 858        struct block_device *bdev;
 859        mode_t mode = FMODE_READ;
 860        int error = 0;
 861
 862        bdev = lookup_bdev(path);
 863        if (IS_ERR(bdev))
 864                return bdev;
 865
 866        if (!(flags & MS_RDONLY))
 867                mode |= FMODE_WRITE;
 868        error = blkdev_get(bdev, mode, 0, kind);
 869        if (error)
 870                return ERR_PTR(error);
 871        error = -EACCES;
 872        if (!(flags & MS_RDONLY) && bdev_read_only(bdev))
 873                goto blkdev_put;
 874        error = bd_claim(bdev, holder);
 875        if (error)
 876                goto blkdev_put;
 877
 878        return bdev;
 879        
 880blkdev_put:
 881        blkdev_put(bdev, BDEV_FS);
 882        return ERR_PTR(error);
 883}
 884
 885EXPORT_SYMBOL(open_bdev_excl);
 886
 887/**
 888 * close_bdev_excl  -  release a blockdevice openen by open_bdev_excl()
 889 *
 890 * @bdev:       blockdevice to close
 891 * @kind:       usage (same as the 4th paramter to blkdev_get)
 892 *
 893 * This is the counterpart to open_bdev_excl().
 894 */
 895void close_bdev_excl(struct block_device *bdev, int kind)
 896{
 897        bd_release(bdev);
 898        blkdev_put(bdev, kind);
 899}
 900
 901EXPORT_SYMBOL(close_bdev_excl);
 902
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.