Embed a struct path into struct nameidata instead of nd->{dentry,mnt}
[safe/jmp/linux-2.6] / fs / block_dev.c
index fc7028b..5f4721f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/mount.h>
 #include <linux/uio.h>
 #include <linux/namei.h>
+#include <linux/log2.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -55,17 +56,19 @@ static sector_t max_block(struct block_device *bdev)
        return retval;
 }
 
-/* Kill _all_ buffers, dirty or not.. */
+/* Kill _all_ buffers and pagecache , dirty or not.. */
 static void kill_bdev(struct block_device *bdev)
 {
-       invalidate_bdev(bdev, 1);
+       if (bdev->bd_inode->i_mapping->nrpages == 0)
+               return;
+       invalidate_bh_lrus();
        truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
 }      
 
 int set_blocksize(struct block_device *bdev, int size)
 {
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
-       if (size > PAGE_SIZE || size < 512 || (size & (size-1)))
+       if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
                return -EINVAL;
 
        /* Size cannot be smaller than the size supported by the device */
@@ -169,7 +172,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 }
 
 #if 0
-static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error)
+static void blk_end_aio(struct bio *bio, int error)
 {
        struct kiocb *iocb = bio->bi_private;
        atomic_t *bio_count = &iocb->ki_bio_count;
@@ -375,14 +378,26 @@ static int blkdev_readpage(struct file * file, struct page * page)
        return block_read_full_page(page, blkdev_get_block);
 }
 
-static int blkdev_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int blkdev_write_begin(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata)
 {
-       return block_prepare_write(page, from, to, blkdev_get_block);
+       *pagep = NULL;
+       return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+                               blkdev_get_block);
 }
 
-static int blkdev_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int blkdev_write_end(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned copied,
+                       struct page *page, void *fsdata)
 {
-       return block_commit_write(page, from, to);
+       int ret;
+       ret = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+
+       unlock_page(page);
+       page_cache_release(page);
+
+       return ret;
 }
 
 /*
@@ -450,24 +465,20 @@ static void bdev_destroy_inode(struct inode *inode)
        kmem_cache_free(bdev_cachep, bdi);
 }
 
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
 {
        struct bdev_inode *ei = (struct bdev_inode *) foo;
        struct block_device *bdev = &ei->bdev;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
-       {
-               memset(bdev, 0, sizeof(*bdev));
-               mutex_init(&bdev->bd_mutex);
-               sema_init(&bdev->bd_mount_sem, 1);
-               INIT_LIST_HEAD(&bdev->bd_inodes);
-               INIT_LIST_HEAD(&bdev->bd_list);
+       memset(bdev, 0, sizeof(*bdev));
+       mutex_init(&bdev->bd_mutex);
+       sema_init(&bdev->bd_mount_sem, 1);
+       INIT_LIST_HEAD(&bdev->bd_inodes);
+       INIT_LIST_HEAD(&bdev->bd_list);
 #ifdef CONFIG_SYSFS
-               INIT_LIST_HEAD(&bdev->bd_holder_list);
+       INIT_LIST_HEAD(&bdev->bd_holder_list);
 #endif
-               inode_init_once(&ei->vfs_inode);
-       }
+       inode_init_once(&ei->vfs_inode);
 }
 
 static inline void __bd_forget(struct inode *inode)
@@ -489,7 +500,7 @@ static void bdev_clear_inode(struct inode *inode)
        spin_unlock(&bdev_lock);
 }
 
-static struct super_operations bdev_sops = {
+static const struct super_operations bdev_sops = {
        .statfs = simple_statfs,
        .alloc_inode = bdev_alloc_inode,
        .destroy_inode = bdev_destroy_inode,
@@ -518,12 +529,11 @@ void __init bdev_cache_init(void)
        bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
                        0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
                                SLAB_MEM_SPREAD|SLAB_PANIC),
-                       init_once, NULL);
+                       init_once);
        err = register_filesystem(&bd_type);
        if (err)
                panic("Cannot register bdev pseudo-fs");
        bd_mnt = kern_mount(&bd_type);
-       err = PTR_ERR(bd_mnt);
        if (IS_ERR(bd_mnt))
                panic("Cannot create bdev pseudo-fs");
        blockdev_superblock = bd_mnt->mnt_sb;   /* For writeback */
