diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 97 |
1 files changed, 92 insertions, 5 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f1b56ff01208..00c98fab6333 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -80,6 +80,36 @@ static void ext4_destroy_lazyinit_thread(void); | |||
80 | static void ext4_unregister_li_request(struct super_block *sb); | 80 | static void ext4_unregister_li_request(struct super_block *sb); |
81 | static void ext4_clear_request_list(void); | 81 | static void ext4_clear_request_list(void); |
82 | 82 | ||
83 | /* | ||
84 | * Lock ordering | ||
85 | * | ||
86 | * Note the difference between i_mmap_sem (EXT4_I(inode)->i_mmap_sem) and | ||
87 | * i_mmap_rwsem (inode->i_mmap_rwsem)! | ||
88 | * | ||
89 | * page fault path: | ||
90 | * mmap_sem -> sb_start_pagefault -> i_mmap_sem (r) -> transaction start -> | ||
91 | * page lock -> i_data_sem (rw) | ||
92 | * | ||
93 | * buffered write path: | ||
94 | * sb_start_write -> i_mutex -> mmap_sem | ||
95 | * sb_start_write -> i_mutex -> transaction start -> page lock -> | ||
96 | * i_data_sem (rw) | ||
97 | * | ||
98 | * truncate: | ||
99 | * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (w) -> i_mmap_sem (w) -> | ||
100 | * i_mmap_rwsem (w) -> page lock | ||
101 | * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (w) -> i_mmap_sem (w) -> | ||
102 | * transaction start -> i_data_sem (rw) | ||
103 | * | ||
104 | * direct IO: | ||
105 | * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (r) -> mmap_sem | ||
106 | * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (r) -> | ||
107 | * transaction start -> i_data_sem (rw) | ||
108 | * | ||
109 | * writepages: | ||
110 | * transaction start -> page lock(s) -> i_data_sem (rw) | ||
111 | */ | ||
112 | |||
83 | #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) | 113 | #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) |
84 | static struct file_system_type ext2_fs_type = { | 114 | static struct file_system_type ext2_fs_type = { |
85 | .owner = THIS_MODULE, | 115 | .owner = THIS_MODULE, |
@@ -958,6 +988,7 @@ static void init_once(void *foo) | |||
958 | INIT_LIST_HEAD(&ei->i_orphan); | 988 | INIT_LIST_HEAD(&ei->i_orphan); |
959 | init_rwsem(&ei->xattr_sem); | 989 | init_rwsem(&ei->xattr_sem); |
960 | init_rwsem(&ei->i_data_sem); | 990 | init_rwsem(&ei->i_data_sem); |
991 | init_rwsem(&ei->i_mmap_sem); | ||
961 | inode_init_once(&ei->vfs_inode); | 992 | inode_init_once(&ei->vfs_inode); |
962 | } | 993 | } |
963 | 994 | ||
@@ -1066,8 +1097,8 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, | |||
1066 | } | 1097 | } |
1067 | 1098 | ||
1068 | #ifdef CONFIG_QUOTA | 1099 | #ifdef CONFIG_QUOTA |
1069 | #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group") | 1100 | static char *quotatypes[] = INITQFNAMES; |
1070 | #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) | 1101 | #define QTYPE2NAME(t) (quotatypes[t]) |
1071 | 1102 | ||
1072 | static int ext4_write_dquot(struct dquot *dquot); | 1103 | static int ext4_write_dquot(struct dquot *dquot); |
1073 | static int ext4_acquire_dquot(struct dquot *dquot); | 1104 | static int ext4_acquire_dquot(struct dquot *dquot); |
@@ -1100,6 +1131,7 @@ static const struct dquot_operations ext4_quota_operations = { | |||
1100 | .write_info = ext4_write_info, | 1131 | .write_info = ext4_write_info, |
1101 | .alloc_dquot = dquot_alloc, | 1132 | .alloc_dquot = dquot_alloc, |
1102 | .destroy_dquot = dquot_destroy, | 1133 | .destroy_dquot = dquot_destroy, |
1134 | .get_projid = ext4_get_projid, | ||
1103 | }; | 1135 | }; |
1104 | 1136 | ||
1105 | static const struct quotactl_ops ext4_qctl_operations = { | 1137 | static const struct quotactl_ops ext4_qctl_operations = { |
@@ -2526,6 +2558,12 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
2526 | "without CONFIG_QUOTA"); | 2558 | "without CONFIG_QUOTA"); |
2527 | return 0; | 2559 | return 0; |
2528 | } | 2560 | } |
2561 | if (ext4_has_feature_project(sb) && !readonly) { | ||
2562 | ext4_msg(sb, KERN_ERR, | ||
2563 | "Filesystem with project quota feature cannot be mounted RDWR " | ||
2564 | "without CONFIG_QUOTA"); | ||
2565 | return 0; | ||
2566 | } | ||
2529 | #endif /* CONFIG_QUOTA */ | 2567 | #endif /* CONFIG_QUOTA */ |
2530 | return 1; | 2568 | return 1; |
2531 | } | 2569 | } |
@@ -3654,7 +3692,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3654 | sb->s_qcop = &dquot_quotactl_sysfile_ops; | 3692 | sb->s_qcop = &dquot_quotactl_sysfile_ops; |
3655 | else | 3693 | else |
3656 | sb->s_qcop = &ext4_qctl_operations; | 3694 | sb->s_qcop = &ext4_qctl_operations; |
3657 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; | 3695 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ; |
3658 | #endif | 3696 | #endif |
3659 | memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); | 3697 | memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); |
3660 | 3698 | ||
@@ -4790,6 +4828,48 @@ restore_opts: | |||
4790 | return err; | 4828 | return err; |
4791 | } | 4829 | } |
4792 | 4830 | ||
4831 | #ifdef CONFIG_QUOTA | ||
4832 | static int ext4_statfs_project(struct super_block *sb, | ||
4833 | kprojid_t projid, struct kstatfs *buf) | ||
4834 | { | ||
4835 | struct kqid qid; | ||
4836 | struct dquot *dquot; | ||
4837 | u64 limit; | ||
4838 | u64 curblock; | ||
4839 | |||
4840 | qid = make_kqid_projid(projid); | ||
4841 | dquot = dqget(sb, qid); | ||
4842 | if (IS_ERR(dquot)) | ||
4843 | return PTR_ERR(dquot); | ||
4844 | spin_lock(&dq_data_lock); | ||
4845 | |||
4846 | limit = (dquot->dq_dqb.dqb_bsoftlimit ? | ||
4847 | dquot->dq_dqb.dqb_bsoftlimit : | ||
4848 | dquot->dq_dqb.dqb_bhardlimit) >> sb->s_blocksize_bits; | ||
4849 | if (limit && buf->f_blocks > limit) { | ||
4850 | curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits; | ||
4851 | buf->f_blocks = limit; | ||
4852 | buf->f_bfree = buf->f_bavail = | ||
4853 | (buf->f_blocks > curblock) ? | ||
4854 | (buf->f_blocks - curblock) : 0; | ||
4855 | } | ||
4856 | |||
4857 | limit = dquot->dq_dqb.dqb_isoftlimit ? | ||
4858 | dquot->dq_dqb.dqb_isoftlimit : | ||
4859 | dquot->dq_dqb.dqb_ihardlimit; | ||
4860 | if (limit && buf->f_files > limit) { | ||
4861 | buf->f_files = limit; | ||
4862 | buf->f_ffree = | ||
4863 | (buf->f_files > dquot->dq_dqb.dqb_curinodes) ? | ||
4864 | (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0; | ||
4865 | } | ||
4866 | |||
4867 | spin_unlock(&dq_data_lock); | ||
4868 | dqput(dquot); | ||
4869 | return 0; | ||
4870 | } | ||
4871 | #endif | ||
4872 | |||
4793 | static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | 4873 | static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) |
4794 | { | 4874 | { |
4795 | struct super_block *sb = dentry->d_sb; | 4875 | struct super_block *sb = dentry->d_sb; |
@@ -4822,6 +4902,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
4822 | buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; | 4902 | buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; |
4823 | buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; | 4903 | buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; |
4824 | 4904 | ||
4905 | #ifdef CONFIG_QUOTA | ||
4906 | if (ext4_test_inode_flag(dentry->d_inode, EXT4_INODE_PROJINHERIT) && | ||
4907 | sb_has_quota_limits_enabled(sb, PRJQUOTA)) | ||
4908 | ext4_statfs_project(sb, EXT4_I(dentry->d_inode)->i_projid, buf); | ||
4909 | #endif | ||
4825 | return 0; | 4910 | return 0; |
4826 | } | 4911 | } |
4827 | 4912 | ||
@@ -4986,7 +5071,8 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id, | |||
4986 | struct inode *qf_inode; | 5071 | struct inode *qf_inode; |
4987 | unsigned long qf_inums[EXT4_MAXQUOTAS] = { | 5072 | unsigned long qf_inums[EXT4_MAXQUOTAS] = { |
4988 | le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), | 5073 | le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), |
4989 | le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) | 5074 | le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum), |
5075 | le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum) | ||
4990 | }; | 5076 | }; |
4991 | 5077 | ||
4992 | BUG_ON(!ext4_has_feature_quota(sb)); | 5078 | BUG_ON(!ext4_has_feature_quota(sb)); |
@@ -5014,7 +5100,8 @@ static int ext4_enable_quotas(struct super_block *sb) | |||
5014 | int type, err = 0; | 5100 | int type, err = 0; |
5015 | unsigned long qf_inums[EXT4_MAXQUOTAS] = { | 5101 | unsigned long qf_inums[EXT4_MAXQUOTAS] = { |
5016 | le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), | 5102 | le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), |
5017 | le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) | 5103 | le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum), |
5104 | le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum) | ||
5018 | }; | 5105 | }; |
5019 | 5106 | ||
5020 | sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; | 5107 | sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; |