fsl-diu-fb: fix regression with uninitalized fb_info->mm_lock mutex
[safe/jmp/linux-2.6] / fs / qnx4 / inode.c
index 75fc849..681df5f 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/qnx4_fs.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <linux/highuid.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
-#include <linux/vfs.h>
-#include <asm/uaccess.h>
+#include <linux/writeback.h>
+#include <linux/statfs.h>
+#include "qnx4.h"
 
 #define QNX4_VERSION  4
 #define QNX4_BMNAME   ".bitmap"
@@ -34,31 +30,6 @@ static const struct super_operations qnx4_sops;
 
 #ifdef CONFIG_QNX4FS_RW
 
-int qnx4_sync_inode(struct inode *inode)
-{
-       int err = 0;
-# if 0
-       struct buffer_head *bh;
-
-       bh = qnx4_update_inode(inode);
-       if (bh && buffer_dirty(bh))
-       {
-               sync_dirty_buffer(bh);
-               if (buffer_req(bh) && !buffer_uptodate(bh))
-               {
-                       printk ("IO error syncing qnx4 inode [%s:%08lx]\n",
-                               inode->i_sb->s_id, inode->i_ino);
-                       err = -1;
-               }
-               brelse (bh);
-       } else if (!bh) {
-               err = -1;
-       }
-# endif
-
-       return err;
-}
-
 static void qnx4_delete_inode(struct inode *inode)
 {
        QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino));
@@ -70,15 +41,7 @@ static void qnx4_delete_inode(struct inode *inode)
        unlock_kernel();
 }
 
-static void qnx4_write_super(struct super_block *sb)
-{
-       lock_kernel();
-       QNX4DEBUG(("qnx4: write_super\n"));
-       sb->s_dirt = 0;
-       unlock_kernel();
-}
-
-static int qnx4_write_inode(struct inode *inode, int unused)
+static int qnx4_write_inode(struct inode *inode, int do_sync)
 {
        struct qnx4_inode_entry *raw_inode;
        int block, ino;
@@ -115,6 +78,16 @@ static int qnx4_write_inode(struct inode *inode, int unused)
        raw_inode->di_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
        raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks);
        mark_buffer_dirty(bh);
+       if (do_sync) {
+               sync_dirty_buffer(bh);
+               if (buffer_req(bh) && !buffer_uptodate(bh)) {
+                       printk("qnx4: IO error syncing inode [%s:%08x]\n",
+                                       inode->i_sb->s_id, ino);
+                       brelse(bh);
+                       unlock_kernel();
+                       return -EIO;
+               }
+       }
        brelse(bh);
        unlock_kernel();
        return 0;
@@ -125,7 +98,6 @@ static int qnx4_write_inode(struct inode *inode, int unused)
 static void qnx4_put_super(struct super_block *sb);
 static struct inode *qnx4_alloc_inode(struct super_block *sb);
 static void qnx4_destroy_inode(struct inode *inode);
-static void qnx4_read_inode(struct inode *);
 static int qnx4_remount(struct super_block *sb, int *flags, char *data);
 static int qnx4_statfs(struct dentry *, struct kstatfs *);
 
@@ -133,14 +105,12 @@ static const struct super_operations qnx4_sops =
 {
        .alloc_inode    = qnx4_alloc_inode,
        .destroy_inode  = qnx4_destroy_inode,
-       .read_inode     = qnx4_read_inode,
        .put_super      = qnx4_put_super,
        .statfs         = qnx4_statfs,
        .remount_fs     = qnx4_remount,
 #ifdef CONFIG_QNX4FS_RW
        .write_inode    = qnx4_write_inode,
        .delete_inode   = qnx4_delete_inode,
-       .write_super    = qnx4_write_super,
 #endif
 };
 
@@ -284,6 +254,7 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
 static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
+       u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
        lock_kernel();
 
@@ -293,6 +264,8 @@ static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_bfree   = qnx4_count_free_blocks(sb);
        buf->f_bavail  = buf->f_bfree;
        buf->f_namelen = QNX4_NAME_MAX;
+       buf->f_fsid.val[0] = (u32)id;
+       buf->f_fsid.val[1] = (u32)(id >> 32);
 
        unlock_kernel();
 
@@ -357,6 +330,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
        struct inode *root;
        const char *errmsg;
        struct qnx4_sb_info *qs;
+       int ret = -EINVAL;
 
        qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);
        if (!qs)
@@ -396,12 +370,14 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
        }
 
        /* does root not have inode number QNX4_ROOT_INO ?? */
-       root = iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
-       if (!root) {
+       root = qnx4_iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
+       if (IS_ERR(root)) {
                printk("qnx4: get inode failed\n");
+               ret = PTR_ERR(root);
                goto out;
        }
 
+       ret = -ENOMEM;
        s->s_root = d_alloc_root(root);
        if (s->s_root == NULL)
                goto outi;
@@ -417,7 +393,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
       outnobh:
        kfree(qs);
        s->s_fs_info = NULL;
-       return -EINVAL;
+       return ret;
 }
 
 static void qnx4_put_super(struct super_block *sb)
