Skip to content

Commit 50b8b3f

Browse files
committed
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o: "This merge window saw the the following new featuers added to ext4: - Direct I/O via iomap (required the iomap-for-next branch from Darrick as a prereq). - Support for using dioread-nolock where the block size < page size. - Support for encryption for file systems where the block size < page size. - Rework of journal credits handling so a revoke-heavy workload will not cause the journal to run out of space. - Replace bit-spinlocks with spinlocks in jbd2 Also included were some bug fixes and cleanups, mostly to clean up corner cases from fuzzed file systems and error path handling" * tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (59 commits) ext4: work around deleting a file with i_nlink == 0 safely ext4: add more paranoia checking in ext4_expand_extra_isize handling jbd2: make jbd2_handle_buffer_credits() handle reserved handles ext4: fix a bug in ext4_wait_for_tail_page_commit ext4: bio_alloc with __GFP_DIRECT_RECLAIM never fails ext4: code cleanup for get_next_id ext4: fix leak of quota reservations ext4: remove unused variable warning in parse_options() ext4: Enable encryption for subpage-sized blocks fs/buffer.c: support fscrypt in block_read_full_page() ext4: Add error handling for io_end_vec struct allocation jbd2: Fine tune estimate of necessary descriptor blocks jbd2: Provide trace event for handle restarts ext4: Reserve revoke credits for freed blocks jbd2: Make credit checking more strict jbd2: Rename h_buffer_credits to h_total_credits jbd2: Reserve space for revoke descriptor blocks jbd2: Drop jbd2_space_needed() jbd2: Account descriptor blocks into t_outstanding_credits jbd2: Factor out common parts of stopping and restarting a handle ...
2 parents f112a2f + dfdeeb4 commit 50b8b3f

30 files changed

+1691
-1461
lines changed

Documentation/filesystems/fscrypt.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,8 @@ Contents encryption
342342
-------------------
343343

344344
For file contents, each filesystem block is encrypted independently.
345-
Currently, only the case where the filesystem block size is equal to
346-
the system's page size (usually 4096 bytes) is supported.
345+
Starting from Linux kernel 5.5, encryption of filesystems with block
346+
size less than system's page size is supported.
347347

348348
Each block's IV is set to the logical block number within the file as
349349
a little endian number, except that:

fs/buffer.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <linux/pagevec.h>
4848
#include <linux/sched/mm.h>
4949
#include <trace/events/block.h>
50+
#include <linux/fscrypt.h>
5051

5152
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
5253
static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
@@ -246,10 +247,6 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
246247
return ret;
247248
}
248249

249-
/*
250-
* I/O completion handler for block_read_full_page() - pages
251-
* which come unlocked at the end of I/O.
252-
*/
253250
static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
254251
{
255252
unsigned long flags;
@@ -307,6 +304,47 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
307304
return;
308305
}
309306

307+
struct decrypt_bh_ctx {
308+
struct work_struct work;
309+
struct buffer_head *bh;
310+
};
311+
312+
static void decrypt_bh(struct work_struct *work)
313+
{
314+
struct decrypt_bh_ctx *ctx =
315+
container_of(work, struct decrypt_bh_ctx, work);
316+
struct buffer_head *bh = ctx->bh;
317+
int err;
318+
319+
err = fscrypt_decrypt_pagecache_blocks(bh->b_page, bh->b_size,
320+
bh_offset(bh));
321+
end_buffer_async_read(bh, err == 0);
322+
kfree(ctx);
323+
}
324+
325+
/*
326+
* I/O completion handler for block_read_full_page() - pages
327+
* which come unlocked at the end of I/O.
328+
*/
329+
static void end_buffer_async_read_io(struct buffer_head *bh, int uptodate)
330+
{
331+
/* Decrypt if needed */
332+
if (uptodate && IS_ENABLED(CONFIG_FS_ENCRYPTION) &&
333+
IS_ENCRYPTED(bh->b_page->mapping->host) &&
334+
S_ISREG(bh->b_page->mapping->host->i_mode)) {
335+
struct decrypt_bh_ctx *ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
336+
337+
if (ctx) {
338+
INIT_WORK(&ctx->work, decrypt_bh);
339+
ctx->bh = bh;
340+
fscrypt_enqueue_decrypt_work(&ctx->work);
341+
return;
342+
}
343+
uptodate = 0;
344+
}
345+
end_buffer_async_read(bh, uptodate);
346+
}
347+
310348
/*
311349
* Completion handler for block_write_full_page() - pages which are unlocked
312350
* during I/O, and which have PageWriteback cleared upon I/O completion.
@@ -379,7 +417,7 @@ EXPORT_SYMBOL(end_buffer_async_write);
379417
*/
380418
static void mark_buffer_async_read(struct buffer_head *bh)
381419
{
382-
bh->b_end_io = end_buffer_async_read;
420+
bh->b_end_io = end_buffer_async_read_io;
383421
set_buffer_async_read(bh);
384422
}
385423

