diff options
author | Li Xi <pkuelelixi@gmail.com> | 2016-01-08 16:01:21 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2016-01-08 16:01:21 -0500 |
commit | 040cb3786d9b25293b8b0b05b90da0f871e1eb9b (patch) | |
tree | bc3decd8a3b122a4334934a4c89e38122b45f2cf /fs/ext4 | |
parent | 56a04915df4e85b34b1c1613c64b87dd2283c26a (diff) |
ext4: adds project ID support
Signed-off-by: Li Xi <lixi@ddn.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 17 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 7 | ||||
-rw-r--r-- | fs/ext4/inode.c | 28 | ||||
-rw-r--r-- | fs/ext4/namei.c | 19 | ||||
-rw-r--r-- | fs/ext4/super.c | 1 |
5 files changed, 68 insertions, 4 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f82da361a823..023781101bae 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -378,14 +378,15 @@ struct flex_groups { | |||
378 | #define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ | 378 | #define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ |
379 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ | 379 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ |
380 | 380 | ||
381 | #define EXT4_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */ | 381 | #define EXT4_FL_USER_VISIBLE 0x304BDFFF /* User visible flags */ |
382 | #define EXT4_FL_USER_MODIFIABLE 0x004380FF /* User modifiable flags */ | 382 | #define EXT4_FL_USER_MODIFIABLE 0x204380FF /* User modifiable flags */ |
383 | 383 | ||
384 | /* Flags that should be inherited by new inodes from their parent. */ | 384 | /* Flags that should be inherited by new inodes from their parent. */ |
385 | #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\ | 385 | #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\ |
386 | EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\ | 386 | EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\ |
387 | EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\ | 387 | EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\ |
388 | EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL) | 388 | EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL |\ |
389 | EXT4_PROJINHERIT_FL) | ||
389 | 390 | ||
390 | /* Flags that are appropriate for regular files (all but dir-specific ones). */ | 391 | /* Flags that are appropriate for regular files (all but dir-specific ones). */ |
391 | #define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL)) | 392 | #define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL)) |
@@ -1004,6 +1005,7 @@ struct ext4_inode_info { | |||
1004 | /* Encryption params */ | 1005 | /* Encryption params */ |
1005 | struct ext4_crypt_info *i_crypt_info; | 1006 | struct ext4_crypt_info *i_crypt_info; |
1006 | #endif | 1007 | #endif |
1008 | kprojid_t i_projid; | ||
1007 | }; | 1009 | }; |
1008 | 1010 | ||
1009 | /* | 1011 | /* |
@@ -1765,7 +1767,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT) | |||
1765 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\ | 1767 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\ |
1766 | EXT4_FEATURE_RO_COMPAT_BIGALLOC |\ | 1768 | EXT4_FEATURE_RO_COMPAT_BIGALLOC |\ |
1767 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ | 1769 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ |
1768 | EXT4_FEATURE_RO_COMPAT_QUOTA) | 1770 | EXT4_FEATURE_RO_COMPAT_QUOTA |\ |
1771 | EXT4_FEATURE_RO_COMPAT_PROJECT) | ||
1769 | 1772 | ||
1770 | #define EXTN_FEATURE_FUNCS(ver) \ | 1773 | #define EXTN_FEATURE_FUNCS(ver) \ |
1771 | static inline bool ext4_has_unknown_ext##ver##_compat_features(struct super_block *sb) \ | 1774 | static inline bool ext4_has_unknown_ext##ver##_compat_features(struct super_block *sb) \ |
@@ -1807,6 +1810,11 @@ static inline bool ext4_has_incompat_features(struct super_block *sb) | |||
1807 | #define EXT4_DEF_RESUID 0 | 1810 | #define EXT4_DEF_RESUID 0 |
1808 | #define EXT4_DEF_RESGID 0 | 1811 | #define EXT4_DEF_RESGID 0 |
1809 | 1812 | ||
1813 | /* | ||
1814 | * Default project ID | ||
1815 | */ | ||
1816 | #define EXT4_DEF_PROJID 0 | ||
1817 | |||
1810 | #define EXT4_DEF_INODE_READAHEAD_BLKS 32 | 1818 | #define EXT4_DEF_INODE_READAHEAD_BLKS 32 |
1811 | 1819 | ||
1812 | /* | 1820 | /* |
@@ -2498,6 +2506,7 @@ extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode, | |||
2498 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); | 2506 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); |
2499 | extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | 2507 | extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf); |
2500 | extern qsize_t *ext4_get_reserved_space(struct inode *inode); | 2508 | extern qsize_t *ext4_get_reserved_space(struct inode *inode); |
2509 | extern int ext4_get_projid(struct inode *inode, kprojid_t *projid); | ||
2501 | extern void ext4_da_update_reserve_space(struct inode *inode, | 2510 | extern void ext4_da_update_reserve_space(struct inode *inode, |
2502 | int used, int quota_claim); | 2511 | int used, int quota_claim); |
2503 | extern int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, | 2512 | extern int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d26f65..3fcfd50a2e8a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -799,6 +799,13 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, | |||
799 | inode->i_gid = dir->i_gid; | 799 | inode->i_gid = dir->i_gid; |
800 | } else | 800 | } else |
801 | inode_init_owner(inode, dir, mode); | 801 | inode_init_owner(inode, dir, mode); |
802 | |||
803 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_PROJECT) && | ||
804 | ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT)) | ||
805 | ei->i_projid = EXT4_I(dir)->i_projid; | ||
806 | else | ||
807 | ei->i_projid = make_kprojid(&init_user_ns, EXT4_DEF_PROJID); | ||
808 | |||
802 | err = dquot_initialize(inode); | 809 | err = dquot_initialize(inode); |
803 | if (err) | 810 | if (err) |
804 | goto out; | 811 | goto out; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ff2f3cd38522..6770c07ab39f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4193,6 +4193,14 @@ static inline void ext4_iget_extra_inode(struct inode *inode, | |||
4193 | EXT4_I(inode)->i_inline_off = 0; | 4193 | EXT4_I(inode)->i_inline_off = 0; |
4194 | } | 4194 | } |
4195 | 4195 | ||
4196 | int ext4_get_projid(struct inode *inode, kprojid_t *projid) | ||
4197 | { | ||
4198 | if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, EXT4_FEATURE_RO_COMPAT_PROJECT)) | ||
4199 | return -EOPNOTSUPP; | ||
4200 | *projid = EXT4_I(inode)->i_projid; | ||
4201 | return 0; | ||
4202 | } | ||
4203 | |||
4196 | struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | 4204 | struct inode *ext4_iget(struct super_block *sb, unsigned long ino) |
4197 | { | 4205 | { |
4198 | struct ext4_iloc iloc; | 4206 | struct ext4_iloc iloc; |
@@ -4204,6 +4212,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4204 | int block; | 4212 | int block; |
4205 | uid_t i_uid; | 4213 | uid_t i_uid; |
4206 | gid_t i_gid; | 4214 | gid_t i_gid; |
4215 | projid_t i_projid; | ||
4207 | 4216 | ||
4208 | inode = iget_locked(sb, ino); | 4217 | inode = iget_locked(sb, ino); |
4209 | if (!inode) | 4218 | if (!inode) |
@@ -4253,12 +4262,20 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4253 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); | 4262 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); |
4254 | i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); | 4263 | i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); |
4255 | i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); | 4264 | i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); |
4265 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_PROJECT) && | ||
4266 | EXT4_INODE_SIZE(sb) > EXT4_GOOD_OLD_INODE_SIZE && | ||
4267 | EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) | ||
4268 | i_projid = (projid_t)le32_to_cpu(raw_inode->i_projid); | ||
4269 | else | ||
4270 | i_projid = EXT4_DEF_PROJID; | ||
4271 | |||
4256 | if (!(test_opt(inode->i_sb, NO_UID32))) { | 4272 | if (!(test_opt(inode->i_sb, NO_UID32))) { |
4257 | i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; | 4273 | i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; |
4258 | i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; | 4274 | i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; |
4259 | } | 4275 | } |
4260 | i_uid_write(inode, i_uid); | 4276 | i_uid_write(inode, i_uid); |
4261 | i_gid_write(inode, i_gid); | 4277 | i_gid_write(inode, i_gid); |
4278 | ei->i_projid = make_kprojid(&init_user_ns, i_projid); | ||
4262 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); | 4279 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); |
4263 | 4280 | ||
4264 | ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */ | 4281 | ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */ |
@@ -4556,6 +4573,7 @@ static int ext4_do_update_inode(handle_t *handle, | |||
4556 | int need_datasync = 0, set_large_file = 0; | 4573 | int need_datasync = 0, set_large_file = 0; |
4557 | uid_t i_uid; | 4574 | uid_t i_uid; |
4558 | gid_t i_gid; | 4575 | gid_t i_gid; |
4576 | projid_t i_projid; | ||
4559 | 4577 | ||
4560 | spin_lock(&ei->i_raw_lock); | 4578 | spin_lock(&ei->i_raw_lock); |
4561 | 4579 | ||
@@ -4568,6 +4586,7 @@ static int ext4_do_update_inode(handle_t *handle, | |||
4568 | raw_inode->i_mode = cpu_to_le16(inode->i_mode); | 4586 | raw_inode->i_mode = cpu_to_le16(inode->i_mode); |
4569 | i_uid = i_uid_read(inode); | 4587 | i_uid = i_uid_read(inode); |
4570 | i_gid = i_gid_read(inode); | 4588 | i_gid = i_gid_read(inode); |
4589 | i_projid = from_kprojid(&init_user_ns, ei->i_projid); | ||
4571 | if (!(test_opt(inode->i_sb, NO_UID32))) { | 4590 | if (!(test_opt(inode->i_sb, NO_UID32))) { |
4572 | raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid)); | 4591 | raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid)); |
4573 | raw_inode->i_gid_low = cpu_to_le16(low_16_bits(i_gid)); | 4592 | raw_inode->i_gid_low = cpu_to_le16(low_16_bits(i_gid)); |
@@ -4645,6 +4664,15 @@ static int ext4_do_update_inode(handle_t *handle, | |||
4645 | cpu_to_le16(ei->i_extra_isize); | 4664 | cpu_to_le16(ei->i_extra_isize); |
4646 | } | 4665 | } |
4647 | } | 4666 | } |
4667 | |||
4668 | BUG_ON(!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | ||
4669 | EXT4_FEATURE_RO_COMPAT_PROJECT) && | ||
4670 | i_projid != EXT4_DEF_PROJID); | ||
4671 | |||
4672 | if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE && | ||
4673 | EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) | ||
4674 | raw_inode->i_projid = cpu_to_le32(i_projid); | ||
4675 | |||
4648 | ext4_inode_csum_set(inode, raw_inode, ei); | 4676 | ext4_inode_csum_set(inode, raw_inode, ei); |
4649 | spin_unlock(&ei->i_raw_lock); | 4677 | spin_unlock(&ei->i_raw_lock); |
4650 | if (inode->i_sb->s_flags & MS_LAZYTIME) | 4678 | if (inode->i_sb->s_flags & MS_LAZYTIME) |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 06c3afcbfac8..2047ff7c5fbc 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -3208,6 +3208,12 @@ static int ext4_link(struct dentry *old_dentry, | |||
3208 | if (ext4_encrypted_inode(dir) && | 3208 | if (ext4_encrypted_inode(dir) && |
3209 | !ext4_is_child_context_consistent_with_parent(dir, inode)) | 3209 | !ext4_is_child_context_consistent_with_parent(dir, inode)) |
3210 | return -EPERM; | 3210 | return -EPERM; |
3211 | |||
3212 | if ((ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT)) && | ||
3213 | (!projid_eq(EXT4_I(dir)->i_projid, | ||
3214 | EXT4_I(old_dentry->d_inode)->i_projid))) | ||
3215 | return -EXDEV; | ||
3216 | |||
3211 | err = dquot_initialize(dir); | 3217 | err = dquot_initialize(dir); |
3212 | if (err) | 3218 | if (err) |
3213 | return err; | 3219 | return err; |
@@ -3488,6 +3494,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3488 | int credits; | 3494 | int credits; |
3489 | u8 old_file_type; | 3495 | u8 old_file_type; |
3490 | 3496 | ||
3497 | if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT)) && | ||
3498 | (!projid_eq(EXT4_I(new_dir)->i_projid, | ||
3499 | EXT4_I(old_dentry->d_inode)->i_projid))) | ||
3500 | return -EXDEV; | ||
3501 | |||
3491 | retval = dquot_initialize(old.dir); | 3502 | retval = dquot_initialize(old.dir); |
3492 | if (retval) | 3503 | if (retval) |
3493 | return retval; | 3504 | return retval; |
@@ -3697,6 +3708,14 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3697 | new.inode))) | 3708 | new.inode))) |
3698 | return -EPERM; | 3709 | return -EPERM; |
3699 | 3710 | ||
3711 | if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) && | ||
3712 | !projid_eq(EXT4_I(new_dir)->i_projid, | ||
3713 | EXT4_I(old_dentry->d_inode)->i_projid)) || | ||
3714 | (ext4_test_inode_flag(old_dir, EXT4_INODE_PROJINHERIT) && | ||
3715 | !projid_eq(EXT4_I(old_dir)->i_projid, | ||
3716 | EXT4_I(new_dentry->d_inode)->i_projid))) | ||
3717 | return -EXDEV; | ||
3718 | |||
3700 | retval = dquot_initialize(old.dir); | 3719 | retval = dquot_initialize(old.dir); |
3701 | if (retval) | 3720 | if (retval) |
3702 | return retval; | 3721 | return retval; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 486e869bd583..844c95d95821 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1131,6 +1131,7 @@ static const struct dquot_operations ext4_quota_operations = { | |||
1131 | .write_info = ext4_write_info, | 1131 | .write_info = ext4_write_info, |
1132 | .alloc_dquot = dquot_alloc, | 1132 | .alloc_dquot = dquot_alloc, |
1133 | .destroy_dquot = dquot_destroy, | 1133 | .destroy_dquot = dquot_destroy, |
1134 | .get_projid = ext4_get_projid, | ||
1134 | }; | 1135 | }; |
1135 | 1136 | ||
1136 | static const struct quotactl_ops ext4_qctl_operations = { | 1137 | static const struct quotactl_ops ext4_qctl_operations = { |