diff options
Diffstat (limited to 'fs/exofs/inode.c')
-rw-r--r-- | fs/exofs/inode.c | 84 |
1 files changed, 38 insertions, 46 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index eb7368ebd8c..42685424817 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
@@ -54,6 +54,9 @@ struct page_collect { | |||
54 | unsigned nr_pages; | 54 | unsigned nr_pages; |
55 | unsigned long length; | 55 | unsigned long length; |
56 | loff_t pg_first; /* keep 64bit also in 32-arches */ | 56 | loff_t pg_first; /* keep 64bit also in 32-arches */ |
57 | bool read_4_write; /* This means two things: that the read is sync | ||
58 | * And the pages should not be unlocked. | ||
59 | */ | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, | 62 | static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, |
@@ -71,6 +74,7 @@ static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, | |||
71 | pcol->nr_pages = 0; | 74 | pcol->nr_pages = 0; |
72 | pcol->length = 0; | 75 | pcol->length = 0; |
73 | pcol->pg_first = -1; | 76 | pcol->pg_first = -1; |
77 | pcol->read_4_write = false; | ||
74 | } | 78 | } |
75 | 79 | ||
76 | static void _pcol_reset(struct page_collect *pcol) | 80 | static void _pcol_reset(struct page_collect *pcol) |
@@ -181,7 +185,7 @@ static void update_write_page(struct page *page, int ret) | |||
181 | /* Called at the end of reads, to optionally unlock pages and update their | 185 | /* Called at the end of reads, to optionally unlock pages and update their |
182 | * status. | 186 | * status. |
183 | */ | 187 | */ |
184 | static int __readpages_done(struct page_collect *pcol, bool do_unlock) | 188 | static int __readpages_done(struct page_collect *pcol) |
185 | { | 189 | { |
186 | int i; | 190 | int i; |
187 | u64 resid; | 191 | u64 resid; |
@@ -217,7 +221,7 @@ static int __readpages_done(struct page_collect *pcol, bool do_unlock) | |||
217 | page_stat ? "bad_bytes" : "good_bytes"); | 221 | page_stat ? "bad_bytes" : "good_bytes"); |
218 | 222 | ||
219 | ret = update_read_page(page, page_stat); | 223 | ret = update_read_page(page, page_stat); |
220 | if (do_unlock) | 224 | if (!pcol->read_4_write) |
221 | unlock_page(page); | 225 | unlock_page(page); |
222 | length += PAGE_SIZE; | 226 | length += PAGE_SIZE; |
223 | } | 227 | } |
@@ -232,7 +236,7 @@ static void readpages_done(struct exofs_io_state *ios, void *p) | |||
232 | { | 236 | { |
233 | struct page_collect *pcol = p; | 237 | struct page_collect *pcol = p; |
234 | 238 | ||
235 | __readpages_done(pcol, true); | 239 | __readpages_done(pcol); |
236 | atomic_dec(&pcol->sbi->s_curr_pending); | 240 | atomic_dec(&pcol->sbi->s_curr_pending); |
237 | kfree(pcol); | 241 | kfree(pcol); |
238 | } | 242 | } |
@@ -253,7 +257,7 @@ static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw) | |||
253 | } | 257 | } |
254 | } | 258 | } |
255 | 259 | ||
256 | static int read_exec(struct page_collect *pcol, bool is_sync) | 260 | static int read_exec(struct page_collect *pcol) |
257 | { | 261 | { |
258 | struct exofs_i_info *oi = exofs_i(pcol->inode); | 262 | struct exofs_i_info *oi = exofs_i(pcol->inode); |
259 | struct exofs_io_state *ios = pcol->ios; | 263 | struct exofs_io_state *ios = pcol->ios; |
@@ -263,17 +267,14 @@ static int read_exec(struct page_collect *pcol, bool is_sync) | |||
263 | if (!pcol->pages) | 267 | if (!pcol->pages) |
264 | return 0; | 268 | return 0; |
265 | 269 | ||
266 | /* see comment in _readpage() about sync reads */ | ||
267 | WARN_ON(is_sync && (pcol->nr_pages != 1)); | ||
268 | |||
269 | ios->pages = pcol->pages; | 270 | ios->pages = pcol->pages; |
270 | ios->nr_pages = pcol->nr_pages; | 271 | ios->nr_pages = pcol->nr_pages; |
271 | ios->length = pcol->length; | 272 | ios->length = pcol->length; |
272 | ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT; | 273 | ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT; |
273 | 274 | ||
274 | if (is_sync) { | 275 | if (pcol->read_4_write) { |
275 | exofs_oi_read(oi, pcol->ios); | 276 | exofs_oi_read(oi, pcol->ios); |
276 | return __readpages_done(pcol, false); | 277 | return __readpages_done(pcol); |
277 | } | 278 | } |
278 | 279 | ||
279 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); | 280 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); |
@@ -299,7 +300,7 @@ static int read_exec(struct page_collect *pcol, bool is_sync) | |||
299 | return 0; | 300 | return 0; |
300 | 301 | ||
301 | err: | 302 | err: |
302 | if (!is_sync) | 303 | if (!pcol->read_4_write) |
303 | _unlock_pcol_pages(pcol, ret, READ); | 304 | _unlock_pcol_pages(pcol, ret, READ); |
304 | 305 | ||
305 | pcol_free(pcol); | 306 | pcol_free(pcol); |
@@ -347,11 +348,12 @@ static int readpage_strip(void *data, struct page *page) | |||
347 | if (PageError(page)) | 348 | if (PageError(page)) |
348 | ClearPageError(page); | 349 | ClearPageError(page); |
349 | 350 | ||
350 | unlock_page(page); | 351 | if (!pcol->read_4_write) |
352 | unlock_page(page); | ||
351 | EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page," | 353 | EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page," |
352 | " splitting\n", inode->i_ino, page->index); | 354 | " splitting\n", inode->i_ino, page->index); |
353 | 355 | ||
354 | return read_exec(pcol, false); | 356 | return read_exec(pcol); |
355 | } | 357 | } |
356 | 358 | ||
357 | try_again: | 359 | try_again: |
@@ -361,7 +363,7 @@ try_again: | |||
361 | } else if (unlikely((pcol->pg_first + pcol->nr_pages) != | 363 | } else if (unlikely((pcol->pg_first + pcol->nr_pages) != |
362 | page->index)) { | 364 | page->index)) { |
363 | /* Discontinuity detected, split the request */ | 365 | /* Discontinuity detected, split the request */ |
364 | ret = read_exec(pcol, false); | 366 | ret = read_exec(pcol); |
365 | if (unlikely(ret)) | 367 | if (unlikely(ret)) |
366 | goto fail; | 368 | goto fail; |
367 | goto try_again; | 369 | goto try_again; |
@@ -386,7 +388,7 @@ try_again: | |||
386 | page, len, pcol->nr_pages, pcol->length); | 388 | page, len, pcol->nr_pages, pcol->length); |
387 | 389 | ||
388 | /* split the request, and start again with current page */ | 390 | /* split the request, and start again with current page */ |
389 | ret = read_exec(pcol, false); | 391 | ret = read_exec(pcol); |
390 | if (unlikely(ret)) | 392 | if (unlikely(ret)) |
391 | goto fail; | 393 | goto fail; |
392 | 394 | ||
@@ -415,26 +417,24 @@ static int exofs_readpages(struct file *file, struct address_space *mapping, | |||
415 | return ret; | 417 | return ret; |
416 | } | 418 | } |
417 | 419 | ||
418 | return read_exec(&pcol, false); | 420 | return read_exec(&pcol); |
419 | } | 421 | } |
420 | 422 | ||
421 | static int _readpage(struct page *page, bool is_sync) | 423 | static int _readpage(struct page *page, bool read_4_write) |
422 | { | 424 | { |
423 | struct page_collect pcol; | 425 | struct page_collect pcol; |
424 | int ret; | 426 | int ret; |
425 | 427 | ||
426 | _pcol_init(&pcol, 1, page->mapping->host); | 428 | _pcol_init(&pcol, 1, page->mapping->host); |
427 | 429 | ||
428 | /* readpage_strip might call read_exec(,is_sync==false) at several | 430 | pcol.read_4_write = read_4_write; |
429 | * places but not if we have a single page. | ||
430 | */ | ||
431 | ret = readpage_strip(&pcol, page); | 431 | ret = readpage_strip(&pcol, page); |
432 | if (ret) { | 432 | if (ret) { |
433 | EXOFS_ERR("_readpage => %d\n", ret); | 433 | EXOFS_ERR("_readpage => %d\n", ret); |
434 | return ret; | 434 | return ret; |
435 | } | 435 | } |
436 | 436 | ||
437 | return read_exec(&pcol, is_sync); | 437 | return read_exec(&pcol); |
438 | } | 438 | } |
439 | 439 | ||
440 | /* | 440 | /* |
@@ -505,7 +505,7 @@ static int write_exec(struct page_collect *pcol) | |||
505 | 505 | ||
506 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); | 506 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); |
507 | if (!pcol_copy) { | 507 | if (!pcol_copy) { |
508 | EXOFS_ERR("write_exec: Faild to kmalloc(pcol)\n"); | 508 | EXOFS_ERR("write_exec: Failed to kmalloc(pcol)\n"); |
509 | ret = -ENOMEM; | 509 | ret = -ENOMEM; |
510 | goto err; | 510 | goto err; |
511 | } | 511 | } |
@@ -521,7 +521,7 @@ static int write_exec(struct page_collect *pcol) | |||
521 | 521 | ||
522 | ret = exofs_oi_write(oi, ios); | 522 | ret = exofs_oi_write(oi, ios); |
523 | if (unlikely(ret)) { | 523 | if (unlikely(ret)) { |
524 | EXOFS_ERR("write_exec: exofs_oi_write() Faild\n"); | 524 | EXOFS_ERR("write_exec: exofs_oi_write() Failed\n"); |
525 | goto err; | 525 | goto err; |
526 | } | 526 | } |
527 | 527 | ||
@@ -622,7 +622,7 @@ try_again: | |||
622 | /* split the request, next loop will start again */ | 622 | /* split the request, next loop will start again */ |
623 | ret = write_exec(pcol); | 623 | ret = write_exec(pcol); |
624 | if (unlikely(ret)) { | 624 | if (unlikely(ret)) { |
625 | EXOFS_DBGMSG("write_exec faild => %d", ret); | 625 | EXOFS_DBGMSG("write_exec failed => %d", ret); |
626 | goto fail; | 626 | goto fail; |
627 | } | 627 | } |
628 | 628 | ||
@@ -713,7 +713,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, | |||
713 | ret = simple_write_begin(file, mapping, pos, len, flags, pagep, | 713 | ret = simple_write_begin(file, mapping, pos, len, flags, pagep, |
714 | fsdata); | 714 | fsdata); |
715 | if (ret) { | 715 | if (ret) { |
716 | EXOFS_DBGMSG("simple_write_begin faild\n"); | 716 | EXOFS_DBGMSG("simple_write_begin failed\n"); |
717 | goto out; | 717 | goto out; |
718 | } | 718 | } |
719 | 719 | ||
@@ -726,7 +726,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, | |||
726 | if (ret) { | 726 | if (ret) { |
727 | /*SetPageError was done by _readpage. Is it ok?*/ | 727 | /*SetPageError was done by _readpage. Is it ok?*/ |
728 | unlock_page(page); | 728 | unlock_page(page); |
729 | EXOFS_DBGMSG("__readpage_filler faild\n"); | 729 | EXOFS_DBGMSG("__readpage_filler failed\n"); |
730 | } | 730 | } |
731 | } | 731 | } |
732 | out: | 732 | out: |
@@ -1030,6 +1030,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) | |||
1030 | memcpy(oi->i_data, fcb.i_data, sizeof(fcb.i_data)); | 1030 | memcpy(oi->i_data, fcb.i_data, sizeof(fcb.i_data)); |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | inode->i_mapping->backing_dev_info = sb->s_bdi; | ||
1033 | if (S_ISREG(inode->i_mode)) { | 1034 | if (S_ISREG(inode->i_mode)) { |
1034 | inode->i_op = &exofs_file_inode_operations; | 1035 | inode->i_op = &exofs_file_inode_operations; |
1035 | inode->i_fop = &exofs_file_operations; | 1036 | inode->i_fop = &exofs_file_operations; |
@@ -1066,8 +1067,10 @@ bad_inode: | |||
1066 | int __exofs_wait_obj_created(struct exofs_i_info *oi) | 1067 | int __exofs_wait_obj_created(struct exofs_i_info *oi) |
1067 | { | 1068 | { |
1068 | if (!obj_created(oi)) { | 1069 | if (!obj_created(oi)) { |
1070 | EXOFS_DBGMSG("!obj_created\n"); | ||
1069 | BUG_ON(!obj_2bcreated(oi)); | 1071 | BUG_ON(!obj_2bcreated(oi)); |
1070 | wait_event(oi->i_wq, obj_created(oi)); | 1072 | wait_event(oi->i_wq, obj_created(oi)); |
1073 | EXOFS_DBGMSG("wait_event done\n"); | ||
1071 | } | 1074 | } |
1072 | return unlikely(is_bad_inode(&oi->vfs_inode)) ? -EIO : 0; | 1075 | return unlikely(is_bad_inode(&oi->vfs_inode)) ? -EIO : 0; |
1073 | } | 1076 | } |
@@ -1089,7 +1092,7 @@ static void create_done(struct exofs_io_state *ios, void *p) | |||
1089 | atomic_dec(&sbi->s_curr_pending); | 1092 | atomic_dec(&sbi->s_curr_pending); |
1090 | 1093 | ||
1091 | if (unlikely(ret)) { | 1094 | if (unlikely(ret)) { |
1092 | EXOFS_ERR("object=0x%llx creation faild in pid=0x%llx", | 1095 | EXOFS_ERR("object=0x%llx creation failed in pid=0x%llx", |
1093 | _LLU(exofs_oi_objno(oi)), _LLU(sbi->layout.s_pid)); | 1096 | _LLU(exofs_oi_objno(oi)), _LLU(sbi->layout.s_pid)); |
1094 | /*TODO: When FS is corrupted creation can fail, object already | 1097 | /*TODO: When FS is corrupted creation can fail, object already |
1095 | * exist. Get rid of this asynchronous creation, if exist | 1098 | * exist. Get rid of this asynchronous creation, if exist |
@@ -1101,7 +1104,6 @@ static void create_done(struct exofs_io_state *ios, void *p) | |||
1101 | 1104 | ||
1102 | set_obj_created(oi); | 1105 | set_obj_created(oi); |
1103 | 1106 | ||
1104 | atomic_dec(&inode->i_count); | ||
1105 | wake_up(&oi->i_wq); | 1107 | wake_up(&oi->i_wq); |
1106 | } | 1108 | } |
1107 | 1109 | ||
@@ -1129,6 +1131,7 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) | |||
1129 | 1131 | ||
1130 | sbi = sb->s_fs_info; | 1132 | sbi = sb->s_fs_info; |
1131 | 1133 | ||
1134 | inode->i_mapping->backing_dev_info = sb->s_bdi; | ||
1132 | sb->s_dirt = 1; | 1135 | sb->s_dirt = 1; |
1133 | inode_init_owner(inode, dir, mode); | 1136 | inode_init_owner(inode, dir, mode); |
1134 | inode->i_ino = sbi->s_nextid++; | 1137 | inode->i_ino = sbi->s_nextid++; |
@@ -1151,17 +1154,11 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) | |||
1151 | ios->obj.id = exofs_oi_objno(oi); | 1154 | ios->obj.id = exofs_oi_objno(oi); |
1152 | exofs_make_credential(oi->i_cred, &ios->obj); | 1155 | exofs_make_credential(oi->i_cred, &ios->obj); |
1153 | 1156 | ||
1154 | /* increment the refcount so that the inode will still be around when we | ||
1155 | * reach the callback | ||
1156 | */ | ||
1157 | atomic_inc(&inode->i_count); | ||
1158 | |||
1159 | ios->done = create_done; | 1157 | ios->done = create_done; |
1160 | ios->private = inode; | 1158 | ios->private = inode; |
1161 | ios->cred = oi->i_cred; | 1159 | ios->cred = oi->i_cred; |
1162 | ret = exofs_sbi_create(ios); | 1160 | ret = exofs_sbi_create(ios); |
1163 | if (ret) { | 1161 | if (ret) { |
1164 | atomic_dec(&inode->i_count); | ||
1165 | exofs_put_io_state(ios); | 1162 | exofs_put_io_state(ios); |
1166 | return ERR_PTR(ret); | 1163 | return ERR_PTR(ret); |
1167 | } | 1164 | } |
@@ -1209,7 +1206,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync) | |||
1209 | 1206 | ||
1210 | args = kzalloc(sizeof(*args), GFP_KERNEL); | 1207 | args = kzalloc(sizeof(*args), GFP_KERNEL); |
1211 | if (!args) { | 1208 | if (!args) { |
1212 | EXOFS_DBGMSG("Faild kzalloc of args\n"); | 1209 | EXOFS_DBGMSG("Failed kzalloc of args\n"); |
1213 | return -ENOMEM; | 1210 | return -ENOMEM; |
1214 | } | 1211 | } |
1215 | 1212 | ||
@@ -1251,12 +1248,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync) | |||
1251 | ios->out_attr_len = 1; | 1248 | ios->out_attr_len = 1; |
1252 | ios->out_attr = &attr; | 1249 | ios->out_attr = &attr; |
1253 | 1250 | ||
1254 | if (!obj_created(oi)) { | 1251 | wait_obj_created(oi); |
1255 | EXOFS_DBGMSG("!obj_created\n"); | ||
1256 | BUG_ON(!obj_2bcreated(oi)); | ||
1257 | wait_event(oi->i_wq, obj_created(oi)); | ||
1258 | EXOFS_DBGMSG("wait_event done\n"); | ||
1259 | } | ||
1260 | 1252 | ||
1261 | if (!do_sync) { | 1253 | if (!do_sync) { |
1262 | args->sbi = sbi; | 1254 | args->sbi = sbi; |
@@ -1319,12 +1311,12 @@ void exofs_evict_inode(struct inode *inode) | |||
1319 | inode->i_size = 0; | 1311 | inode->i_size = 0; |
1320 | end_writeback(inode); | 1312 | end_writeback(inode); |
1321 | 1313 | ||
1322 | /* if we are deleting an obj that hasn't been created yet, wait */ | 1314 | /* if we are deleting an obj that hasn't been created yet, wait. |
1323 | if (!obj_created(oi)) { | 1315 | * This also makes sure that create_done cannot be called with an |
1324 | BUG_ON(!obj_2bcreated(oi)); | 1316 | * already evicted inode. |
1325 | wait_event(oi->i_wq, obj_created(oi)); | 1317 | */ |
1326 | /* ignore the error attempt a remove anyway */ | 1318 | wait_obj_created(oi); |
1327 | } | 1319 | /* ignore the error, attempt a remove anyway */ |
1328 | 1320 | ||
1329 | /* Now Remove the OSD objects */ | 1321 | /* Now Remove the OSD objects */ |
1330 | ret = exofs_get_io_state(&sbi->layout, &ios); | 1322 | ret = exofs_get_io_state(&sbi->layout, &ios); |