diff options
Diffstat (limited to 'fs/exofs/inode.c')
| -rw-r--r-- | fs/exofs/inode.c | 198 |
1 files changed, 120 insertions, 78 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 2afbcebeda71..a17e4b733e35 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
| @@ -41,16 +41,18 @@ | |||
| 41 | 41 | ||
| 42 | enum { BIO_MAX_PAGES_KMALLOC = | 42 | enum { BIO_MAX_PAGES_KMALLOC = |
| 43 | (PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec), | 43 | (PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec), |
| 44 | MAX_PAGES_KMALLOC = | ||
| 45 | PAGE_SIZE / sizeof(struct page *), | ||
| 44 | }; | 46 | }; |
| 45 | 47 | ||
| 46 | struct page_collect { | 48 | struct page_collect { |
| 47 | struct exofs_sb_info *sbi; | 49 | struct exofs_sb_info *sbi; |
| 48 | struct request_queue *req_q; | ||
| 49 | struct inode *inode; | 50 | struct inode *inode; |
| 50 | unsigned expected_pages; | 51 | unsigned expected_pages; |
| 51 | struct exofs_io_state *ios; | 52 | struct exofs_io_state *ios; |
| 52 | 53 | ||
| 53 | struct bio *bio; | 54 | struct page **pages; |
| 55 | unsigned alloc_pages; | ||
| 54 | unsigned nr_pages; | 56 | unsigned nr_pages; |
| 55 | unsigned long length; | 57 | unsigned long length; |
| 56 | loff_t pg_first; /* keep 64bit also in 32-arches */ | 58 | loff_t pg_first; /* keep 64bit also in 32-arches */ |
| @@ -62,15 +64,12 @@ static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, | |||
| 62 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; | 64 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; |
| 63 | 65 | ||
| 64 | pcol->sbi = sbi; | 66 | pcol->sbi = sbi; |
| 65 | /* Create master bios on first Q, later on cloning, each clone will be | ||
| 66 | * allocated on it's destination Q | ||
| 67 | */ | ||
| 68 | pcol->req_q = osd_request_queue(sbi->s_ods[0]); | ||
| 69 | pcol->inode = inode; | 67 | pcol->inode = inode; |
| 70 | pcol->expected_pages = expected_pages; | 68 | pcol->expected_pages = expected_pages; |
| 71 | 69 | ||
| 72 | pcol->ios = NULL; | 70 | pcol->ios = NULL; |
| 73 | pcol->bio = NULL; | 71 | pcol->pages = NULL; |
| 72 | pcol->alloc_pages = 0; | ||
| 74 | pcol->nr_pages = 0; | 73 | pcol->nr_pages = 0; |
| 75 | pcol->length = 0; | 74 | pcol->length = 0; |
| 76 | pcol->pg_first = -1; | 75 | pcol->pg_first = -1; |
| @@ -80,7 +79,8 @@ static void _pcol_reset(struct page_collect *pcol) | |||
| 80 | { | 79 | { |
| 81 | pcol->expected_pages -= min(pcol->nr_pages, pcol->expected_pages); | 80 | pcol->expected_pages -= min(pcol->nr_pages, pcol->expected_pages); |
| 82 | 81 | ||
| 83 | pcol->bio = NULL; | 82 | pcol->pages = NULL; |
| 83 | pcol->alloc_pages = 0; | ||
| 84 | pcol->nr_pages = 0; | 84 | pcol->nr_pages = 0; |
| 85 | pcol->length = 0; | 85 | pcol->length = 0; |
| 86 | pcol->pg_first = -1; | 86 | pcol->pg_first = -1; |
| @@ -90,38 +90,43 @@ static void _pcol_reset(struct page_collect *pcol) | |||
| 90 | * it might not end here. don't be left with nothing | 90 | * it might not end here. don't be left with nothing |
| 91 | */ | 91 | */ |
| 92 | if (!pcol->expected_pages) | 92 | if (!pcol->expected_pages) |
| 93 | pcol->expected_pages = BIO_MAX_PAGES_KMALLOC; | 93 | pcol->expected_pages = MAX_PAGES_KMALLOC; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static int pcol_try_alloc(struct page_collect *pcol) | 96 | static int pcol_try_alloc(struct page_collect *pcol) |
| 97 | { | 97 | { |
| 98 | int pages = min_t(unsigned, pcol->expected_pages, | 98 | unsigned pages = min_t(unsigned, pcol->expected_pages, |
| 99 | BIO_MAX_PAGES_KMALLOC); | 99 | MAX_PAGES_KMALLOC); |
| 100 | 100 | ||
| 101 | if (!pcol->ios) { /* First time allocate io_state */ | 101 | if (!pcol->ios) { /* First time allocate io_state */ |
| 102 | int ret = exofs_get_io_state(pcol->sbi, &pcol->ios); | 102 | int ret = exofs_get_io_state(&pcol->sbi->layout, &pcol->ios); |
| 103 | 103 | ||
| 104 | if (ret) | 104 | if (ret) |
| 105 | return ret; | 105 | return ret; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /* TODO: easily support bio chaining */ | ||
| 109 | pages = min_t(unsigned, pages, | ||
| 110 | pcol->sbi->layout.group_width * BIO_MAX_PAGES_KMALLOC); | ||
| 111 | |||
| 108 | for (; pages; pages >>= 1) { | 112 | for (; pages; pages >>= 1) { |
| 109 | pcol->bio = bio_kmalloc(GFP_KERNEL, pages); | 113 | pcol->pages = kmalloc(pages * sizeof(struct page *), |
| 110 | if (likely(pcol->bio)) | 114 | GFP_KERNEL); |
| 115 | if (likely(pcol->pages)) { | ||
| 116 | pcol->alloc_pages = pages; | ||
| 111 | return 0; | 117 | return 0; |
| 118 | } | ||
| 112 | } | 119 | } |
| 113 | 120 | ||
| 114 | EXOFS_ERR("Failed to bio_kmalloc expected_pages=%u\n", | 121 | EXOFS_ERR("Failed to kmalloc expected_pages=%u\n", |
| 115 | pcol->expected_pages); | 122 | pcol->expected_pages); |
| 116 | return -ENOMEM; | 123 | return -ENOMEM; |
| 117 | } | 124 | } |
| 118 | 125 | ||
| 119 | static void pcol_free(struct page_collect *pcol) | 126 | static void pcol_free(struct page_collect *pcol) |
| 120 | { | 127 | { |
| 121 | if (pcol->bio) { | 128 | kfree(pcol->pages); |
| 122 | bio_put(pcol->bio); | 129 | pcol->pages = NULL; |
| 123 | pcol->bio = NULL; | ||
| 124 | } | ||
| 125 | 130 | ||
| 126 | if (pcol->ios) { | 131 | if (pcol->ios) { |
| 127 | exofs_put_io_state(pcol->ios); | 132 | exofs_put_io_state(pcol->ios); |
| @@ -132,11 +137,10 @@ static void pcol_free(struct page_collect *pcol) | |||
| 132 | static int pcol_add_page(struct page_collect *pcol, struct page *page, | 137 | static int pcol_add_page(struct page_collect *pcol, struct page *page, |
| 133 | unsigned len) | 138 | unsigned len) |
| 134 | { | 139 | { |
| 135 | int added_len = bio_add_pc_page(pcol->req_q, pcol->bio, page, len, 0); | 140 | if (unlikely(pcol->nr_pages >= pcol->alloc_pages)) |
| 136 | if (unlikely(len != added_len)) | ||
| 137 | return -ENOMEM; | 141 | return -ENOMEM; |
| 138 | 142 | ||
| 139 | ++pcol->nr_pages; | 143 | pcol->pages[pcol->nr_pages++] = page; |
| 140 | pcol->length += len; | 144 | pcol->length += len; |
| 141 | return 0; | 145 | return 0; |
| 142 | } | 146 | } |
| @@ -181,7 +185,6 @@ static void update_write_page(struct page *page, int ret) | |||
| 181 | */ | 185 | */ |
| 182 | static int __readpages_done(struct page_collect *pcol, bool do_unlock) | 186 | static int __readpages_done(struct page_collect *pcol, bool do_unlock) |
| 183 | { | 187 | { |
| 184 | struct bio_vec *bvec; | ||
| 185 | int i; | 188 | int i; |
| 186 | u64 resid; | 189 | u64 resid; |
| 187 | u64 good_bytes; | 190 | u64 good_bytes; |
| @@ -193,13 +196,13 @@ static int __readpages_done(struct page_collect *pcol, bool do_unlock) | |||
| 193 | else | 196 | else |
| 194 | good_bytes = pcol->length - resid; | 197 | good_bytes = pcol->length - resid; |
| 195 | 198 | ||
| 196 | EXOFS_DBGMSG("readpages_done(0x%lx) good_bytes=0x%llx" | 199 | EXOFS_DBGMSG2("readpages_done(0x%lx) good_bytes=0x%llx" |
| 197 | " length=0x%lx nr_pages=%u\n", | 200 | " length=0x%lx nr_pages=%u\n", |
| 198 | pcol->inode->i_ino, _LLU(good_bytes), pcol->length, | 201 | pcol->inode->i_ino, _LLU(good_bytes), pcol->length, |
| 199 | pcol->nr_pages); | 202 | pcol->nr_pages); |
| 200 | 203 | ||
| 201 | __bio_for_each_segment(bvec, pcol->bio, i, 0) { | 204 | for (i = 0; i < pcol->nr_pages; i++) { |
| 202 | struct page *page = bvec->bv_page; | 205 | struct page *page = pcol->pages[i]; |
| 203 | struct inode *inode = page->mapping->host; | 206 | struct inode *inode = page->mapping->host; |
| 204 | int page_stat; | 207 | int page_stat; |
| 205 | 208 | ||
| @@ -218,11 +221,11 @@ static int __readpages_done(struct page_collect *pcol, bool do_unlock) | |||
| 218 | ret = update_read_page(page, page_stat); | 221 | ret = update_read_page(page, page_stat); |
| 219 | if (do_unlock) | 222 | if (do_unlock) |
| 220 | unlock_page(page); | 223 | unlock_page(page); |
| 221 | length += bvec->bv_len; | 224 | length += PAGE_SIZE; |
| 222 | } | 225 | } |
| 223 | 226 | ||
| 224 | pcol_free(pcol); | 227 | pcol_free(pcol); |
| 225 | EXOFS_DBGMSG("readpages_done END\n"); | 228 | EXOFS_DBGMSG2("readpages_done END\n"); |
| 226 | return ret; | 229 | return ret; |
| 227 | } | 230 | } |
| 228 | 231 | ||
| @@ -238,11 +241,10 @@ static void readpages_done(struct exofs_io_state *ios, void *p) | |||
| 238 | 241 | ||
| 239 | static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw) | 242 | static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw) |
| 240 | { | 243 | { |
| 241 | struct bio_vec *bvec; | ||
| 242 | int i; | 244 | int i; |
| 243 | 245 | ||
| 244 | __bio_for_each_segment(bvec, pcol->bio, i, 0) { | 246 | for (i = 0; i < pcol->nr_pages; i++) { |
| 245 | struct page *page = bvec->bv_page; | 247 | struct page *page = pcol->pages[i]; |
| 246 | 248 | ||
| 247 | if (rw == READ) | 249 | if (rw == READ) |
| 248 | update_read_page(page, ret); | 250 | update_read_page(page, ret); |
| @@ -260,13 +262,14 @@ static int read_exec(struct page_collect *pcol, bool is_sync) | |||
| 260 | struct page_collect *pcol_copy = NULL; | 262 | struct page_collect *pcol_copy = NULL; |
| 261 | int ret; | 263 | int ret; |
| 262 | 264 | ||
| 263 | if (!pcol->bio) | 265 | if (!pcol->pages) |
| 264 | return 0; | 266 | return 0; |
| 265 | 267 | ||
| 266 | /* see comment in _readpage() about sync reads */ | 268 | /* see comment in _readpage() about sync reads */ |
| 267 | WARN_ON(is_sync && (pcol->nr_pages != 1)); | 269 | WARN_ON(is_sync && (pcol->nr_pages != 1)); |
| 268 | 270 | ||
| 269 | ios->bio = pcol->bio; | 271 | ios->pages = pcol->pages; |
| 272 | ios->nr_pages = pcol->nr_pages; | ||
| 270 | ios->length = pcol->length; | 273 | ios->length = pcol->length; |
| 271 | ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT; | 274 | ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT; |
| 272 | 275 | ||
| @@ -290,7 +293,7 @@ static int read_exec(struct page_collect *pcol, bool is_sync) | |||
| 290 | 293 | ||
| 291 | atomic_inc(&pcol->sbi->s_curr_pending); | 294 | atomic_inc(&pcol->sbi->s_curr_pending); |
| 292 | 295 | ||
| 293 | EXOFS_DBGMSG("read_exec obj=0x%llx start=0x%llx length=0x%lx\n", | 296 | EXOFS_DBGMSG2("read_exec obj=0x%llx start=0x%llx length=0x%lx\n", |
| 294 | ios->obj.id, _LLU(ios->offset), pcol->length); | 297 | ios->obj.id, _LLU(ios->offset), pcol->length); |
| 295 | 298 | ||
| 296 | /* pages ownership was passed to pcol_copy */ | 299 | /* pages ownership was passed to pcol_copy */ |
| @@ -366,7 +369,7 @@ try_again: | |||
| 366 | goto try_again; | 369 | goto try_again; |
| 367 | } | 370 | } |
| 368 | 371 | ||
| 369 | if (!pcol->bio) { | 372 | if (!pcol->pages) { |
| 370 | ret = pcol_try_alloc(pcol); | 373 | ret = pcol_try_alloc(pcol); |
| 371 | if (unlikely(ret)) | 374 | if (unlikely(ret)) |
| 372 | goto fail; | 375 | goto fail; |
| @@ -448,7 +451,6 @@ static int exofs_readpage(struct file *file, struct page *page) | |||
| 448 | static void writepages_done(struct exofs_io_state *ios, void *p) | 451 | static void writepages_done(struct exofs_io_state *ios, void *p) |
| 449 | { | 452 | { |
| 450 | struct page_collect *pcol = p; | 453 | struct page_collect *pcol = p; |
| 451 | struct bio_vec *bvec; | ||
| 452 | int i; | 454 | int i; |
| 453 | u64 resid; | 455 | u64 resid; |
| 454 | u64 good_bytes; | 456 | u64 good_bytes; |
| @@ -462,13 +464,13 @@ static void writepages_done(struct exofs_io_state *ios, void *p) | |||
| 462 | else | 464 | else |
| 463 | good_bytes = pcol->length - resid; | 465 | good_bytes = pcol->length - resid; |
| 464 | 466 | ||
| 465 | EXOFS_DBGMSG("writepages_done(0x%lx) good_bytes=0x%llx" | 467 | EXOFS_DBGMSG2("writepages_done(0x%lx) good_bytes=0x%llx" |
| 466 | " length=0x%lx nr_pages=%u\n", | 468 | " length=0x%lx nr_pages=%u\n", |
| 467 | pcol->inode->i_ino, _LLU(good_bytes), pcol->length, | 469 | pcol->inode->i_ino, _LLU(good_bytes), pcol->length, |
| 468 | pcol->nr_pages); | 470 | pcol->nr_pages); |
| 469 | 471 | ||
| 470 | __bio_for_each_segment(bvec, pcol->bio, i, 0) { | 472 | for (i = 0; i < pcol->nr_pages; i++) { |
| 471 | struct page *page = bvec->bv_page; | 473 | struct page *page = pcol->pages[i]; |
| 472 | struct inode *inode = page->mapping->host; | 474 | struct inode *inode = page->mapping->host; |
| 473 | int page_stat; | 475 | int page_stat; |
| 474 | 476 | ||
| @@ -485,12 +487,12 @@ static void writepages_done(struct exofs_io_state *ios, void *p) | |||
| 485 | EXOFS_DBGMSG2(" writepages_done(0x%lx, 0x%lx) status=%d\n", | 487 | EXOFS_DBGMSG2(" writepages_done(0x%lx, 0x%lx) status=%d\n", |
| 486 | inode->i_ino, page->index, page_stat); | 488 | inode->i_ino, page->index, page_stat); |
| 487 | 489 | ||
| 488 | length += bvec->bv_len; | 490 | length += PAGE_SIZE; |
| 489 | } | 491 | } |
| 490 | 492 | ||
| 491 | pcol_free(pcol); | 493 | pcol_free(pcol); |
| 492 | kfree(pcol); | 494 | kfree(pcol); |
| 493 | EXOFS_DBGMSG("writepages_done END\n"); | 495 | EXOFS_DBGMSG2("writepages_done END\n"); |
| 494 | } | 496 | } |
| 495 | 497 | ||
| 496 | static int write_exec(struct page_collect *pcol) | 498 | static int write_exec(struct page_collect *pcol) |
| @@ -500,7 +502,7 @@ static int write_exec(struct page_collect *pcol) | |||
| 500 | struct page_collect *pcol_copy = NULL; | 502 | struct page_collect *pcol_copy = NULL; |
| 501 | int ret; | 503 | int ret; |
| 502 | 504 | ||
| 503 | if (!pcol->bio) | 505 | if (!pcol->pages) |
| 504 | return 0; | 506 | return 0; |
| 505 | 507 | ||
| 506 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); | 508 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); |
| @@ -512,9 +514,8 @@ static int write_exec(struct page_collect *pcol) | |||
| 512 | 514 | ||
| 513 | *pcol_copy = *pcol; | 515 | *pcol_copy = *pcol; |
| 514 | 516 | ||
| 515 | pcol_copy->bio->bi_rw |= (1 << BIO_RW); /* FIXME: bio_set_dir() */ | 517 | ios->pages = pcol_copy->pages; |
| 516 | 518 | ios->nr_pages = pcol_copy->nr_pages; | |
| 517 | ios->bio = pcol_copy->bio; | ||
| 518 | ios->offset = pcol_copy->pg_first << PAGE_CACHE_SHIFT; | 519 | ios->offset = pcol_copy->pg_first << PAGE_CACHE_SHIFT; |
| 519 | ios->length = pcol_copy->length; | 520 | ios->length = pcol_copy->length; |
| 520 | ios->done = writepages_done; | 521 | ios->done = writepages_done; |
| @@ -527,7 +528,7 @@ static int write_exec(struct page_collect *pcol) | |||
| 527 | } | 528 | } |
| 528 | 529 | ||
| 529 | atomic_inc(&pcol->sbi->s_curr_pending); | 530 | atomic_inc(&pcol->sbi->s_curr_pending); |
| 530 | EXOFS_DBGMSG("write_exec(0x%lx, 0x%llx) start=0x%llx length=0x%lx\n", | 531 | EXOFS_DBGMSG2("write_exec(0x%lx, 0x%llx) start=0x%llx length=0x%lx\n", |
| 531 | pcol->inode->i_ino, pcol->pg_first, _LLU(ios->offset), | 532 | pcol->inode->i_ino, pcol->pg_first, _LLU(ios->offset), |
| 532 | pcol->length); | 533 | pcol->length); |
| 533 | /* pages ownership was passed to pcol_copy */ | 534 | /* pages ownership was passed to pcol_copy */ |
| @@ -605,7 +606,7 @@ try_again: | |||
| 605 | goto try_again; | 606 | goto try_again; |
| 606 | } | 607 | } |
| 607 | 608 | ||
| 608 | if (!pcol->bio) { | 609 | if (!pcol->pages) { |
| 609 | ret = pcol_try_alloc(pcol); | 610 | ret = pcol_try_alloc(pcol); |
| 610 | if (unlikely(ret)) | 611 | if (unlikely(ret)) |
| 611 | goto fail; | 612 | goto fail; |
| @@ -616,7 +617,7 @@ try_again: | |||
| 616 | 617 | ||
| 617 | ret = pcol_add_page(pcol, page, len); | 618 | ret = pcol_add_page(pcol, page, len); |
| 618 | if (unlikely(ret)) { | 619 | if (unlikely(ret)) { |
| 619 | EXOFS_DBGMSG("Failed pcol_add_page " | 620 | EXOFS_DBGMSG2("Failed pcol_add_page " |
| 620 | "nr_pages=%u total_length=0x%lx\n", | 621 | "nr_pages=%u total_length=0x%lx\n", |
| 621 | pcol->nr_pages, pcol->length); | 622 | pcol->nr_pages, pcol->length); |
| 622 | 623 | ||
| @@ -663,7 +664,7 @@ static int exofs_writepages(struct address_space *mapping, | |||
| 663 | if (expected_pages < 32L) | 664 | if (expected_pages < 32L) |
| 664 | expected_pages = 32L; | 665 | expected_pages = 32L; |
| 665 | 666 | ||
| 666 | EXOFS_DBGMSG("inode(0x%lx) wbc->start=0x%llx wbc->end=0x%llx " | 667 | EXOFS_DBGMSG2("inode(0x%lx) wbc->start=0x%llx wbc->end=0x%llx " |
| 667 | "nrpages=%lu start=0x%lx end=0x%lx expected_pages=%ld\n", | 668 | "nrpages=%lu start=0x%lx end=0x%lx expected_pages=%ld\n", |
| 668 | mapping->host->i_ino, wbc->range_start, wbc->range_end, | 669 | mapping->host->i_ino, wbc->range_start, wbc->range_end, |
| 669 | mapping->nrpages, start, end, expected_pages); | 670 | mapping->nrpages, start, end, expected_pages); |
| @@ -859,20 +860,33 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
| 859 | return error; | 860 | return error; |
| 860 | } | 861 | } |
| 861 | 862 | ||
| 863 | static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF( | ||
| 864 | EXOFS_APAGE_FS_DATA, | ||
| 865 | EXOFS_ATTR_INODE_FILE_LAYOUT, | ||
| 866 | 0); | ||
| 867 | static const struct osd_attr g_attr_inode_dir_layout = ATTR_DEF( | ||
| 868 | EXOFS_APAGE_FS_DATA, | ||
| 869 | EXOFS_ATTR_INODE_DIR_LAYOUT, | ||
| 870 | 0); | ||
| 871 | |||
| 862 | /* | 872 | /* |
| 863 | * Read an inode from the OSD, and return it as is. We also return the size | 873 | * Read the Linux inode info from the OSD, and return it as is. In exofs the |
| 864 | * attribute in the 'obj_size' argument. | 874 | * inode info is in an application specific page/attribute of the osd-object. |
| 865 | */ | 875 | */ |
| 866 | static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, | 876 | static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, |
| 867 | struct exofs_fcb *inode, uint64_t *obj_size) | 877 | struct exofs_fcb *inode) |
| 868 | { | 878 | { |
| 869 | struct exofs_sb_info *sbi = sb->s_fs_info; | 879 | struct exofs_sb_info *sbi = sb->s_fs_info; |
| 870 | struct osd_attr attrs[2]; | 880 | struct osd_attr attrs[] = { |
| 881 | [0] = g_attr_inode_data, | ||
| 882 | [1] = g_attr_inode_file_layout, | ||
| 883 | [2] = g_attr_inode_dir_layout, | ||
| 884 | }; | ||
| 871 | struct exofs_io_state *ios; | 885 | struct exofs_io_state *ios; |
| 886 | struct exofs_on_disk_inode_layout *layout; | ||
| 872 | int ret; | 887 | int ret; |
| 873 | 888 | ||
| 874 | *obj_size = ~0; | 889 | ret = exofs_get_io_state(&sbi->layout, &ios); |
| 875 | ret = exofs_get_io_state(sbi, &ios); | ||
| 876 | if (unlikely(ret)) { | 890 | if (unlikely(ret)) { |
| 877 | EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); | 891 | EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); |
| 878 | return ret; | 892 | return ret; |
| @@ -882,14 +896,25 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, | |||
| 882 | exofs_make_credential(oi->i_cred, &ios->obj); | 896 | exofs_make_credential(oi->i_cred, &ios->obj); |
| 883 | ios->cred = oi->i_cred; | 897 | ios->cred = oi->i_cred; |
| 884 | 898 | ||
| 885 | attrs[0] = g_attr_inode_data; | 899 | attrs[1].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs); |
| 886 | attrs[1] = g_attr_logical_length; | 900 | attrs[2].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs); |
| 901 | |||
| 887 | ios->in_attr = attrs; | 902 | ios->in_attr = attrs; |
| 888 | ios->in_attr_len = ARRAY_SIZE(attrs); | 903 | ios->in_attr_len = ARRAY_SIZE(attrs); |
| 889 | 904 | ||
| 890 | ret = exofs_sbi_read(ios); | 905 | ret = exofs_sbi_read(ios); |
| 891 | if (ret) | 906 | if (unlikely(ret)) { |
| 907 | EXOFS_ERR("object(0x%llx) corrupted, return empty file=>%d\n", | ||
| 908 | _LLU(ios->obj.id), ret); | ||
| 909 | memset(inode, 0, sizeof(*inode)); | ||
| 910 | inode->i_mode = 0040000 | (0777 & ~022); | ||
| 911 | /* If object is lost on target we might as well enable it's | ||
| 912 | * delete. | ||
| 913 | */ | ||
| 914 | if ((ret == -ENOENT) || (ret == -EINVAL)) | ||
| 915 | ret = 0; | ||
| 892 | goto out; | 916 | goto out; |
| 917 | } | ||
| 893 | 918 | ||
| 894 | ret = extract_attr_from_ios(ios, &attrs[0]); | 919 | ret = extract_attr_from_ios(ios, &attrs[0]); |
| 895 | if (ret) { | 920 | if (ret) { |
| @@ -901,11 +926,33 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, | |||
| 901 | 926 | ||
| 902 | ret = extract_attr_from_ios(ios, &attrs[1]); | 927 | ret = extract_attr_from_ios(ios, &attrs[1]); |
| 903 | if (ret) { | 928 | if (ret) { |
| 904 | EXOFS_ERR("%s: extract_attr of logical_length failed\n", | 929 | EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__); |
| 905 | __func__); | 930 | goto out; |
| 931 | } | ||
| 932 | if (attrs[1].len) { | ||
| 933 | layout = attrs[1].val_ptr; | ||
| 934 | if (layout->gen_func != cpu_to_le16(LAYOUT_MOVING_WINDOW)) { | ||
| 935 | EXOFS_ERR("%s: unsupported files layout %d\n", | ||
| 936 | __func__, layout->gen_func); | ||
| 937 | ret = -ENOTSUPP; | ||
| 938 | goto out; | ||
| 939 | } | ||
| 940 | } | ||
| 941 | |||
| 942 | ret = extract_attr_from_ios(ios, &attrs[2]); | ||
| 943 | if (ret) { | ||
| 944 | EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__); | ||
| 906 | goto out; | 945 | goto out; |
| 907 | } | 946 | } |
| 908 | *obj_size = get_unaligned_be64(attrs[1].val_ptr); | 947 | if (attrs[2].len) { |
| 948 | layout = attrs[2].val_ptr; | ||
| 949 | if (layout->gen_func != cpu_to_le16(LAYOUT_MOVING_WINDOW)) { | ||
| 950 | EXOFS_ERR("%s: unsupported meta-data layout %d\n", | ||
| 951 | __func__, layout->gen_func); | ||
| 952 | ret = -ENOTSUPP; | ||
| 953 | goto out; | ||
| 954 | } | ||
| 955 | } | ||
| 909 | 956 | ||
| 910 | out: | 957 | out: |
| 911 | exofs_put_io_state(ios); | 958 | exofs_put_io_state(ios); |
| @@ -925,7 +972,6 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) | |||
| 925 | struct exofs_i_info *oi; | 972 | struct exofs_i_info *oi; |
| 926 | struct exofs_fcb fcb; | 973 | struct exofs_fcb fcb; |
| 927 | struct inode *inode; | 974 | struct inode *inode; |
| 928 | uint64_t obj_size; | ||
| 929 | int ret; | 975 | int ret; |
| 930 | 976 | ||
| 931 | inode = iget_locked(sb, ino); | 977 | inode = iget_locked(sb, ino); |
| @@ -937,7 +983,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) | |||
| 937 | __oi_init(oi); | 983 | __oi_init(oi); |
| 938 | 984 | ||
| 939 | /* read the inode from the osd */ | 985 | /* read the inode from the osd */ |
| 940 | ret = exofs_get_inode(sb, oi, &fcb, &obj_size); | 986 | ret = exofs_get_inode(sb, oi, &fcb); |
| 941 | if (ret) | 987 | if (ret) |
| 942 | goto bad_inode; | 988 | goto bad_inode; |
| 943 | 989 | ||
| @@ -958,13 +1004,6 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) | |||
| 958 | inode->i_blkbits = EXOFS_BLKSHIFT; | 1004 | inode->i_blkbits = EXOFS_BLKSHIFT; |
| 959 | inode->i_generation = le32_to_cpu(fcb.i_generation); | 1005 | inode->i_generation = le32_to_cpu(fcb.i_generation); |
| 960 | 1006 | ||
| 961 | if ((inode->i_size != obj_size) && | ||
| 962 | (!exofs_inode_is_fast_symlink(inode))) { | ||
| 963 | EXOFS_ERR("WARNING: Size of inode=%llu != object=%llu\n", | ||
| 964 | inode->i_size, _LLU(obj_size)); | ||
| 965 | /* FIXME: call exofs_inode_recovery() */ | ||
| 966 | } | ||
| 967 | |||
| 968 | oi->i_dir_start_lookup = 0; | 1007 | oi->i_dir_start_lookup = 0; |
| 969 | 1008 | ||
| 970 | if ((inode->i_nlink == 0) && (inode->i_mode == 0)) { | 1009 | if ((inode->i_nlink == 0) && (inode->i_mode == 0)) { |
| @@ -1043,7 +1082,7 @@ static void create_done(struct exofs_io_state *ios, void *p) | |||
| 1043 | 1082 | ||
| 1044 | if (unlikely(ret)) { | 1083 | if (unlikely(ret)) { |
| 1045 | EXOFS_ERR("object=0x%llx creation faild in pid=0x%llx", | 1084 | EXOFS_ERR("object=0x%llx creation faild in pid=0x%llx", |
| 1046 | _LLU(exofs_oi_objno(oi)), _LLU(sbi->s_pid)); | 1085 | _LLU(exofs_oi_objno(oi)), _LLU(sbi->layout.s_pid)); |
| 1047 | /*TODO: When FS is corrupted creation can fail, object already | 1086 | /*TODO: When FS is corrupted creation can fail, object already |
| 1048 | * exist. Get rid of this asynchronous creation, if exist | 1087 | * exist. Get rid of this asynchronous creation, if exist |
| 1049 | * increment the obj counter and try the next object. Until we | 1088 | * increment the obj counter and try the next object. Until we |
| @@ -1104,7 +1143,7 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) | |||
| 1104 | 1143 | ||
| 1105 | mark_inode_dirty(inode); | 1144 | mark_inode_dirty(inode); |
| 1106 | 1145 | ||
| 1107 | ret = exofs_get_io_state(sbi, &ios); | 1146 | ret = exofs_get_io_state(&sbi->layout, &ios); |
| 1108 | if (unlikely(ret)) { | 1147 | if (unlikely(ret)) { |
| 1109 | EXOFS_ERR("exofs_new_inode: exofs_get_io_state failed\n"); | 1148 | EXOFS_ERR("exofs_new_inode: exofs_get_io_state failed\n"); |
| 1110 | return ERR_PTR(ret); | 1149 | return ERR_PTR(ret); |
| @@ -1170,8 +1209,10 @@ static int exofs_update_inode(struct inode *inode, int do_sync) | |||
| 1170 | int ret; | 1209 | int ret; |
| 1171 | 1210 | ||
| 1172 | args = kzalloc(sizeof(*args), GFP_KERNEL); | 1211 | args = kzalloc(sizeof(*args), GFP_KERNEL); |
| 1173 | if (!args) | 1212 | if (!args) { |
| 1213 | EXOFS_DBGMSG("Faild kzalloc of args\n"); | ||
| 1174 | return -ENOMEM; | 1214 | return -ENOMEM; |
| 1215 | } | ||
| 1175 | 1216 | ||
| 1176 | fcb = &args->fcb; | 1217 | fcb = &args->fcb; |
| 1177 | 1218 | ||
| @@ -1200,7 +1241,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync) | |||
| 1200 | } else | 1241 | } else |
| 1201 | memcpy(fcb->i_data, oi->i_data, sizeof(fcb->i_data)); | 1242 | memcpy(fcb->i_data, oi->i_data, sizeof(fcb->i_data)); |
| 1202 | 1243 | ||
| 1203 | ret = exofs_get_io_state(sbi, &ios); | 1244 | ret = exofs_get_io_state(&sbi->layout, &ios); |
| 1204 | if (unlikely(ret)) { | 1245 | if (unlikely(ret)) { |
| 1205 | EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); | 1246 | EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); |
| 1206 | goto free_args; | 1247 | goto free_args; |
| @@ -1234,13 +1275,14 @@ static int exofs_update_inode(struct inode *inode, int do_sync) | |||
| 1234 | free_args: | 1275 | free_args: |
| 1235 | kfree(args); | 1276 | kfree(args); |
| 1236 | out: | 1277 | out: |
| 1237 | EXOFS_DBGMSG("ret=>%d\n", ret); | 1278 | EXOFS_DBGMSG("(0x%lx) do_sync=%d ret=>%d\n", |
| 1279 | inode->i_ino, do_sync, ret); | ||
| 1238 | return ret; | 1280 | return ret; |
| 1239 | } | 1281 | } |
| 1240 | 1282 | ||
| 1241 | int exofs_write_inode(struct inode *inode, int wait) | 1283 | int exofs_write_inode(struct inode *inode, struct writeback_control *wbc) |
| 1242 | { | 1284 | { |
| 1243 | return exofs_update_inode(inode, wait); | 1285 | return exofs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL); |
| 1244 | } | 1286 | } |
| 1245 | 1287 | ||
| 1246 | /* | 1288 | /* |
| @@ -1283,7 +1325,7 @@ void exofs_delete_inode(struct inode *inode) | |||
| 1283 | 1325 | ||
| 1284 | clear_inode(inode); | 1326 | clear_inode(inode); |
| 1285 | 1327 | ||
| 1286 | ret = exofs_get_io_state(sbi, &ios); | 1328 | ret = exofs_get_io_state(&sbi->layout, &ios); |
| 1287 | if (unlikely(ret)) { | 1329 | if (unlikely(ret)) { |
| 1288 | EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__); | 1330 | EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__); |
| 1289 | return; | 1331 | return; |
