Skip to content

Commit 4b2414d

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: support journalled quota
This patch supports to enable f2fs to accept quota information through mount option: - {usr,grp,prj}jquota=<quota file path> - jqfmt=<quota type> Then, in ->mount flow, we can recover quota file during log replaying, by this, journelled quota can be supported. Signed-off-by: Chao Yu <yuchao0@huawei.com> [Jaegeuk Kim: Fix wrong return values.] Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent b8c502b commit 4b2414d

File tree

5 files changed

+412
-30
lines changed

5 files changed

+412
-30
lines changed

Documentation/filesystems/f2fs.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ io_bits=%u Set the bit size of write IO requests. It should be set
165165
usrquota Enable plain user disk quota accounting.
166166
grpquota Enable plain group disk quota accounting.
167167
prjquota Enable plain project quota accounting.
168+
usrjquota=<file> Appoint specified file and type during mount, so that quota
169+
grpjquota=<file> information can be properly updated during recovery flow,
170+
prjjquota=<file> <quota file>: must be in root directory;
171+
jqfmt=<quota type> <quota type>: [vfsold,vfsv0,vfsv1].
172+
offusrjquota Turn off user journelled quota.
173+
offgrpjquota Turn off group journelled quota.
174+
offprjjquota Turn off project journelled quota.
175+
quota Enable plain user disk quota accounting.
176+
noquota Disable all plain disk quota option.
168177

169178
================================================================================
170179
DEBUGFS ENTRIES

fs/f2fs/checkpoint.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -588,11 +588,24 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
588588
int recover_orphan_inodes(struct f2fs_sb_info *sbi)
589589
{
590590
block_t start_blk, orphan_blocks, i, j;
591-
int err;
591+
unsigned int s_flags = sbi->sb->s_flags;
592+
int err = 0;
592593

593594
if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG))
594595
return 0;
595596

597+
if (s_flags & MS_RDONLY) {
598+
f2fs_msg(sbi->sb, KERN_INFO, "orphan cleanup on readonly fs");
599+
sbi->sb->s_flags &= ~MS_RDONLY;
600+
}
601+
602+
#ifdef CONFIG_QUOTA
603+
/* Needed for iput() to work correctly and not trash data */
604+
sbi->sb->s_flags |= MS_ACTIVE;
605+
/* Turn on quotas so that they are updated correctly */
606+
f2fs_enable_quota_files(sbi);
607+
#endif
608+
596609
start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
597610
orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
598611

@@ -608,14 +621,21 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
608621
err = recover_orphan_inode(sbi, ino);
609622
if (err) {
610623
f2fs_put_page(page, 1);
611-
return err;
624+
goto out;
612625
}
613626
}
614627
f2fs_put_page(page, 1);
615628
}
616629
/* clear Orphan Flag */
617630
clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG);
618-
return 0;
631+
out:
632+
#ifdef CONFIG_QUOTA
633+
/* Turn quotas off */
634+
f2fs_quota_off_umount(sbi->sb);
635+
#endif
636+
sbi->sb->s_flags = s_flags; /* Restore MS_RDONLY status */
637+
638+
return err;
619639
}
620640

621641
static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)

fs/f2fs/f2fs.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ extern char *fault_name[FAULT_MAX];
9292
#define F2FS_MOUNT_USRQUOTA 0x00080000
9393
#define F2FS_MOUNT_GRPQUOTA 0x00100000
9494
#define F2FS_MOUNT_PRJQUOTA 0x00200000
95+
#define F2FS_MOUNT_QUOTA 0x00400000
9596

9697
#define clear_opt(sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)
9798
#define set_opt(sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -1117,6 +1118,12 @@ struct f2fs_sb_info {
11171118
#ifdef CONFIG_F2FS_FAULT_INJECTION
11181119
struct f2fs_fault_info fault_info;
11191120
#endif
1121+
1122+
#ifdef CONFIG_QUOTA
1123+
/* Names of quota files with journalled quota */
1124+
char *s_qf_names[MAXQUOTAS];
1125+
int s_jquota_fmt; /* Format of quota to use */
1126+
#endif
11201127
};
11211128

11221129
#ifdef CONFIG_F2FS_FAULT_INJECTION
@@ -2429,6 +2436,8 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
24292436
*/
24302437
int f2fs_inode_dirtied(struct inode *inode, bool sync);
24312438
void f2fs_inode_synced(struct inode *inode);
2439+
void f2fs_enable_quota_files(struct f2fs_sb_info *sbi);
2440+
void f2fs_quota_off_umount(struct super_block *sb);
24322441
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
24332442
int f2fs_sync_fs(struct super_block *sb, int sync);
24342443
extern __printf(3, 4)

fs/f2fs/recovery.c

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,34 @@ static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
6969
}
7070

7171
static struct fsync_inode_entry *add_fsync_inode(struct f2fs_sb_info *sbi,
72-
struct list_head *head, nid_t ino)
72+
struct list_head *head, nid_t ino, bool quota_inode)
7373
{
7474
struct inode *inode;
7575
struct fsync_inode_entry *entry;
76+
int err;
7677

7778
inode = f2fs_iget_retry(sbi->sb, ino);
7879
if (IS_ERR(inode))
7980
return ERR_CAST(inode);
8081

82+
err = dquot_initialize(inode);
83+
if (err)
84+
goto err_out;
85+
86+
if (quota_inode) {
87+
err = dquot_alloc_inode(inode);
88+
if (err)
89+
goto err_out;
90+
}
91+
8192
entry = f2fs_kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO);
8293
entry->inode = inode;
8394
list_add_tail(&entry->list, head);
8495

