Skip to content

Commit 9daee91

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: "Add new ioctls to set and get the file system UUID in the ext4 superblock and improved the performance of the online resizing of file systems with bigalloc enabled. Fixed a lot of bugs, in particular for the inline data feature, potential races when creating and deleting inodes with shared extended attribute blocks, and the handling of directory blocks which are corrupted" * tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (37 commits) ext4: add ioctls to get/set the ext4 superblock uuid ext4: avoid resizing to a partial cluster size ext4: reduce computation of overhead during resize jbd2: fix assertion 'jh->b_frozen_data == NULL' failure when journal aborted ext4: block range must be validated before use in ext4_mb_clear_bb() mbcache: automatically delete entries from cache on freeing mbcache: Remove mb_cache_entry_delete() ext2: avoid deleting xattr block that is being reused ext2: unindent codeblock in ext2_xattr_set() ext2: factor our freeing of xattr block reference ext4: fix race when reusing xattr blocks ext4: unindent codeblock in ext4_xattr_block_set() ext4: remove EA inode entry from mbcache on inode eviction mbcache: add functions to delete entry if unused mbcache: don't reclaim used entries ext4: make sure ext4_append() always allocates new block ext4: check if directory block is within i_size ext4: reflect mb_optimize_scan value in options file ext4: avoid remove directory when directory is corrupted ext4: aligned '*' in comments ...
2 parents fa9db65 + d95efb1 commit 9daee91

28 files changed

+678
-386
lines changed

Documentation/filesystems/ext4/blockmap.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.. SPDX-License-Identifier: GPL-2.0
22
33
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
4-
| i.i_block Offset | Where It Points |
4+
| i.i_block Offset | Where It Points |
55
+=====================+==============================================================================================================================================================================================================================+
66
| 0 to 11 | Direct map to file blocks 0 to 11. |
77
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

fs/ext2/xattr.c

Lines changed: 78 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -517,36 +517,36 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
517517
/* Here we know that we can set the new attribute. */
518518

519519
if (header) {
520-
/* assert(header == HDR(bh)); */
520+
int offset;
521+
521522
lock_buffer(bh);
522523
if (header->h_refcount == cpu_to_le32(1)) {
523524
__u32 hash = le32_to_cpu(header->h_hash);
525+
struct mb_cache_entry *oe;
524526

525-
ea_bdebug(bh, "modifying in-place");
527+
oe = mb_cache_entry_delete_or_get(EA_BLOCK_CACHE(inode),
528+
hash, bh->b_blocknr);
529+
if (!oe) {
530+
ea_bdebug(bh, "modifying in-place");
531+
goto update_block;
532+
}
526533
/*
527-
* This must happen under buffer lock for
528-
* ext2_xattr_set2() to reliably detect modified block
534+
* Someone is trying to reuse the block, leave it alone
529535
*/
530-
mb_cache_entry_delete(EA_BLOCK_CACHE(inode), hash,
531-
bh->b_blocknr);
532-
533-
/* keep the buffer locked while modifying it. */
534-
} else {
535-
int offset;
536-
537-
unlock_buffer(bh);
538-
ea_bdebug(bh, "cloning");
539-
header = kmemdup(HDR(bh), bh->b_size, GFP_KERNEL);
540-
error = -ENOMEM;
541-
if (header == NULL)
542-
goto cleanup;
543-
header->h_refcount = cpu_to_le32(1);
544-
545-
offset = (char *)here - bh->b_data;
546-
here = ENTRY((char *)header + offset);
547-
offset = (char *)last - bh->b_data;
548-
last = ENTRY((char *)header + offset);
536+
mb_cache_entry_put(EA_BLOCK_CACHE(inode), oe);
549537
}
538+
unlock_buffer(bh);
539+
ea_bdebug(bh, "cloning");
540+
header = kmemdup(HDR(bh), bh->b_size, GFP_KERNEL);
541+
error = -ENOMEM;
542+
if (header == NULL)
543+
goto cleanup;
544+
header->h_refcount = cpu_to_le32(1);
545+
546+
offset = (char *)here - bh->b_data;
547+
here = ENTRY((char *)header + offset);
548+
offset = (char *)last - bh->b_data;
549+
last = ENTRY((char *)header + offset);
550550
} else {
551551
/* Allocate a buffer where we construct the new block. */
552552
header = kzalloc(sb->s_blocksize, GFP_KERNEL);
@@ -559,6 +559,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
559559
last = here = ENTRY(header+1);
560560
}
561561

562+
update_block:
562563
/* Iff we are modifying the block in-place, bh is locked here. */
563564

564565
if (not_found) {
@@ -651,6 +652,55 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
651652
return error;
652653
}
653654

