[PATCH v3] f2fs: support journalled quota

2017-08-07 Thread Chao Yu
This patch supports to enable f2fs to accept quota information through
mount option:
- {usr,grp,prj}jquota=
- jqfmt=

Then, in ->mount flow, we can recover quota file during log replaying,
by this, journelled quota can be supported.

Signed-off-by: Chao Yu 
---
v3:
- add missing quota initialization during recovery.
 Documentation/filesystems/f2fs.txt |   9 +
 fs/f2fs/checkpoint.c   |  26 ++-
 fs/f2fs/f2fs.h |   9 +
 fs/f2fs/recovery.c |  72 +++-
 fs/f2fs/super.c| 325 ++---
 5 files changed, 411 insertions(+), 30 deletions(-)

diff --git a/Documentation/filesystems/f2fs.txt 
b/Documentation/filesystems/f2fs.txt
index b8f495a8b67d..deafeff7795b 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -165,6 +165,15 @@ io_bits=%u Set the bit size of write IO 
requests. It should be set
 usrquota   Enable plain user disk quota accounting.
 grpquota   Enable plain group disk quota accounting.
 prjquota   Enable plain project quota accounting.
+usrjquota=   Appoint specified file and type during mount, so that 
quota
+grpjquota=   information can be properly updated during recovery 
flow,
+prjjquota=   : must be in root directory;
+jqfmt= : [vfsold,vfsv0,vfsv1].
+offusrjquota   Turn off user journelled quota.
+offgrpjquota   Turn off group journelled quota.
+offprjjquota   Turn off project journelled quota.
+quota  Enable plain user disk quota accounting.
+noquotaDisable all plain disk quota option.
 
 

 DEBUGFS ENTRIES
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index da5b49183e09..04fe1df052b2 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -588,11 +588,24 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, 
nid_t ino)
 int recover_orphan_inodes(struct f2fs_sb_info *sbi)
 {
block_t start_blk, orphan_blocks, i, j;
-   int err;
+   unsigned int s_flags = sbi->sb->s_flags;
+   int err = 0;
 
if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG))
return 0;
 
+   if (s_flags & MS_RDONLY) {
+   f2fs_msg(sbi->sb, KERN_INFO, "orphan cleanup on readonly fs");
+   sbi->sb->s_flags &= ~MS_RDONLY;
+   }
+
+#ifdef CONFIG_QUOTA
+   /* Needed for iput() to work correctly and not trash data */
+   sbi->sb->s_flags |= MS_ACTIVE;
+   /* Turn on quotas so that they are updated correctly */
+   f2fs_enable_quota_files(sbi);
+#endif
+
start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
 
@@ -608,14 +621,21 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
err = recover_orphan_inode(sbi, ino);
if (err) {
f2fs_put_page(page, 1);
-   return err;
+   goto out;
}
}
f2fs_put_page(page, 1);
}
/* clear Orphan Flag */
clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG);
-   return 0;
+out:
+#ifdef CONFIG_QUOTA
+   /* Turn quotas off */
+   f2fs_quota_off_umount(sbi->sb);
+#endif
+   sbi->sb->s_flags = s_flags; /* Restore MS_RDONLY status */
+
+   return err;
 }
 
 static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1bcaa93bfed7..cea329f75068 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -92,6 +92,7 @@ extern char *fault_name[FAULT_MAX];
 #define F2FS_MOUNT_USRQUOTA0x0008
 #define F2FS_MOUNT_GRPQUOTA0x0010
 #define F2FS_MOUNT_PRJQUOTA0x0020
+#define F2FS_MOUNT_QUOTA   0x0040
 
 #define clear_opt(sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)
 #define set_opt(sbi, option)   ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -1121,6 +1122,12 @@ struct f2fs_sb_info {
 #ifdef CONFIG_F2FS_FAULT_INJECTION
struct f2fs_fault_info fault_info;
 #endif
+
+#ifdef CONFIG_QUOTA
+   /* Names of quota files with journalled quota */
+   char *s_qf_names[MAXQUOTAS];
+   int s_jquota_fmt;   /* Format of quota to use */
+#endif
 };
 
 #ifdef CONFIG_F2FS_FAULT_INJECTION
@@ -2433,6 +2440,8 @@ static inline int f2fs_add_link(struct dentry *dentry, 
struct inode *inode)
  */
 int f2fs_inode_dirtied(struct inode *inode, bool sync);
 void f2fs_inode_synced(struct inode *inode);
