aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4.h5
-rw-r--r--fs/ext4/ialloc.c19
-rw-r--r--fs/ext4/super.c52
3 files changed, 65 insertions, 11 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0fe078d368d0..4c5fe37b237d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1574,6 +1574,11 @@ struct ext4_li_request {
1574 unsigned long lr_timeout; 1574 unsigned long lr_timeout;
1575}; 1575};
1576 1576
1577struct ext4_features {
1578 struct kobject f_kobj;
1579 struct completion f_kobj_unregister;
1580};
1581
1577/* 1582/*
1578 * Function prototypes 1583 * Function prototypes
1579 */ 1584 */
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index e428f23215c0..87d228aae6b0 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1274,6 +1274,16 @@ extern int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
1274 ext4_itable_unused_count(sb, gdp)), 1274 ext4_itable_unused_count(sb, gdp)),
1275 sbi->s_inodes_per_block); 1275 sbi->s_inodes_per_block);
1276 1276
1277 if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) {
1278 ext4_error(sb, "Something is wrong with group %u\n"
1279 "Used itable blocks: %d"
1280 "itable unused count: %u\n",
1281 group, used_blks,
1282 ext4_itable_unused_count(sb, gdp));
1283 ret = 1;
1284 goto out;
1285 }
1286
1277 blk = ext4_inode_table(sb, gdp) + used_blks; 1287 blk = ext4_inode_table(sb, gdp) + used_blks;
1278 num = sbi->s_itb_per_group - used_blks; 1288 num = sbi->s_itb_per_group - used_blks;
1279 1289
@@ -1283,15 +1293,6 @@ extern int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
1283 if (ret) 1293 if (ret)
1284 goto err_out; 1294 goto err_out;
1285 1295
1286 if (unlikely(num > EXT4_INODES_PER_GROUP(sb))) {
1287 ext4_error(sb, "Something is wrong with group %u\n"
1288 "Used itable blocks: %d"
1289 "Itable blocks per group: %lu\n",
1290 group, used_blks, sbi->s_itb_per_group);
1291 ret = 1;
1292 goto err_out;
1293 }
1294
1295 /* 1296 /*
1296 * Skip zeroout if the inode table is full. But we set the ZEROED 1297 * Skip zeroout if the inode table is full. But we set the ZEROED
1297 * flag anyway, because obviously, when it is full it does not need 1298 * flag anyway, because obviously, when it is full it does not need
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 5066537e5a38..c5b890140d01 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -57,6 +57,7 @@ struct proc_dir_entry *ext4_proc_root;
57static struct kset *ext4_kset; 57static struct kset *ext4_kset;
58struct ext4_lazy_init *ext4_li_info; 58struct ext4_lazy_init *ext4_li_info;
59struct mutex ext4_li_mtx; 59struct mutex ext4_li_mtx;
60struct ext4_features *ext4_feat;
60 61
61static int ext4_load_journal(struct super_block *, struct ext4_super_block *, 62static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
62 unsigned long journal_devnum); 63 unsigned long journal_devnum);
@@ -709,6 +710,7 @@ static void ext4_put_super(struct super_block *sb)
709 struct ext4_super_block *es = sbi->s_es; 710 struct ext4_super_block *es = sbi->s_es;
710 int i, err; 711 int i, err;
711 712
713 ext4_unregister_li_request(sb);
712 dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); 714 dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
713 715
714 flush_workqueue(sbi->dio_unwritten_wq); 716 flush_workqueue(sbi->dio_unwritten_wq);
@@ -727,7 +729,6 @@ static void ext4_put_super(struct super_block *sb)
727 } 729 }
728 730
729 del_timer(&sbi->s_err_report); 731 del_timer(&sbi->s_err_report);
730 ext4_unregister_li_request(sb);
731 ext4_release_system_zone(sb); 732 ext4_release_system_zone(sb);
732 ext4_mb_release(sb); 733 ext4_mb_release(sb);
733 ext4_ext_release(sb); 734 ext4_ext_release(sb);
@@ -2416,6 +2417,7 @@ static struct ext4_attr ext4_attr_##_name = { \
2416#define EXT4_ATTR(name, mode, show, store) \ 2417#define EXT4_ATTR(name, mode, show, store) \
2417static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) 2418static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
2418 2419
2420#define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL)
2419#define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL) 2421#define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
2420#define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store) 2422#define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
2421#define EXT4_RW_ATTR_SBI_UI(name, elname) \ 2423#define EXT4_RW_ATTR_SBI_UI(name, elname) \
@@ -2452,6 +2454,14 @@ static struct attribute *ext4_attrs[] = {
2452 NULL, 2454 NULL,
2453}; 2455};
2454 2456
2457/* Features this copy of ext4 supports */
2458EXT4_INFO_ATTR(lazy_itable_init);
2459
2460static struct attribute *ext4_feat_attrs[] = {
2461 ATTR_LIST(lazy_itable_init),
2462 NULL,
2463};
2464
2455static ssize_t ext4_attr_show(struct kobject *kobj, 2465static ssize_t ext4_attr_show(struct kobject *kobj,
2456 struct attribute *attr, char *buf) 2466 struct attribute *attr, char *buf)
2457{ 2467{
@@ -2480,7 +2490,6 @@ static void ext4_sb_release(struct kobject *kobj)
2480 complete(&sbi->s_kobj_unregister); 2490 complete(&sbi->s_kobj_unregister);
2481} 2491}
2482 2492
2483
2484static const struct sysfs_ops ext4_attr_ops = { 2493static const struct sysfs_ops ext4_attr_ops = {
2485 .show = ext4_attr_show, 2494 .show = ext4_attr_show,
2486 .store = ext4_attr_store, 2495 .store = ext4_attr_store,
@@ -2492,6 +2501,17 @@ static struct kobj_type ext4_ktype = {
2492 .release = ext4_sb_release, 2501 .release = ext4_sb_release,
2493}; 2502};
2494 2503
2504static void ext4_feat_release(struct kobject *kobj)
2505{
2506 complete(&ext4_feat->f_kobj_unregister);
2507}
2508
2509static struct kobj_type ext4_feat_ktype = {
2510 .default_attrs = ext4_feat_attrs,
2511 .sysfs_ops = &ext4_attr_ops,
2512 .release = ext4_feat_release,
2513};
2514
2495/* 2515/*
2496 * Check whether this filesystem can be mounted based on 2516 * Check whether this filesystem can be mounted based on
2497 * the features present and the RDONLY/RDWR mount requested. 2517 * the features present and the RDONLY/RDWR mount requested.
@@ -4720,6 +4740,30 @@ static struct file_system_type ext4_fs_type = {
4720 .fs_flags = FS_REQUIRES_DEV, 4740 .fs_flags = FS_REQUIRES_DEV,
4721}; 4741};
4722 4742
4743int __init ext4_init_feat_adverts(void)
4744{
4745 struct ext4_features *ef;
4746 int ret = -ENOMEM;
4747
4748 ef = kzalloc(sizeof(struct ext4_features), GFP_KERNEL);
4749 if (!ef)
4750 goto out;
4751
4752 ef->f_kobj.kset = ext4_kset;
4753 init_completion(&ef->f_kobj_unregister);
4754 ret = kobject_init_and_add(&ef->f_kobj, &ext4_feat_ktype, NULL,
4755 "features");
4756 if (ret) {
4757 kfree(ef);
4758 goto out;
4759 }
4760
4761 ext4_feat = ef;
4762 ret = 0;
4763out:
4764 return ret;
4765}
4766
4723static int __init init_ext4_fs(void) 4767static int __init init_ext4_fs(void)
4724{ 4768{
4725 int err; 4769 int err;
@@ -4732,6 +4776,9 @@ static int __init init_ext4_fs(void)
4732 if (!ext4_kset) 4776 if (!ext4_kset)
4733 goto out4; 4777 goto out4;
4734 ext4_proc_root = proc_mkdir("fs/ext4", NULL); 4778 ext4_proc_root = proc_mkdir("fs/ext4", NULL);
4779
4780 err = ext4_init_feat_adverts();
4781
4735 err = init_ext4_mballoc(); 4782 err = init_ext4_mballoc();
4736 if (err) 4783 if (err)
4737 goto out3; 4784 goto out3;
@@ -4760,6 +4807,7 @@ out1:
4760out2: 4807out2:
4761 exit_ext4_mballoc(); 4808 exit_ext4_mballoc();
4762out3: 4809out3:
4810 kfree(ext4_feat);
4763 remove_proc_entry("fs/ext4", NULL); 4811 remove_proc_entry("fs/ext4", NULL);
4764 kset_unregister(ext4_kset); 4812 kset_unregister(ext4_kset);
4765out4: 4813out4: