1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * NILFS checkpoint file. 4 * 5 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. 6 * 7 * Written by Koji Sato. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/fs.h> 12 #include <linux/string.h> 13 #include <linux/buffer_head.h> 14 #include <linux/errno.h> 15 #include "mdt.h" 16 #include "cpfile.h" 17 18 19 static inline unsigned long 20 nilfs_cpfile_checkpoints_per_block(const struct inode *cpfile) 21 { 22 return NILFS_MDT(cpfile)->mi_entries_per_block; 23 } 24 25 /* block number from the beginning of the file */ 26 static unsigned long 27 nilfs_cpfile_get_blkoff(const struct inode *cpfile, __u64 cno) 28 { 29 __u64 tcno = cno + NILFS_MDT(cpfile)->mi_first_entry_offset - 1; 30 31 tcno = div64_ul(tcno, nilfs_cpfile_checkpoints_per_block(cpfile)); 32 return (unsigned long)tcno; 33 } 34 35 /* offset in block */ 36 static unsigned long 37 nilfs_cpfile_get_offset(const struct inode *cpfile, __u64 cno) 38 { 39 __u64 tcno = cno + NILFS_MDT(cpfile)->mi_first_entry_offset - 1; 40 41 return do_div(tcno, nilfs_cpfile_checkpoints_per_block(cpfile)); 42 } 43 44 static __u64 nilfs_cpfile_first_checkpoint_in_block(const struct inode *cpfile, 45 unsigned long blkoff) 46 { 47 return (__u64)nilfs_cpfile_checkpoints_per_block(cpfile) * blkoff 48 + 1 - NILFS_MDT(cpfile)->mi_first_entry_offset; 49 } 50 51 static unsigned long 52 nilfs_cpfile_checkpoints_in_block(const struct inode *cpfile, 53 __u64 curr, 54 __u64 max) 55 { 56 return min_t(__u64, 57 nilfs_cpfile_checkpoints_per_block(cpfile) - 58 nilfs_cpfile_get_offset(cpfile, curr), 59 max - curr); 60 } 61 62 static inline int nilfs_cpfile_is_in_first(const struct inode *cpfile, 63 __u64 cno) 64 { 65 return nilfs_cpfile_get_blkoff(cpfile, cno) == 0; 66 } 67 68 static unsigned int 69 nilfs_cpfile_block_add_valid_checkpoints(const struct inode *cpfile, 70 struct buffer_head *bh, 71 void *kaddr, 72 unsigned int n) 73 { 74 struct nilfs_checkpoint *cp = kaddr + bh_offset(bh); 75 unsigned int count; 76 77 count = le32_to_cpu(cp->cp_checkpoints_count) + n; 78 cp->cp_checkpoints_count = cpu_to_le32(count); 79 return count; 80 } 81 82 static unsigned int 83 nilfs_cpfile_block_sub_valid_checkpoints(const struct inode *cpfile, 84 struct buffer_head *bh, 85 void *kaddr, 86 unsigned int n) 87 { 88 struct nilfs_checkpoint *cp = kaddr + bh_offset(bh); 89 unsigned int count; 90 91 WARN_ON(le32_to_cpu(cp->cp_checkpoints_count) < n); 92 count = le32_to_cpu(cp->cp_checkpoints_count) - n; 93 cp->cp_checkpoints_count = cpu_to_le32(count); 94 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 } 113 114 static void nilfs_cpfile_block_init(struct inode *cpfile, 115 struct buffer_head *bh, 116 void *kaddr) 117 { 118 struct nilfs_checkpoint *cp = kaddr + bh_offset(bh); 119 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 120 int n = nilfs_cpfile_checkpoints_per_block(cpfile); 121 122 while (n-- > 0) { 123 nilfs_checkpoint_set_invalid(cp); 124 cp = (void *)cp + cpsz; 125 } 126 } 127 128 static inline int nilfs_cpfile_get_header_block(struct inode *cpfile, 129 struct buffer_head **bhp) 130 { 131 return nilfs_mdt_get_block(cpfile, 0, 0, NULL, bhp); 132 } 133 134 static inline int nilfs_cpfile_get_checkpoint_block(struct inode *cpfile, 135 __u64 cno, 136 int create, 137 struct buffer_head **bhp) 138 { 139 return nilfs_mdt_get_block(cpfile, 140 nilfs_cpfile_get_blkoff(cpfile, cno), 141 create, nilfs_cpfile_block_init, bhp); 142 } 143 144 /** 145 * nilfs_cpfile_find_checkpoint_block - find and get a buffer on cpfile 146 * @cpfile: inode of cpfile 147 * @start_cno: start checkpoint number (inclusive) 148 * @end_cno: end checkpoint number (inclusive) 149 * @cnop: place to store the next checkpoint number 150 * @bhp: place to store a pointer to buffer_head struct 151 * 152 * Return Value: On success, it returns 0. On error, the following negative 153 * error code is returned. 154 * 155 * %-ENOMEM - Insufficient memory available. 156 * 157 * %-EIO - I/O error 158 * 159 * %-ENOENT - no block exists in the range. 160 */ 161 static int nilfs_cpfile_find_checkpoint_block(struct inode *cpfile, 162 __u64 start_cno, __u64 end_cno, 163 __u64 *cnop, 164 struct buffer_head **bhp) 165 { 166 unsigned long start, end, blkoff; 167 int ret; 168 169 if (unlikely(start_cno > end_cno)) 170 return -ENOENT; 171 172 start = nilfs_cpfile_get_blkoff(cpfile, start_cno); 173 end = nilfs_cpfile_get_blkoff(cpfile, end_cno); 174 175 ret = nilfs_mdt_find_block(cpfile, start, end, &blkoff, bhp); 176 if (!ret) 177 *cnop = (blkoff == start) ? start_cno : 178 nilfs_cpfile_first_checkpoint_in_block(cpfile, blkoff); 179 return ret; 180 } 181 182 static inline int nilfs_cpfile_delete_checkpoint_block(struct inode *cpfile, 183 __u64 cno) 184 { 185 return nilfs_mdt_delete_block(cpfile, 186 nilfs_cpfile_get_blkoff(cpfile, cno)); 187 } 188 189 /** 190 * nilfs_cpfile_read_checkpoint - read a checkpoint entry in cpfile 191 * @cpfile: checkpoint file inode 192 * @cno: number of checkpoint entry to read 193 * @root: nilfs root object 194 * @ifile: ifile's inode to read and attach to @root 195 * 196 * This function imports checkpoint information from the checkpoint file and 197 * stores it to the inode file given by @ifile and the nilfs root object 198 * given by @root. 199 * 200 * Return: 0 on success, or the following negative error code on failure. 201 * * %-EINVAL - Invalid checkpoint. 202 * * %-ENOMEM - Insufficient memory available. 203 * * %-EIO - I/O error (including metadata corruption). 204 */ 205 int nilfs_cpfile_read_checkpoint(struct inode *cpfile, __u64 cno, 206 struct nilfs_root *root, struct inode *ifile) 207 { 208 struct buffer_head *cp_bh; 209 struct nilfs_checkpoint *cp; 210 void *kaddr; 211 int ret; 212 213 if (cno < 1 || cno > nilfs_mdt_cno(cpfile)) 214 return -EINVAL; 215 216 down_read(&NILFS_MDT(cpfile)->mi_sem); 217 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 218 if (unlikely(ret < 0)) { 219 if (ret == -ENOENT) 220 ret = -EINVAL; 221 goto out_sem; 222 } 223 224 kaddr = kmap_local_page(cp_bh->b_page); 225 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 226 if (nilfs_checkpoint_invalid(cp)) { 227 ret = -EINVAL; 228 goto put_cp; 229 } 230 231 ret = nilfs_read_inode_common(ifile, &cp->cp_ifile_inode); 232 if (unlikely(ret)) { 233 /* 234 * Since this inode is on a checkpoint entry, treat errors 235 * as metadata corruption. 236 */ 237 nilfs_err(cpfile->i_sb, 238 "ifile inode (checkpoint number=%llu) corrupted", 239 (unsigned long long)cno); 240 ret = -EIO; 241 goto put_cp; 242 } 243 244 /* Configure the nilfs root object */ 245 atomic64_set(&root->inodes_count, le64_to_cpu(cp->cp_inodes_count)); 246 atomic64_set(&root->blocks_count, le64_to_cpu(cp->cp_blocks_count)); 247 root->ifile = ifile; 248 249 put_cp: 250 kunmap_local(kaddr); 251 brelse(cp_bh); 252 out_sem: 253 up_read(&NILFS_MDT(cpfile)->mi_sem); 254 return ret; 255 } 256 257 /** 258 * nilfs_cpfile_create_checkpoint - create a checkpoint entry on cpfile 259 * @cpfile: checkpoint file inode 260 * @cno: number of checkpoint to set up 261 * 262 * This function creates a checkpoint with the number specified by @cno on 263 * cpfile. If the specified checkpoint entry already exists due to a past 264 * failure, it will be reused without returning an error. 265 * In either case, the buffer of the block containing the checkpoint entry 266 * and the cpfile inode are made dirty for inclusion in the write log. 267 * 268 * Return: 0 on success, or the following negative error code on failure. 269 * * %-ENOMEM - Insufficient memory available. 270 * * %-EIO - I/O error (including metadata corruption). 271 * * %-EROFS - Read only filesystem 272 */ 273 int nilfs_cpfile_create_checkpoint(struct inode *cpfile, __u64 cno) 274 { 275 struct buffer_head *header_bh, *cp_bh; 276 struct nilfs_cpfile_header *header; 277 struct nilfs_checkpoint *cp; 278 void *kaddr; 279 int ret; 280 281 if (WARN_ON_ONCE(cno < 1)) 282 return -EIO; 283 284 down_write(&NILFS_MDT(cpfile)->mi_sem); 285 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 286 if (unlikely(ret < 0)) { 287 if (ret == -ENOENT) { 288 nilfs_error(cpfile->i_sb, 289 "checkpoint creation failed due to metadata corruption."); 290 ret = -EIO; 291 } 292 goto out_sem; 293 } 294 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 1, &cp_bh); 295 if (unlikely(ret < 0)) 296 goto out_header; 297 298 kaddr = kmap_local_page(cp_bh->b_page); 299 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 300 if (nilfs_checkpoint_invalid(cp)) { 301 /* a newly-created checkpoint */ 302 nilfs_checkpoint_clear_invalid(cp); 303 if (!nilfs_cpfile_is_in_first(cpfile, cno)) 304 nilfs_cpfile_block_add_valid_checkpoints(cpfile, cp_bh, 305 kaddr, 1); 306 kunmap_local(kaddr); 307 308 kaddr = kmap_local_page(header_bh->b_page); 309 header = nilfs_cpfile_block_get_header(cpfile, header_bh, 310 kaddr); 311 le64_add_cpu(&header->ch_ncheckpoints, 1); 312 kunmap_local(kaddr); 313 mark_buffer_dirty(header_bh); 314 } else { 315 kunmap_local(kaddr); 316 } 317 318 /* Force the buffer and the inode to become dirty */ 319 mark_buffer_dirty(cp_bh); 320 brelse(cp_bh); 321 nilfs_mdt_mark_dirty(cpfile); 322 323 out_header: 324 brelse(header_bh); 325 326 out_sem: 327 up_write(&NILFS_MDT(cpfile)->mi_sem); 328 return ret; 329 } 330 331 /** 332 * nilfs_cpfile_finalize_checkpoint - fill in a checkpoint entry in cpfile 333 * @cpfile: checkpoint file inode 334 * @cno: checkpoint number 335 * @root: nilfs root object 336 * @blkinc: number of blocks added by this checkpoint 337 * @ctime: checkpoint creation time 338 * @minor: minor checkpoint flag 339 * 340 * This function completes the checkpoint entry numbered by @cno in the 341 * cpfile with the data given by the arguments @root, @blkinc, @ctime, and 342 * @minor. 343 * 344 * Return: 0 on success, or the following negative error code on failure. 345 * * %-ENOMEM - Insufficient memory available. 346 * * %-EIO - I/O error (including metadata corruption). 347 */ 348 int nilfs_cpfile_finalize_checkpoint(struct inode *cpfile, __u64 cno, 349 struct nilfs_root *root, __u64 blkinc, 350 time64_t ctime, bool minor) 351 { 352 struct buffer_head *cp_bh; 353 struct nilfs_checkpoint *cp; 354 void *kaddr; 355 int ret; 356 357 if (WARN_ON_ONCE(cno < 1)) 358 return -EIO; 359 360 down_write(&NILFS_MDT(cpfile)->mi_sem); 361 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 362 if (unlikely(ret < 0)) { 363 if (ret == -ENOENT) 364 goto error; 365 goto out_sem; 366 } 367 368 kaddr = kmap_local_page(cp_bh->b_page); 369 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 370 if (unlikely(nilfs_checkpoint_invalid(cp))) { 371 kunmap_local(kaddr); 372 brelse(cp_bh); 373 goto error; 374 } 375 376 cp->cp_snapshot_list.ssl_next = 0; 377 cp->cp_snapshot_list.ssl_prev = 0; 378 cp->cp_inodes_count = cpu_to_le64(atomic64_read(&root->inodes_count)); 379 cp->cp_blocks_count = cpu_to_le64(atomic64_read(&root->blocks_count)); 380 cp->cp_nblk_inc = cpu_to_le64(blkinc); 381 cp->cp_create = cpu_to_le64(ctime); 382 cp->cp_cno = cpu_to_le64(cno); 383 384 if (minor) 385 nilfs_checkpoint_set_minor(cp); 386 else 387 nilfs_checkpoint_clear_minor(cp); 388 389 nilfs_write_inode_common(root->ifile, &cp->cp_ifile_inode); 390 nilfs_bmap_write(NILFS_I(root->ifile)->i_bmap, &cp->cp_ifile_inode); 391 392 kunmap_local(kaddr); 393 brelse(cp_bh); 394 out_sem: 395 up_write(&NILFS_MDT(cpfile)->mi_sem); 396 return ret; 397 398 error: 399 nilfs_error(cpfile->i_sb, 400 "checkpoint finalization failed due to metadata corruption."); 401 ret = -EIO; 402 goto out_sem; 403 } 404 405 /** 406 * nilfs_cpfile_delete_checkpoints - delete checkpoints 407 * @cpfile: inode of checkpoint file 408 * @start: start checkpoint number 409 * @end: end checkpoint number 410 * 411 * Description: nilfs_cpfile_delete_checkpoints() deletes the checkpoints in 412 * the period from @start to @end, excluding @end itself. The checkpoints 413 * which have been already deleted are ignored. 414 * 415 * Return Value: On success, 0 is returned. On error, one of the following 416 * negative error codes is returned. 417 * 418 * %-EIO - I/O error. 419 * 420 * %-ENOMEM - Insufficient amount of memory available. 421 * 422 * %-EINVAL - invalid checkpoints. 423 */ 424 int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, 425 __u64 start, 426 __u64 end) 427 { 428 struct buffer_head *header_bh, *cp_bh; 429 struct nilfs_cpfile_header *header; 430 struct nilfs_checkpoint *cp; 431 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 432 __u64 cno; 433 void *kaddr; 434 unsigned long tnicps; 435 int ret, ncps, nicps, nss, count, i; 436 437 if (unlikely(start == 0 || start > end)) { 438 nilfs_err(cpfile->i_sb, 439 "cannot delete checkpoints: invalid range [%llu, %llu)", 440 (unsigned long long)start, (unsigned long long)end); 441 return -EINVAL; 442 } 443 444 down_write(&NILFS_MDT(cpfile)->mi_sem); 445 446 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 447 if (ret < 0) 448 goto out_sem; 449 tnicps = 0; 450 nss = 0; 451 452 for (cno = start; cno < end; cno += ncps) { 453 ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, end); 454 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 455 if (ret < 0) { 456 if (ret != -ENOENT) 457 break; 458 /* skip hole */ 459 ret = 0; 460 continue; 461 } 462 463 kaddr = kmap_local_page(cp_bh->b_page); 464 cp = nilfs_cpfile_block_get_checkpoint( 465 cpfile, cno, cp_bh, kaddr); 466 nicps = 0; 467 for (i = 0; i < ncps; i++, cp = (void *)cp + cpsz) { 468 if (nilfs_checkpoint_snapshot(cp)) { 469 nss++; 470 } else if (!nilfs_checkpoint_invalid(cp)) { 471 nilfs_checkpoint_set_invalid(cp); 472 nicps++; 473 } 474 } 475 if (nicps > 0) { 476 tnicps += nicps; 477 mark_buffer_dirty(cp_bh); 478 nilfs_mdt_mark_dirty(cpfile); 479 if (!nilfs_cpfile_is_in_first(cpfile, cno)) { 480 count = 481 nilfs_cpfile_block_sub_valid_checkpoints( 482 cpfile, cp_bh, kaddr, nicps); 483 if (count == 0) { 484 /* make hole */ 485 kunmap_local(kaddr); 486 brelse(cp_bh); 487 ret = 488 nilfs_cpfile_delete_checkpoint_block( 489 cpfile, cno); 490 if (ret == 0) 491 continue; 492 nilfs_err(cpfile->i_sb, 493 "error %d deleting checkpoint block", 494 ret); 495 break; 496 } 497 } 498 } 499 500 kunmap_local(kaddr); 501 brelse(cp_bh); 502 } 503 504 if (tnicps > 0) { 505 kaddr = kmap_local_page(header_bh->b_page); 506 header = nilfs_cpfile_block_get_header(cpfile, header_bh, 507 kaddr); 508 le64_add_cpu(&header->ch_ncheckpoints, -(u64)tnicps); 509 mark_buffer_dirty(header_bh); 510 nilfs_mdt_mark_dirty(cpfile); 511 kunmap_local(kaddr); 512 } 513 514 brelse(header_bh); 515 if (nss > 0) 516 ret = -EBUSY; 517 518 out_sem: 519 up_write(&NILFS_MDT(cpfile)->mi_sem); 520 return ret; 521 } 522 523 static void nilfs_cpfile_checkpoint_to_cpinfo(struct inode *cpfile, 524 struct nilfs_checkpoint *cp, 525 struct nilfs_cpinfo *ci) 526 { 527 ci->ci_flags = le32_to_cpu(cp->cp_flags); 528 ci->ci_cno = le64_to_cpu(cp->cp_cno); 529 ci->ci_create = le64_to_cpu(cp->cp_create); 530 ci->ci_nblk_inc = le64_to_cpu(cp->cp_nblk_inc); 531 ci->ci_inodes_count = le64_to_cpu(cp->cp_inodes_count); 532 ci->ci_blocks_count = le64_to_cpu(cp->cp_blocks_count); 533 ci->ci_next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); 534 } 535 536 static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, 537 void *buf, unsigned int cisz, 538 size_t nci) 539 { 540 struct nilfs_checkpoint *cp; 541 struct nilfs_cpinfo *ci = buf; 542 struct buffer_head *bh; 543 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 544 __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop; 545 void *kaddr; 546 int n, ret; 547 int ncps, i; 548 549 if (cno == 0) 550 return -ENOENT; /* checkpoint number 0 is invalid */ 551 down_read(&NILFS_MDT(cpfile)->mi_sem); 552 553 for (n = 0; n < nci; cno += ncps) { 554 ret = nilfs_cpfile_find_checkpoint_block( 555 cpfile, cno, cur_cno - 1, &cno, &bh); 556 if (ret < 0) { 557 if (likely(ret == -ENOENT)) 558 break; 559 goto out; 560 } 561 ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno); 562 563 kaddr = kmap_local_page(bh->b_page); 564 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 565 for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) { 566 if (!nilfs_checkpoint_invalid(cp)) { 567 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, 568 ci); 569 ci = (void *)ci + cisz; 570 n++; 571 } 572 } 573 kunmap_local(kaddr); 574 brelse(bh); 575 } 576 577 ret = n; 578 if (n > 0) { 579 ci = (void *)ci - cisz; 580 *cnop = ci->ci_cno + 1; 581 } 582 583 out: 584 up_read(&NILFS_MDT(cpfile)->mi_sem); 585 return ret; 586 } 587 588 static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, 589 void *buf, unsigned int cisz, 590 size_t nci) 591 { 592 struct buffer_head *bh; 593 struct nilfs_cpfile_header *header; 594 struct nilfs_checkpoint *cp; 595 struct nilfs_cpinfo *ci = buf; 596 __u64 curr = *cnop, next; 597 unsigned long curr_blkoff, next_blkoff; 598 void *kaddr; 599 int n = 0, ret; 600 601 down_read(&NILFS_MDT(cpfile)->mi_sem); 602 603 if (curr == 0) { 604 ret = nilfs_cpfile_get_header_block(cpfile, &bh); 605 if (ret < 0) 606 goto out; 607 kaddr = kmap_local_page(bh->b_page); 608 header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 609 curr = le64_to_cpu(header->ch_snapshot_list.ssl_next); 610 kunmap_local(kaddr); 611 brelse(bh); 612 if (curr == 0) { 613 ret = 0; 614 goto out; 615 } 616 } else if (unlikely(curr == ~(__u64)0)) { 617 ret = 0; 618 goto out; 619 } 620 621 curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr); 622 ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh); 623 if (unlikely(ret < 0)) { 624 if (ret == -ENOENT) 625 ret = 0; /* No snapshots (started from a hole block) */ 626 goto out; 627 } 628 kaddr = kmap_local_page(bh->b_page); 629 while (n < nci) { 630 cp = nilfs_cpfile_block_get_checkpoint(cpfile, curr, bh, kaddr); 631 curr = ~(__u64)0; /* Terminator */ 632 if (unlikely(nilfs_checkpoint_invalid(cp) || 633 !nilfs_checkpoint_snapshot(cp))) 634 break; 635 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, ci); 636 ci = (void *)ci + cisz; 637 n++; 638 next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); 639 if (next == 0) 640 break; /* reach end of the snapshot list */ 641 642 next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next); 643 if (curr_blkoff != next_blkoff) { 644 kunmap_local(kaddr); 645 brelse(bh); 646 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 647 0, &bh); 648 if (unlikely(ret < 0)) { 649 WARN_ON(ret == -ENOENT); 650 goto out; 651 } 652 kaddr = kmap_local_page(bh->b_page); 653 } 654 curr = next; 655 curr_blkoff = next_blkoff; 656 } 657 kunmap_local(kaddr); 658 brelse(bh); 659 *cnop = curr; 660 ret = n; 661 662 out: 663 up_read(&NILFS_MDT(cpfile)->mi_sem); 664 return ret; 665 } 666 667 /** 668 * nilfs_cpfile_get_cpinfo - get information on checkpoints 669 * @cpfile: checkpoint file inode 670 * @cnop: place to pass a starting checkpoint number and receive a 671 * checkpoint number to continue the search 672 * @mode: mode of checkpoints that the caller wants to retrieve 673 * @buf: buffer for storing checkpoints' information 674 * @cisz: byte size of one checkpoint info item in array 675 * @nci: number of checkpoint info items to retrieve 676 * 677 * nilfs_cpfile_get_cpinfo() searches for checkpoints in @mode state 678 * starting from the checkpoint number stored in @cnop, and stores 679 * information about found checkpoints in @buf. 680 * The buffer pointed to by @buf must be large enough to store information 681 * for @nci checkpoints. If at least one checkpoint information is 682 * successfully retrieved, @cnop is updated to point to the checkpoint 683 * number to continue searching. 684 * 685 * Return: Count of checkpoint info items stored in the output buffer on 686 * success, or the following negative error code on failure. 687 * * %-EINVAL - Invalid checkpoint mode. 688 * * %-ENOMEM - Insufficient memory available. 689 * * %-EIO - I/O error (including metadata corruption). 690 * * %-ENOENT - Invalid checkpoint number specified. 691 */ 692 693 ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode, 694 void *buf, unsigned int cisz, size_t nci) 695 { 696 switch (mode) { 697 case NILFS_CHECKPOINT: 698 return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, buf, cisz, nci); 699 case NILFS_SNAPSHOT: 700 return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, buf, cisz, nci); 701 default: 702 return -EINVAL; 703 } 704 } 705 706 /** 707 * nilfs_cpfile_delete_checkpoint - 708 * @cpfile: 709 * @cno: 710 */ 711 int nilfs_cpfile_delete_checkpoint(struct inode *cpfile, __u64 cno) 712 { 713 struct nilfs_cpinfo ci; 714 __u64 tcno = cno; 715 ssize_t nci; 716 717 nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, sizeof(ci), 1); 718 if (nci < 0) 719 return nci; 720 else if (nci == 0 || ci.ci_cno != cno) 721 return -ENOENT; 722 else if (nilfs_cpinfo_snapshot(&ci)) 723 return -EBUSY; 724 725 return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1); 726 } 727 728 static struct nilfs_snapshot_list * 729 nilfs_cpfile_block_get_snapshot_list(const struct inode *cpfile, 730 __u64 cno, 731 struct buffer_head *bh, 732 void *kaddr) 733 { 734 struct nilfs_cpfile_header *header; 735 struct nilfs_checkpoint *cp; 736 struct nilfs_snapshot_list *list; 737 738 if (cno != 0) { 739 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 740 list = &cp->cp_snapshot_list; 741 } else { 742 header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 743 list = &header->ch_snapshot_list; 744 } 745 return list; 746 } 747 748 static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno) 749 { 750 struct buffer_head *header_bh, *curr_bh, *prev_bh, *cp_bh; 751 struct nilfs_cpfile_header *header; 752 struct nilfs_checkpoint *cp; 753 struct nilfs_snapshot_list *list; 754 __u64 curr, prev; 755 unsigned long curr_blkoff, prev_blkoff; 756 void *kaddr; 757 int ret; 758 759 if (cno == 0) 760 return -ENOENT; /* checkpoint number 0 is invalid */ 761 down_write(&NILFS_MDT(cpfile)->mi_sem); 762 763 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 764 if (ret < 0) 765 goto out_sem; 766 kaddr = kmap_local_page(cp_bh->b_page); 767 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 768 if (nilfs_checkpoint_invalid(cp)) { 769 ret = -ENOENT; 770 kunmap_local(kaddr); 771 goto out_cp; 772 } 773 if (nilfs_checkpoint_snapshot(cp)) { 774 ret = 0; 775 kunmap_local(kaddr); 776 goto out_cp; 777 } 778 kunmap_local(kaddr); 779 780 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 781 if (ret < 0) 782 goto out_cp; 783 kaddr = kmap_local_page(header_bh->b_page); 784 header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 785 list = &header->ch_snapshot_list; 786 curr_bh = header_bh; 787 get_bh(curr_bh); 788 curr = 0; 789 curr_blkoff = 0; 790 prev = le64_to_cpu(list->ssl_prev); 791 while (prev > cno) { 792 prev_blkoff = nilfs_cpfile_get_blkoff(cpfile, prev); 793 curr = prev; 794 if (curr_blkoff != prev_blkoff) { 795 kunmap_local(kaddr); 796 brelse(curr_bh); 797 ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 798 0, &curr_bh); 799 if (ret < 0) 800 goto out_header; 801 kaddr = kmap_local_page(curr_bh->b_page); 802 } 803 curr_blkoff = prev_blkoff; 804 cp = nilfs_cpfile_block_get_checkpoint( 805 cpfile, curr, curr_bh, kaddr); 806 list = &cp->cp_snapshot_list; 807 prev = le64_to_cpu(list->ssl_prev); 808 } 809 kunmap_local(kaddr); 810 811 if (prev != 0) { 812 ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0, 813 &prev_bh); 814 if (ret < 0) 815 goto out_curr; 816 } else { 817 prev_bh = header_bh; 818 get_bh(prev_bh); 819 } 820 821 kaddr = kmap_local_page(curr_bh->b_page); 822 list = nilfs_cpfile_block_get_snapshot_list( 823 cpfile, curr, curr_bh, kaddr); 824 list->ssl_prev = cpu_to_le64(cno); 825 kunmap_local(kaddr); 826 827 kaddr = kmap_local_page(cp_bh->b_page); 828 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 829 cp->cp_snapshot_list.ssl_next = cpu_to_le64(curr); 830 cp->cp_snapshot_list.ssl_prev = cpu_to_le64(prev); 831 nilfs_checkpoint_set_snapshot(cp); 832 kunmap_local(kaddr); 833 834 kaddr = kmap_local_page(prev_bh->b_page); 835 list = nilfs_cpfile_block_get_snapshot_list( 836 cpfile, prev, prev_bh, kaddr); 837 list->ssl_next = cpu_to_le64(cno); 838 kunmap_local(kaddr); 839 840 kaddr = kmap_local_page(header_bh->b_page); 841 header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 842 le64_add_cpu(&header->ch_nsnapshots, 1); 843 kunmap_local(kaddr); 844 845 mark_buffer_dirty(prev_bh); 846 mark_buffer_dirty(curr_bh); 847 mark_buffer_dirty(cp_bh); 848 mark_buffer_dirty(header_bh); 849 nilfs_mdt_mark_dirty(cpfile); 850 851 brelse(prev_bh); 852 853 out_curr: 854 brelse(curr_bh); 855 856 out_header: 857 brelse(header_bh); 858 859 out_cp: 860 brelse(cp_bh); 861 862 out_sem: 863 up_write(&NILFS_MDT(cpfile)->mi_sem); 864 return ret; 865 } 866 867 static int nilfs_cpfile_clear_snapshot(struct inode *cpfile, __u64 cno) 868 { 869 struct buffer_head *header_bh, *next_bh, *prev_bh, *cp_bh; 870 struct nilfs_cpfile_header *header; 871 struct nilfs_checkpoint *cp; 872 struct nilfs_snapshot_list *list; 873 __u64 next, prev; 874 void *kaddr; 875 int ret; 876 877 if (cno == 0) 878 return -ENOENT; /* checkpoint number 0 is invalid */ 879 down_write(&NILFS_MDT(cpfile)->mi_sem); 880 881 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 882 if (ret < 0) 883 goto out_sem; 884 kaddr = kmap_local_page(cp_bh->b_page); 885 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 886 if (nilfs_checkpoint_invalid(cp)) { 887 ret = -ENOENT; 888 kunmap_local(kaddr); 889 goto out_cp; 890 } 891 if (!nilfs_checkpoint_snapshot(cp)) { 892 ret = 0; 893 kunmap_local(kaddr); 894 goto out_cp; 895 } 896 897 list = &cp->cp_snapshot_list; 898 next = le64_to_cpu(list->ssl_next); 899 prev = le64_to_cpu(list->ssl_prev); 900 kunmap_local(kaddr); 901 902 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 903 if (ret < 0) 904 goto out_cp; 905 if (next != 0) { 906 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 0, 907 &next_bh); 908 if (ret < 0) 909 goto out_header; 910 } else { 911 next_bh = header_bh; 912 get_bh(next_bh); 913 } 914 if (prev != 0) { 915 ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0, 916 &prev_bh); 917 if (ret < 0) 918 goto out_next; 919 } else { 920 prev_bh = header_bh; 921 get_bh(prev_bh); 922 } 923 924 kaddr = kmap_local_page(next_bh->b_page); 925 list = nilfs_cpfile_block_get_snapshot_list( 926 cpfile, next, next_bh, kaddr); 927 list->ssl_prev = cpu_to_le64(prev); 928 kunmap_local(kaddr); 929 930 kaddr = kmap_local_page(prev_bh->b_page); 931 list = nilfs_cpfile_block_get_snapshot_list( 932 cpfile, prev, prev_bh, kaddr); 933 list->ssl_next = cpu_to_le64(next); 934 kunmap_local(kaddr); 935 936 kaddr = kmap_local_page(cp_bh->b_page); 937 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 938 cp->cp_snapshot_list.ssl_next = cpu_to_le64(0); 939 cp->cp_snapshot_list.ssl_prev = cpu_to_le64(0); 940 nilfs_checkpoint_clear_snapshot(cp); 941 kunmap_local(kaddr); 942 943 kaddr = kmap_local_page(header_bh->b_page); 944 header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 945 le64_add_cpu(&header->ch_nsnapshots, -1); 946 kunmap_local(kaddr); 947 948 mark_buffer_dirty(next_bh); 949 mark_buffer_dirty(prev_bh); 950 mark_buffer_dirty(cp_bh); 951 mark_buffer_dirty(header_bh); 952 nilfs_mdt_mark_dirty(cpfile); 953 954 brelse(prev_bh); 955 956 out_next: 957 brelse(next_bh); 958 959 out_header: 960 brelse(header_bh); 961 962 out_cp: 963 brelse(cp_bh); 964 965 out_sem: 966 up_write(&NILFS_MDT(cpfile)->mi_sem); 967 return ret; 968 } 969 970 /** 971 * nilfs_cpfile_is_snapshot - 972 * @cpfile: inode of checkpoint file 973 * @cno: checkpoint number 974 * 975 * Description: 976 * 977 * Return Value: On success, 1 is returned if the checkpoint specified by 978 * @cno is a snapshot, or 0 if not. On error, one of the following negative 979 * error codes is returned. 980 * 981 * %-EIO - I/O error. 982 * 983 * %-ENOMEM - Insufficient amount of memory available. 984 * 985 * %-ENOENT - No such checkpoint. 986 */ 987 int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) 988 { 989 struct buffer_head *bh; 990 struct nilfs_checkpoint *cp; 991 void *kaddr; 992 int ret; 993 994 /* 995 * CP number is invalid if it's zero or larger than the 996 * largest existing one. 997 */ 998 if (cno == 0 || cno >= nilfs_mdt_cno(cpfile)) 999 return -ENOENT; 1000 down_read(&NILFS_MDT(cpfile)->mi_sem); 1001 1002 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); 1003 if (ret < 0) 1004 goto out; 1005 kaddr = kmap_local_page(bh->b_page); 1006 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 1007 if (nilfs_checkpoint_invalid(cp)) 1008 ret = -ENOENT; 1009 else 1010 ret = nilfs_checkpoint_snapshot(cp); 1011 kunmap_local(kaddr); 1012 brelse(bh); 1013 1014 out: 1015 up_read(&NILFS_MDT(cpfile)->mi_sem); 1016 return ret; 1017 } 1018 1019 /** 1020 * nilfs_cpfile_change_cpmode - change checkpoint mode 1021 * @cpfile: inode of checkpoint file 1022 * @cno: checkpoint number 1023 * @mode: mode of checkpoint 1024 * 1025 * Description: nilfs_change_cpmode() changes the mode of the checkpoint 1026 * specified by @cno. The mode @mode is NILFS_CHECKPOINT or NILFS_SNAPSHOT. 1027 * 1028 * Return Value: On success, 0 is returned. On error, one of the following 1029 * negative error codes is returned. 1030 * 1031 * %-EIO - I/O error. 1032 * 1033 * %-ENOMEM - Insufficient amount of memory available. 1034 * 1035 * %-ENOENT - No such checkpoint. 1036 */ 1037 int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode) 1038 { 1039 int ret; 1040 1041 switch (mode) { 1042 case NILFS_CHECKPOINT: 1043 if (nilfs_checkpoint_is_mounted(cpfile->i_sb, cno)) 1044 /* 1045 * Current implementation does not have to protect 1046 * plain read-only mounts since they are exclusive 1047 * with a read/write mount and are protected from the 1048 * cleaner. 1049 */ 1050 ret = -EBUSY; 1051 else 1052 ret = nilfs_cpfile_clear_snapshot(cpfile, cno); 1053 return ret; 1054 case NILFS_SNAPSHOT: 1055 return nilfs_cpfile_set_snapshot(cpfile, cno); 1056 default: 1057 return -EINVAL; 1058 } 1059 } 1060 1061 /** 1062 * nilfs_cpfile_get_stat - get checkpoint statistics 1063 * @cpfile: inode of checkpoint file 1064 * @cpstat: pointer to a structure of checkpoint statistics 1065 * 1066 * Description: nilfs_cpfile_get_stat() returns information about checkpoints. 1067 * 1068 * Return Value: On success, 0 is returned, and checkpoints information is 1069 * stored in the place pointed by @cpstat. On error, one of the following 1070 * negative error codes is returned. 1071 * 1072 * %-EIO - I/O error. 1073 * 1074 * %-ENOMEM - Insufficient amount of memory available. 1075 */ 1076 int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat) 1077 { 1078 struct buffer_head *bh; 1079 struct nilfs_cpfile_header *header; 1080 void *kaddr; 1081 int ret; 1082 1083 down_read(&NILFS_MDT(cpfile)->mi_sem); 1084 1085 ret = nilfs_cpfile_get_header_block(cpfile, &bh); 1086 if (ret < 0) 1087 goto out_sem; 1088 kaddr = kmap_local_page(bh->b_page); 1089 header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 1090 cpstat->cs_cno = nilfs_mdt_cno(cpfile); 1091 cpstat->cs_ncps = le64_to_cpu(header->ch_ncheckpoints); 1092 cpstat->cs_nsss = le64_to_cpu(header->ch_nsnapshots); 1093 kunmap_local(kaddr); 1094 brelse(bh); 1095 1096 out_sem: 1097 up_read(&NILFS_MDT(cpfile)->mi_sem); 1098 return ret; 1099 } 1100 1101 /** 1102 * nilfs_cpfile_read - read or get cpfile inode 1103 * @sb: super block instance 1104 * @cpsize: size of a checkpoint entry 1105 * @raw_inode: on-disk cpfile inode 1106 * @inodep: buffer to store the inode 1107 */ 1108 int nilfs_cpfile_read(struct super_block *sb, size_t cpsize, 1109 struct nilfs_inode *raw_inode, struct inode **inodep) 1110 { 1111 struct inode *cpfile; 1112 int err; 1113 1114 if (cpsize > sb->s_blocksize) { 1115 nilfs_err(sb, "too large checkpoint size: %zu bytes", cpsize); 1116 return -EINVAL; 1117 } else if (cpsize < NILFS_MIN_CHECKPOINT_SIZE) { 1118 nilfs_err(sb, "too small checkpoint size: %zu bytes", cpsize); 1119 return -EINVAL; 1120 } 1121 1122 cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO); 1123 if (unlikely(!cpfile)) 1124 return -ENOMEM; 1125 if (!(cpfile->i_state & I_NEW)) 1126 goto out; 1127 1128 err = nilfs_mdt_init(cpfile, NILFS_MDT_GFP, 0); 1129 if (err) 1130 goto failed; 1131 1132 nilfs_mdt_set_entry_size(cpfile, cpsize, 1133 sizeof(struct nilfs_cpfile_header)); 1134 1135 err = nilfs_read_inode_common(cpfile, raw_inode); 1136 if (err) 1137 goto failed; 1138 1139 unlock_new_inode(cpfile); 1140 out: 1141 *inodep = cpfile; 1142 return 0; 1143 failed: 1144 iget_failed(cpfile); 1145 return err; 1146 } 1147
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.