]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ext4/super.c
ext4: move headers out of include/linux
[linux-2.6-omap-h63xx.git] / fs / ext4 / super.c
index 055a0cd0168e5029ee87bb3ce8c55153fae3b171..3435184114c4fb008c07890e078335afa356ef1a 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/seq_file.h>
 #include <linux/log2.h>
 #include <linux/crc16.h>
-
 #include <asm/uaccess.h>
 
+#include "ext4.h"
+#include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
 #include "namei.h"
@@ -135,7 +134,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
         * take the FS itself readonly cleanly. */
        journal = EXT4_SB(sb)->s_journal;
        if (is_journal_aborted(journal)) {
-               ext4_abort(sb, __FUNCTION__,
+               ext4_abort(sb, __func__,
                           "Detected aborted journal");
                return ERR_PTR(-EROFS);
        }
@@ -355,7 +354,7 @@ void ext4_update_dynamic_rev(struct super_block *sb)
        if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV)
                return;
 
-       ext4_warning(sb, __FUNCTION__,
+       ext4_warning(sb, __func__,
                     "updating to rev %d because of new feature flag, "
                     "running e2fsck is recommended",
                     EXT4_DYNAMIC_REV);
@@ -777,11 +776,10 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
         * 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)) {
+       inode = ext4_iget(sb, ino);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+       if (generation && inode->i_generation != generation) {
                iput(inode);
                return ERR_PTR(-ESTALE);
        }
@@ -814,7 +812,8 @@ static int ext4_acquire_dquot(struct dquot *dquot);
 static int ext4_release_dquot(struct dquot *dquot);
 static int ext4_mark_dquot_dirty(struct dquot *dquot);
 static int ext4_write_info(struct super_block *sb, int type);
-static int ext4_quota_on(struct super_block *sb, int type, int format_id, char *path);
+static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+                               char *path, int remount);
 static int ext4_quota_on_mount(struct super_block *sb, int type);
 static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
                               size_t len, loff_t off);
@@ -850,7 +849,6 @@ static struct quotactl_ops ext4_qctl_operations = {
 static const struct super_operations ext4_sops = {
        .alloc_inode    = ext4_alloc_inode,
        .destroy_inode  = ext4_destroy_inode,
-       .read_inode     = ext4_read_inode,
        .write_inode    = ext4_write_inode,
        .dirty_inode    = ext4_dirty_inode,
        .delete_inode   = ext4_delete_inode,
@@ -946,8 +944,8 @@ static match_table_t tokens = {
        {Opt_mballoc, "mballoc"},
        {Opt_nomballoc, "nomballoc"},
        {Opt_stripe, "stripe=%u"},
-       {Opt_err, NULL},
        {Opt_resize, "resize"},
+       {Opt_err, NULL},
 };
 
 static ext4_fsblk_t get_sb_block(void **data)
@@ -1389,11 +1387,11 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
                 * a plain journaled filesystem we can keep it set as
                 * valid forever! :)
                 */
-       es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT4_VALID_FS);
+       es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
 #endif
        if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
                es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
-       es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
+       le16_add_cpu(&es->s_mnt_count, 1);
        es->s_mtime = cpu_to_le32(get_seconds());
        ext4_update_dynamic_rev(sb);
        EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
@@ -1458,7 +1456,7 @@ int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 block_group,
 }
 
 /* Called at mount-time, super-block is locked */
-static int ext4_check_descriptors (struct super_block * sb)
+static int ext4_check_descriptors(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
@@ -1466,8 +1464,6 @@ static int ext4_check_descriptors (struct super_block * sb)
        ext4_fsblk_t block_bitmap;
        ext4_fsblk_t inode_bitmap;
        ext4_fsblk_t inode_table;
-       struct ext4_group_desc * gdp = NULL;
-       int desc_block = 0;
        int flexbg_flag = 0;
        ext4_group_t i;
 
@@ -1476,17 +1472,15 @@ static int ext4_check_descriptors (struct super_block * sb)
 
        ext4_debug ("Checking group descriptors");
 
-       for (i = 0; i < sbi->s_groups_count; i++)
-       {
+       for (i = 0; i < sbi->s_groups_count; i++) {
+               struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
+
                if (i == sbi->s_groups_count - 1 || flexbg_flag)
                        last_block = ext4_blocks_count(sbi->s_es) - 1;
                else
                        last_block = first_block +
                                (EXT4_BLOCKS_PER_GROUP(sb) - 1);
 
-               if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)
-                       gdp = (struct ext4_group_desc *)
-                                       sbi->s_group_desc[desc_block++]->b_data;
                block_bitmap = ext4_block_bitmap(sb, gdp);
                if (block_bitmap < first_block || block_bitmap > last_block)
                {
@@ -1516,7 +1510,7 @@ static int ext4_check_descriptors (struct super_block * sb)
                        return 0;
                }
                if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
-                       ext4_error(sb, __FUNCTION__,
+                       ext4_error(sb, __func__,
                                   "Checksum for group %lu failed (%u!=%u)\n",
                                    i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
                                    gdp)), le16_to_cpu(gdp->bg_checksum));
@@ -1524,8 +1518,6 @@ static int ext4_check_descriptors (struct super_block * sb)
                }
                if (!flexbg_flag)
                        first_block += EXT4_BLOCKS_PER_GROUP(sb);
-               gdp = (struct ext4_group_desc *)
-                       ((__u8 *)gdp + EXT4_DESC_SIZE(sb));
        }
 
        ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
@@ -1601,8 +1593,8 @@ static void ext4_orphan_cleanup (struct super_block * sb,
        while (es->s_last_orphan) {
                struct inode *inode;
 
-               if (!(inode =
-                     ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {
+               inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
+               if (IS_ERR(inode)) {
                        es->s_last_orphan = 0;
                        break;
                }
@@ -1612,7 +1604,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
                if (inode->i_nlink) {
                        printk(KERN_DEBUG
                                "%s: truncating inode %lu to %Ld bytes\n",
-                               __FUNCTION__, inode->i_ino, inode->i_size);
+                               __func__, inode->i_ino, inode->i_size);
                        jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
                                  inode->i_ino, inode->i_size);
                        ext4_truncate(inode);
@@ -1620,7 +1612,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
                } else {
                        printk(KERN_DEBUG
                                "%s: deleting unreferenced inode %lu\n",
-                               __FUNCTION__, inode->i_ino);
+                               __func__, inode->i_ino);
                        jbd_debug(2, "deleting unreferenced inode %lu\n",
                                  inode->i_ino);
                        nr_orphans++;
@@ -1640,7 +1632,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
        /* Turn quotas off */
        for (i = 0; i < MAXQUOTAS; i++) {
                if (sb_dqopt(sb)->files[i])
-                       vfs_quota_off(sb, i);
+                       vfs_quota_off(sb, i, 0);
        }
 #endif
        sb->s_flags = s_flags; /* Restore MS_RDONLY status */
@@ -1811,6 +1803,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        unsigned long journal_devnum = 0;
        unsigned long def_mount_opts;
        struct inode *root;
+       int ret = -EINVAL;
        int blocksize;
        int db_count;
        int i;
@@ -1926,6 +1919,17 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                printk(KERN_WARNING
                       "EXT4-fs warning: feature flags set on rev 0 fs, "
                       "running e2fsck is recommended\n");
+
+       /*
+        * Since ext4 is still considered development code, we require
+        * that the TEST_FILESYS flag in s->flags be set.
+        */
+       if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) {
+               printk(KERN_WARNING "EXT4-fs: %s: not marked "
+                      "OK to use with test code.\n", sb->s_id);
+               goto failed_mount;
+       }
+
        /*
         * Check feature flags regardless of the revision level, since we
         * previously didn't change the revision level when setting the flags,
@@ -2243,19 +2247,24 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
         * so we can safely mount the rest of the filesystem now.
         */
 
-       root = iget(sb, EXT4_ROOT_INO);
-       sb->s_root = d_alloc_root(root);
-       if (!sb->s_root) {
+       root = ext4_iget(sb, EXT4_ROOT_INO);
+       if (IS_ERR(root)) {
                printk(KERN_ERR "EXT4-fs: get root inode failed\n");
-               iput(root);
+               ret = PTR_ERR(root);
                goto failed_mount4;
        }
        if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
-               dput(sb->s_root);
-               sb->s_root = NULL;
+               iput(root);
                printk(KERN_ERR "EXT4-fs: corrupt root inode, run e2fsck\n");
                goto failed_mount4;
        }
+       sb->s_root = d_alloc_root(root);
+       if (!sb->s_root) {
+               printk(KERN_ERR "EXT4-fs: get root dentry failed\n");
+               iput(root);
+               ret = -ENOMEM;
+               goto failed_mount4;
+       }
 
        ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY);
 
@@ -2336,7 +2345,7 @@ out_fail:
        sb->s_fs_info = NULL;
        kfree(sbi);
        lock_kernel();
-       return -EINVAL;
+       return ret;
 }
 
 /*
@@ -2372,8 +2381,8 @@ static journal_t *ext4_get_journal(struct super_block *sb,
         * things happen if we iget() an unused inode, as the subsequent
         * iput() will try to delete it. */
 
