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