OSDN Git Service

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[uclinux-h8/linux.git] / fs / ext4 / super.c
index 0ae853d..58987b5 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
+#include <linux/backing-dev.h>
 #include <linux/parser.h>
 #include <linux/buffer_head.h>
 #include <linux/exportfs.h>
@@ -294,6 +295,8 @@ static void __save_error_info(struct super_block *sb, const char *func,
        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
 
        EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+       if (bdev_read_only(sb->s_bdev))
+               return;
        es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
        es->s_last_error_time = cpu_to_le32(get_seconds());
        strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
@@ -589,14 +592,17 @@ void __ext4_msg(struct super_block *sb,
        va_end(args);
 }
 
+#define ext4_warning_ratelimit(sb)                                     \
+               ___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state), \
+                            "EXT4-fs warning")
+
 void __ext4_warning(struct super_block *sb, const char *function,
                    unsigned int line, const char *fmt, ...)
 {
        struct va_format vaf;
        va_list args;
 
-       if (!___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),
-                         "EXT4-fs warning"))
+       if (!ext4_warning_ratelimit(sb))
                return;
 
        va_start(args, fmt);
@@ -607,6 +613,24 @@ void __ext4_warning(struct super_block *sb, const char *function,
        va_end(args);
 }
 
+void __ext4_warning_inode(const struct inode *inode, const char *function,
+                         unsigned int line, const char *fmt, ...)
+{
+       struct va_format vaf;
+       va_list args;
+
+       if (!ext4_warning_ratelimit(inode->i_sb))
+               return;
+
+       va_start(args, fmt);
+       vaf.fmt = fmt;
+       vaf.va = &args;
+       printk(KERN_WARNING "EXT4-fs warning (device %s): %s:%d: "
+              "inode #%lu: comm %s: %pV\n", inode->i_sb->s_id,
+              function, line, inode->i_ino, current->comm, &vaf);
+       va_end(args);
+}
+
 void __ext4_grp_locked_error(const char *function, unsigned int line,
                             struct super_block *sb, ext4_group_t grp,
                             unsigned long ino, ext4_fsblk_t block,
@@ -805,6 +829,7 @@ static void ext4_put_super(struct super_block *sb)
                dump_orphan_list(sb, sbi);
        J_ASSERT(list_empty(&sbi->s_orphan));
 
+       sync_blockdev(sb->s_bdev);
        invalidate_bdev(sb->s_bdev);
        if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
                /*
@@ -877,9 +902,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        atomic_set(&ei->i_unwritten, 0);
        INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
-       ei->i_encryption_key.mode = EXT4_ENCRYPTION_MODE_INVALID;
+       ei->i_crypt_info = NULL;
 #endif
-
        return &ei->vfs_inode;
 }
 
@@ -956,6 +980,10 @@ void ext4_clear_inode(struct inode *inode)
                jbd2_free_inode(EXT4_I(inode)->jinode);
                EXT4_I(inode)->jinode = NULL;
        }
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+       if (EXT4_I(inode)->i_crypt_info)
+               ext4_free_encryption_info(inode, EXT4_I(inode)->i_crypt_info);
+#endif
 }
 
 static struct inode *ext4_nfs_get_inode(struct super_block *sb,
@@ -3418,7 +3446,6 @@ 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;
-       char *cp;
        const char *descr;
        int ret = -ENOMEM;
        int blocksize, clustersize;
@@ -3447,15 +3474,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        if (sb->s_bdev->bd_part)
                sbi->s_sectors_written_start =
                        part_stat_read(sb->s_bdev->bd_part, sectors[1]);
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
-       /* Modes of operations for file and directory encryption. */
-       sbi->s_file_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
-       sbi->s_dir_encryption_mode = EXT4_ENCRYPTION_MODE_INVALID;
-#endif
 
        /* Cleanup superblock name */
-       for (cp = sb->s_id; (cp = strchr(cp, '/'));)
-               *cp = '!';
+       strreplace(sb->s_id, '/', '!');
 
        /* -EINVAL is default */
        ret = -EINVAL;
@@ -4065,7 +4086,15 @@ no_journal:
                }
        }
 
-       if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) &&
+       if ((DUMMY_ENCRYPTION_ENABLED(sbi) ||
+            EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) &&
+           (blocksize != PAGE_CACHE_SIZE)) {
+               ext4_msg(sb, KERN_ERR,
+                        "Unsupported blocksize for fs encryption");
+               goto failed_mount_wq;
+       }
+
+       if (DUMMY_ENCRYPTION_ENABLED(sbi) &&
            !(sb->s_flags & MS_RDONLY) &&
            !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
                EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT);
@@ -4941,6 +4970,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
        }
 
+       if (*flags & MS_LAZYTIME)
+               sb->s_flags |= MS_LAZYTIME;
+
        if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
                if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
                        err = -EROFS;
@@ -5408,6 +5440,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
        struct inode *inode = sb_dqopt(sb)->files[type];
        ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
        int err, offset = off & (sb->s_blocksize - 1);
+       int retries = 0;
        struct buffer_head *bh;
        handle_t *handle = journal_current_handle();
 
@@ -5428,7 +5461,12 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
                return -EIO;
        }
 
-       bh = ext4_bread(handle, inode, blk, 1);
+       do {
+               bh = ext4_bread(handle, inode, blk,
+                               EXT4_GET_BLOCKS_CREATE |
+                               EXT4_GET_BLOCKS_METADATA_NOFAIL);
+       } while (IS_ERR(bh) && (PTR_ERR(bh) == -ENOSPC) &&
+                ext4_should_retry_alloc(inode->i_sb, &retries));
        if (IS_ERR(bh))
                return PTR_ERR(bh);
        if (!bh)
@@ -5645,6 +5683,7 @@ out7:
 
 static void __exit ext4_exit_fs(void)
 {
+       ext4_exit_crypto();
        ext4_destroy_lazyinit_thread();
        unregister_as_ext2();
        unregister_as_ext3();