mm: remove destroy_dirty_buffers from invalidate_bdev()
[linux-2.6.git] / fs / ext3 / super.c
index 7c45acf..4266b70 100644 (file)
@@ -16,7 +16,6 @@
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
@@ -46,7 +45,7 @@
 static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
                             unsigned long journal_devnum);
 static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
-                              int);
+                              unsigned int);
 static void ext3_commit_super (struct super_block * sb,
                               struct ext3_super_block * es,
                               int sync);
@@ -58,18 +57,18 @@ static int ext3_sync_fs(struct super_block *sb, int wait);
 static const char *ext3_decode_error(struct super_block * sb, int errno,
                                     char nbuf[16]);
 static int ext3_remount (struct super_block * sb, int * flags, char * data);
-static int ext3_statfs (struct super_block * sb, struct kstatfs * buf);
+static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
 static void ext3_unlockfs(struct super_block *sb);
 static void ext3_write_super (struct super_block * sb);
 static void ext3_write_super_lockfs(struct super_block *sb);
 
-/* 
+/*
  * Wrappers for journal_start/end.
  *
  * The only special thing we need to do here is to make sure that all
  * journal_end calls result in the superblock being marked dirty, so
  * that sync() will call the filesystem's write_super callback if
- * appropriate. 
+ * appropriate.
  */
 handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
 {
@@ -91,11 +90,11 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
        return journal_start(journal, nblocks);
 }
 