655+
static void ext2_xattr_release_block(struct inode *inode,
656+
struct buffer_head *bh)
657+
{
658+
struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
659+
660+
retry_ref:
661+
lock_buffer(bh);
662+
if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
663+
__u32 hash = le32_to_cpu(HDR(bh)->h_hash);
664+
struct mb_cache_entry *oe;
665+
666+
/*
667+
* This must happen under buffer lock to properly
668+
* serialize with ext2_xattr_set() reusing the block.
669+
*/
670+
oe = mb_cache_entry_delete_or_get(ea_block_cache, hash,
671+
bh->b_blocknr);
672+
if (oe) {
673+
/*
674+
* Someone is trying to reuse the block. Wait
675+
* and retry.
676+
*/
677+
unlock_buffer(bh);
678+
mb_cache_entry_wait_unused(oe);
679+
mb_cache_entry_put(ea_block_cache, oe);
680+
goto retry_ref;
681+
}
682+
683+
/* Free the old block. */
684+
ea_bdebug(bh, "freeing");
685+
ext2_free_blocks(inode, bh->b_blocknr, 1);
686+
/* We let our caller release bh, so we
687+
* need to duplicate the buffer before. */
688+
get_bh(bh);
689+
bforget(bh);
690+
unlock_buffer(bh);
691+
} else {
692+
/* Decrement the refcount only. */
693+
le32_add_cpu(&HDR(bh)->h_refcount, -1);
694+
dquot_free_block(inode, 1);
695+
mark_buffer_dirty(bh);
696+
unlock_buffer(bh);
697+
ea_bdebug(bh, "refcount now=%d",
698+
le32_to_cpu(HDR(bh)->h_refcount));
699+
if (IS_SYNC(inode))
700+
sync_dirty_buffer(bh);
701+
}
702+
}
703+
654704
/*
655705
* Second half of ext2_xattr_set(): Update the file system.
656706
*/
@@ -747,34 +797,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
747797
* If there was an old block and we are no longer using it,
748798
* release the old block.
749799
*/
750-
lock_buffer(old_bh);
751-
if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
752-
__u32 hash = le32_to_cpu(HDR(old_bh)->h_hash);
753-
754-
/*
755-
* This must happen under buffer lock for
756-
* ext2_xattr_set2() to reliably detect freed block
757-
*/
758-
mb_cache_entry_delete(ea_block_cache, hash,
759-
old_bh->b_blocknr);
760-
/* Free the old block. */
761-
ea_bdebug(old_bh, "freeing");
762-
ext2_free_blocks(inode, old_bh->b_blocknr, 1);
763-
mark_inode_dirty(inode);
764-
/* We let our caller release old_bh, so we
765-
* need to duplicate the buffer before. */
766-
get_bh(old_bh);
767-
bforget(old_bh);
768-
} else {
769-
/* Decrement the refcount only. */
770-
le32_add_cpu(&HDR(old_bh)->h_refcount, -1);
771-
dquot_free_block_nodirty(inode, 1);
772-
mark_inode_dirty(inode);
773-
mark_buffer_dirty(old_bh);
774-
ea_bdebug(old_bh, "refcount now=%d",
775-
le32_to_cpu(HDR(old_bh)->h_refcount));
776-
}
777-
unlock_buffer(old_bh);
800+
ext2_xattr_release_block(inode, old_bh);
778801
}
779802

780803
cleanup:
@@ -828,30 +851,7 @@ ext2_xattr_delete_inode(struct inode *inode)
828851
EXT2_I(inode)->i_file_acl);
829852
goto cleanup;
830853
}
831-
lock_buffer(bh);
832-
if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
833-
__u32 hash = le32_to_cpu(HDR(bh)->h_hash);
834-
835-
/*
836-
* This must happen under buffer lock for ext2_xattr_set2() to
837-
* reliably detect freed block
838-
*/
839-
mb_cache_entry_delete(EA_BLOCK_CACHE(inode), hash,
840-
bh->b_blocknr);
841-
ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
842-
get_bh(bh);
843-
bforget(bh);
844-
unlock_buffer(bh);
845-
} else {
846-
le32_add_cpu(&HDR(bh)->h_refcount, -1);
847-
ea_bdebug(bh, "refcount now=%d",
848-
le32_to_cpu(HDR(bh)->h_refcount));
849-
unlock_buffer(bh);
850-
mark_buffer_dirty(bh);
851-
if (IS_SYNC(inode))
852-
sync_dirty_buffer(bh);
853-
dquot_free_block_nodirty(inode, 1);
854-
}
854+
ext2_xattr_release_block(inode, bh);
855855
EXT2_I(inode)->i_file_acl = 0;
856856

