diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-08-12 08:08:03 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-08-26 07:15:01 -0400 |
commit | de93653fe31fc9439971296842dcd0280f8ab5f4 (patch) | |
tree | d4db3c55eead49b0a4f3c9e56eca372f9142d6cd | |
parent | 444c580f7e9ad29927a5d5269d576bd7cdccebb8 (diff) |
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>
-rw-r--r-- | fs/f2fs/data.c | 5 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 18 | ||||
-rw-r--r-- | fs/f2fs/file.c | 2 | ||||
-rw-r--r-- | fs/f2fs/gc.c | 9 | ||||
-rw-r--r-- | fs/f2fs/node.c | 9 | ||||
-rw-r--r-- | fs/f2fs/recovery.c | 13 | ||||
-rw-r--r-- | fs/f2fs/super.c | 2 | ||||
-rw-r--r-- | include/linux/f2fs_fs.h | 16 |
8 files changed, 45 insertions, 29 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6b328de41728..941f9b9ca3a5 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -117,7 +117,8 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn) | |||
117 | block_t start_blkaddr, end_blkaddr; | 117 | block_t start_blkaddr, end_blkaddr; |
118 | 118 | ||
119 | BUG_ON(blk_addr == NEW_ADDR); | 119 | BUG_ON(blk_addr == NEW_ADDR); |
120 | fofs = start_bidx_of_node(ofs_of_node(dn->node_page)) + dn->ofs_in_node; | 120 | fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) + |
121 | dn->ofs_in_node; | ||
121 | 122 | ||
122 | /* Update the page address in the parent node */ | 123 | /* Update the page address in the parent node */ |
123 | __set_data_blkaddr(dn, blk_addr); | 124 | __set_data_blkaddr(dn, blk_addr); |
@@ -448,7 +449,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock, | |||
448 | unsigned int end_offset; | 449 | unsigned int end_offset; |
449 | 450 | ||
450 | end_offset = IS_INODE(dn.node_page) ? | 451 | end_offset = IS_INODE(dn.node_page) ? |
451 | ADDRS_PER_INODE : | 452 | ADDRS_PER_INODE(F2FS_I(inode)) : |
452 | ADDRS_PER_BLOCK; | 453 | ADDRS_PER_BLOCK; |
453 | 454 | ||
454 | clear_buffer_new(bh_result); | 455 | clear_buffer_new(bh_result); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b82f14199921..0343759ceb4c 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -301,15 +301,6 @@ struct f2fs_sm_info { | |||
301 | }; | 301 | }; |
302 | 302 | ||
303 | /* | 303 | /* |
304 | * For directory operation | ||
305 | */ | ||
306 | #define NODE_DIR1_BLOCK (ADDRS_PER_INODE + 1) | ||
307 | #define NODE_DIR2_BLOCK (ADDRS_PER_INODE + 2) | ||
308 | #define NODE_IND1_BLOCK (ADDRS_PER_INODE + 3) | ||
309 | #define NODE_IND2_BLOCK (ADDRS_PER_INODE + 4) | ||
310 | #define NODE_DIND_BLOCK (ADDRS_PER_INODE + 5) | ||
311 | |||
312 | /* | ||
313 | * For superblock | 304 | * For superblock |
314 | */ | 305 | */ |
315 | /* | 306 | /* |
@@ -942,6 +933,13 @@ static inline void set_raw_inline(struct f2fs_inode_info *fi, | |||
942 | ri->i_inline |= F2FS_INLINE_XATTR; | 933 | ri->i_inline |= F2FS_INLINE_XATTR; |
943 | } | 934 | } |
944 | 935 | ||
936 | static inline unsigned int addrs_per_inode(struct f2fs_inode_info *fi) | ||
937 | { | ||
938 | if (is_inode_flag_set(fi, FI_INLINE_XATTR)) | ||
939 | return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS; | ||
940 | return DEF_ADDRS_PER_INODE; | ||
941 | } | ||
942 | |||
945 | static inline int f2fs_readonly(struct super_block *sb) | 943 | static inline int f2fs_readonly(struct super_block *sb) |
946 | { | 944 | { |
947 | return sb->s_flags & MS_RDONLY; | 945 | return sb->s_flags & MS_RDONLY; |
@@ -1108,7 +1106,7 @@ int do_write_data_page(struct page *); | |||
1108 | */ | 1106 | */ |
1109 | int start_gc_thread(struct f2fs_sb_info *); | 1107 | int start_gc_thread(struct f2fs_sb_info *); |
1110 | void stop_gc_thread(struct f2fs_sb_info *); | 1108 | void stop_gc_thread(struct f2fs_sb_info *); |
1111 | block_t start_bidx_of_node(unsigned int); | 1109 | block_t start_bidx_of_node(unsigned int, struct f2fs_inode_info *); |
1112 | int f2fs_gc(struct f2fs_sb_info *); | 1110 | int f2fs_gc(struct f2fs_sb_info *); |
1113 | void build_gc_manager(struct f2fs_sb_info *); | 1111 | void build_gc_manager(struct f2fs_sb_info *); |
1114 | int __init create_gc_caches(void); | 1112 | int __init create_gc_caches(void); |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index bd4184e35525..02c906971cc6 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -290,7 +290,7 @@ static int truncate_blocks(struct inode *inode, u64 from) | |||
290 | } | 290 | } |
291 | 291 | ||
292 | if (IS_INODE(dn.node_page)) | 292 | if (IS_INODE(dn.node_page)) |
293 | count = ADDRS_PER_INODE; | 293 | count = ADDRS_PER_INODE(F2FS_I(inode)); |
294 | else | 294 | else |
295 | count = ADDRS_PER_BLOCK; | 295 | count = ADDRS_PER_BLOCK; |
296 | 296 | ||
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index e6b3ffd5ff6a..eb89037e3312 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -461,7 +461,7 @@ next_step: | |||
461 | * as indirect or double indirect node blocks, are given, it must be a caller's | 461 | * as indirect or double indirect node blocks, are given, it must be a caller's |
462 | * bug. | 462 | * bug. |
463 | */ | 463 | */ |
464 | block_t start_bidx_of_node(unsigned int node_ofs) | 464 | block_t start_bidx_of_node(unsigned int node_ofs, struct f2fs_inode_info *fi) |
465 | { | 465 | { |
466 | unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; | 466 | unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; |
467 | unsigned int bidx; | 467 | unsigned int bidx; |
@@ -478,7 +478,7 @@ block_t start_bidx_of_node(unsigned int node_ofs) | |||
478 | int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); | 478 | int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); |
479 | bidx = node_ofs - 5 - dec; | 479 | bidx = node_ofs - 5 - dec; |
480 | } | 480 | } |
481 | return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE; | 481 | return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(fi); |
482 | } | 482 | } |
483 | 483 | ||
484 | static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, | 484 | static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, |
@@ -586,7 +586,6 @@ next_step: | |||
586 | continue; | 586 | continue; |
587 | } | 587 | } |
588 | 588 | ||
589 | start_bidx = start_bidx_of_node(nofs); | ||
590 | ofs_in_node = le16_to_cpu(entry->ofs_in_node); | 589 | ofs_in_node = le16_to_cpu(entry->ofs_in_node); |
591 | 590 | ||
592 | if (phase == 2) { | 591 | if (phase == 2) { |
@@ -594,6 +593,8 @@ next_step: | |||
594 | if (IS_ERR(inode)) | 593 | if (IS_ERR(inode)) |
595 | continue; | 594 | continue; |
596 | 595 | ||
596 | start_bidx = start_bidx_of_node(nofs, F2FS_I(inode)); | ||
597 | |||
597 | data_page = find_data_page(inode, | 598 | data_page = find_data_page(inode, |
598 | start_bidx + ofs_in_node, false); | 599 | start_bidx + ofs_in_node, false); |
599 | if (IS_ERR(data_page)) | 600 | if (IS_ERR(data_page)) |
@@ -604,6 +605,8 @@ next_step: | |||
604 | } else { | 605 | } else { |
605 | inode = find_gc_inode(dni.ino, ilist); | 606 | inode = find_gc_inode(dni.ino, ilist); |
606 | if (inode) { | 607 | if (inode) { |
608 | start_bidx = start_bidx_of_node(nofs, | ||
609 | F2FS_I(inode)); | ||
607 | data_page = get_lock_data_page(inode, | 610 | data_page = get_lock_data_page(inode, |
608 | start_bidx + ofs_in_node); | 611 | start_bidx + ofs_in_node); |
609 | if (IS_ERR(data_page)) | 612 | if (IS_ERR(data_page)) |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 818ff368de81..f0e733b21b2a 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -315,9 +315,10 @@ cache: | |||
315 | * The maximum depth is four. | 315 | * The maximum depth is four. |
316 | * Offset[0] will have raw inode offset. | 316 | * Offset[0] will have raw inode offset. |
317 | */ | 317 | */ |
318 | static int get_node_path(long block, int offset[4], unsigned int noffset[4]) | 318 | static int get_node_path(struct f2fs_inode_info *fi, long block, |
319 | int offset[4], unsigned int noffset[4]) | ||
319 | { | 320 | { |
320 | const long direct_index = ADDRS_PER_INODE; | 321 | const long direct_index = ADDRS_PER_INODE(fi); |
321 | const long direct_blks = ADDRS_PER_BLOCK; | 322 | const long direct_blks = ADDRS_PER_BLOCK; |
322 | const long dptrs_per_blk = NIDS_PER_BLOCK; | 323 | const long dptrs_per_blk = NIDS_PER_BLOCK; |
323 | const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; | 324 | 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) | |||
405 | int level, i; | 406 | int level, i; |
406 | int err = 0; | 407 | int err = 0; |
407 | 408 | ||
408 | level = get_node_path(index, offset, noffset); | 409 | level = get_node_path(F2FS_I(dn->inode), index, offset, noffset); |
409 | 410 | ||
410 | nids[0] = dn->inode->i_ino; | 411 | nids[0] = dn->inode->i_ino; |
411 | npage[0] = dn->inode_page; | 412 | npage[0] = dn->inode_page; |
@@ -687,7 +688,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from) | |||
687 | 688 | ||
688 | trace_f2fs_truncate_inode_blocks_enter(inode, from); | 689 | trace_f2fs_truncate_inode_blocks_enter(inode, from); |
689 | 690 | ||
690 | level = get_node_path(from, offset, noffset); | 691 | level = get_node_path(F2FS_I(inode), from, offset, noffset); |
691 | restart: | 692 | restart: |
692 | page = get_node_page(sbi, inode->i_ino); | 693 | page = get_node_page(sbi, inode->i_ino); |
693 | if (IS_ERR(page)) { | 694 | if (IS_ERR(page)) { |
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index fa493bb64167..51ef5eec33d7 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -213,6 +213,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
213 | void *kaddr; | 213 | void *kaddr; |
214 | struct inode *inode; | 214 | struct inode *inode; |
215 | struct page *node_page; | 215 | struct page *node_page; |
216 | unsigned int offset; | ||
216 | block_t bidx; | 217 | block_t bidx; |
217 | int i; | 218 | int i; |
218 | 219 | ||
@@ -257,8 +258,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
257 | node_page = get_node_page(sbi, nid); | 258 | node_page = get_node_page(sbi, nid); |
258 | if (IS_ERR(node_page)) | 259 | if (IS_ERR(node_page)) |
259 | return PTR_ERR(node_page); | 260 | return PTR_ERR(node_page); |
260 | bidx = start_bidx_of_node(ofs_of_node(node_page)) + | 261 | |
261 | le16_to_cpu(sum.ofs_in_node); | 262 | offset = ofs_of_node(node_page); |
262 | ino = ino_of_node(node_page); | 263 | ino = ino_of_node(node_page); |
263 | f2fs_put_page(node_page, 1); | 264 | f2fs_put_page(node_page, 1); |
264 | 265 | ||
@@ -267,6 +268,9 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
267 | if (IS_ERR(inode)) | 268 | if (IS_ERR(inode)) |
268 | return PTR_ERR(inode); | 269 | return PTR_ERR(inode); |
269 | 270 | ||
271 | bidx = start_bidx_of_node(offset, F2FS_I(inode)) + | ||
272 | le16_to_cpu(sum.ofs_in_node); | ||
273 | |||
270 | truncate_hole(inode, bidx, bidx + 1); | 274 | truncate_hole(inode, bidx, bidx + 1); |
271 | iput(inode); | 275 | iput(inode); |
272 | return 0; | 276 | return 0; |
@@ -275,6 +279,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
275 | static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | 279 | static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, |
276 | struct page *page, block_t blkaddr) | 280 | struct page *page, block_t blkaddr) |
277 | { | 281 | { |
282 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
278 | unsigned int start, end; | 283 | unsigned int start, end; |
279 | struct dnode_of_data dn; | 284 | struct dnode_of_data dn; |
280 | struct f2fs_summary sum; | 285 | struct f2fs_summary sum; |
@@ -282,9 +287,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
282 | int err = 0, recovered = 0; | 287 | int err = 0, recovered = 0; |
283 | int ilock; | 288 | int ilock; |
284 | 289 | ||
285 | start = start_bidx_of_node(ofs_of_node(page)); | 290 | start = start_bidx_of_node(ofs_of_node(page), fi); |
286 | if (IS_INODE(page)) | 291 | if (IS_INODE(page)) |
287 | end = start + ADDRS_PER_INODE; | 292 | end = start + ADDRS_PER_INODE(fi); |
288 | else | 293 | else |
289 | end = start + ADDRS_PER_BLOCK; | 294 | end = start + ADDRS_PER_BLOCK; |
290 | 295 | ||
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 70ecf484e7e5..13d0a0fe49dd 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -618,7 +618,7 @@ static const struct export_operations f2fs_export_ops = { | |||
618 | 618 | ||
619 | static loff_t max_file_size(unsigned bits) | 619 | static loff_t max_file_size(unsigned bits) |
620 | { | 620 | { |
621 | loff_t result = ADDRS_PER_INODE; | 621 | loff_t result = (DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS); |
622 | loff_t leaf_count = ADDRS_PER_BLOCK; | 622 | loff_t leaf_count = ADDRS_PER_BLOCK; |
623 | 623 | ||
624 | /* two direct node blocks */ | 624 | /* two direct node blocks */ |
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 10ab11f8f99d..93e7020fb7a8 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h | |||
@@ -140,9 +140,17 @@ struct f2fs_extent { | |||
140 | } __packed; | 140 | } __packed; |
141 | 141 | ||
142 | #define F2FS_NAME_LEN 255 | 142 | #define F2FS_NAME_LEN 255 |
143 | #define ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ | 143 | #define F2FS_INLINE_XATTR_ADDRS 0 /* 0 bytes for inline xattrs */ |
144 | #define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ | 144 | #define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ |
145 | #define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ | 145 | #define ADDRS_PER_INODE(fi) addrs_per_inode(fi) |
146 | #define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ | ||
147 | #define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ | ||
148 | |||
149 | #define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) | ||
150 | #define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) | ||
151 | #define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3) | ||
152 | #define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4) | ||
153 | #define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5) | ||
146 | 154 | ||
147 | #define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ | 155 | #define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ |
148 | 156 | ||
@@ -172,7 +180,7 @@ struct f2fs_inode { | |||
172 | 180 | ||
173 | struct f2fs_extent i_ext; /* caching a largest extent */ | 181 | struct f2fs_extent i_ext; /* caching a largest extent */ |
174 | 182 | ||
175 | __le32 i_addr[ADDRS_PER_INODE]; /* Pointers to data blocks */ | 183 | __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ |
176 | 184 | ||
177 | __le32 i_nid[5]; /* direct(2), indirect(2), | 185 | __le32 i_nid[5]; /* direct(2), indirect(2), |
178 | double_indirect(1) node id */ | 186 | double_indirect(1) node id */ |