-/* 
+/*
  * The only special thing we need to do here is to make sure that all
  * journal_stop calls result in the superblock being marked dirty, so
  * that sync() will call the filesystem's write_super callback if
- * appropriate. 
+ * appropriate.
  */
 int __ext3_journal_stop(const char *where, handle_t *handle)
 {
@@ -160,20 +159,21 @@ static void ext3_handle_error(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return;
 
-       if (test_opt (sb, ERRORS_RO)) {
-               printk (KERN_CRIT "Remounting filesystem read-only\n");
-               sb->s_flags |= MS_RDONLY;
-       } else {
+       if (!test_opt (sb, ERRORS_CONT)) {
                journal_t *journal = EXT3_SB(sb)->s_journal;
 
                EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
                if (journal)
                        journal_abort(journal, -EIO);
        }
+       if (test_opt (sb, ERRORS_RO)) {
+               printk (KERN_CRIT "Remounting filesystem read-only\n");
+               sb->s_flags |= MS_RDONLY;
+       }
+       ext3_commit_super(sb, es, 1);
        if (test_opt(sb, ERRORS_PANIC))
                panic("EXT3-fs (device %s): panic forced after error\n",
                        sb->s_id);
-       ext3_commit_super(sb, es, 1);
 }
 
 void ext3_error (struct super_block * sb, const char * function,
@@ -370,16 +370,16 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
 {
        struct list_head *l;
 
-       printk(KERN_ERR "sb orphan head is %d\n", 
+       printk(KERN_ERR "sb orphan head is %d\n",
               le32_to_cpu(sbi->s_es->s_last_orphan));
 
        printk(KERN_ERR "sb_info orphan list:\n");
        list_for_each(l, &sbi->s_orphan) {
                struct inode *inode = orphan_list_entry(l);
                printk(KERN_ERR "  "
-                      "inode %s:%ld at %p: mode %o, nlink %d, next %d\n",
+                      "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
                       inode->i_sb->s_id, inode->i_ino, inode,
-                      inode->i_mode, inode->i_nlink, 
+                      inode->i_mode, inode->i_nlink,
                       NEXT_ORPHAN(inode));
        }
 }
@@ -420,7 +420,7 @@ static void ext3_put_super (struct super_block * sb)
                dump_orphan_list(sb, sbi);
        J_ASSERT(list_empty(&sbi->s_orphan));
 
-       invalidate_bdev(sb->s_bdev, 0);
+       invalidate_bdev(sb->s_bdev);
        if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
                /*
                 * Invalidate the journal device's buffers.  We don't want them
@@ -428,7 +428,7 @@ static void ext3_put_super (struct super_block * sb)
                 * hotswapped, and it breaks the `ro-after' testing code.
                 */
                sync_blockdev(sbi->journal_bdev);
-               invalidate_bdev(sbi->journal_bdev, 0);
+               invalidate_bdev(sbi->journal_bdev);
                ext3_blkdev_remove(sbi);
        }
        sb->s_fs_info = NULL;
@@ -436,7 +436,7 @@ static void ext3_put_super (struct super_block * sb)
        return;
 }
 
-static kmem_cache_t *ext3_inode_cachep;
+static struct kmem_cache *ext3_inode_cachep;
 
 /*
  * Called inside transaction, so use GFP_NOFS
@@ -445,7 +445,7 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
 {
        struct ext3_inode_info *ei;
 
-       ei = kmem_cache_alloc(ext3_inode_cachep, SLAB_NOFS);
+       ei = kmem_cache_alloc(ext3_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
@@ -462,7 +462,7 @@ static void ext3_destroy_inode(struct inode *inode)
        kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct ext3_inode_info *ei = (struct ext3_inode_info *) foo;
 
@@ -472,16 +472,17 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
 #ifdef CONFIG_EXT3_FS_XATTR
                init_rwsem(&ei->xattr_sem);
 #endif
-               init_MUTEX(&ei->truncate_sem);
+               mutex_init(&ei->truncate_mutex);
                inode_init_once(&ei->vfs_inode);
        }
 }
+
 static int init_inodecache(void)
 {
        ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
                                             sizeof(struct ext3_inode_info),
-                                            0, SLAB_RECLAIM_ACCOUNT,
+                                            0, (SLAB_RECLAIM_ACCOUNT|
+                                               SLAB_MEM_SPREAD),
                                             init_once, NULL);
        if (ext3_inode_cachep == NULL)
                return -ENOMEM;
@@ -490,28 +491,28 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ext3_inode_cachep))
-               printk(KERN_INFO "ext3_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ext3_inode_cachep);
 }
 
 static void ext3_clear_inode(struct inode *inode)
 {
        struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
-       if (EXT3_I(inode)->i_acl &&
-           EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) {
-               posix_acl_release(EXT3_I(inode)->i_acl);
-               EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED;
-       }
-       if (EXT3_I(inode)->i_default_acl &&
-           EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) {
-               posix_acl_release(EXT3_I(inode)->i_default_acl);
-               EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED;
-       }
+       if (EXT3_I(inode)->i_acl &&
+                       EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) {
+               posix_acl_release(EXT3_I(inode)->i_acl);
+               EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED;
+       }
+       if (EXT3_I(inode)->i_default_acl &&
+                       EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) {
+               posix_acl_release(EXT3_I(inode)->i_default_acl);
+               EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED;
+       }
 #endif
        ext3_discard_reservation(inode);
        EXT3_I(inode)->i_block_alloc_info = NULL;
-       kfree(rsv);
+       if (unlikely(rsv))
+               kfree(rsv);
 }
 
 static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb)
@@ -553,6 +554,47 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
        return 0;
 }
 
+
+static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp)
+{
+       __u32 *objp = vobjp;
+       unsigned long ino = objp[0];
+       __u32 generation = objp[1];
+       struct inode *inode;
+       struct dentry *result;
+
+       if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO)
+               return ERR_PTR(-ESTALE);
+       if (ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count))
+               return ERR_PTR(-ESTALE);
+
+       /* iget isn't really right if the inode is currently unallocated!!
+        *
+        * ext3_read_inode will return a bad_inode if the inode had been
+        * deleted, so we should be safe.
+        *
+        * Currently we don't know the generation for parent directory, so
+        * a generation of 0 means "accept any"
+        */
+       inode = iget(sb, ino);
+       if (inode == NULL)
+               return ERR_PTR(-ENOMEM);
+       if (is_bad_inode(inode) ||
+           (generation && inode->i_generation != generation)) {
+               iput(inode);
+               return ERR_PTR(-ESTALE);
+       }
+       /* now to find a dentry.
+        * If possible, get a well-connected one
+        */
+       result = d_alloc_anon(inode);
+       if (!result) {
+               iput(inode);
+               return ERR_PTR(-ENOMEM);
+       }
+       return result;
+}
+
 #ifdef CONFIG_QUOTA
 #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
 #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
@@ -597,7 +639,7 @@ static struct quotactl_ops ext3_qctl_operations = {
 };
 #endif
 
-static struct super_operations ext3_sops = {
+static const struct super_operations ext3_sops = {
        .alloc_inode    = ext3_alloc_inode,
        .destroy_inode  = ext3_destroy_inode,
        .read_inode     = ext3_read_inode,
@@ -621,6 +663,7 @@ static struct super_operations ext3_sops = {
 
 static struct export_operations ext3_export_ops = {
        .get_parent = ext3_get_parent,
+       .get_dentry = ext3_get_dentry,
 };
 
 enum {
@@ -628,7 +671,7 @@ enum {
        Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
        Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
        Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
-       Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh,
+       Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
        Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
@@ -664,6 +707,7 @@ static match_table_t tokens = {
        {Opt_noreservation, "noreservation"},
        {Opt_noload, "noload"},
        {Opt_nobh, "nobh"},
+       {Opt_bh, "bh"},
        {Opt_commit, "commit=%u"},
        {Opt_journal_update, "journal=update"},
        {Opt_journal_inum, "journal=%u"},
@@ -687,14 +731,15 @@ static match_table_t tokens = {
        {Opt_resize, "resize"},
 };
 
-static unsigned long get_sb_block(void **data)
+static ext3_fsblk_t get_sb_block(void **data)
 {
-       unsigned long   sb_block;
-       char            *options = (char *) *data;
+       ext3_fsblk_t    sb_block;
+       char            *options = (char *) *data;
 
        if (!options || strncmp(options, "sb=", 3) != 0)
                return 1;       /* Default location */
        options += 3;
+       /*todo: use simple_strtoll with >32bit ext3 */
        sb_block = simple_strtoul(options, &options, 0);
        if (*options && *options != ',') {
                printk("EXT3-fs: Invalid sb specification: %s\n",
@@ -708,8 +753,8 @@ static unsigned long get_sb_block(void **data)
 }
 
 static int parse_options (char *options, struct super_block *sb,
-                         unsigned long *inum, unsigned long *journal_devnum,
-                         unsigned long *n_blocks_count, int is_remount)
+                         unsigned int *inum, unsigned long *journal_devnum,
+                         ext3_fsblk_t *n_blocks_count, int is_remount)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
        char * p;
@@ -1011,6 +1056,9 @@ clear_qf_name:
                case Opt_nobh:
                        set_opt(sbi->s_mount_opt, NOBH);
                        break;
+               case Opt_bh:
+                       clear_opt(sbi->s_mount_opt, NOBH);
+                       break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
@@ -1126,7 +1174,8 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
 static int ext3_check_descriptors (struct super_block * sb)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
-       unsigned long block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       ext3_fsblk_t last_block;
        struct ext3_group_desc * gdp = NULL;
        int desc_block = 0;
        int i;
@@ -1135,12 +1184,17 @@ static int ext3_check_descriptors (struct super_block * sb)
 
        for (i = 0; i < sbi->s_groups_count; i++)
        {
+               if (i == sbi->s_groups_count - 1)
+                       last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+               else
+                       last_block = first_block +
+                               (EXT3_BLOCKS_PER_GROUP(sb) - 1);
+
                if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext3_group_desc *)
                                        sbi->s_group_desc[desc_block++]->b_data;
-               if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_block_bitmap) >=
-                               block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_block_bitmap) > last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Block bitmap for group %d"
@@ -1149,9 +1203,8 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_block_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_inode_bitmap) >=
-                               block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Inode bitmap for group %d"
@@ -1160,9 +1213,9 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_inode_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_table) < block ||
-                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
-                   block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
+                   last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Inode table for group %d"
@@ -1171,7 +1224,7 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_inode_table));
                        return 0;
                }
-               block += EXT3_BLOCKS_PER_GROUP(sb);
+               first_block += EXT3_BLOCKS_PER_GROUP(sb);
                gdp++;
        }
 