8596
return entry;
97+
err_out:
98+
iput(inode);
99+
return ERR_PTR(err);
86100
}
87101

88102
static void del_fsync_inode(struct fsync_inode_entry *entry)
@@ -107,7 +121,8 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
107121

108122
entry = get_fsync_inode(dir_list, pino);
109123
if (!entry) {
110-
entry = add_fsync_inode(F2FS_I_SB(inode), dir_list, pino);
124+
entry = add_fsync_inode(F2FS_I_SB(inode), dir_list,
125+
pino, false);
111126
if (IS_ERR(entry)) {
112127
dir = ERR_CAST(entry);
113128
err = PTR_ERR(entry);
@@ -140,6 +155,13 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
140155
err = -EEXIST;
141156
goto out_unmap_put;
142157
}
158+
159+
err = dquot_initialize(einode);
160+
if (err) {
161+
iput(einode);
162+
goto out_unmap_put;
163+
}
164+
143165
err = acquire_orphan_inode(F2FS_I_SB(inode));
144166
if (err) {
145167
iput(einode);
@@ -226,18 +248,22 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
226248

227249
entry = get_fsync_inode(head, ino_of_node(page));
228250
if (!entry) {
251+
bool quota_inode = false;
252+
229253
if (!check_only &&
230254
IS_INODE(page) && is_dent_dnode(page)) {
231255
err = recover_inode_page(sbi, page);
232256
if (err)
233257
break;
258+
quota_inode = true;
234259
}
235260

236261
/*
237262
* CP | dnode(F) | inode(DF)
238263
* For this case, we should not give up now.
239264
*/
240-
entry = add_fsync_inode(sbi, head, ino_of_node(page));
265+
entry = add_fsync_inode(sbi, head, ino_of_node(page),
266+
quota_inode);
241267
if (IS_ERR(entry)) {
242268
err = PTR_ERR(entry);
243269
if (err == -ENOENT) {
@@ -328,10 +354,18 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
328354
f2fs_put_page(node_page, 1);
329355

330356
if (ino != dn->inode->i_ino) {
357+
int ret;
358+
331359
/* Deallocate previous index in the node page */
332360
inode = f2fs_iget_retry(sbi->sb, ino);
333361
if (IS_ERR(inode))
334362
return PTR_ERR(inode);
363+
364+
ret = dquot_initialize(inode);
365+
if (ret) {
366+
iput(inode);
367+
return ret;
368+
}
335369
} else {
336370
inode = dn->inode;
337371
}
@@ -558,12 +592,27 @@ int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
558592
struct list_head dir_list;
559593
int err;
560594
int ret = 0;
595+
unsigned long s_flags = sbi->sb->s_flags;
561596
bool need_writecp = false;
562597

598+
if (s_flags & MS_RDONLY) {
599+
f2fs_msg(sbi->sb, KERN_INFO, "orphan cleanup on readonly fs");
600+
sbi->sb->s_flags &= ~MS_RDONLY;
601+
}
602+
603+
#ifdef CONFIG_QUOTA
604+
/* Needed for iput() to work correctly and not trash data */
605+
sbi->sb->s_flags |= MS_ACTIVE;
606+
/* Turn on quotas so that they are updated correctly */
607+
f2fs_enable_quota_files(sbi);
608+
#endif
609+
563610
fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
564611
sizeof(struct fsync_inode_entry));
565-
if (!fsync_entry_slab)
566-
return -ENOMEM;
612+
if (!fsync_entry_slab) {
613+
err = -ENOMEM;
614+
goto out;
615+
}
567616

568617
INIT_LIST_HEAD(&inode_list);
569618
INIT_LIST_HEAD(&dir_list);
@@ -574,11 +623,11 @@ int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
574623
/* step #1: find fsynced inode numbers */
575624
err = find_fsync_dnodes(sbi, &inode_list, check_only);
576625
if (err || list_empty(&inode_list))
577-
goto out;
626+
goto skip;
578627

579628
if (check_only) {
580629
ret = 1;
581-
goto out;
630+
goto skip;
582631
}
583632

584633
need_writecp = true;
@@ -587,7 +636,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
587636
err = recover_data(sbi, &inode_list, &dir_list);
588637
if (!err)
589638
f2fs_bug_on(sbi, !list_empty(&inode_list));
590-
out:
639+
skip:
591640
destroy_fsync_dnodes(&inode_list);
592641

593642
/* truncate meta pages to be used by the recovery */
@@ -615,5 +664,12 @@ int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
615664
}
616665

617666
kmem_cache_destroy(fsync_entry_slab);
667+
out:
668+
#ifdef CONFIG_QUOTA
669+
/* Turn quotas off */
670+
f2fs_quota_off_umount(sbi->sb);
671+
#endif
672+
sbi->sb->s_flags = s_flags; /* Restore MS_RDONLY status */
673+
618674
return ret ? ret: err;
619675
}

0 commit comments

Comments
 (0)