diff options
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/super.c | 34 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 52 |
3 files changed, 59 insertions, 28 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index fe92a63c86cb..68ddd24db9a2 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1114,6 +1114,7 @@ struct ext4_inode_info { | |||
1114 | /* | 1114 | /* |
1115 | * Mount flags set via mount options or defaults | 1115 | * Mount flags set via mount options or defaults |
1116 | */ | 1116 | */ |
1117 | #define EXT4_MOUNT_NO_MBCACHE 0x00001 /* Do not use mbcache */ | ||
1117 | #define EXT4_MOUNT_GRPID 0x00004 /* Create files with directory's group */ | 1118 | #define EXT4_MOUNT_GRPID 0x00004 /* Create files with directory's group */ |
1118 | #define EXT4_MOUNT_DEBUG 0x00008 /* Some debugging messages */ | 1119 | #define EXT4_MOUNT_DEBUG 0x00008 /* Some debugging messages */ |
1119 | #define EXT4_MOUNT_ERRORS_CONT 0x00010 /* Continue on errors */ | 1120 | #define EXT4_MOUNT_ERRORS_CONT 0x00010 /* Continue on errors */ |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 5ac76e8d4013..1fec35bd4084 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1336,7 +1336,7 @@ enum { | |||
1336 | Opt_inode_readahead_blks, Opt_journal_ioprio, | 1336 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
1337 | Opt_dioread_nolock, Opt_dioread_lock, | 1337 | Opt_dioread_nolock, Opt_dioread_lock, |
1338 | Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, | 1338 | Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, |
1339 | Opt_max_dir_size_kb, Opt_nojournal_checksum, | 1339 | Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache, |
1340 | }; | 1340 | }; |
1341 | 1341 | ||
1342 | static const match_table_t tokens = { | 1342 | static const match_table_t tokens = { |
@@ -1419,6 +1419,8 @@ static const match_table_t tokens = { | |||
1419 | {Opt_noinit_itable, "noinit_itable"}, | 1419 | {Opt_noinit_itable, "noinit_itable"}, |
1420 | {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, | 1420 | {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, |
1421 | {Opt_test_dummy_encryption, "test_dummy_encryption"}, | 1421 | {Opt_test_dummy_encryption, "test_dummy_encryption"}, |
1422 | {Opt_nombcache, "nombcache"}, | ||
1423 | {Opt_nombcache, "no_mbcache"}, /* for backward compatibility */ | ||
1422 | {Opt_removed, "check=none"}, /* mount option from ext2/3 */ | 1424 | {Opt_removed, "check=none"}, /* mount option from ext2/3 */ |
1423 | {Opt_removed, "nocheck"}, /* mount option from ext2/3 */ | 1425 | {Opt_removed, "nocheck"}, /* mount option from ext2/3 */ |
1424 | {Opt_removed, "reservation"}, /* mount option from ext2/3 */ | 1426 | {Opt_removed, "reservation"}, /* mount option from ext2/3 */ |
@@ -1626,6 +1628,7 @@ static const struct mount_opts { | |||
1626 | {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT}, | 1628 | {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT}, |
1627 | {Opt_max_dir_size_kb, 0, MOPT_GTE0}, | 1629 | {Opt_max_dir_size_kb, 0, MOPT_GTE0}, |
1628 | {Opt_test_dummy_encryption, 0, MOPT_GTE0}, | 1630 | {Opt_test_dummy_encryption, 0, MOPT_GTE0}, |
1631 | {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET}, | ||
1629 | {Opt_err, 0, 0} | 1632 | {Opt_err, 0, 0} |
1630 | }; | 1633 | }; |
1631 | 1634 | ||
@@ -4080,19 +4083,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
4080 | sbi->s_journal->j_commit_callback = ext4_journal_commit_callback; | 4083 | sbi->s_journal->j_commit_callback = ext4_journal_commit_callback; |
4081 | 4084 | ||
4082 | no_journal: | 4085 | no_journal: |
4083 | sbi->s_ea_block_cache = ext4_xattr_create_cache(); | 4086 | if (!test_opt(sb, NO_MBCACHE)) { |
4084 | if (!sbi->s_ea_block_cache) { | 4087 | sbi->s_ea_block_cache = ext4_xattr_create_cache(); |
4085 | ext4_msg(sb, KERN_ERR, "Failed to create ea_block_cache"); | 4088 | if (!sbi->s_ea_block_cache) { |
4086 | goto failed_mount_wq; | ||
4087 | } | ||
4088 | |||
4089 | if (ext4_has_feature_ea_inode(sb)) { | ||
4090 | sbi->s_ea_inode_cache = ext4_xattr_create_cache(); | ||
4091 | if (!sbi->s_ea_inode_cache) { | ||
4092 | ext4_msg(sb, KERN_ERR, | 4089 | ext4_msg(sb, KERN_ERR, |
4093 | "Failed to create ea_inode_cache"); | 4090 | "Failed to create ea_block_cache"); |
4094 | goto failed_mount_wq; | 4091 | goto failed_mount_wq; |
4095 | } | 4092 | } |
4093 | |||
4094 | if (ext4_has_feature_ea_inode(sb)) { | ||
4095 | sbi->s_ea_inode_cache = ext4_xattr_create_cache(); | ||
4096 | if (!sbi->s_ea_inode_cache) { | ||
4097 | ext4_msg(sb, KERN_ERR, | ||
4098 | "Failed to create ea_inode_cache"); | ||
4099 | goto failed_mount_wq; | ||
4100 | } | ||
4101 | } | ||
4096 | } | 4102 | } |
4097 | 4103 | ||
4098 | if ((DUMMY_ENCRYPTION_ENABLED(sbi) || ext4_has_feature_encrypt(sb)) && | 4104 | if ((DUMMY_ENCRYPTION_ENABLED(sbi) || ext4_has_feature_encrypt(sb)) && |
@@ -4989,6 +4995,12 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
4989 | } | 4995 | } |
4990 | } | 4996 | } |
4991 | 4997 | ||
4998 | if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_NO_MBCACHE) { | ||
4999 | ext4_msg(sb, KERN_ERR, "can't enable nombcache during remount"); | ||
5000 | err = -EINVAL; | ||
5001 | goto restore_opts; | ||
5002 | } | ||
5003 | |||
4992 | if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX) { | 5004 | if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX) { |
4993 | ext4_msg(sb, KERN_WARNING, "warning: refusing change of " | 5005 | ext4_msg(sb, KERN_WARNING, "warning: refusing change of " |
4994 | "dax flag with busy inodes while remounting"); | 5006 | "dax flag with busy inodes while remounting"); |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index a5ad0ccdd1cb..34fa37e7744c 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -991,10 +991,13 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, | |||
991 | set_nlink(ea_inode, 1); | 991 | set_nlink(ea_inode, 1); |
992 | ext4_orphan_del(handle, ea_inode); | 992 | ext4_orphan_del(handle, ea_inode); |
993 | 993 | ||
994 | hash = ext4_xattr_inode_get_hash(ea_inode); | 994 | if (ea_inode_cache) { |
995 | mb_cache_entry_create(ea_inode_cache, GFP_NOFS, hash, | 995 | hash = ext4_xattr_inode_get_hash(ea_inode); |
996 | ea_inode->i_ino, | 996 | mb_cache_entry_create(ea_inode_cache, |
997 | true /* reusable */); | 997 | GFP_NOFS, hash, |
998 | ea_inode->i_ino, | ||
999 | true /* reusable */); | ||
1000 | } | ||
998 | } | 1001 | } |
999 | } else { | 1002 | } else { |
1000 | WARN_ONCE(ref_count < 0, "EA inode %lu ref_count=%lld", | 1003 | WARN_ONCE(ref_count < 0, "EA inode %lu ref_count=%lld", |
@@ -1008,9 +1011,11 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, | |||
1008 | clear_nlink(ea_inode); | 1011 | clear_nlink(ea_inode); |
1009 | ext4_orphan_add(handle, ea_inode); | 1012 | ext4_orphan_add(handle, ea_inode); |
1010 | 1013 | ||
1011 | hash = ext4_xattr_inode_get_hash(ea_inode); | 1014 | if (ea_inode_cache) { |
1012 | mb_cache_entry_delete(ea_inode_cache, hash, | 1015 | hash = ext4_xattr_inode_get_hash(ea_inode); |
1013 | ea_inode->i_ino); | 1016 | mb_cache_entry_delete(ea_inode_cache, hash, |
1017 | ea_inode->i_ino); | ||
1018 | } | ||
1014 | } | 1019 | } |
1015 | } | 1020 | } |
1016 | 1021 | ||
@@ -1194,7 +1199,9 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
1194 | * This must happen under buffer lock for | 1199 | * This must happen under buffer lock for |
1195 | * ext4_xattr_block_set() to reliably detect freed block | 1200 | * ext4_xattr_block_set() to reliably detect freed block |
1196 | */ | 1201 | */ |
1197 | mb_cache_entry_delete(ea_block_cache, hash, bh->b_blocknr); | 1202 | if (ea_block_cache) |
1203 | mb_cache_entry_delete(ea_block_cache, hash, | ||
1204 | bh->b_blocknr); | ||
1198 | get_bh(bh); | 1205 | get_bh(bh); |
1199 | unlock_buffer(bh); | 1206 | unlock_buffer(bh); |
1200 | 1207 | ||
@@ -1214,11 +1221,13 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
1214 | if (ref == EXT4_XATTR_REFCOUNT_MAX - 1) { | 1221 | if (ref == EXT4_XATTR_REFCOUNT_MAX - 1) { |
1215 | struct mb_cache_entry *ce; | 1222 | struct mb_cache_entry *ce; |
1216 | 1223 | ||
1217 | ce = mb_cache_entry_get(ea_block_cache, hash, | 1224 | if (ea_block_cache) { |
1218 | bh->b_blocknr); | 1225 | ce = mb_cache_entry_get(ea_block_cache, hash, |
1219 | if (ce) { | 1226 | bh->b_blocknr); |
1220 | ce->e_reusable = 1; | 1227 | if (ce) { |
1221 | mb_cache_entry_put(ea_block_cache, ce); | 1228 | ce->e_reusable = 1; |
1229 | mb_cache_entry_put(ea_block_cache, ce); | ||
1230 | } | ||
1222 | } | 1231 | } |
1223 | } | 1232 | } |
1224 | 1233 | ||
@@ -1395,6 +1404,9 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value, | |||
1395 | struct mb_cache *ea_inode_cache = EA_INODE_CACHE(inode); | 1404 | struct mb_cache *ea_inode_cache = EA_INODE_CACHE(inode); |
1396 | void *ea_data; | 1405 | void *ea_data; |
1397 | 1406 | ||
1407 | if (!ea_inode_cache) | ||
1408 | return NULL; | ||
1409 | |||
1398 | ce = mb_cache_entry_find_first(ea_inode_cache, hash); | 1410 | ce = mb_cache_entry_find_first(ea_inode_cache, hash); |
1399 | if (!ce) | 1411 | if (!ce) |
1400 | return NULL; | 1412 | return NULL; |
@@ -1465,8 +1477,9 @@ static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode, | |||
1465 | return err; | 1477 | return err; |
1466 | } | 1478 | } |
1467 | 1479 | ||
1468 | mb_cache_entry_create(EA_INODE_CACHE(inode), GFP_NOFS, hash, | 1480 | if (EA_INODE_CACHE(inode)) |
1469 | ea_inode->i_ino, true /* reusable */); | 1481 | mb_cache_entry_create(EA_INODE_CACHE(inode), GFP_NOFS, hash, |
1482 | ea_inode->i_ino, true /* reusable */); | ||
1470 | 1483 | ||
1471 | *ret_inode = ea_inode; | 1484 | *ret_inode = ea_inode; |
1472 | return 0; | 1485 | return 0; |
@@ -1793,8 +1806,9 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
1793 | * ext4_xattr_block_set() to reliably detect modified | 1806 | * ext4_xattr_block_set() to reliably detect modified |
1794 | * block | 1807 | * block |
1795 | */ | 1808 | */ |
1796 | mb_cache_entry_delete(ea_block_cache, hash, | 1809 | if (ea_block_cache) |
1797 | bs->bh->b_blocknr); | 1810 | mb_cache_entry_delete(ea_block_cache, hash, |
1811 | bs->bh->b_blocknr); | ||
1798 | ea_bdebug(bs->bh, "modifying in-place"); | 1812 | ea_bdebug(bs->bh, "modifying in-place"); |
1799 | error = ext4_xattr_set_entry(i, s, handle, inode, | 1813 | error = ext4_xattr_set_entry(i, s, handle, inode, |
1800 | true /* is_block */); | 1814 | true /* is_block */); |
@@ -2883,6 +2897,8 @@ ext4_xattr_block_cache_insert(struct mb_cache *ea_block_cache, | |||
2883 | EXT4_XATTR_REFCOUNT_MAX; | 2897 | EXT4_XATTR_REFCOUNT_MAX; |
2884 | int error; | 2898 | int error; |
2885 | 2899 | ||
2900 | if (!ea_block_cache) | ||
2901 | return; | ||
2886 | error = mb_cache_entry_create(ea_block_cache, GFP_NOFS, hash, | 2902 | error = mb_cache_entry_create(ea_block_cache, GFP_NOFS, hash, |
2887 | bh->b_blocknr, reusable); | 2903 | bh->b_blocknr, reusable); |
2888 | if (error) { | 2904 | if (error) { |
@@ -2949,6 +2965,8 @@ ext4_xattr_block_cache_find(struct inode *inode, | |||
2949 | struct mb_cache_entry *ce; | 2965 | struct mb_cache_entry *ce; |
2950 | struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode); | 2966 | struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode); |
2951 | 2967 | ||
2968 | if (!ea_block_cache) | ||
2969 | return NULL; | ||
2952 | if (!header->h_hash) | 2970 | if (!header->h_hash) |
2953 | return NULL; /* never share */ | 2971 | return NULL; /* never share */ |
2954 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); | 2972 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); |