diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-03-08 07:29:23 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-03-20 05:30:06 -0400 |
commit | 393ff91f57c87d48ffed30878be6e3e486d3a00a (patch) | |
tree | c80fe33bcf8546ebce9ab6fc043b99889e67536f /fs/f2fs/recovery.c | |
parent | 25c0a6e529b56ca010e1f46239edd07c1b484b63 (diff) |
f2fs: reduce unncessary locking pages during read
This patch reduces redundant locking and unlocking pages during read operations.
In f2fs_readpage, let's use wait_on_page_locked() instead of lock_page.
And then, when we need to modify any data finally, let's lock the page so that
we can avoid lock contention.
[readpage rule]
- The f2fs_readpage returns unlocked page, or released page too in error cases.
- Its caller should handle read error, -EIO, after locking the page, which
indicates read completion.
- Its caller should check PageUptodate after grab_cache_page.
Signed-off-by: Changman Lee <cm224.lee@samsung.com>
Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/recovery.c')
-rw-r--r-- | fs/f2fs/recovery.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 6b82e2034cfd..2d86eb26c493 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -112,11 +112,16 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
112 | while (1) { | 112 | while (1) { |
113 | struct fsync_inode_entry *entry; | 113 | struct fsync_inode_entry *entry; |
114 | 114 | ||
115 | if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC)) | 115 | err = f2fs_readpage(sbi, page, blkaddr, READ_SYNC); |
116 | if (err) | ||
116 | goto out; | 117 | goto out; |
117 | 118 | ||
118 | if (cp_ver != cpver_of_node(page)) | 119 | lock_page(page); |
119 | goto out; | 120 | |
121 | if (cp_ver != cpver_of_node(page)) { | ||
122 | err = -EINVAL; | ||
123 | goto unlock_out; | ||
124 | } | ||
120 | 125 | ||
121 | if (!is_fsync_dnode(page)) | 126 | if (!is_fsync_dnode(page)) |
122 | goto next; | 127 | goto next; |
@@ -131,7 +136,7 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
131 | if (IS_INODE(page) && is_dent_dnode(page)) { | 136 | if (IS_INODE(page) && is_dent_dnode(page)) { |
132 | if (recover_inode_page(sbi, page)) { | 137 | if (recover_inode_page(sbi, page)) { |
133 | err = -ENOMEM; | 138 | err = -ENOMEM; |
134 | goto out; | 139 | goto unlock_out; |
135 | } | 140 | } |
136 | } | 141 | } |
137 | 142 | ||
@@ -139,14 +144,14 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
139 | entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS); | 144 | entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS); |
140 | if (!entry) { | 145 | if (!entry) { |
141 | err = -ENOMEM; | 146 | err = -ENOMEM; |
142 | goto out; | 147 | goto unlock_out; |
143 | } | 148 | } |
144 | 149 | ||
145 | entry->inode = f2fs_iget(sbi->sb, ino_of_node(page)); | 150 | entry->inode = f2fs_iget(sbi->sb, ino_of_node(page)); |
146 | if (IS_ERR(entry->inode)) { | 151 | if (IS_ERR(entry->inode)) { |
147 | err = PTR_ERR(entry->inode); | 152 | err = PTR_ERR(entry->inode); |
148 | kmem_cache_free(fsync_entry_slab, entry); | 153 | kmem_cache_free(fsync_entry_slab, entry); |
149 | goto out; | 154 | goto unlock_out; |
150 | } | 155 | } |
151 | 156 | ||
152 | list_add_tail(&entry->list, head); | 157 | list_add_tail(&entry->list, head); |
@@ -155,15 +160,15 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
155 | if (IS_INODE(page)) { | 160 | if (IS_INODE(page)) { |
156 | err = recover_inode(entry->inode, page); | 161 | err = recover_inode(entry->inode, page); |
157 | if (err) | 162 | if (err) |
158 | goto out; | 163 | goto unlock_out; |
159 | } | 164 | } |
160 | next: | 165 | next: |
161 | /* check next segment */ | 166 | /* check next segment */ |
162 | blkaddr = next_blkaddr_of_node(page); | 167 | blkaddr = next_blkaddr_of_node(page); |
163 | ClearPageUptodate(page); | ||
164 | } | 168 | } |
165 | out: | 169 | unlock_out: |
166 | unlock_page(page); | 170 | unlock_page(page); |
171 | out: | ||
167 | __free_pages(page, 0); | 172 | __free_pages(page, 0); |
168 | return err; | 173 | return err; |
169 | } | 174 | } |
@@ -319,8 +324,10 @@ static void recover_data(struct f2fs_sb_info *sbi, | |||
319 | if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC)) | 324 | if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC)) |
320 | goto out; | 325 | goto out; |
321 | 326 | ||
327 | lock_page(page); | ||
328 | |||
322 | if (cp_ver != cpver_of_node(page)) | 329 | if (cp_ver != cpver_of_node(page)) |
323 | goto out; | 330 | goto unlock_out; |
324 | 331 | ||
325 | entry = get_fsync_inode(head, ino_of_node(page)); | 332 | entry = get_fsync_inode(head, ino_of_node(page)); |
326 | if (!entry) | 333 | if (!entry) |
@@ -336,10 +343,10 @@ static void recover_data(struct f2fs_sb_info *sbi, | |||
336 | next: | 343 | next: |
337 | /* check next segment */ | 344 | /* check next segment */ |
338 | blkaddr = next_blkaddr_of_node(page); | 345 | blkaddr = next_blkaddr_of_node(page); |
339 | ClearPageUptodate(page); | ||
340 | } | 346 | } |
341 | out: | 347 | unlock_out: |
342 | unlock_page(page); | 348 | unlock_page(page); |
349 | out: | ||
343 | __free_pages(page, 0); | 350 | __free_pages(page, 0); |
344 | 351 | ||
345 | allocate_new_segments(sbi); | 352 | allocate_new_segments(sbi); |