f2fs: reserve the xattr space dynamically
This patch enables the number of direct pointers inside on-disk inode block to be changed dynamically according to the size of inline xattr space. The number of direct pointers, ADDRS_PER_INODE, can be changed only if the file has inline xattr flag. The number of direct pointers that will be used by inline xattrs is defined as F2FS_INLINE_XATTR_ADDRS. Current patch assigns F2FS_INLINE_XATTR_ADDRS to 0 temporarily. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
This commit is contained in:
parent
444c580f7e
commit
de93653fe3
@ -117,7 +117,8 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
|
|||||||
block_t start_blkaddr, end_blkaddr;
|
block_t start_blkaddr, end_blkaddr;
|
||||||
|
|
||||||
BUG_ON(blk_addr == NEW_ADDR);
|
BUG_ON(blk_addr == NEW_ADDR);
|
||||||
fofs = start_bidx_of_node(ofs_of_node(dn->node_page)) + dn->ofs_in_node;
|
fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) +
|
||||||
|
dn->ofs_in_node;
|
||||||
|
|
||||||
/* Update the page address in the parent node */
|
/* Update the page address in the parent node */
|
||||||
__set_data_blkaddr(dn, blk_addr);
|
__set_data_blkaddr(dn, blk_addr);
|
||||||
@ -448,7 +449,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock,
|
|||||||
unsigned int end_offset;
|
unsigned int end_offset;
|
||||||
|
|
||||||
end_offset = IS_INODE(dn.node_page) ?
|
end_offset = IS_INODE(dn.node_page) ?
|
||||||
ADDRS_PER_INODE :
|
ADDRS_PER_INODE(F2FS_I(inode)) :
|
||||||
ADDRS_PER_BLOCK;
|
ADDRS_PER_BLOCK;
|
||||||
|
|
||||||
clear_buffer_new(bh_result);
|
clear_buffer_new(bh_result);
|
||||||
|
@ -300,15 +300,6 @@ struct f2fs_sm_info {
|
|||||||
unsigned int ovp_segments; /* # of overprovision segments */
|
unsigned int ovp_segments; /* # of overprovision segments */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* For directory operation
|
|
||||||
*/
|
|
||||||
#define NODE_DIR1_BLOCK (ADDRS_PER_INODE + 1)
|
|
||||||
#define NODE_DIR2_BLOCK (ADDRS_PER_INODE + 2)
|
|
||||||
#define NODE_IND1_BLOCK (ADDRS_PER_INODE + 3)
|
|
||||||
#define NODE_IND2_BLOCK (ADDRS_PER_INODE + 4)
|
|
||||||
#define NODE_DIND_BLOCK (ADDRS_PER_INODE + 5)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For superblock
|
* For superblock
|
||||||
*/
|
*/
|
||||||
@ -942,6 +933,13 @@ static inline void set_raw_inline(struct f2fs_inode_info *fi,
|
|||||||
ri->i_inline |= F2FS_INLINE_XATTR;
|
ri->i_inline |= F2FS_INLINE_XATTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int addrs_per_inode(struct f2fs_inode_info *fi)
|
||||||
|
{
|
||||||
|
if (is_inode_flag_set(fi, FI_INLINE_XATTR))
|
||||||
|
return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS;
|
||||||
|
return DEF_ADDRS_PER_INODE;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int f2fs_readonly(struct super_block *sb)
|
static inline int f2fs_readonly(struct super_block *sb)
|
||||||
{
|
{
|
||||||
return sb->s_flags & MS_RDONLY;
|
return sb->s_flags & MS_RDONLY;
|
||||||
@ -1108,7 +1106,7 @@ int do_write_data_page(struct page *);
|
|||||||
*/
|
*/
|
||||||
int start_gc_thread(struct f2fs_sb_info *);
|
int start_gc_thread(struct f2fs_sb_info *);
|
||||||
void stop_gc_thread(struct f2fs_sb_info *);
|
void stop_gc_thread(struct f2fs_sb_info *);
|
||||||
block_t start_bidx_of_node(unsigned int);
|
block_t start_bidx_of_node(unsigned int, struct f2fs_inode_info *);
|
||||||
int f2fs_gc(struct f2fs_sb_info *);
|
int f2fs_gc(struct f2fs_sb_info *);
|
||||||
void build_gc_manager(struct f2fs_sb_info *);
|
void build_gc_manager(struct f2fs_sb_info *);
|
||||||
int __init create_gc_caches(void);
|
int __init create_gc_caches(void);
|
||||||
|
@ -290,7 +290,7 @@ static int truncate_blocks(struct inode *inode, u64 from)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IS_INODE(dn.node_page))
|
if (IS_INODE(dn.node_page))
|
||||||
count = ADDRS_PER_INODE;
|
count = ADDRS_PER_INODE(F2FS_I(inode));
|
||||||
else
|
else
|
||||||
count = ADDRS_PER_BLOCK;
|
count = ADDRS_PER_BLOCK;
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
|
|||||||
* as indirect or double indirect node blocks, are given, it must be a caller's
|
* as indirect or double indirect node blocks, are given, it must be a caller's
|
||||||
* bug.
|
* bug.
|
||||||
*/
|
*/
|
||||||
block_t start_bidx_of_node(unsigned int node_ofs)
|
block_t start_bidx_of_node(unsigned int node_ofs, struct f2fs_inode_info *fi)
|
||||||
{
|
{
|
||||||
unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
|
unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
|
||||||
unsigned int bidx;
|
unsigned int bidx;
|
||||||
@ -478,7 +478,7 @@ block_t start_bidx_of_node(unsigned int node_ofs)
|
|||||||
int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
|
int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
|
||||||
bidx = node_ofs - 5 - dec;
|
bidx = node_ofs - 5 - dec;
|
||||||
}
|
}
|
||||||
return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE;
|
return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
||||||
@ -586,7 +586,6 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_bidx = start_bidx_of_node(nofs);
|
|
||||||
ofs_in_node = le16_to_cpu(entry->ofs_in_node);
|
ofs_in_node = le16_to_cpu(entry->ofs_in_node);
|
||||||
|
|
||||||
if (phase == 2) {
|
if (phase == 2) {
|
||||||
@ -594,6 +593,8 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
|||||||
if (IS_ERR(inode))
|
if (IS_ERR(inode))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
start_bidx = start_bidx_of_node(nofs, F2FS_I(inode));
|
||||||
|
|
||||||
data_page = find_data_page(inode,
|
data_page = find_data_page(inode,
|
||||||
start_bidx + ofs_in_node, false);
|
start_bidx + ofs_in_node, false);
|
||||||
if (IS_ERR(data_page))
|
if (IS_ERR(data_page))
|
||||||
@ -604,6 +605,8 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
|||||||
} else {
|
} else {
|
||||||
inode = find_gc_inode(dni.ino, ilist);
|
inode = find_gc_inode(dni.ino, ilist);
|
||||||
if (inode) {
|
if (inode) {
|
||||||
|
start_bidx = start_bidx_of_node(nofs,
|
||||||
|
F2FS_I(inode));
|
||||||
data_page = get_lock_data_page(inode,
|
data_page = get_lock_data_page(inode,
|
||||||
start_bidx + ofs_in_node);
|
start_bidx + ofs_in_node);
|
||||||
if (IS_ERR(data_page))
|
if (IS_ERR(data_page))
|
||||||
|
@ -315,9 +315,10 @@ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
|
|||||||
* The maximum depth is four.
|
* The maximum depth is four.
|
||||||
* Offset[0] will have raw inode offset.
|
* Offset[0] will have raw inode offset.
|
||||||
*/
|
*/
|
||||||
static int get_node_path(long block, int offset[4], unsigned int noffset[4])
|
static int get_node_path(struct f2fs_inode_info *fi, long block,
|
||||||
|
int offset[4], unsigned int noffset[4])
|
||||||
{
|
{
|
||||||
const long direct_index = ADDRS_PER_INODE;
|
const long direct_index = ADDRS_PER_INODE(fi);
|
||||||
const long direct_blks = ADDRS_PER_BLOCK;
|
const long direct_blks = ADDRS_PER_BLOCK;
|
||||||
const long dptrs_per_blk = NIDS_PER_BLOCK;
|
const long dptrs_per_blk = NIDS_PER_BLOCK;
|
||||||
const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
|
const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
|
||||||
@ -405,7 +406,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
|
|||||||
int level, i;
|
int level, i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
level = get_node_path(index, offset, noffset);
|
level = get_node_path(F2FS_I(dn->inode), index, offset, noffset);
|
||||||
|
|
||||||
nids[0] = dn->inode->i_ino;
|
nids[0] = dn->inode->i_ino;
|
||||||
npage[0] = dn->inode_page;
|
npage[0] = dn->inode_page;
|
||||||
@ -687,7 +688,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from)
|
|||||||
|
|
||||||
trace_f2fs_truncate_inode_blocks_enter(inode, from);
|
trace_f2fs_truncate_inode_blocks_enter(inode, from);
|
||||||
|
|
||||||
level = get_node_path(from, offset, noffset);
|
level = get_node_path(F2FS_I(inode), from, offset, noffset);
|
||||||
restart:
|
restart:
|
||||||
page = get_node_page(sbi, inode->i_ino);
|
page = get_node_page(sbi, inode->i_ino);
|
||||||
if (IS_ERR(page)) {
|
if (IS_ERR(page)) {
|
||||||
|
@ -213,6 +213,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
|
|||||||
void *kaddr;
|
void *kaddr;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct page *node_page;
|
struct page *node_page;
|
||||||
|
unsigned int offset;
|
||||||
block_t bidx;
|
block_t bidx;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -257,8 +258,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
|
|||||||
node_page = get_node_page(sbi, nid);
|
node_page = get_node_page(sbi, nid);
|
||||||
if (IS_ERR(node_page))
|
if (IS_ERR(node_page))
|
||||||
return PTR_ERR(node_page);
|
return PTR_ERR(node_page);
|
||||||
bidx = start_bidx_of_node(ofs_of_node(node_page)) +
|
|
||||||
le16_to_cpu(sum.ofs_in_node);
|
offset = ofs_of_node(node_page);
|
||||||
ino = ino_of_node(node_page);
|
ino = ino_of_node(node_page);
|
||||||
f2fs_put_page(node_page, 1);
|
f2fs_put_page(node_page, 1);
|
||||||
|
|
||||||
@ -267,6 +268,9 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
|
|||||||
if (IS_ERR(inode))
|
if (IS_ERR(inode))
|
||||||
return PTR_ERR(inode);
|
return PTR_ERR(inode);
|
||||||
|
|
||||||
|
bidx = start_bidx_of_node(offset, F2FS_I(inode)) +
|
||||||
|
le16_to_cpu(sum.ofs_in_node);
|
||||||
|
|
||||||
truncate_hole(inode, bidx, bidx + 1);
|
truncate_hole(inode, bidx, bidx + 1);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
return 0;
|
return 0;
|
||||||
@ -275,6 +279,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
|
|||||||
static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
|
static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
|
||||||
struct page *page, block_t blkaddr)
|
struct page *page, block_t blkaddr)
|
||||||
{
|
{
|
||||||
|
struct f2fs_inode_info *fi = F2FS_I(inode);
|
||||||
unsigned int start, end;
|
unsigned int start, end;
|
||||||
struct dnode_of_data dn;
|
struct dnode_of_data dn;
|
||||||
struct f2fs_summary sum;
|
struct f2fs_summary sum;
|
||||||
@ -282,9 +287,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
|
|||||||
int err = 0, recovered = 0;
|
int err = 0, recovered = 0;
|
||||||
int ilock;
|
int ilock;
|
||||||
|
|
||||||
start = start_bidx_of_node(ofs_of_node(page));
|
start = start_bidx_of_node(ofs_of_node(page), fi);
|
||||||
if (IS_INODE(page))
|
if (IS_INODE(page))
|
||||||
end = start + ADDRS_PER_INODE;
|
end = start + ADDRS_PER_INODE(fi);
|
||||||
else
|
else
|
||||||
end = start + ADDRS_PER_BLOCK;
|
end = start + ADDRS_PER_BLOCK;
|
||||||
|
|
||||||
|
@ -618,7 +618,7 @@ static const struct export_operations f2fs_export_ops = {
|
|||||||
|
|
||||||
static loff_t max_file_size(unsigned bits)
|
static loff_t max_file_size(unsigned bits)
|
||||||
{
|
{
|
||||||
loff_t result = ADDRS_PER_INODE;
|
loff_t result = (DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS);
|
||||||
loff_t leaf_count = ADDRS_PER_BLOCK;
|
loff_t leaf_count = ADDRS_PER_BLOCK;
|
||||||
|
|
||||||
/* two direct node blocks */
|
/* two direct node blocks */
|
||||||
|
@ -140,9 +140,17 @@ struct f2fs_extent {
|
|||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define F2FS_NAME_LEN 255
|
#define F2FS_NAME_LEN 255
|
||||||
#define ADDRS_PER_INODE 923 /* Address Pointers in an Inode */
|
#define F2FS_INLINE_XATTR_ADDRS 0 /* 0 bytes for inline xattrs */
|
||||||
#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */
|
#define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode */
|
||||||
#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */
|
#define ADDRS_PER_INODE(fi) addrs_per_inode(fi)
|
||||||
|
#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */
|
||||||
|
#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */
|
||||||
|
|
||||||
|
#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1)
|
||||||
|
#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2)
|
||||||
|
#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3)
|
||||||
|
#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4)
|
||||||
|
#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5)
|
||||||
|
|
||||||
#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */
|
#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */
|
||||||
|
|
||||||
@ -172,7 +180,7 @@ struct f2fs_inode {
|
|||||||
|
|
||||||
struct f2fs_extent i_ext; /* caching a largest extent */
|
struct f2fs_extent i_ext; /* caching a largest extent */
|
||||||
|
|
||||||
__le32 i_addr[ADDRS_PER_INODE]; /* Pointers to data blocks */
|
__le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */
|
||||||
|
|
||||||
__le32 i_nid[5]; /* direct(2), indirect(2),
|
__le32 i_nid[5]; /* direct(2), indirect(2),
|
||||||
double_indirect(1) node id */
|
double_indirect(1) node id */
|
||||||
|
Loading…
Reference in New Issue
Block a user