857857
cleanup:
@@ -943,7 +943,7 @@ ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
943943
if (!header->h_hash)
944944
return NULL; /* never share */
945945
ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
946-
again:
946+
947947
ce = mb_cache_entry_find_first(ea_block_cache, hash);
948948
while (ce) {
949949
struct buffer_head *bh;
@@ -955,22 +955,8 @@ ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
955955
inode->i_ino, (unsigned long) ce->e_value);
956956
} else {
957957
lock_buffer(bh);
958-
/*
959-
* We have to be careful about races with freeing or
960-
* rehashing of xattr block. Once we hold buffer lock
961-
* xattr block's state is stable so we can check
962-
* whether the block got freed / rehashed or not.
963-
* Since we unhash mbcache entry under buffer lock when
964-
* freeing / rehashing xattr block, checking whether
965-
* entry is still hashed is reliable.
966-
*/
967-
if (hlist_bl_unhashed(&ce->e_hash_list)) {
968-
mb_cache_entry_put(ea_block_cache, ce);
969-
unlock_buffer(bh);
970-
brelse(bh);
971-
goto again;
972-
} else if (le32_to_cpu(HDR(bh)->h_refcount) >
973-
EXT2_XATTR_REFCOUNT_MAX) {
958+
if (le32_to_cpu(HDR(bh)->h_refcount) >
959+
EXT2_XATTR_REFCOUNT_MAX) {
974960
ea_idebug(inode, "block %ld refcount %d>%d",
975961
(unsigned long) ce->e_value,
976962
le32_to_cpu(HDR(bh)->h_refcount),

fs/ext4/balloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
666666
* it's possible we've just missed a transaction commit here,
667667
* so ignore the returned status
668668
*/
669-
jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
669+
ext4_debug("%s: retrying operation after ENOSPC\n", sb->s_id);
670670
(void) jbd2_journal_force_commit_nested(sbi->s_journal);
671671
return 1;
672672
}

fs/ext4/ext4.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,8 @@ enum {
724724
#define EXT4_IOC_GETSTATE _IOW('f', 41, __u32)
725725
#define EXT4_IOC_GET_ES_CACHE _IOWR('f', 42, struct fiemap)
726726
#define EXT4_IOC_CHECKPOINT _IOW('f', 43, __u32)
727+
#define EXT4_IOC_GETFSUUID _IOR('f', 44, struct fsuuid)
728+
#define EXT4_IOC_SETFSUUID _IOW('f', 44, struct fsuuid)
727729

728730
#define EXT4_IOC_SHUTDOWN _IOR ('X', 125, __u32)
729731

@@ -753,6 +755,15 @@ enum {
753755
EXT4_IOC_CHECKPOINT_FLAG_ZEROOUT | \
754756
EXT4_IOC_CHECKPOINT_FLAG_DRY_RUN)
755757

758+
/*
759+
* Structure for EXT4_IOC_GETFSUUID/EXT4_IOC_SETFSUUID
760+
*/
761+
struct fsuuid {
762+
__u32 fsu_len;
763+
__u32 fsu_flags;
764+
__u8 fsu_uuid[];
765+
};
766+
756767
#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
757768
/*
758769
* ioctl commands in 32 bit emulation
@@ -3016,7 +3027,7 @@ int ext4_fileattr_set(struct user_namespace *mnt_userns,
30163027
struct dentry *dentry, struct fileattr *fa);
30173028
int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa);
30183029
extern void ext4_reset_inode_seed(struct inode *inode);
3019-
int ext4_update_overhead(struct super_block *sb);
3030+
int ext4_update_overhead(struct super_block *sb, bool force);
30203031

30213032
/* migrate.c */
30223033
extern int ext4_ext_migrate(struct inode *);
@@ -3583,6 +3594,7 @@ extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode,
35833594
extern int ext4_inline_data_fiemap(struct inode *inode,
35843595
struct fiemap_extent_info *fieinfo,
35853596
int *has_inline, __u64 start, __u64 len);
3597+
extern void *ext4_read_inline_link(struct inode *inode);
35863598

35873599
struct iomap;
35883600
extern int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap);
@@ -3799,7 +3811,7 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh)
37993811
extern wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
38003812

38013813
extern int ext4_resize_begin(struct super_block *sb);
3802-
extern void ext4_resize_end(struct super_block *sb);
3814+
extern int ext4_resize_end(struct super_block *sb, bool update_backups);
38033815

38043816
static inline void ext4_set_io_unwritten_flag(struct inode *inode,
38053817
struct ext4_io_end *io_end)

fs/ext4/ext4_jbd2.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,7 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
267267
trace_ext4_forget(inode, is_metadata, blocknr);
268268
BUFFER_TRACE(bh, "enter");
269269

270-
jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
271-
"data mode %x\n",
270+
ext4_debug("forgetting bh %p: is_metadata=%d, mode %o, data mode %x\n",
272271
bh, is_metadata, inode->i_mode,
273272
test_opt(inode->i_sb, DATA_FLAGS));
274273

0 commit comments

Comments
 (0)