Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nilfs2: convert checkpoint file to be folio-based

Regarding the cpfile, a metadata file that manages checkpoints, convert
the page-based implementation to a folio-based implementation.

This change involves some helper functions to calculate byte offsets on
folios and removing a few helper functions that are no longer needed.

Link: https://lkml.kernel.org/r/20241024092602.13395-9-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ryusuke Konishi and committed by
Andrew Morton
a6cb5b1e cdee1796

+204 -175
+204 -175
fs/nilfs2/cpfile.c
··· 68 68 static unsigned int 69 69 nilfs_cpfile_block_add_valid_checkpoints(const struct inode *cpfile, 70 70 struct buffer_head *bh, 71 - void *kaddr, 72 71 unsigned int n) 73 72 { 74 - struct nilfs_checkpoint *cp = kaddr + bh_offset(bh); 73 + struct nilfs_checkpoint *cp; 75 74 unsigned int count; 76 75 76 + cp = kmap_local_folio(bh->b_folio, 77 + offset_in_folio(bh->b_folio, bh->b_data)); 77 78 count = le32_to_cpu(cp->cp_checkpoints_count) + n; 78 79 cp->cp_checkpoints_count = cpu_to_le32(count); 80 + kunmap_local(cp); 79 81 return count; 80 82 } 81 83 82 84 static unsigned int 83 85 nilfs_cpfile_block_sub_valid_checkpoints(const struct inode *cpfile, 84 86 struct buffer_head *bh, 85 - void *kaddr, 86 87 unsigned int n) 87 88 { 88 - struct nilfs_checkpoint *cp = kaddr + bh_offset(bh); 89 + struct nilfs_checkpoint *cp; 89 90 unsigned int count; 90 91 92 + cp = kmap_local_folio(bh->b_folio, 93 + offset_in_folio(bh->b_folio, bh->b_data)); 91 94 WARN_ON(le32_to_cpu(cp->cp_checkpoints_count) < n); 92 95 count = le32_to_cpu(cp->cp_checkpoints_count) - n; 93 96 cp->cp_checkpoints_count = cpu_to_le32(count); 97 + kunmap_local(cp); 94 98 return count; 95 - } 96 - 97 - static inline struct nilfs_cpfile_header * 98 - nilfs_cpfile_block_get_header(const struct inode *cpfile, 99 - struct buffer_head *bh, 100 - void *kaddr) 101 - { 102 - return kaddr + bh_offset(bh); 103 - } 104 - 105 - static struct nilfs_checkpoint * 106 - nilfs_cpfile_block_get_checkpoint(const struct inode *cpfile, __u64 cno, 107 - struct buffer_head *bh, 108 - void *kaddr) 109 - { 110 - return kaddr + bh_offset(bh) + nilfs_cpfile_get_offset(cpfile, cno) * 111 - NILFS_MDT(cpfile)->mi_entry_size; 112 99 } 113 100 114 101 static void nilfs_cpfile_block_init(struct inode *cpfile, ··· 110 123 nilfs_checkpoint_set_invalid(cp); 111 124 cp = (void *)cp + cpsz; 112 125 } 126 + } 127 + 128 + /** 129 + * nilfs_cpfile_checkpoint_offset - calculate the byte offset of a checkpoint 130 + * entry in the folio containing it 131 + * @cpfile: checkpoint file inode 132 + * @cno: checkpoint number 133 + * @bh: buffer head of block containing checkpoint indexed by @cno 134 + * 135 + * Return: Byte offset in the folio of the checkpoint specified by @cno. 136 + */ 137 + static size_t nilfs_cpfile_checkpoint_offset(const struct inode *cpfile, 138 + __u64 cno, 139 + struct buffer_head *bh) 140 + { 141 + return offset_in_folio(bh->b_folio, bh->b_data) + 142 + nilfs_cpfile_get_offset(cpfile, cno) * 143 + NILFS_MDT(cpfile)->mi_entry_size; 144 + } 145 + 146 + /** 147 + * nilfs_cpfile_cp_snapshot_list_offset - calculate the byte offset of a 148 + * checkpoint snapshot list in the folio 149 + * containing it 150 + * @cpfile: checkpoint file inode 151 + * @cno: checkpoint number 152 + * @bh: buffer head of block containing checkpoint indexed by @cno 153 + * 154 + * Return: Byte offset in the folio of the checkpoint snapshot list specified 155 + * by @cno. 156 + */ 157 + static size_t nilfs_cpfile_cp_snapshot_list_offset(const struct inode *cpfile, 158 + __u64 cno, 159 + struct buffer_head *bh) 160 + { 161 + return nilfs_cpfile_checkpoint_offset(cpfile, cno, bh) + 162 + offsetof(struct nilfs_checkpoint, cp_snapshot_list); 163 + } 164 + 165 + /** 166 + * nilfs_cpfile_ch_snapshot_list_offset - calculate the byte offset of the 167 + * snapshot list in the header 168 + * 169 + * Return: Byte offset in the folio of the checkpoint snapshot list 170 + */ 171 + static size_t nilfs_cpfile_ch_snapshot_list_offset(void) 172 + { 173 + return offsetof(struct nilfs_cpfile_header, ch_snapshot_list); 113 174 } 114 175 115 176 static int nilfs_cpfile_get_header_block(struct inode *cpfile, ··· 249 214 { 250 215 struct buffer_head *cp_bh; 251 216 struct nilfs_checkpoint *cp; 252 - void *kaddr; 217 + size_t offset; 253 218 int ret; 254 219 255 220 if (cno < 1 || cno > nilfs_mdt_cno(cpfile)) ··· 263 228 goto out_sem; 264 229 } 265 230 266 - kaddr = kmap_local_page(cp_bh->b_page); 267 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 231 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, cp_bh); 232 + cp = kmap_local_folio(cp_bh->b_folio, offset); 268 233 if (nilfs_checkpoint_invalid(cp)) { 269 234 ret = -EINVAL; 270 235 goto put_cp; ··· 289 254 root->ifile = ifile; 290 255 291 256 put_cp: 292 - kunmap_local(kaddr); 257 + kunmap_local(cp); 293 258 brelse(cp_bh); 294 259 out_sem: 295 260 up_read(&NILFS_MDT(cpfile)->mi_sem); ··· 317 282 struct buffer_head *header_bh, *cp_bh; 318 283 struct nilfs_cpfile_header *header; 319 284 struct nilfs_checkpoint *cp; 320 - void *kaddr; 285 + size_t offset; 321 286 int ret; 322 287 323 288 if (WARN_ON_ONCE(cno < 1)) ··· 332 297 if (unlikely(ret < 0)) 333 298 goto out_header; 334 299 335 - kaddr = kmap_local_page(cp_bh->b_page); 336 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 300 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, cp_bh); 301 + cp = kmap_local_folio(cp_bh->b_folio, offset); 337 302 if (nilfs_checkpoint_invalid(cp)) { 338 303 /* a newly-created checkpoint */ 339 304 nilfs_checkpoint_clear_invalid(cp); 305 + kunmap_local(cp); 340 306 if (!nilfs_cpfile_is_in_first(cpfile, cno)) 341 307 nilfs_cpfile_block_add_valid_checkpoints(cpfile, cp_bh, 342 - kaddr, 1); 343 - kunmap_local(kaddr); 308 + 1); 344 309 345 - kaddr = kmap_local_page(header_bh->b_page); 346 - header = nilfs_cpfile_block_get_header(cpfile, header_bh, 347 - kaddr); 310 + header = kmap_local_folio(header_bh->b_folio, 0); 348 311 le64_add_cpu(&header->ch_ncheckpoints, 1); 349 - kunmap_local(kaddr); 312 + kunmap_local(header); 350 313 mark_buffer_dirty(header_bh); 351 314 } else { 352 - kunmap_local(kaddr); 315 + kunmap_local(cp); 353 316 } 354 317 355 318 /* Force the buffer and the inode to become dirty */ ··· 386 353 { 387 354 struct buffer_head *cp_bh; 388 355 struct nilfs_checkpoint *cp; 389 - void *kaddr; 356 + size_t offset; 390 357 int ret; 391 358 392 359 if (WARN_ON_ONCE(cno < 1)) ··· 400 367 goto out_sem; 401 368 } 402 369 403 - kaddr = kmap_local_page(cp_bh->b_page); 404 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 370 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, cp_bh); 371 + cp = kmap_local_folio(cp_bh->b_folio, offset); 405 372 if (unlikely(nilfs_checkpoint_invalid(cp))) { 406 - kunmap_local(kaddr); 373 + kunmap_local(cp); 407 374 brelse(cp_bh); 408 375 goto error; 409 376 } ··· 424 391 nilfs_write_inode_common(root->ifile, &cp->cp_ifile_inode); 425 392 nilfs_bmap_write(NILFS_I(root->ifile)->i_bmap, &cp->cp_ifile_inode); 426 393 427 - kunmap_local(kaddr); 394 + kunmap_local(cp); 428 395 brelse(cp_bh); 429 396 out_sem: 430 397 up_write(&NILFS_MDT(cpfile)->mi_sem); ··· 465 432 struct nilfs_checkpoint *cp; 466 433 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 467 434 __u64 cno; 435 + size_t offset; 468 436 void *kaddr; 469 437 unsigned long tnicps; 470 438 int ret, ncps, nicps, nss, count, i; ··· 496 462 continue; 497 463 } 498 464 499 - kaddr = kmap_local_page(cp_bh->b_page); 500 - cp = nilfs_cpfile_block_get_checkpoint( 501 - cpfile, cno, cp_bh, kaddr); 465 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, cp_bh); 466 + cp = kaddr = kmap_local_folio(cp_bh->b_folio, offset); 502 467 nicps = 0; 503 468 for (i = 0; i < ncps; i++, cp = (void *)cp + cpsz) { 504 469 if (nilfs_checkpoint_snapshot(cp)) { ··· 507 474 nicps++; 508 475 } 509 476 } 510 - if (nicps > 0) { 511 - tnicps += nicps; 512 - mark_buffer_dirty(cp_bh); 513 - nilfs_mdt_mark_dirty(cpfile); 514 - if (!nilfs_cpfile_is_in_first(cpfile, cno)) { 515 - count = 516 - nilfs_cpfile_block_sub_valid_checkpoints( 517 - cpfile, cp_bh, kaddr, nicps); 518 - if (count == 0) { 519 - /* make hole */ 520 - kunmap_local(kaddr); 521 - brelse(cp_bh); 522 - ret = 523 - nilfs_cpfile_delete_checkpoint_block( 524 - cpfile, cno); 525 - if (ret == 0) 526 - continue; 527 - nilfs_err(cpfile->i_sb, 528 - "error %d deleting checkpoint block", 529 - ret); 530 - break; 531 - } 532 - } 477 + kunmap_local(kaddr); 478 + 479 + if (nicps <= 0) { 480 + brelse(cp_bh); 481 + continue; 533 482 } 534 483 535 - kunmap_local(kaddr); 484 + tnicps += nicps; 485 + mark_buffer_dirty(cp_bh); 486 + nilfs_mdt_mark_dirty(cpfile); 487 + if (nilfs_cpfile_is_in_first(cpfile, cno)) { 488 + brelse(cp_bh); 489 + continue; 490 + } 491 + 492 + count = nilfs_cpfile_block_sub_valid_checkpoints(cpfile, cp_bh, 493 + nicps); 536 494 brelse(cp_bh); 495 + if (count) 496 + continue; 497 + 498 + /* Delete the block if there are no more valid checkpoints */ 499 + ret = nilfs_cpfile_delete_checkpoint_block(cpfile, cno); 500 + if (unlikely(ret)) { 501 + nilfs_err(cpfile->i_sb, 502 + "error %d deleting checkpoint block", ret); 503 + break; 504 + } 537 505 } 538 506 539 507 if (tnicps > 0) { 540 - kaddr = kmap_local_page(header_bh->b_page); 541 - header = nilfs_cpfile_block_get_header(cpfile, header_bh, 542 - kaddr); 508 + header = kmap_local_folio(header_bh->b_folio, 0); 543 509 le64_add_cpu(&header->ch_ncheckpoints, -(u64)tnicps); 544 510 mark_buffer_dirty(header_bh); 545 511 nilfs_mdt_mark_dirty(cpfile); 546 - kunmap_local(kaddr); 512 + kunmap_local(header); 547 513 } 548 514 549 515 brelse(header_bh); ··· 576 544 struct buffer_head *bh; 577 545 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 578 546 __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop; 547 + size_t offset; 579 548 void *kaddr; 580 549 int n, ret; 581 550 int ncps, i; ··· 595 562 } 596 563 ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno); 597 564 598 - kaddr = kmap_local_page(bh->b_page); 599 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 565 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, bh); 566 + cp = kaddr = kmap_local_folio(bh->b_folio, offset); 600 567 for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) { 601 568 if (!nilfs_checkpoint_invalid(cp)) { 602 569 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, ··· 630 597 struct nilfs_cpinfo *ci = buf; 631 598 __u64 curr = *cnop, next; 632 599 unsigned long curr_blkoff, next_blkoff; 633 - void *kaddr; 600 + size_t offset; 634 601 int n = 0, ret; 635 602 636 603 down_read(&NILFS_MDT(cpfile)->mi_sem); ··· 639 606 ret = nilfs_cpfile_get_header_block(cpfile, &bh); 640 607 if (ret < 0) 641 608 goto out; 642 - kaddr = kmap_local_page(bh->b_page); 643 - header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 609 + header = kmap_local_folio(bh->b_folio, 0); 644 610 curr = le64_to_cpu(header->ch_snapshot_list.ssl_next); 645 - kunmap_local(kaddr); 611 + kunmap_local(header); 646 612 brelse(bh); 647 613 if (curr == 0) { 648 614 ret = 0; ··· 659 627 ret = 0; /* No snapshots (started from a hole block) */ 660 628 goto out; 661 629 } 662 - kaddr = kmap_local_page(bh->b_page); 630 + offset = nilfs_cpfile_checkpoint_offset(cpfile, curr, bh); 631 + cp = kmap_local_folio(bh->b_folio, offset); 663 632 while (n < nci) { 664 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, curr, bh, kaddr); 665 633 curr = ~(__u64)0; /* Terminator */ 666 634 if (unlikely(nilfs_checkpoint_invalid(cp) || 667 635 !nilfs_checkpoint_snapshot(cp))) ··· 673 641 if (next == 0) 674 642 break; /* reach end of the snapshot list */ 675 643 644 + kunmap_local(cp); 676 645 next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next); 677 646 if (curr_blkoff != next_blkoff) { 678 - kunmap_local(kaddr); 679 647 brelse(bh); 680 648 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 681 649 0, &bh); ··· 683 651 WARN_ON(ret == -ENOENT); 684 652 goto out; 685 653 } 686 - kaddr = kmap_local_page(bh->b_page); 687 654 } 655 + offset = nilfs_cpfile_checkpoint_offset(cpfile, next, bh); 656 + cp = kmap_local_folio(bh->b_folio, offset); 688 657 curr = next; 689 658 curr_blkoff = next_blkoff; 690 659 } 691 - kunmap_local(kaddr); 660 + kunmap_local(cp); 692 661 brelse(bh); 693 662 *cnop = curr; 694 663 ret = n; ··· 766 733 return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1); 767 734 } 768 735 769 - static struct nilfs_snapshot_list * 770 - nilfs_cpfile_block_get_snapshot_list(const struct inode *cpfile, 771 - __u64 cno, 772 - struct buffer_head *bh, 773 - void *kaddr) 774 - { 775 - struct nilfs_cpfile_header *header; 776 - struct nilfs_checkpoint *cp; 777 - struct nilfs_snapshot_list *list; 778 - 779 - if (cno != 0) { 780 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 781 - list = &cp->cp_snapshot_list; 782 - } else { 783 - header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 784 - list = &header->ch_snapshot_list; 785 - } 786 - return list; 787 - } 788 - 789 736 static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno) 790 737 { 791 738 struct buffer_head *header_bh, *curr_bh, *prev_bh, *cp_bh; ··· 774 761 struct nilfs_snapshot_list *list; 775 762 __u64 curr, prev; 776 763 unsigned long curr_blkoff, prev_blkoff; 777 - void *kaddr; 764 + size_t offset, curr_list_offset, prev_list_offset; 778 765 int ret; 779 766 780 767 if (cno == 0) 781 768 return -ENOENT; /* checkpoint number 0 is invalid */ 782 769 down_write(&NILFS_MDT(cpfile)->mi_sem); 783 770 771 + ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 772 + if (unlikely(ret < 0)) 773 + goto out_sem; 774 + 784 775 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 785 776 if (ret < 0) 786 - goto out_sem; 787 - kaddr = kmap_local_page(cp_bh->b_page); 788 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 777 + goto out_header; 778 + 779 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, cp_bh); 780 + cp = kmap_local_folio(cp_bh->b_folio, offset); 789 781 if (nilfs_checkpoint_invalid(cp)) { 790 782 ret = -ENOENT; 791 - kunmap_local(kaddr); 783 + kunmap_local(cp); 792 784 goto out_cp; 793 785 } 794 786 if (nilfs_checkpoint_snapshot(cp)) { 795 787 ret = 0; 796 - kunmap_local(kaddr); 788 + kunmap_local(cp); 797 789 goto out_cp; 798 790 } 799 - kunmap_local(kaddr); 791 + kunmap_local(cp); 800 792 801 - ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 802 - if (ret < 0) 803 - goto out_cp; 804 - kaddr = kmap_local_page(header_bh->b_page); 805 - header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 793 + /* 794 + * Find the last snapshot before the checkpoint being changed to 795 + * snapshot mode by going backwards through the snapshot list. 796 + * Set "prev" to its checkpoint number, or 0 if not found. 797 + */ 798 + header = kmap_local_folio(header_bh->b_folio, 0); 806 799 list = &header->ch_snapshot_list; 807 800 curr_bh = header_bh; 808 801 get_bh(curr_bh); 809 802 curr = 0; 810 803 curr_blkoff = 0; 804 + curr_list_offset = nilfs_cpfile_ch_snapshot_list_offset(); 811 805 prev = le64_to_cpu(list->ssl_prev); 812 806 while (prev > cno) { 813 807 prev_blkoff = nilfs_cpfile_get_blkoff(cpfile, prev); 814 808 curr = prev; 809 + kunmap_local(list); 815 810 if (curr_blkoff != prev_blkoff) { 816 - kunmap_local(kaddr); 817 811 brelse(curr_bh); 818 812 ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 819 813 0, &curr_bh); 820 - if (ret < 0) 821 - goto out_header; 822 - kaddr = kmap_local_page(curr_bh->b_page); 814 + if (unlikely(ret < 0)) 815 + goto out_cp; 823 816 } 817 + curr_list_offset = nilfs_cpfile_cp_snapshot_list_offset( 818 + cpfile, curr, curr_bh); 819 + list = kmap_local_folio(curr_bh->b_folio, curr_list_offset); 824 820 curr_blkoff = prev_blkoff; 825 - cp = nilfs_cpfile_block_get_checkpoint( 826 - cpfile, curr, curr_bh, kaddr); 827 - list = &cp->cp_snapshot_list; 828 821 prev = le64_to_cpu(list->ssl_prev); 829 822 } 830 - kunmap_local(kaddr); 823 + kunmap_local(list); 831 824 832 825 if (prev != 0) { 833 826 ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0, 834 827 &prev_bh); 835 828 if (ret < 0) 836 829 goto out_curr; 830 + 831 + prev_list_offset = nilfs_cpfile_cp_snapshot_list_offset( 832 + cpfile, prev, prev_bh); 837 833 } else { 838 834 prev_bh = header_bh; 839 835 get_bh(prev_bh); 836 + prev_list_offset = nilfs_cpfile_ch_snapshot_list_offset(); 840 837 } 841 838 842 - kaddr = kmap_local_page(curr_bh->b_page); 843 - list = nilfs_cpfile_block_get_snapshot_list( 844 - cpfile, curr, curr_bh, kaddr); 839 + /* Update the list entry for the next snapshot */ 840 + list = kmap_local_folio(curr_bh->b_folio, curr_list_offset); 845 841 list->ssl_prev = cpu_to_le64(cno); 846 - kunmap_local(kaddr); 842 + kunmap_local(list); 847 843 848 - kaddr = kmap_local_page(cp_bh->b_page); 849 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 844 + /* Update the checkpoint being changed to a snapshot */ 845 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, cp_bh); 846 + cp = kmap_local_folio(cp_bh->b_folio, offset); 850 847 cp->cp_snapshot_list.ssl_next = cpu_to_le64(curr); 851 848 cp->cp_snapshot_list.ssl_prev = cpu_to_le64(prev); 852 849 nilfs_checkpoint_set_snapshot(cp); 853 - kunmap_local(kaddr); 850 + kunmap_local(cp); 854 851 855 - kaddr = kmap_local_page(prev_bh->b_page); 856 - list = nilfs_cpfile_block_get_snapshot_list( 857 - cpfile, prev, prev_bh, kaddr); 852 + /* Update the list entry for the previous snapshot */ 853 + list = kmap_local_folio(prev_bh->b_folio, prev_list_offset); 858 854 list->ssl_next = cpu_to_le64(cno); 859 - kunmap_local(kaddr); 855 + kunmap_local(list); 860 856 861 - kaddr = kmap_local_page(header_bh->b_page); 862 - header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 857 + /* Update the statistics in the header */ 858 + header = kmap_local_folio(header_bh->b_folio, 0); 863 859 le64_add_cpu(&header->ch_nsnapshots, 1); 864 - kunmap_local(kaddr); 860 + kunmap_local(header); 865 861 866 862 mark_buffer_dirty(prev_bh); 867 863 mark_buffer_dirty(curr_bh); ··· 883 861 out_curr: 884 862 brelse(curr_bh); 885 863 886 - out_header: 887 - brelse(header_bh); 888 - 889 864 out_cp: 890 865 brelse(cp_bh); 866 + 867 + out_header: 868 + brelse(header_bh); 891 869 892 870 out_sem: 893 871 up_write(&NILFS_MDT(cpfile)->mi_sem); ··· 901 879 struct nilfs_checkpoint *cp; 902 880 struct nilfs_snapshot_list *list; 903 881 __u64 next, prev; 904 - void *kaddr; 882 + size_t offset, next_list_offset, prev_list_offset; 905 883 int ret; 906 884 907 885 if (cno == 0) 908 886 return -ENOENT; /* checkpoint number 0 is invalid */ 909 887 down_write(&NILFS_MDT(cpfile)->mi_sem); 910 888 889 + ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 890 + if (unlikely(ret < 0)) 891 + goto out_sem; 892 + 911 893 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 912 894 if (ret < 0) 913 - goto out_sem; 914 - kaddr = kmap_local_page(cp_bh->b_page); 915 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 895 + goto out_header; 896 + 897 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, cp_bh); 898 + cp = kmap_local_folio(cp_bh->b_folio, offset); 916 899 if (nilfs_checkpoint_invalid(cp)) { 917 900 ret = -ENOENT; 918 - kunmap_local(kaddr); 901 + kunmap_local(cp); 919 902 goto out_cp; 920 903 } 921 904 if (!nilfs_checkpoint_snapshot(cp)) { 922 905 ret = 0; 923 - kunmap_local(kaddr); 906 + kunmap_local(cp); 924 907 goto out_cp; 925 908 } 926 909 927 910 list = &cp->cp_snapshot_list; 928 911 next = le64_to_cpu(list->ssl_next); 929 912 prev = le64_to_cpu(list->ssl_prev); 930 - kunmap_local(kaddr); 913 + kunmap_local(cp); 931 914 932 - ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 933 - if (ret < 0) 934 - goto out_cp; 935 915 if (next != 0) { 936 916 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 0, 937 917 &next_bh); 938 918 if (ret < 0) 939 - goto out_header; 919 + goto out_cp; 920 + 921 + next_list_offset = nilfs_cpfile_cp_snapshot_list_offset( 922 + cpfile, next, next_bh); 940 923 } else { 941 924 next_bh = header_bh; 942 925 get_bh(next_bh); 926 + next_list_offset = nilfs_cpfile_ch_snapshot_list_offset(); 943 927 } 944 928 if (prev != 0) { 945 929 ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0, 946 930 &prev_bh); 947 931 if (ret < 0) 948 932 goto out_next; 933 + 934 + prev_list_offset = nilfs_cpfile_cp_snapshot_list_offset( 935 + cpfile, prev, prev_bh); 949 936 } else { 950 937 prev_bh = header_bh; 951 938 get_bh(prev_bh); 939 + prev_list_offset = nilfs_cpfile_ch_snapshot_list_offset(); 952 940 } 953 941 954 - kaddr = kmap_local_page(next_bh->b_page); 955 - list = nilfs_cpfile_block_get_snapshot_list( 956 - cpfile, next, next_bh, kaddr); 942 + /* Update the list entry for the next snapshot */ 943 + list = kmap_local_folio(next_bh->b_folio, next_list_offset); 957 944 list->ssl_prev = cpu_to_le64(prev); 958 - kunmap_local(kaddr); 945 + kunmap_local(list); 959 946 960 - kaddr = kmap_local_page(prev_bh->b_page); 961 - list = nilfs_cpfile_block_get_snapshot_list( 962 - cpfile, prev, prev_bh, kaddr); 947 + /* Update the list entry for the previous snapshot */ 948 + list = kmap_local_folio(prev_bh->b_folio, prev_list_offset); 963 949 list->ssl_next = cpu_to_le64(next); 964 - kunmap_local(kaddr); 950 + kunmap_local(list); 965 951 966 - kaddr = kmap_local_page(cp_bh->b_page); 967 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 952 + /* Update the snapshot being changed back to a plain checkpoint */ 953 + cp = kmap_local_folio(cp_bh->b_folio, offset); 968 954 cp->cp_snapshot_list.ssl_next = cpu_to_le64(0); 969 955 cp->cp_snapshot_list.ssl_prev = cpu_to_le64(0); 970 956 nilfs_checkpoint_clear_snapshot(cp); 971 - kunmap_local(kaddr); 957 + kunmap_local(cp); 972 958 973 - kaddr = kmap_local_page(header_bh->b_page); 974 - header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 959 + /* Update the statistics in the header */ 960 + header = kmap_local_folio(header_bh->b_folio, 0); 975 961 le64_add_cpu(&header->ch_nsnapshots, -1); 976 - kunmap_local(kaddr); 962 + kunmap_local(header); 977 963 978 964 mark_buffer_dirty(next_bh); 979 965 mark_buffer_dirty(prev_bh); ··· 994 964 out_next: 995 965 brelse(next_bh); 996 966 997 - out_header: 998 - brelse(header_bh); 999 - 1000 967 out_cp: 1001 968 brelse(cp_bh); 969 + 970 + out_header: 971 + brelse(header_bh); 1002 972 1003 973 out_sem: 1004 974 up_write(&NILFS_MDT(cpfile)->mi_sem); ··· 1020 990 { 1021 991 struct buffer_head *bh; 1022 992 struct nilfs_checkpoint *cp; 1023 - void *kaddr; 993 + size_t offset; 1024 994 int ret; 1025 995 1026 996 /* ··· 1034 1004 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); 1035 1005 if (ret < 0) 1036 1006 goto out; 1037 - kaddr = kmap_local_page(bh->b_page); 1038 - cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 1007 + 1008 + offset = nilfs_cpfile_checkpoint_offset(cpfile, cno, bh); 1009 + cp = kmap_local_folio(bh->b_folio, offset); 1039 1010 if (nilfs_checkpoint_invalid(cp)) 1040 1011 ret = -ENOENT; 1041 1012 else 1042 1013 ret = nilfs_checkpoint_snapshot(cp); 1043 - kunmap_local(kaddr); 1014 + kunmap_local(cp); 1044 1015 brelse(bh); 1045 1016 1046 1017 out: ··· 1110 1079 { 1111 1080 struct buffer_head *bh; 1112 1081 struct nilfs_cpfile_header *header; 1113 - void *kaddr; 1114 1082 int ret; 1115 1083 1116 1084 down_read(&NILFS_MDT(cpfile)->mi_sem); ··· 1117 1087 ret = nilfs_cpfile_get_header_block(cpfile, &bh); 1118 1088 if (ret < 0) 1119 1089 goto out_sem; 1120 - kaddr = kmap_local_page(bh->b_page); 1121 - header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 1090 + header = kmap_local_folio(bh->b_folio, 0); 1122 1091 cpstat->cs_cno = nilfs_mdt_cno(cpfile); 1123 1092 cpstat->cs_ncps = le64_to_cpu(header->ch_ncheckpoints); 1124 1093 cpstat->cs_nsss = le64_to_cpu(header->ch_nsnapshots); 1125 - kunmap_local(kaddr); 1094 + kunmap_local(header); 1126 1095 brelse(bh); 1127 1096 1128 1097 out_sem: