diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 12:04:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 12:04:34 -0400 |
commit | eb97a784f02991cc3736d787511e788f32f0627f (patch) | |
tree | b81bd078b145b9af6339269c8f77421e98894e03 | |
parent | 2e032852245b3dcfe5461d7353e34eb6da095ccf (diff) | |
parent | a26b7c8a0149ce1e3b6a10f2801aada6e447e4e7 (diff) |
Merge tag 'for-f2fs-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim:
"This patch-set includes the following major enhancement patches:
- support inline xattrs
- add sysfs support to control GCs explicitly
- add proc entry to show the current segment usage information
- improve the GC/SSR performance
The other bug fixes are as follows:
- avoid the overflow on status calculation
- fix some error handling routines
- fix inconsistent xattr states after power-off-recovery
- fix incorrect xattr node offset definition
- fix deadlock condition in fsync
- fix the fdatasync routine for power-off-recovery"
* tag 'for-f2fs-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (40 commits)
f2fs: optimize gc for better performance
f2fs: merge more bios of node block writes
f2fs: avoid an overflow during utilization calculation
f2fs: trigger GC when there are prefree segments
f2fs: use strncasecmp() simplify the string comparison
f2fs: fix omitting to update inode page
f2fs: support the inline xattrs
f2fs: add the truncate_xattr_node function
f2fs: introduce __find_xattr for readability
f2fs: reserve the xattr space dynamically
f2fs: add flags for inline xattrs
f2fs: fix error return code in init_f2fs_fs()
f2fs: fix wrong BUG_ON condition
f2fs: fix memory leak when init f2fs filesystem fail
f2fs: fix a compound statement label error
f2fs: avoid writing inode redundantly when creating a file
f2fs: alloc_page() doesn't return an ERR_PTR
f2fs: should cover i_xattr_nid with its xattr node page lock
f2fs: check the free space first in new_node_page
f2fs: clean up the needless end 'return' of void function
...
-rw-r--r-- | Documentation/ABI/testing/sysfs-fs-f2fs | 26 | ||||
-rw-r--r-- | Documentation/filesystems/f2fs.txt | 75 | ||||
-rw-r--r-- | fs/f2fs/checkpoint.c | 24 | ||||
-rw-r--r-- | fs/f2fs/data.c | 28 | ||||
-rw-r--r-- | fs/f2fs/debug.c | 34 | ||||
-rw-r--r-- | fs/f2fs/dir.c | 19 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 106 | ||||
-rw-r--r-- | fs/f2fs/file.c | 25 | ||||
-rw-r--r-- | fs/f2fs/gc.c | 58 | ||||
-rw-r--r-- | fs/f2fs/gc.h | 38 | ||||
-rw-r--r-- | fs/f2fs/inode.c | 15 | ||||
-rw-r--r-- | fs/f2fs/namei.c | 33 | ||||
-rw-r--r-- | fs/f2fs/node.c | 100 | ||||
-rw-r--r-- | fs/f2fs/node.h | 44 | ||||
-rw-r--r-- | fs/f2fs/recovery.c | 29 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 41 | ||||
-rw-r--r-- | fs/f2fs/segment.h | 6 | ||||
-rw-r--r-- | fs/f2fs/super.c | 209 | ||||
-rw-r--r-- | fs/f2fs/xattr.c | 289 | ||||
-rw-r--r-- | fs/f2fs/xattr.h | 15 | ||||
-rw-r--r-- | include/linux/f2fs_fs.h | 20 |
21 files changed, 890 insertions, 344 deletions
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs new file mode 100644 index 000000000000..31942efcaf0e --- /dev/null +++ b/Documentation/ABI/testing/sysfs-fs-f2fs | |||
@@ -0,0 +1,26 @@ | |||
1 | What: /sys/fs/f2fs/<disk>/gc_max_sleep_time | ||
2 | Date: July 2013 | ||
3 | Contact: "Namjae Jeon" <namjae.jeon@samsung.com> | ||
4 | Description: | ||
5 | Controls the maximun sleep time for gc_thread. Time | ||
6 | is in milliseconds. | ||
7 | |||
8 | What: /sys/fs/f2fs/<disk>/gc_min_sleep_time | ||
9 | Date: July 2013 | ||
10 | Contact: "Namjae Jeon" <namjae.jeon@samsung.com> | ||
11 | Description: | ||
12 | Controls the minimum sleep time for gc_thread. Time | ||
13 | is in milliseconds. | ||
14 | |||
15 | What: /sys/fs/f2fs/<disk>/gc_no_gc_sleep_time | ||
16 | Date: July 2013 | ||
17 | Contact: "Namjae Jeon" <namjae.jeon@samsung.com> | ||
18 | Description: | ||
19 | Controls the default sleep time for gc_thread. Time | ||
20 | is in milliseconds. | ||
21 | |||
22 | What: /sys/fs/f2fs/<disk>/gc_idle | ||
23 | Date: July 2013 | ||
24 | Contact: "Namjae Jeon" <namjae.jeon@samsung.com> | ||
25 | Description: | ||
26 | Controls the victim selection policy for garbage collection. | ||
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index b91e2f26b672..3cd27bed6349 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt | |||
@@ -18,8 +18,8 @@ according to its internal geometry or flash memory management scheme, namely FTL | |||
18 | F2FS and its tools support various parameters not only for configuring on-disk | 18 | F2FS and its tools support various parameters not only for configuring on-disk |
19 | layout, but also for selecting allocation and cleaning algorithms. | 19 | layout, but also for selecting allocation and cleaning algorithms. |
20 | 20 | ||
21 | The file system formatting tool, "mkfs.f2fs", is available from the following | 21 | The following git tree provides the file system formatting tool (mkfs.f2fs), |
22 | git tree: | 22 | a consistency checking tool (fsck.f2fs), and a debugging tool (dump.f2fs). |
23 | >> git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git | 23 | >> git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git |
24 | 24 | ||
25 | For reporting bugs and sending patches, please use the following mailing list: | 25 | For reporting bugs and sending patches, please use the following mailing list: |
@@ -133,6 +133,38 @@ f2fs. Each file shows the whole f2fs information. | |||
133 | - current memory footprint consumed by f2fs. | 133 | - current memory footprint consumed by f2fs. |
134 | 134 | ||
135 | ================================================================================ | 135 | ================================================================================ |
136 | SYSFS ENTRIES | ||
137 | ================================================================================ | ||
138 | |||
139 | Information about mounted f2f2 file systems can be found in | ||
140 | /sys/fs/f2fs. Each mounted filesystem will have a directory in | ||
141 | /sys/fs/f2fs based on its device name (i.e., /sys/fs/f2fs/sda). | ||
142 | The files in each per-device directory are shown in table below. | ||
143 | |||
144 | Files in /sys/fs/f2fs/<devname> | ||
145 | (see also Documentation/ABI/testing/sysfs-fs-f2fs) | ||
146 | .............................................................................. | ||
147 | File Content | ||
148 | |||
149 | gc_max_sleep_time This tuning parameter controls the maximum sleep | ||
150 | time for the garbage collection thread. Time is | ||
151 | in milliseconds. | ||
152 | |||
153 | gc_min_sleep_time This tuning parameter controls the minimum sleep | ||
154 | time for the garbage collection thread. Time is | ||
155 | in milliseconds. | ||
156 | |||
157 | gc_no_gc_sleep_time This tuning parameter controls the default sleep | ||
158 | time for the garbage collection thread. Time is | ||
159 | in milliseconds. | ||
160 | |||
161 | gc_idle This parameter controls the selection of victim | ||
162 | policy for garbage collection. Setting gc_idle = 0 | ||
163 | (default) will disable this option. Setting | ||
164 | gc_idle = 1 will select the Cost Benefit approach | ||
165 | & setting gc_idle = 2 will select the greedy aproach. | ||
166 | |||
167 | ================================================================================ | ||
136 | USAGE | 168 | USAGE |
137 | ================================================================================ | 169 | ================================================================================ |
138 | 170 | ||
@@ -149,8 +181,12 @@ USAGE | |||
149 | # mkfs.f2fs -l label /dev/block_device | 181 | # mkfs.f2fs -l label /dev/block_device |
150 | # mount -t f2fs /dev/block_device /mnt/f2fs | 182 | # mount -t f2fs /dev/block_device /mnt/f2fs |
151 | 183 | ||
152 | Format options | 184 | mkfs.f2fs |
153 | -------------- | 185 | --------- |
186 | The mkfs.f2fs is for the use of formatting a partition as the f2fs filesystem, | ||
187 | which builds a basic on-disk layout. | ||
188 | |||
189 | The options consist of: | ||
154 | -l [label] : Give a volume label, up to 512 unicode name. | 190 | -l [label] : Give a volume label, up to 512 unicode name. |
155 | -a [0 or 1] : Split start location of each area for heap-based allocation. | 191 | -a [0 or 1] : Split start location of each area for heap-based allocation. |
156 | 1 is set by default, which performs this. | 192 | 1 is set by default, which performs this. |
@@ -164,6 +200,37 @@ Format options | |||
164 | -t [0 or 1] : Disable discard command or not. | 200 | -t [0 or 1] : Disable discard command or not. |
165 | 1 is set by default, which conducts discard. | 201 | 1 is set by default, which conducts discard. |
166 | 202 | ||
203 | fsck.f2fs | ||
204 | --------- | ||
205 | The fsck.f2fs is a tool to check the consistency of an f2fs-formatted | ||
206 | partition, which examines whether the filesystem metadata and user-made data | ||
207 | are cross-referenced correctly or not. | ||
208 | Note that, initial version of the tool does not fix any inconsistency. | ||
209 | |||
210 | The options consist of: | ||
211 | -d debug level [default:0] | ||
212 | |||
213 | dump.f2fs | ||
214 | --------- | ||
215 | The dump.f2fs shows the information of specific inode and dumps SSA and SIT to | ||
216 | file. Each file is dump_ssa and dump_sit. | ||
217 | |||
218 | The dump.f2fs is used to debug on-disk data structures of the f2fs filesystem. | ||
219 | It shows on-disk inode information reconized by a given inode number, and is | ||
220 | able to dump all the SSA and SIT entries into predefined files, ./dump_ssa and | ||
221 | ./dump_sit respectively. | ||
222 | |||
223 | The options consist of: | ||
224 | -d debug level [default:0] | ||
225 | -i inode no (hex) | ||
226 | -s [SIT dump segno from #1~#2 (decimal), for all 0~-1] | ||
227 | -a [SSA dump segno from #1~#2 (decimal), for all 0~-1] | ||
228 | |||
229 | Examples: | ||
230 | # dump.f2fs -i [ino] /dev/sdx | ||
231 | # dump.f2fs -s 0~-1 /dev/sdx (SIT dump) | ||
232 | # dump.f2fs -a 0~-1 /dev/sdx (SSA dump) | ||
233 | |||
167 | ================================================================================ | 234 | ================================================================================ |
168 | DESIGN | 235 | DESIGN |
169 | ================================================================================ | 236 | ================================================================================ |
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 66a6b85a51d8..bb312201ca95 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -182,7 +182,7 @@ const struct address_space_operations f2fs_meta_aops = { | |||
182 | .set_page_dirty = f2fs_set_meta_page_dirty, | 182 | .set_page_dirty = f2fs_set_meta_page_dirty, |
183 | }; | 183 | }; |
184 | 184 | ||
185 | int check_orphan_space(struct f2fs_sb_info *sbi) | 185 | int acquire_orphan_inode(struct f2fs_sb_info *sbi) |
186 | { | 186 | { |
187 | unsigned int max_orphans; | 187 | unsigned int max_orphans; |
188 | int err = 0; | 188 | int err = 0; |
@@ -197,10 +197,19 @@ int check_orphan_space(struct f2fs_sb_info *sbi) | |||
197 | mutex_lock(&sbi->orphan_inode_mutex); | 197 | mutex_lock(&sbi->orphan_inode_mutex); |
198 | if (sbi->n_orphans >= max_orphans) | 198 | if (sbi->n_orphans >= max_orphans) |
199 | err = -ENOSPC; | 199 | err = -ENOSPC; |
200 | else | ||
201 | sbi->n_orphans++; | ||
200 | mutex_unlock(&sbi->orphan_inode_mutex); | 202 | mutex_unlock(&sbi->orphan_inode_mutex); |
201 | return err; | 203 | return err; |
202 | } | 204 | } |
203 | 205 | ||
206 | void release_orphan_inode(struct f2fs_sb_info *sbi) | ||
207 | { | ||
208 | mutex_lock(&sbi->orphan_inode_mutex); | ||
209 | sbi->n_orphans--; | ||
210 | mutex_unlock(&sbi->orphan_inode_mutex); | ||
211 | } | ||
212 | |||
204 | void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 213 | void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
205 | { | 214 | { |
206 | struct list_head *head, *this; | 215 | struct list_head *head, *this; |
@@ -229,21 +238,18 @@ retry: | |||
229 | list_add(&new->list, this->prev); | 238 | list_add(&new->list, this->prev); |
230 | else | 239 | else |
231 | list_add_tail(&new->list, head); | 240 | list_add_tail(&new->list, head); |
232 | |||
233 | sbi->n_orphans++; | ||
234 | out: | 241 | out: |
235 | mutex_unlock(&sbi->orphan_inode_mutex); | 242 | mutex_unlock(&sbi->orphan_inode_mutex); |
236 | } | 243 | } |
237 | 244 | ||
238 | void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 245 | void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
239 | { | 246 | { |
240 | struct list_head *this, *next, *head; | 247 | struct list_head *head; |
241 | struct orphan_inode_entry *orphan; | 248 | struct orphan_inode_entry *orphan; |
242 | 249 | ||
243 | mutex_lock(&sbi->orphan_inode_mutex); | 250 | mutex_lock(&sbi->orphan_inode_mutex); |
244 | head = &sbi->orphan_inode_list; | 251 | head = &sbi->orphan_inode_list; |
245 | list_for_each_safe(this, next, head) { | 252 | list_for_each_entry(orphan, head, list) { |
246 | orphan = list_entry(this, struct orphan_inode_entry, list); | ||
247 | if (orphan->ino == ino) { | 253 | if (orphan->ino == ino) { |
248 | list_del(&orphan->list); | 254 | list_del(&orphan->list); |
249 | kmem_cache_free(orphan_entry_slab, orphan); | 255 | kmem_cache_free(orphan_entry_slab, orphan); |
@@ -373,7 +379,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | |||
373 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) | 379 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) |
374 | goto invalid_cp1; | 380 | goto invalid_cp1; |
375 | 381 | ||
376 | pre_version = le64_to_cpu(cp_block->checkpoint_ver); | 382 | pre_version = cur_cp_version(cp_block); |
377 | 383 | ||
378 | /* Read the 2nd cp block in this CP pack */ | 384 | /* Read the 2nd cp block in this CP pack */ |
379 | cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1; | 385 | cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1; |
@@ -388,7 +394,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | |||
388 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) | 394 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) |
389 | goto invalid_cp2; | 395 | goto invalid_cp2; |
390 | 396 | ||
391 | cur_version = le64_to_cpu(cp_block->checkpoint_ver); | 397 | cur_version = cur_cp_version(cp_block); |
392 | 398 | ||
393 | if (cur_version == pre_version) { | 399 | if (cur_version == pre_version) { |
394 | *version = cur_version; | 400 | *version = cur_version; |
@@ -793,7 +799,7 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
793 | * Increase the version number so that | 799 | * Increase the version number so that |
794 | * SIT entries and seg summaries are written at correct place | 800 | * SIT entries and seg summaries are written at correct place |
795 | */ | 801 | */ |
796 | ckpt_ver = le64_to_cpu(ckpt->checkpoint_ver); | 802 | ckpt_ver = cur_cp_version(ckpt); |
797 | ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); | 803 | ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); |
798 | 804 | ||
799 | /* write cached NAT/SIT entries to NAT/SIT area */ | 805 | /* write cached NAT/SIT entries to NAT/SIT area */ |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 035f9a345cdf..941f9b9ca3a5 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -37,9 +37,9 @@ static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr) | |||
37 | struct page *node_page = dn->node_page; | 37 | struct page *node_page = dn->node_page; |
38 | unsigned int ofs_in_node = dn->ofs_in_node; | 38 | unsigned int ofs_in_node = dn->ofs_in_node; |
39 | 39 | ||
40 | wait_on_page_writeback(node_page); | 40 | f2fs_wait_on_page_writeback(node_page, NODE, false); |
41 | 41 | ||
42 | rn = (struct f2fs_node *)page_address(node_page); | 42 | rn = F2FS_NODE(node_page); |
43 | 43 | ||
44 | /* Get physical address of data block */ | 44 | /* Get physical address of data block */ |
45 | addr_array = blkaddr_in_node(rn); | 45 | addr_array = blkaddr_in_node(rn); |
@@ -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); |
@@ -176,7 +177,6 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn) | |||
176 | end_update: | 177 | end_update: |
177 | write_unlock(&fi->ext.ext_lock); | 178 | write_unlock(&fi->ext.ext_lock); |
178 | sync_inode_page(dn); | 179 | sync_inode_page(dn); |
179 | return; | ||
180 | } | 180 | } |
181 | 181 | ||
182 | struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync) | 182 | struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync) |
@@ -260,8 +260,17 @@ repeat: | |||
260 | if (PageUptodate(page)) | 260 | if (PageUptodate(page)) |
261 | return page; | 261 | return page; |
262 | 262 | ||
263 | BUG_ON(dn.data_blkaddr == NEW_ADDR); | 263 | /* |
264 | BUG_ON(dn.data_blkaddr == NULL_ADDR); | 264 | * A new dentry page is allocated but not able to be written, since its |
265 | * new inode page couldn't be allocated due to -ENOSPC. | ||
266 | * In such the case, its blkaddr can be remained as NEW_ADDR. | ||
267 | * see, f2fs_add_link -> get_new_data_page -> init_inode_metadata. | ||
268 | */ | ||
269 | if (dn.data_blkaddr == NEW_ADDR) { | ||
270 | zero_user_segment(page, 0, PAGE_CACHE_SIZE); | ||
271 | SetPageUptodate(page); | ||
272 | return page; | ||
273 | } | ||
265 | 274 | ||
266 | err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC); | 275 | err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC); |
267 | if (err) | 276 | if (err) |
@@ -365,7 +374,6 @@ static void read_end_io(struct bio *bio, int err) | |||
365 | } | 374 | } |
366 | unlock_page(page); | 375 | unlock_page(page); |
367 | } while (bvec >= bio->bi_io_vec); | 376 | } while (bvec >= bio->bi_io_vec); |
368 | kfree(bio->bi_private); | ||
369 | bio_put(bio); | 377 | bio_put(bio); |
370 | } | 378 | } |
371 | 379 | ||
@@ -391,7 +399,6 @@ int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page, | |||
391 | bio->bi_end_io = read_end_io; | 399 | bio->bi_end_io = read_end_io; |
392 | 400 | ||
393 | if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { | 401 | if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { |
394 | kfree(bio->bi_private); | ||
395 | bio_put(bio); | 402 | bio_put(bio); |
396 | up_read(&sbi->bio_sem); | 403 | up_read(&sbi->bio_sem); |
397 | f2fs_put_page(page, 1); | 404 | f2fs_put_page(page, 1); |
@@ -442,7 +449,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock, | |||
442 | unsigned int end_offset; | 449 | unsigned int end_offset; |
443 | 450 | ||
444 | end_offset = IS_INODE(dn.node_page) ? | 451 | end_offset = IS_INODE(dn.node_page) ? |
445 | ADDRS_PER_INODE : | 452 | ADDRS_PER_INODE(F2FS_I(inode)) : |
446 | ADDRS_PER_BLOCK; | 453 | ADDRS_PER_BLOCK; |
447 | 454 | ||
448 | clear_buffer_new(bh_result); | 455 | clear_buffer_new(bh_result); |
@@ -636,9 +643,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, | |||
636 | int err = 0; | 643 | int err = 0; |
637 | int ilock; | 644 | int ilock; |
638 | 645 | ||
639 | /* for nobh_write_end */ | ||
640 | *fsdata = NULL; | ||
641 | |||
642 | f2fs_balance_fs(sbi); | 646 | f2fs_balance_fs(sbi); |
643 | repeat: | 647 | repeat: |
644 | page = grab_cache_page_write_begin(mapping, index, flags); | 648 | page = grab_cache_page_write_begin(mapping, index, flags); |
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 0d6c6aafb235..a84b0a8e6854 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c | |||
@@ -29,7 +29,7 @@ static DEFINE_MUTEX(f2fs_stat_mutex); | |||
29 | 29 | ||
30 | static void update_general_status(struct f2fs_sb_info *sbi) | 30 | static void update_general_status(struct f2fs_sb_info *sbi) |
31 | { | 31 | { |
32 | struct f2fs_stat_info *si = sbi->stat_info; | 32 | struct f2fs_stat_info *si = F2FS_STAT(sbi); |
33 | int i; | 33 | int i; |
34 | 34 | ||
35 | /* valid check of the segment numbers */ | 35 | /* valid check of the segment numbers */ |
@@ -83,7 +83,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) | |||
83 | */ | 83 | */ |
84 | static void update_sit_info(struct f2fs_sb_info *sbi) | 84 | static void update_sit_info(struct f2fs_sb_info *sbi) |
85 | { | 85 | { |
86 | struct f2fs_stat_info *si = sbi->stat_info; | 86 | struct f2fs_stat_info *si = F2FS_STAT(sbi); |
87 | unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist; | 87 | unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist; |
88 | struct sit_info *sit_i = SIT_I(sbi); | 88 | struct sit_info *sit_i = SIT_I(sbi); |
89 | unsigned int segno, vblocks; | 89 | unsigned int segno, vblocks; |
@@ -118,7 +118,7 @@ static void update_sit_info(struct f2fs_sb_info *sbi) | |||
118 | */ | 118 | */ |
119 | static void update_mem_info(struct f2fs_sb_info *sbi) | 119 | static void update_mem_info(struct f2fs_sb_info *sbi) |
120 | { | 120 | { |
121 | struct f2fs_stat_info *si = sbi->stat_info; | 121 | struct f2fs_stat_info *si = F2FS_STAT(sbi); |
122 | unsigned npages; | 122 | unsigned npages; |
123 | 123 | ||
124 | if (si->base_mem) | 124 | if (si->base_mem) |
@@ -253,21 +253,21 @@ static int stat_show(struct seq_file *s, void *v) | |||
253 | si->nats, NM_WOUT_THRESHOLD); | 253 | si->nats, NM_WOUT_THRESHOLD); |
254 | seq_printf(s, " - SITs: %5d\n - free_nids: %5d\n", | 254 | seq_printf(s, " - SITs: %5d\n - free_nids: %5d\n", |
255 | si->sits, si->fnids); | 255 | si->sits, si->fnids); |
256 | seq_printf(s, "\nDistribution of User Blocks:"); | 256 | seq_puts(s, "\nDistribution of User Blocks:"); |
257 | seq_printf(s, " [ valid | invalid | free ]\n"); | 257 | seq_puts(s, " [ valid | invalid | free ]\n"); |
258 | seq_printf(s, " ["); | 258 | seq_puts(s, " ["); |
259 | 259 | ||
260 | for (j = 0; j < si->util_valid; j++) | 260 | for (j = 0; j < si->util_valid; j++) |
261 | seq_printf(s, "-"); | 261 | seq_putc(s, '-'); |
262 | seq_printf(s, "|"); | 262 | seq_putc(s, '|'); |
263 | 263 | ||
264 | for (j = 0; j < si->util_invalid; j++) | 264 | for (j = 0; j < si->util_invalid; j++) |
265 | seq_printf(s, "-"); | 265 | seq_putc(s, '-'); |
266 | seq_printf(s, "|"); | 266 | seq_putc(s, '|'); |
267 | 267 | ||
268 | for (j = 0; j < si->util_free; j++) | 268 | for (j = 0; j < si->util_free; j++) |
269 | seq_printf(s, "-"); | 269 | seq_putc(s, '-'); |
270 | seq_printf(s, "]\n\n"); | 270 | seq_puts(s, "]\n\n"); |
271 | seq_printf(s, "SSR: %u blocks in %u segments\n", | 271 | seq_printf(s, "SSR: %u blocks in %u segments\n", |
272 | si->block_count[SSR], si->segment_count[SSR]); | 272 | si->block_count[SSR], si->segment_count[SSR]); |
273 | seq_printf(s, "LFS: %u blocks in %u segments\n", | 273 | seq_printf(s, "LFS: %u blocks in %u segments\n", |
@@ -305,11 +305,10 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) | |||
305 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | 305 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); |
306 | struct f2fs_stat_info *si; | 306 | struct f2fs_stat_info *si; |
307 | 307 | ||
308 | sbi->stat_info = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL); | 308 | si = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL); |
309 | if (!sbi->stat_info) | 309 | if (!si) |
310 | return -ENOMEM; | 310 | return -ENOMEM; |
311 | 311 | ||
312 | si = sbi->stat_info; | ||
313 | si->all_area_segs = le32_to_cpu(raw_super->segment_count); | 312 | si->all_area_segs = le32_to_cpu(raw_super->segment_count); |
314 | si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); | 313 | si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); |
315 | si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); | 314 | si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); |
@@ -319,6 +318,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) | |||
319 | si->main_area_zones = si->main_area_sections / | 318 | si->main_area_zones = si->main_area_sections / |
320 | le32_to_cpu(raw_super->secs_per_zone); | 319 | le32_to_cpu(raw_super->secs_per_zone); |
321 | si->sbi = sbi; | 320 | si->sbi = sbi; |
321 | sbi->stat_info = si; | ||
322 | 322 | ||
323 | mutex_lock(&f2fs_stat_mutex); | 323 | mutex_lock(&f2fs_stat_mutex); |
324 | list_add_tail(&si->stat_list, &f2fs_stat_list); | 324 | list_add_tail(&si->stat_list, &f2fs_stat_list); |
@@ -329,13 +329,13 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) | |||
329 | 329 | ||
330 | void f2fs_destroy_stats(struct f2fs_sb_info *sbi) | 330 | void f2fs_destroy_stats(struct f2fs_sb_info *sbi) |
331 | { | 331 | { |
332 | struct f2fs_stat_info *si = sbi->stat_info; | 332 | struct f2fs_stat_info *si = F2FS_STAT(sbi); |
333 | 333 | ||
334 | mutex_lock(&f2fs_stat_mutex); | 334 | mutex_lock(&f2fs_stat_mutex); |
335 | list_del(&si->stat_list); | 335 | list_del(&si->stat_list); |
336 | mutex_unlock(&f2fs_stat_mutex); | 336 | mutex_unlock(&f2fs_stat_mutex); |
337 | 337 | ||
338 | kfree(sbi->stat_info); | 338 | kfree(si); |
339 | } | 339 | } |
340 | 340 | ||
341 | void __init f2fs_create_root_stats(void) | 341 | void __init f2fs_create_root_stats(void) |
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 62f0d5977c64..384c6daf9a89 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -270,12 +270,27 @@ static void init_dent_inode(const struct qstr *name, struct page *ipage) | |||
270 | struct f2fs_node *rn; | 270 | struct f2fs_node *rn; |
271 | 271 | ||
272 | /* copy name info. to this inode page */ | 272 | /* copy name info. to this inode page */ |
273 | rn = (struct f2fs_node *)page_address(ipage); | 273 | rn = F2FS_NODE(ipage); |
274 | rn->i.i_namelen = cpu_to_le32(name->len); | 274 | rn->i.i_namelen = cpu_to_le32(name->len); |
275 | memcpy(rn->i.i_name, name->name, name->len); | 275 | memcpy(rn->i.i_name, name->name, name->len); |
276 | set_page_dirty(ipage); | 276 | set_page_dirty(ipage); |
277 | } | 277 | } |
278 | 278 | ||
279 | int update_dent_inode(struct inode *inode, const struct qstr *name) | ||
280 | { | ||
281 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
282 | struct page *page; | ||
283 | |||
284 | page = get_node_page(sbi, inode->i_ino); | ||
285 | if (IS_ERR(page)) | ||
286 | return PTR_ERR(page); | ||
287 | |||
288 | init_dent_inode(name, page); | ||
289 | f2fs_put_page(page, 1); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
279 | static int make_empty_dir(struct inode *inode, | 294 | static int make_empty_dir(struct inode *inode, |
280 | struct inode *parent, struct page *page) | 295 | struct inode *parent, struct page *page) |
281 | { | 296 | { |
@@ -557,6 +572,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, | |||
557 | 572 | ||
558 | if (inode->i_nlink == 0) | 573 | if (inode->i_nlink == 0) |
559 | add_orphan_inode(sbi, inode->i_ino); | 574 | add_orphan_inode(sbi, inode->i_ino); |
575 | else | ||
576 | release_orphan_inode(sbi); | ||
560 | } | 577 | } |
561 | 578 | ||
562 | if (bit_pos == NR_DENTRY_IN_BLOCK) { | 579 | if (bit_pos == NR_DENTRY_IN_BLOCK) { |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 467d42d65c48..608f0df5b919 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/crc32.h> | 18 | #include <linux/crc32.h> |
19 | #include <linux/magic.h> | 19 | #include <linux/magic.h> |
20 | #include <linux/kobject.h> | ||
20 | 21 | ||
21 | /* | 22 | /* |
22 | * For mount options | 23 | * For mount options |
@@ -28,6 +29,7 @@ | |||
28 | #define F2FS_MOUNT_XATTR_USER 0x00000010 | 29 | #define F2FS_MOUNT_XATTR_USER 0x00000010 |
29 | #define F2FS_MOUNT_POSIX_ACL 0x00000020 | 30 | #define F2FS_MOUNT_POSIX_ACL 0x00000020 |
30 | #define F2FS_MOUNT_DISABLE_EXT_IDENTIFY 0x00000040 | 31 | #define F2FS_MOUNT_DISABLE_EXT_IDENTIFY 0x00000040 |
32 | #define F2FS_MOUNT_INLINE_XATTR 0x00000080 | ||
31 | 33 | ||
32 | #define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option) | 34 | #define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option) |
33 | #define set_opt(sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option) | 35 | #define set_opt(sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option) |
@@ -134,11 +136,13 @@ static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i) | |||
134 | /* | 136 | /* |
135 | * For INODE and NODE manager | 137 | * For INODE and NODE manager |
136 | */ | 138 | */ |
137 | #define XATTR_NODE_OFFSET (-1) /* | 139 | /* |
138 | * store xattrs to one node block per | 140 | * XATTR_NODE_OFFSET stores xattrs to one node block per file keeping -1 |
139 | * file keeping -1 as its node offset to | 141 | * as its node offset to distinguish from index node blocks. |
140 | * distinguish from index node blocks. | 142 | * But some bits are used to mark the node block. |
141 | */ | 143 | */ |
144 | #define XATTR_NODE_OFFSET ((((unsigned int)-1) << OFFSET_BIT_SHIFT) \ | ||
145 | >> OFFSET_BIT_SHIFT) | ||
142 | enum { | 146 | enum { |
143 | ALLOC_NODE, /* allocate a new node page if needed */ | 147 | ALLOC_NODE, /* allocate a new node page if needed */ |
144 | LOOKUP_NODE, /* look up a node without readahead */ | 148 | LOOKUP_NODE, /* look up a node without readahead */ |
@@ -178,6 +182,7 @@ struct f2fs_inode_info { | |||
178 | f2fs_hash_t chash; /* hash value of given file name */ | 182 | f2fs_hash_t chash; /* hash value of given file name */ |
179 | unsigned int clevel; /* maximum level of given file name */ | 183 | unsigned int clevel; /* maximum level of given file name */ |
180 | nid_t i_xattr_nid; /* node id that contains xattrs */ | 184 | nid_t i_xattr_nid; /* node id that contains xattrs */ |
185 | unsigned long long xattr_ver; /* cp version of xattr modification */ | ||
181 | struct extent_info ext; /* in-memory extent cache entry */ | 186 | struct extent_info ext; /* in-memory extent cache entry */ |
182 | }; | 187 | }; |
183 | 188 | ||
@@ -296,15 +301,6 @@ struct f2fs_sm_info { | |||
296 | }; | 301 | }; |
297 | 302 | ||
298 | /* | 303 | /* |
299 | * For directory operation | ||
300 | */ | ||
301 | #define NODE_DIR1_BLOCK (ADDRS_PER_INODE + 1) | ||
302 | #define NODE_DIR2_BLOCK (ADDRS_PER_INODE + 2) | ||
303 | #define NODE_IND1_BLOCK (ADDRS_PER_INODE + 3) | ||
304 | #define NODE_IND2_BLOCK (ADDRS_PER_INODE + 4) | ||
305 | #define NODE_DIND_BLOCK (ADDRS_PER_INODE + 5) | ||
306 | |||
307 | /* | ||
308 | * For superblock | 304 | * For superblock |
309 | */ | 305 | */ |
310 | /* | 306 | /* |
@@ -350,6 +346,7 @@ enum page_type { | |||
350 | 346 | ||
351 | struct f2fs_sb_info { | 347 | struct f2fs_sb_info { |
352 | struct super_block *sb; /* pointer to VFS super block */ | 348 | struct super_block *sb; /* pointer to VFS super block */ |
349 | struct proc_dir_entry *s_proc; /* proc entry */ | ||
353 | struct buffer_head *raw_super_buf; /* buffer head of raw sb */ | 350 | struct buffer_head *raw_super_buf; /* buffer head of raw sb */ |
354 | struct f2fs_super_block *raw_super; /* raw super block pointer */ | 351 | struct f2fs_super_block *raw_super; /* raw super block pointer */ |
355 | int s_dirty; /* dirty flag for checkpoint */ | 352 | int s_dirty; /* dirty flag for checkpoint */ |
@@ -429,6 +426,10 @@ struct f2fs_sb_info { | |||
429 | #endif | 426 | #endif |
430 | unsigned int last_victim[2]; /* last victim segment # */ | 427 | unsigned int last_victim[2]; /* last victim segment # */ |
431 | spinlock_t stat_lock; /* lock for stat operations */ | 428 | spinlock_t stat_lock; /* lock for stat operations */ |
429 | |||
430 | /* For sysfs suppport */ | ||
431 | struct kobject s_kobj; | ||
432 | struct completion s_kobj_unregister; | ||
432 | }; | 433 | }; |
433 | 434 | ||
434 | /* | 435 | /* |
@@ -454,6 +455,11 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi) | |||
454 | return (struct f2fs_checkpoint *)(sbi->ckpt); | 455 | return (struct f2fs_checkpoint *)(sbi->ckpt); |
455 | } | 456 | } |
456 | 457 | ||
458 | static inline struct f2fs_node *F2FS_NODE(struct page *page) | ||
459 | { | ||
460 | return (struct f2fs_node *)page_address(page); | ||
461 | } | ||
462 | |||
457 | static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi) | 463 | static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi) |
458 | { | 464 | { |
459 | return (struct f2fs_nm_info *)(sbi->nm_info); | 465 | return (struct f2fs_nm_info *)(sbi->nm_info); |
@@ -489,6 +495,11 @@ static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi) | |||
489 | sbi->s_dirty = 0; | 495 | sbi->s_dirty = 0; |
490 | } | 496 | } |
491 | 497 | ||
498 | static inline unsigned long long cur_cp_version(struct f2fs_checkpoint *cp) | ||
499 | { | ||
500 | return le64_to_cpu(cp->checkpoint_ver); | ||
501 | } | ||
502 | |||
492 | static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) | 503 | static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) |
493 | { | 504 | { |
494 | unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags); | 505 | unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags); |
@@ -677,7 +688,7 @@ static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi) | |||
677 | { | 688 | { |
678 | block_t start_addr; | 689 | block_t start_addr; |
679 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 690 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
680 | unsigned long long ckpt_version = le64_to_cpu(ckpt->checkpoint_ver); | 691 | unsigned long long ckpt_version = cur_cp_version(ckpt); |
681 | 692 | ||
682 | start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr); | 693 | start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr); |
683 | 694 | ||
@@ -812,7 +823,7 @@ static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name, | |||
812 | 823 | ||
813 | static inline bool IS_INODE(struct page *page) | 824 | static inline bool IS_INODE(struct page *page) |
814 | { | 825 | { |
815 | struct f2fs_node *p = (struct f2fs_node *)page_address(page); | 826 | struct f2fs_node *p = F2FS_NODE(page); |
816 | return RAW_IS_INODE(p); | 827 | return RAW_IS_INODE(p); |
817 | } | 828 | } |
818 | 829 | ||
@@ -826,7 +837,7 @@ static inline block_t datablock_addr(struct page *node_page, | |||
826 | { | 837 | { |
827 | struct f2fs_node *raw_node; | 838 | struct f2fs_node *raw_node; |
828 | __le32 *addr_array; | 839 | __le32 *addr_array; |
829 | raw_node = (struct f2fs_node *)page_address(node_page); | 840 | raw_node = F2FS_NODE(node_page); |
830 | addr_array = blkaddr_in_node(raw_node); | 841 | addr_array = blkaddr_in_node(raw_node); |
831 | return le32_to_cpu(addr_array[offset]); | 842 | return le32_to_cpu(addr_array[offset]); |
832 | } | 843 | } |
@@ -873,6 +884,7 @@ enum { | |||
873 | FI_NO_ALLOC, /* should not allocate any blocks */ | 884 | FI_NO_ALLOC, /* should not allocate any blocks */ |
874 | FI_UPDATE_DIR, /* should update inode block for consistency */ | 885 | FI_UPDATE_DIR, /* should update inode block for consistency */ |
875 | FI_DELAY_IPUT, /* used for the recovery */ | 886 | FI_DELAY_IPUT, /* used for the recovery */ |
887 | FI_INLINE_XATTR, /* used for inline xattr */ | ||
876 | }; | 888 | }; |
877 | 889 | ||
878 | static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) | 890 | static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) |
@@ -905,6 +917,45 @@ static inline int cond_clear_inode_flag(struct f2fs_inode_info *fi, int flag) | |||
905 | return 0; | 917 | return 0; |
906 | } | 918 | } |
907 | 919 | ||
920 | static inline void get_inline_info(struct f2fs_inode_info *fi, | ||
921 | struct f2fs_inode *ri) | ||
922 | { | ||
923 | if (ri->i_inline & F2FS_INLINE_XATTR) | ||
924 | set_inode_flag(fi, FI_INLINE_XATTR); | ||
925 | } | ||
926 | |||
927 | static inline void set_raw_inline(struct f2fs_inode_info *fi, | ||
928 | struct f2fs_inode *ri) | ||
929 | { | ||
930 | ri->i_inline = 0; | ||
931 | |||
932 | if (is_inode_flag_set(fi, FI_INLINE_XATTR)) | ||
933 | ri->i_inline |= F2FS_INLINE_XATTR; | ||
934 | } | ||
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 | |||
943 | static inline void *inline_xattr_addr(struct page *page) | ||
944 | { | ||
945 | struct f2fs_inode *ri; | ||
946 | ri = (struct f2fs_inode *)page_address(page); | ||
947 | return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE - | ||
948 | F2FS_INLINE_XATTR_ADDRS]); | ||
949 | } | ||
950 | |||
951 | static inline int inline_xattr_size(struct inode *inode) | ||
952 | { | ||
953 | if (is_inode_flag_set(F2FS_I(inode), FI_INLINE_XATTR)) | ||
954 | return F2FS_INLINE_XATTR_ADDRS << 2; | ||
955 | else | ||
956 | return 0; | ||
957 | } | ||
958 | |||
908 | static inline int f2fs_readonly(struct super_block *sb) | 959 | static inline int f2fs_readonly(struct super_block *sb) |
909 | { | 960 | { |
910 | return sb->s_flags & MS_RDONLY; | 961 | return sb->s_flags & MS_RDONLY; |
@@ -947,6 +998,7 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **); | |||
947 | ino_t f2fs_inode_by_name(struct inode *, struct qstr *); | 998 | ino_t f2fs_inode_by_name(struct inode *, struct qstr *); |
948 | void f2fs_set_link(struct inode *, struct f2fs_dir_entry *, | 999 | void f2fs_set_link(struct inode *, struct f2fs_dir_entry *, |
949 | struct page *, struct inode *); | 1000 | struct page *, struct inode *); |
1001 | int update_dent_inode(struct inode *, const struct qstr *); | ||
950 | int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *); | 1002 | int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *); |
951 | void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *); | 1003 | void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *); |
952 | int f2fs_make_empty(struct inode *, struct inode *); | 1004 | int f2fs_make_empty(struct inode *, struct inode *); |
@@ -980,6 +1032,7 @@ int is_checkpointed_node(struct f2fs_sb_info *, nid_t); | |||
980 | void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); | 1032 | void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); |
981 | int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); | 1033 | int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); |
982 | int truncate_inode_blocks(struct inode *, pgoff_t); | 1034 | int truncate_inode_blocks(struct inode *, pgoff_t); |
1035 | int truncate_xattr_node(struct inode *, struct page *); | ||
983 | int remove_inode_page(struct inode *); | 1036 | int remove_inode_page(struct inode *); |
984 | struct page *new_inode_page(struct inode *, const struct qstr *); | 1037 | struct page *new_inode_page(struct inode *, const struct qstr *); |
985 | struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *); | 1038 | struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *); |
@@ -1012,7 +1065,8 @@ int npages_for_summary_flush(struct f2fs_sb_info *); | |||
1012 | void allocate_new_segments(struct f2fs_sb_info *); | 1065 | void allocate_new_segments(struct f2fs_sb_info *); |
1013 | struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); | 1066 | struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); |
1014 | struct bio *f2fs_bio_alloc(struct block_device *, int); | 1067 | struct bio *f2fs_bio_alloc(struct block_device *, int); |
1015 | void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync); | 1068 | void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool); |
1069 | void f2fs_wait_on_page_writeback(struct page *, enum page_type, bool); | ||
1016 | void write_meta_page(struct f2fs_sb_info *, struct page *); | 1070 | void write_meta_page(struct f2fs_sb_info *, struct page *); |
1017 | void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int, | 1071 | void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int, |
1018 | block_t, block_t *); | 1072 | block_t, block_t *); |
@@ -1037,7 +1091,8 @@ void destroy_segment_manager(struct f2fs_sb_info *); | |||
1037 | struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t); | 1091 | struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t); |
1038 | struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t); | 1092 | struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t); |
1039 | long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long); | 1093 | long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long); |
1040 | int check_orphan_space(struct f2fs_sb_info *); | 1094 | int acquire_orphan_inode(struct f2fs_sb_info *); |
1095 | void release_orphan_inode(struct f2fs_sb_info *); | ||
1041 | void add_orphan_inode(struct f2fs_sb_info *, nid_t); | 1096 | void add_orphan_inode(struct f2fs_sb_info *, nid_t); |
1042 | void remove_orphan_inode(struct f2fs_sb_info *, nid_t); | 1097 | void remove_orphan_inode(struct f2fs_sb_info *, nid_t); |
1043 | int recover_orphan_inodes(struct f2fs_sb_info *); | 1098 | int recover_orphan_inodes(struct f2fs_sb_info *); |
@@ -1068,7 +1123,7 @@ int do_write_data_page(struct page *); | |||
1068 | */ | 1123 | */ |
1069 | int start_gc_thread(struct f2fs_sb_info *); | 1124 | int start_gc_thread(struct f2fs_sb_info *); |
1070 | void stop_gc_thread(struct f2fs_sb_info *); | 1125 | void stop_gc_thread(struct f2fs_sb_info *); |
1071 | block_t start_bidx_of_node(unsigned int); | 1126 | block_t start_bidx_of_node(unsigned int, struct f2fs_inode_info *); |
1072 | int f2fs_gc(struct f2fs_sb_info *); | 1127 | int f2fs_gc(struct f2fs_sb_info *); |
1073 | void build_gc_manager(struct f2fs_sb_info *); | 1128 | void build_gc_manager(struct f2fs_sb_info *); |
1074 | int __init create_gc_caches(void); | 1129 | int __init create_gc_caches(void); |
@@ -1112,11 +1167,16 @@ struct f2fs_stat_info { | |||
1112 | unsigned base_mem, cache_mem; | 1167 | unsigned base_mem, cache_mem; |
1113 | }; | 1168 | }; |
1114 | 1169 | ||
1170 | static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi) | ||
1171 | { | ||
1172 | return (struct f2fs_stat_info*)sbi->stat_info; | ||
1173 | } | ||
1174 | |||
1115 | #define stat_inc_call_count(si) ((si)->call_count++) | 1175 | #define stat_inc_call_count(si) ((si)->call_count++) |
1116 | 1176 | ||
1117 | #define stat_inc_seg_count(sbi, type) \ | 1177 | #define stat_inc_seg_count(sbi, type) \ |
1118 | do { \ | 1178 | do { \ |
1119 | struct f2fs_stat_info *si = sbi->stat_info; \ | 1179 | struct f2fs_stat_info *si = F2FS_STAT(sbi); \ |
1120 | (si)->tot_segs++; \ | 1180 | (si)->tot_segs++; \ |
1121 | if (type == SUM_TYPE_DATA) \ | 1181 | if (type == SUM_TYPE_DATA) \ |
1122 | si->data_segs++; \ | 1182 | si->data_segs++; \ |
@@ -1129,14 +1189,14 @@ struct f2fs_stat_info { | |||
1129 | 1189 | ||
1130 | #define stat_inc_data_blk_count(sbi, blks) \ | 1190 | #define stat_inc_data_blk_count(sbi, blks) \ |
1131 | do { \ | 1191 | do { \ |
1132 | struct f2fs_stat_info *si = sbi->stat_info; \ | 1192 | struct f2fs_stat_info *si = F2FS_STAT(sbi); \ |
1133 | stat_inc_tot_blk_count(si, blks); \ | 1193 | stat_inc_tot_blk_count(si, blks); \ |
1134 | si->data_blks += (blks); \ | 1194 | si->data_blks += (blks); \ |
1135 | } while (0) | 1195 | } while (0) |
1136 | 1196 | ||
1137 | #define stat_inc_node_blk_count(sbi, blks) \ | 1197 | #define stat_inc_node_blk_count(sbi, blks) \ |
1138 | do { \ | 1198 | do { \ |
1139 | struct f2fs_stat_info *si = sbi->stat_info; \ | 1199 | struct f2fs_stat_info *si = F2FS_STAT(sbi); \ |
1140 | stat_inc_tot_blk_count(si, blks); \ | 1200 | stat_inc_tot_blk_count(si, blks); \ |
1141 | si->node_blks += (blks); \ | 1201 | si->node_blks += (blks); \ |
1142 | } while (0) | 1202 | } while (0) |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index d2d2b7dbdcc1..02c906971cc6 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -112,11 +112,13 @@ static int get_parent_ino(struct inode *inode, nid_t *pino) | |||
112 | if (!dentry) | 112 | if (!dentry) |
113 | return 0; | 113 | return 0; |
114 | 114 | ||
115 | inode = igrab(dentry->d_parent->d_inode); | 115 | if (update_dent_inode(inode, &dentry->d_name)) { |
116 | dput(dentry); | 116 | dput(dentry); |
117 | return 0; | ||
118 | } | ||
117 | 119 | ||
118 | *pino = inode->i_ino; | 120 | *pino = parent_ino(dentry); |
119 | iput(inode); | 121 | dput(dentry); |
120 | return 1; | 122 | return 1; |
121 | } | 123 | } |
122 | 124 | ||
@@ -147,9 +149,10 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
147 | 149 | ||
148 | mutex_lock(&inode->i_mutex); | 150 | mutex_lock(&inode->i_mutex); |
149 | 151 | ||
150 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 152 | /* |
151 | goto out; | 153 | * Both of fdatasync() and fsync() are able to be recovered from |
152 | 154 | * sudden-power-off. | |
155 | */ | ||
153 | if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) | 156 | if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) |
154 | need_cp = true; | 157 | need_cp = true; |
155 | else if (file_wrong_pino(inode)) | 158 | else if (file_wrong_pino(inode)) |
@@ -158,10 +161,14 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
158 | need_cp = true; | 161 | need_cp = true; |
159 | else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino)) | 162 | else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino)) |
160 | need_cp = true; | 163 | need_cp = true; |
164 | else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi))) | ||
165 | need_cp = true; | ||
161 | 166 | ||
162 | if (need_cp) { | 167 | if (need_cp) { |
163 | nid_t pino; | 168 | nid_t pino; |
164 | 169 | ||
170 | F2FS_I(inode)->xattr_ver = 0; | ||
171 | |||
165 | /* all the dirty node pages should be flushed for POR */ | 172 | /* all the dirty node pages should be flushed for POR */ |
166 | ret = f2fs_sync_fs(inode->i_sb, 1); | 173 | ret = f2fs_sync_fs(inode->i_sb, 1); |
167 | if (file_wrong_pino(inode) && inode->i_nlink == 1 && | 174 | if (file_wrong_pino(inode) && inode->i_nlink == 1 && |
@@ -205,7 +212,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) | |||
205 | struct f2fs_node *raw_node; | 212 | struct f2fs_node *raw_node; |
206 | __le32 *addr; | 213 | __le32 *addr; |
207 | 214 | ||
208 | raw_node = page_address(dn->node_page); | 215 | raw_node = F2FS_NODE(dn->node_page); |
209 | addr = blkaddr_in_node(raw_node) + ofs; | 216 | addr = blkaddr_in_node(raw_node) + ofs; |
210 | 217 | ||
211 | for ( ; count > 0; count--, addr++, dn->ofs_in_node++) { | 218 | for ( ; count > 0; count--, addr++, dn->ofs_in_node++) { |
@@ -283,7 +290,7 @@ static int truncate_blocks(struct inode *inode, u64 from) | |||
283 | } | 290 | } |
284 | 291 | ||
285 | if (IS_INODE(dn.node_page)) | 292 | if (IS_INODE(dn.node_page)) |
286 | count = ADDRS_PER_INODE; | 293 | count = ADDRS_PER_INODE(F2FS_I(inode)); |
287 | else | 294 | else |
288 | count = ADDRS_PER_BLOCK; | 295 | count = ADDRS_PER_BLOCK; |
289 | 296 | ||
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 35f9b1a196aa..2f157e883687 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -29,10 +29,11 @@ static struct kmem_cache *winode_slab; | |||
29 | static int gc_thread_func(void *data) | 29 | static int gc_thread_func(void *data) |
30 | { | 30 | { |
31 | struct f2fs_sb_info *sbi = data; | 31 | struct f2fs_sb_info *sbi = data; |
32 | struct f2fs_gc_kthread *gc_th = sbi->gc_thread; | ||
32 | wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head; | 33 | wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head; |
33 | long wait_ms; | 34 | long wait_ms; |
34 | 35 | ||
35 | wait_ms = GC_THREAD_MIN_SLEEP_TIME; | 36 | wait_ms = gc_th->min_sleep_time; |
36 | 37 | ||
37 | do { | 38 | do { |
38 | if (try_to_freeze()) | 39 | if (try_to_freeze()) |
@@ -45,7 +46,7 @@ static int gc_thread_func(void *data) | |||
45 | break; | 46 | break; |
46 | 47 | ||
47 | if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) { | 48 | if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) { |
48 | wait_ms = GC_THREAD_MAX_SLEEP_TIME; | 49 | wait_ms = increase_sleep_time(gc_th, wait_ms); |
49 | continue; | 50 | continue; |
50 | } | 51 | } |
51 | 52 | ||
@@ -66,15 +67,15 @@ static int gc_thread_func(void *data) | |||
66 | continue; | 67 | continue; |
67 | 68 | ||
68 | if (!is_idle(sbi)) { | 69 | if (!is_idle(sbi)) { |
69 | wait_ms = increase_sleep_time(wait_ms); | 70 | wait_ms = increase_sleep_time(gc_th, wait_ms); |
70 | mutex_unlock(&sbi->gc_mutex); | 71 | mutex_unlock(&sbi->gc_mutex); |
71 | continue; | 72 | continue; |
72 | } | 73 | } |
73 | 74 | ||
74 | if (has_enough_invalid_blocks(sbi)) | 75 | if (has_enough_invalid_blocks(sbi)) |
75 | wait_ms = decrease_sleep_time(wait_ms); | 76 | wait_ms = decrease_sleep_time(gc_th, wait_ms); |
76 | else | 77 | else |
77 | wait_ms = increase_sleep_time(wait_ms); | 78 | wait_ms = increase_sleep_time(gc_th, wait_ms); |
78 | 79 | ||
79 | #ifdef CONFIG_F2FS_STAT_FS | 80 | #ifdef CONFIG_F2FS_STAT_FS |
80 | sbi->bg_gc++; | 81 | sbi->bg_gc++; |
@@ -82,7 +83,7 @@ static int gc_thread_func(void *data) | |||
82 | 83 | ||
83 | /* if return value is not zero, no victim was selected */ | 84 | /* if return value is not zero, no victim was selected */ |
84 | if (f2fs_gc(sbi)) | 85 | if (f2fs_gc(sbi)) |
85 | wait_ms = GC_THREAD_NOGC_SLEEP_TIME; | 86 | wait_ms = gc_th->no_gc_sleep_time; |
86 | } while (!kthread_should_stop()); | 87 | } while (!kthread_should_stop()); |
87 | return 0; | 88 | return 0; |
88 | } | 89 | } |
@@ -101,6 +102,12 @@ int start_gc_thread(struct f2fs_sb_info *sbi) | |||
101 | goto out; | 102 | goto out; |
102 | } | 103 | } |
103 | 104 | ||
105 | gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME; | ||
106 | gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME; | ||
107 | gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME; | ||
108 | |||
109 | gc_th->gc_idle = 0; | ||
110 | |||
104 | sbi->gc_thread = gc_th; | 111 | sbi->gc_thread = gc_th; |
105 | init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head); | 112 | init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head); |
106 | sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi, | 113 | sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi, |
@@ -125,9 +132,17 @@ void stop_gc_thread(struct f2fs_sb_info *sbi) | |||
125 | sbi->gc_thread = NULL; | 132 | sbi->gc_thread = NULL; |
126 | } | 133 | } |
127 | 134 | ||
128 | static int select_gc_type(int gc_type) | 135 | static int select_gc_type(struct f2fs_gc_kthread *gc_th, int gc_type) |
129 | { | 136 | { |
130 | return (gc_type == BG_GC) ? GC_CB : GC_GREEDY; | 137 | int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY; |
138 | |||
139 | if (gc_th && gc_th->gc_idle) { | ||
140 | if (gc_th->gc_idle == 1) | ||
141 | gc_mode = GC_CB; | ||
142 | else if (gc_th->gc_idle == 2) | ||
143 | gc_mode = GC_GREEDY; | ||
144 | } | ||
145 | return gc_mode; | ||
131 | } | 146 | } |
132 | 147 | ||
133 | static void select_policy(struct f2fs_sb_info *sbi, int gc_type, | 148 | static void select_policy(struct f2fs_sb_info *sbi, int gc_type, |
@@ -138,12 +153,18 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, | |||
138 | if (p->alloc_mode == SSR) { | 153 | if (p->alloc_mode == SSR) { |
139 | p->gc_mode = GC_GREEDY; | 154 | p->gc_mode = GC_GREEDY; |
140 | p->dirty_segmap = dirty_i->dirty_segmap[type]; | 155 | p->dirty_segmap = dirty_i->dirty_segmap[type]; |
156 | p->max_search = dirty_i->nr_dirty[type]; | ||
141 | p->ofs_unit = 1; | 157 | p->ofs_unit = 1; |
142 | } else { | 158 | } else { |
143 | p->gc_mode = select_gc_type(gc_type); | 159 | p->gc_mode = select_gc_type(sbi->gc_thread, gc_type); |
144 | p->dirty_segmap = dirty_i->dirty_segmap[DIRTY]; | 160 | p->dirty_segmap = dirty_i->dirty_segmap[DIRTY]; |
161 | p->max_search = dirty_i->nr_dirty[DIRTY]; | ||
145 | p->ofs_unit = sbi->segs_per_sec; | 162 | p->ofs_unit = sbi->segs_per_sec; |
146 | } | 163 | } |
164 | |||
165 | if (p->max_search > MAX_VICTIM_SEARCH) | ||
166 | p->max_search = MAX_VICTIM_SEARCH; | ||
167 | |||
147 | p->offset = sbi->last_victim[p->gc_mode]; | 168 | p->offset = sbi->last_victim[p->gc_mode]; |
148 | } | 169 | } |
149 | 170 | ||
@@ -290,7 +311,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
290 | if (cost == max_cost) | 311 | if (cost == max_cost) |
291 | continue; | 312 | continue; |
292 | 313 | ||
293 | if (nsearched++ >= MAX_VICTIM_SEARCH) { | 314 | if (nsearched++ >= p.max_search) { |
294 | sbi->last_victim[p.gc_mode] = segno; | 315 | sbi->last_victim[p.gc_mode] = segno; |
295 | break; | 316 | break; |
296 | } | 317 | } |
@@ -407,8 +428,7 @@ next_step: | |||
407 | 428 | ||
408 | /* set page dirty and write it */ | 429 | /* set page dirty and write it */ |
409 | if (gc_type == FG_GC) { | 430 | if (gc_type == FG_GC) { |
410 | f2fs_submit_bio(sbi, NODE, true); | 431 | f2fs_wait_on_page_writeback(node_page, NODE, true); |
411 | wait_on_page_writeback(node_page); | ||
412 | set_page_dirty(node_page); | 432 | set_page_dirty(node_page); |
413 | } else { | 433 | } else { |
414 | if (!PageWriteback(node_page)) | 434 | if (!PageWriteback(node_page)) |
@@ -447,7 +467,7 @@ next_step: | |||
447 | * as indirect or double indirect node blocks, are given, it must be a caller's | 467 | * as indirect or double indirect node blocks, are given, it must be a caller's |
448 | * bug. | 468 | * bug. |
449 | */ | 469 | */ |
450 | block_t start_bidx_of_node(unsigned int node_ofs) | 470 | block_t start_bidx_of_node(unsigned int node_ofs, struct f2fs_inode_info *fi) |
451 | { | 471 | { |
452 | unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; | 472 | unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; |
453 | unsigned int bidx; | 473 | unsigned int bidx; |
@@ -464,7 +484,7 @@ block_t start_bidx_of_node(unsigned int node_ofs) | |||
464 | int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); | 484 | int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); |
465 | bidx = node_ofs - 5 - dec; | 485 | bidx = node_ofs - 5 - dec; |
466 | } | 486 | } |
467 | return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE; | 487 | return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(fi); |
468 | } | 488 | } |
469 | 489 | ||
470 | static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, | 490 | static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, |
@@ -508,10 +528,7 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type) | |||
508 | } else { | 528 | } else { |
509 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 529 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
510 | 530 | ||
511 | if (PageWriteback(page)) { | 531 | f2fs_wait_on_page_writeback(page, DATA, true); |
512 | f2fs_submit_bio(sbi, DATA, true); | ||
513 | wait_on_page_writeback(page); | ||
514 | } | ||
515 | 532 | ||
516 | if (clear_page_dirty_for_io(page) && | 533 | if (clear_page_dirty_for_io(page) && |
517 | S_ISDIR(inode->i_mode)) { | 534 | S_ISDIR(inode->i_mode)) { |
@@ -575,7 +592,6 @@ next_step: | |||
575 | continue; | 592 | continue; |
576 | } | 593 | } |
577 | 594 | ||
578 | start_bidx = start_bidx_of_node(nofs); | ||
579 | ofs_in_node = le16_to_cpu(entry->ofs_in_node); | 595 | ofs_in_node = le16_to_cpu(entry->ofs_in_node); |
580 | 596 | ||
581 | if (phase == 2) { | 597 | if (phase == 2) { |
@@ -583,6 +599,8 @@ next_step: | |||
583 | if (IS_ERR(inode)) | 599 | if (IS_ERR(inode)) |
584 | continue; | 600 | continue; |
585 | 601 | ||
602 | start_bidx = start_bidx_of_node(nofs, F2FS_I(inode)); | ||
603 | |||
586 | data_page = find_data_page(inode, | 604 | data_page = find_data_page(inode, |
587 | start_bidx + ofs_in_node, false); | 605 | start_bidx + ofs_in_node, false); |
588 | if (IS_ERR(data_page)) | 606 | if (IS_ERR(data_page)) |
@@ -593,6 +611,8 @@ next_step: | |||
593 | } else { | 611 | } else { |
594 | inode = find_gc_inode(dni.ino, ilist); | 612 | inode = find_gc_inode(dni.ino, ilist); |
595 | if (inode) { | 613 | if (inode) { |
614 | start_bidx = start_bidx_of_node(nofs, | ||
615 | F2FS_I(inode)); | ||
596 | data_page = get_lock_data_page(inode, | 616 | data_page = get_lock_data_page(inode, |
597 | start_bidx + ofs_in_node); | 617 | start_bidx + ofs_in_node); |
598 | if (IS_ERR(data_page)) | 618 | if (IS_ERR(data_page)) |
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index 2c6a6bd08322..507056d22205 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h | |||
@@ -13,18 +13,26 @@ | |||
13 | * whether IO subsystem is idle | 13 | * whether IO subsystem is idle |
14 | * or not | 14 | * or not |
15 | */ | 15 | */ |
16 | #define GC_THREAD_MIN_SLEEP_TIME 30000 /* milliseconds */ | 16 | #define DEF_GC_THREAD_MIN_SLEEP_TIME 30000 /* milliseconds */ |
17 | #define GC_THREAD_MAX_SLEEP_TIME 60000 | 17 | #define DEF_GC_THREAD_MAX_SLEEP_TIME 60000 |
18 | #define GC_THREAD_NOGC_SLEEP_TIME 300000 /* wait 5 min */ | 18 | #define DEF_GC_THREAD_NOGC_SLEEP_TIME 300000 /* wait 5 min */ |
19 | #define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ | 19 | #define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ |
20 | #define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */ | 20 | #define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */ |
21 | 21 | ||
22 | /* Search max. number of dirty segments to select a victim segment */ | 22 | /* Search max. number of dirty segments to select a victim segment */ |
23 | #define MAX_VICTIM_SEARCH 20 | 23 | #define MAX_VICTIM_SEARCH 4096 /* covers 8GB */ |
24 | 24 | ||
25 | struct f2fs_gc_kthread { | 25 | struct f2fs_gc_kthread { |
26 | struct task_struct *f2fs_gc_task; | 26 | struct task_struct *f2fs_gc_task; |
27 | wait_queue_head_t gc_wait_queue_head; | 27 | wait_queue_head_t gc_wait_queue_head; |
28 | |||
29 | /* for gc sleep time */ | ||
30 | unsigned int min_sleep_time; | ||
31 | unsigned int max_sleep_time; | ||
32 | unsigned int no_gc_sleep_time; | ||
33 | |||
34 | /* for changing gc mode */ | ||
35 | unsigned int gc_idle; | ||
28 | }; | 36 | }; |
29 | 37 | ||
30 | struct inode_entry { | 38 | struct inode_entry { |
@@ -56,25 +64,25 @@ static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi) | |||
56 | return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100; | 64 | return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100; |
57 | } | 65 | } |
58 | 66 | ||
59 | static inline long increase_sleep_time(long wait) | 67 | static inline long increase_sleep_time(struct f2fs_gc_kthread *gc_th, long wait) |
60 | { | 68 | { |
61 | if (wait == GC_THREAD_NOGC_SLEEP_TIME) | 69 | if (wait == gc_th->no_gc_sleep_time) |
62 | return wait; | 70 | return wait; |
63 | 71 | ||
64 | wait += GC_THREAD_MIN_SLEEP_TIME; | 72 | wait += gc_th->min_sleep_time; |
65 | if (wait > GC_THREAD_MAX_SLEEP_TIME) | 73 | if (wait > gc_th->max_sleep_time) |
66 | wait = GC_THREAD_MAX_SLEEP_TIME; | 74 | wait = gc_th->max_sleep_time; |
67 | return wait; | 75 | return wait; |
68 | } | 76 | } |
69 | 77 | ||
70 | static inline long decrease_sleep_time(long wait) | 78 | static inline long decrease_sleep_time(struct f2fs_gc_kthread *gc_th, long wait) |
71 | { | 79 | { |
72 | if (wait == GC_THREAD_NOGC_SLEEP_TIME) | 80 | if (wait == gc_th->no_gc_sleep_time) |
73 | wait = GC_THREAD_MAX_SLEEP_TIME; | 81 | wait = gc_th->max_sleep_time; |
74 | 82 | ||
75 | wait -= GC_THREAD_MIN_SLEEP_TIME; | 83 | wait -= gc_th->min_sleep_time; |
76 | if (wait <= GC_THREAD_MIN_SLEEP_TIME) | 84 | if (wait <= gc_th->min_sleep_time) |
77 | wait = GC_THREAD_MIN_SLEEP_TIME; | 85 | wait = gc_th->min_sleep_time; |
78 | return wait; | 86 | return wait; |
79 | } | 87 | } |
80 | 88 | ||
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 2b2d45d19e3e..9339cd292047 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
@@ -56,7 +56,7 @@ static int do_read_inode(struct inode *inode) | |||
56 | if (IS_ERR(node_page)) | 56 | if (IS_ERR(node_page)) |
57 | return PTR_ERR(node_page); | 57 | return PTR_ERR(node_page); |
58 | 58 | ||
59 | rn = page_address(node_page); | 59 | rn = F2FS_NODE(node_page); |
60 | ri = &(rn->i); | 60 | ri = &(rn->i); |
61 | 61 | ||
62 | inode->i_mode = le16_to_cpu(ri->i_mode); | 62 | inode->i_mode = le16_to_cpu(ri->i_mode); |
@@ -85,6 +85,7 @@ static int do_read_inode(struct inode *inode) | |||
85 | fi->i_advise = ri->i_advise; | 85 | fi->i_advise = ri->i_advise; |
86 | fi->i_pino = le32_to_cpu(ri->i_pino); | 86 | fi->i_pino = le32_to_cpu(ri->i_pino); |
87 | get_extent_info(&fi->ext, ri->i_ext); | 87 | get_extent_info(&fi->ext, ri->i_ext); |
88 | get_inline_info(fi, ri); | ||
88 | f2fs_put_page(node_page, 1); | 89 | f2fs_put_page(node_page, 1); |
89 | return 0; | 90 | return 0; |
90 | } | 91 | } |
@@ -151,9 +152,9 @@ void update_inode(struct inode *inode, struct page *node_page) | |||
151 | struct f2fs_node *rn; | 152 | struct f2fs_node *rn; |
152 | struct f2fs_inode *ri; | 153 | struct f2fs_inode *ri; |
153 | 154 | ||
154 | wait_on_page_writeback(node_page); | 155 | f2fs_wait_on_page_writeback(node_page, NODE, false); |
155 | 156 | ||
156 | rn = page_address(node_page); | 157 | rn = F2FS_NODE(node_page); |
157 | ri = &(rn->i); | 158 | ri = &(rn->i); |
158 | 159 | ||
159 | ri->i_mode = cpu_to_le16(inode->i_mode); | 160 | ri->i_mode = cpu_to_le16(inode->i_mode); |
@@ -164,6 +165,7 @@ void update_inode(struct inode *inode, struct page *node_page) | |||
164 | ri->i_size = cpu_to_le64(i_size_read(inode)); | 165 | ri->i_size = cpu_to_le64(i_size_read(inode)); |
165 | ri->i_blocks = cpu_to_le64(inode->i_blocks); | 166 | ri->i_blocks = cpu_to_le64(inode->i_blocks); |
166 | set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext); | 167 | set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext); |
168 | set_raw_inline(F2FS_I(inode), ri); | ||
167 | 169 | ||
168 | ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec); | 170 | ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec); |
169 | ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); | 171 | ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); |
@@ -221,9 +223,6 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
221 | if (!is_inode_flag_set(F2FS_I(inode), FI_DIRTY_INODE)) | 223 | if (!is_inode_flag_set(F2FS_I(inode), FI_DIRTY_INODE)) |
222 | return 0; | 224 | return 0; |
223 | 225 | ||
224 | if (wbc) | ||
225 | f2fs_balance_fs(sbi); | ||
226 | |||
227 | /* | 226 | /* |
228 | * We need to lock here to prevent from producing dirty node pages | 227 | * We need to lock here to prevent from producing dirty node pages |
229 | * during the urgent cleaning time when runing out of free sections. | 228 | * during the urgent cleaning time when runing out of free sections. |
@@ -231,6 +230,10 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
231 | ilock = mutex_lock_op(sbi); | 230 | ilock = mutex_lock_op(sbi); |
232 | ret = update_inode_page(inode); | 231 | ret = update_inode_page(inode); |
233 | mutex_unlock_op(sbi, ilock); | 232 | mutex_unlock_op(sbi, ilock); |
233 | |||
234 | if (wbc) | ||
235 | f2fs_balance_fs(sbi); | ||
236 | |||
234 | return ret; | 237 | return ret; |
235 | } | 238 | } |
236 | 239 | ||
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 64c07169df05..2a5359c990fc 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c | |||
@@ -83,21 +83,11 @@ static int is_multimedia_file(const unsigned char *s, const char *sub) | |||
83 | { | 83 | { |
84 | size_t slen = strlen(s); | 84 | size_t slen = strlen(s); |
85 | size_t sublen = strlen(sub); | 85 | size_t sublen = strlen(sub); |
86 | int ret; | ||
87 | 86 | ||
88 | if (sublen > slen) | 87 | if (sublen > slen) |
89 | return 0; | 88 | return 0; |
90 | 89 | ||
91 | ret = memcmp(s + slen - sublen, sub, sublen); | 90 | return !strncasecmp(s + slen - sublen, sub, sublen); |
92 | if (ret) { /* compare upper case */ | ||
93 | int i; | ||
94 | char upper_sub[8]; | ||
95 | for (i = 0; i < sublen && i < sizeof(upper_sub); i++) | ||
96 | upper_sub[i] = toupper(sub[i]); | ||
97 | return !memcmp(s + slen - sublen, upper_sub, sublen); | ||
98 | } | ||
99 | |||
100 | return !ret; | ||
101 | } | 91 | } |
102 | 92 | ||
103 | /* | 93 | /* |
@@ -239,7 +229,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) | |||
239 | if (!de) | 229 | if (!de) |
240 | goto fail; | 230 | goto fail; |
241 | 231 | ||
242 | err = check_orphan_space(sbi); | 232 | err = acquire_orphan_inode(sbi); |
243 | if (err) { | 233 | if (err) { |
244 | kunmap(page); | 234 | kunmap(page); |
245 | f2fs_put_page(page, 0); | 235 | f2fs_put_page(page, 0); |
@@ -393,7 +383,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
393 | struct inode *old_inode = old_dentry->d_inode; | 383 | struct inode *old_inode = old_dentry->d_inode; |
394 | struct inode *new_inode = new_dentry->d_inode; | 384 | struct inode *new_inode = new_dentry->d_inode; |
395 | struct page *old_dir_page; | 385 | struct page *old_dir_page; |
396 | struct page *old_page; | 386 | struct page *old_page, *new_page; |
397 | struct f2fs_dir_entry *old_dir_entry = NULL; | 387 | struct f2fs_dir_entry *old_dir_entry = NULL; |
398 | struct f2fs_dir_entry *old_entry; | 388 | struct f2fs_dir_entry *old_entry; |
399 | struct f2fs_dir_entry *new_entry; | 389 | struct f2fs_dir_entry *new_entry; |
@@ -415,7 +405,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
415 | ilock = mutex_lock_op(sbi); | 405 | ilock = mutex_lock_op(sbi); |
416 | 406 | ||
417 | if (new_inode) { | 407 | if (new_inode) { |
418 | struct page *new_page; | ||
419 | 408 | ||
420 | err = -ENOTEMPTY; | 409 | err = -ENOTEMPTY; |
421 | if (old_dir_entry && !f2fs_empty_dir(new_inode)) | 410 | if (old_dir_entry && !f2fs_empty_dir(new_inode)) |
@@ -427,14 +416,28 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
427 | if (!new_entry) | 416 | if (!new_entry) |
428 | goto out_dir; | 417 | goto out_dir; |
429 | 418 | ||
419 | err = acquire_orphan_inode(sbi); | ||
420 | if (err) | ||
421 | goto put_out_dir; | ||
422 | |||
423 | if (update_dent_inode(old_inode, &new_dentry->d_name)) { | ||
424 | release_orphan_inode(sbi); | ||
425 | goto put_out_dir; | ||
426 | } | ||
427 | |||
430 | f2fs_set_link(new_dir, new_entry, new_page, old_inode); | 428 | f2fs_set_link(new_dir, new_entry, new_page, old_inode); |
431 | 429 | ||
432 | new_inode->i_ctime = CURRENT_TIME; | 430 | new_inode->i_ctime = CURRENT_TIME; |
433 | if (old_dir_entry) | 431 | if (old_dir_entry) |
434 | drop_nlink(new_inode); | 432 | drop_nlink(new_inode); |
435 | drop_nlink(new_inode); | 433 | drop_nlink(new_inode); |
434 | |||
436 | if (!new_inode->i_nlink) | 435 | if (!new_inode->i_nlink) |
437 | add_orphan_inode(sbi, new_inode->i_ino); | 436 | add_orphan_inode(sbi, new_inode->i_ino); |
437 | else | ||
438 | release_orphan_inode(sbi); | ||
439 | |||
440 | update_inode_page(old_inode); | ||
438 | update_inode_page(new_inode); | 441 | update_inode_page(new_inode); |
439 | } else { | 442 | } else { |
440 | err = f2fs_add_link(new_dentry, old_inode); | 443 | err = f2fs_add_link(new_dentry, old_inode); |
@@ -467,6 +470,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
467 | mutex_unlock_op(sbi, ilock); | 470 | mutex_unlock_op(sbi, ilock); |
468 | return 0; | 471 | return 0; |
469 | 472 | ||
473 | put_out_dir: | ||
474 | f2fs_put_page(new_page, 1); | ||
470 | out_dir: | 475 | out_dir: |
471 | if (old_dir_entry) { | 476 | if (old_dir_entry) { |
472 | kunmap(old_dir_page); | 477 | kunmap(old_dir_page); |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index b418aee09573..51ef27894433 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; |
@@ -565,7 +566,7 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, | |||
565 | return PTR_ERR(page); | 566 | return PTR_ERR(page); |
566 | } | 567 | } |
567 | 568 | ||
568 | rn = (struct f2fs_node *)page_address(page); | 569 | rn = F2FS_NODE(page); |
569 | if (depth < 3) { | 570 | if (depth < 3) { |
570 | for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { | 571 | for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { |
571 | child_nid = le32_to_cpu(rn->in.nid[i]); | 572 | child_nid = le32_to_cpu(rn->in.nid[i]); |
@@ -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)) { |
@@ -698,7 +699,7 @@ restart: | |||
698 | set_new_dnode(&dn, inode, page, NULL, 0); | 699 | set_new_dnode(&dn, inode, page, NULL, 0); |
699 | unlock_page(page); | 700 | unlock_page(page); |
700 | 701 | ||
701 | rn = page_address(page); | 702 | rn = F2FS_NODE(page); |
702 | switch (level) { | 703 | switch (level) { |
703 | case 0: | 704 | case 0: |
704 | case 1: | 705 | case 1: |
@@ -771,6 +772,33 @@ fail: | |||
771 | return err > 0 ? 0 : err; | 772 | return err > 0 ? 0 : err; |
772 | } | 773 | } |
773 | 774 | ||
775 | int truncate_xattr_node(struct inode *inode, struct page *page) | ||
776 | { | ||
777 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
778 | nid_t nid = F2FS_I(inode)->i_xattr_nid; | ||
779 | struct dnode_of_data dn; | ||
780 | struct page *npage; | ||
781 | |||
782 | if (!nid) | ||
783 | return 0; | ||
784 | |||
785 | npage = get_node_page(sbi, nid); | ||
786 | if (IS_ERR(npage)) | ||
787 | return PTR_ERR(npage); | ||
788 | |||
789 | F2FS_I(inode)->i_xattr_nid = 0; | ||
790 | |||
791 | /* need to do checkpoint during fsync */ | ||
792 | F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi)); | ||
793 | |||
794 | set_new_dnode(&dn, inode, page, npage, nid); | ||
795 | |||
796 | if (page) | ||
797 | dn.inode_page_locked = 1; | ||
798 | truncate_node(&dn); | ||
799 | return 0; | ||
800 | } | ||
801 | |||
774 | /* | 802 | /* |
775 | * Caller should grab and release a mutex by calling mutex_lock_op() and | 803 | * Caller should grab and release a mutex by calling mutex_lock_op() and |
776 | * mutex_unlock_op(). | 804 | * mutex_unlock_op(). |
@@ -781,22 +809,16 @@ int remove_inode_page(struct inode *inode) | |||
781 | struct page *page; | 809 | struct page *page; |
782 | nid_t ino = inode->i_ino; | 810 | nid_t ino = inode->i_ino; |
783 | struct dnode_of_data dn; | 811 | struct dnode_of_data dn; |
812 | int err; | ||
784 | 813 | ||
785 | page = get_node_page(sbi, ino); | 814 | page = get_node_page(sbi, ino); |
786 | if (IS_ERR(page)) | 815 | if (IS_ERR(page)) |
787 | return PTR_ERR(page); | 816 | return PTR_ERR(page); |
788 | 817 | ||
789 | if (F2FS_I(inode)->i_xattr_nid) { | 818 | err = truncate_xattr_node(inode, page); |
790 | nid_t nid = F2FS_I(inode)->i_xattr_nid; | 819 | if (err) { |
791 | struct page *npage = get_node_page(sbi, nid); | 820 | f2fs_put_page(page, 1); |
792 | 821 | return err; | |
793 | if (IS_ERR(npage)) | ||
794 | return PTR_ERR(npage); | ||
795 | |||
796 | F2FS_I(inode)->i_xattr_nid = 0; | ||
797 | set_new_dnode(&dn, inode, page, npage, nid); | ||
798 | dn.inode_page_locked = 1; | ||
799 | truncate_node(&dn); | ||
800 | } | 822 | } |
801 | 823 | ||
802 | /* 0 is possible, after f2fs_new_inode() is failed */ | 824 | /* 0 is possible, after f2fs_new_inode() is failed */ |
@@ -833,29 +855,32 @@ struct page *new_node_page(struct dnode_of_data *dn, | |||
833 | if (!page) | 855 | if (!page) |
834 | return ERR_PTR(-ENOMEM); | 856 | return ERR_PTR(-ENOMEM); |
835 | 857 | ||
836 | get_node_info(sbi, dn->nid, &old_ni); | 858 | if (!inc_valid_node_count(sbi, dn->inode, 1)) { |
859 | err = -ENOSPC; | ||
860 | goto fail; | ||
861 | } | ||
837 | 862 | ||
838 | SetPageUptodate(page); | 863 | get_node_info(sbi, dn->nid, &old_ni); |
839 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); | ||
840 | 864 | ||
841 | /* Reinitialize old_ni with new node page */ | 865 | /* Reinitialize old_ni with new node page */ |
842 | BUG_ON(old_ni.blk_addr != NULL_ADDR); | 866 | BUG_ON(old_ni.blk_addr != NULL_ADDR); |
843 | new_ni = old_ni; | 867 | new_ni = old_ni; |
844 | new_ni.ino = dn->inode->i_ino; | 868 | new_ni.ino = dn->inode->i_ino; |
845 | |||
846 | if (!inc_valid_node_count(sbi, dn->inode, 1)) { | ||
847 | err = -ENOSPC; | ||
848 | goto fail; | ||
849 | } | ||
850 | set_node_addr(sbi, &new_ni, NEW_ADDR); | 869 | set_node_addr(sbi, &new_ni, NEW_ADDR); |
870 | |||
871 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); | ||
851 | set_cold_node(dn->inode, page); | 872 | set_cold_node(dn->inode, page); |
873 | SetPageUptodate(page); | ||
874 | set_page_dirty(page); | ||
875 | |||
876 | if (ofs == XATTR_NODE_OFFSET) | ||
877 | F2FS_I(dn->inode)->i_xattr_nid = dn->nid; | ||
852 | 878 | ||
853 | dn->node_page = page; | 879 | dn->node_page = page; |
854 | if (ipage) | 880 | if (ipage) |
855 | update_inode(dn->inode, ipage); | 881 | update_inode(dn->inode, ipage); |
856 | else | 882 | else |
857 | sync_inode_page(dn); | 883 | sync_inode_page(dn); |
858 | set_page_dirty(page); | ||
859 | if (ofs == 0) | 884 | if (ofs == 0) |
860 | inc_valid_inode_count(sbi); | 885 | inc_valid_inode_count(sbi); |
861 | 886 | ||
@@ -916,7 +941,6 @@ void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) | |||
916 | f2fs_put_page(apage, 0); | 941 | f2fs_put_page(apage, 0); |
917 | else if (err == LOCKED_PAGE) | 942 | else if (err == LOCKED_PAGE) |
918 | f2fs_put_page(apage, 1); | 943 | f2fs_put_page(apage, 1); |
919 | return; | ||
920 | } | 944 | } |
921 | 945 | ||
922 | struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) | 946 | struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) |
@@ -1167,9 +1191,9 @@ static int f2fs_write_node_page(struct page *page, | |||
1167 | /* | 1191 | /* |
1168 | * It is very important to gather dirty pages and write at once, so that we can | 1192 | * It is very important to gather dirty pages and write at once, so that we can |
1169 | * submit a big bio without interfering other data writes. | 1193 | * submit a big bio without interfering other data writes. |
1170 | * Be default, 512 pages (2MB), a segment size, is quite reasonable. | 1194 | * Be default, 512 pages (2MB) * 3 node types, is more reasonable. |
1171 | */ | 1195 | */ |
1172 | #define COLLECT_DIRTY_NODES 512 | 1196 | #define COLLECT_DIRTY_NODES 1536 |
1173 | static int f2fs_write_node_pages(struct address_space *mapping, | 1197 | static int f2fs_write_node_pages(struct address_space *mapping, |
1174 | struct writeback_control *wbc) | 1198 | struct writeback_control *wbc) |
1175 | { | 1199 | { |
@@ -1187,9 +1211,10 @@ static int f2fs_write_node_pages(struct address_space *mapping, | |||
1187 | return 0; | 1211 | return 0; |
1188 | 1212 | ||
1189 | /* if mounting is failed, skip writing node pages */ | 1213 | /* if mounting is failed, skip writing node pages */ |
1190 | wbc->nr_to_write = max_hw_blocks(sbi); | 1214 | wbc->nr_to_write = 3 * max_hw_blocks(sbi); |
1191 | sync_node_pages(sbi, 0, wbc); | 1215 | sync_node_pages(sbi, 0, wbc); |
1192 | wbc->nr_to_write = nr_to_write - (max_hw_blocks(sbi) - wbc->nr_to_write); | 1216 | wbc->nr_to_write = nr_to_write - (3 * max_hw_blocks(sbi) - |
1217 | wbc->nr_to_write); | ||
1193 | return 0; | 1218 | return 0; |
1194 | } | 1219 | } |
1195 | 1220 | ||
@@ -1444,6 +1469,9 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) | |||
1444 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1469 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1445 | struct free_nid *i; | 1470 | struct free_nid *i; |
1446 | 1471 | ||
1472 | if (!nid) | ||
1473 | return; | ||
1474 | |||
1447 | spin_lock(&nm_i->free_nid_list_lock); | 1475 | spin_lock(&nm_i->free_nid_list_lock); |
1448 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); | 1476 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); |
1449 | BUG_ON(!i || i->state != NID_ALLOC); | 1477 | BUG_ON(!i || i->state != NID_ALLOC); |
@@ -1484,8 +1512,8 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | |||
1484 | SetPageUptodate(ipage); | 1512 | SetPageUptodate(ipage); |
1485 | fill_node_footer(ipage, ino, ino, 0, true); | 1513 | fill_node_footer(ipage, ino, ino, 0, true); |
1486 | 1514 | ||
1487 | src = (struct f2fs_node *)page_address(page); | 1515 | src = F2FS_NODE(page); |
1488 | dst = (struct f2fs_node *)page_address(ipage); | 1516 | dst = F2FS_NODE(ipage); |
1489 | 1517 | ||
1490 | memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i); | 1518 | memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i); |
1491 | dst->i.i_size = 0; | 1519 | dst->i.i_size = 0; |
@@ -1515,8 +1543,8 @@ int restore_node_summary(struct f2fs_sb_info *sbi, | |||
1515 | 1543 | ||
1516 | /* alloc temporal page for read node */ | 1544 | /* alloc temporal page for read node */ |
1517 | page = alloc_page(GFP_NOFS | __GFP_ZERO); | 1545 | page = alloc_page(GFP_NOFS | __GFP_ZERO); |
1518 | if (IS_ERR(page)) | 1546 | if (!page) |
1519 | return PTR_ERR(page); | 1547 | return -ENOMEM; |
1520 | lock_page(page); | 1548 | lock_page(page); |
1521 | 1549 | ||
1522 | /* scan the node segment */ | 1550 | /* scan the node segment */ |
@@ -1535,7 +1563,7 @@ int restore_node_summary(struct f2fs_sb_info *sbi, | |||
1535 | goto out; | 1563 | goto out; |
1536 | 1564 | ||
1537 | lock_page(page); | 1565 | lock_page(page); |
1538 | rn = (struct f2fs_node *)page_address(page); | 1566 | rn = F2FS_NODE(page); |
1539 | sum_entry->nid = rn->footer.nid; | 1567 | sum_entry->nid = rn->footer.nid; |
1540 | sum_entry->version = 0; | 1568 | sum_entry->version = 0; |
1541 | sum_entry->ofs_in_node = 0; | 1569 | sum_entry->ofs_in_node = 0; |
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index c65fb4f4230f..3496bb3e15dc 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h | |||
@@ -155,8 +155,7 @@ static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid) | |||
155 | static inline void fill_node_footer(struct page *page, nid_t nid, | 155 | static inline void fill_node_footer(struct page *page, nid_t nid, |
156 | nid_t ino, unsigned int ofs, bool reset) | 156 | nid_t ino, unsigned int ofs, bool reset) |
157 | { | 157 | { |
158 | void *kaddr = page_address(page); | 158 | struct f2fs_node *rn = F2FS_NODE(page); |
159 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
160 | if (reset) | 159 | if (reset) |
161 | memset(rn, 0, sizeof(*rn)); | 160 | memset(rn, 0, sizeof(*rn)); |
162 | rn->footer.nid = cpu_to_le32(nid); | 161 | rn->footer.nid = cpu_to_le32(nid); |
@@ -166,10 +165,8 @@ static inline void fill_node_footer(struct page *page, nid_t nid, | |||
166 | 165 | ||
167 | static inline void copy_node_footer(struct page *dst, struct page *src) | 166 | static inline void copy_node_footer(struct page *dst, struct page *src) |
168 | { | 167 | { |
169 | void *src_addr = page_address(src); | 168 | struct f2fs_node *src_rn = F2FS_NODE(src); |
170 | void *dst_addr = page_address(dst); | 169 | struct f2fs_node *dst_rn = F2FS_NODE(dst); |
171 | struct f2fs_node *src_rn = (struct f2fs_node *)src_addr; | ||
172 | struct f2fs_node *dst_rn = (struct f2fs_node *)dst_addr; | ||
173 | memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer)); | 170 | memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer)); |
174 | } | 171 | } |
175 | 172 | ||
@@ -177,45 +174,40 @@ static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr) | |||
177 | { | 174 | { |
178 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); | 175 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); |
179 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 176 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
180 | void *kaddr = page_address(page); | 177 | struct f2fs_node *rn = F2FS_NODE(page); |
181 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | 178 | |
182 | rn->footer.cp_ver = ckpt->checkpoint_ver; | 179 | rn->footer.cp_ver = ckpt->checkpoint_ver; |
183 | rn->footer.next_blkaddr = cpu_to_le32(blkaddr); | 180 | rn->footer.next_blkaddr = cpu_to_le32(blkaddr); |
184 | } | 181 | } |
185 | 182 | ||
186 | static inline nid_t ino_of_node(struct page *node_page) | 183 | static inline nid_t ino_of_node(struct page *node_page) |
187 | { | 184 | { |
188 | void *kaddr = page_address(node_page); | 185 | struct f2fs_node *rn = F2FS_NODE(node_page); |
189 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
190 | return le32_to_cpu(rn->footer.ino); | 186 | return le32_to_cpu(rn->footer.ino); |
191 | } | 187 | } |
192 | 188 | ||
193 | static inline nid_t nid_of_node(struct page *node_page) | 189 | static inline nid_t nid_of_node(struct page *node_page) |
194 | { | 190 | { |
195 | void *kaddr = page_address(node_page); | 191 | struct f2fs_node *rn = F2FS_NODE(node_page); |
196 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
197 | return le32_to_cpu(rn->footer.nid); | 192 | return le32_to_cpu(rn->footer.nid); |
198 | } | 193 | } |
199 | 194 | ||
200 | static inline unsigned int ofs_of_node(struct page *node_page) | 195 | static inline unsigned int ofs_of_node(struct page *node_page) |
201 | { | 196 | { |
202 | void *kaddr = page_address(node_page); | 197 | struct f2fs_node *rn = F2FS_NODE(node_page); |
203 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
204 | unsigned flag = le32_to_cpu(rn->footer.flag); | 198 | unsigned flag = le32_to_cpu(rn->footer.flag); |
205 | return flag >> OFFSET_BIT_SHIFT; | 199 | return flag >> OFFSET_BIT_SHIFT; |
206 | } | 200 | } |
207 | 201 | ||
208 | static inline unsigned long long cpver_of_node(struct page *node_page) | 202 | static inline unsigned long long cpver_of_node(struct page *node_page) |
209 | { | 203 | { |
210 | void *kaddr = page_address(node_page); | 204 | struct f2fs_node *rn = F2FS_NODE(node_page); |
211 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
212 | return le64_to_cpu(rn->footer.cp_ver); | 205 | return le64_to_cpu(rn->footer.cp_ver); |
213 | } | 206 | } |
214 | 207 | ||
215 | static inline block_t next_blkaddr_of_node(struct page *node_page) | 208 | static inline block_t next_blkaddr_of_node(struct page *node_page) |
216 | { | 209 | { |
217 | void *kaddr = page_address(node_page); | 210 | struct f2fs_node *rn = F2FS_NODE(node_page); |
218 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
219 | return le32_to_cpu(rn->footer.next_blkaddr); | 211 | return le32_to_cpu(rn->footer.next_blkaddr); |
220 | } | 212 | } |
221 | 213 | ||
@@ -237,6 +229,10 @@ static inline block_t next_blkaddr_of_node(struct page *node_page) | |||
237 | static inline bool IS_DNODE(struct page *node_page) | 229 | static inline bool IS_DNODE(struct page *node_page) |
238 | { | 230 | { |
239 | unsigned int ofs = ofs_of_node(node_page); | 231 | unsigned int ofs = ofs_of_node(node_page); |
232 | |||
233 | if (ofs == XATTR_NODE_OFFSET) | ||
234 | return false; | ||
235 | |||
240 | if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK || | 236 | if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK || |
241 | ofs == 5 + 2 * NIDS_PER_BLOCK) | 237 | ofs == 5 + 2 * NIDS_PER_BLOCK) |
242 | return false; | 238 | return false; |
@@ -250,7 +246,7 @@ static inline bool IS_DNODE(struct page *node_page) | |||
250 | 246 | ||
251 | static inline void set_nid(struct page *p, int off, nid_t nid, bool i) | 247 | static inline void set_nid(struct page *p, int off, nid_t nid, bool i) |
252 | { | 248 | { |
253 | struct f2fs_node *rn = (struct f2fs_node *)page_address(p); | 249 | struct f2fs_node *rn = F2FS_NODE(p); |
254 | 250 | ||
255 | wait_on_page_writeback(p); | 251 | wait_on_page_writeback(p); |
256 | 252 | ||
@@ -263,7 +259,8 @@ static inline void set_nid(struct page *p, int off, nid_t nid, bool i) | |||
263 | 259 | ||
264 | static inline nid_t get_nid(struct page *p, int off, bool i) | 260 | static inline nid_t get_nid(struct page *p, int off, bool i) |
265 | { | 261 | { |
266 | struct f2fs_node *rn = (struct f2fs_node *)page_address(p); | 262 | struct f2fs_node *rn = F2FS_NODE(p); |
263 | |||
267 | if (i) | 264 | if (i) |
268 | return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); | 265 | return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); |
269 | return le32_to_cpu(rn->in.nid[off]); | 266 | return le32_to_cpu(rn->in.nid[off]); |
@@ -314,8 +311,7 @@ static inline void clear_cold_data(struct page *page) | |||
314 | 311 | ||
315 | static inline int is_node(struct page *page, int type) | 312 | static inline int is_node(struct page *page, int type) |
316 | { | 313 | { |
317 | void *kaddr = page_address(page); | 314 | struct f2fs_node *rn = F2FS_NODE(page); |
318 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
319 | return le32_to_cpu(rn->footer.flag) & (1 << type); | 315 | return le32_to_cpu(rn->footer.flag) & (1 << type); |
320 | } | 316 | } |
321 | 317 | ||
@@ -325,7 +321,7 @@ static inline int is_node(struct page *page, int type) | |||
325 | 321 | ||
326 | static inline void set_cold_node(struct inode *inode, struct page *page) | 322 | static inline void set_cold_node(struct inode *inode, struct page *page) |
327 | { | 323 | { |
328 | struct f2fs_node *rn = (struct f2fs_node *)page_address(page); | 324 | struct f2fs_node *rn = F2FS_NODE(page); |
329 | unsigned int flag = le32_to_cpu(rn->footer.flag); | 325 | unsigned int flag = le32_to_cpu(rn->footer.flag); |
330 | 326 | ||
331 | if (S_ISDIR(inode->i_mode)) | 327 | if (S_ISDIR(inode->i_mode)) |
@@ -337,7 +333,7 @@ static inline void set_cold_node(struct inode *inode, struct page *page) | |||
337 | 333 | ||
338 | static inline void set_mark(struct page *page, int mark, int type) | 334 | static inline void set_mark(struct page *page, int mark, int type) |
339 | { | 335 | { |
340 | struct f2fs_node *rn = (struct f2fs_node *)page_address(page); | 336 | struct f2fs_node *rn = F2FS_NODE(page); |
341 | unsigned int flag = le32_to_cpu(rn->footer.flag); | 337 | unsigned int flag = le32_to_cpu(rn->footer.flag); |
342 | if (mark) | 338 | if (mark) |
343 | flag |= (0x1 << type); | 339 | flag |= (0x1 << type); |
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index d56d951c2253..51ef5eec33d7 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -40,8 +40,7 @@ static struct fsync_inode_entry *get_fsync_inode(struct list_head *head, | |||
40 | 40 | ||
41 | static int recover_dentry(struct page *ipage, struct inode *inode) | 41 | static int recover_dentry(struct page *ipage, struct inode *inode) |
42 | { | 42 | { |
43 | void *kaddr = page_address(ipage); | 43 | struct f2fs_node *raw_node = F2FS_NODE(ipage); |
44 | struct f2fs_node *raw_node = (struct f2fs_node *)kaddr; | ||
45 | struct f2fs_inode *raw_inode = &(raw_node->i); | 44 | struct f2fs_inode *raw_inode = &(raw_node->i); |
46 | nid_t pino = le32_to_cpu(raw_inode->i_pino); | 45 | nid_t pino = le32_to_cpu(raw_inode->i_pino); |
47 | struct f2fs_dir_entry *de; | 46 | struct f2fs_dir_entry *de; |
@@ -93,8 +92,7 @@ out: | |||
93 | 92 | ||
94 | static int recover_inode(struct inode *inode, struct page *node_page) | 93 | static int recover_inode(struct inode *inode, struct page *node_page) |
95 | { | 94 | { |
96 | void *kaddr = page_address(node_page); | 95 | struct f2fs_node *raw_node = F2FS_NODE(node_page); |
97 | struct f2fs_node *raw_node = (struct f2fs_node *)kaddr; | ||
98 | struct f2fs_inode *raw_inode = &(raw_node->i); | 96 | struct f2fs_inode *raw_inode = &(raw_node->i); |
99 | 97 | ||
100 | if (!IS_INODE(node_page)) | 98 | if (!IS_INODE(node_page)) |
@@ -119,7 +117,7 @@ static int recover_inode(struct inode *inode, struct page *node_page) | |||
119 | 117 | ||
120 | static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | 118 | static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) |
121 | { | 119 | { |
122 | unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver); | 120 | unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); |
123 | struct curseg_info *curseg; | 121 | struct curseg_info *curseg; |
124 | struct page *page; | 122 | struct page *page; |
125 | block_t blkaddr; | 123 | block_t blkaddr; |
@@ -131,8 +129,8 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
131 | 129 | ||
132 | /* read node page */ | 130 | /* read node page */ |
133 | page = alloc_page(GFP_F2FS_ZERO); | 131 | page = alloc_page(GFP_F2FS_ZERO); |
134 | if (IS_ERR(page)) | 132 | if (!page) |
135 | return PTR_ERR(page); | 133 | return -ENOMEM; |
136 | lock_page(page); | 134 | lock_page(page); |
137 | 135 | ||
138 | while (1) { | 136 | while (1) { |
@@ -215,6 +213,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
215 | void *kaddr; | 213 | void *kaddr; |
216 | struct inode *inode; | 214 | struct inode *inode; |
217 | struct page *node_page; | 215 | struct page *node_page; |
216 | unsigned int offset; | ||
218 | block_t bidx; | 217 | block_t bidx; |
219 | int i; | 218 | int i; |
220 | 219 | ||
@@ -259,8 +258,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
259 | node_page = get_node_page(sbi, nid); | 258 | node_page = get_node_page(sbi, nid); |
260 | if (IS_ERR(node_page)) | 259 | if (IS_ERR(node_page)) |
261 | return PTR_ERR(node_page); | 260 | return PTR_ERR(node_page); |
262 | bidx = start_bidx_of_node(ofs_of_node(node_page)) + | 261 | |
263 | le16_to_cpu(sum.ofs_in_node); | 262 | offset = ofs_of_node(node_page); |
264 | ino = ino_of_node(node_page); | 263 | ino = ino_of_node(node_page); |
265 | f2fs_put_page(node_page, 1); | 264 | f2fs_put_page(node_page, 1); |
266 | 265 | ||
@@ -269,6 +268,9 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
269 | if (IS_ERR(inode)) | 268 | if (IS_ERR(inode)) |
270 | return PTR_ERR(inode); | 269 | return PTR_ERR(inode); |
271 | 270 | ||
271 | bidx = start_bidx_of_node(offset, F2FS_I(inode)) + | ||
272 | le16_to_cpu(sum.ofs_in_node); | ||
273 | |||
272 | truncate_hole(inode, bidx, bidx + 1); | 274 | truncate_hole(inode, bidx, bidx + 1); |
273 | iput(inode); | 275 | iput(inode); |
274 | return 0; | 276 | return 0; |
@@ -277,6 +279,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
277 | 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, |
278 | struct page *page, block_t blkaddr) | 280 | struct page *page, block_t blkaddr) |
279 | { | 281 | { |
282 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
280 | unsigned int start, end; | 283 | unsigned int start, end; |
281 | struct dnode_of_data dn; | 284 | struct dnode_of_data dn; |
282 | struct f2fs_summary sum; | 285 | struct f2fs_summary sum; |
@@ -284,9 +287,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
284 | int err = 0, recovered = 0; | 287 | int err = 0, recovered = 0; |
285 | int ilock; | 288 | int ilock; |
286 | 289 | ||
287 | start = start_bidx_of_node(ofs_of_node(page)); | 290 | start = start_bidx_of_node(ofs_of_node(page), fi); |
288 | if (IS_INODE(page)) | 291 | if (IS_INODE(page)) |
289 | end = start + ADDRS_PER_INODE; | 292 | end = start + ADDRS_PER_INODE(fi); |
290 | else | 293 | else |
291 | end = start + ADDRS_PER_BLOCK; | 294 | end = start + ADDRS_PER_BLOCK; |
292 | 295 | ||
@@ -357,7 +360,7 @@ err: | |||
357 | static int recover_data(struct f2fs_sb_info *sbi, | 360 | static int recover_data(struct f2fs_sb_info *sbi, |
358 | struct list_head *head, int type) | 361 | struct list_head *head, int type) |
359 | { | 362 | { |
360 | unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver); | 363 | unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); |
361 | struct curseg_info *curseg; | 364 | struct curseg_info *curseg; |
362 | struct page *page; | 365 | struct page *page; |
363 | int err = 0; | 366 | int err = 0; |
@@ -369,7 +372,7 @@ static int recover_data(struct f2fs_sb_info *sbi, | |||
369 | 372 | ||
370 | /* read node page */ | 373 | /* read node page */ |
371 | page = alloc_page(GFP_NOFS | __GFP_ZERO); | 374 | page = alloc_page(GFP_NOFS | __GFP_ZERO); |
372 | if (IS_ERR(page)) | 375 | if (!page) |
373 | return -ENOMEM; | 376 | return -ENOMEM; |
374 | 377 | ||
375 | lock_page(page); | 378 | lock_page(page); |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index a86d125a9885..09af9c7b0f52 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -117,7 +117,6 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | |||
117 | } | 117 | } |
118 | 118 | ||
119 | mutex_unlock(&dirty_i->seglist_lock); | 119 | mutex_unlock(&dirty_i->seglist_lock); |
120 | return; | ||
121 | } | 120 | } |
122 | 121 | ||
123 | /* | 122 | /* |
@@ -261,7 +260,6 @@ static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, | |||
261 | void *addr = curseg->sum_blk; | 260 | void *addr = curseg->sum_blk; |
262 | addr += curseg->next_blkoff * sizeof(struct f2fs_summary); | 261 | addr += curseg->next_blkoff * sizeof(struct f2fs_summary); |
263 | memcpy(addr, sum, sizeof(struct f2fs_summary)); | 262 | memcpy(addr, sum, sizeof(struct f2fs_summary)); |
264 | return; | ||
265 | } | 263 | } |
266 | 264 | ||
267 | /* | 265 | /* |
@@ -542,12 +540,9 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | |||
542 | { | 540 | { |
543 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 541 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
544 | 542 | ||
545 | if (force) { | 543 | if (force) |
546 | new_curseg(sbi, type, true); | 544 | new_curseg(sbi, type, true); |
547 | goto out; | 545 | else if (type == CURSEG_WARM_NODE) |
548 | } | ||
549 | |||
550 | if (type == CURSEG_WARM_NODE) | ||
551 | new_curseg(sbi, type, false); | 546 | new_curseg(sbi, type, false); |
552 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) | 547 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) |
553 | new_curseg(sbi, type, false); | 548 | new_curseg(sbi, type, false); |
@@ -555,11 +550,9 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | |||
555 | change_curseg(sbi, type, true); | 550 | change_curseg(sbi, type, true); |
556 | else | 551 | else |
557 | new_curseg(sbi, type, false); | 552 | new_curseg(sbi, type, false); |
558 | out: | ||
559 | #ifdef CONFIG_F2FS_STAT_FS | 553 | #ifdef CONFIG_F2FS_STAT_FS |
560 | sbi->segment_count[curseg->alloc_type]++; | 554 | sbi->segment_count[curseg->alloc_type]++; |
561 | #endif | 555 | #endif |
562 | return; | ||
563 | } | 556 | } |
564 | 557 | ||
565 | void allocate_new_segments(struct f2fs_sb_info *sbi) | 558 | void allocate_new_segments(struct f2fs_sb_info *sbi) |
@@ -611,18 +604,12 @@ static void f2fs_end_io_write(struct bio *bio, int err) | |||
611 | struct bio *f2fs_bio_alloc(struct block_device *bdev, int npages) | 604 | struct bio *f2fs_bio_alloc(struct block_device *bdev, int npages) |
612 | { | 605 | { |
613 | struct bio *bio; | 606 | struct bio *bio; |
614 | struct bio_private *priv; | ||
615 | retry: | ||
616 | priv = kmalloc(sizeof(struct bio_private), GFP_NOFS); | ||
617 | if (!priv) { | ||
618 | cond_resched(); | ||
619 | goto retry; | ||
620 | } | ||
621 | 607 | ||
622 | /* No failure on bio allocation */ | 608 | /* No failure on bio allocation */ |
623 | bio = bio_alloc(GFP_NOIO, npages); | 609 | bio = bio_alloc(GFP_NOIO, npages); |
624 | bio->bi_bdev = bdev; | 610 | bio->bi_bdev = bdev; |
625 | bio->bi_private = priv; | 611 | bio->bi_private = NULL; |
612 | |||
626 | return bio; | 613 | return bio; |
627 | } | 614 | } |
628 | 615 | ||
@@ -681,8 +668,17 @@ static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page, | |||
681 | do_submit_bio(sbi, type, false); | 668 | do_submit_bio(sbi, type, false); |
682 | alloc_new: | 669 | alloc_new: |
683 | if (sbi->bio[type] == NULL) { | 670 | if (sbi->bio[type] == NULL) { |
671 | struct bio_private *priv; | ||
672 | retry: | ||
673 | priv = kmalloc(sizeof(struct bio_private), GFP_NOFS); | ||
674 | if (!priv) { | ||
675 | cond_resched(); | ||
676 | goto retry; | ||
677 | } | ||
678 | |||
684 | sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi)); | 679 | sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi)); |
685 | sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); | 680 | sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); |
681 | sbi->bio[type]->bi_private = priv; | ||
686 | /* | 682 | /* |
687 | * The end_io will be assigned at the sumbission phase. | 683 | * The end_io will be assigned at the sumbission phase. |
688 | * Until then, let bio_add_page() merge consecutive IOs as much | 684 | * Until then, let bio_add_page() merge consecutive IOs as much |
@@ -702,6 +698,16 @@ alloc_new: | |||
702 | trace_f2fs_submit_write_page(page, blk_addr, type); | 698 | trace_f2fs_submit_write_page(page, blk_addr, type); |
703 | } | 699 | } |
704 | 700 | ||
701 | void f2fs_wait_on_page_writeback(struct page *page, | ||
702 | enum page_type type, bool sync) | ||
703 | { | ||
704 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); | ||
705 | if (PageWriteback(page)) { | ||
706 | f2fs_submit_bio(sbi, type, sync); | ||
707 | wait_on_page_writeback(page); | ||
708 | } | ||
709 | } | ||
710 | |||
705 | static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type) | 711 | static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type) |
706 | { | 712 | { |
707 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 713 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
@@ -1179,7 +1185,6 @@ void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk) | |||
1179 | { | 1185 | { |
1180 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) | 1186 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) |
1181 | write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); | 1187 | write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); |
1182 | return; | ||
1183 | } | 1188 | } |
1184 | 1189 | ||
1185 | int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type, | 1190 | int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type, |
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 062424a0e4c3..bdd10eab8c40 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h | |||
@@ -142,6 +142,7 @@ struct victim_sel_policy { | |||
142 | int alloc_mode; /* LFS or SSR */ | 142 | int alloc_mode; /* LFS or SSR */ |
143 | int gc_mode; /* GC_CB or GC_GREEDY */ | 143 | int gc_mode; /* GC_CB or GC_GREEDY */ |
144 | unsigned long *dirty_segmap; /* dirty segment bitmap */ | 144 | unsigned long *dirty_segmap; /* dirty segment bitmap */ |
145 | unsigned int max_search; /* maximum # of segments to search */ | ||
145 | unsigned int offset; /* last scanned bitmap offset */ | 146 | unsigned int offset; /* last scanned bitmap offset */ |
146 | unsigned int ofs_unit; /* bitmap search unit */ | 147 | unsigned int ofs_unit; /* bitmap search unit */ |
147 | unsigned int min_cost; /* minimum cost */ | 148 | unsigned int min_cost; /* minimum cost */ |
@@ -453,7 +454,8 @@ static inline int reserved_sections(struct f2fs_sb_info *sbi) | |||
453 | 454 | ||
454 | static inline bool need_SSR(struct f2fs_sb_info *sbi) | 455 | static inline bool need_SSR(struct f2fs_sb_info *sbi) |
455 | { | 456 | { |
456 | return (free_sections(sbi) < overprovision_sections(sbi)); | 457 | return ((prefree_segments(sbi) / sbi->segs_per_sec) |
458 | + free_sections(sbi) < overprovision_sections(sbi)); | ||
457 | } | 459 | } |
458 | 460 | ||
459 | static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) | 461 | static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) |
@@ -470,7 +472,7 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) | |||
470 | 472 | ||
471 | static inline int utilization(struct f2fs_sb_info *sbi) | 473 | static inline int utilization(struct f2fs_sb_info *sbi) |
472 | { | 474 | { |
473 | return div_u64(valid_user_blocks(sbi) * 100, sbi->user_block_count); | 475 | return div_u64((u64)valid_user_blocks(sbi) * 100, sbi->user_block_count); |
474 | } | 476 | } |
475 | 477 | ||
476 | /* | 478 | /* |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 75c7dc363e92..13d0a0fe49dd 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -18,20 +18,25 @@ | |||
18 | #include <linux/parser.h> | 18 | #include <linux/parser.h> |
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | #include <linux/proc_fs.h> | ||
21 | #include <linux/random.h> | 22 | #include <linux/random.h> |
22 | #include <linux/exportfs.h> | 23 | #include <linux/exportfs.h> |
23 | #include <linux/blkdev.h> | 24 | #include <linux/blkdev.h> |
24 | #include <linux/f2fs_fs.h> | 25 | #include <linux/f2fs_fs.h> |
26 | #include <linux/sysfs.h> | ||
25 | 27 | ||
26 | #include "f2fs.h" | 28 | #include "f2fs.h" |
27 | #include "node.h" | 29 | #include "node.h" |
28 | #include "segment.h" | 30 | #include "segment.h" |
29 | #include "xattr.h" | 31 | #include "xattr.h" |
32 | #include "gc.h" | ||
30 | 33 | ||
31 | #define CREATE_TRACE_POINTS | 34 | #define CREATE_TRACE_POINTS |
32 | #include <trace/events/f2fs.h> | 35 | #include <trace/events/f2fs.h> |
33 | 36 | ||
37 | static struct proc_dir_entry *f2fs_proc_root; | ||
34 | static struct kmem_cache *f2fs_inode_cachep; | 38 | static struct kmem_cache *f2fs_inode_cachep; |
39 | static struct kset *f2fs_kset; | ||
35 | 40 | ||
36 | enum { | 41 | enum { |
37 | Opt_gc_background, | 42 | Opt_gc_background, |
@@ -42,6 +47,7 @@ enum { | |||
42 | Opt_noacl, | 47 | Opt_noacl, |
43 | Opt_active_logs, | 48 | Opt_active_logs, |
44 | Opt_disable_ext_identify, | 49 | Opt_disable_ext_identify, |
50 | Opt_inline_xattr, | ||
45 | Opt_err, | 51 | Opt_err, |
46 | }; | 52 | }; |
47 | 53 | ||
@@ -54,9 +60,117 @@ static match_table_t f2fs_tokens = { | |||
54 | {Opt_noacl, "noacl"}, | 60 | {Opt_noacl, "noacl"}, |
55 | {Opt_active_logs, "active_logs=%u"}, | 61 | {Opt_active_logs, "active_logs=%u"}, |
56 | {Opt_disable_ext_identify, "disable_ext_identify"}, | 62 | {Opt_disable_ext_identify, "disable_ext_identify"}, |
63 | {Opt_inline_xattr, "inline_xattr"}, | ||
57 | {Opt_err, NULL}, | 64 | {Opt_err, NULL}, |
58 | }; | 65 | }; |
59 | 66 | ||
67 | /* Sysfs support for f2fs */ | ||
68 | struct f2fs_attr { | ||
69 | struct attribute attr; | ||
70 | ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *); | ||
71 | ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *, | ||
72 | const char *, size_t); | ||
73 | int offset; | ||
74 | }; | ||
75 | |||
76 | static ssize_t f2fs_sbi_show(struct f2fs_attr *a, | ||
77 | struct f2fs_sb_info *sbi, char *buf) | ||
78 | { | ||
79 | struct f2fs_gc_kthread *gc_kth = sbi->gc_thread; | ||
80 | unsigned int *ui; | ||
81 | |||
82 | if (!gc_kth) | ||
83 | return -EINVAL; | ||
84 | |||
85 | ui = (unsigned int *)(((char *)gc_kth) + a->offset); | ||
86 | |||
87 | return snprintf(buf, PAGE_SIZE, "%u\n", *ui); | ||
88 | } | ||
89 | |||
90 | static ssize_t f2fs_sbi_store(struct f2fs_attr *a, | ||
91 | struct f2fs_sb_info *sbi, | ||
92 | const char *buf, size_t count) | ||
93 | { | ||
94 | struct f2fs_gc_kthread *gc_kth = sbi->gc_thread; | ||
95 | unsigned long t; | ||
96 | unsigned int *ui; | ||
97 | ssize_t ret; | ||
98 | |||
99 | if (!gc_kth) | ||
100 | return -EINVAL; | ||
101 | |||
102 | ui = (unsigned int *)(((char *)gc_kth) + a->offset); | ||
103 | |||
104 | ret = kstrtoul(skip_spaces(buf), 0, &t); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | *ui = t; | ||
108 | return count; | ||
109 | } | ||
110 | |||
111 | static ssize_t f2fs_attr_show(struct kobject *kobj, | ||
112 | struct attribute *attr, char *buf) | ||
113 | { | ||
114 | struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, | ||
115 | s_kobj); | ||
116 | struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); | ||
117 | |||
118 | return a->show ? a->show(a, sbi, buf) : 0; | ||
119 | } | ||
120 | |||
121 | static ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr, | ||
122 | const char *buf, size_t len) | ||
123 | { | ||
124 | struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, | ||
125 | s_kobj); | ||
126 | struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); | ||
127 | |||
128 | return a->store ? a->store(a, sbi, buf, len) : 0; | ||
129 | } | ||
130 | |||
131 | static void f2fs_sb_release(struct kobject *kobj) | ||
132 | { | ||
133 | struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, | ||
134 | s_kobj); | ||
135 | complete(&sbi->s_kobj_unregister); | ||
136 | } | ||
137 | |||
138 | #define F2FS_ATTR_OFFSET(_name, _mode, _show, _store, _elname) \ | ||
139 | static struct f2fs_attr f2fs_attr_##_name = { \ | ||
140 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
141 | .show = _show, \ | ||
142 | .store = _store, \ | ||
143 | .offset = offsetof(struct f2fs_gc_kthread, _elname), \ | ||
144 | } | ||
145 | |||
146 | #define F2FS_RW_ATTR(name, elname) \ | ||
147 | F2FS_ATTR_OFFSET(name, 0644, f2fs_sbi_show, f2fs_sbi_store, elname) | ||
148 | |||
149 | F2FS_RW_ATTR(gc_min_sleep_time, min_sleep_time); | ||
150 | F2FS_RW_ATTR(gc_max_sleep_time, max_sleep_time); | ||
151 | F2FS_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time); | ||
152 | F2FS_RW_ATTR(gc_idle, gc_idle); | ||
153 | |||
154 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) | ||
155 | static struct attribute *f2fs_attrs[] = { | ||
156 | ATTR_LIST(gc_min_sleep_time), | ||
157 | ATTR_LIST(gc_max_sleep_time), | ||
158 | ATTR_LIST(gc_no_gc_sleep_time), | ||
159 | ATTR_LIST(gc_idle), | ||
160 | NULL, | ||
161 | }; | ||
162 | |||
163 | static const struct sysfs_ops f2fs_attr_ops = { | ||
164 | .show = f2fs_attr_show, | ||
165 | .store = f2fs_attr_store, | ||
166 | }; | ||
167 | |||
168 | static struct kobj_type f2fs_ktype = { | ||
169 | .default_attrs = f2fs_attrs, | ||
170 | .sysfs_ops = &f2fs_attr_ops, | ||
171 | .release = f2fs_sb_release, | ||
172 | }; | ||
173 | |||
60 | void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) | 174 | void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) |
61 | { | 175 | { |
62 | struct va_format vaf; | 176 | struct va_format vaf; |
@@ -126,11 +240,18 @@ static int parse_options(struct super_block *sb, char *options) | |||
126 | case Opt_nouser_xattr: | 240 | case Opt_nouser_xattr: |
127 | clear_opt(sbi, XATTR_USER); | 241 | clear_opt(sbi, XATTR_USER); |
128 | break; | 242 | break; |
243 | case Opt_inline_xattr: | ||
244 | set_opt(sbi, INLINE_XATTR); | ||
245 | break; | ||
129 | #else | 246 | #else |
130 | case Opt_nouser_xattr: | 247 | case Opt_nouser_xattr: |
131 | f2fs_msg(sb, KERN_INFO, | 248 | f2fs_msg(sb, KERN_INFO, |
132 | "nouser_xattr options not supported"); | 249 | "nouser_xattr options not supported"); |
133 | break; | 250 | break; |
251 | case Opt_inline_xattr: | ||
252 | f2fs_msg(sb, KERN_INFO, | ||
253 | "inline_xattr options not supported"); | ||
254 | break; | ||
134 | #endif | 255 | #endif |
135 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 256 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
136 | case Opt_noacl: | 257 | case Opt_noacl: |
@@ -180,6 +301,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) | |||
180 | 301 | ||
181 | set_inode_flag(fi, FI_NEW_INODE); | 302 | set_inode_flag(fi, FI_NEW_INODE); |
182 | 303 | ||
304 | if (test_opt(F2FS_SB(sb), INLINE_XATTR)) | ||
305 | set_inode_flag(fi, FI_INLINE_XATTR); | ||
306 | |||
183 | return &fi->vfs_inode; | 307 | return &fi->vfs_inode; |
184 | } | 308 | } |
185 | 309 | ||
@@ -205,7 +329,6 @@ static int f2fs_drop_inode(struct inode *inode) | |||
205 | static void f2fs_dirty_inode(struct inode *inode, int flags) | 329 | static void f2fs_dirty_inode(struct inode *inode, int flags) |
206 | { | 330 | { |
207 | set_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); | 331 | set_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); |
208 | return; | ||
209 | } | 332 | } |
210 | 333 | ||
211 | static void f2fs_i_callback(struct rcu_head *head) | 334 | static void f2fs_i_callback(struct rcu_head *head) |
@@ -223,6 +346,12 @@ static void f2fs_put_super(struct super_block *sb) | |||
223 | { | 346 | { |
224 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 347 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
225 | 348 | ||
349 | if (sbi->s_proc) { | ||
350 | remove_proc_entry("segment_info", sbi->s_proc); | ||
351 | remove_proc_entry(sb->s_id, f2fs_proc_root); | ||
352 | } | ||
353 | kobject_del(&sbi->s_kobj); | ||
354 | |||
226 | f2fs_destroy_stats(sbi); | 355 | f2fs_destroy_stats(sbi); |
227 | stop_gc_thread(sbi); | 356 | stop_gc_thread(sbi); |
228 | 357 | ||
@@ -236,6 +365,8 @@ static void f2fs_put_super(struct super_block *sb) | |||
236 | destroy_segment_manager(sbi); | 365 | destroy_segment_manager(sbi); |
237 | 366 | ||
238 | kfree(sbi->ckpt); | 367 | kfree(sbi->ckpt); |
368 | kobject_put(&sbi->s_kobj); | ||
369 | wait_for_completion(&sbi->s_kobj_unregister); | ||
239 | 370 | ||
240 | sb->s_fs_info = NULL; | 371 | sb->s_fs_info = NULL; |
241 | brelse(sbi->raw_super_buf); | 372 | brelse(sbi->raw_super_buf); |
@@ -325,6 +456,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) | |||
325 | seq_puts(seq, ",user_xattr"); | 456 | seq_puts(seq, ",user_xattr"); |
326 | else | 457 | else |
327 | seq_puts(seq, ",nouser_xattr"); | 458 | seq_puts(seq, ",nouser_xattr"); |
459 | if (test_opt(sbi, INLINE_XATTR)) | ||
460 | seq_puts(seq, ",inline_xattr"); | ||
328 | #endif | 461 | #endif |
329 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 462 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
330 | if (test_opt(sbi, POSIX_ACL)) | 463 | if (test_opt(sbi, POSIX_ACL)) |
@@ -340,6 +473,36 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) | |||
340 | return 0; | 473 | return 0; |
341 | } | 474 | } |
342 | 475 | ||
476 | static int segment_info_seq_show(struct seq_file *seq, void *offset) | ||
477 | { | ||
478 | struct super_block *sb = seq->private; | ||
479 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
480 | unsigned int total_segs = le32_to_cpu(sbi->raw_super->segment_count_main); | ||
481 | int i; | ||
482 | |||
483 | for (i = 0; i < total_segs; i++) { | ||
484 | seq_printf(seq, "%u", get_valid_blocks(sbi, i, 1)); | ||
485 | if (i != 0 && (i % 10) == 0) | ||
486 | seq_puts(seq, "\n"); | ||
487 | else | ||
488 | seq_puts(seq, " "); | ||
489 | } | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | static int segment_info_open_fs(struct inode *inode, struct file *file) | ||
494 | { | ||
495 | return single_open(file, segment_info_seq_show, PDE_DATA(inode)); | ||
496 | } | ||
497 | |||
498 | static const struct file_operations f2fs_seq_segment_info_fops = { | ||
499 | .owner = THIS_MODULE, | ||
500 | .open = segment_info_open_fs, | ||
501 | .read = seq_read, | ||
502 | .llseek = seq_lseek, | ||
503 | .release = single_release, | ||
504 | }; | ||
505 | |||
343 | static int f2fs_remount(struct super_block *sb, int *flags, char *data) | 506 | static int f2fs_remount(struct super_block *sb, int *flags, char *data) |
344 | { | 507 | { |
345 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 508 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
@@ -455,7 +618,7 @@ static const struct export_operations f2fs_export_ops = { | |||
455 | 618 | ||
456 | static loff_t max_file_size(unsigned bits) | 619 | static loff_t max_file_size(unsigned bits) |
457 | { | 620 | { |
458 | loff_t result = ADDRS_PER_INODE; | 621 | loff_t result = (DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS); |
459 | loff_t leaf_count = ADDRS_PER_BLOCK; | 622 | loff_t leaf_count = ADDRS_PER_BLOCK; |
460 | 623 | ||
461 | /* two direct node blocks */ | 624 | /* two direct node blocks */ |
@@ -766,6 +929,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
766 | if (err) | 929 | if (err) |
767 | goto fail; | 930 | goto fail; |
768 | 931 | ||
932 | if (f2fs_proc_root) | ||
933 | sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); | ||
934 | |||
935 | if (sbi->s_proc) | ||
936 | proc_create_data("segment_info", S_IRUGO, sbi->s_proc, | ||
937 | &f2fs_seq_segment_info_fops, sb); | ||
938 | |||
769 | if (test_opt(sbi, DISCARD)) { | 939 | if (test_opt(sbi, DISCARD)) { |
770 | struct request_queue *q = bdev_get_queue(sb->s_bdev); | 940 | struct request_queue *q = bdev_get_queue(sb->s_bdev); |
771 | if (!blk_queue_discard(q)) | 941 | if (!blk_queue_discard(q)) |
@@ -774,6 +944,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
774 | "the device does not support discard"); | 944 | "the device does not support discard"); |
775 | } | 945 | } |
776 | 946 | ||
947 | sbi->s_kobj.kset = f2fs_kset; | ||
948 | init_completion(&sbi->s_kobj_unregister); | ||
949 | err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL, | ||
950 | "%s", sb->s_id); | ||
951 | if (err) | ||
952 | goto fail; | ||
953 | |||
777 | return 0; | 954 | return 0; |
778 | fail: | 955 | fail: |
779 | stop_gc_thread(sbi); | 956 | stop_gc_thread(sbi); |
@@ -841,29 +1018,49 @@ static int __init init_f2fs_fs(void) | |||
841 | goto fail; | 1018 | goto fail; |
842 | err = create_node_manager_caches(); | 1019 | err = create_node_manager_caches(); |
843 | if (err) | 1020 | if (err) |
844 | goto fail; | 1021 | goto free_inodecache; |
845 | err = create_gc_caches(); | 1022 | err = create_gc_caches(); |
846 | if (err) | 1023 | if (err) |
847 | goto fail; | 1024 | goto free_node_manager_caches; |
848 | err = create_checkpoint_caches(); | 1025 | err = create_checkpoint_caches(); |
849 | if (err) | 1026 | if (err) |
850 | goto fail; | 1027 | goto free_gc_caches; |
1028 | f2fs_kset = kset_create_and_add("f2fs", NULL, fs_kobj); | ||
1029 | if (!f2fs_kset) { | ||
1030 | err = -ENOMEM; | ||
1031 | goto free_checkpoint_caches; | ||
1032 | } | ||
851 | err = register_filesystem(&f2fs_fs_type); | 1033 | err = register_filesystem(&f2fs_fs_type); |
852 | if (err) | 1034 | if (err) |
853 | goto fail; | 1035 | goto free_kset; |
854 | f2fs_create_root_stats(); | 1036 | f2fs_create_root_stats(); |
1037 | f2fs_proc_root = proc_mkdir("fs/f2fs", NULL); | ||
1038 | return 0; | ||
1039 | |||
1040 | free_kset: | ||
1041 | kset_unregister(f2fs_kset); | ||
1042 | free_checkpoint_caches: | ||
1043 | destroy_checkpoint_caches(); | ||
1044 | free_gc_caches: | ||
1045 | destroy_gc_caches(); | ||
1046 | free_node_manager_caches: | ||
1047 | destroy_node_manager_caches(); | ||
1048 | free_inodecache: | ||
1049 | destroy_inodecache(); | ||
855 | fail: | 1050 | fail: |
856 | return err; | 1051 | return err; |
857 | } | 1052 | } |
858 | 1053 | ||
859 | static void __exit exit_f2fs_fs(void) | 1054 | static void __exit exit_f2fs_fs(void) |
860 | { | 1055 | { |
1056 | remove_proc_entry("fs/f2fs", NULL); | ||
861 | f2fs_destroy_root_stats(); | 1057 | f2fs_destroy_root_stats(); |
862 | unregister_filesystem(&f2fs_fs_type); | 1058 | unregister_filesystem(&f2fs_fs_type); |
863 | destroy_checkpoint_caches(); | 1059 | destroy_checkpoint_caches(); |
864 | destroy_gc_caches(); | 1060 | destroy_gc_caches(); |
865 | destroy_node_manager_caches(); | 1061 | destroy_node_manager_caches(); |
866 | destroy_inodecache(); | 1062 | destroy_inodecache(); |
1063 | kset_unregister(f2fs_kset); | ||
867 | } | 1064 | } |
868 | 1065 | ||
869 | module_init(init_f2fs_fs) | 1066 | module_init(init_f2fs_fs) |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 3ab07ecd86ca..1ac8a5f6e380 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -246,40 +246,170 @@ static inline const struct xattr_handler *f2fs_xattr_handler(int name_index) | |||
246 | return handler; | 246 | return handler; |
247 | } | 247 | } |
248 | 248 | ||
249 | static struct f2fs_xattr_entry *__find_xattr(void *base_addr, int name_index, | ||
250 | size_t name_len, const char *name) | ||
251 | { | ||
252 | struct f2fs_xattr_entry *entry; | ||
253 | |||
254 | list_for_each_xattr(entry, base_addr) { | ||
255 | if (entry->e_name_index != name_index) | ||
256 | continue; | ||
257 | if (entry->e_name_len != name_len) | ||
258 | continue; | ||
259 | if (!memcmp(entry->e_name, name, name_len)) | ||
260 | break; | ||
261 | } | ||
262 | return entry; | ||
263 | } | ||
264 | |||
265 | static void *read_all_xattrs(struct inode *inode, struct page *ipage) | ||
266 | { | ||
267 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
268 | struct f2fs_xattr_header *header; | ||
269 | size_t size = PAGE_SIZE, inline_size = 0; | ||
270 | void *txattr_addr; | ||
271 | |||
272 | inline_size = inline_xattr_size(inode); | ||
273 | |||
274 | txattr_addr = kzalloc(inline_size + size, GFP_KERNEL); | ||
275 | if (!txattr_addr) | ||
276 | return NULL; | ||
277 | |||
278 | /* read from inline xattr */ | ||
279 | if (inline_size) { | ||
280 | struct page *page = NULL; | ||
281 | void *inline_addr; | ||
282 | |||
283 | if (ipage) { | ||
284 | inline_addr = inline_xattr_addr(ipage); | ||
285 | } else { | ||
286 | page = get_node_page(sbi, inode->i_ino); | ||
287 | if (IS_ERR(page)) | ||
288 | goto fail; | ||
289 | inline_addr = inline_xattr_addr(page); | ||
290 | } | ||
291 | memcpy(txattr_addr, inline_addr, inline_size); | ||
292 | f2fs_put_page(page, 1); | ||
293 | } | ||
294 | |||
295 | /* read from xattr node block */ | ||
296 | if (F2FS_I(inode)->i_xattr_nid) { | ||
297 | struct page *xpage; | ||
298 | void *xattr_addr; | ||
299 | |||
300 | /* The inode already has an extended attribute block. */ | ||
301 | xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); | ||
302 | if (IS_ERR(xpage)) | ||
303 | goto fail; | ||
304 | |||
305 | xattr_addr = page_address(xpage); | ||
306 | memcpy(txattr_addr + inline_size, xattr_addr, PAGE_SIZE); | ||
307 | f2fs_put_page(xpage, 1); | ||
308 | } | ||
309 | |||
310 | header = XATTR_HDR(txattr_addr); | ||
311 | |||
312 | /* never been allocated xattrs */ | ||
313 | if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) { | ||
314 | header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC); | ||
315 | header->h_refcount = cpu_to_le32(1); | ||
316 | } | ||
317 | return txattr_addr; | ||
318 | fail: | ||
319 | kzfree(txattr_addr); | ||
320 | return NULL; | ||
321 | } | ||
322 | |||
323 | static inline int write_all_xattrs(struct inode *inode, __u32 hsize, | ||
324 | void *txattr_addr, struct page *ipage) | ||
325 | { | ||
326 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
327 | size_t inline_size = 0; | ||
328 | void *xattr_addr; | ||
329 | struct page *xpage; | ||
330 | nid_t new_nid = 0; | ||
331 | int err; | ||
332 | |||
333 | inline_size = inline_xattr_size(inode); | ||
334 | |||
335 | if (hsize > inline_size && !F2FS_I(inode)->i_xattr_nid) | ||
336 | if (!alloc_nid(sbi, &new_nid)) | ||
337 | return -ENOSPC; | ||
338 | |||
339 | /* write to inline xattr */ | ||
340 | if (inline_size) { | ||
341 | struct page *page = NULL; | ||
342 | void *inline_addr; | ||
343 | |||
344 | if (ipage) { | ||
345 | inline_addr = inline_xattr_addr(ipage); | ||
346 | } else { | ||
347 | page = get_node_page(sbi, inode->i_ino); | ||
348 | if (IS_ERR(page)) { | ||
349 | alloc_nid_failed(sbi, new_nid); | ||
350 | return PTR_ERR(page); | ||
351 | } | ||
352 | inline_addr = inline_xattr_addr(page); | ||
353 | } | ||
354 | memcpy(inline_addr, txattr_addr, inline_size); | ||
355 | f2fs_put_page(page, 1); | ||
356 | |||
357 | /* no need to use xattr node block */ | ||
358 | if (hsize <= inline_size) { | ||
359 | err = truncate_xattr_node(inode, ipage); | ||
360 | alloc_nid_failed(sbi, new_nid); | ||
361 | return err; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /* write to xattr node block */ | ||
366 | if (F2FS_I(inode)->i_xattr_nid) { | ||
367 | xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); | ||
368 | if (IS_ERR(xpage)) { | ||
369 | alloc_nid_failed(sbi, new_nid); | ||
370 | return PTR_ERR(xpage); | ||
371 | } | ||
372 | BUG_ON(new_nid); | ||
373 | } else { | ||
374 | struct dnode_of_data dn; | ||
375 | set_new_dnode(&dn, inode, NULL, NULL, new_nid); | ||
376 | xpage = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); | ||
377 | if (IS_ERR(xpage)) { | ||
378 | alloc_nid_failed(sbi, new_nid); | ||
379 | return PTR_ERR(xpage); | ||
380 | } | ||
381 | alloc_nid_done(sbi, new_nid); | ||
382 | } | ||
383 | |||
384 | xattr_addr = page_address(xpage); | ||
385 | memcpy(xattr_addr, txattr_addr + inline_size, PAGE_SIZE - | ||
386 | sizeof(struct node_footer)); | ||
387 | set_page_dirty(xpage); | ||
388 | f2fs_put_page(xpage, 1); | ||
389 | |||
390 | /* need to checkpoint during fsync */ | ||
391 | F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi)); | ||
392 | return 0; | ||
393 | } | ||
394 | |||
249 | int f2fs_getxattr(struct inode *inode, int name_index, const char *name, | 395 | int f2fs_getxattr(struct inode *inode, int name_index, const char *name, |
250 | void *buffer, size_t buffer_size) | 396 | void *buffer, size_t buffer_size) |
251 | { | 397 | { |
252 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
253 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
254 | struct f2fs_xattr_entry *entry; | 398 | struct f2fs_xattr_entry *entry; |
255 | struct page *page; | ||
256 | void *base_addr; | 399 | void *base_addr; |
257 | int error = 0, found = 0; | 400 | int error = 0; |
258 | size_t value_len, name_len; | 401 | size_t value_len, name_len; |
259 | 402 | ||
260 | if (name == NULL) | 403 | if (name == NULL) |
261 | return -EINVAL; | 404 | return -EINVAL; |
262 | name_len = strlen(name); | 405 | name_len = strlen(name); |
263 | 406 | ||
264 | if (!fi->i_xattr_nid) | 407 | base_addr = read_all_xattrs(inode, NULL); |
265 | return -ENODATA; | 408 | if (!base_addr) |
409 | return -ENOMEM; | ||
266 | 410 | ||
267 | page = get_node_page(sbi, fi->i_xattr_nid); | 411 | entry = __find_xattr(base_addr, name_index, name_len, name); |
268 | if (IS_ERR(page)) | 412 | if (IS_XATTR_LAST_ENTRY(entry)) { |
269 | return PTR_ERR(page); | ||
270 | base_addr = page_address(page); | ||
271 | |||
272 | list_for_each_xattr(entry, base_addr) { | ||
273 | if (entry->e_name_index != name_index) | ||
274 | continue; | ||
275 | if (entry->e_name_len != name_len) | ||
276 | continue; | ||
277 | if (!memcmp(entry->e_name, name, name_len)) { | ||
278 | found = 1; | ||
279 | break; | ||
280 | } | ||
281 | } | ||
282 | if (!found) { | ||
283 | error = -ENODATA; | 413 | error = -ENODATA; |
284 | goto cleanup; | 414 | goto cleanup; |
285 | } | 415 | } |
@@ -298,28 +428,21 @@ int f2fs_getxattr(struct inode *inode, int name_index, const char *name, | |||
298 | error = value_len; | 428 | error = value_len; |
299 | 429 | ||
300 | cleanup: | 430 | cleanup: |
301 | f2fs_put_page(page, 1); | 431 | kzfree(base_addr); |
302 | return error; | 432 | return error; |
303 | } | 433 | } |
304 | 434 | ||
305 | ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | 435 | ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) |
306 | { | 436 | { |
307 | struct inode *inode = dentry->d_inode; | 437 | struct inode *inode = dentry->d_inode; |
308 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
309 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
310 | struct f2fs_xattr_entry *entry; | 438 | struct f2fs_xattr_entry *entry; |
311 | struct page *page; | ||
312 | void *base_addr; | 439 | void *base_addr; |
313 | int error = 0; | 440 | int error = 0; |
314 | size_t rest = buffer_size; | 441 | size_t rest = buffer_size; |
315 | 442 | ||
316 | if (!fi->i_xattr_nid) | 443 | base_addr = read_all_xattrs(inode, NULL); |
317 | return 0; | 444 | if (!base_addr) |
318 | 445 | return -ENOMEM; | |
319 | page = get_node_page(sbi, fi->i_xattr_nid); | ||
320 | if (IS_ERR(page)) | ||
321 | return PTR_ERR(page); | ||
322 | base_addr = page_address(page); | ||
323 | 446 | ||
324 | list_for_each_xattr(entry, base_addr) { | 447 | list_for_each_xattr(entry, base_addr) { |
325 | const struct xattr_handler *handler = | 448 | const struct xattr_handler *handler = |
@@ -342,7 +465,7 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
342 | } | 465 | } |
343 | error = buffer_size - rest; | 466 | error = buffer_size - rest; |
344 | cleanup: | 467 | cleanup: |
345 | f2fs_put_page(page, 1); | 468 | kzfree(base_addr); |
346 | return error; | 469 | return error; |
347 | } | 470 | } |
348 | 471 | ||
@@ -351,14 +474,13 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
351 | { | 474 | { |
352 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 475 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
353 | struct f2fs_inode_info *fi = F2FS_I(inode); | 476 | struct f2fs_inode_info *fi = F2FS_I(inode); |
354 | struct f2fs_xattr_header *header = NULL; | ||
355 | struct f2fs_xattr_entry *here, *last; | 477 | struct f2fs_xattr_entry *here, *last; |
356 | struct page *page; | ||
357 | void *base_addr; | 478 | void *base_addr; |
358 | int error, found, free, newsize; | 479 | int found, newsize; |
359 | size_t name_len; | 480 | size_t name_len; |
360 | char *pval; | ||
361 | int ilock; | 481 | int ilock; |
482 | __u32 new_hsize; | ||
483 | int error = -ENOMEM; | ||
362 | 484 | ||
363 | if (name == NULL) | 485 | if (name == NULL) |
364 | return -EINVAL; | 486 | return -EINVAL; |
@@ -368,67 +490,21 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
368 | 490 | ||
369 | name_len = strlen(name); | 491 | name_len = strlen(name); |
370 | 492 | ||
371 | if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN) | 493 | if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN(inode)) |
372 | return -ERANGE; | 494 | return -ERANGE; |
373 | 495 | ||
374 | f2fs_balance_fs(sbi); | 496 | f2fs_balance_fs(sbi); |
375 | 497 | ||
376 | ilock = mutex_lock_op(sbi); | 498 | ilock = mutex_lock_op(sbi); |
377 | 499 | ||
378 | if (!fi->i_xattr_nid) { | 500 | base_addr = read_all_xattrs(inode, ipage); |
379 | /* Allocate new attribute block */ | 501 | if (!base_addr) |
380 | struct dnode_of_data dn; | 502 | goto exit; |
381 | |||
382 | if (!alloc_nid(sbi, &fi->i_xattr_nid)) { | ||
383 | error = -ENOSPC; | ||
384 | goto exit; | ||
385 | } | ||
386 | set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); | ||
387 | mark_inode_dirty(inode); | ||
388 | |||
389 | page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); | ||
390 | if (IS_ERR(page)) { | ||
391 | alloc_nid_failed(sbi, fi->i_xattr_nid); | ||
392 | fi->i_xattr_nid = 0; | ||
393 | error = PTR_ERR(page); | ||
394 | goto exit; | ||
395 | } | ||
396 | |||
397 | alloc_nid_done(sbi, fi->i_xattr_nid); | ||
398 | base_addr = page_address(page); | ||
399 | header = XATTR_HDR(base_addr); | ||
400 | header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC); | ||
401 | header->h_refcount = cpu_to_le32(1); | ||
402 | } else { | ||
403 | /* The inode already has an extended attribute block. */ | ||
404 | page = get_node_page(sbi, fi->i_xattr_nid); | ||
405 | if (IS_ERR(page)) { | ||
406 | error = PTR_ERR(page); | ||
407 | goto exit; | ||
408 | } | ||
409 | |||
410 | base_addr = page_address(page); | ||
411 | header = XATTR_HDR(base_addr); | ||
412 | } | ||
413 | |||
414 | if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) { | ||
415 | error = -EIO; | ||
416 | goto cleanup; | ||
417 | } | ||
418 | 503 | ||
419 | /* find entry with wanted name. */ | 504 | /* find entry with wanted name. */ |
420 | found = 0; | 505 | here = __find_xattr(base_addr, name_index, name_len, name); |
421 | list_for_each_xattr(here, base_addr) { | ||
422 | if (here->e_name_index != name_index) | ||
423 | continue; | ||
424 | if (here->e_name_len != name_len) | ||
425 | continue; | ||
426 | if (!memcmp(here->e_name, name, name_len)) { | ||
427 | found = 1; | ||
428 | break; | ||
429 | } | ||
430 | } | ||
431 | 506 | ||
507 | found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1; | ||
432 | last = here; | 508 | last = here; |
433 | 509 | ||
434 | while (!IS_XATTR_LAST_ENTRY(last)) | 510 | while (!IS_XATTR_LAST_ENTRY(last)) |
@@ -439,22 +515,25 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
439 | 515 | ||
440 | /* 1. Check space */ | 516 | /* 1. Check space */ |
441 | if (value) { | 517 | if (value) { |
442 | /* If value is NULL, it is remove operation. | 518 | int free; |
519 | /* | ||
520 | * If value is NULL, it is remove operation. | ||
443 | * In case of update operation, we caculate free. | 521 | * In case of update operation, we caculate free. |
444 | */ | 522 | */ |
445 | free = MIN_OFFSET - ((char *)last - (char *)header); | 523 | free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr); |
446 | if (found) | 524 | if (found) |
447 | free = free - ENTRY_SIZE(here); | 525 | free = free - ENTRY_SIZE(here); |
448 | 526 | ||
449 | if (free < newsize) { | 527 | if (free < newsize) { |
450 | error = -ENOSPC; | 528 | error = -ENOSPC; |
451 | goto cleanup; | 529 | goto exit; |
452 | } | 530 | } |
453 | } | 531 | } |
454 | 532 | ||
455 | /* 2. Remove old entry */ | 533 | /* 2. Remove old entry */ |
456 | if (found) { | 534 | if (found) { |
457 | /* If entry is found, remove old entry. | 535 | /* |
536 | * If entry is found, remove old entry. | ||
458 | * If not found, remove operation is not needed. | 537 | * If not found, remove operation is not needed. |
459 | */ | 538 | */ |
460 | struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here); | 539 | struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here); |
@@ -465,10 +544,15 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
465 | memset(last, 0, oldsize); | 544 | memset(last, 0, oldsize); |
466 | } | 545 | } |
467 | 546 | ||
547 | new_hsize = (char *)last - (char *)base_addr; | ||
548 | |||
468 | /* 3. Write new entry */ | 549 | /* 3. Write new entry */ |
469 | if (value) { | 550 | if (value) { |
470 | /* Before we come here, old entry is removed. | 551 | char *pval; |
471 | * We just write new entry. */ | 552 | /* |
553 | * Before we come here, old entry is removed. | ||
554 | * We just write new entry. | ||
555 | */ | ||
472 | memset(last, 0, newsize); | 556 | memset(last, 0, newsize); |
473 | last->e_name_index = name_index; | 557 | last->e_name_index = name_index; |
474 | last->e_name_len = name_len; | 558 | last->e_name_len = name_len; |
@@ -476,26 +560,25 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
476 | pval = last->e_name + name_len; | 560 | pval = last->e_name + name_len; |
477 | memcpy(pval, value, value_len); | 561 | memcpy(pval, value, value_len); |
478 | last->e_value_size = cpu_to_le16(value_len); | 562 | last->e_value_size = cpu_to_le16(value_len); |
563 | new_hsize += newsize; | ||
479 | } | 564 | } |
480 | 565 | ||
481 | set_page_dirty(page); | 566 | error = write_all_xattrs(inode, new_hsize, base_addr, ipage); |
482 | f2fs_put_page(page, 1); | 567 | if (error) |
568 | goto exit; | ||
483 | 569 | ||
484 | if (is_inode_flag_set(fi, FI_ACL_MODE)) { | 570 | if (is_inode_flag_set(fi, FI_ACL_MODE)) { |
485 | inode->i_mode = fi->i_acl_mode; | 571 | inode->i_mode = fi->i_acl_mode; |
486 | inode->i_ctime = CURRENT_TIME; | 572 | inode->i_ctime = CURRENT_TIME; |
487 | clear_inode_flag(fi, FI_ACL_MODE); | 573 | clear_inode_flag(fi, FI_ACL_MODE); |
488 | } | 574 | } |
575 | |||
489 | if (ipage) | 576 | if (ipage) |
490 | update_inode(inode, ipage); | 577 | update_inode(inode, ipage); |
491 | else | 578 | else |
492 | update_inode_page(inode); | 579 | update_inode_page(inode); |
493 | mutex_unlock_op(sbi, ilock); | ||
494 | |||
495 | return 0; | ||
496 | cleanup: | ||
497 | f2fs_put_page(page, 1); | ||
498 | exit: | 580 | exit: |
499 | mutex_unlock_op(sbi, ilock); | 581 | mutex_unlock_op(sbi, ilock); |
582 | kzfree(base_addr); | ||
500 | return error; | 583 | return error; |
501 | } | 584 | } |
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 3c0817bef25d..02a08fb88a15 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h | |||
@@ -51,7 +51,7 @@ struct f2fs_xattr_entry { | |||
51 | 51 | ||
52 | #define XATTR_HDR(ptr) ((struct f2fs_xattr_header *)(ptr)) | 52 | #define XATTR_HDR(ptr) ((struct f2fs_xattr_header *)(ptr)) |
53 | #define XATTR_ENTRY(ptr) ((struct f2fs_xattr_entry *)(ptr)) | 53 | #define XATTR_ENTRY(ptr) ((struct f2fs_xattr_entry *)(ptr)) |
54 | #define XATTR_FIRST_ENTRY(ptr) (XATTR_ENTRY(XATTR_HDR(ptr)+1)) | 54 | #define XATTR_FIRST_ENTRY(ptr) (XATTR_ENTRY(XATTR_HDR(ptr) + 1)) |
55 | #define XATTR_ROUND (3) | 55 | #define XATTR_ROUND (3) |
56 | 56 | ||
57 | #define XATTR_ALIGN(size) ((size + XATTR_ROUND) & ~XATTR_ROUND) | 57 | #define XATTR_ALIGN(size) ((size + XATTR_ROUND) & ~XATTR_ROUND) |
@@ -69,17 +69,16 @@ struct f2fs_xattr_entry { | |||
69 | !IS_XATTR_LAST_ENTRY(entry);\ | 69 | !IS_XATTR_LAST_ENTRY(entry);\ |
70 | entry = XATTR_NEXT_ENTRY(entry)) | 70 | entry = XATTR_NEXT_ENTRY(entry)) |
71 | 71 | ||
72 | #define MIN_OFFSET(i) XATTR_ALIGN(inline_xattr_size(i) + PAGE_SIZE - \ | ||
73 | sizeof(struct node_footer) - sizeof(__u32)) | ||
72 | 74 | ||
73 | #define MIN_OFFSET XATTR_ALIGN(PAGE_SIZE - \ | 75 | #define MAX_VALUE_LEN(i) (MIN_OFFSET(i) - \ |
74 | sizeof(struct node_footer) - \ | 76 | sizeof(struct f2fs_xattr_header) - \ |
75 | sizeof(__u32)) | 77 | sizeof(struct f2fs_xattr_entry)) |
76 | |||
77 | #define MAX_VALUE_LEN (MIN_OFFSET - sizeof(struct f2fs_xattr_header) - \ | ||
78 | sizeof(struct f2fs_xattr_entry)) | ||
79 | 78 | ||
80 | /* | 79 | /* |
81 | * On-disk structure of f2fs_xattr | 80 | * On-disk structure of f2fs_xattr |
82 | * We use only 1 block for xattr. | 81 | * We use inline xattrs space + 1 block for xattr. |
83 | * | 82 | * |
84 | * +--------------------+ | 83 | * +--------------------+ |
85 | * | f2fs_xattr_header | | 84 | * | f2fs_xattr_header | |
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 383d5e39b280..bb942f6d5702 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h | |||
@@ -140,14 +140,24 @@ 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 50 /* 200 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) | ||
154 | |||
155 | #define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ | ||
146 | 156 | ||
147 | struct f2fs_inode { | 157 | struct f2fs_inode { |
148 | __le16 i_mode; /* file mode */ | 158 | __le16 i_mode; /* file mode */ |
149 | __u8 i_advise; /* file hints */ | 159 | __u8 i_advise; /* file hints */ |
150 | __u8 i_reserved; /* reserved */ | 160 | __u8 i_inline; /* file inline flags */ |
151 | __le32 i_uid; /* user ID */ | 161 | __le32 i_uid; /* user ID */ |
152 | __le32 i_gid; /* group ID */ | 162 | __le32 i_gid; /* group ID */ |
153 | __le32 i_links; /* links count */ | 163 | __le32 i_links; /* links count */ |
@@ -170,7 +180,7 @@ struct f2fs_inode { | |||
170 | 180 | ||
171 | struct f2fs_extent i_ext; /* caching a largest extent */ | 181 | struct f2fs_extent i_ext; /* caching a largest extent */ |
172 | 182 | ||
173 | __le32 i_addr[ADDRS_PER_INODE]; /* Pointers to data blocks */ | 183 | __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ |
174 | 184 | ||
175 | __le32 i_nid[5]; /* direct(2), indirect(2), | 185 | __le32 i_nid[5]; /* direct(2), indirect(2), |
176 | double_indirect(1) node id */ | 186 | double_indirect(1) node id */ |