fs/ext4/ext4.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ struct ext4_system_blocks {
198198
*/
199199
#define EXT4_IO_END_UNWRITTEN 0x0001
200200

201+
struct ext4_io_end_vec {
202+
struct list_head list; /* list of io_end_vec */
203+
loff_t offset; /* offset in the file */
204+
ssize_t size; /* size of the extent */
205+
};
206+
201207
/*
202208
* For converting unwritten extents on a work queue. 'handle' is used for
203209
* buffered writeback.
@@ -211,8 +217,7 @@ typedef struct ext4_io_end {
211217
* bios covering the extent */
212218
unsigned int flag; /* unwritten or not */
213219
atomic_t count; /* reference counter */
214-
loff_t offset; /* offset in the file */
215-
ssize_t size; /* size of the extent */
220+
struct list_head list_vec; /* list of ext4_io_end_vec */
216221
} ext4_io_end_t;
217222

218223
struct ext4_io_submit {
@@ -1579,7 +1584,6 @@ enum {
15791584
EXT4_STATE_NO_EXPAND, /* No space for expansion */
15801585
EXT4_STATE_DA_ALLOC_CLOSE, /* Alloc DA blks on close */
15811586
EXT4_STATE_EXT_MIGRATE, /* Inode is migrating */
1582-
EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/
15831587
EXT4_STATE_NEWENTRY, /* File just added to dir */
15841588
EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */
15851589
EXT4_STATE_EXT_PRECACHED, /* extents have been precached */
@@ -2562,8 +2566,6 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
25622566
struct buffer_head *bh_result, int create);
25632567
int ext4_get_block(struct inode *inode, sector_t iblock,
25642568
struct buffer_head *bh_result, int create);
2565-
int ext4_dio_get_block(struct inode *inode, sector_t iblock,
2566-
struct buffer_head *bh_result, int create);
25672569
int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
25682570
struct buffer_head *bh, int create);
25692571
int ext4_walk_page_buffers(handle_t *handle,
@@ -2606,7 +2608,6 @@ extern int ext4_can_truncate(struct inode *inode);
26062608
extern int ext4_truncate(struct inode *);
26072609
extern int ext4_break_layouts(struct inode *);
26082610
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
2609-
extern int ext4_truncate_restart_trans(handle_t *, struct inode *, int nblocks);
26102611
extern void ext4_set_inode_flags(struct inode *);
26112612
extern int ext4_alloc_da_blocks(struct inode *inode);
26122613
extern void ext4_set_aops(struct inode *inode);
@@ -3266,6 +3267,8 @@ extern long ext4_fallocate(struct file *file, int mode, loff_t offset,
32663267
loff_t len);
32673268
extern int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
32683269
loff_t offset, ssize_t len);
3270+
extern int ext4_convert_unwritten_io_end_vec(handle_t *handle,
3271+
ext4_io_end_t *io_end);
32693272
extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
32703273
struct ext4_map_blocks *map, int flags);
32713274
extern int ext4_ext_calc_metadata_amount(struct inode *inode,
@@ -3298,6 +3301,10 @@ extern int ext4_swap_extents(handle_t *handle, struct inode *inode1,
32983301
ext4_lblk_t lblk2, ext4_lblk_t count,
32993302
int mark_unwritten,int *err);
33003303
extern int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu);
3304+
extern int ext4_datasem_ensure_credits(handle_t *handle, struct inode *inode,
3305+
int check_cred, int restart_cred,
3306+
int revoke_cred);
3307+
33013308

