These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / ext4 / dir.c
index 5665d82..1d1bca7 100644 (file)
@@ -40,8 +40,7 @@ static int is_dx_dir(struct inode *inode)
 {
        struct super_block *sb = inode->i_sb;
 
-       if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
-                    EXT4_FEATURE_COMPAT_DIR_INDEX) &&
+       if (ext4_has_feature_dir_index(inode->i_sb) &&
            ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
             ((inode->i_size >> sb->s_blocksize_bits) == 1) ||
             ext4_has_inline_data(inode)))
@@ -110,7 +109,6 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
        struct super_block *sb = inode->i_sb;
        struct buffer_head *bh = NULL;
        int dir_has_error = 0;
-       struct ext4_fname_crypto_ctx *enc_ctx = NULL;
        struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
 
        if (is_dx_dir(inode)) {
@@ -134,16 +132,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
                        return err;
        }
 
-       enc_ctx = ext4_get_fname_crypto_ctx(inode, EXT4_NAME_LEN);
-       if (IS_ERR(enc_ctx))
-               return PTR_ERR(enc_ctx);
-       if (enc_ctx) {
-               err = ext4_fname_crypto_alloc_buffer(enc_ctx, EXT4_NAME_LEN,
+       if (ext4_encrypted_inode(inode)) {
+               err = ext4_fname_crypto_alloc_buffer(inode, EXT4_NAME_LEN,
                                                     &fname_crypto_str);
-               if (err < 0) {
-                       ext4_put_fname_crypto_ctx(&enc_ctx);
+               if (err < 0)
                        return err;
-               }
        }
 
        offset = ctx->pos & (sb->s_blocksize - 1);
@@ -239,17 +232,19 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
                        offset += ext4_rec_len_from_disk(de->rec_len,
                                        sb->s_blocksize);
                        if (le32_to_cpu(de->inode)) {
-                               if (enc_ctx == NULL) {
-                                       /* Directory is not encrypted */
+                               if (!ext4_encrypted_inode(inode)) {
                                        if (!dir_emit(ctx, de->name,
                                            de->name_len,
                                            le32_to_cpu(de->inode),
                                            get_dtype(sb, de->file_type)))
                                                goto done;
                                } else {
+                                       int save_len = fname_crypto_str.len;
+
                                        /* Directory is encrypted */
-                                       err = ext4_fname_disk_to_usr(enc_ctx,
+                                       err = ext4_fname_disk_to_usr(inode,
                                                NULL, de, &fname_crypto_str);
+                                       fname_crypto_str.len = save_len;
                                        if (err < 0)
                                                goto errout;
                                        if (!dir_emit(ctx,
@@ -272,7 +267,6 @@ done:
        err = 0;
 errout:
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
-       ext4_put_fname_crypto_ctx(&enc_ctx);
        ext4_fname_crypto_free_buffer(&fname_crypto_str);
 #endif
        brelse(bh);
@@ -598,6 +592,13 @@ finished:
        return 0;
 }
 
+static int ext4_dir_open(struct inode * inode, struct file * filp)
+{
+       if (ext4_encrypted_inode(inode))
+               return ext4_get_encryption_info(inode) ? -EACCES : 0;
+       return 0;
+}
+
 static int ext4_release_dir(struct inode *inode, struct file *filp)
 {
        if (filp->private_data)
@@ -619,14 +620,14 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
        while ((char *) de < top) {
                if (ext4_check_dir_entry(dir, NULL, de, bh,
                                         buf, buf_size, offset))
-                       return -EIO;
+                       return -EFSCORRUPTED;
                nlen = EXT4_DIR_REC_LEN(de->name_len);
                rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
                de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
                offset += rlen;
        }
        if ((char *) de > top)
-               return -EIO;
+               return -EFSCORRUPTED;
 
        return 0;
 }
@@ -640,5 +641,6 @@ const struct file_operations ext4_dir_operations = {
        .compat_ioctl   = ext4_compat_ioctl,
 #endif
        .fsync          = ext4_sync_file,
+       .open           = ext4_dir_open,
        .release        = ext4_release_dir,
 };