aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2018-09-25 03:36:02 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2018-10-22 20:54:48 -0400
commit78130819695f17f5c042d8ba097802639478faf5 (patch)
tree468624c7bdc9ab656be4982a635cca65526444c2
parentaf033b2aa8a874fd5737fafe90d159136527b5b4 (diff)
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>
-rw-r--r--fs/f2fs/f2fs.h1
-rw-r--r--fs/f2fs/file.c37
-rw-r--r--fs/f2fs/recovery.c12
3 files changed, 39 insertions, 11 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index f447cbc2295f..56204a8f8a12 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2811,6 +2811,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count);
2811int f2fs_precache_extents(struct inode *inode); 2811int f2fs_precache_extents(struct inode *inode);
2812long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); 2812long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
2813long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 2813long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
2814int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid);
2814int f2fs_pin_file_control(struct inode *inode, bool inc); 2815int f2fs_pin_file_control(struct inode *inode, bool inc);
2815 2816
2816/* 2817/*
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 971463e0589e..88b124677189 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2613,13 +2613,29 @@ static int f2fs_ioc_get_features(struct file *filp, unsigned long arg)
2613} 2613}
2614 2614
2615#ifdef CONFIG_QUOTA 2615#ifdef CONFIG_QUOTA
2616int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid)
2617{
2618 struct dquot *transfer_to[MAXQUOTAS] = {};
2619 struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
2620 struct super_block *sb = sbi->sb;
2621 int err = 0;
2622
2623 transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
2624 if (!IS_ERR(transfer_to[PRJQUOTA])) {
2625 err = __dquot_transfer(inode, transfer_to);
2626 if (err)
2627 set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2628 dqput(transfer_to[PRJQUOTA]);
2629 }
2630 return err;
2631}
2632
2616static int f2fs_ioc_setproject(struct file *filp, __u32 projid) 2633static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
2617{ 2634{
2618 struct inode *inode = file_inode(filp); 2635 struct inode *inode = file_inode(filp);
2619 struct f2fs_inode_info *fi = F2FS_I(inode); 2636 struct f2fs_inode_info *fi = F2FS_I(inode);
2620 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 2637 struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
2621 struct super_block *sb = sbi->sb; 2638 struct super_block *sb = sbi->sb;
2622 struct dquot *transfer_to[MAXQUOTAS] = {};
2623 struct page *ipage; 2639 struct page *ipage;
2624 kprojid_t kprojid; 2640 kprojid_t kprojid;
2625 int err; 2641 int err;
@@ -2660,21 +2676,24 @@ static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
2660 if (err) 2676 if (err)
2661 return err; 2677 return err;
2662 2678
2663 transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid)); 2679 f2fs_lock_op(sbi);
2664 if (!IS_ERR(transfer_to[PRJQUOTA])) { 2680 err = f2fs_transfer_project_quota(inode, kprojid);
2665 err = __dquot_transfer(inode, transfer_to); 2681 if (err)
2666 dqput(transfer_to[PRJQUOTA]); 2682 goto out_unlock;
2667 if (err)
2668 goto out_dirty;
2669 }
2670 2683
2671 F2FS_I(inode)->i_projid = kprojid; 2684 F2FS_I(inode)->i_projid = kprojid;
2672 inode->i_ctime = current_time(inode); 2685 inode->i_ctime = current_time(inode);
2673out_dirty:
2674 f2fs_mark_inode_dirty_sync(inode, true); 2686 f2fs_mark_inode_dirty_sync(inode, true);
2687out_unlock:
2688 f2fs_unlock_op(sbi);
2675 return err; 2689 return err;
2676} 2690}
2677#else 2691#else
2692int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid)
2693{
2694 return 0;
2695}
2696
2678static int f2fs_ioc_setproject(struct file *filp, __u32 projid) 2697static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
2679{ 2698{
2680 if (projid != F2FS_DEF_PROJID) 2699 if (projid != F2FS_DEF_PROJID)
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index df2123759ac7..1dfb17f9f9ff 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -254,10 +254,18 @@ static int recover_inode(struct inode *inode, struct page *page)
254 F2FS_FITS_IN_INODE(raw, le16_to_cpu(raw->i_extra_isize), 254 F2FS_FITS_IN_INODE(raw, le16_to_cpu(raw->i_extra_isize),
255 i_projid)) { 255 i_projid)) {
256 projid_t i_projid; 256 projid_t i_projid;
257 kprojid_t kprojid;
257 258
258 i_projid = (projid_t)le32_to_cpu(raw->i_projid); 259 i_projid = (projid_t)le32_to_cpu(raw->i_projid);
259 F2FS_I(inode)->i_projid = 260 kprojid = make_kprojid(&init_user_ns, i_projid);
260 make_kprojid(&init_user_ns, i_projid); 261
262 if (!projid_eq(kprojid, F2FS_I(inode)->i_projid)) {
263 err = f2fs_transfer_project_quota(inode,
264 kprojid);
265 if (err)
266 return err;
267 F2FS_I(inode)->i_projid = kprojid;
268 }
261 } 269 }
262 } 270 }
263 271