-       journal_inode = iget(sb, journal_inum);
-       if (!journal_inode) {
+       journal_inode = ext4_iget(sb, journal_inum);
+       if (IS_ERR(journal_inode)) {
                printk(KERN_ERR "EXT4-fs: no journal found.\n");
                return NULL;
        }
@@ -2386,7 +2395,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
 
        jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
                  journal_inode, journal_inode->i_size);
-       if (is_bad_inode(journal_inode) || !S_ISREG(journal_inode->i_mode)) {
+       if (!S_ISREG(journal_inode->i_mode)) {
                printk(KERN_ERR "EXT4-fs: invalid journal inode.\n");
                iput(journal_inode);
                return NULL;
@@ -2689,9 +2698,9 @@ static void ext4_clear_journal_err(struct super_block * sb,
                char nbuf[16];
 
                errstr = ext4_decode_error(sb, j_errno, nbuf);
-               ext4_warning(sb, __FUNCTION__, "Filesystem error recorded "
+               ext4_warning(sb, __func__, "Filesystem error recorded "
                             "from previous mount: %s", errstr);
-               ext4_warning(sb, __FUNCTION__, "Marking fs in need of "
+               ext4_warning(sb, __func__, "Marking fs in need of "
                             "filesystem check.");
 
                EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
@@ -2818,7 +2827,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
        }
 
        if (sbi->s_mount_opt & EXT4_MOUNT_ABORT)
-               ext4_abort(sb, __FUNCTION__, "Abort forced by user");
+               ext4_abort(sb, __func__, "Abort forced by user");
 
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
                ((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
@@ -3030,8 +3039,14 @@ static int ext4_dquot_drop(struct inode *inode)
 
        /* We may delete quota structure so we need to reserve enough blocks */
        handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
-       if (IS_ERR(handle))
+       if (IS_ERR(handle)) {
+               /*
+                * We call dquot_drop() anyway to at least release references
+                * to quota structures so that umount does not hang.
+                */
+               dquot_drop(inode);
                return PTR_ERR(handle);
+       }
        ret = dquot_drop(inode);
        err = ext4_journal_stop(handle);
        if (!ret)
@@ -3134,7 +3149,7 @@ static int ext4_quota_on_mount(struct super_block *sb, int type)
  * Standard function to be called on quota_on
  */
 static int ext4_quota_on(struct super_block *sb, int type, int format_id,
-                        char *path)
+                        char *path, int remount)
 {
        int err;
        struct nameidata nd;
@@ -3142,24 +3157,24 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
        if (!test_opt(sb, QUOTA))
                return -EINVAL;
        /* Not journalling quota? */
-       if (!EXT4_SB(sb)->s_qf_names[USRQUOTA] &&
-           !EXT4_SB(sb)->s_qf_names[GRPQUOTA])
-               return vfs_quota_on(sb, type, format_id, path);
+       if ((!EXT4_SB(sb)->s_qf_names[USRQUOTA] &&
+           !EXT4_SB(sb)->s_qf_names[GRPQUOTA]) || remount)
+               return vfs_quota_on(sb, type, format_id, path, remount);
        err = path_lookup(path, LOOKUP_FOLLOW, &nd);
        if (err)
                return err;
        /* Quotafile not on the same filesystem? */
-       if (nd.mnt->mnt_sb != sb) {
-               path_release(&nd);
+       if (nd.path.mnt->mnt_sb != sb) {
+               path_put(&nd.path);
                return -EXDEV;
        }
        /* Quotafile not of fs root? */
-       if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
+       if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
                printk(KERN_WARNING
                        "EXT4-fs: Quota file not on filesystem root. "
                        "Journalled quota will not work.\n");
-       path_release(&nd);
-       return vfs_quota_on(sb, type, format_id, path);
+       path_put(&nd.path);
+       return vfs_quota_on(sb, type, format_id, path, remount);
 }
 
 /* Read data from quotafile - avoid pagecache and such because we cannot afford