@@ -589,12 +599,10 @@ EXPORT_SYMBOL(bdget);
 
 long nr_blockdev_pages(void)
 {
-       struct list_head *p;
+       struct block_device *bdev;
        long ret = 0;
        spin_lock(&bdev_lock);
-       list_for_each(p, &all_bdevs) {
-               struct block_device *bdev;
-               bdev = list_entry(p, struct block_device, bd_list);
+       list_for_each_entry(bdev, &all_bdevs, bd_list) {
                ret += bdev->bd_inode->i_mapping->nrpages;
        }
        spin_unlock(&bdev_lock);
@@ -729,9 +737,9 @@ EXPORT_SYMBOL(bd_release);
 static struct kobject *bdev_get_kobj(struct block_device *bdev)
 {
        if (bdev->bd_contains != bdev)
-               return kobject_get(&bdev->bd_part->kobj);
+               return kobject_get(&bdev->bd_part->dev.kobj);
        else
-               return kobject_get(&bdev->bd_disk->kobj);
+               return kobject_get(&bdev->bd_disk->dev.kobj);
 }
 
 static struct kobject *bdev_get_holder(struct block_device *bdev)
@@ -875,7 +883,7 @@ static struct bd_holder *find_bd_holder(struct block_device *bdev,
  */
 static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
 {
-       int ret;
+       int err;
 
        if (!bo)
                return -EINVAL;
@@ -883,15 +891,18 @@ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
        if (!bd_holder_grab_dirs(bdev, bo))
                return -EBUSY;
 
-       ret = add_symlink(bo->sdir, bo->sdev);
-       if (ret == 0) {
-               ret = add_symlink(bo->hdir, bo->hdev);
-               if (ret)
-                       del_symlink(bo->sdir, bo->sdev);
+       err = add_symlink(bo->sdir, bo->sdev);
+       if (err)
+               return err;
+
+       err = add_symlink(bo->hdir, bo->hdev);
+       if (err) {
+               del_symlink(bo->sdir, bo->sdev);
+               return err;
        }
-       if (ret == 0)
-               list_add_tail(&bo->list, &bdev->bd_holder_list);
-       return ret;
+
+       list_add_tail(&bo->list, &bdev->bd_holder_list);
+       return 0;
 }
 
 /**
@@ -949,7 +960,7 @@ static struct bd_holder *del_bd_holder(struct block_device *bdev,
 static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
                                struct kobject *kobj)
 {
-       int res;
+       int err;
        struct bd_holder *bo, *found;
 
        if (!kobj)
@@ -960,21 +971,24 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
                return -ENOMEM;
 
        mutex_lock(&bdev->bd_mutex);
-       res = bd_claim(bdev, holder);
-       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);
+       err = bd_claim(bdev, holder);
+       if (err)
+               goto fail;
 
-       return res;
+       found = find_bd_holder(bdev, bo);
+       if (found)
+               goto fail;
+
+       err = add_bd_holder(bdev, bo);
+       if (err)
+               bd_release(bdev);
+       else
+               bo = NULL;
+fail:
+       mutex_unlock(&bdev->bd_mutex);
+       free_bd_holder(bo);
+       return err;
 }
 
 /**
@@ -988,15 +1002,12 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
 static void bd_release_from_kobject(struct block_device *bdev,
                                        struct kobject *kobj)
 {
-       struct bd_holder *bo;
-
        if (!kobj)
                return;
 
        mutex_lock(&bdev->bd_mutex);
        bd_release(bdev);
-       if ((bo = del_bd_holder(bdev, kobj)))
-               free_bd_holder(bo);
+       free_bd_holder(del_bd_holder(bdev, kobj));
        mutex_unlock(&bdev->bd_mutex);
 }
 
@@ -1101,6 +1112,13 @@ static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
                        int for_part);
 static int __blkdev_put(struct block_device *bdev, int for_part);
 
+/*
+ * bd_mutex locking:
+ *
+ *  mutex_lock(part->bd_mutex)
+ *    mutex_lock_nested(whole->bd_mutex, 1)
+ */
+
 static int do_open(struct block_device *bdev, struct file *file, int for_part)
 {
        struct module *owner = NULL;
@@ -1157,7 +1175,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part)
                                ret = -ENXIO;
                                goto out_first;
                        }
-                       kobject_get(&p->kobj);
+                       kobject_get(&p->dev.kobj);
                        bdev->bd_part = p;
                        bd_set_size(bdev, (loff_t) p->nr_sects << 9);
                }
@@ -1280,7 +1298,7 @@ static int __blkdev_put(struct block_device *bdev, int for_part)
                module_put(owner);
 
                if (bdev->bd_contains != bdev) {
-                       kobject_put(&bdev->bd_part->kobj);
+                       kobject_put(&bdev->bd_part->dev.kobj);
                        bdev->bd_part = NULL;
                }
                bdev->bd_disk = NULL;
@@ -1320,8 +1338,8 @@ const struct address_space_operations def_blk_aops = {
        .readpage       = blkdev_readpage,
        .writepage      = blkdev_writepage,
        .sync_page      = block_sync_page,
-       .prepare_write  = blkdev_prepare_write,
-       .commit_write   = blkdev_commit_write,
+       .write_begin    = blkdev_write_begin,
+       .write_end      = blkdev_write_end,
        .writepages     = generic_writepages,
        .direct_IO      = blkdev_direct_IO,
 };
@@ -1340,7 +1358,6 @@ const struct file_operations def_blk_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .sendfile       = generic_file_sendfile,
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
 };
@@ -1380,12 +1397,12 @@ struct block_device *lookup_bdev(const char *path)
        if (error)
                return ERR_PTR(error);
 
-       inode = nd.dentry->d_inode;
+       inode = nd.path.dentry->d_inode;
        error = -ENOTBLK;
        if (!S_ISBLK(inode->i_mode))
                goto fail;
        error = -EACCES;
-       if (nd.mnt->mnt_flags & MNT_NODEV)
+       if (nd.path.mnt->mnt_flags & MNT_NODEV)
                goto fail;
        error = -ENOMEM;
        bdev = bd_acquire(inode);
@@ -1471,7 +1488,7 @@ int __invalidate_device(struct block_device *bdev)
                res = invalidate_inodes(sb);
                drop_super(sb);
        }
-       invalidate_bdev(bdev, 0);
+       invalidate_bdev(bdev);
        return res;
 }
 EXPORT_SYMBOL(__invalidate_device);