Commit 78130819 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

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: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent af033b2a
...@@ -2811,6 +2811,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment