aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/dir.c64
-rw-r--r--fs/ext4/ialloc.c21
2 files changed, 68 insertions, 17 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 315f13ad382e..61db51a5ce4c 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -108,7 +108,10 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
108 int err; 108 int err;
109 struct inode *inode = file_inode(file); 109 struct inode *inode = file_inode(file);
110 struct super_block *sb = inode->i_sb; 110 struct super_block *sb = inode->i_sb;
111 struct buffer_head *bh = NULL;
111 int dir_has_error = 0; 112 int dir_has_error = 0;
113 struct ext4_fname_crypto_ctx *enc_ctx = NULL;
114 struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
112 115
113 if (is_dx_dir(inode)) { 116 if (is_dx_dir(inode)) {
114 err = ext4_dx_readdir(file, ctx); 117 err = ext4_dx_readdir(file, ctx);
@@ -125,17 +128,28 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
125 128
126 if (ext4_has_inline_data(inode)) { 129 if (ext4_has_inline_data(inode)) {
127 int has_inline_data = 1; 130 int has_inline_data = 1;
128 int ret = ext4_read_inline_dir(file, ctx, 131 err = ext4_read_inline_dir(file, ctx,
129 &has_inline_data); 132 &has_inline_data);
130 if (has_inline_data) 133 if (has_inline_data)
131 return ret; 134 return err;
135 }
136
137 enc_ctx = ext4_get_fname_crypto_ctx(inode, EXT4_NAME_LEN);
138 if (IS_ERR(enc_ctx))
139 return PTR_ERR(enc_ctx);
140 if (enc_ctx) {
141 err = ext4_fname_crypto_alloc_buffer(enc_ctx, EXT4_NAME_LEN,
142 &fname_crypto_str);
143 if (err < 0) {
144 ext4_put_fname_crypto_ctx(&enc_ctx);
145 return err;
146 }
132 } 147 }
133 148
134 offset = ctx->pos & (sb->s_blocksize - 1); 149 offset = ctx->pos & (sb->s_blocksize - 1);
135 150
136 while (ctx->pos < inode->i_size) { 151 while (ctx->pos < inode->i_size) {
137 struct ext4_map_blocks map; 152 struct ext4_map_blocks map;
138 struct buffer_head *bh = NULL;
139 153
140 map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb); 154 map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
141 map.m_len = 1; 155 map.m_len = 1;
@@ -178,6 +192,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
178 (unsigned long long)ctx->pos); 192 (unsigned long long)ctx->pos);
179 ctx->pos += sb->s_blocksize - offset; 193 ctx->pos += sb->s_blocksize - offset;
180 brelse(bh); 194 brelse(bh);
195 bh = NULL;
181 continue; 196 continue;
182 } 197 }
183 set_buffer_verified(bh); 198 set_buffer_verified(bh);
@@ -224,25 +239,44 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
224 offset += ext4_rec_len_from_disk(de->rec_len, 239 offset += ext4_rec_len_from_disk(de->rec_len,
225 sb->s_blocksize); 240 sb->s_blocksize);
226 if (le32_to_cpu(de->inode)) { 241 if (le32_to_cpu(de->inode)) {
227 if (!dir_emit(ctx, de->name, 242 if (enc_ctx == NULL) {
228 de->name_len, 243 /* Directory is not encrypted */
229 le32_to_cpu(de->inode), 244 if (!dir_emit(ctx, de->name,
230 get_dtype(sb, de->file_type))) { 245 de->name_len,
231 brelse(bh); 246 le32_to_cpu(de->inode),
232 return 0; 247 get_dtype(sb, de->file_type)))
248 goto done;
249 } else {
250 /* Directory is encrypted */
251 err = ext4_fname_disk_to_usr(enc_ctx,
252 de, &fname_crypto_str);
253 if (err < 0)
254 goto errout;
255 if (!dir_emit(ctx,
256 fname_crypto_str.name, err,
257 le32_to_cpu(de->inode),
258 get_dtype(sb, de->file_type)))
259 goto done;
233 } 260 }
234 } 261 }
235 ctx->pos += ext4_rec_len_from_disk(de->rec_len, 262 ctx->pos += ext4_rec_len_from_disk(de->rec_len,
236 sb->s_blocksize); 263 sb->s_blocksize);
237 } 264 }
238 offset = 0; 265 if ((ctx->pos < inode->i_size) && !dir_relax(inode))
266 goto done;
239 brelse(bh); 267 brelse(bh);
240 if (ctx->pos < inode->i_size) { 268 bh = NULL;
241 if (!dir_relax(inode)) 269 offset = 0;
242 return 0;
243 }
244 } 270 }
245 return 0; 271done:
272 err = 0;
273errout:
274#ifdef CONFIG_EXT4_FS_ENCRYPTION
275 ext4_put_fname_crypto_ctx(&enc_ctx);
276 ext4_fname_crypto_free_buffer(&fname_crypto_str);
277#endif
278 brelse(bh);
279 return err;
246} 280}
247 281
248static inline int is_32bit_api(void) 282static inline int is_32bit_api(void)
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 247737efd725..850267c89407 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1033,11 +1033,28 @@ got:
1033 ext4_set_inode_state(inode, EXT4_STATE_NEW); 1033 ext4_set_inode_state(inode, EXT4_STATE_NEW);
1034 1034
1035 ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize; 1035 ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
1036 1036#ifdef CONFIG_EXT4_FS_ENCRYPTION
1037 if ((sbi->s_file_encryption_mode == EXT4_ENCRYPTION_MODE_INVALID) &&
1038 (sbi->s_dir_encryption_mode == EXT4_ENCRYPTION_MODE_INVALID)) {
1039 ei->i_inline_off = 0;
1040 if (EXT4_HAS_INCOMPAT_FEATURE(sb,
1041 EXT4_FEATURE_INCOMPAT_INLINE_DATA))
1042 ext4_set_inode_state(inode,
1043 EXT4_STATE_MAY_INLINE_DATA);
1044 } else {
1045 /* Inline data and encryption are incompatible
1046 * We turn off inline data since encryption is enabled */
1047 ei->i_inline_off = 1;
1048 if (EXT4_HAS_INCOMPAT_FEATURE(sb,
1049 EXT4_FEATURE_INCOMPAT_INLINE_DATA))
1050 ext4_clear_inode_state(inode,
1051 EXT4_STATE_MAY_INLINE_DATA);
1052 }
1053#else
1037 ei->i_inline_off = 0; 1054 ei->i_inline_off = 0;
1038 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_INLINE_DATA)) 1055 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_INLINE_DATA))
1039 ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 1056 ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
1040 1057#endif
1041 ret = inode; 1058 ret = inode;
1042 err = dquot_alloc_inode(inode); 1059 err = dquot_alloc_inode(inode);
1043 if (err) 1060 if (err)