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 do_div(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_get_checkpoint - get a checkpoint 191 * @cpfile: inode of checkpoint file 192 * @cno: checkpoint number 193 * @create: create flag 194 * @cpp: pointer to a checkpoint 195 * @bhp: pointer to a buffer head 196 * 197 * Description: nilfs_cpfile_get_checkpoint() acquires the checkpoint 198 * specified by @cno. A new checkpoint will be created if @cno is the current 199 * checkpoint number and @create is nonzero. 200 * 201 * Return Value: On success, 0 is returned, and the checkpoint and the 202 * buffer head of the buffer on which the checkpoint is located are stored in 203 * the place pointed by @cpp and @bhp, respectively. On error, one of the 204 * following negative error codes is returned. 205 * 206 * %-EIO - I/O error. 207 * 208 * %-ENOMEM - Insufficient amount of memory available. 209 * 210 * %-ENOENT - No such checkpoint. 211 * 212 * %-EINVAL - invalid checkpoint. 213 */ 214 int nilfs_cpfile_get_checkpoint(struct inode *cpfile, 215 __u64 cno, 216 int create, 217 struct nilfs_checkpoint **cpp, 218 struct buffer_head **bhp) 219 { 220 struct buffer_head *header_bh, *cp_bh; 221 struct nilfs_cpfile_header *header; 222 struct nilfs_checkpoint *cp; 223 void *kaddr; 224 int ret; 225 226 if (unlikely(cno < 1 || cno > nilfs_mdt_cno(cpfile) || 227 (cno < nilfs_mdt_cno(cpfile) && create))) 228 return -EINVAL; 229 230 down_write(&NILFS_MDT(cpfile)->mi_sem); 231 232 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 233 if (ret < 0) 234 goto out_sem; 235 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, create, &cp_bh); 236 if (ret < 0) 237 goto out_header; 238 kaddr = kmap(cp_bh->b_page); 239 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 240 if (nilfs_checkpoint_invalid(cp)) { 241 if (!create) { 242 kunmap(cp_bh->b_page); 243 brelse(cp_bh); 244 ret = -ENOENT; 245 goto out_header; 246 } 247 /* a newly-created checkpoint */ 248 nilfs_checkpoint_clear_invalid(cp); 249 if (!nilfs_cpfile_is_in_first(cpfile, cno)) 250 nilfs_cpfile_block_add_valid_checkpoints(cpfile, cp_bh, 251 kaddr, 1); 252 mark_buffer_dirty(cp_bh); 253 254 kaddr = kmap_atomic(header_bh->b_page); 255 header = nilfs_cpfile_block_get_header(cpfile, header_bh, 256 kaddr); 257 le64_add_cpu(&header->ch_ncheckpoints, 1); 258 kunmap_atomic(kaddr); 259 mark_buffer_dirty(header_bh); 260 nilfs_mdt_mark_dirty(cpfile); 261 } 262 263 if (cpp != NULL) 264 *cpp = cp; 265 *bhp = cp_bh; 266 267 out_header: 268 brelse(header_bh); 269 270 out_sem: 271 up_write(&NILFS_MDT(cpfile)->mi_sem); 272 return ret; 273 } 274 275 /** 276 * nilfs_cpfile_put_checkpoint - put a checkpoint 277 * @cpfile: inode of checkpoint file 278 * @cno: checkpoint number 279 * @bh: buffer head 280 * 281 * Description: nilfs_cpfile_put_checkpoint() releases the checkpoint 282 * specified by @cno. @bh must be the buffer head which has been returned by 283 * a previous call to nilfs_cpfile_get_checkpoint() with @cno. 284 */ 285 void nilfs_cpfile_put_checkpoint(struct inode *cpfile, __u64 cno, 286 struct buffer_head *bh) 287 { 288 kunmap(bh->b_page); 289 brelse(bh); 290 } 291 292 /** 293 * nilfs_cpfile_delete_checkpoints - delete checkpoints 294 * @cpfile: inode of checkpoint file 295 * @start: start checkpoint number 296 * @end: end checkpoint number 297 * 298 * Description: nilfs_cpfile_delete_checkpoints() deletes the checkpoints in 299 * the period from @start to @end, excluding @end itself. The checkpoints 300 * which have been already deleted are ignored. 301 * 302 * Return Value: On success, 0 is returned. On error, one of the following 303 * negative error codes is returned. 304 * 305 * %-EIO - I/O error. 306 * 307 * %-ENOMEM - Insufficient amount of memory available. 308 * 309 * %-EINVAL - invalid checkpoints. 310 */ 311 int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, 312 __u64 start, 313 __u64 end) 314 { 315 struct buffer_head *header_bh, *cp_bh; 316 struct nilfs_cpfile_header *header; 317 struct nilfs_checkpoint *cp; 318 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 319 __u64 cno; 320 void *kaddr; 321 unsigned long tnicps; 322 int ret, ncps, nicps, nss, count, i; 323 324 if (unlikely(start == 0 || start > end)) { 325 nilfs_err(cpfile->i_sb, 326 "cannot delete checkpoints: invalid range [%llu, %llu)", 327 (unsigned long long)start, (unsigned long long)end); 328 return -EINVAL; 329 } 330 331 down_write(&NILFS_MDT(cpfile)->mi_sem); 332 333 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 334 if (ret < 0) 335 goto out_sem; 336 tnicps = 0; 337 nss = 0; 338 339 for (cno = start; cno < end; cno += ncps) { 340 ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, end); 341 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 342 if (ret < 0) { 343 if (ret != -ENOENT) 344 break; 345 /* skip hole */ 346 ret = 0; 347 continue; 348 } 349 350 kaddr = kmap_atomic(cp_bh->b_page); 351 cp = nilfs_cpfile_block_get_checkpoint( 352 cpfile, cno, cp_bh, kaddr); 353 nicps = 0; 354 for (i = 0; i < ncps; i++, cp = (void *)cp + cpsz) { 355 if (nilfs_checkpoint_snapshot(cp)) { 356 nss++; 357 } else if (!nilfs_checkpoint_invalid(cp)) { 358 nilfs_checkpoint_set_invalid(cp); 359 nicps++; 360 } 361 } 362 if (nicps > 0) { 363 tnicps += nicps; 364 mark_buffer_dirty(cp_bh); 365 nilfs_mdt_mark_dirty(cpfile); 366 if (!nilfs_cpfile_is_in_first(cpfile, cno)) { 367 count = 368 nilfs_cpfile_block_sub_valid_checkpoints( 369 cpfile, cp_bh, kaddr, nicps); 370 if (count == 0) { 371 /* make hole */ 372 kunmap_atomic(kaddr); 373 brelse(cp_bh); 374 ret = 375 nilfs_cpfile_delete_checkpoint_block( 376 cpfile, cno); 377 if (ret == 0) 378 continue; 379 nilfs_err(cpfile->i_sb, 380 "error %d deleting checkpoint block", 381 ret); 382 break; 383 } 384 } 385 } 386 387 kunmap_atomic(kaddr); 388 brelse(cp_bh); 389 } 390 391 if (tnicps > 0) { 392 kaddr = kmap_atomic(header_bh->b_page); 393 header = nilfs_cpfile_block_get_header(cpfile, header_bh, 394 kaddr); 395 le64_add_cpu(&header->ch_ncheckpoints, -(u64)tnicps); 396 mark_buffer_dirty(header_bh); 397 nilfs_mdt_mark_dirty(cpfile); 398 kunmap_atomic(kaddr); 399 } 400 401 brelse(header_bh); 402 if (nss > 0) 403 ret = -EBUSY; 404 405 out_sem: 406 up_write(&NILFS_MDT(cpfile)->mi_sem); 407 return ret; 408 } 409 410 static void nilfs_cpfile_checkpoint_to_cpinfo(struct inode *cpfile, 411 struct nilfs_checkpoint *cp, 412 struct nilfs_cpinfo *ci) 413 { 414 ci->ci_flags = le32_to_cpu(cp->cp_flags); 415 ci->ci_cno = le64_to_cpu(cp->cp_cno); 416 ci->ci_create = le64_to_cpu(cp->cp_create); 417 ci->ci_nblk_inc = le64_to_cpu(cp->cp_nblk_inc); 418 ci->ci_inodes_count = le64_to_cpu(cp->cp_inodes_count); 419 ci->ci_blocks_count = le64_to_cpu(cp->cp_blocks_count); 420 ci->ci_next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); 421 } 422 423 static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, 424 void *buf, unsigned int cisz, 425 size_t nci) 426 { 427 struct nilfs_checkpoint *cp; 428 struct nilfs_cpinfo *ci = buf; 429 struct buffer_head *bh; 430 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 431 __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop; 432 void *kaddr; 433 int n, ret; 434 int ncps, i; 435 436 if (cno == 0) 437 return -ENOENT; /* checkpoint number 0 is invalid */ 438 down_read(&NILFS_MDT(cpfile)->mi_sem); 439 440 for (n = 0; n < nci; cno += ncps) { 441 ret = nilfs_cpfile_find_checkpoint_block( 442 cpfile, cno, cur_cno - 1, &cno, &bh); 443 if (ret < 0) { 444 if (likely(ret == -ENOENT)) 445 break; 446 goto out; 447 } 448 ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno); 449 450 kaddr = kmap_atomic(bh->b_page); 451 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 452 for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) { 453 if (!nilfs_checkpoint_invalid(cp)) { 454 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, 455 ci); 456 ci = (void *)ci + cisz; 457 n++; 458 } 459 } 460 kunmap_atomic(kaddr); 461 brelse(bh); 462 } 463 464 ret = n; 465 if (n > 0) { 466 ci = (void *)ci - cisz; 467 *cnop = ci->ci_cno + 1; 468 } 469 470 out: 471 up_read(&NILFS_MDT(cpfile)->mi_sem); 472 return ret; 473 } 474 475 static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, 476 void *buf, unsigned int cisz, 477 size_t nci) 478 { 479 struct buffer_head *bh; 480 struct nilfs_cpfile_header *header; 481 struct nilfs_checkpoint *cp; 482 struct nilfs_cpinfo *ci = buf; 483 __u64 curr = *cnop, next; 484 unsigned long curr_blkoff, next_blkoff; 485 void *kaddr; 486 int n = 0, ret; 487 488 down_read(&NILFS_MDT(cpfile)->mi_sem); 489 490 if (curr == 0) { 491 ret = nilfs_cpfile_get_header_block(cpfile, &bh); 492 if (ret < 0) 493 goto out; 494 kaddr = kmap_atomic(bh->b_page); 495 header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 496 curr = le64_to_cpu(header->ch_snapshot_list.ssl_next); 497 kunmap_atomic(kaddr); 498 brelse(bh); 499 if (curr == 0) { 500 ret = 0; 501 goto out; 502 } 503 } else if (unlikely(curr == ~(__u64)0)) { 504 ret = 0; 505 goto out; 506 } 507 508 curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr); 509 ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh); 510 if (unlikely(ret < 0)) { 511 if (ret == -ENOENT) 512 ret = 0; /* No snapshots (started from a hole block) */ 513 goto out; 514 } 515 kaddr = kmap_atomic(bh->b_page); 516 while (n < nci) { 517 cp = nilfs_cpfile_block_get_checkpoint(cpfile, curr, bh, kaddr); 518 curr = ~(__u64)0; /* Terminator */ 519 if (unlikely(nilfs_checkpoint_invalid(cp) || 520 !nilfs_checkpoint_snapshot(cp))) 521 break; 522 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, ci); 523 ci = (void *)ci + cisz; 524 n++; 525 next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); 526 if (next == 0) 527 break; /* reach end of the snapshot list */ 528 529 next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next); 530 if (curr_blkoff != next_blkoff) { 531 kunmap_atomic(kaddr); 532 brelse(bh); 533 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 534 0, &bh); 535 if (unlikely(ret < 0)) { 536 WARN_ON(ret == -ENOENT); 537 goto out; 538 } 539 kaddr = kmap_atomic(bh->b_page); 540 } 541 curr = next; 542 curr_blkoff = next_blkoff; 543 } 544 kunmap_atomic(kaddr); 545 brelse(bh); 546 *cnop = curr; 547 ret = n; 548 549 out: 550 up_read(&NILFS_MDT(cpfile)->mi_sem); 551 return ret; 552 } 553 554 /** 555 * nilfs_cpfile_get_cpinfo - get information on checkpoints 556 * @cpfile: checkpoint file inode 557 * @cnop: place to pass a starting checkpoint number and receive a 558 * checkpoint number to continue the search 559 * @mode: mode of checkpoints that the caller wants to retrieve 560 * @buf: buffer for storing checkpoints' information 561 * @cisz: byte size of one checkpoint info item in array 562 * @nci: number of checkpoint info items to retrieve 563 * 564 * nilfs_cpfile_get_cpinfo() searches for checkpoints in @mode state 565 * starting from the checkpoint number stored in @cnop, and stores 566 * information about found checkpoints in @buf. 567 * The buffer pointed to by @buf must be large enough to store information 568 * for @nci checkpoints. If at least one checkpoint information is 569 * successfully retrieved, @cnop is updated to point to the checkpoint 570 * number to continue searching. 571 * 572 * Return: Count of checkpoint info items stored in the output buffer on 573 * success, or the following negative error code on failure. 574 * * %-EINVAL - Invalid checkpoint mode. 575 * * %-ENOMEM - Insufficient memory available. 576 * * %-EIO - I/O error (including metadata corruption). 577 * * %-ENOENT - Invalid checkpoint number specified. 578 */ 579 580 ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode, 581 void *buf, unsigned int cisz, size_t nci) 582 { 583 switch (mode) { 584 case NILFS_CHECKPOINT: 585 return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, buf, cisz, nci); 586 case NILFS_SNAPSHOT: 587 return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, buf, cisz, nci); 588 default: 589 return -EINVAL; 590 } 591 } 592 593 /** 594 * nilfs_cpfile_delete_checkpoint - 595 * @cpfile: 596 * @cno: 597 */ 598 int nilfs_cpfile_delete_checkpoint(struct inode *cpfile, __u64 cno) 599 { 600 struct nilfs_cpinfo ci; 601 __u64 tcno = cno; 602 ssize_t nci; 603 604 nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, sizeof(ci), 1); 605 if (nci < 0) 606 return nci; 607 else if (nci == 0 || ci.ci_cno != cno) 608 return -ENOENT; 609 else if (nilfs_cpinfo_snapshot(&ci)) 610 return -EBUSY; 611 612 return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1); 613 } 614 615 static struct nilfs_snapshot_list * 616 nilfs_cpfile_block_get_snapshot_list(const struct inode *cpfile, 617 __u64 cno, 618 struct buffer_head *bh, 619 void *kaddr) 620 { 621 struct nilfs_cpfile_header *header; 622 struct nilfs_checkpoint *cp; 623 struct nilfs_snapshot_list *list; 624 625 if (cno != 0) { 626 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 627 list = &cp->cp_snapshot_list; 628 } else { 629 header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 630 list = &header->ch_snapshot_list; 631 } 632 return list; 633 } 634 635 static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno) 636 { 637 struct buffer_head *header_bh, *curr_bh, *prev_bh, *cp_bh; 638 struct nilfs_cpfile_header *header; 639 struct nilfs_checkpoint *cp; 640 struct nilfs_snapshot_list *list; 641 __u64 curr, prev; 642 unsigned long curr_blkoff, prev_blkoff; 643 void *kaddr; 644 int ret; 645 646 if (cno == 0) 647 return -ENOENT; /* checkpoint number 0 is invalid */ 648 down_write(&NILFS_MDT(cpfile)->mi_sem); 649 650 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 651 if (ret < 0) 652 goto out_sem; 653 kaddr = kmap_atomic(cp_bh->b_page); 654 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 655 if (nilfs_checkpoint_invalid(cp)) { 656 ret = -ENOENT; 657 kunmap_atomic(kaddr); 658 goto out_cp; 659 } 660 if (nilfs_checkpoint_snapshot(cp)) { 661 ret = 0; 662 kunmap_atomic(kaddr); 663 goto out_cp; 664 } 665 kunmap_atomic(kaddr); 666 667 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 668 if (ret < 0) 669 goto out_cp; 670 kaddr = kmap_atomic(header_bh->b_page); 671 header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 672 list = &header->ch_snapshot_list; 673 curr_bh = header_bh; 674 get_bh(curr_bh); 675 curr = 0; 676 curr_blkoff = 0; 677 prev = le64_to_cpu(list->ssl_prev); 678 while (prev > cno) { 679 prev_blkoff = nilfs_cpfile_get_blkoff(cpfile, prev); 680 curr = prev; 681 if (curr_blkoff != prev_blkoff) { 682 kunmap_atomic(kaddr); 683 brelse(curr_bh); 684 ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 685 0, &curr_bh); 686 if (ret < 0) 687 goto out_header; 688 kaddr = kmap_atomic(curr_bh->b_page); 689 } 690 curr_blkoff = prev_blkoff; 691 cp = nilfs_cpfile_block_get_checkpoint( 692 cpfile, curr, curr_bh, kaddr); 693 list = &cp->cp_snapshot_list; 694 prev = le64_to_cpu(list->ssl_prev); 695 } 696 kunmap_atomic(kaddr); 697 698 if (prev != 0) { 699 ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0, 700 &prev_bh); 701 if (ret < 0) 702 goto out_curr; 703 } else { 704 prev_bh = header_bh; 705 get_bh(prev_bh); 706 } 707 708 kaddr = kmap_atomic(curr_bh->b_page); 709 list = nilfs_cpfile_block_get_snapshot_list( 710 cpfile, curr, curr_bh, kaddr); 711 list->ssl_prev = cpu_to_le64(cno); 712 kunmap_atomic(kaddr); 713 714 kaddr = kmap_atomic(cp_bh->b_page); 715 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 716 cp->cp_snapshot_list.ssl_next = cpu_to_le64(curr); 717 cp->cp_snapshot_list.ssl_prev = cpu_to_le64(prev); 718 nilfs_checkpoint_set_snapshot(cp); 719 kunmap_atomic(kaddr); 720 721 kaddr = kmap_atomic(prev_bh->b_page); 722 list = nilfs_cpfile_block_get_snapshot_list( 723 cpfile, prev, prev_bh, kaddr); 724 list->ssl_next = cpu_to_le64(cno); 725 kunmap_atomic(kaddr); 726 727 kaddr = kmap_atomic(header_bh->b_page); 728 header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 729 le64_add_cpu(&header->ch_nsnapshots, 1); 730 kunmap_atomic(kaddr); 731 732 mark_buffer_dirty(prev_bh); 733 mark_buffer_dirty(curr_bh); 734 mark_buffer_dirty(cp_bh); 735 mark_buffer_dirty(header_bh); 736 nilfs_mdt_mark_dirty(cpfile); 737 738 brelse(prev_bh); 739 740 out_curr: 741 brelse(curr_bh); 742 743 out_header: 744 brelse(header_bh); 745 746 out_cp: 747 brelse(cp_bh); 748 749 out_sem: 750 up_write(&NILFS_MDT(cpfile)->mi_sem); 751 return ret; 752 } 753 754 static int nilfs_cpfile_clear_snapshot(struct inode *cpfile, __u64 cno) 755 { 756 struct buffer_head *header_bh, *next_bh, *prev_bh, *cp_bh; 757 struct nilfs_cpfile_header *header; 758 struct nilfs_checkpoint *cp; 759 struct nilfs_snapshot_list *list; 760 __u64 next, prev; 761 void *kaddr; 762 int ret; 763 764 if (cno == 0) 765 return -ENOENT; /* checkpoint number 0 is invalid */ 766 down_write(&NILFS_MDT(cpfile)->mi_sem); 767 768 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); 769 if (ret < 0) 770 goto out_sem; 771 kaddr = kmap_atomic(cp_bh->b_page); 772 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 773 if (nilfs_checkpoint_invalid(cp)) { 774 ret = -ENOENT; 775 kunmap_atomic(kaddr); 776 goto out_cp; 777 } 778 if (!nilfs_checkpoint_snapshot(cp)) { 779 ret = 0; 780 kunmap_atomic(kaddr); 781 goto out_cp; 782 } 783 784 list = &cp->cp_snapshot_list; 785 next = le64_to_cpu(list->ssl_next); 786 prev = le64_to_cpu(list->ssl_prev); 787 kunmap_atomic(kaddr); 788 789 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 790 if (ret < 0) 791 goto out_cp; 792 if (next != 0) { 793 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 0, 794 &next_bh); 795 if (ret < 0) 796 goto out_header; 797 } else { 798 next_bh = header_bh; 799 get_bh(next_bh); 800 } 801 if (prev != 0) { 802 ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0, 803 &prev_bh); 804 if (ret < 0) 805 goto out_next; 806 } else { 807 prev_bh = header_bh; 808 get_bh(prev_bh); 809 } 810 811 kaddr = kmap_atomic(next_bh->b_page); 812 list = nilfs_cpfile_block_get_snapshot_list( 813 cpfile, next, next_bh, kaddr); 814 list->ssl_prev = cpu_to_le64(prev); 815 kunmap_atomic(kaddr); 816 817 kaddr = kmap_atomic(prev_bh->b_page); 818 list = nilfs_cpfile_block_get_snapshot_list( 819 cpfile, prev, prev_bh, kaddr); 820 list->ssl_next = cpu_to_le64(next); 821 kunmap_atomic(kaddr); 822 823 kaddr = kmap_atomic(cp_bh->b_page); 824 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr); 825 cp->cp_snapshot_list.ssl_next = cpu_to_le64(0); 826 cp->cp_snapshot_list.ssl_prev = cpu_to_le64(0); 827 nilfs_checkpoint_clear_snapshot(cp); 828 kunmap_atomic(kaddr); 829 830 kaddr = kmap_atomic(header_bh->b_page); 831 header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr); 832 le64_add_cpu(&header->ch_nsnapshots, -1); 833 kunmap_atomic(kaddr); 834 835 mark_buffer_dirty(next_bh); 836 mark_buffer_dirty(prev_bh); 837 mark_buffer_dirty(cp_bh); 838 mark_buffer_dirty(header_bh); 839 nilfs_mdt_mark_dirty(cpfile); 840 841 brelse(prev_bh); 842 843 out_next: 844 brelse(next_bh); 845 846 out_header: 847 brelse(header_bh); 848 849 out_cp: 850 brelse(cp_bh); 851 852 out_sem: 853 up_write(&NILFS_MDT(cpfile)->mi_sem); 854 return ret; 855 } 856 857 /** 858 * nilfs_cpfile_is_snapshot - 859 * @cpfile: inode of checkpoint file 860 * @cno: checkpoint number 861 * 862 * Description: 863 * 864 * Return Value: On success, 1 is returned if the checkpoint specified by 865 * @cno is a snapshot, or 0 if not. On error, one of the following negative 866 * error codes is returned. 867 * 868 * %-EIO - I/O error. 869 * 870 * %-ENOMEM - Insufficient amount of memory available. 871 * 872 * %-ENOENT - No such checkpoint. 873 */ 874 int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) 875 { 876 struct buffer_head *bh; 877 struct nilfs_checkpoint *cp; 878 void *kaddr; 879 int ret; 880 881 /* 882 * CP number is invalid if it's zero or larger than the 883 * largest existing one. 884 */ 885 if (cno == 0 || cno >= nilfs_mdt_cno(cpfile)) 886 return -ENOENT; 887 down_read(&NILFS_MDT(cpfile)->mi_sem); 888 889 ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); 890 if (ret < 0) 891 goto out; 892 kaddr = kmap_atomic(bh->b_page); 893 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 894 if (nilfs_checkpoint_invalid(cp)) 895 ret = -ENOENT; 896 else 897 ret = nilfs_checkpoint_snapshot(cp); 898 kunmap_atomic(kaddr); 899 brelse(bh); 900 901 out: 902 up_read(&NILFS_MDT(cpfile)->mi_sem); 903 return ret; 904 } 905 906 /** 907 * nilfs_cpfile_change_cpmode - change checkpoint mode 908 * @cpfile: inode of checkpoint file 909 * @cno: checkpoint number 910 * @mode: mode of checkpoint 911 * 912 * Description: nilfs_change_cpmode() changes the mode of the checkpoint 913 * specified by @cno. The mode @mode is NILFS_CHECKPOINT or NILFS_SNAPSHOT. 914 * 915 * Return Value: On success, 0 is returned. On error, one of the following 916 * negative error codes is returned. 917 * 918 * %-EIO - I/O error. 919 * 920 * %-ENOMEM - Insufficient amount of memory available. 921 * 922 * %-ENOENT - No such checkpoint. 923 */ 924 int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode) 925 { 926 int ret; 927 928 switch (mode) { 929 case NILFS_CHECKPOINT: 930 if (nilfs_checkpoint_is_mounted(cpfile->i_sb, cno)) 931 /* 932 * Current implementation does not have to protect 933 * plain read-only mounts since they are exclusive 934 * with a read/write mount and are protected from the 935 * cleaner. 936 */ 937 ret = -EBUSY; 938 else 939 ret = nilfs_cpfile_clear_snapshot(cpfile, cno); 940 return ret; 941 case NILFS_SNAPSHOT: 942 return nilfs_cpfile_set_snapshot(cpfile, cno); 943 default: 944 return -EINVAL; 945 } 946 } 947 948 /** 949 * nilfs_cpfile_get_stat - get checkpoint statistics 950 * @cpfile: inode of checkpoint file 951 * @cpstat: pointer to a structure of checkpoint statistics 952 * 953 * Description: nilfs_cpfile_get_stat() returns information about checkpoints. 954 * 955 * Return Value: On success, 0 is returned, and checkpoints information is 956 * stored in the place pointed by @cpstat. On error, one of the following 957 * negative error codes is returned. 958 * 959 * %-EIO - I/O error. 960 * 961 * %-ENOMEM - Insufficient amount of memory available. 962 */ 963 int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat) 964 { 965 struct buffer_head *bh; 966 struct nilfs_cpfile_header *header; 967 void *kaddr; 968 int ret; 969 970 down_read(&NILFS_MDT(cpfile)->mi_sem); 971 972 ret = nilfs_cpfile_get_header_block(cpfile, &bh); 973 if (ret < 0) 974 goto out_sem; 975 kaddr = kmap_atomic(bh->b_page); 976 header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr); 977 cpstat->cs_cno = nilfs_mdt_cno(cpfile); 978 cpstat->cs_ncps = le64_to_cpu(header->ch_ncheckpoints); 979 cpstat->cs_nsss = le64_to_cpu(header->ch_nsnapshots); 980 kunmap_atomic(kaddr); 981 brelse(bh); 982 983 out_sem: 984 up_read(&NILFS_MDT(cpfile)->mi_sem); 985 return ret; 986 } 987 988 /** 989 * nilfs_cpfile_read - read or get cpfile inode 990 * @sb: super block instance 991 * @cpsize: size of a checkpoint entry 992 * @raw_inode: on-disk cpfile inode 993 * @inodep: buffer to store the inode 994 */ 995 int nilfs_cpfile_read(struct super_block *sb, size_t cpsize, 996 struct nilfs_inode *raw_inode, struct inode **inodep) 997 { 998 struct inode *cpfile; 999 int err; 1000 1001 if (cpsize > sb->s_blocksize) { 1002 nilfs_err(sb, "too large checkpoint size: %zu bytes", cpsize); 1003 return -EINVAL; 1004 } else if (cpsize < NILFS_MIN_CHECKPOINT_SIZE) { 1005 nilfs_err(sb, "too small checkpoint size: %zu bytes", cpsize); 1006 return -EINVAL; 1007 } 1008 1009 cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO); 1010 if (unlikely(!cpfile)) 1011 return -ENOMEM; 1012 if (!(cpfile->i_state & I_NEW)) 1013 goto out; 1014 1015 err = nilfs_mdt_init(cpfile, NILFS_MDT_GFP, 0); 1016 if (err) 1017 goto failed; 1018 1019 nilfs_mdt_set_entry_size(cpfile, cpsize, 1020 sizeof(struct nilfs_cpfile_header)); 1021 1022 err = nilfs_read_inode_common(cpfile, raw_inode); 1023 if (err) 1024 goto failed; 1025 1026 unlock_new_inode(cpfile); 1027 out: 1028 *inodep = cpfile; 1029 return 0; 1030 failed: 1031 iget_failed(cpfile); 1032 return err; 1033 } 1034