@@ -1211,6 +1264,12 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                return;
        }
 
+       if (bdev_read_only(sb->s_bdev)) {
+               printk(KERN_ERR "EXT3-fs: write access "
+                       "unavailable, skipping orphan cleanup.\n");
+               return;
+       }
+
        if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
                if (es->s_last_orphan)
                        jbd_debug(1, "Errors on filesystem, "
@@ -1253,17 +1312,17 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                DQUOT_INIT(inode);
                if (inode->i_nlink) {
                        printk(KERN_DEBUG
-                               "%s: truncating inode %ld to %Ld bytes\n",
+                               "%s: truncating inode %lu to %Ld bytes\n",
                                __FUNCTION__, inode->i_ino, inode->i_size);
-                       jbd_debug(2, "truncating inode %ld to %Ld bytes\n",
+                       jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
                                  inode->i_ino, inode->i_size);
                        ext3_truncate(inode);
                        nr_truncates++;
                } else {
                        printk(KERN_DEBUG
-                               "%s: deleting unreferenced inode %ld\n",
+                               "%s: deleting unreferenced inode %lu\n",
                                __FUNCTION__, inode->i_ino);
-                       jbd_debug(2, "deleting unreferenced inode %ld\n",
+                       jbd_debug(2, "deleting unreferenced inode %lu\n",
                                  inode->i_ino);
                        nr_orphans++;
                }
@@ -1288,8 +1347,6 @@ static void ext3_orphan_cleanup (struct super_block * sb,
        sb->s_flags = s_flags; /* Restore MS_RDONLY status */
 }
 
-#define log2(n) ffz(~(n))
-
 /*
  * Maximal file size.  There is a direct, and {,double-,triple-}indirect
  * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
@@ -1313,15 +1370,14 @@ static loff_t ext3_max_size(int bits)
        return res;
 }
 
-static unsigned long descriptor_loc(struct super_block *sb,
-                                   unsigned long logic_sb_block,
+static ext3_fsblk_t descriptor_loc(struct super_block *sb,
+                                   ext3_fsblk_t logic_sb_block,
                                    int nr)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
-       unsigned long bg, first_data_block, first_meta_bg;
+       unsigned long bg, first_meta_bg;
        int has_super = 0;
 
-       first_data_block = le32_to_cpu(sbi->s_es->s_first_data_block);
        first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
 
        if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_META_BG) ||
@@ -1330,7 +1386,7 @@ static unsigned long descriptor_loc(struct super_block *sb,
        bg = sbi->s_desc_per_block * nr;
        if (ext3_bg_has_super(sb, bg))
                has_super = 1;
-       return (first_data_block + has_super + (bg * sbi->s_blocks_per_group));
+       return (has_super + ext3_group_first_block_no(sb, bg));
 }
 
 
@@ -1339,11 +1395,11 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        struct buffer_head * bh;
        struct ext3_super_block *es = NULL;
        struct ext3_sb_info *sbi;
-       unsigned long block;
-       unsigned long sb_block = get_sb_block(&data);
-       unsigned long logic_sb_block;
+       ext3_fsblk_t block;
+       ext3_fsblk_t sb_block = get_sb_block(&data);
+       ext3_fsblk_t logic_sb_block;
        unsigned long offset = 0;
-       unsigned long journal_inum = 0;
+       unsigned int journal_inum = 0;
        unsigned long journal_devnum = 0;
        unsigned long def_mount_opts;
        struct inode *root;
@@ -1354,11 +1410,10 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        int needs_recovery;
        __le32 features;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
        sbi->s_mount_opt = 0;
        sbi->s_resuid = EXT3_DEF_RESUID;
        sbi->s_resgid = EXT3_DEF_RESGID;
@@ -1404,10 +1459,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                set_opt(sbi->s_mount_opt, GRPID);
        if (def_mount_opts & EXT3_DEFM_UID16)
                set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT3_FS_XATTR
        if (def_mount_opts & EXT3_DEFM_XATTR_USER)
                set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT3_FS_POSIX_ACL
        if (def_mount_opts & EXT3_DEFM_ACL)
                set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
        if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_DATA)
                sbi->s_mount_opt |= EXT3_MOUNT_JOURNAL_DATA;
        else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_ORDERED)
@@ -1419,6 +1478,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                set_opt(sbi->s_mount_opt, ERRORS_PANIC);
        else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_RO)
                set_opt(sbi->s_mount_opt, ERRORS_RO);
+       else
+               set_opt(sbi->s_mount_opt, ERRORS_CONT);
 
        sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
        sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
@@ -1436,7 +1497,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
            (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||
             EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
             EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U)))
-               printk(KERN_WARNING 
+               printk(KERN_WARNING
                       "EXT3-fs warning: feature flags set on rev 0 fs, "
                       "running e2fsck is recommended\n");
        /*
@@ -1462,7 +1523,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        if (blocksize < EXT3_MIN_BLOCK_SIZE ||
            blocksize > EXT3_MAX_BLOCK_SIZE) {
-               printk(KERN_ERR 
+               printk(KERN_ERR
                       "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n",
                       blocksize, sb->s_id);
                goto failed_mount;
@@ -1486,14 +1547,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
                bh = sb_bread(sb, logic_sb_block);
                if (!bh) {
-                       printk(KERN_ERR 
+                       printk(KERN_ERR
                               "EXT3-fs: Can't read superblock on 2nd try.\n");
                        goto failed_mount;
                }
                es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
                sbi->s_es = es;
                if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
-                       printk (KERN_ERR 
+                       printk (KERN_ERR
                                "EXT3-fs: Magic mismatch, very weird !\n");
                        goto failed_mount;
                }
@@ -1538,8 +1599,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);
        sbi->s_sbh = bh;
        sbi->s_mount_state = le16_to_cpu(es->s_state);
-       sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));
-       sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));
+       sbi->s_addr_per_block_bits = ilog2(EXT3_ADDR_PER_BLOCK(sb));
+       sbi->s_desc_per_block_bits = ilog2(EXT3_DESC_PER_BLOCK(sb));
        for (i=0; i < 4; i++)
                sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
        sbi->s_def_hash_version = es->s_def_hash_version;
@@ -1563,12 +1624,21 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
+       if (le32_to_cpu(es->s_blocks_count) >
+                   (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+               printk(KERN_ERR "EXT3-fs: filesystem on %s:"
+                       " too large to mount safely\n", sb->s_id);
+               if (sizeof(sector_t) < 8)
+                       printk(KERN_WARNING "EXT3-fs: CONFIG_LBD not "
+                                       "enabled\n");
+               goto failed_mount;
+       }
+
        if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
                goto cantfind_ext3;
-       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
-                              le32_to_cpu(es->s_first_data_block) +
-                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
-                             EXT3_BLOCKS_PER_GROUP(sb);
+       sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) - 1)
+                                      / EXT3_BLOCKS_PER_GROUP(sb)) + 1;
        db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /
                   EXT3_DESC_PER_BLOCK(sb);
        sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
@@ -1578,9 +1648,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       percpu_counter_init(&sbi->s_freeblocks_counter);
-       percpu_counter_init(&sbi->s_freeinodes_counter);
-       percpu_counter_init(&sbi->s_dirs_counter);
        bgl_lock_init(&sbi->s_blockgroup_lock);
 
        for (i = 0; i < db_count; i++) {
@@ -1594,12 +1661,20 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                }
        }
        if (!ext3_check_descriptors (sb)) {
-               printk (KERN_ERR "EXT3-fs: group descriptors corrupted !\n");
+               printk(KERN_ERR "EXT3-fs: group descriptors corrupted!\n");
                goto failed_mount2;
        }
        sbi->s_gdb_count = db_count;
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
        spin_lock_init(&sbi->s_next_gen_lock);
+
+       percpu_counter_init(&sbi->s_freeblocks_counter,
+               ext3_count_free_blocks(sb));
+       percpu_counter_init(&sbi->s_freeinodes_counter,
+               ext3_count_free_inodes(sb));
+       percpu_counter_init(&sbi->s_dirs_counter,
+               ext3_count_dirs(sb));
+
        /* per fileystem reservation list head & lock */
        spin_lock_init(&sbi->s_rsv_window_lock);
        sbi->s_rsv_window_root = RB_ROOT;
@@ -1638,16 +1713,16 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        if (!test_opt(sb, NOLOAD) &&
            EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
                if (ext3_load_journal(sb, es, journal_devnum))
-                       goto failed_mount2;
+                       goto failed_mount3;
        } else if (journal_inum) {
                if (ext3_create_journal(sb, es, journal_inum))
-                       goto failed_mount2;
+                       goto failed_mount3;
        } else {
                if (!silent)
                        printk (KERN_ERR
                                "ext3: No journal on filesystem on %s\n",
                                sb->s_id);
-               goto failed_mount2;
+               goto failed_mount3;
        }
 
        /* We have now updated the journal if required, so we can
@@ -1670,19 +1745,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
                        printk(KERN_ERR "EXT3-fs: Journal does not support "
                               "requested data journaling mode\n");
-                       goto failed_mount3;
+                       goto failed_mount4;
                }
        default:
                break;
        }
 
        if (test_opt(sb, NOBH)) {
-               if (sb->s_blocksize_bits != PAGE_CACHE_SHIFT) {
-                       printk(KERN_WARNING "EXT3-fs: Ignoring nobh option "
-                               "since filesystem blocksize doesn't match "
-                               "pagesize\n");
-                       clear_opt(sbi->s_mount_opt, NOBH);
-               }
                if (!(test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)) {
                        printk(KERN_WARNING "EXT3-fs: Ignoring nobh option - "
                                "its supported only with writeback mode\n");
@@ -1699,13 +1768,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        if (!sb->s_root) {
                printk(KERN_ERR "EXT3-fs: get root inode failed\n");
                iput(root);
-               goto failed_mount3;
+               goto failed_mount4;
        }
        if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
                dput(sb->s_root);
                sb->s_root = NULL;
                printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n");
-               goto failed_mount3;
+               goto failed_mount4;
        }
 
        ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
@@ -1728,13 +1797,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
                "writeback");
 
-       percpu_counter_mod(&sbi->s_freeblocks_counter,
-               ext3_count_free_blocks(sb));
-       percpu_counter_mod(&sbi->s_freeinodes_counter,
-               ext3_count_free_inodes(sb));
-       percpu_counter_mod(&sbi->s_dirs_counter,
-               ext3_count_dirs(sb));
-
        lock_kernel();
        return 0;
 
@@ -1744,8 +1806,12 @@ cantfind_ext3:
                       sb->s_id);
        goto failed_mount;
 
-failed_mount3:
+failed_mount4:
        journal_destroy(sbi->s_journal);
+failed_mount3:
+       percpu_counter_destroy(&sbi->s_freeblocks_counter);
+       percpu_counter_destroy(&sbi->s_freeinodes_counter);
+       percpu_counter_destroy(&sbi->s_dirs_counter);
 failed_mount2:
        for (i = 0; i < db_count; i++)
                brelse(sbi->s_group_desc[i]);
@@ -1767,7 +1833,7 @@ out_fail:
 /*
  * Setup any per-fs journal parameters now.  We'll do this both on
  * initial mount, once the journal has been initialised but before we've
- * done any recovery; and again on any subsequent remount. 
+ * done any recovery; and again on any subsequent remount.
  */
 static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
 {
@@ -1787,7 +1853,8 @@ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
        spin_unlock(&journal->j_state_lock);
 }
 
-static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
+static journal_t *ext3_get_journal(struct super_block *sb,
+                                  unsigned int journal_inum)
 {
        struct inode *journal_inode;
        journal_t *journal;
@@ -1832,10 +1899,10 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
 {
        struct buffer_head * bh;
        journal_t *journal;
-       int start;
-       int len;
+       ext3_fsblk_t start;
+       ext3_fsblk_t len;
        int hblock, blocksize;
-       unsigned long sb_block;
+       ext3_fsblk_t sb_block;
        unsigned long offset;
        struct ext3_super_block * es;
        struct block_device *bdev;
@@ -1922,7 +1989,7 @@ static int ext3_load_journal(struct super_block *sb,
                             unsigned long journal_devnum)
 {
        journal_t *journal;
-       int journal_inum = le32_to_cpu(es->s_journal_inum);
+       unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);
        dev_t journal_dev;
        int err = 0;
        int really_read_only;
@@ -2008,7 +2075,7 @@ static int ext3_load_journal(struct super_block *sb,
 
 static int ext3_create_journal(struct super_block * sb,
                               struct ext3_super_block * es,
-                              int journal_inum)
+                              unsigned int journal_inum)
 {
        journal_t *journal;
 
@@ -2021,7 +2088,7 @@ static int ext3_create_journal(struct super_block * sb,
        if (!(journal = ext3_get_journal(sb, journal_inum)))
                return -EINVAL;
 
-       printk(KERN_INFO "EXT3-fs: creating new journal on inode %d\n",
+       printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",
               journal_inum);
 
        if (journal_create(journal)) {
@@ -2150,7 +2217,7 @@ int ext3_force_commit(struct super_block *sb)
 
 static void ext3_write_super (struct super_block * sb)
 {
-       if (down_trylock(&sb->s_lock) == 0)
+       if (mutex_trylock(&sb->s_lock) != 0)
                BUG();
        sb->s_dirt = 0;
 }
@@ -2208,7 +2275,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
 {
        struct ext3_super_block * es;
        struct ext3_sb_info *sbi = EXT3_SB(sb);
-       unsigned long n_blocks_count = 0;
+       ext3_fsblk_t n_blocks_count = 0;
        unsigned long old_sb_flags;
        struct ext3_mount_options old_opts;
        int err;
@@ -2281,6 +2348,22 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                                err = -EROFS;
                                goto restore_opts;
                        }
+
+                       /*
+                        * If we have an unprocessed orphan list hanging
+                        * around from a previously readonly bdev mount,
+                        * require a full umount/remount for now.
+                        */
+                       if (es->s_last_orphan) {
+                               printk(KERN_WARNING "EXT3-fs: %s: couldn't "
+                                      "remount RDWR because of unprocessed "
+                                      "orphan inode list.  Please "
+                                      "umount/remount instead.\n",
+                                      sb->s_id);
+                               err = -EINVAL;
+                               goto restore_opts;
+                       }
+
                        /*
                         * Mounting a RDONLY partition read-write, so reread
                         * and store the current valid flag.  (It may have
@@ -2289,10 +2372,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                         */
                        ext3_clear_journal_err(sb, es);
                        sbi->s_mount_state = le16_to_cpu(es->s_state);
-                       if ((ret = ext3_group_extend(sb, es, n_blocks_count))) {
-                               err = ret;
+                       if ((err = ext3_group_extend(sb, es, n_blocks_count)))
                                goto restore_opts;
-                       }
                        if (!ext3_setup_super (sb, es, 0))
                                sb->s_flags &= ~MS_RDONLY;
                }
@@ -2323,11 +2404,14 @@ restore_opts:
        return err;
 }
 
-static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
+static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
 {
-       struct ext3_super_block *es = EXT3_SB(sb)->s_es;
-       unsigned long overhead;
+       struct super_block *sb = dentry->d_sb;
+       struct ext3_sb_info *sbi = EXT3_SB(sb);
+       struct ext3_super_block *es = sbi->s_es;
+       ext3_fsblk_t overhead;
        int i;
+       u64 fsid;
 
        if (test_opt (sb, MINIX_DF))
                overhead = 0;
@@ -2367,13 +2451,17 @@ static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
        buf->f_type = EXT3_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
-       buf->f_bfree = ext3_count_free_blocks (sb);
+       buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
        buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
        if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
                buf->f_bavail = 0;
        buf->f_files = le32_to_cpu(es->s_inodes_count);
-       buf->f_ffree = ext3_count_free_inodes (sb);
+       buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
        buf->f_namelen = EXT3_NAME_LEN;
+       fsid = le64_to_cpup((void *)es->s_uuid) ^
+              le64_to_cpup((void *)es->s_uuid + sizeof(u64));
+       buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
+       buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
        return 0;
 }
 
@@ -2382,8 +2470,8 @@ static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
  * Process 1                         Process 2
  * ext3_create()                     quota_sync()
  *   journal_start()                   write_dquot()
- *   DQUOT_INIT()                        down(dqio_sem)
- *     down(dqio_sem)                    journal_start()
+ *   DQUOT_INIT()                        down(dqio_mutex)
+ *     down(dqio_mutex)                    journal_start()
  *
  */
 
@@ -2601,7 +2689,7 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
        struct buffer_head *bh;
        handle_t *handle = journal_current_handle();
 
-       down(&inode->i_sem);
+       mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
        while (towrite > 0) {
                tocopy = sb->s_blocksize - offset < towrite ?
                                sb->s_blocksize - offset : towrite;
@@ -2644,16 +2732,16 @@ out:
        inode->i_version++;
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        ext3_mark_inode_dirty(handle, inode);
-       up(&inode->i_sem);
+       mutex_unlock(&inode->i_mutex);
        return len - towrite;
 }
 
 #endif
 
-static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data)
+static int ext3_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-       return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super);
+       return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt);
 }
 
 static struct file_system_type ext3_fs_type = {
@@ -2679,7 +2767,7 @@ static int __init init_ext3_fs(void)
 out:
        destroy_inodecache();
 out1:
-       exit_ext3_xattr();
+       exit_ext3_xattr();
        return err;
 }