Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 664265d8 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: support project quota



This patch adds to support plain project quota.

Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent c2e3a205
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ io_bits=%u Set the bit size of write IO requests. It should be set
                       with "mode=lfs".
usrquota               Enable plain user disk quota accounting.
grpquota               Enable plain group disk quota accounting.
prjquota               Enable plain project quota accounting.

================================================================================
DEBUGFS ENTRIES
+33 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ extern char *fault_name[FAULT_MAX];
#define F2FS_MOUNT_LFS			0x00040000
#define F2FS_MOUNT_USRQUOTA		0x00080000
#define F2FS_MOUNT_GRPQUOTA		0x00100000
#define F2FS_MOUNT_PRJQUOTA		0x00200000

#define clear_opt(sbi, option)	((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)
#define set_opt(sbi, option)	((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -116,6 +117,7 @@ struct f2fs_mount_info {
#define F2FS_FEATURE_BLKZONED		0x0002
#define F2FS_FEATURE_ATOMIC_WRITE	0x0004
#define F2FS_FEATURE_EXTRA_ATTR		0x0008
#define F2FS_FEATURE_PRJQUOTA		0x0010

#define F2FS_HAS_FEATURE(sb, mask)					\
	((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -667,6 +669,7 @@ struct f2fs_inode_info {
	struct rw_semaphore i_mmap_sem;

	int i_extra_isize;		/* size of extra space located in i_addr */
	kprojid_t i_projid;		/* id for project quota */
};

static inline void get_extent_info(struct extent_info *ext,
@@ -1025,6 +1028,10 @@ enum {
	MAX_TIME,
};

#ifdef CONFIG_QUOTA
#define F2FS_MAXQUOTAS 2
#endif

struct f2fs_sb_info {
	struct super_block *sb;			/* pointer to VFS super block */
	struct proc_dir_entry *s_proc;		/* proc entry */
@@ -1981,6 +1988,20 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr)
	*addr ^= mask;
}

#define F2FS_REG_FLMASK		(~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
#define F2FS_OTHER_FLMASK	(FS_NODUMP_FL | FS_NOATIME_FL)
#define F2FS_FL_INHERITED	(FS_PROJINHERIT_FL)

static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags)
{
	if (S_ISDIR(mode))
		return flags;
	else if (S_ISREG(mode))
		return flags & F2FS_REG_FLMASK;
	else
		return flags & F2FS_OTHER_FLMASK;
}

/* used for f2fs_inode_info->flags */
enum {
	FI_NEW_INODE,		/* indicate newly allocated inode */
@@ -2009,6 +2030,7 @@ enum {
	FI_DIRTY_FILE,		/* indicate regular/symlink has dirty pages */
	FI_HOT_DATA,		/* indicate file is hot */
	FI_EXTRA_ATTR,		/* indicate file has extra attribute */
	FI_PROJ_INHERIT,	/* indicate file inherits projectid */
};

static inline void __mark_inode_dirty_flag(struct inode *inode,
@@ -2352,6 +2374,12 @@ static inline int get_extra_isize(struct inode *inode)
	(offsetof(struct f2fs_inode, i_extra_end) -	\
	offsetof(struct f2fs_inode, i_extra_isize))	\

#define F2FS_OLD_ATTRIBUTE_SIZE	(offsetof(struct f2fs_inode, i_addr))
#define F2FS_FITS_IN_INODE(f2fs_inode, extra_isize, field)		\
		((offsetof(typeof(*f2fs_inode), field) +	\
		sizeof((f2fs_inode)->field))			\
		<= (F2FS_OLD_ATTRIBUTE_SIZE + extra_isize))	\

/*
 * file.c
 */
@@ -2950,6 +2978,11 @@ static inline int f2fs_sb_has_extra_attr(struct super_block *sb)
	return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_EXTRA_ATTR);
}

static inline int f2fs_sb_has_project_quota(struct super_block *sb)
{
	return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_PRJQUOTA);
}

#ifdef CONFIG_BLK_DEV_ZONED
static inline int get_blkz_type(struct f2fs_sb_info *sbi,
			struct block_device *bdev, block_t blkaddr)
+0 −13
Original line number Diff line number Diff line
@@ -1510,19 +1510,6 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id)
	return 0;
}

#define F2FS_REG_FLMASK		(~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
#define F2FS_OTHER_FLMASK	(FS_NODUMP_FL | FS_NOATIME_FL)

