mirror of
https://gitee.com/openharmony/third_party_f2fs-tools
synced 2024-11-27 04:00:57 +00:00
mkfs.f2fs: support quota option in mkfs
This patch let mkfs to handle quota option and create quota files. Signed-off-by: Hyojun Kim <hyojun@google.com> Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
This commit is contained in:
parent
68593f4981
commit
23a872f9ba
@ -458,6 +458,12 @@ enum {
|
|||||||
#define F2FS_NODE_INO(sbi) (sbi->node_ino_num)
|
#define F2FS_NODE_INO(sbi) (sbi->node_ino_num)
|
||||||
#define F2FS_META_INO(sbi) (sbi->meta_ino_num)
|
#define F2FS_META_INO(sbi) (sbi->meta_ino_num)
|
||||||
|
|
||||||
|
#define F2FS_MAX_QUOTAS 3
|
||||||
|
#define QUOTA_DATA(i) (2)
|
||||||
|
#define QUOTA_INO(sb,t) (le32_to_cpu((sb)->qf_ino[t]))
|
||||||
|
|
||||||
|
#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
|
||||||
|
|
||||||
/* This flag is used by node and meta inodes, and by recovery */
|
/* This flag is used by node and meta inodes, and by recovery */
|
||||||
#define GFP_F2FS_ZERO (GFP_NOFS | __GFP_ZERO)
|
#define GFP_F2FS_ZERO (GFP_NOFS | __GFP_ZERO)
|
||||||
|
|
||||||
@ -478,6 +484,7 @@ enum {
|
|||||||
#define F2FS_FEATURE_PRJQUOTA 0x0010
|
#define F2FS_FEATURE_PRJQUOTA 0x0010
|
||||||
#define F2FS_FEATURE_INODE_CHKSUM 0x0020
|
#define F2FS_FEATURE_INODE_CHKSUM 0x0020
|
||||||
#define F2FS_FEATURE_FLEXIBLE_INLINE_XATTR 0x0040
|
#define F2FS_FEATURE_FLEXIBLE_INLINE_XATTR 0x0040
|
||||||
|
#define F2FS_FEATURE_QUOTA_INO 0x0080
|
||||||
|
|
||||||
#define MAX_VOLUME_NAME 512
|
#define MAX_VOLUME_NAME 512
|
||||||
|
|
||||||
@ -528,7 +535,8 @@ struct f2fs_super_block {
|
|||||||
__u8 encryption_level; /* versioning level for encryption */
|
__u8 encryption_level; /* versioning level for encryption */
|
||||||
__u8 encrypt_pw_salt[16]; /* Salt used for string2key algorithm */
|
__u8 encrypt_pw_salt[16]; /* Salt used for string2key algorithm */
|
||||||
struct f2fs_device devs[MAX_DEVICES]; /* device list */
|
struct f2fs_device devs[MAX_DEVICES]; /* device list */
|
||||||
__u8 reserved[327]; /* valid reserved region */
|
__le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */
|
||||||
|
__u8 reserved[315]; /* valid reserved region */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1171,4 +1179,14 @@ static inline __le64 get_cp_crc(struct f2fs_checkpoint *cp)
|
|||||||
return cpu_to_le64(cp_ver);
|
return cpu_to_le64(cp_ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int is_qf_ino(struct f2fs_super_block *sb, nid_t ino)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < F2FS_MAX_QUOTAS; i++)
|
||||||
|
if (sb->qf_ino[i] == ino)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*__F2FS_FS_H */
|
#endif /*__F2FS_FS_H */
|
||||||
|
77
include/quota.h
Normal file
77
include/quota.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Header file for disk format of new quotafile format
|
||||||
|
*
|
||||||
|
* Copied essential definitions and structures for mkfs.f2fs from quotaio.h
|
||||||
|
*
|
||||||
|
* Aditya Kali <adityakali@google.com>
|
||||||
|
* Jan Kara <jack@suse.cz>
|
||||||
|
* Hyojun Kim <hyojun@google.com> - Ported to f2fs-tools
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef F2FS_QUOTA_H
|
||||||
|
#define F2FS_QUOTA_H
|
||||||
|
|
||||||
|
enum quota_type {
|
||||||
|
USRQUOTA = 0,
|
||||||
|
GRPQUOTA = 1,
|
||||||
|
PRJQUOTA = 2,
|
||||||
|
MAXQUOTAS = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if MAXQUOTAS > 32
|
||||||
|
#error "cannot have more than 32 quota types to fit in qtype_bits"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define QUOTA_USR_BIT (1 << USRQUOTA)
|
||||||
|
#define QUOTA_GRP_BIT (1 << GRPQUOTA)
|
||||||
|
#define QUOTA_PRJ_BIT (1 << PRJQUOTA)
|
||||||
|
#define QUOTA_ALL_BIT (QUOTA_USR_BIT | QUOTA_GRP_BIT | QUOTA_PRJ_BIT)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions of magics and versions of current quota files
|
||||||
|
*/
|
||||||
|
#define INITQMAGICS {\
|
||||||
|
0xd9c01f11, /* USRQUOTA */\
|
||||||
|
0xd9c01927, /* GRPQUOTA */\
|
||||||
|
0xd9c03f14 /* PRJQUOTA */\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader) /* Offset of info header in file */
|
||||||
|
|
||||||
|
#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
|
||||||
|
#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
|
||||||
|
|
||||||
|
#define QT_TREEOFF 1 /* Offset of tree in file in blocks */
|
||||||
|
|
||||||
|
struct v2_disk_dqheader {
|
||||||
|
u_int32_t dqh_magic; /* Magic number identifying file */
|
||||||
|
u_int32_t dqh_version; /* File version */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* Header with type and version specific information */
|
||||||
|
struct v2_disk_dqinfo {
|
||||||
|
u_int32_t dqi_bgrace; /* Time before block soft limit becomes hard limit */
|
||||||
|
u_int32_t dqi_igrace; /* Time before inode soft limit becomes hard limit */
|
||||||
|
u_int32_t dqi_flags; /* Flags for quotafile (DQF_*) */
|
||||||
|
u_int32_t dqi_blocks; /* Number of blocks in file */
|
||||||
|
u_int32_t dqi_free_blk; /* Number of first free block in the list */
|
||||||
|
u_int32_t dqi_free_entry; /* Number of block with at least one free entry */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct v2r1_disk_dqblk {
|
||||||
|
__le32 dqb_id; /* id this quota applies to */
|
||||||
|
__le32 dqb_pad;
|
||||||
|
__le64 dqb_ihardlimit; /* absolute limit on allocated inodes */
|
||||||
|
__le64 dqb_isoftlimit; /* preferred inode limit */
|
||||||
|
__le64 dqb_curinodes; /* current # allocated inodes */
|
||||||
|
__le64 dqb_bhardlimit; /* absolute limit on disk space
|
||||||
|
* (in QUOTABLOCK_SIZE) */
|
||||||
|
__le64 dqb_bsoftlimit; /* preferred limit on disk space
|
||||||
|
* (in QUOTABLOCK_SIZE) */
|
||||||
|
__le64 dqb_curspace; /* current space occupied (in bytes) */
|
||||||
|
__le64 dqb_btime; /* time limit for excessive disk use */
|
||||||
|
__le64 dqb_itime; /* time limit for excessive inode use */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#endif
|
@ -19,6 +19,7 @@
|
|||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
#include "f2fs_fs.h"
|
#include "f2fs_fs.h"
|
||||||
|
#include "quota.h"
|
||||||
#include "f2fs_format_utils.h"
|
#include "f2fs_format_utils.h"
|
||||||
|
|
||||||
extern struct f2fs_configuration c;
|
extern struct f2fs_configuration c;
|
||||||
@ -32,6 +33,8 @@ struct f2fs_checkpoint *cp;
|
|||||||
#define last_zone(cur) ((cur - 1) * c.segs_per_zone)
|
#define last_zone(cur) ((cur - 1) * c.segs_per_zone)
|
||||||
#define last_section(cur) (cur + (c.secs_per_zone - 1) * c.segs_per_sec)
|
#define last_section(cur) (cur + (c.secs_per_zone - 1) * c.segs_per_sec)
|
||||||
|
|
||||||
|
static unsigned int quotatype_bits = 0;
|
||||||
|
|
||||||
const char *media_ext_lists[] = {
|
const char *media_ext_lists[] = {
|
||||||
"jpg",
|
"jpg",
|
||||||
"gif",
|
"gif",
|
||||||
@ -153,6 +156,8 @@ static int f2fs_prepare_super_block(void)
|
|||||||
u_int32_t sit_bitmap_size, max_sit_bitmap_size;
|
u_int32_t sit_bitmap_size, max_sit_bitmap_size;
|
||||||
u_int32_t max_nat_bitmap_size, max_nat_segments;
|
u_int32_t max_nat_bitmap_size, max_nat_segments;
|
||||||
u_int32_t total_zones;
|
u_int32_t total_zones;
|
||||||
|
u_int32_t next_ino;
|
||||||
|
enum quota_type qtype;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
set_sb(magic, F2FS_SUPER_MAGIC);
|
set_sb(magic, F2FS_SUPER_MAGIC);
|
||||||
@ -382,6 +387,17 @@ static int f2fs_prepare_super_block(void)
|
|||||||
set_sb(node_ino, 1);
|
set_sb(node_ino, 1);
|
||||||
set_sb(meta_ino, 2);
|
set_sb(meta_ino, 2);
|
||||||
set_sb(root_ino, 3);
|
set_sb(root_ino, 3);
|
||||||
|
next_ino = 4;
|
||||||
|
|
||||||
|
if (c.feature & cpu_to_le32(F2FS_FEATURE_QUOTA_INO)) {
|
||||||
|
quotatype_bits = QUOTA_USR_BIT | QUOTA_GRP_BIT;
|
||||||
|
if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA))
|
||||||
|
quotatype_bits |= QUOTA_PRJ_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++)
|
||||||
|
sb->qf_ino[qtype] =
|
||||||
|
((1 << qtype) & quotatype_bits) ? next_ino++ : 0;
|
||||||
|
|
||||||
if (total_zones <= 6) {
|
if (total_zones <= 6) {
|
||||||
MSG(1, "\tError: %d zones: Need more zones "
|
MSG(1, "\tError: %d zones: Need more zones "
|
||||||
@ -513,6 +529,9 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
char *cp_payload = NULL;
|
char *cp_payload = NULL;
|
||||||
char *sum_compact, *sum_compact_p;
|
char *sum_compact, *sum_compact_p;
|
||||||
struct f2fs_summary *sum_entry;
|
struct f2fs_summary *sum_entry;
|
||||||
|
enum quota_type qtype;
|
||||||
|
u_int32_t quota_inum, quota_dnum;
|
||||||
|
int off;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
cp = calloc(F2FS_BLKSIZE, 1);
|
cp = calloc(F2FS_BLKSIZE, 1);
|
||||||
@ -562,9 +581,16 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
set_cp(cur_data_segno[i], 0xffffffff);
|
set_cp(cur_data_segno[i], 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_cp(cur_node_blkoff[0], 1);
|
quota_inum = quota_dnum = 0;
|
||||||
set_cp(cur_data_blkoff[0], 1);
|
for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++)
|
||||||
set_cp(valid_block_count, 2);
|
if (sb->qf_ino[qtype]) {
|
||||||
|
quota_inum++;
|
||||||
|
quota_dnum += QUOTA_DATA(qtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_cp(cur_node_blkoff[0], 1 + quota_inum);
|
||||||
|
set_cp(cur_data_blkoff[0], 1 + quota_dnum);
|
||||||
|
set_cp(valid_block_count, 2 + quota_inum + quota_dnum);
|
||||||
set_cp(rsvd_segment_count, c.reserved_segments);
|
set_cp(rsvd_segment_count, c.reserved_segments);
|
||||||
set_cp(overprov_segment_count, (get_sb(segment_count_main) -
|
set_cp(overprov_segment_count, (get_sb(segment_count_main) -
|
||||||
get_cp(rsvd_segment_count)) *
|
get_cp(rsvd_segment_count)) *
|
||||||
@ -593,9 +619,9 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
|
|
||||||
set_cp(ckpt_flags, flags);
|
set_cp(ckpt_flags, flags);
|
||||||
set_cp(cp_pack_start_sum, 1 + get_sb(cp_payload));
|
set_cp(cp_pack_start_sum, 1 + get_sb(cp_payload));
|
||||||
set_cp(valid_node_count, 1);
|
set_cp(valid_node_count, 1 + quota_inum);
|
||||||
set_cp(valid_inode_count, 1);
|
set_cp(valid_inode_count, 1 + quota_inum);
|
||||||
set_cp(next_free_nid, get_sb(root_ino) + 1);
|
set_cp(next_free_nid, get_sb(root_ino) + 1 + quota_inum);
|
||||||
set_cp(sit_ver_bitmap_bytesize, ((get_sb(segment_count_sit) / 2) <<
|
set_cp(sit_ver_bitmap_bytesize, ((get_sb(segment_count_sit) / 2) <<
|
||||||
get_sb(log_blocks_per_seg)) / 8);
|
get_sb(log_blocks_per_seg)) / 8);
|
||||||
|
|
||||||
@ -653,7 +679,7 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
|
SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
|
||||||
|
|
||||||
journal = &sum->journal;
|
journal = &sum->journal;
|
||||||
journal->n_nats = cpu_to_le16(1);
|
journal->n_nats = cpu_to_le16(1 + quota_inum);
|
||||||
journal->nat_j.entries[0].nid = sb->root_ino;
|
journal->nat_j.entries[0].nid = sb->root_ino;
|
||||||
journal->nat_j.entries[0].ne.version = 0;
|
journal->nat_j.entries[0].ne.version = 0;
|
||||||
journal->nat_j.entries[0].ne.ino = sb->root_ino;
|
journal->nat_j.entries[0].ne.ino = sb->root_ino;
|
||||||
@ -661,6 +687,19 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
get_sb(main_blkaddr) +
|
get_sb(main_blkaddr) +
|
||||||
get_cp(cur_node_segno[0]) * c.blks_per_seg);
|
get_cp(cur_node_segno[0]) * c.blks_per_seg);
|
||||||
|
|
||||||
|
for (qtype = 0, i = 1; qtype < F2FS_MAX_QUOTAS; qtype++) {
|
||||||
|
if (sb->qf_ino[qtype] == 0)
|
||||||
|
continue;
|
||||||
|
journal->nat_j.entries[i].nid = sb->qf_ino[qtype];
|
||||||
|
journal->nat_j.entries[i].ne.version = 0;
|
||||||
|
journal->nat_j.entries[i].ne.ino = sb->qf_ino[qtype];
|
||||||
|
journal->nat_j.entries[i].ne.block_addr = cpu_to_le32(
|
||||||
|
get_sb(main_blkaddr) +
|
||||||
|
get_cp(cur_node_segno[0]) *
|
||||||
|
c.blks_per_seg + i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(sum_compact_p, &journal->n_nats, SUM_JOURNAL_SIZE);
|
memcpy(sum_compact_p, &journal->n_nats, SUM_JOURNAL_SIZE);
|
||||||
sum_compact_p += SUM_JOURNAL_SIZE;
|
sum_compact_p += SUM_JOURNAL_SIZE;
|
||||||
|
|
||||||
@ -669,8 +708,11 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
journal->n_sits = cpu_to_le16(6);
|
journal->n_sits = cpu_to_le16(6);
|
||||||
journal->sit_j.entries[0].segno = cp->cur_node_segno[0];
|
journal->sit_j.entries[0].segno = cp->cur_node_segno[0];
|
||||||
journal->sit_j.entries[0].se.vblocks =
|
journal->sit_j.entries[0].se.vblocks =
|
||||||
cpu_to_le16((CURSEG_HOT_NODE << 10) | 1);
|
cpu_to_le16((CURSEG_HOT_NODE << 10) |
|
||||||
|
(1 + quota_inum));
|
||||||
f2fs_set_bit(0, (char *)journal->sit_j.entries[0].se.valid_map);
|
f2fs_set_bit(0, (char *)journal->sit_j.entries[0].se.valid_map);
|
||||||
|
for (i = 1; i <= quota_inum; i++)
|
||||||
|
f2fs_set_bit(i, (char *)journal->sit_j.entries[0].se.valid_map);
|
||||||
journal->sit_j.entries[1].segno = cp->cur_node_segno[1];
|
journal->sit_j.entries[1].segno = cp->cur_node_segno[1];
|
||||||
journal->sit_j.entries[1].se.vblocks =
|
journal->sit_j.entries[1].se.vblocks =
|
||||||
cpu_to_le16((CURSEG_WARM_NODE << 10));
|
cpu_to_le16((CURSEG_WARM_NODE << 10));
|
||||||
@ -681,8 +723,12 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
/* data sit for root */
|
/* data sit for root */
|
||||||
journal->sit_j.entries[3].segno = cp->cur_data_segno[0];
|
journal->sit_j.entries[3].segno = cp->cur_data_segno[0];
|
||||||
journal->sit_j.entries[3].se.vblocks =
|
journal->sit_j.entries[3].se.vblocks =
|
||||||
cpu_to_le16((CURSEG_HOT_DATA << 10) | 1);
|
cpu_to_le16((CURSEG_HOT_DATA << 10) |
|
||||||
|
(1 + quota_dnum));
|
||||||
f2fs_set_bit(0, (char *)journal->sit_j.entries[3].se.valid_map);
|
f2fs_set_bit(0, (char *)journal->sit_j.entries[3].se.valid_map);
|
||||||
|
for (i = 1; i <= quota_dnum; i++)
|
||||||
|
f2fs_set_bit(i, (char *)journal->sit_j.entries[3].se.valid_map);
|
||||||
|
|
||||||
journal->sit_j.entries[4].segno = cp->cur_data_segno[1];
|
journal->sit_j.entries[4].segno = cp->cur_data_segno[1];
|
||||||
journal->sit_j.entries[4].se.vblocks =
|
journal->sit_j.entries[4].se.vblocks =
|
||||||
cpu_to_le16((CURSEG_WARM_DATA << 10));
|
cpu_to_le16((CURSEG_WARM_DATA << 10));
|
||||||
@ -697,6 +743,20 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
sum_entry = (struct f2fs_summary *)sum_compact_p;
|
sum_entry = (struct f2fs_summary *)sum_compact_p;
|
||||||
sum_entry->nid = sb->root_ino;
|
sum_entry->nid = sb->root_ino;
|
||||||
sum_entry->ofs_in_node = 0;
|
sum_entry->ofs_in_node = 0;
|
||||||
|
|
||||||
|
off = 1;
|
||||||
|
for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++) {
|
||||||
|
if (sb->qf_ino[qtype] == 0)
|
||||||
|
continue;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < QUOTA_DATA(qtype); j++) {
|
||||||
|
(sum_entry + off + j)->nid = sb->qf_ino[qtype];
|
||||||
|
(sum_entry + off + j)->ofs_in_node = j;
|
||||||
|
}
|
||||||
|
off += QUOTA_DATA(qtype);
|
||||||
|
}
|
||||||
|
|
||||||
/* warm data summary, nothing to do */
|
/* warm data summary, nothing to do */
|
||||||
/* cold data summary, nothing to do */
|
/* cold data summary, nothing to do */
|
||||||
|
|
||||||
@ -714,6 +774,13 @@ static int f2fs_write_check_point_pack(void)
|
|||||||
|
|
||||||
sum->entries[0].nid = sb->root_ino;
|
sum->entries[0].nid = sb->root_ino;
|
||||||
sum->entries[0].ofs_in_node = 0;
|
sum->entries[0].ofs_in_node = 0;
|
||||||
|
for (qtype = i = 0; qtype < F2FS_MAX_QUOTAS; qtype++) {
|
||||||
|
if (sb->qf_ino[qtype] == 0)
|
||||||
|
continue;
|
||||||
|
sum->entries[1 + i].nid = sb->qf_ino[qtype];
|
||||||
|
sum->entries[1 + i].ofs_in_node = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
cp_seg_blk++;
|
cp_seg_blk++;
|
||||||
DBG(1, "\tWriting Segment summary for HOT_NODE, at offset 0x%08"PRIx64"\n",
|
DBG(1, "\tWriting Segment summary for HOT_NODE, at offset 0x%08"PRIx64"\n",
|
||||||
@ -855,12 +922,19 @@ static int f2fs_write_super_block(void)
|
|||||||
static int discard_obsolete_dnode(struct f2fs_node *raw_node, u_int64_t offset)
|
static int discard_obsolete_dnode(struct f2fs_node *raw_node, u_int64_t offset)
|
||||||
{
|
{
|
||||||
u_int64_t next_blkaddr = 0;
|
u_int64_t next_blkaddr = 0;
|
||||||
u_int64_t root_inode_pos = get_sb(main_blkaddr);
|
|
||||||
u64 end_blkaddr = (get_sb(segment_count_main) <<
|
u64 end_blkaddr = (get_sb(segment_count_main) <<
|
||||||
get_sb(log_blocks_per_seg)) + get_sb(main_blkaddr);
|
get_sb(log_blocks_per_seg)) + get_sb(main_blkaddr);
|
||||||
|
u_int64_t start_inode_pos = get_sb(main_blkaddr);
|
||||||
|
u_int64_t last_inode_pos;
|
||||||
|
enum quota_type qtype;
|
||||||
|
u_int32_t quota_inum = 0;
|
||||||
|
|
||||||
|
for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++)
|
||||||
|
if (sb->qf_ino[qtype]) quota_inum++;
|
||||||
|
|
||||||
/* only root inode was written before truncating dnodes */
|
/* only root inode was written before truncating dnodes */
|
||||||
root_inode_pos += c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg;
|
last_inode_pos = start_inode_pos +
|
||||||
|
c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg + quota_inum;
|
||||||
|
|
||||||
if (c.zoned_mode)
|
if (c.zoned_mode)
|
||||||
return 0;
|
return 0;
|
||||||
@ -883,7 +957,7 @@ static int discard_obsolete_dnode(struct f2fs_node *raw_node, u_int64_t offset)
|
|||||||
}
|
}
|
||||||
offset = next_blkaddr;
|
offset = next_blkaddr;
|
||||||
/* should avoid recursive chain due to stale data */
|
/* should avoid recursive chain due to stale data */
|
||||||
if (offset == root_inode_pos)
|
if (offset >= start_inode_pos || offset <= last_inode_pos)
|
||||||
break;
|
break;
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
@ -963,7 +1037,6 @@ static int f2fs_write_root_inode(void)
|
|||||||
c.blks_per_seg, main_area_node_seg_blk_offset);
|
c.blks_per_seg, main_area_node_seg_blk_offset);
|
||||||
if (dev_write_block(raw_node, main_area_node_seg_blk_offset)) {
|
if (dev_write_block(raw_node, main_area_node_seg_blk_offset)) {
|
||||||
MSG(1, "\tError: While writing the raw_node to disk!!!\n");
|
MSG(1, "\tError: While writing the raw_node to disk!!!\n");
|
||||||
free(raw_node);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -974,10 +1047,161 @@ static int f2fs_write_root_inode(void)
|
|||||||
|
|
||||||
#ifndef WITH_ANDROID
|
#ifndef WITH_ANDROID
|
||||||
if (discard_obsolete_dnode(raw_node, main_area_node_seg_blk_offset)) {
|
if (discard_obsolete_dnode(raw_node, main_area_node_seg_blk_offset)) {
|
||||||
free(raw_node);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f2fs_write_default_quota(int qtype, unsigned int blkaddr)
|
||||||
|
{
|
||||||
|
char *filebuf = calloc(F2FS_BLKSIZE, 2);
|
||||||
|
int file_magics[] = INITQMAGICS;
|
||||||
|
struct v2_disk_dqheader ddqheader;
|
||||||
|
struct v2_disk_dqinfo ddqinfo;
|
||||||
|
struct v2r1_disk_dqblk dqblk;
|
||||||
|
|
||||||
|
if (filebuf == NULL) {
|
||||||
|
MSG(1, "\tError: Calloc Failed for filebuf!!!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write basic quota header */
|
||||||
|
ddqheader.dqh_magic = cpu_to_le32(file_magics[qtype]);
|
||||||
|
/* only support QF_VFSV1 */
|
||||||
|
ddqheader.dqh_version = cpu_to_le32(1);
|
||||||
|
|
||||||
|
memcpy(filebuf, &ddqheader, sizeof(ddqheader));
|
||||||
|
|
||||||
|
/* Fill Initial quota file content */
|
||||||
|
ddqinfo.dqi_bgrace = cpu_to_le32(MAX_DQ_TIME);
|
||||||
|
ddqinfo.dqi_igrace = cpu_to_le32(MAX_IQ_TIME);
|
||||||
|
ddqinfo.dqi_flags = cpu_to_le32(0);
|
||||||
|
ddqinfo.dqi_blocks = cpu_to_le32(QT_TREEOFF + 5);
|
||||||
|
ddqinfo.dqi_free_blk = cpu_to_le32(0);
|
||||||
|
ddqinfo.dqi_free_entry = cpu_to_le32(5);
|
||||||
|
|
||||||
|
memcpy(filebuf + V2_DQINFOOFF, &ddqinfo, sizeof(ddqinfo));
|
||||||
|
|
||||||
|
filebuf[1024] = 2;
|
||||||
|
filebuf[2048] = 3;
|
||||||
|
filebuf[3072] = 4;
|
||||||
|
filebuf[4096] = 5;
|
||||||
|
|
||||||
|
filebuf[5120 + 8] = 1;
|
||||||
|
|
||||||
|
dqblk.dqb_id = cpu_to_le32(0);
|
||||||
|
dqblk.dqb_pad = cpu_to_le32(0);
|
||||||
|
dqblk.dqb_ihardlimit = cpu_to_le64(0);
|
||||||
|
dqblk.dqb_isoftlimit = cpu_to_le64(0);
|
||||||
|
dqblk.dqb_curinodes = cpu_to_le64(1);
|
||||||
|
dqblk.dqb_bhardlimit = cpu_to_le64(0);
|
||||||
|
dqblk.dqb_bsoftlimit = cpu_to_le64(0);
|
||||||
|
dqblk.dqb_curspace = cpu_to_le64(4096);
|
||||||
|
dqblk.dqb_btime = cpu_to_le64(0);
|
||||||
|
dqblk.dqb_itime = cpu_to_le64(0);
|
||||||
|
|
||||||
|
memcpy(filebuf + 5136, &dqblk, sizeof(struct v2r1_disk_dqblk));
|
||||||
|
|
||||||
|
/* Write two blocks */
|
||||||
|
if (dev_write_block(filebuf, blkaddr) ||
|
||||||
|
dev_write_block(filebuf + F2FS_BLKSIZE, blkaddr + 1)) {
|
||||||
|
MSG(1, "\tError: While writing the quota_blk to disk!!!\n");
|
||||||
|
free(filebuf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(filebuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f2fs_write_qf_inode(int qtype)
|
||||||
|
{
|
||||||
|
struct f2fs_node *raw_node = NULL;
|
||||||
|
u_int64_t data_blk_nor;
|
||||||
|
u_int64_t main_area_node_seg_blk_offset = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
raw_node = calloc(F2FS_BLKSIZE, 1);
|
||||||
|
if (raw_node == NULL) {
|
||||||
|
MSG(1, "\tError: Calloc Failed for raw_node!!!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_node->footer.nid = sb->qf_ino[qtype];
|
||||||
|
raw_node->footer.ino = sb->qf_ino[qtype];
|
||||||
|
raw_node->footer.cp_ver = cpu_to_le64(1);
|
||||||
|
raw_node->footer.next_blkaddr = cpu_to_le32(
|
||||||
|
get_sb(main_blkaddr) +
|
||||||
|
c.cur_seg[CURSEG_HOT_NODE] *
|
||||||
|
c.blks_per_seg + 1 + qtype + 1);
|
||||||
|
|
||||||
|
raw_node->i.i_mode = cpu_to_le16(0x8180);
|
||||||
|
raw_node->i.i_links = cpu_to_le32(1);
|
||||||
|
raw_node->i.i_uid = cpu_to_le32(getuid());
|
||||||
|
raw_node->i.i_gid = cpu_to_le32(getgid());
|
||||||
|
|
||||||
|
raw_node->i.i_size = cpu_to_le64(1024 * 6); /* Hard coded */
|
||||||
|
raw_node->i.i_blocks = cpu_to_le64(1 + QUOTA_DATA(qtype));
|
||||||
|
|
||||||
|
raw_node->i.i_atime = cpu_to_le32(time(NULL));
|
||||||
|
raw_node->i.i_atime_nsec = 0;
|
||||||
|
raw_node->i.i_ctime = cpu_to_le32(time(NULL));
|
||||||
|
raw_node->i.i_ctime_nsec = 0;
|
||||||
|
raw_node->i.i_mtime = cpu_to_le32(time(NULL));
|
||||||
|
raw_node->i.i_mtime_nsec = 0;
|
||||||
|
raw_node->i.i_generation = 0;
|
||||||
|
raw_node->i.i_xattr_nid = 0;
|
||||||
|
raw_node->i.i_flags = FS_IMMUTABLE_FL;
|
||||||
|
raw_node->i.i_current_depth = cpu_to_le32(1);
|
||||||
|
raw_node->i.i_dir_level = DEF_DIR_LEVEL;
|
||||||
|
|
||||||
|
if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
|
||||||
|
raw_node->i.i_inline = F2FS_EXTRA_ATTR;
|
||||||
|
raw_node->i.i_extra_isize =
|
||||||
|
cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA))
|
||||||
|
raw_node->i.i_projid = cpu_to_le32(F2FS_DEF_PROJID);
|
||||||
|
|
||||||
|
data_blk_nor = get_sb(main_blkaddr) +
|
||||||
|
c.cur_seg[CURSEG_HOT_DATA] * c.blks_per_seg + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < qtype; i++)
|
||||||
|
if (sb->qf_ino[i])
|
||||||
|
data_blk_nor += QUOTA_DATA(i);
|
||||||
|
|
||||||
|
/* write two blocks */
|
||||||
|
if (f2fs_write_default_quota(qtype, data_blk_nor)) {
|
||||||
|
free(raw_node);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < QUOTA_DATA(qtype); i++)
|
||||||
|
raw_node->i.i_addr[get_extra_isize(raw_node) + i] =
|
||||||
|
cpu_to_le32(data_blk_nor + i);
|
||||||
|
raw_node->i.i_ext.fofs = 0;
|
||||||
|
raw_node->i.i_ext.blk_addr = 0;
|
||||||
|
raw_node->i.i_ext.len = 0;
|
||||||
|
|
||||||
|
if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
|
||||||
|
raw_node->i.i_inode_checksum =
|
||||||
|
cpu_to_le32(f2fs_inode_chksum(raw_node));
|
||||||
|
|
||||||
|
main_area_node_seg_blk_offset = get_sb(main_blkaddr);
|
||||||
|
main_area_node_seg_blk_offset += c.cur_seg[CURSEG_HOT_NODE] *
|
||||||
|
c.blks_per_seg + qtype + 1;
|
||||||
|
|
||||||
|
DBG(1, "\tWriting quota inode (hot node), %x %x %x at offset 0x%08"PRIu64"\n",
|
||||||
|
get_sb(main_blkaddr),
|
||||||
|
c.cur_seg[CURSEG_HOT_NODE],
|
||||||
|
c.blks_per_seg, main_area_node_seg_blk_offset);
|
||||||
|
if (dev_write_block(raw_node, main_area_node_seg_blk_offset)) {
|
||||||
|
MSG(1, "\tError: While writing the raw_node to disk!!!\n");
|
||||||
|
free(raw_node);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
free(raw_node);
|
free(raw_node);
|
||||||
return 0;
|
return 0;
|
||||||
@ -987,6 +1211,8 @@ static int f2fs_update_nat_root(void)
|
|||||||
{
|
{
|
||||||
struct f2fs_nat_block *nat_blk = NULL;
|
struct f2fs_nat_block *nat_blk = NULL;
|
||||||
u_int64_t nat_seg_blk_offset = 0;
|
u_int64_t nat_seg_blk_offset = 0;
|
||||||
|
enum quota_type qtype;
|
||||||
|
int i;
|
||||||
|
|
||||||
nat_blk = calloc(F2FS_BLKSIZE, 1);
|
nat_blk = calloc(F2FS_BLKSIZE, 1);
|
||||||
if(nat_blk == NULL) {
|
if(nat_blk == NULL) {
|
||||||
@ -994,6 +1220,18 @@ static int f2fs_update_nat_root(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update quota */
|
||||||
|
for (qtype = i = 0; qtype < F2FS_MAX_QUOTAS; qtype++) {
|
||||||
|
if (sb->qf_ino[qtype] == 0)
|
||||||
|
continue;
|
||||||
|
nat_blk->entries[sb->qf_ino[qtype]].block_addr =
|
||||||
|
cpu_to_le32(get_sb(main_blkaddr) +
|
||||||
|
c.cur_seg[CURSEG_HOT_NODE] *
|
||||||
|
c.blks_per_seg + i + 1);
|
||||||
|
nat_blk->entries[sb->qf_ino[qtype]].ino = sb->qf_ino[qtype];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
/* update root */
|
/* update root */
|
||||||
nat_blk->entries[get_sb(root_ino)].block_addr = cpu_to_le32(
|
nat_blk->entries[get_sb(root_ino)].block_addr = cpu_to_le32(
|
||||||
get_sb(main_blkaddr) +
|
get_sb(main_blkaddr) +
|
||||||
@ -1048,6 +1286,7 @@ static int f2fs_add_default_dentry_root(void)
|
|||||||
/* bitmap for . and .. */
|
/* bitmap for . and .. */
|
||||||
test_and_set_bit_le(0, dent_blk->dentry_bitmap);
|
test_and_set_bit_le(0, dent_blk->dentry_bitmap);
|
||||||
test_and_set_bit_le(1, dent_blk->dentry_bitmap);
|
test_and_set_bit_le(1, dent_blk->dentry_bitmap);
|
||||||
|
|
||||||
data_blk_offset = get_sb(main_blkaddr);
|
data_blk_offset = get_sb(main_blkaddr);
|
||||||
data_blk_offset += c.cur_seg[CURSEG_HOT_DATA] *
|
data_blk_offset += c.cur_seg[CURSEG_HOT_DATA] *
|
||||||
c.blks_per_seg;
|
c.blks_per_seg;
|
||||||
@ -1066,6 +1305,7 @@ static int f2fs_add_default_dentry_root(void)
|
|||||||
|
|
||||||
static int f2fs_create_root_dir(void)
|
static int f2fs_create_root_dir(void)
|
||||||
{
|
{
|
||||||
|
enum quota_type qtype;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
err = f2fs_write_root_inode();
|
err = f2fs_write_root_inode();
|
||||||
@ -1074,6 +1314,16 @@ static int f2fs_create_root_dir(void)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++) {
|
||||||
|
if (sb->qf_ino[qtype] == 0)
|
||||||
|
continue;
|
||||||
|
err = f2fs_write_qf_inode(qtype);
|
||||||
|
if (err < 0) {
|
||||||
|
MSG(1, "\tError: Failed to write quota inode!!!\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = f2fs_update_nat_root();
|
err = f2fs_update_nat_root();
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
MSG(1, "\tError: Failed to update NAT for root!!!\n");
|
MSG(1, "\tError: Failed to update NAT for root!!!\n");
|
||||||
|
@ -88,6 +88,8 @@ static void parse_feature(const char *features)
|
|||||||
c.feature |= cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM);
|
c.feature |= cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM);
|
||||||
} else if (!strcmp(features, "flexible_inline_xattr")) {
|
} else if (!strcmp(features, "flexible_inline_xattr")) {
|
||||||
c.feature |= cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR);
|
c.feature |= cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR);
|
||||||
|
} else if (!strcmp(features, "quota")) {
|
||||||
|
c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
|
||||||
} else {
|
} else {
|
||||||
MSG(0, "Error: Wrong features\n");
|
MSG(0, "Error: Wrong features\n");
|
||||||
mkfs_usage();
|
mkfs_usage();
|
||||||
|
Loading…
Reference in New Issue
Block a user