diff options
Diffstat (limited to 'fs/nilfs2/dir.c')
| -rw-r--r-- | fs/nilfs2/dir.c | 58 |
1 files changed, 22 insertions, 36 deletions
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 85c89dfc71f..cb003c8ee1f 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c | |||
| @@ -80,23 +80,10 @@ static unsigned nilfs_last_byte(struct inode *inode, unsigned long page_nr) | |||
| 80 | return last_byte; | 80 | return last_byte; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static int nilfs_prepare_chunk_uninterruptible(struct page *page, | 83 | static int nilfs_prepare_chunk(struct page *page, unsigned from, unsigned to) |
| 84 | struct address_space *mapping, | ||
| 85 | unsigned from, unsigned to) | ||
| 86 | { | 84 | { |
| 87 | loff_t pos = page_offset(page) + from; | 85 | loff_t pos = page_offset(page) + from; |
| 88 | return block_write_begin(NULL, mapping, pos, to - from, | 86 | return __block_write_begin(page, pos, to - from, nilfs_get_block); |
| 89 | AOP_FLAG_UNINTERRUPTIBLE, &page, | ||
| 90 | NULL, nilfs_get_block); | ||
| 91 | } | ||
| 92 | |||
| 93 | static int nilfs_prepare_chunk(struct page *page, | ||
| 94 | struct address_space *mapping, | ||
| 95 | unsigned from, unsigned to) | ||
| 96 | { | ||
| 97 | loff_t pos = page_offset(page) + from; | ||
| 98 | return block_write_begin(NULL, mapping, pos, to - from, 0, &page, | ||
| 99 | NULL, nilfs_get_block); | ||
| 100 | } | 87 | } |
| 101 | 88 | ||
| 102 | static void nilfs_commit_chunk(struct page *page, | 89 | static void nilfs_commit_chunk(struct page *page, |
| @@ -141,7 +128,7 @@ static void nilfs_check_page(struct page *page) | |||
| 141 | } | 128 | } |
| 142 | for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) { | 129 | for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) { |
| 143 | p = (struct nilfs_dir_entry *)(kaddr + offs); | 130 | p = (struct nilfs_dir_entry *)(kaddr + offs); |
| 144 | rec_len = le16_to_cpu(p->rec_len); | 131 | rec_len = nilfs_rec_len_from_disk(p->rec_len); |
| 145 | 132 | ||
| 146 | if (rec_len < NILFS_DIR_REC_LEN(1)) | 133 | if (rec_len < NILFS_DIR_REC_LEN(1)) |
| 147 | goto Eshort; | 134 | goto Eshort; |
| @@ -199,13 +186,10 @@ fail: | |||
| 199 | static struct page *nilfs_get_page(struct inode *dir, unsigned long n) | 186 | static struct page *nilfs_get_page(struct inode *dir, unsigned long n) |
| 200 | { | 187 | { |
| 201 | struct address_space *mapping = dir->i_mapping; | 188 | struct address_space *mapping = dir->i_mapping; |
| 202 | struct page *page = read_cache_page(mapping, n, | 189 | struct page *page = read_mapping_page(mapping, n, NULL); |
| 203 | (filler_t *)mapping->a_ops->readpage, NULL); | 190 | |
| 204 | if (!IS_ERR(page)) { | 191 | if (!IS_ERR(page)) { |
| 205 | wait_on_page_locked(page); | ||
| 206 | kmap(page); | 192 | kmap(page); |
| 207 | if (!PageUptodate(page)) | ||
| 208 | goto fail; | ||
| 209 | if (!PageChecked(page)) | 193 | if (!PageChecked(page)) |
| 210 | nilfs_check_page(page); | 194 | nilfs_check_page(page); |
| 211 | if (PageError(page)) | 195 | if (PageError(page)) |
| @@ -238,7 +222,8 @@ nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de) | |||
| 238 | */ | 222 | */ |
| 239 | static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p) | 223 | static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p) |
| 240 | { | 224 | { |
| 241 | return (struct nilfs_dir_entry *)((char *)p + le16_to_cpu(p->rec_len)); | 225 | return (struct nilfs_dir_entry *)((char *)p + |
| 226 | nilfs_rec_len_from_disk(p->rec_len)); | ||
| 242 | } | 227 | } |
| 243 | 228 | ||
| 244 | static unsigned char | 229 | static unsigned char |
| @@ -329,7 +314,7 @@ static int nilfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 329 | goto success; | 314 | goto success; |
| 330 | } | 315 | } |
| 331 | } | 316 | } |
| 332 | filp->f_pos += le16_to_cpu(de->rec_len); | 317 | filp->f_pos += nilfs_rec_len_from_disk(de->rec_len); |
| 333 | } | 318 | } |
| 334 | nilfs_put_page(page); | 319 | nilfs_put_page(page); |
| 335 | } | 320 | } |
| @@ -444,12 +429,12 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, | |||
| 444 | struct page *page, struct inode *inode) | 429 | struct page *page, struct inode *inode) |
| 445 | { | 430 | { |
| 446 | unsigned from = (char *) de - (char *) page_address(page); | 431 | unsigned from = (char *) de - (char *) page_address(page); |
| 447 | unsigned to = from + le16_to_cpu(de->rec_len); | 432 | unsigned to = from + nilfs_rec_len_from_disk(de->rec_len); |
| 448 | struct address_space *mapping = page->mapping; | 433 | struct address_space *mapping = page->mapping; |
| 449 | int err; | 434 | int err; |
| 450 | 435 | ||
| 451 | lock_page(page); | 436 | lock_page(page); |
| 452 | err = nilfs_prepare_chunk_uninterruptible(page, mapping, from, to); | 437 | err = nilfs_prepare_chunk(page, from, to); |
| 453 | BUG_ON(err); | 438 | BUG_ON(err); |
| 454 | de->inode = cpu_to_le64(inode->i_ino); | 439 | de->inode = cpu_to_le64(inode->i_ino); |
| 455 | nilfs_set_de_type(de, inode); | 440 | nilfs_set_de_type(de, inode); |
| @@ -500,7 +485,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) | |||
| 500 | /* We hit i_size */ | 485 | /* We hit i_size */ |
| 501 | name_len = 0; | 486 | name_len = 0; |
| 502 | rec_len = chunk_size; | 487 | rec_len = chunk_size; |
| 503 | de->rec_len = cpu_to_le16(chunk_size); | 488 | de->rec_len = nilfs_rec_len_to_disk(chunk_size); |
| 504 | de->inode = 0; | 489 | de->inode = 0; |
| 505 | goto got_it; | 490 | goto got_it; |
| 506 | } | 491 | } |
| @@ -514,7 +499,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) | |||
| 514 | if (nilfs_match(namelen, name, de)) | 499 | if (nilfs_match(namelen, name, de)) |
| 515 | goto out_unlock; | 500 | goto out_unlock; |
| 516 | name_len = NILFS_DIR_REC_LEN(de->name_len); | 501 | name_len = NILFS_DIR_REC_LEN(de->name_len); |
| 517 | rec_len = le16_to_cpu(de->rec_len); | 502 | rec_len = nilfs_rec_len_from_disk(de->rec_len); |
| 518 | if (!de->inode && rec_len >= reclen) | 503 | if (!de->inode && rec_len >= reclen) |
| 519 | goto got_it; | 504 | goto got_it; |
| 520 | if (rec_len >= name_len + reclen) | 505 | if (rec_len >= name_len + reclen) |
| @@ -530,15 +515,15 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) | |||
| 530 | got_it: | 515 | got_it: |
| 531 | from = (char *)de - (char *)page_address(page); | 516 | from = (char *)de - (char *)page_address(page); |
| 532 | to = from + rec_len; | 517 | to = from + rec_len; |
| 533 | err = nilfs_prepare_chunk(page, page->mapping, from, to); | 518 | err = nilfs_prepare_chunk(page, from, to); |
| 534 | if (err) | 519 | if (err) |
| 535 | goto out_unlock; | 520 | goto out_unlock; |
| 536 | if (de->inode) { | 521 | if (de->inode) { |
| 537 | struct nilfs_dir_entry *de1; | 522 | struct nilfs_dir_entry *de1; |
| 538 | 523 | ||
| 539 | de1 = (struct nilfs_dir_entry *)((char *)de + name_len); | 524 | de1 = (struct nilfs_dir_entry *)((char *)de + name_len); |
| 540 | de1->rec_len = cpu_to_le16(rec_len - name_len); | 525 | de1->rec_len = nilfs_rec_len_to_disk(rec_len - name_len); |
| 541 | de->rec_len = cpu_to_le16(name_len); | 526 | de->rec_len = nilfs_rec_len_to_disk(name_len); |
| 542 | de = de1; | 527 | de = de1; |
| 543 | } | 528 | } |
| 544 | de->name_len = namelen; | 529 | de->name_len = namelen; |
| @@ -569,7 +554,8 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) | |||
| 569 | struct inode *inode = mapping->host; | 554 | struct inode *inode = mapping->host; |
| 570 | char *kaddr = page_address(page); | 555 | char *kaddr = page_address(page); |
| 571 | unsigned from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1); | 556 | unsigned from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1); |
| 572 | unsigned to = ((char *)dir - kaddr) + le16_to_cpu(dir->rec_len); | 557 | unsigned to = ((char *)dir - kaddr) + |
| 558 | nilfs_rec_len_from_disk(dir->rec_len); | ||
| 573 | struct nilfs_dir_entry *pde = NULL; | 559 | struct nilfs_dir_entry *pde = NULL; |
| 574 | struct nilfs_dir_entry *de = (struct nilfs_dir_entry *)(kaddr + from); | 560 | struct nilfs_dir_entry *de = (struct nilfs_dir_entry *)(kaddr + from); |
| 575 | int err; | 561 | int err; |
| @@ -587,10 +573,10 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) | |||
| 587 | if (pde) | 573 | if (pde) |
| 588 | from = (char *)pde - (char *)page_address(page); | 574 | from = (char *)pde - (char *)page_address(page); |
| 589 | lock_page(page); | 575 | lock_page(page); |
| 590 | err = nilfs_prepare_chunk(page, mapping, from, to); | 576 | err = nilfs_prepare_chunk(page, from, to); |
| 591 | BUG_ON(err); | 577 | BUG_ON(err); |
| 592 | if (pde) | 578 | if (pde) |
| 593 | pde->rec_len = cpu_to_le16(to - from); | 579 | pde->rec_len = nilfs_rec_len_to_disk(to - from); |
| 594 | dir->inode = 0; | 580 | dir->inode = 0; |
| 595 | nilfs_commit_chunk(page, mapping, from, to); | 581 | nilfs_commit_chunk(page, mapping, from, to); |
| 596 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | 582 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; |
| @@ -615,7 +601,7 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent) | |||
| 615 | if (!page) | 601 | if (!page) |
| 616 | return -ENOMEM; | 602 | return -ENOMEM; |
| 617 | 603 | ||
| 618 | err = nilfs_prepare_chunk(page, mapping, 0, chunk_size); | 604 | err = nilfs_prepare_chunk(page, 0, chunk_size); |
| 619 | if (unlikely(err)) { | 605 | if (unlikely(err)) { |
| 620 | unlock_page(page); | 606 | unlock_page(page); |
| 621 | goto fail; | 607 | goto fail; |
| @@ -624,14 +610,14 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent) | |||
| 624 | memset(kaddr, 0, chunk_size); | 610 | memset(kaddr, 0, chunk_size); |
| 625 | de = (struct nilfs_dir_entry *)kaddr; | 611 | de = (struct nilfs_dir_entry *)kaddr; |
| 626 | de->name_len = 1; | 612 | de->name_len = 1; |
| 627 | de->rec_len = cpu_to_le16(NILFS_DIR_REC_LEN(1)); | 613 | de->rec_len = nilfs_rec_len_to_disk(NILFS_DIR_REC_LEN(1)); |
| 628 | memcpy(de->name, ".\0\0", 4); | 614 | memcpy(de->name, ".\0\0", 4); |
| 629 | de->inode = cpu_to_le64(inode->i_ino); | 615 | de->inode = cpu_to_le64(inode->i_ino); |
| 630 | nilfs_set_de_type(de, inode); | 616 | nilfs_set_de_type(de, inode); |
| 631 | 617 | ||
| 632 | de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1)); | 618 | de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1)); |
| 633 | de->name_len = 2; | 619 | de->name_len = 2; |
| 634 | de->rec_len = cpu_to_le16(chunk_size - NILFS_DIR_REC_LEN(1)); | 620 | de->rec_len = nilfs_rec_len_to_disk(chunk_size - NILFS_DIR_REC_LEN(1)); |
| 635 | de->inode = cpu_to_le64(parent->i_ino); | 621 | de->inode = cpu_to_le64(parent->i_ino); |
| 636 | memcpy(de->name, "..\0", 4); | 622 | memcpy(de->name, "..\0", 4); |
| 637 | nilfs_set_de_type(de, inode); | 623 | nilfs_set_de_type(de, inode); |
