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