f2fs: fix to keep project quota consistent
This patch does below changes to keep consistence of project quota data in sudden power-cut case: - update inode.i_projid and project quota atomically under lock_op() in f2fs_ioc_setproject() - recover inode.i_projid and project quota in recover_inode() Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
af033b2aa8
commit
7813081969
|
@ -2811,6 +2811,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count);
|
||||||
int f2fs_precache_extents(struct inode *inode);
|
int f2fs_precache_extents(struct inode *inode);
|
||||||
long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||||
long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||||||
|
int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid);
|
||||||
int f2fs_pin_file_control(struct inode *inode, bool inc);
|
int f2fs_pin_file_control(struct inode *inode, bool inc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2613,13 +2613,29 @@ static int f2fs_ioc_get_features(struct file *filp, unsigned long arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
|
int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid)
|
||||||
|
{
|
||||||
|
struct dquot *transfer_to[MAXQUOTAS] = {};
|
||||||
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||||
|
struct super_block *sb = sbi->sb;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
|
||||||
|
if (!IS_ERR(transfer_to[PRJQUOTA])) {
|
||||||
|
err = __dquot_transfer(inode, transfer_to);
|
||||||
|
if (err)
|
||||||
|
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
|
||||||
|
dqput(transfer_to[PRJQUOTA]);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
|
static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(filp);
|
struct inode *inode = file_inode(filp);
|
||||||
struct f2fs_inode_info *fi = F2FS_I(inode);
|
struct f2fs_inode_info *fi = F2FS_I(inode);
|
||||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||||
struct super_block *sb = sbi->sb;
|
struct super_block *sb = sbi->sb;
|
||||||
struct dquot *transfer_to[MAXQUOTAS] = {};
|
|
||||||
struct page *ipage;
|
struct page *ipage;
|
||||||
kprojid_t kprojid;
|
kprojid_t kprojid;
|
||||||
int err;
|
int err;
|
||||||
|
@ -2660,21 +2676,24 @@ static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
|
f2fs_lock_op(sbi);
|
||||||
if (!IS_ERR(transfer_to[PRJQUOTA])) {
|
err = f2fs_transfer_project_quota(inode, kprojid);
|
||||||
err = __dquot_transfer(inode, transfer_to);
|
if (err)
|
||||||
dqput(transfer_to[PRJQUOTA]);
|
goto out_unlock;
|
||||||
if (err)
|
|
||||||
goto out_dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
F2FS_I(inode)->i_projid = kprojid;
|
F2FS_I(inode)->i_projid = kprojid;
|
||||||
inode->i_ctime = current_time(inode);
|
inode->i_ctime = current_time(inode);
|
||||||
out_dirty:
|
|
||||||
f2fs_mark_inode_dirty_sync(inode, true);
|
f2fs_mark_inode_dirty_sync(inode, true);
|
||||||
|
out_unlock:
|
||||||
|
f2fs_unlock_op(sbi);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
|
static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
|
||||||
{
|
{
|
||||||
if (projid != F2FS_DEF_PROJID)
|
if (projid != F2FS_DEF_PROJID)
|
||||||
|
|
|
@ -254,10 +254,18 @@ static int recover_inode(struct inode *inode, struct page *page)
|
||||||
F2FS_FITS_IN_INODE(raw, le16_to_cpu(raw->i_extra_isize),
|
F2FS_FITS_IN_INODE(raw, le16_to_cpu(raw->i_extra_isize),
|
||||||
i_projid)) {
|
i_projid)) {
|
||||||
projid_t i_projid;
|
projid_t i_projid;
|
||||||
|
kprojid_t kprojid;
|
||||||
|
|
||||||
i_projid = (projid_t)le32_to_cpu(raw->i_projid);
|
i_projid = (projid_t)le32_to_cpu(raw->i_projid);
|
||||||
F2FS_I(inode)->i_projid =
|
kprojid = make_kprojid(&init_user_ns, i_projid);
|
||||||
make_kprojid(&init_user_ns, i_projid);
|
|
||||||
|
if (!projid_eq(kprojid, F2FS_I(inode)->i_projid)) {
|
||||||
|
err = f2fs_transfer_project_quota(inode,
|
||||||
|
kprojid);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
F2FS_I(inode)->i_projid = kprojid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue