OSDN Git Service

knfsd: exportfs: add exportfs.h header
[linux-kernel-docs/linux-2.6.git] / fs / ext4 / super.c
index cb9afdd..b806e68 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
 #include <linux/mount.h>
@@ -510,6 +511,14 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 
 static void ext4_destroy_inode(struct inode *inode)
 {
+       if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
+               printk("EXT4 Inode %p: orphan list check failed!\n",
+                       EXT4_I(inode));
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+                               EXT4_I(inode), sizeof(struct ext4_inode_info),
+                               true);
+               dump_stack();
+       }
        kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
@@ -1985,7 +1994,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
 
        if (bd_claim(bdev, sb)) {
                printk(KERN_ERR
-                       "EXT4: failed to claim external journal device.\n");
+                       "EXT4: failed to claim external journal device.\n");
                blkdev_put(bdev);
                return NULL;
        }
@@ -2150,6 +2159,7 @@ static int ext4_create_journal(struct super_block * sb,
                               unsigned int journal_inum)
 {
        journal_t *journal;
+       int err;
 
        if (sb->s_flags & MS_RDONLY) {
                printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to "
@@ -2157,13 +2167,15 @@ static int ext4_create_journal(struct super_block * sb,
                return -EROFS;
        }
 
-       if (!(journal = ext4_get_journal(sb, journal_inum)))
+       journal = ext4_get_journal(sb, journal_inum);
+       if (!journal)
                return -EINVAL;
 
        printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n",
               journal_inum);
 
-       if (jbd2_journal_create(journal)) {
+       err = jbd2_journal_create(journal);
+       if (err) {
                printk(KERN_ERR "EXT4-fs: error creating journal.\n");
                jbd2_journal_destroy(journal);
                return -EIO;
@@ -2214,12 +2226,14 @@ static void ext4_mark_recovery_complete(struct super_block * sb,
 
        jbd2_journal_lock_updates(journal);
        jbd2_journal_flush(journal);
+       lock_super(sb);
        if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
            sb->s_flags & MS_RDONLY) {
                EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
                sb->s_dirt = 0;
                ext4_commit_super(sb, es, 1);
        }
+       unlock_super(sb);
        jbd2_journal_unlock_updates(journal);
 }
 
@@ -2408,7 +2422,13 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
                            (sbi->s_mount_state & EXT4_VALID_FS))
                                es->s_state = cpu_to_le16(sbi->s_mount_state);
 
+                       /*
+                        * We have to unlock super so that we can wait for
+                        * transactions.
+                        */
+                       unlock_super(sb);
                        ext4_mark_recovery_complete(sb, es);
+                       lock_super(sb);
                } else {
                        __le32 ret;
                        if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -2481,19 +2501,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
        struct super_block *sb = dentry->d_sb;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
-       ext4_fsblk_t overhead;
-       int i;
        u64 fsid;
 
-       if (test_opt (sb, MINIX_DF))
-               overhead = 0;
-       else {
-               unsigned long ngroups;
-               ngroups = EXT4_SB(sb)->s_groups_count;
+       if (test_opt(sb, MINIX_DF)) {
+               sbi->s_overhead_last = 0;
+       } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+               unsigned long ngroups = sbi->s_groups_count, i;
+               ext4_fsblk_t overhead = 0;
                smp_rmb();
 
                /*
-                * Compute the overhead (FS structures)
+                * Compute the overhead (FS structures).  This is constant
+                * for a given filesystem unless the number of block groups
+                * changes so we cache the previous value until it does.
                 */
 
                /*
@@ -2517,18 +2537,23 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
                 * Every block group has an inode bitmap, a block
                 * bitmap, and an inode table.
                 */
-               overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group));
+               overhead += ngroups * (2 + sbi->s_itb_per_group);
+               sbi->s_overhead_last = overhead;
+               smp_wmb();
+               sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
        }
 
        buf->f_type = EXT4_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
-       buf->f_blocks = ext4_blocks_count(es) - overhead;
+       buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
        buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+       es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
        buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
        if (buf->f_bfree < ext4_r_blocks_count(es))
                buf->f_bavail = 0;
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+       es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
        buf->f_namelen = EXT4_NAME_LEN;
        fsid = le64_to_cpup((void *)es->s_uuid) ^
               le64_to_cpup((void *)es->s_uuid + sizeof(u64));