+void f2fs_enable_quota_files(struct f2fs_sb_info *sbi);
+void f2fs_quota_off_umount(struct super_block *sb);
 int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
 int f2fs_sync_fs(struct 

[PATCH v3] f2fs: support journalled quota

2017-08-07 Thread Chao Yu
This patch supports to enable f2fs to accept quota information through
mount option:
- {usr,grp,prj}jquota=
- jqfmt=

Then, in ->mount flow, we can recover quota file during log replaying,
by this, journelled quota can be supported.

Signed-off-by: Chao Yu 
---
v3:
- add missing quota initialization during recovery.
 Documentation/filesystems/f2fs.txt |   9 +
 fs/f2fs/checkpoint.c   |  26 ++-
 fs/f2fs/f2fs.h |   9 +
 fs/f2fs/recovery.c |  72 +++-
 fs/f2fs/super.c| 325 ++---
 5 files changed, 411 insertions(+), 30 deletions(-)

diff --git a/Documentation/filesystems/f2fs.txt 
b/Documentation/filesystems/f2fs.txt
index b8f495a8b67d..deafeff7795b 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -165,6 +165,15 @@ io_bits=%u Set the bit size of write IO 
requests. It should be set
 usrquota   Enable plain user disk quota accounting.
 grpquota   Enable plain group disk quota accounting.
 prjquota   Enable plain project quota accounting.
+usrjquota=   Appoint specified file and type during mount, so that 
quota
+grpjquota=   information can be properly updated during recovery 
flow,
+prjjquota=   : must be in root directory;
+jqfmt= : [vfsold,vfsv0,vfsv1].
+offusrjquota   Turn off user journelled quota.
+offgrpjquota   Turn off group journelled quota.
+offprjjquota   Turn off project journelled quota.
+quota  Enable plain user disk quota accounting.
+noquotaDisable all plain disk quota option.
 
 

 DEBUGFS ENTRIES
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index da5b49183e09..04fe1df052b2 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -588,11 +588,24 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, 
nid_t ino)
 int recover_orphan_inodes(struct f2fs_sb_info *sbi)
 {
block_t start_blk, orphan_blocks, i, j;
-   int err;
+   unsigned int s_flags = sbi->sb->s_flags;
+   int err = 0;
 
if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG))
return 0;
 
+   if (s_flags & MS_RDONLY) {
+   f2fs_msg(sbi->sb, KERN_INFO, "orphan cleanup on readonly fs");
+   sbi->sb->s_flags &= ~MS_RDONLY;
+   }
+
+#ifdef CONFIG_QUOTA
+   /* Needed for iput() to work correctly and not trash data */
+   sbi->sb->s_flags |= MS_ACTIVE;
+   /* Turn on quotas so that they are updated correctly */
+   f2fs_enable_quota_files(sbi);
+#endif
+
start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
 
@@ -608,14 +621,21 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
err = recover_orphan_inode(sbi, ino);
if (err) {
f2fs_put_page(page, 1);
-   return err;
+   goto out;
}
}
f2fs_put_page(page, 1);
}
/* clear Orphan Flag */
clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG);
-   return 0;
+out:
+#ifdef CONFIG_QUOTA
+   /* Turn quotas off */
+   f2fs_quota_off_umount(sbi->sb);
+#endif
+   sbi->sb->s_flags = s_flags; /* Restore MS_RDONLY status */
+
+   return err;
 }
 
 static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1bcaa93bfed7..cea329f75068 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -92,6 +92,7 @@ extern char *fault_name[FAULT_MAX];
 #define F2FS_MOUNT_USRQUOTA0x0008
 #define F2FS_MOUNT_GRPQUOTA0x0010
 #define F2FS_MOUNT_PRJQUOTA0x0020
+#define F2FS_MOUNT_QUOTA   0x0040
 
 #define clear_opt(sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)
 #define set_opt(sbi, option)   ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -1121,6 +1122,12 @@ struct f2fs_sb_info {
 #ifdef CONFIG_F2FS_FAULT_INJECTION
struct f2fs_fault_info fault_info;
 #endif
+
+#ifdef CONFIG_QUOTA
+   /* Names of quota files with journalled quota */
+   char *s_qf_names[MAXQUOTAS];
+   int s_jquota_fmt;   /* Format of quota to use */
+#endif
 };
 
 #ifdef CONFIG_F2FS_FAULT_INJECTION
@@ -2433,6 +2440,8 @@ static inline int f2fs_add_link(struct dentry *dentry, 
struct inode *inode)
  */
 int f2fs_inode_dirtied(struct inode *inode, bool sync);
 void f2fs_inode_synced(struct inode *inode);
+void f2fs_enable_quota_files(struct f2fs_sb_info *sbi);
+void f2fs_quota_off_umount(struct super_block *sb);
 int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
 int f2fs_sync_fs(struct super_block *sb, int