static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags)
{
	if (S_ISDIR(mode))
		return flags;
	else if (S_ISREG(mode))
		return flags & F2FS_REG_FLMASK;
	else
		return flags & F2FS_OTHER_FLMASK;
}

static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
{
	struct inode *inode = file_inode(filp);
+23 −1
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ static int do_read_inode(struct inode *inode)
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct page *node_page;
	struct f2fs_inode *ri;
	projid_t i_projid;

	/* Check if ino is within scope */
	if (check_nid_range(sbi, inode->i_ino)) {
@@ -173,6 +174,16 @@ static int do_read_inode(struct inode *inode)
	if (!need_inode_block_update(sbi, inode->i_ino))
		fi->last_disk_size = inode->i_size;

	if (fi->i_flags & FS_PROJINHERIT_FL)
		set_inode_flag(inode, FI_PROJ_INHERIT);

	if (f2fs_has_extra_attr(inode) && f2fs_sb_has_project_quota(sbi->sb) &&
			F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_projid))
		i_projid = (projid_t)le32_to_cpu(ri->i_projid);
	else
		i_projid = F2FS_DEF_PROJID;
	fi->i_projid = make_kprojid(&init_user_ns, i_projid);

	f2fs_put_page(node_page, 1);

	stat_inc_inline_xattr(inode);
@@ -299,9 +310,20 @@ int update_inode(struct inode *inode, struct page *node_page)
	ri->i_generation = cpu_to_le32(inode->i_generation);
	ri->i_dir_level = F2FS_I(inode)->i_dir_level;

	if (f2fs_has_extra_attr(inode))
	if (f2fs_has_extra_attr(inode)) {
		ri->i_extra_isize = cpu_to_le16(F2FS_I(inode)->i_extra_isize);

		if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)->sb) &&
			F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
								i_projid)) {
			projid_t i_projid;

			i_projid = from_kprojid(&init_user_ns,
						F2FS_I(inode)->i_projid);
			ri->i_projid = cpu_to_le32(i_projid);
		}
	}

	__set_inode_rdev(inode, ri);
	set_cold_node(inode, node_page);

+30 −0
Original line number Diff line number Diff line
@@ -59,6 +59,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
		goto fail;
	}

	if (f2fs_sb_has_project_quota(sbi->sb) &&
		(F2FS_I(dir)->i_flags & FS_PROJINHERIT_FL))
		F2FS_I(inode)->i_projid = F2FS_I(dir)->i_projid;
	else
		F2FS_I(inode)->i_projid = make_kprojid(&init_user_ns,
							F2FS_DEF_PROJID);
	dquot_initialize(inode);

	err = dquot_alloc_inode(inode);
@@ -89,6 +95,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
	stat_inc_inline_inode(inode);
	stat_inc_inline_dir(inode);

	F2FS_I(inode)->i_flags =
		f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED);

	if (F2FS_I(inode)->i_flags & FS_PROJINHERIT_FL)
		set_inode_flag(inode, FI_PROJ_INHERIT);

	trace_f2fs_new_inode(inode, 0);
	return inode;

@@ -206,6 +218,11 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
			!fscrypt_has_permitted_context(dir, inode))
		return -EPERM;

	if (is_inode_flag_set(dir, FI_PROJ_INHERIT) &&
			(!projid_eq(F2FS_I(dir)->i_projid,
			F2FS_I(old_dentry->d_inode)->i_projid)))
		return -EXDEV;

	dquot_initialize(dir);

	f2fs_balance_fs(sbi, true);
@@ -727,6 +744,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
		goto out;
	}

	if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
			(!projid_eq(F2FS_I(new_dir)->i_projid,
			F2FS_I(old_dentry->d_inode)->i_projid)))
		return -EXDEV;

	dquot_initialize(old_dir);

	dquot_initialize(new_dir);
@@ -911,6 +933,14 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
			 !fscrypt_has_permitted_context(old_dir, new_inode)))
		return -EPERM;

	if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
			!projid_eq(F2FS_I(new_dir)->i_projid,
			F2FS_I(old_dentry->d_inode)->i_projid)) ||
	    (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
			!projid_eq(F2FS_I(old_dir)->i_projid,
			F2FS_I(new_dentry->d_inode)->i_projid)))
		return -EXDEV;

	dquot_initialize(old_dir);

	dquot_initialize(new_dir);
Loading