@@ -433,16 +409,21 @@ static int qnx4_writepage(struct page *page, struct writeback_control *wbc)
 {
        return block_write_full_page(page,qnx4_get_block, wbc);
 }
+
 static int qnx4_readpage(struct file *file, struct page *page)
 {
        return block_read_full_page(page,qnx4_get_block);
 }
-static int qnx4_prepare_write(struct file *file, struct page *page,
-                             unsigned from, unsigned to)
+
+static int qnx4_write_begin(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata)
 {
-       struct qnx4_inode_info *qnx4_inode = qnx4_i(page->mapping->host);
-       return cont_prepare_write(page, from, to, qnx4_get_block,
-                                 &qnx4_inode->mmu_private);
+       struct qnx4_inode_info *qnx4_inode = qnx4_i(mapping->host);
+       *pagep = NULL;
+       return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+                               qnx4_get_block,
+                               &qnx4_inode->mmu_private);
 }
 static sector_t qnx4_bmap(struct address_space *mapping, sector_t block)
 {
@@ -452,34 +433,43 @@ static const struct address_space_operations qnx4_aops = {
        .readpage       = qnx4_readpage,
        .writepage      = qnx4_writepage,
        .sync_page      = block_sync_page,
-       .prepare_write  = qnx4_prepare_write,
-       .commit_write   = generic_commit_write,
+       .write_begin    = qnx4_write_begin,
+       .write_end      = generic_write_end,
        .bmap           = qnx4_bmap
 };
 
-static void qnx4_read_inode(struct inode *inode)
+struct inode *qnx4_iget(struct super_block *sb, unsigned long ino)
 {
        struct buffer_head *bh;
        struct qnx4_inode_entry *raw_inode;
-       int block, ino;
-       struct super_block *sb = inode->i_sb;
-       struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);
+       int block;
+       struct qnx4_inode_entry *qnx4_inode;
+       struct inode *inode;
 
-       ino = inode->i_ino;
+       inode = iget_locked(sb, ino);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+       if (!(inode->i_state & I_NEW))
+               return inode;
+
+       qnx4_inode = qnx4_raw_inode(inode);
        inode->i_mode = 0;
 
        QNX4DEBUG(("Reading inode : [%d]\n", ino));
        if (!ino) {
-               printk("qnx4: bad inode number on dev %s: %d is out of range\n",
+               printk(KERN_ERR "qnx4: bad inode number on dev %s: %lu is "
+                               "out of range\n",
                       sb->s_id, ino);
-               return;
+               iget_failed(inode);
+               return ERR_PTR(-EIO);
        }
        block = ino / QNX4_INODES_PER_BLOCK;
 
        if (!(bh = sb_bread(sb, block))) {
                printk("qnx4: major problem: unable to read inode from dev "
                       "%s\n", sb->s_id);
-               return;
+               iget_failed(inode);
+               return ERR_PTR(-EIO);
        }
        raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
            (ino % QNX4_INODES_PER_BLOCK);
@@ -510,9 +500,16 @@ static void qnx4_read_inode(struct inode *inode)
                inode->i_op = &page_symlink_inode_operations;
                inode->i_mapping->a_ops = &qnx4_aops;
                qnx4_i(inode)->mmu_private = inode->i_size;
-       } else
-               printk("qnx4: bad inode %d on dev %s\n",ino,sb->s_id);
+       } else {
+               printk(KERN_ERR "qnx4: bad inode %lu on dev %s\n",
+                       ino, sb->s_id);
+               iget_failed(inode);
+               brelse(bh);
+               return ERR_PTR(-EIO);
+       }
        brelse(bh);
+       unlock_new_inode(inode);
+       return inode;
 }
 
 static struct kmem_cache *qnx4_inode_cachep;
@@ -531,13 +528,11 @@ static void qnx4_destroy_inode(struct inode *inode)
        kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode));
 }
 
-static void init_once(void *foo, struct kmem_cache * cachep,
-                     unsigned long flags)
+static void init_once(void *foo)
 {
        struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo;
 
-       if (flags & SLAB_CTOR_CONSTRUCTOR)
-               inode_init_once(&ei->vfs_inode);
+       inode_init_once(&ei->vfs_inode);
 }
 
 static int init_inodecache(void)
@@ -546,7 +541,7 @@ static int init_inodecache(void)
                                             sizeof(struct qnx4_inode_info),
                                             0, (SLAB_RECLAIM_ACCOUNT|
                                                SLAB_MEM_SPREAD),
-                                            init_once, NULL);
+                                            init_once);
        if (qnx4_inode_cachep == NULL)
                return -ENOMEM;
        return 0;