Skip to content

Commit 040cb37

Browse files
mtfstytso
authored andcommitted
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>
1 parent 56a0491 commit 040cb37

File tree

5 files changed

+68
-4
lines changed

5 files changed

+68
-4
lines changed

fs/ext4/ext4.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,14 +378,15 @@ struct flex_groups {
378378
#define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
379379
#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
380380

381-
#define EXT4_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */
382-
#define EXT4_FL_USER_MODIFIABLE 0x004380FF /* User modifiable flags */
381+
#define EXT4_FL_USER_VISIBLE 0x304BDFFF /* User visible flags */
382+
#define EXT4_FL_USER_MODIFIABLE 0x204380FF /* User modifiable flags */
383383

384384
/* Flags that should be inherited by new inodes from their parent. */
385385
#define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
386386
EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
387387
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)
389390

390391
/* Flags that are appropriate for regular files (all but dir-specific ones). */
391392
#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL))
@@ -1004,6 +1005,7 @@ struct ext4_inode_info {
10041005
/* Encryption params */
10051006
struct ext4_crypt_info *i_crypt_info;
10061007
#endif
1008+
kprojid_t i_projid;
10071009
};
10081010

10091011
/*
@@ -1765,7 +1767,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT)
17651767
EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
17661768
EXT4_FEATURE_RO_COMPAT_BIGALLOC |\
17671769
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
1768-
EXT4_FEATURE_RO_COMPAT_QUOTA)
1770+
EXT4_FEATURE_RO_COMPAT_QUOTA |\
1771+
EXT4_FEATURE_RO_COMPAT_PROJECT)
17691772

17701773
#define EXTN_FEATURE_FUNCS(ver) \
17711774
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)
18071810
#define EXT4_DEF_RESUID 0
18081811
#define EXT4_DEF_RESGID 0
18091812

1813+
/*
1814+
* Default project ID
1815+
*/
1816+
#define EXT4_DEF_PROJID 0
1817+
18101818
#define EXT4_DEF_INODE_READAHEAD_BLKS 32
18111819

18121820
/*
@@ -2498,6 +2506,7 @@ extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
24982506
extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
24992507
extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
25002508
extern qsize_t *ext4_get_reserved_space(struct inode *inode);
2509+
extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
25012510
extern void ext4_da_update_reserve_space(struct inode *inode,
25022511
int used, int quota_claim);
25032512
extern int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk,

fs/ext4/ialloc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,13 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
799799
inode->i_gid = dir->i_gid;
800800
} else
801801
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+
802809
err = dquot_initialize(inode);
803810
if (err)
804811
goto out;

fs/ext4/inode.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4193,6 +4193,14 @@ static inline void ext4_iget_extra_inode(struct inode *inode,
41934193
EXT4_I(inode)->i_inline_off = 0;
41944194
}
41954195

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+
41964204
struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
41974205
{
41984206
struct ext4_iloc iloc;
@@ -4204,6 +4212,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
42044212
int block;
42054213
uid_t i_uid;
42064214
gid_t i_gid;
4215+
projid_t i_projid;
42074216

42084217
inode = iget_locked(sb, ino);
42094218
if (!inode)
@@ -4253,12 +4262,20 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
42534262
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
42544263
i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
42554264
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+
42564272
if (!(test_opt(inode->i_sb, NO_UID32))) {
42574273
i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
42584274
i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
42594275
}
42604276
i_uid_write(inode, i_uid);
42614277
i_gid_write(inode, i_gid);
4278+
ei->i_projid = make_kprojid(&init_user_ns, i_projid);
42624279
set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
42634280

42644281
ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */
@@ -4556,6 +4573,7 @@ static int ext4_do_update_inode(handle_t *handle,
45564573
int need_datasync = 0, set_large_file = 0;
45574574
uid_t i_uid;
45584575
gid_t i_gid;
4576+
projid_t i_projid;
45594577

45604578
spin_lock(&ei->i_raw_lock);
45614579

@@ -4568,6 +4586,7 @@ static int ext4_do_update_inode(handle_t *handle,
45684586
raw_inode->i_mode = cpu_to_le16(inode->i_mode);
45694587
i_uid = i_uid_read(inode);
45704588
i_gid = i_gid_read(inode);
4589+
i_projid = from_kprojid(&init_user_ns, ei->i_projid);
45714590
if (!(test_opt(inode->i_sb, NO_UID32))) {
45724591
raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid));
45734592
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,
46454664
cpu_to_le16(ei->i_extra_isize);
46464665
}
46474666
}
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+
46484676
ext4_inode_csum_set(inode, raw_inode, ei);
46494677
spin_unlock(&ei->i_raw_lock);
46504678
if (inode->i_sb->s_flags & MS_LAZYTIME)

fs/ext4/namei.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,6 +3208,12 @@ static int ext4_link(struct dentry *old_dentry,
32083208
if (ext4_encrypted_inode(dir) &&
32093209
!ext4_is_child_context_consistent_with_parent(dir, inode))
32103210
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+
32113217
err = dquot_initialize(dir);
32123218
if (err)
32133219
return err;
@@ -3488,6 +3494,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
34883494
int credits;
34893495
u8 old_file_type;
34903496

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+
34913502
retval = dquot_initialize(old.dir);
34923503
if (retval)
34933504
return retval;
@@ -3697,6 +3708,14 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
36973708
new.inode)))
36983709
return -EPERM;
36993710

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+
37003719
retval = dquot_initialize(old.dir);
37013720
if (retval)
37023721
return retval;

fs/ext4/super.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,7 @@ static const struct dquot_operations ext4_quota_operations = {
11311131
.write_info = ext4_write_info,
11321132
.alloc_dquot = dquot_alloc,
11331133
.destroy_dquot = dquot_destroy,
1134+
.get_projid = ext4_get_projid,
11341135
};
11351136

11361137
static const struct quotactl_ops ext4_qctl_operations = {

0 commit comments

Comments
 (0)