33023309
/* move_extent.c */
33033310
extern void ext4_double_down_write_data_sem(struct inode *first,
@@ -3324,6 +3331,8 @@ extern int ext4_bio_write_page(struct ext4_io_submit *io,
33243331
int len,
33253332
struct writeback_control *wbc,
33263333
bool keep_towrite);
3334+
extern struct ext4_io_end_vec *ext4_alloc_io_end_vec(ext4_io_end_t *io_end);
3335+
extern struct ext4_io_end_vec *ext4_last_io_end_vec(ext4_io_end_t *io_end);
33273336

33283337
/* mmp.c */
33293338
extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t);
@@ -3381,6 +3390,7 @@ static inline void ext4_clear_io_unwritten_flag(ext4_io_end_t *io_end)
33813390
}
33823391

33833392
extern const struct iomap_ops ext4_iomap_ops;
3393+
extern const struct iomap_ops ext4_iomap_report_ops;
33843394

33853395
static inline int ext4_buffer_uptodate(struct buffer_head *bh)
33863396
{

fs/ext4/ext4_jbd2.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,23 @@ static int ext4_journal_check_start(struct super_block *sb)
6565
}
6666

6767
handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
68-
int type, int blocks, int rsv_blocks)
68+
int type, int blocks, int rsv_blocks,
69+
int revoke_creds)
6970
{
7071
journal_t *journal;
7172
int err;
7273

73-
trace_ext4_journal_start(sb, blocks, rsv_blocks, _RET_IP_);
74+
trace_ext4_journal_start(sb, blocks, rsv_blocks, revoke_creds,
75+
_RET_IP_);
7476
err = ext4_journal_check_start(sb);
7577
if (err < 0)
7678
return ERR_PTR(err);
7779

7880
journal = EXT4_SB(sb)->s_journal;
7981
if (!journal)
8082
return ext4_get_nojournal();
81-
return jbd2__journal_start(journal, blocks, rsv_blocks, GFP_NOFS,
82-
type, line);
83+
return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds,
84+
GFP_NOFS, type, line);
8385
}
8486

8587
int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
@@ -119,8 +121,8 @@ handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
119121
return ext4_get_nojournal();
120122

121123
sb = handle->h_journal->j_private;
122-
trace_ext4_journal_start_reserved(sb, handle->h_buffer_credits,
123-
_RET_IP_);
124+
trace_ext4_journal_start_reserved(sb,
125+
jbd2_handle_buffer_credits(handle), _RET_IP_);
124126
err = ext4_journal_check_start(sb);
125127
if (err < 0) {
126128
jbd2_journal_free_reserved(handle);
@@ -133,6 +135,19 @@ handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
133135
return handle;
134136
}
135137

138+
int __ext4_journal_ensure_credits(handle_t *handle, int check_cred,
139+
int extend_cred, int revoke_cred)
140+
{
141+
if (!ext4_handle_valid(handle))
142+
return 0;
143+
if (jbd2_handle_buffer_credits(handle) >= check_cred &&
144+
handle->h_revoke_credits >= revoke_cred)
145+
return 0;
146+
extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle));
147+
revoke_cred = max(0, revoke_cred - handle->h_revoke_credits);
148+
return ext4_journal_extend(handle, extend_cred, revoke_cred);
149+
}
150+
136151
static void ext4_journal_abort_handle(const char *caller, unsigned int line,
137152
const char *err_fn,
138153
struct buffer_head *bh,
@@ -278,7 +293,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
278293
handle->h_type,
279294
handle->h_line_no,
280295
handle->h_requested_credits,
281-
handle->h_buffer_credits, err);
296+
jbd2_handle_buffer_credits(handle), err);
282297
return err;
283298
}
284299
ext4_error_inode(inode, where, line,
@@ -289,7 +304,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
289304
handle->h_type,
290305
handle->h_line_no,
291306
handle->h_requested_credits,
292-
handle->h_buffer_credits, err);
307+
jbd2_handle_buffer_credits(handle),
308+
err);
293309
}
294310
} else {
295311
if (inode)

0 commit comments

Comments
 (0)